chore: Typescript: Rewrite remaining components (#21638)
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Co-authored-by: Michael Geers <michael@geers.tv>
This commit is contained in:
parent
f927d5fa18
commit
4e619580ed
11 changed files with 105 additions and 56 deletions
|
|
@ -136,13 +136,14 @@
|
|||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import Modal from "bootstrap/js/dist/modal";
|
||||
import { docsPrefix } from "../i18n";
|
||||
import { performRestart } from "../restart";
|
||||
import { isLoggedIn, openLoginModal } from "./Auth/auth";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: "HelpModal",
|
||||
props: {},
|
||||
computed: {
|
||||
|
|
@ -152,11 +153,15 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
openHelpModal() {
|
||||
const modal = Modal.getOrCreateInstance(document.getElementById("helpModal"));
|
||||
const modal = Modal.getOrCreateInstance(
|
||||
document.getElementById("helpModal") as HTMLElement
|
||||
);
|
||||
modal.show();
|
||||
},
|
||||
openConfirmRestartModal() {
|
||||
const modal = Modal.getOrCreateInstance(document.getElementById("confirmRestartModal"));
|
||||
const modal = Modal.getOrCreateInstance(
|
||||
document.getElementById("confirmRestartModal") as HTMLElement
|
||||
);
|
||||
if (!isLoggedIn()) {
|
||||
openLoginModal(null, modal);
|
||||
} else {
|
||||
|
|
@ -167,5 +172,5 @@ export default {
|
|||
await performRestart();
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export default defineComponent({
|
|||
props: {
|
||||
id: String,
|
||||
options: Array as PropType<SelectOption<string>[]>,
|
||||
modelValue: [Number, String, Boolean],
|
||||
modelValue: [Number, String, Boolean, null],
|
||||
equalWidth: Boolean,
|
||||
large: Boolean,
|
||||
transparent: Boolean,
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import LabelAndValue from "../Helper/LabelAndValue.vue";
|
|||
import CustomSelect from "../Helper/CustomSelect.vue";
|
||||
import formatter from "@/mixins/formatter";
|
||||
import { getSessionInfo, setSessionInfo } from "./session";
|
||||
import type { CURRENCY, SelectOption } from "@/types/evcc";
|
||||
import type { CURRENCY, SelectOption, SessionInfoKey } from "@/types/evcc";
|
||||
|
||||
export default defineComponent({
|
||||
name: "LoadpointSessionInfo",
|
||||
|
|
@ -59,39 +59,44 @@ export default defineComponent({
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
options() {
|
||||
options(): Array<{
|
||||
key: SessionInfoKey;
|
||||
value: string;
|
||||
valueSm?: string;
|
||||
available?: boolean;
|
||||
}> {
|
||||
const result = [
|
||||
{
|
||||
key: "remaining",
|
||||
key: "remaining" as const,
|
||||
value: this.fmtDuration(this.chargeRemainingDurationInterpolated),
|
||||
available: this.chargeRemainingDurationInterpolated > 0,
|
||||
},
|
||||
{
|
||||
key: "finished",
|
||||
key: "finished" as const,
|
||||
value: this.fmtHourMinute(this.finishTime),
|
||||
available: this.chargeRemainingDurationInterpolated > 0,
|
||||
},
|
||||
{
|
||||
key: "duration",
|
||||
key: "duration" as const,
|
||||
value: this.fmtDuration(this.chargeDurationInterpolated),
|
||||
},
|
||||
{
|
||||
key: "solar",
|
||||
key: "solar" as const,
|
||||
value: this.solarFormatted,
|
||||
},
|
||||
{
|
||||
key: "avgPrice",
|
||||
key: "avgPrice" as const,
|
||||
value: this.fmtAvgPrice(this.sessionPricePerKWh),
|
||||
valueSm: this.fmtAvgPriceShort(this.sessionPricePerKWh),
|
||||
available: this.tariffGrid !== undefined,
|
||||
},
|
||||
{
|
||||
key: "price",
|
||||
key: "price" as const,
|
||||
value: this.priceFormatted,
|
||||
available: this.tariffGrid !== undefined,
|
||||
},
|
||||
{
|
||||
key: "co2",
|
||||
key: "co2" as const,
|
||||
value: this.fmtCo2Medium(this.sessionCo2PerKWh),
|
||||
valueSm: this.fmtCo2Short(this.sessionCo2PerKWh),
|
||||
available: this.tariffCo2 !== undefined,
|
||||
|
|
@ -100,10 +105,10 @@ export default defineComponent({
|
|||
// only show options that are available
|
||||
return result.filter(({ available }) => available === undefined || available);
|
||||
},
|
||||
optionKeys() {
|
||||
optionKeys(): SessionInfoKey[] {
|
||||
return this.options.map((option) => option.key);
|
||||
},
|
||||
selectOptions(): SelectOption<string>[] {
|
||||
selectOptions(): SelectOption<SessionInfoKey>[] {
|
||||
return this.optionKeys.map((key) => ({
|
||||
name: this.$t(`main.loadpoint.${key}`),
|
||||
value: key,
|
||||
|
|
@ -151,16 +156,18 @@ export default defineComponent({
|
|||
return this.fmtPricePerKWh(value, this.currency, true);
|
||||
},
|
||||
nextSessionInfo() {
|
||||
const index = this.optionKeys.indexOf(this.selectedKey);
|
||||
const index = this.selectedKey ? this.optionKeys.indexOf(this.selectedKey) : -1;
|
||||
this.selectedKey = this.optionKeys[index + 1] || this.optionKeys[0];
|
||||
this.presist();
|
||||
},
|
||||
selectOption(value: string) {
|
||||
selectOption(value: SessionInfoKey) {
|
||||
this.selectedKey = value;
|
||||
this.presist();
|
||||
},
|
||||
presist() {
|
||||
setSessionInfo(this.id, this.selectedKey);
|
||||
if (this.selectedKey) {
|
||||
setSessionInfo(this.id, this.selectedKey);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import settings from "@/settings";
|
||||
import type { SessionInfoKey } from "@/types/evcc";
|
||||
|
||||
export function getSessionInfo(index: number, fallback?: string) {
|
||||
return settings.sessionInfo[index - 1] || fallback;
|
||||
export function getSessionInfo(index: number): SessionInfoKey | undefined {
|
||||
return settings.sessionInfo[index - 1];
|
||||
}
|
||||
|
||||
export function setSessionInfo(index: number, value: string) {
|
||||
export function setSessionInfo(index: number, value: SessionInfoKey) {
|
||||
const clone = [...settings.sessionInfo];
|
||||
clone[index - 1] = value;
|
||||
clone.map((v) => v || "");
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ import Tile from "./Tile.vue";
|
|||
import LiveCommunity from "./LiveCommunity.vue";
|
||||
import TelemetrySettings from "../TelemetrySettings.vue";
|
||||
import CustomSelect from "../Helper/CustomSelect.vue";
|
||||
import settings from "@/settings";
|
||||
import settings from "@/settings.ts";
|
||||
import api, { allowClientError } from "@/api.ts";
|
||||
import { docsPrefix } from "@/i18n.ts";
|
||||
import { defineComponent, type PropType } from "vue";
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ import { defineComponent, type PropType } from "vue";
|
|||
import CustomSelect from "../Helper/CustomSelect.vue";
|
||||
import formatter, { POWER_UNIT } from "@/mixins/formatter";
|
||||
import breakpoint from "@/mixins/breakpoint.ts";
|
||||
import settings from "@/settings";
|
||||
import settings from "@/settings.ts";
|
||||
import type { CURRENCY } from "@/types/evcc";
|
||||
import type { Session, Column } from "./types";
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ export default defineComponent({
|
|||
emits: ["show-session"],
|
||||
data() {
|
||||
return {
|
||||
selectedColumns: settings.sessionColumns,
|
||||
selectedColumns: [] as string[],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -417,7 +417,7 @@ export default defineComponent({
|
|||
.filter(this.filterByVehicle)
|
||||
.filter((s) => !loadpoint || s.loadpoint === loadpoint).length;
|
||||
},
|
||||
selectColumnPosition(index: number, value: Column) {
|
||||
selectColumnPosition(index: number, value: string) {
|
||||
this.selectedColumns[index] = value;
|
||||
settings.sessionColumns = [...this.selectedColumns];
|
||||
},
|
||||
|
|
|
|||
|
|
@ -30,12 +30,14 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import api from "../api";
|
||||
import { docsPrefix } from "../i18n";
|
||||
import settings from "../settings";
|
||||
import settings from "@/settings.ts";
|
||||
import type { AxiosError } from "axios";
|
||||
|
||||
function parseMarkdown(markdownText) {
|
||||
function parseMarkdown(markdownText: string) {
|
||||
const htmlText = markdownText
|
||||
.replace(/\*\*(.*)\*\*/gim, "<b>$1</b>")
|
||||
.replace(/\*(.*)\*/gim, "<i>$1</i>")
|
||||
|
|
@ -43,12 +45,12 @@ function parseMarkdown(markdownText) {
|
|||
return htmlText.trim();
|
||||
}
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: "TelemetrySettings",
|
||||
props: { sponsorActive: Boolean },
|
||||
data() {
|
||||
return {
|
||||
error: null,
|
||||
error: null as string | null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -63,14 +65,17 @@ export default {
|
|||
await this.update();
|
||||
},
|
||||
methods: {
|
||||
async change(e) {
|
||||
async change(e: Event) {
|
||||
try {
|
||||
this.error = null;
|
||||
const response = await api.post(`settings/telemetry/${e.target.checked}`);
|
||||
const response = await api.post(
|
||||
`settings/telemetry/${(e.target as HTMLInputElement).checked}`
|
||||
);
|
||||
settings.telemetry = response.data.result;
|
||||
} catch (err) {
|
||||
if (err.response) {
|
||||
this.error = parseMarkdown("**Error:** " + err.response.data.error);
|
||||
const e = err as AxiosError<{ error: string }>;
|
||||
if (e.response) {
|
||||
this.error = parseMarkdown("**Error:** " + e.response.data.error);
|
||||
settings.telemetry = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -91,7 +96,7 @@ export default {
|
|||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.form-check {
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ export function getLocalePreference() {
|
|||
|
||||
export function removeLocalePreference(i18n: VueI18nInstance) {
|
||||
settings.locale = null;
|
||||
setI18nLanguage(i18n, DEFAULT_BROWSER_LOCALE as typeof i18n.locale);
|
||||
setI18nLanguage(i18n, DEFAULT_BROWSER_LOCALE as keyof typeof LOCALES);
|
||||
ensureCurrentLocaleMessages(i18n);
|
||||
}
|
||||
|
||||
export function setLocalePreference(i18n: VueI18nInstance, locale: typeof i18n.locale) {
|
||||
export function setLocalePreference(i18n: VueI18nInstance, locale: keyof typeof LOCALES) {
|
||||
if (!(locale in LOCALES)) {
|
||||
console.error("unknown locale", locale);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { reactive, watch } from "vue";
|
||||
import type { THEME, SessionInfoKey } from "./types/evcc";
|
||||
import type { LOCALES } from "./i18n";
|
||||
|
||||
const SETTINGS_LOCALE = "settings_locale";
|
||||
const SETTINGS_THEME = "settings_theme";
|
||||
|
|
@ -16,12 +18,12 @@ const SAVINGS_REGION = "savings_region";
|
|||
const SESSIONS_GROUP = "sessions_group";
|
||||
const SESSIONS_TYPE = "sessions_type";
|
||||
const SETTINGS_SOLAR_ADJUSTED = "settings_solar_adjusted";
|
||||
function read(key) {
|
||||
function read(key: string) {
|
||||
return window.localStorage[key];
|
||||
}
|
||||
|
||||
function save(key) {
|
||||
return (value) => {
|
||||
function save(key: string) {
|
||||
return (value: string | null) => {
|
||||
try {
|
||||
if (value) {
|
||||
window.localStorage[key] = value;
|
||||
|
|
@ -34,29 +36,49 @@ function save(key) {
|
|||
};
|
||||
}
|
||||
|
||||
function readBool(key) {
|
||||
function readBool(key: string) {
|
||||
return read(key) === "true";
|
||||
}
|
||||
|
||||
function saveBool(key) {
|
||||
return (value) => {
|
||||
function saveBool(key: string) {
|
||||
return (value: boolean) => {
|
||||
save(key)(value ? "true" : "false");
|
||||
};
|
||||
}
|
||||
|
||||
function readArray(key) {
|
||||
function readArray(key: string) {
|
||||
const value = read(key);
|
||||
return value ? value.split(",") : [];
|
||||
}
|
||||
|
||||
function saveArray(key) {
|
||||
return (value) => {
|
||||
function saveArray(key: string) {
|
||||
return (value: string[]) => {
|
||||
save(key)(value.join(","));
|
||||
};
|
||||
}
|
||||
|
||||
const settings = reactive({
|
||||
telemetry: null,
|
||||
export interface Settings {
|
||||
telemetry: boolean;
|
||||
locale: keyof typeof LOCALES | null;
|
||||
theme: THEME | null;
|
||||
unit: string;
|
||||
is12hFormat: boolean;
|
||||
hiddenFeatures: boolean;
|
||||
energyflowDetails: boolean;
|
||||
energyflowPv: boolean;
|
||||
energyflowBattery: boolean;
|
||||
energyflowLoadpoints: boolean;
|
||||
sessionInfo: SessionInfoKey[];
|
||||
sessionColumns: string[];
|
||||
savingsPeriod: string;
|
||||
savingsRegion: string;
|
||||
sessionsGroup: string;
|
||||
sessionsType: string;
|
||||
solarAdjusted: boolean;
|
||||
}
|
||||
|
||||
const settings: Settings = reactive({
|
||||
telemetry: false,
|
||||
locale: read(SETTINGS_LOCALE),
|
||||
theme: read(SETTINGS_THEME),
|
||||
unit: read(SETTINGS_UNIT),
|
||||
|
|
@ -66,7 +88,7 @@ const settings = reactive({
|
|||
energyflowPv: readBool(SETTINGS_ENERGYFLOW_PV),
|
||||
energyflowBattery: readBool(SETTINGS_ENERGYFLOW_BATTERY),
|
||||
energyflowLoadpoints: readBool(SETTINGS_ENERGYFLOW_LOADPOINTS),
|
||||
sessionInfo: readArray(SESSION_INFO),
|
||||
sessionInfo: readArray(SESSION_INFO) as SessionInfoKey[],
|
||||
sessionColumns: readArray(SESSION_COLUMNS),
|
||||
savingsPeriod: read(SAVINGS_PERIOD),
|
||||
savingsRegion: read(SAVINGS_REGION),
|
||||
|
|
@ -85,7 +107,7 @@ watch(() => settings.energyflowPv, saveBool(SETTINGS_ENERGYFLOW_PV));
|
|||
watch(() => settings.energyflowBattery, saveBool(SETTINGS_ENERGYFLOW_BATTERY));
|
||||
watch(() => settings.energyflowLoadpoints, saveBool(SETTINGS_ENERGYFLOW_LOADPOINTS));
|
||||
watch(() => settings.sessionInfo, saveArray(SESSION_INFO));
|
||||
watch(() => settings.sessionColumns, saveArray(SESSION_COLUMNS));
|
||||
watch(() => settings.sessionColumns as string[], saveArray(SESSION_COLUMNS));
|
||||
watch(() => settings.savingsPeriod, save(SAVINGS_PERIOD));
|
||||
watch(() => settings.savingsRegion, save(SAVINGS_REGION));
|
||||
watch(() => settings.sessionsGroup, save(SESSIONS_GROUP));
|
||||
|
|
@ -3,9 +3,9 @@ import { THEME } from "./types/evcc";
|
|||
|
||||
const darkModeMatcher = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
||||
export function getThemePreference(): THEME {
|
||||
export function getThemePreference(): THEME | null {
|
||||
const theme = settings.theme;
|
||||
if (Object.values(THEME).includes(theme)) {
|
||||
if (theme && Object.values(THEME).includes(theme)) {
|
||||
return theme;
|
||||
}
|
||||
return THEME.AUTO;
|
||||
|
|
@ -19,10 +19,10 @@ export function setThemePreference(theme: THEME) {
|
|||
updateTheme();
|
||||
}
|
||||
|
||||
function setMetaThemeColor(theme: Exclude<THEME, THEME.AUTO>) {
|
||||
function setMetaThemeColor(theme: Exclude<THEME, THEME.AUTO> | null) {
|
||||
const themeColors = { light: "#f3f3f7", dark: "#020318" };
|
||||
const $metaThemeColor = document.querySelector("meta[name=theme-color]");
|
||||
if ($metaThemeColor) {
|
||||
if ($metaThemeColor && theme) {
|
||||
$metaThemeColor.setAttribute("content", themeColors[theme]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,15 @@ export enum PHASES {
|
|||
THREE_PHASES = 3,
|
||||
}
|
||||
|
||||
export type SessionInfoKey =
|
||||
| "remaining"
|
||||
| "finished"
|
||||
| "duration"
|
||||
| "solar"
|
||||
| "avgPrice"
|
||||
| "price"
|
||||
| "co2";
|
||||
|
||||
export interface Sponsor {
|
||||
name: string;
|
||||
expiresAt: string;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue