UI: configure settings via URL params (#31244)
This commit is contained in:
parent
64a7600b78
commit
b0a3564d26
5 changed files with 90 additions and 7 deletions
|
|
@ -6,6 +6,7 @@ import App from "./views/App.vue";
|
|||
import setupRouter from "./router.ts";
|
||||
import setupI18n from "./i18n.ts";
|
||||
import { watchThemeChanges } from "./theme.ts";
|
||||
import { applyUrlSettings } from "./urlSettings.ts";
|
||||
import { appDetection, sendToApp } from "./utils/native";
|
||||
import store from "./store";
|
||||
import type { Notification } from "./types/evcc";
|
||||
|
|
@ -74,6 +75,8 @@ const app = createApp(
|
|||
})
|
||||
);
|
||||
|
||||
applyUrlSettings();
|
||||
|
||||
const i18n = setupI18n();
|
||||
const head = createHead();
|
||||
|
||||
|
|
|
|||
|
|
@ -94,10 +94,7 @@ import { getThemePreference, setThemePreference } from "@/theme.ts";
|
|||
import { getUnits, setUnits, is12hFormat, set12hFormat } from "@/units";
|
||||
import { isApp } from "@/utils/native";
|
||||
import { defineComponent, type PropType } from "vue";
|
||||
import { LENGTH_UNIT, THEME, type UiLoadpoint } from "@/types/evcc";
|
||||
|
||||
const TIME_12H = "12";
|
||||
const TIME_24H = "24";
|
||||
import { LENGTH_UNIT, THEME, TIME_FORMAT, type UiLoadpoint } from "@/types/evcc";
|
||||
|
||||
export default defineComponent({
|
||||
name: "UserInterfaceSettings",
|
||||
|
|
@ -110,11 +107,11 @@ export default defineComponent({
|
|||
theme: getThemePreference(),
|
||||
language: getLocalePreference() || "",
|
||||
unit: getUnits(),
|
||||
timeFormat: is12hFormat() ? TIME_12H : TIME_24H,
|
||||
timeFormat: is12hFormat() ? TIME_FORMAT.H12 : TIME_FORMAT.H24,
|
||||
fullscreenActive: false,
|
||||
THEMES: Object.values(THEME),
|
||||
UNITS: Object.values(LENGTH_UNIT),
|
||||
TIME_FORMATS: [TIME_24H, TIME_12H],
|
||||
TIME_FORMATS: [TIME_FORMAT.H24, TIME_FORMAT.H12],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -139,7 +136,7 @@ export default defineComponent({
|
|||
setUnits(value);
|
||||
},
|
||||
timeFormat(value) {
|
||||
set12hFormat(value === TIME_12H);
|
||||
set12hFormat(value === TIME_FORMAT.H12);
|
||||
},
|
||||
theme(value) {
|
||||
setThemePreference(value);
|
||||
|
|
|
|||
|
|
@ -289,6 +289,11 @@ export enum LENGTH_UNIT {
|
|||
MILES = "mi",
|
||||
}
|
||||
|
||||
export enum TIME_FORMAT {
|
||||
H12 = "12",
|
||||
H24 = "24",
|
||||
}
|
||||
|
||||
export interface Loadpoint {
|
||||
name: string;
|
||||
batteryBoost: boolean;
|
||||
|
|
|
|||
41
assets/js/urlSettings.ts
Normal file
41
assets/js/urlSettings.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import settings from "./settings";
|
||||
import { LOCALES } from "./i18n";
|
||||
import { LENGTH_UNIT, THEME, TIME_FORMAT } from "./types/evcc";
|
||||
|
||||
export function applyUrlSettings() {
|
||||
const url = new URL(window.location.href);
|
||||
const params = url.searchParams;
|
||||
let touched = false;
|
||||
|
||||
const theme = params.get("theme");
|
||||
if (theme && Object.values(THEME).includes(theme as THEME)) {
|
||||
settings.theme = theme as THEME;
|
||||
touched = true;
|
||||
}
|
||||
|
||||
const lang = params.get("lang");
|
||||
if (lang === "auto") {
|
||||
settings.locale = null;
|
||||
touched = true;
|
||||
} else if (lang && lang in LOCALES) {
|
||||
settings.locale = lang as keyof typeof LOCALES;
|
||||
touched = true;
|
||||
}
|
||||
|
||||
const unit = params.get("unit");
|
||||
if (unit && Object.values(LENGTH_UNIT).includes(unit as LENGTH_UNIT)) {
|
||||
settings.unit = unit as LENGTH_UNIT;
|
||||
touched = true;
|
||||
}
|
||||
|
||||
const format = params.get("format");
|
||||
if (format && Object.values(TIME_FORMAT).includes(format as TIME_FORMAT)) {
|
||||
settings.is12hFormat = format === TIME_FORMAT.H12;
|
||||
touched = true;
|
||||
}
|
||||
|
||||
if (touched) {
|
||||
["theme", "lang", "unit", "format"].forEach((k) => params.delete(k));
|
||||
window.history.replaceState(window.history.state, "", url.pathname + url.search + url.hash);
|
||||
}
|
||||
}
|
||||
37
tests/url-settings.spec.ts
Normal file
37
tests/url-settings.spec.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import { test, expect } from "@playwright/test";
|
||||
import { start, stop, baseUrl } from "./evcc";
|
||||
|
||||
test.use({ baseURL: baseUrl() });
|
||||
|
||||
test.beforeAll(async () => {
|
||||
await start();
|
||||
});
|
||||
test.afterAll(async () => {
|
||||
await stop();
|
||||
});
|
||||
|
||||
test.describe("ui settings via url", async () => {
|
||||
test("apply, persist and strip valid params", async ({ page }) => {
|
||||
await page.goto("/?theme=dark&lang=de&unit=mi&format=12");
|
||||
|
||||
await expect(page.locator("html")).toHaveAttribute("data-bs-theme", "dark");
|
||||
await expect(page.locator("html")).toHaveAttribute("lang", "de");
|
||||
|
||||
const stored = await page.evaluate(() => ({
|
||||
theme: localStorage["settings_theme"],
|
||||
locale: localStorage["settings_locale"],
|
||||
unit: localStorage["settings_unit"],
|
||||
format: localStorage["settings_12h_format"],
|
||||
}));
|
||||
expect(stored).toEqual({ theme: "dark", locale: "de", unit: "mi", format: "true" });
|
||||
|
||||
// params removed from address bar
|
||||
expect(new URL(page.url()).search).toBe("");
|
||||
});
|
||||
|
||||
test("ignore invalid value and keep it in url", async ({ page }) => {
|
||||
await page.goto("/?theme=bogus");
|
||||
await expect(page.locator("html")).not.toHaveAttribute("data-bs-theme", "bogus");
|
||||
expect(new URL(page.url()).searchParams.get("theme")).toBe("bogus");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue