From 554ce1db6025ee202c6ae22cf873432835901ea2 Mon Sep 17 00:00:00 2001 From: Michael Geers Date: Sat, 8 Jun 2024 14:35:46 +0200 Subject: [PATCH] Config UI: add missing config sections / partial yaml inputs (BC) (#13319) --- .gitignore | 1 + api/globalconfig/types.go | 142 ++++++ assets/css/app.css | 61 ++- assets/js/components/Config/CircuitsModal.vue | 26 + assets/js/components/Config/ControlModal.vue | 194 ++++++++ assets/js/components/Config/DeviceCard.vue | 42 +- assets/js/components/Config/DeviceTags.vue | 70 ++- assets/js/components/Config/EebusModal.vue | 25 + assets/js/components/Config/FormRow.vue | 12 +- assets/js/components/Config/GeneralConfig.vue | 245 ++++++---- assets/js/components/Config/HemsModal.vue | 26 + assets/js/components/Config/InfluxModal.vue | 122 +++++ assets/js/components/Config/JsonModal.vue | 174 +++++++ .../js/components/Config/MessagingModal.vue | 25 + .../js/components/Config/ModbusProxyModal.vue | 26 + assets/js/components/Config/MqttModal.vue | 79 +++ assets/js/components/Config/NetworkModal.vue | 75 +++ assets/js/components/Config/SponsorModal.vue | 96 ++++ assets/js/components/Config/TariffsModal.vue | 26 + assets/js/components/Config/TestResult.vue | 43 +- assets/js/components/Config/TitleModal.vue | 81 +-- .../Config/UserInterfaceSettings.vue | 9 +- assets/js/components/Config/YamlEditor.vue | 122 +++++ assets/js/components/Config/YamlModal.vue | 145 ++++++ .../Config/defaultYaml/circuits.yaml | 18 + .../components/Config/defaultYaml/eebus.yaml | 12 + .../components/Config/defaultYaml/hems.yaml | 4 + .../Config/defaultYaml/messaging.yaml | 35 ++ .../Config/defaultYaml/modbusproxy.yaml | 9 + .../Config/defaultYaml/tariffs.yaml | 13 + assets/js/components/Footer.vue | 3 +- assets/js/components/GlobalSettingsModal.vue | 8 +- assets/js/components/HelpModal.vue | 8 +- .../js/components/MaterialIcon/Circuits.vue | 17 + assets/js/components/MaterialIcon/Edit.vue | 17 + assets/js/components/MaterialIcon/Eebus.vue | 21 + assets/js/components/MaterialIcon/Hems.vue | 17 + assets/js/components/MaterialIcon/Influx.vue | 17 + .../components/MaterialIcon/ModbusProxy.vue | 17 + assets/js/components/MaterialIcon/Mqtt.vue | 33 ++ .../components/MaterialIcon/Notification.vue | 17 + assets/js/components/MaterialIcon/Restart.vue | 17 + assets/js/components/OfflineIndicator.vue | 158 +++++- assets/js/components/Savings.vue | 7 +- assets/js/components/Site.vue | 12 +- assets/js/components/Sponsor.story.vue | 2 +- assets/js/components/Sponsor.vue | 18 +- .../components/SponsorTokenExpires.story.vue | 4 +- assets/js/components/SponsorTokenExpires.vue | 16 +- assets/js/components/TelemetrySettings.vue | 6 +- assets/js/components/TopNavigation.story.vue | 2 +- assets/js/components/TopNavigation.vue | 33 +- assets/js/mixins/icon.js | 3 +- assets/js/restart.js | 23 + assets/js/router.js | 4 - assets/js/views/App.vue | 15 +- assets/js/views/Config.vue | 461 +++++++++++------- assets/js/views/StartupError.vue | 154 ------ charger/eebus/eebus.go | 28 +- cmd/charger.go | 2 +- cmd/charger_ramp.go | 2 +- cmd/class_enumer.go | 147 ++++++ cmd/configure/eebus.go | 16 +- cmd/demo.go | 4 +- cmd/device.go | 2 +- cmd/dump.go | 4 +- cmd/error.go | 78 +++ cmd/error_test.go | 22 + cmd/flags.go | 3 + cmd/helper.go | 29 +- cmd/meter.go | 2 +- cmd/migrate.go | 116 +++++ cmd/password_reset.go | 2 +- cmd/password_set.go | 2 +- cmd/root.go | 146 +++--- cmd/settings-get.go | 4 +- cmd/settings-set.go | 4 +- cmd/setup.go | 406 +++++++++------ cmd/setup_circuits_test.go | 7 +- cmd/setup_test.go | 3 +- cmd/tariff.go | 2 +- cmd/token_tronity.go | 3 +- cmd/vehicle.go | 2 +- core/keys/global.go | 18 + core/keys/site.go | 11 +- core/site.go | 87 ++-- core/site/api.go | 6 +- core/site_api.go | 38 +- docs/encoding.md | 9 + go.mod | 2 + go.sum | 5 +- hems/config.go | 5 +- hems/ocpp/ocpp.go | 98 ---- hems/ocpp/profile/configmap.go | 135 ----- hems/ocpp/profile/core.go | 43 -- hems/ocpp/profile/core_configuration.go | 41 -- hems/ocpp/profile/core_other.go | 23 - hems/ocpp/profile/smartcharging.go | 34 -- i18n/de.toml | 113 ++++- i18n/en.toml | 120 ++++- package-lock.json | 67 +++ package.json | 3 +- playwright.config.js | 1 - provider/config.go | 2 +- provider/mqtt/client.go | 10 +- push/hub.go | 2 +- server/db/settings/setting.go | 94 +++- server/http.go | 159 ++++-- server/http_config_helper.go | 7 +- server/http_config_site_other_handler.go | 34 ++ server/http_global_settings_handler.go | 113 +++++ server/http_handler_test.go | 17 - server/http_site_handler.go | 41 +- server/influxdb.go | 11 - server/mqtt.go | 2 +- server/socket_helper.go | 42 +- server/socket_test.go | 8 +- tests/auth.spec.js | 4 +- tests/config-meters.spec.js | 17 +- tests/config-mqtt.spec.js | 76 +++ tests/config-tariffs.spec.js | 117 +++++ tests/config-vehicles.spec.js | 2 +- tests/config-with-tariffs.evcc.yaml | 53 ++ tests/config.spec.js | 8 +- tests/evcc.js | 7 +- tests/logs.spec.js | 2 +- util/cache.go | 47 +- util/config/types.go | 10 +- util/encode/encode.go | 67 +++ util/encode/encode_test.go | 18 + util/providerauth.go | 3 +- util/sponsor/auth.go | 33 +- util/tee.go | 8 + 133 files changed, 4405 insertions(+), 1572 deletions(-) create mode 100644 api/globalconfig/types.go create mode 100644 assets/js/components/Config/CircuitsModal.vue create mode 100644 assets/js/components/Config/ControlModal.vue create mode 100644 assets/js/components/Config/EebusModal.vue create mode 100644 assets/js/components/Config/HemsModal.vue create mode 100644 assets/js/components/Config/InfluxModal.vue create mode 100644 assets/js/components/Config/JsonModal.vue create mode 100644 assets/js/components/Config/MessagingModal.vue create mode 100644 assets/js/components/Config/ModbusProxyModal.vue create mode 100644 assets/js/components/Config/MqttModal.vue create mode 100644 assets/js/components/Config/NetworkModal.vue create mode 100644 assets/js/components/Config/SponsorModal.vue create mode 100644 assets/js/components/Config/TariffsModal.vue create mode 100644 assets/js/components/Config/YamlEditor.vue create mode 100644 assets/js/components/Config/YamlModal.vue create mode 100644 assets/js/components/Config/defaultYaml/circuits.yaml create mode 100644 assets/js/components/Config/defaultYaml/eebus.yaml create mode 100644 assets/js/components/Config/defaultYaml/hems.yaml create mode 100644 assets/js/components/Config/defaultYaml/messaging.yaml create mode 100644 assets/js/components/Config/defaultYaml/modbusproxy.yaml create mode 100644 assets/js/components/Config/defaultYaml/tariffs.yaml create mode 100644 assets/js/components/MaterialIcon/Circuits.vue create mode 100644 assets/js/components/MaterialIcon/Edit.vue create mode 100644 assets/js/components/MaterialIcon/Eebus.vue create mode 100644 assets/js/components/MaterialIcon/Hems.vue create mode 100644 assets/js/components/MaterialIcon/Influx.vue create mode 100644 assets/js/components/MaterialIcon/ModbusProxy.vue create mode 100644 assets/js/components/MaterialIcon/Mqtt.vue create mode 100644 assets/js/components/MaterialIcon/Notification.vue create mode 100644 assets/js/components/MaterialIcon/Restart.vue create mode 100644 assets/js/restart.js delete mode 100644 assets/js/views/StartupError.vue create mode 100644 cmd/class_enumer.go create mode 100644 cmd/error.go create mode 100644 cmd/error_test.go create mode 100644 cmd/migrate.go create mode 100644 core/keys/global.go create mode 100644 docs/encoding.md delete mode 100644 hems/ocpp/ocpp.go delete mode 100644 hems/ocpp/profile/configmap.go delete mode 100644 hems/ocpp/profile/core.go delete mode 100644 hems/ocpp/profile/core_configuration.go delete mode 100644 hems/ocpp/profile/core_other.go delete mode 100644 hems/ocpp/profile/smartcharging.go create mode 100644 server/http_config_site_other_handler.go create mode 100644 server/http_global_settings_handler.go delete mode 100644 server/http_handler_test.go create mode 100644 tests/config-mqtt.spec.js create mode 100644 tests/config-tariffs.spec.js create mode 100755 tests/config-with-tariffs.evcc.yaml create mode 100644 util/encode/encode.go create mode 100644 util/encode/encode_test.go diff --git a/.gitignore b/.gitignore index 81e4c508c..7bd2fa6b8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ __debug_bin* !templates/**/*.yaml !templates/**/*-schema.json !util/templates/**/*.yaml +!assets/js/**/*.yaml !package*.json !evcc.dist.yaml !tests/**/*.evcc.yaml diff --git a/api/globalconfig/types.go b/api/globalconfig/types.go new file mode 100644 index 000000000..a69765674 --- /dev/null +++ b/api/globalconfig/types.go @@ -0,0 +1,142 @@ +package globalconfig + +import ( + "fmt" + "net" + "strconv" + "time" + + "github.com/evcc-io/evcc/charger/eebus" + "github.com/evcc-io/evcc/provider/mqtt" + "github.com/evcc-io/evcc/push" + "github.com/evcc-io/evcc/util/config" + "github.com/evcc-io/evcc/util/modbus" +) + +type All struct { + Network Network + Log string + SponsorToken string + Plant string // telemetry plant id + Telemetry bool + Metrics bool + Profile bool + Levels map[string]string + Interval time.Duration + Database DB + Mqtt Mqtt + ModbusProxy []ModbusProxy + Javascript []Javascript + Go []Go + Influx Influx + EEBus eebus.Config + HEMS config.Typed + Messaging Messaging + Meters []config.Named + Chargers []config.Named + Vehicles []config.Named + Tariffs Tariffs + Site map[string]interface{} + Loadpoints []map[string]interface{} + Circuits []config.Named +} + +type Javascript struct { + VM string + Script string +} + +type Go struct { + VM string + Script string +} + +type ModbusProxy struct { + Port int + ReadOnly string + modbus.Settings `mapstructure:",squash"` +} + +type Mqtt struct { + mqtt.Config `mapstructure:",squash"` + Topic string `json:"topic"` +} + +// Redacted implements the redactor interface used by the tee publisher +func (m Mqtt) Redacted() any { + // TODO add masked password + return struct { + Broker string `json:"broker"` + Topic string `json:"topic"` + User string `json:"user"` + ClientID string `json:"clientID"` + Insecure bool `json:"insecure"` + }{ + Broker: m.Broker, + Topic: m.Topic, + User: m.User, + ClientID: m.ClientID, + Insecure: m.Insecure, + } +} + +// Influx is the influx db configuration +type Influx struct { + URL string `json:"url"` + Database string `json:"database"` + Token string `json:"token"` + Org string `json:"org"` + User string `json:"user"` + Password string `json:"password"` +} + +// Redacted implements the redactor interface used by the tee publisher +func (c Influx) Redacted() any { + // TODO add masked password + return struct { + URL string `json:"url"` + Database string `json:"database"` + Org string `json:"org"` + User string `json:"user"` + }{ + URL: c.URL, + Database: c.Database, + Org: c.Org, + User: c.User, + } +} + +type DB struct { + Type string + Dsn string +} + +type Messaging struct { + Events map[string]push.EventTemplateConfig + Services []config.Typed +} + +type Tariffs struct { + Currency string + Grid config.Typed + FeedIn config.Typed + Co2 config.Typed + Planner config.Typed +} + +type Network struct { + Schema string `json:"schema"` + Host string `json:"host"` + Port int `json:"port"` +} + +func (c Network) HostPort() string { + if c.Schema == "http" && c.Port == 80 || c.Schema == "https" && c.Port == 443 { + return c.Host + } + return net.JoinHostPort(c.Host, strconv.Itoa(c.Port)) +} + +func (c Network) URI() string { + return fmt.Sprintf("%s://%s", c.Schema, c.HostPort()) +} diff --git a/assets/css/app.css b/assets/css/app.css index eae80f4f6..f3ae7cee3 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -35,9 +35,11 @@ --evcc-red-rgb: 252, 68, 15; --bs-gray-deep: #010322; --bs-gray-dark: #28293e; + --bs-gray-darker: #151630; --bs-gray-medium: #93949e; --bs-gray-light: #b5b6c3; --bs-gray-bright: #f3f3f7; + --bs-gray-brighter: #f9f9fb; --evcc-grid: var(--bs-gray-dark); --evcc-self: var(--evcc-dark-green); @@ -46,6 +48,7 @@ --evcc-export: var(--evcc-yellow); --evcc-background: var(--bs-gray-bright); --evcc-box: var(--bs-white); + --evcc-box-border: var(--bs-gray-brighter); --evcc-default-text: var(--bs-gray-dark); --evcc-gray: var(--bs-gray-medium); --evcc-gray-50: #93949e80; @@ -65,6 +68,10 @@ --bs-warning: var(--evcc-orange); --bs-warning-rgb: var(--evcc-orange-rgb); + --bs-danger-50: #dc354580; + + --bs-danger: var(--evcc-red); + --bs-danger-rgb: var(--evcc-red-rgb); --bs-danger: var(--evcc-red); --bs-danger-rgb: var(--evcc-red-rgb); @@ -76,12 +83,14 @@ --bs-success: var(--evcc-primary); --bs-success-rgb: var(--bs-primary-rgb); --bs-code-color: var(--evcc-darkest-green); + --evcc-backdrop: #93949eaa; /* --bs-gray-medium + transparent */ } :root.dark { --evcc-grid: var(--bs-gray-medium); --evcc-background: var(--bs-gray-deep); --evcc-box: var(--bs-gray-dark); + --evcc-box-border: var(--vs-gray-darker); --evcc-default-text: var(--bs-white); --evcc-gray: var(--bs-gray-light); --evcc-accent1: var(--evcc-yellow); @@ -90,15 +99,10 @@ --bs-primary: var(--evcc-dark-green); --bs-border-color-translucent: rgba(255, 255, 255, 0.175); --bs-code-color: var(--evcc-dark-green); + --evcc-backdrop: #000000aa; /* black + transparent */ color-scheme: dark; } -html { - /* prevents content jump when scrollbar is activate */ - width: 100vw; - overflow-x: hidden; -} - html.no-transitions * { transition: none !important; } @@ -322,7 +326,19 @@ a:hover { } .modal-backdrop.show { - opacity: 0.8; + opacity: 1; +} + +.modal-backdrop { + --bs-backdrop-bg: var(--evcc-backdrop); + -webkit-backdrop-filter: blur(8px); + backdrop-filter: blur(8px); +} + +.modal-backdrop.fade { + transition-property: opacity, backdrop-filter, background-color; + transition-duration: var(--evcc-transition-fast); + transition-timing-function: linear; } .modal-header { @@ -342,6 +358,13 @@ a:hover { color: var(--evcc-default-text); } +.modal-content h6 { + margin-top: 2rem; + margin-bottom: 1.5rem; + font-size: 1rem; + font-weight: bold; +} + /* breakpoint sm */ @media (min-width: 576px) { .modal-content { @@ -362,6 +385,10 @@ a:hover { margin: 0; } +html:has(.modal.show) { + overflow-y: hidden; +} + .cursor-pointer { cursor: pointer; } @@ -514,6 +541,9 @@ input[type="time"]::-webkit-calendar-picker-indicator { .w-sm-50 { width: 50% !important; } + .w-sm-25 { + width: 25% !important; + } } html.app .hide-in-app { @@ -553,13 +583,20 @@ html.app .modal-dialog { .round-box { border-radius: 1rem; - box-shadow: 0 0 0 0 var(--evcc-gray-50); color: var(--evcc-default-text); background: var(--evcc-box); padding: 1rem; - border: 1px solid var(--evcc-gray-50); - transition: box-shadow var(--evcc-transition-fast) linear; } -.round-box:hover { - border-color: var(--evcc-gray); + +.round-box--error { + box-shadow: 0 0 0.5rem var(--bs-danger); + border: 1px solid var(--bs-danger); +} + +.round-box--error .tags * { + color: var(--bs-danger-text-emphasis) !important; +} + +.alert-danger code { + color: var(--evcc-darkest-green); } diff --git a/assets/js/components/Config/CircuitsModal.vue b/assets/js/components/Config/CircuitsModal.vue new file mode 100644 index 000000000..d11227866 --- /dev/null +++ b/assets/js/components/Config/CircuitsModal.vue @@ -0,0 +1,26 @@ + + + diff --git a/assets/js/components/Config/ControlModal.vue b/assets/js/components/Config/ControlModal.vue new file mode 100644 index 000000000..bd563e967 --- /dev/null +++ b/assets/js/components/Config/ControlModal.vue @@ -0,0 +1,194 @@ + + + + diff --git a/assets/js/components/Config/DeviceCard.vue b/assets/js/components/Config/DeviceCard.vue index 57c7049b6..20b68e5b9 100644 --- a/assets/js/components/Config/DeviceCard.vue +++ b/assets/js/components/Config/DeviceCard.vue @@ -1,21 +1,12 @@ - + diff --git a/assets/js/components/Config/EebusModal.vue b/assets/js/components/Config/EebusModal.vue new file mode 100644 index 000000000..fb242bf24 --- /dev/null +++ b/assets/js/components/Config/EebusModal.vue @@ -0,0 +1,25 @@ + + + diff --git a/assets/js/components/Config/FormRow.vue b/assets/js/components/Config/FormRow.vue index ed0d22e64..119d194ed 100644 --- a/assets/js/components/Config/FormRow.vue +++ b/assets/js/components/Config/FormRow.vue @@ -12,13 +12,19 @@
{{ $t("config.form.example") }}: {{ example }}
-
+
+ + + {{ $t("config.general.docsLink") }} + +
diff --git a/assets/js/components/Config/GeneralConfig.vue b/assets/js/components/Config/GeneralConfig.vue index 6b90345de..0f9e9366d 100644 --- a/assets/js/components/Config/GeneralConfig.vue +++ b/assets/js/components/Config/GeneralConfig.vue @@ -1,93 +1,111 @@ diff --git a/assets/js/components/Config/InfluxModal.vue b/assets/js/components/Config/InfluxModal.vue new file mode 100644 index 000000000..914ecddc9 --- /dev/null +++ b/assets/js/components/Config/InfluxModal.vue @@ -0,0 +1,122 @@ + + + diff --git a/assets/js/components/Config/JsonModal.vue b/assets/js/components/Config/JsonModal.vue new file mode 100644 index 000000000..ec8001ca3 --- /dev/null +++ b/assets/js/components/Config/JsonModal.vue @@ -0,0 +1,174 @@ + + + + diff --git a/assets/js/components/Config/MessagingModal.vue b/assets/js/components/Config/MessagingModal.vue new file mode 100644 index 000000000..32747b4c3 --- /dev/null +++ b/assets/js/components/Config/MessagingModal.vue @@ -0,0 +1,25 @@ + + + diff --git a/assets/js/components/Config/ModbusProxyModal.vue b/assets/js/components/Config/ModbusProxyModal.vue new file mode 100644 index 000000000..1bf1de41f --- /dev/null +++ b/assets/js/components/Config/ModbusProxyModal.vue @@ -0,0 +1,26 @@ + + + diff --git a/assets/js/components/Config/MqttModal.vue b/assets/js/components/Config/MqttModal.vue new file mode 100644 index 000000000..ee22621aa --- /dev/null +++ b/assets/js/components/Config/MqttModal.vue @@ -0,0 +1,79 @@ + + + diff --git a/assets/js/components/Config/NetworkModal.vue b/assets/js/components/Config/NetworkModal.vue new file mode 100644 index 000000000..400bffc9f --- /dev/null +++ b/assets/js/components/Config/NetworkModal.vue @@ -0,0 +1,75 @@ + + + diff --git a/assets/js/components/Config/SponsorModal.vue b/assets/js/components/Config/SponsorModal.vue new file mode 100644 index 000000000..e8a3f4456 --- /dev/null +++ b/assets/js/components/Config/SponsorModal.vue @@ -0,0 +1,96 @@ +