8000 Config UI: filter parameters by usage by Maschga · Pull Request #21821 · evcc-io/evcc · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Config UI: filter parameters by usage #21821

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Jun 14, 2025
Merged

Conversation

Maschga
Copy link
Contributor
@Maschga Maschga commented Jun 13, 2025

Fix #21814

@Maschga Maschga marked this pull request as ready for review June 13, 2025 07:18
Copy link
Contributor
@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Maschga - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `assets/js/components/Config/MeterModal.vue:274` </location>
<code_context>
 			return params.filter((p) => !CUSTOM_FIELDS.includes(p.Name));
 		},
 		normalParams() {
-			return this.templateParams.filter((p) => !p.Advanced);
+			return this.templateParams.filter(
</code_context>

<issue_to_address>
Duplicate filtering logic across modal components

Consider extracting the shared filtering logic into a utility or mixin to reduce duplication and enhance maintainability.

Suggested implementation:

```
		normalParams() {
			return filterTemplateParams(this.templateParams, this.templateType, false);
		},
		advancedParams() {
			return filterTemplateParams(this.templateParams, this.templateType, true);

```

```
<script>
import { filterTemplateParams } from '@/utils/templateParamFilters';

export default {
	computed: {

```

You need to create a new file at `assets/js/utils/templateParamFilters.js` (or `.ts` if using TypeScript) with the following content:

```js
export function filterTemplateParams(params, templateType, advanced) {
	return params.filter(
		(p) =>
			!!p.Advanced === !!advanced &&
			!p.Deprecated &&
			(p.Usages && templateType ? p.Usages.includes(templateType) : true)
	);
}
```

Make sure to adjust the import path if your project structure differs.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@naltatis naltatis self-assigned this Jun 13, 2025
@naltatis naltatis added enhancement New feature or request ux User experience/ interface labels Jun 13, 2025
@naltatis
Copy link
Member

@Maschga magst du einen playwirght test ergänzen der das prüft. als einmal ein pv-meter und ein battery-meter erstellen und prüfen dass es die richtigen Optionen gibt. dafür können wir ruhig ein "echtes" template verwenden. brauchen ja nicht speichern/anlegen.

@Maschga
Copy link
Contributor Author
Maschga commented Jun 13, 2025

Dürfen die beiden Tests auch hier rein?

test.describe("battery meter", async () => {
test("create, edit and remove battery meter", async ({ page }) => {
// setup test data for mock openems api
await page.goto(simulatorUrl());
await page.getByLabel("Battery Power").fill("-2500");
await page.getByLabel("Battery SoC").fill("75");
await page.getByRole("button", { name: "Apply changes" }).click();
await page.goto("/#/config");
await enableExperimental(page);
await expect(page.getByTestId("battery")).toHaveCount(0);
// create #1
await page.getByRole("button", { name: "Add solar or battery" }).click();
const meterModal = page.getByTestId("meter-modal");
await meterModal.getByRole("button", { name: "Add battery meter" }).click();
await meterModal.getByLabel("Title").fill("Battery Basement");
await meterModal.getByLabel("Manufacturer").selectOption("OpenEMS");
await meterModal.getByLabel("IP address or hostname").fill(simulatorHost());
await expect(meterModal.getByRole("button", { name: "Validate & save" })).toBeVisible();
await meterModal.getByRole("link", { name: "validate" }).click();
await expect(meterModal.getByTestId("device-tag-soc")).toContainText("75.0%");
await expect(meterModal.getByTestId("device-tag-power")).toContainText("-2.5 kW");
await meterModal.getByRole("button", { name: "Save" }).click();
await expectModalHidden(meterModal);
await expect(page.getByTestId("battery")).toBeVisible(1);
await expect(page.getByTestId("battery")).toContainText("Battery Basement");
// edit #1
await page.getByTestId("battery").getByRole("button", { name: "edit" }).click();
await expectModalVisible(meterModal);
await meterModal.getByLabel("Battery capacity").fill("20");
await meterModal.getByRole("button", { name: "Validate & save" }).click();
await expectModalHidden(meterModal);
const battery = page.getByTestId("battery");
await expect(battery).toBeVisible(1);
await expect(battery).toContainText("Battery Basement");
await expect(battery.getByTestId("device-tag-soc")).toContainText("75.0%");
await expect(battery.getByTestId("device-tag-power")).toContainText("-2.5 kW");
await expect(battery.getByTestId("device-tag-capacity")).toContainText("20.0 kWh");
// restart and check in main ui
await restart(CONFIG_GRID_ONLY);
await page.goto("/");
await page.getByTestId("visualization").click();
await expect(page.getByTestId("energyflow")).toContainText("Battery charging75%2.5 kW");
// delete #1
await page.goto("/#/config");
await page.getByTestId("battery").getByRole("button", { name: "edit" }).click();
await expectModalVisible(meterModal);
await meterModal.getByRole("button", { name: "Delete" }).click();
await expectModalHidden(meterModal);
await expect(page.getByTestId("battery")).toHaveCount(0);
});
test("advanced fields", async ({ page }) => {
await page.goto("/#/config");
await enableExperimental(page);
await page.getByRole("button", { name: "Add solar or battery" }).click();
const meterModal = page.getByTestId("meter-modal");
await meterModal.getByRole("button", { name: "Add battery meter" }).click();
await meterModal.getByLabel("Title").fill("Battery Basement");
await meterModal.getByLabel("Manufacturer").selectOption("OpenEMS");
await expect(meterModal.getByLabel("Password optional")).not.toBeVisible();
await page.getByRole("button", { name: "Show advanced settings" }).click();
await expect(meterModal.getByLabel("Password optional")).toBeVisible();
await page.getByRole("button", { name: "Hide advanced settings" }).click();
await expect(meterModal.getByLabel("Password optional")).not.toBeVisible();
});
});

test.describe("pv meter", async () => {
test("create, edit and remove pv meter", async ({ page }) => {
await page.goto("/#/config");
await enableExperimental(page);
await expect(page.getByTestId("pv")).toHaveCount(0);
// create #1
await page.getByRole("button", { name: "Add solar or battery" }).click();
const meterModal = page.getByTestId("meter-modal");
await meterModal.getByRole("button", { name: "Add solar meter" }).click();
await meterModal.getByLabel("Title").fill("PV North");
await meterModal.getByLabel("Manufacturer").selectOption("Demo meter");
await meterModal.getByLabel("Power").fill("5000");
await expect(meterModal.getByRole("button", { name: "Validate & save" })).toBeVisible();
await meterModal.getByRole("link", { name: "validate" }).click();
await expect(meterModal.getByTestId("device-tag-power")).toContainText("5.0 kW");
await meterModal.getByRole("button", { name: "Save" }).click();
await expectModalHidden(meterModal);
await expect(page.getByTestId("pv")).toBeVisible(1);
await expect(page.getByTestId("pv")).toContainText("PV North");
// edit #1
await page.getByTestId("pv").getByRole("button", { name: "edit" }).click();
await expectModalVisible(meterModal);
await meterModal.getByLabel("Power").fill("6000");
await meterModal.getByRole("button", { name: "Validate & save" }).click();
await expectModalHidden(meterModal);
const pv = page.getByTestId("pv");
await expect(pv).toBeVisible(1);
await expect(pv).toContainText("PV North");
await expect(pv.getByTestId("device-tag-power")).toContainText("6.0 kW");
// restart and check in main ui
await restart(CONFIG_GRID_ONLY);
await page.goto("/");
await page.getByTestId("visualization").click();
await expect(page.getByTestId("energyflow")).toContainText("Production6.0 kW");
// delete #1
await page.goto("/#/config");
await page.getByTestId("pv").getByRole("button", { name: "edit" }).click();
await expectModalVisible(meterModal);
await meterModal.getByRole("button", { name: "Delete" }).click();
await expectModalHidden(meterModal);
await expect(page.getByTestId("pv")).toHaveCount(0);
// restart and check again
await restart(CONFIG_GRID_ONLY);
await page.reload();
await expect(page.getByTestId("pv")).toHaveCount(0);
});

@naltatis
Copy link
Member

Dürfen die beiden Tests auch hier rein?

Ja, braucht kein eigener Testcase sein. In einen bestehenden integrieren ist immer besser. Ggf. nen Kommentar hinzufügen wenn unklar ist wieso der Extracheck im Test ist.

@Maschga
Copy link
Contributor Author
Maschga commented Jun 13, 2025

Sind die Tests so ausreichend?
Ich habe mir gedacht, dass es ausreicht das Fehlen dieser beiden Felder zu überprüfen.

description:
en: Maximum charge power
de: Maximale Ladeleistung
advanced: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

siehe oben

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alternativ kannst du dem soc (drüber) einfach eine usage verpassen

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Danke- nix doppeln!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In demo-meter.yaml sehe ich keinen soc. 🤔 Meinst du energy oder power?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wenn wir Max Ladeleistung haben dann wäre auch Soc auf jeden Fall sinnvoll ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ja!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auf welche Frage bezieht sich dein Ja?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aber fürs Testen reicht maxchargepower aus, oder nicht?

Ja.

oder darum, maxchargepower durch einen bereits vorhandenen Parameter wie energy zu ersetzen und bei energy usages: ["battery"] hinzuzufügen?

Nein weil das physikalisch unsinnig wäre, demo hin oder her.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deshalb hatte ich soc vorgeschlagen- den braucht es in der realen Welt immer und er passt gut zu einer demo battery.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxchargepower wurde jetzt durch minsoc ersetzt.

Maschga and others added 2 commits June 14, 2025 10:51
Co-authored-by: Michael Geers <michael@geers.tv>
@andig andig changed the title Config UI: Filter parameters by usage Config UI: filter parameters by usage Jun 14, 2025
@naltatis naltatis enabled auto-merge (squash) June 14, 2025 18:41
@naltatis naltatis merged commit cf99834 into evcc-io:master Jun 14, 2025
6 checks passed
@Maschga Maschga deleted the fix/usages branch June 14, 2025 19:45
guido4096 pushed a commit to guido4096/evcc that referenced this pull request Jun 15, 2025
Co-authored-by: Michael Geers <michael@geers.tv>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request ux User experience/ interface
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Config UI: hide parameters not matching usage
3 participants
0