Config UI: improve sponsor communication (#22683)

This commit is contained in:
Michael Geers 2025-08-02 12:29:08 +02:00 • committed by GitHub
parent e3aa811875
commit dc4f80b055
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 85 additions and 12 deletions

View file

@ -1,6 +1,11 @@
<template>
<div>
<TestResult v-if="testState" v-bind="testState" @test="$emit('test')" />
<TestResult
v-if="testState"
v-bind="testState"
:sponsor-token-required="sponsorTokenRequired"
@test="$emit('test')"
/>
<div class="my-4 d-flex justify-content-between">
<button

View file

@ -1,5 +1,10 @@
<template>
<div class="alert alert-warning my-4">
<div v-if="compact" class="mt-4">
<a href="#" role="button" class="text-danger" @click.prevent="openModal">
{{ $t("config.sponsor.tokenRequiredShort") }}
</a>
</div>
<div v-else class="alert alert-warning my-4">
{{ $t("config.sponsor.tokenRequired") }}
<a href="#" role="button" class="text-warning" @click.prevent="openModal">
{{ $t("config.sponsor.tokenRequiredLearnMore") }}
@ -12,6 +17,9 @@ import Modal from "bootstrap/js/dist/modal";
export default {
name: "SponsorTokenRequired",
props: {
compact: Boolean,
},
methods: {
openModal() {
Modal.getOrCreateInstance(document.getElementById("sponsorModal")).show();

View file

@ -12,16 +12,20 @@
{{ $t("config.validation.failed") }}
</span>
</strong>
<span
v-if="isRunning"
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
></span>
<a v-else href="#" class="alert-link" tabindex="0" @click.prevent="$emit('test')">
{{ $t("config.validation.validate") }}
</a>
<div v-if="!showTokenRequired">
<span
v-if="isRunning"
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
></span>
<a v-else href="#" class="alert-link" tabindex="0" @click.prevent="test">
{{ $t("config.validation.validate") }}
</a>
</div>
</div>
<hr v-if="showTokenRequired" class="divider" />
<SponsorTokenRequired v-if="showTokenRequired" compact />
<hr v-if="error" class="divider" />
<div v-if="error" class="text-danger">
{{ error }}
@ -36,10 +40,11 @@
<script lang="ts">
import { defineComponent, type PropType } from "vue";
import DeviceTags from "./DeviceTags.vue";
import SponsorTokenRequired from "./DeviceModal/SponsorTokenRequired.vue";
export default defineComponent({
name: "TestResult",
components: { DeviceTags },
components: { DeviceTags, SponsorTokenRequired },
props: {
isUnknown: Boolean,
isSuccess: Boolean,
@ -47,8 +52,28 @@ export default defineComponent({
isRunning: Boolean,
result: Object as PropType<Record<string, any> | null>,
error: String as PropType<string | null>,
sponsorTokenRequired: Boolean,
},
emits: ["test"],
data() {
return {
showTokenRequired: false,
};
},
watch: {
sponsorTokenRequired() {
this.showTokenRequired = false;
},
},
methods: {
test() {
if (this.sponsorTokenRequired) {
this.showTokenRequired = true;
} else {
this.$emit("test");
}
},
},
});
</script>
<style scoped>

View file

@ -435,6 +435,7 @@
"title": "Sponsoring",
"tokenRequired": "Du musst ein Sponsortoken konfigurieren, bevor du dieses Gerät anlegen kannst.",
"tokenRequiredLearnMore": "Mehr erfahren.",
"tokenRequiredShort": "Kein Sponsortoken konfiguriert.",
"trialToken": "Testtoken"
},
"system": {

View file

@ -435,6 +435,7 @@
"title": "Sponsorship",
"tokenRequired": "You must configure a sponsor token before you can create this device.",
"tokenRequiredLearnMore": "Learn more.",
"tokenRequiredShort": "No sponsor token configured.",
"trialToken": "Trial token"
},
"system": {

View file

@ -699,3 +699,36 @@ temp:
await expect(lpModal.getByRole("button", { name: "Add heating device" })).toBeVisible();
});
});
test.describe("sponsor token", () => {
test("create charger with missing sponsor token", async ({ page }) => {
await start();
await page.goto("/#/config");
await enableExperimental(page);
// add loadpoint with OCPP charger
await newLoadpoint(page, "OCPP Test Charger");
await page.getByTestId("loadpoint-modal").getByRole("button", { name: "Add charger" }).click();
const chargerModal = page.getByTestId("charger-modal");
await expectModalVisible(chargerModal);
await chargerModal.getByLabel("Manufacturer").selectOption({ label: "OCPP 1.6J compatible" });
// verify disabled save button
await expect(chargerModal.getByRole("button", { name: "Save" })).toBeDisabled();
// verify sponsor notice
await expect(chargerModal).toContainText(
"You must configure a sponsor token before you can create this device."
);
const testResult = chargerModal.getByTestId("test-result");
await testResult.getByRole("link", { name: "Validate" }).click();
const sponsorMessage = testResult.getByText("No sponsor token configured.");
await expect(sponsorMessage).toBeVisible();
// verify click on sponsor
await sponsorMessage.click();
const sponsorModal = page.getByTestId("sponsor-modal");
await expectModalVisible(sponsorModal);
await expect(sponsorModal.getByRole("heading")).toContainText("Sponsorship");
});
});