diff --git a/frigate/config.py b/frigate/config.py index 3e31b1fcb..2ea17ebe2 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -1028,3 +1028,8 @@ class FrigateConfig(FrigateBaseModel): config = json.loads(raw_config) return cls.parse_obj(config) + + @classmethod + def parse_raw(cls, raw_config): + config = load_config_with_no_duplicates(raw_config) + return cls.parse_obj(config) diff --git a/frigate/http.py b/frigate/http.py index 7df3300e5..3ce9586e1 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -27,11 +27,17 @@ from flask import ( from peewee import SqliteDatabase, operator, fn, DoesNotExist from playhouse.shortcuts import model_to_dict +from frigate.config import FrigateConfig from frigate.const import CLIPS_DIR, RECORD_DIR from frigate.models import Event, Recordings from frigate.object_processing import TrackedObject from frigate.stats import stats_snapshot -from frigate.util import clean_camera_user_pass, ffprobe_stream, vainfo_hwaccel +from frigate.util import ( + clean_camera_user_pass, + ffprobe_stream, + restart_frigate, + vainfo_hwaccel, +) from frigate.storage import StorageMaintainer from frigate.version import VERSION @@ -618,6 +624,22 @@ def config_raw(): return raw_config, 200 +@bp.route("/config/save", methods=["POST"]) +def config_save(): + new_config = request.get_data().decode() + logging.error(f"The data is {new_config}") + + if not new_config: + return "Config with body param is required", 400 + + try: + new_yaml = FrigateConfig.parse_raw(new_config) + restart_frigate() + return "Config successfully saved", 200 + except Exception as e: + return f"Schema error: {e}", 400 + + @bp.route("/config/schema") def config_schema(): return current_app.response_class( diff --git a/web/src/routes/Config.jsx b/web/src/routes/Config.jsx index 526772861..a17ff8d75 100644 --- a/web/src/routes/Config.jsx +++ b/web/src/routes/Config.jsx @@ -5,12 +5,29 @@ import ActivityIndicator from '../components/ActivityIndicator'; import Heading from '../components/Heading'; import { useState } from 'preact/hooks'; import Button from '../components/Button'; +import axios from 'axios'; export default function Config() { const { data: config } = useSWR('config/raw'); const [newCode, setNewCode] = useState(config); const [error, setError] = useState(); + const onHandleSaveConfig = async (e) => { + if (e) { + e.stopPropagation(); + } + + const response = await axios.post('config/save', newCode, { + headers: { 'Content-Type': 'text/plain' }, + }); + console.log('The resp is ' + response.status + ' and data ' + response.data); + if (response.status === 200) { + // TODO set success + } else { + setError(response.data); + } + }; + const handleCopyConfig = async () => { await window.navigator.clipboard.writeText(newCode); }; @@ -24,8 +41,14 @@ export default function Config() {