Skip to content

Commit 3e7f3ca

Browse files
committed
feat: support all nws files
1 parent 06337a0 commit 3e7f3ca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+6469
-522
lines changed

app/app.vue

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,14 @@ const items: NavigationMenuItem[] = [
102102
},
103103
];
104104
105-
const importStore = useImportStore();
105+
const uiStore = useUIStore();
106106
107107
onMounted(() => {
108108
if (
109-
Object.keys(importStore.translations).length === 0 &&
110-
Object.keys(importStore.remoteTranslations).length > 0
109+
Object.keys(uiStore.translations).length === 0 &&
110+
Object.keys(uiStore.remoteTranslations).length > 0
111111
) {
112-
importStore.translations = parseTranslationFile(
113-
importStore.translationsString,
114-
);
112+
uiStore.translations = parseTranslationFile(uiStore.translationsString);
115113
}
116114
});
117115
</script>

app/components/FileSelect.vue

Whitespace-only changes.

app/components/ImportForm.vue

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
<template>
2+
<UForm
3+
:state="state"
4+
:schema="schema"
5+
class="flex flex-col gap-4"
6+
@error="onError"
7+
@submit="onSubmit"
8+
>
9+
<UFormField
10+
required
11+
name="ui"
12+
label="NWS UI"
13+
description="Plak tekst uit het Google Docs bestand."
14+
>
15+
<UTextarea
16+
v-model="state.ui"
17+
class="w-full"
18+
placeholder="about: About&#10;about1: New World Scheduler..."
19+
/>
20+
</UFormField>
21+
<UFormField
22+
v-if="!noNwp"
23+
name="nwp"
24+
label="NWP UI"
25+
description="Plak tekst uit het Google Docs bestand."
26+
>
27+
<UTextarea
28+
v-model="state.nwp"
29+
class="w-full"
30+
placeholder='"____v360____": "",&#10;"____GENERAL____": "",&#10;...'
31+
/>
32+
</UFormField>
33+
<UFormField
34+
v-for="file in jsonFiles"
35+
:key="file.key"
36+
:name="file.key"
37+
:label="file.label"
38+
:error="errors[file.key]"
39+
description="Plak tekst uit het lokale .json-bestand (Literature, Outlines, Songs, Tips)."
40+
>
41+
<UTextarea v-model="state[file.key]" class="w-full" />
42+
</UFormField>
43+
<UButton class="w-fit" type="submit" label="Opslaan" />
44+
</UForm>
45+
</template>
46+
47+
<script setup lang="ts">
48+
import type { FormErrorEvent, FormSubmitEvent } from "@nuxt/ui";
49+
50+
import { z } from "zod";
51+
52+
defineProps<{
53+
noNwp?: boolean;
54+
}>();
55+
56+
const model = defineModel<Output>();
57+
58+
const jsonFiles: { key: keyof Input; label: string }[] = [
59+
{ key: "literature", label: "Literatuur" },
60+
{ key: "outlines", label: "Lezingen" },
61+
{ key: "songs", label: "Liederen" },
62+
{ key: "tips", label: "Tips" },
63+
];
64+
65+
const schema = z.object({
66+
literature: jsonCodec(literatureSchema).optional(),
67+
nwp: translationFileSchema.optional(),
68+
outlines: jsonCodec(outlinesSchema).optional(),
69+
songs: jsonCodec(songsSchema).optional(),
70+
tips: jsonCodec(tipsSchema).optional(),
71+
ui: translationFileSchema,
72+
});
73+
74+
export type Input = z.input<typeof schema>;
75+
export type Output = z.output<typeof schema>;
76+
77+
const state = reactive<Partial<Input>>(
78+
model.value && schema.partial().safeEncode(model.value).success
79+
? schema.partial().encode(model.value)
80+
: {},
81+
);
82+
83+
watch(
84+
model,
85+
(newVal) => {
86+
if (newVal) {
87+
const parsed = newVal.ui
88+
? schema.partial().safeEncode(newVal)
89+
: schema.omit({ ui: true }).safeEncode(newVal);
90+
if (parsed.success) {
91+
typedKeys(parsed.data).forEach((key) => {
92+
state[key] = parsed.data[key];
93+
});
94+
} else {
95+
console.warn("Invalid model", parsed.error);
96+
}
97+
} else {
98+
typedKeys(state).forEach((key) => {
99+
state[key] = undefined;
100+
});
101+
}
102+
},
103+
{ immediate: true },
104+
);
105+
106+
const errors = ref<Record<string, string>>({});
107+
108+
function onError(event: FormErrorEvent) {
109+
errors.value = {};
110+
event.errors.forEach((error) => {
111+
if (error.name && !jsonFiles.some((file) => file.key === error.name)) {
112+
const key = error.name.split(".")[0];
113+
if (key) errors.value[key] = error.message;
114+
}
115+
});
116+
117+
if (Object.keys(errors.value).length === 0) {
118+
showError("De ingevoerde tekst is niet geldig.");
119+
}
120+
}
121+
122+
function onSubmit(event: FormSubmitEvent<Output>) {
123+
model.value = event.data;
124+
}
125+
</script>

app/components/LiteratureForm.vue

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<template>
2+
<UForm
3+
:state="state"
4+
:schema="schema"
5+
class="flex flex-col gap-4"
6+
@submit="onSubmit"
7+
>
8+
<UFormField
9+
name="title"
10+
:hint="item.symbol"
11+
:description="item.title"
12+
:label="`Lectuurartikel ${item.id}`"
13+
>
14+
<UInput v-model="state.title" class="w-full" />
15+
</UFormField>
16+
<UButton class="w-fit" type="submit" label="Opslaan" />
17+
</UForm>
18+
</template>
19+
<script setup lang="ts">
20+
import type { FormSubmitEvent } from "@nuxt/ui";
21+
22+
import { z } from "zod";
23+
24+
const props = defineProps<{
25+
item: LiteratureItem;
26+
}>();
27+
28+
const translationStore = useTranslationStore();
29+
30+
const translation = computed(() =>
31+
translationStore.translations.literature?.find((s) => s.id === props.item.id),
32+
);
33+
34+
const schema = z.object({
35+
title: z.string().nonempty(),
36+
});
37+
38+
type Schema = z.infer<typeof schema>;
39+
40+
const state = reactive<Partial<Schema>>({
41+
title: translation.value?.title,
42+
});
43+
44+
const { showSuccess } = useFlash();
45+
46+
function onSubmit(event: FormSubmitEvent<Schema>) {
47+
const literature = translationStore.translations.literature?.map((item) =>
48+
item.id === props.item.id ? { ...item, ...event.data } : item,
49+
);
50+
51+
translationStore.setTranslations({ literature }, "literature");
52+
showSuccess({ description: "Lectuurartikel opgeslagen.", id: "item-saved" });
53+
}
54+
</script>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<template>
2+
<TranslationForm
3+
:translation="translation"
4+
:translation-key="translationKey"
5+
@submit="save"
6+
/>
7+
</template>
8+
<script setup lang="ts">
9+
const props = defineProps<{
10+
newValue?: string;
11+
translationKey: string;
12+
}>();
13+
14+
const emit = defineEmits<{
15+
(e: "save"): void;
16+
}>();
17+
18+
const uiStore = useUIStore();
19+
20+
const translation = computed(() => {
21+
return (
22+
props.newValue || uiStore.nwpTranslations?.[props.translationKey] || ""
23+
);
24+
});
25+
26+
const { showSuccess } = useFlash();
27+
28+
const save = (newTranslation: string) => {
29+
if (!uiStore.nwpTranslations) return;
30+
uiStore.nwpTranslations[props.translationKey] = newTranslation;
31+
emit("save");
32+
showSuccess({
33+
description: "NWP-vertaling opgeslagen.",
34+
id: "nwp-translation-form",
35+
});
36+
};
37+
</script>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<template>
2+
<TranslationForm
3+
:original="original"
4+
:translation="translation"
5+
:translation-key="translationKey"
6+
@submit="save"
7+
/>
8+
</template>
9+
<script setup lang="ts">
10+
const props = defineProps<{
11+
newValue?: string;
12+
translationKey: string;
13+
}>();
14+
15+
const emit = defineEmits<{
16+
(e: "save"): void;
17+
}>();
18+
19+
const uiStore = useUIStore();
20+
21+
const original = computed(
22+
() => uiStore.references[props.translationKey] || props.translationKey,
23+
);
24+
const translation = computed(() => {
25+
return props.newValue || uiStore.translations[props.translationKey] || "";
26+
});
27+
28+
const { showSuccess } = useFlash();
29+
30+
const save = (newTranslation: string) => {
31+
uiStore.translations[props.translationKey] = newTranslation;
32+
emit("save");
33+
showSuccess({
34+
description: "NWS-vertaling opgeslagen.",
35+
id: "nws-translation-form",
36+
});
37+
};
38+
</script>

app/components/OutlineForm.vue

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<template>
2+
<UForm
3+
v-if="outline.title"
4+
:state="state"
5+
:schema="schema"
6+
class="flex flex-col gap-4"
7+
@submit="onSubmit"
8+
>
9+
<UFormField
10+
name="title"
11+
:description="outline.title"
12+
:label="`Lezing nr. ${outline.number}`"
13+
>
14+
<UInput v-model="state.title" class="w-full" />
15+
</UFormField>
16+
<UFormField
17+
v-if="outline.updated"
18+
hint="m/yy"
19+
name="updated"
20+
label="Bijgewerkt op"
21+
:description="outline.updated"
22+
>
23+
<UInput v-model="state.updated" class="w-full" />
24+
</UFormField>
25+
<UFormField
26+
v-if="outline.notes"
27+
name="notes"
28+
label="Opmerking"
29+
:description="outline.notes"
30+
>
31+
<UTextarea v-model="state.notes" :rows="1" autoresize class="w-full" />
32+
</UFormField>
33+
<UButton class="w-fit" type="submit" label="Opslaan" />
34+
</UForm>
35+
</template>
36+
<script setup lang="ts">
37+
import type { FormSubmitEvent } from "@nuxt/ui";
38+
39+
import { z } from "zod";
40+
41+
const props = defineProps<{
42+
outline: Outline;
43+
}>();
44+
45+
const translationStore = useTranslationStore();
46+
47+
const translation = computed(() =>
48+
translationStore.translations.outlines?.find(
49+
(s) => s.number === props.outline.number,
50+
),
51+
);
52+
53+
const schema = z.object({
54+
notes: z.string().optional(),
55+
title: z.string().optional(),
56+
updated: z.string(),
57+
});
58+
59+
type Schema = z.infer<typeof schema>;
60+
61+
const state = reactive<Partial<Schema>>({
62+
notes: translation.value?.notes,
63+
title: translation.value?.title,
64+
updated: translation.value?.updated,
65+
});
66+
67+
const { showSuccess } = useFlash();
68+
69+
function onSubmit(event: FormSubmitEvent<Schema>) {
70+
const outlines = translationStore.translations.outlines?.map((outline) =>
71+
outline.number === props.outline.number
72+
? { ...outline, ...event.data }
73+
: outline,
74+
);
75+
76+
translationStore.setTranslations({ outlines }, "outlines");
77+
showSuccess({ description: "Schema opgeslagen.", id: "outline-saved" });
78+
}
79+
</script>

0 commit comments

Comments
 (0)