Skip to content

Commit

Permalink
Config UI: markdown help, priority, param sort, deprecation (#18619)
Browse files Browse the repository at this point in the history
  • Loading branch information
naltatis authored Feb 7, 2025
1 parent 04d310a commit 24efc97
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 74 deletions.
16 changes: 10 additions & 6 deletions assets/js/components/Config/FormRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
<label :for="id">
<div class="form-label">
{{ label }}
<small v-if="optional" class="evcc-gray">{{ $t("config.form.optional") }}</small>
<small v-if="deprecated" class="evcc-gray">{{
$t("config.form.deprecated")
}}</small>
<small v-else-if="optional" class="evcc-gray">{{
$t("config.form.optional")
}}</small>
</div>
</label>
<div class="w-100">
Expand All @@ -15,7 +20,7 @@
{{ $t("config.form.example") }}: {{ example }}
</div>
<div v-if="help">
<span class="text-gray hyphenate" v-html="helpHtml"></span>
<Markdown :markdown="help" class="text-gray hyphenate" />
<a v-if="link" class="ms-1 text-gray" :href="link" target="_blank">
{{ $t("config.general.docsLink") }}
</a>
Expand All @@ -25,23 +30,22 @@
</template>

<script>
import linkify from "../../utils/linkify";
import { docsPrefix } from "../../i18n";
import Markdown from "./Markdown.vue";

export default {
name: "FormRow",
components: { Markdown },
props: {
id: String,
label: String,
help: String,
optional: Boolean,
deprecated: Boolean,
example: String,
docsLink: String,
},
computed: {
helpHtml() {
return linkify(this.help);
},
link() {
return this.docsLink ? `${docsPrefix()}${this.docsLink}` : null;
},
Expand Down
21 changes: 11 additions & 10 deletions assets/js/components/Config/LoadpointModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,14 @@
:label="$t('config.loadpoint.priorityLabel')"
:help="$t('config.loadpoint.priorityHelp')"
>
<SelectGroup
<PropertyField
id="loadpointParamPriority"
v-model="values.priority"
class="w-100"
:options="priorityOptions"
transparent
type="Choice"
size="w-100"
class="me-2"
:choice="priorityOptions"
required
/>
</FormRow>

Expand Down Expand Up @@ -654,14 +656,13 @@ export default {
return !this.isNew;
},
showPriority() {
return this.priorityOptions.length > 1;
return this.isNew ? this.loadpointCount > 0 : this.loadpointCount > 1;
},
priorityOptions() {
const maxPriority = this.loadpointCount + (this.isNew ? 1 : 0);
const result = Array.from({ length: maxPriority }, (_, i) => ({
value: i,
name: `${i}`,
}));
const result = Array.from({ length: 11 }, (_, i) => ({ key: i, name: `${i}` }));
result[0].name = "0 (default)";
result[0].key = undefined;
result[10].name = "10 (highest)";
return result;
},
showCircuit() {
Expand Down
2 changes: 2 additions & 0 deletions assets/js/components/Config/PropertyEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<FormRow
:id="id"
:optional="!Required"
:deprecated="Deprecated"
:label="Description || `[${Name}]`"
:help="Description === Help ? undefined : Help"
:example="Example"
Expand Down Expand Up @@ -31,6 +32,7 @@ export default {
id: String,
Name: String,
Required: Boolean,
Deprecated: Boolean,
Description: String,
Help: String,
Example: String,
Expand Down
7 changes: 4 additions & 3 deletions assets/js/components/Config/VehicleModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@
</FormRow>
</div>

<!-- todo: only show when multiple loadpoints exist -->
<FormRow
id="vehicleParamPriority"
label="Priority"
Expand Down Expand Up @@ -300,17 +299,19 @@ export default {
return p;
});
// non-optional fields first
params.sort((a, b) => (a.Required ? -1 : 1) - (b.Required ? -1 : 1));
// always start with title and icon field
const order = { title: -2, icon: -1 };
params.sort((a, b) => (order[a.Name] || 0) - (order[b.Name] || 0));
return params;
},
normalParams() {
return this.templateParams.filter((p) => !p.Advanced);
return this.templateParams.filter((p) => !p.Advanced && !p.Deprecated);
},
advancedParams() {
return this.templateParams.filter((p) => p.Advanced);
return this.templateParams.filter((p) => p.Advanced || p.Deprecated);
},
description() {
return this.template?.Requirements?.Description;
Expand Down
7 changes: 0 additions & 7 deletions assets/js/utils/linkify.js

This file was deleted.

25 changes: 0 additions & 25 deletions assets/js/utils/linkify.test.js

This file was deleted.

1 change: 1 addition & 0 deletions i18n/de.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ description = "Grundkonfiguration für die Kommunikation mit anderen EEBus-Gerä
title = "EEBus"

[config.form]
deprecated = "veraltet"
example = "Beispiel"
optional = "optional"

Expand Down
1 change: 1 addition & 0 deletions i18n/en.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ description = "Configuration that enables evcc to communicate with other EEBus d
title = "EEBus"

[config.form]
deprecated = "deprecated"
example = "Example"
optional = "optional"

Expand Down
35 changes: 12 additions & 23 deletions tests/config-loadpoint.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,43 +136,32 @@ test.describe("loadpoint", async () => {
await expect(page.getByTestId("loadpoint")).toHaveCount(1);
await expect(page.getByTestId("loadpoint")).toContainText("Carport");

// add two more loadpoints
for (const title of ["Garage", "Garden"]) {
await newLoadpoint(page, title);
await addDemoCharger(page);
await lpModal.getByRole("button", { name: "Save" }).click();
await expect(lpModal).not.toBeVisible();
}
// add loadpoint via UI
await newLoadpoint(page, "Garage");
await addDemoCharger(page);
await lpModal.getByRole("button", { name: "Save" }).click();
await expect(lpModal).not.toBeVisible();

// three loadpoints
await expect(page.getByTestId("loadpoint")).toHaveCount(3);
// two loadpoints
await expect(page.getByTestId("loadpoint")).toHaveCount(2);
await expect(page.getByTestId("loadpoint").nth(0)).toContainText("Carport");
await expect(page.getByTestId("loadpoint").nth(1)).toContainText("Garage");
await expect(page.getByTestId("loadpoint").nth(2)).toContainText("Garden");

// second loadpoint > priority 2
// second loadpoint: increase priority
await page.getByTestId("loadpoint").nth(1).getByRole("button", { name: "edit" }).click();
await lpModal.getByTestId("loadpointParamPriority-2").click();
await expect(lpModal).toBeVisible();
await expect(lpModal.getByLabel("Priority")).toHaveValue("0 (default)");
await lpModal.getByLabel("Priority").selectOption("1");
await lpModal.getByRole("button", { name: "Save" }).click();
await expect(lpModal).not.toBeVisible();

// third loadpoint > priority 1
await page.getByTestId("loadpoint").nth(2).getByRole("button", { name: "edit" }).click();
await lpModal.getByTestId("loadpointParamPriority-1").click();
await lpModal.getByRole("button", { name: "Save" }).click();
await expect(lpModal).not.toBeVisible();
// restart
await restart(CONFIG_ONE_LP);
await page.reload();

// check priorities
await page.getByTestId("loadpoint").nth(1).getByRole("button", { name: "edit" }).click();
await expect(lpModal.getByTestId("loadpointParamPriority-2")).toHaveClass(/active/);
await lpModal.getByRole("button", { name: "Close" }).click();

await page.getByTestId("loadpoint").nth(2).getByRole("button", { name: "edit" }).click();
await expect(lpModal.getByTestId("loadpointParamPriority-1")).toHaveClass(/active/);
await lpModal.getByRole("button", { name: "Close" }).click();
await expect(lpModal.getByLabel("Priority")).toHaveValue("1");
});

test("vehicle", async ({ page }) => {
Expand Down

0 comments on commit 24efc97

Please sign in to comment.