wip
This commit is contained in:
parent
c742b244b4
commit
b5ce0124a0
49
frontend/package-lock.json
generated
49
frontend/package-lock.json
generated
|
@ -11,7 +11,9 @@
|
||||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||||
"@sveltejs/adapter-auto": "^2.1.0",
|
"@sveltejs/adapter-auto": "^2.1.0",
|
||||||
"@sveltejs/kit": "^1.24.1",
|
"@sveltejs/kit": "^1.24.1",
|
||||||
"axios": "^1.5.0"
|
"axios": "^1.5.0",
|
||||||
|
"svelte-forms-lib": "^2.0.1",
|
||||||
|
"yup": "^1.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
||||||
|
@ -1756,6 +1758,11 @@
|
||||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/property-expr": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
|
||||||
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
|
@ -2071,6 +2078,14 @@
|
||||||
"svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0"
|
"svelte": "^3.55.0 || ^4.0.0-next.0 || ^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelte-forms-lib": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-forms-lib/-/svelte-forms-lib-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-kwbJ3ynsepsrrJyAMrvSc0Lj/myc9vfI2DL8OKxgArZimrNYsRh1gENYhvrcKEI3BiZrv8q3VFfmGo/GMyk7Zg==",
|
||||||
|
"dependencies": {
|
||||||
|
"dequal": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/svelte-hmr": {
|
"node_modules/svelte-hmr": {
|
||||||
"version": "0.15.3",
|
"version": "0.15.3",
|
||||||
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz",
|
"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz",
|
||||||
|
@ -2226,6 +2241,11 @@
|
||||||
"node": ">=0.8"
|
"node": ">=0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-case": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="
|
||||||
|
},
|
||||||
"node_modules/tiny-glob": {
|
"node_modules/tiny-glob": {
|
||||||
"version": "0.2.9",
|
"version": "0.2.9",
|
||||||
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
||||||
|
@ -2247,6 +2267,11 @@
|
||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/toposort": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
|
||||||
|
},
|
||||||
"node_modules/totalist": {
|
"node_modules/totalist": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
|
||||||
|
@ -2267,6 +2292,17 @@
|
||||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
|
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/type-fest": {
|
||||||
|
"version": "2.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.2.2",
|
"version": "5.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
|
||||||
|
@ -2408,6 +2444,17 @@
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 14"
|
"node": ">= 14"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yup": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yup/-/yup-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-PPqYKSAXjpRCgLgLKVGPA33v5c/WgEx3wi6NFjIiegz90zSwyMpvTFp/uGcVnnbx6to28pgnzp/q8ih3QRjLMQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"property-expr": "^2.0.5",
|
||||||
|
"tiny-case": "^1.0.3",
|
||||||
|
"toposort": "^2.0.2",
|
||||||
|
"type-fest": "^2.19.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
"@fortawesome/fontawesome-free": "^6.4.2",
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
||||||
"@sveltejs/adapter-auto": "^2.1.0",
|
"@sveltejs/adapter-auto": "^2.1.0",
|
||||||
"@sveltejs/kit": "^1.24.1",
|
"@sveltejs/kit": "^1.24.1",
|
||||||
"axios": "^1.5.0"
|
"axios": "^1.5.0",
|
||||||
|
"svelte-forms-lib": "^2.0.1",
|
||||||
|
"yup": "^1.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
frontend/src/lib/ButtonMain.svelte
Normal file
11
frontend/src/lib/ButtonMain.svelte
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script lang="ts">
|
||||||
|
export let onClick = (e?) => {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="bg-violet-600 hover:bg-violet-700 rounded-md text-white p-1 w-6 h-6 justify-center"
|
||||||
|
on:click|preventDefault={onClick}
|
||||||
|
>
|
||||||
|
<slot />
|
||||||
|
</button>
|
11
frontend/src/lib/ButtonTrash.svelte
Normal file
11
frontend/src/lib/ButtonTrash.svelte
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script lang="ts">
|
||||||
|
export let onClick = (e?) => {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="bg-red-600 hover:bg-red-700 rounded-md text-white p-1 w-6 h-6 justify-center"
|
||||||
|
on:click|preventDefault={onClick}
|
||||||
|
>
|
||||||
|
<span class="fa-solid fa-trash align-top" />
|
||||||
|
</button>
|
|
@ -1,14 +1,102 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { afterUpdate, createEventDispatcher } from "svelte";
|
||||||
import type { Level } from "./types";
|
import type { Level } from "./types";
|
||||||
import LevelTag from "./LevelTag.svelte";
|
import LevelTag from "./LevelTag.svelte";
|
||||||
|
import ButtonMain from "./ButtonMain.svelte";
|
||||||
|
import ButtonTrash from "./ButtonTrash.svelte";
|
||||||
|
import axios from "$lib/api.ts";
|
||||||
|
|
||||||
|
export let id: number;
|
||||||
export let word: string;
|
export let word: string;
|
||||||
export let definition: string;
|
export let definition: string;
|
||||||
export let level: Level;
|
export let level: Level;
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
function deleteWord() {
|
||||||
|
dispatch("deleteWord");
|
||||||
|
}
|
||||||
|
|
||||||
|
let isEditLevel = false;
|
||||||
|
let isEditWord = false;
|
||||||
|
let isEditDefinition = false;
|
||||||
|
|
||||||
|
function toggleEditLevel() {
|
||||||
|
isEditLevel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleEditWord() {
|
||||||
|
isEditWord = true;
|
||||||
|
}
|
||||||
|
function toggleEditDefinition() {
|
||||||
|
isEditDefinition = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(el) {
|
||||||
|
el.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateWord() {
|
||||||
|
try {
|
||||||
|
axios.patch("words/" + id + "/", { word: word });
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function updateDefinition() {
|
||||||
|
try {
|
||||||
|
axios.patch("words/" + id + "/", { definition: definition });
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="">
|
<tr class="text-slate-700 border-b">
|
||||||
<LevelTag {level} />
|
<td class="p-2">
|
||||||
|
{#if !isEditLevel}
|
||||||
|
<LevelTag {level} on:click={toggleEditLevel} />
|
||||||
|
{:else}
|
||||||
|
<select />
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
<td class="p-2">
|
||||||
|
{#if !isEditWord}
|
||||||
|
<div
|
||||||
|
class="p-1 w-full hover:cursor-pointer"
|
||||||
|
on:click={toggleEditWord}
|
||||||
|
>
|
||||||
|
{word}
|
||||||
</div>
|
</div>
|
||||||
<div>{word}</div>
|
{:else}
|
||||||
<div>{definition}</div>
|
<input
|
||||||
|
name="word"
|
||||||
|
bind:value={word}
|
||||||
|
class="p-1 rounded-md border w-full"
|
||||||
|
use:init
|
||||||
|
on:change={updateWord}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
<td class="p-2">
|
||||||
|
{#if !isEditDefinition}
|
||||||
|
<div
|
||||||
|
class="w-full hover:cursor-pointer"
|
||||||
|
on:click={toggleEditDefinition}
|
||||||
|
>
|
||||||
|
{definition}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
name="definition"
|
||||||
|
bind:value={definition}
|
||||||
|
on:change={updateDefinition}
|
||||||
|
use:init
|
||||||
|
class="p-1 rounded-md border w-full"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ButtonTrash onClick={deleteWord} />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
7
frontend/src/lib/arrays.ts
Normal file
7
frontend/src/lib/arrays.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export function deleteFromArray(arr: any[], obj: any): any[] {
|
||||||
|
const index = arr.indexOf(obj, 0);
|
||||||
|
if (index > -1) {
|
||||||
|
arr.splice(index, 1);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
|
@ -2,80 +2,197 @@
|
||||||
import { page } from "$app/stores";
|
import { page } from "$app/stores";
|
||||||
import axios from "$lib/api.ts";
|
import axios from "$lib/api.ts";
|
||||||
import WordForm from "$lib/WordForm.svelte";
|
import WordForm from "$lib/WordForm.svelte";
|
||||||
import { type Word } from "../../lib/types";
|
import ButtonMain from "$lib/ButtonMain.svelte";
|
||||||
|
import type { Level, Word } from "../../lib/types";
|
||||||
|
import { deleteFromArray } from "$lib/arrays";
|
||||||
|
|
||||||
import { snakeToCamelCase } from "$lib/case";
|
import { snakeToCamelCase } from "$lib/case";
|
||||||
|
import { onMount, tick } from "svelte";
|
||||||
|
import type { AxiosResponse } from "axios";
|
||||||
|
import { createForm } from "svelte-forms-lib";
|
||||||
|
import * as yup from "yup";
|
||||||
|
|
||||||
let words: Word[];
|
let words: Word[];
|
||||||
const wordResponse = axios.get("words/").then((data) => {
|
$: words;
|
||||||
|
let levels: Level[];
|
||||||
|
let promise;
|
||||||
|
let promiseLevels;
|
||||||
|
|
||||||
|
// Form
|
||||||
|
const { form, errors, state, handleChange, handleSubmit } = createForm({
|
||||||
|
initialValues: {
|
||||||
|
level: "",
|
||||||
|
word: "",
|
||||||
|
definition: "",
|
||||||
|
},
|
||||||
|
validationSchema: yup.object().shape({
|
||||||
|
level: yup.number().required(),
|
||||||
|
word: yup.string().required(),
|
||||||
|
definition: yup.string().required(),
|
||||||
|
}),
|
||||||
|
onSubmit: (values) => {
|
||||||
|
submitNewWord(values);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function fetchLevels() {
|
||||||
|
try {
|
||||||
|
promiseLevels = axios.get("levels/").then((data) => {
|
||||||
|
levels = snakeToCamelCase(data.data);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchData() {
|
||||||
|
try {
|
||||||
|
promise = axios.get("words/").then((data) => {
|
||||||
words = snakeToCamelCase(data.data);
|
words = snakeToCamelCase(data.data);
|
||||||
});
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let isFormNewShown = false;
|
let isFormNewShown = false;
|
||||||
|
|
||||||
function toggleFormNew() {
|
function toggleFormNew() {
|
||||||
isFormNewShown = !isFormNewShown;
|
isFormNewShown = !isFormNewShown;
|
||||||
}
|
}
|
||||||
|
|
||||||
function newWord(e) {
|
function submitNewWord(values) {
|
||||||
const formData = new FormData(e.target);
|
const formData = {
|
||||||
|
level_id: values.level,
|
||||||
|
word: values.word,
|
||||||
|
definition: values.definition,
|
||||||
|
};
|
||||||
|
|
||||||
const data = {};
|
try {
|
||||||
for (let field of formData) {
|
axios
|
||||||
const [key, value] = field;
|
.post("words/", formData)
|
||||||
data[key] = value;
|
.then((data) => {
|
||||||
|
words = [snakeToCamelCase(data.data), ...words];
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
$form.definition = "";
|
||||||
|
$form.word = "";
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
}
|
}
|
||||||
console.log(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteWord(word: Word) {
|
||||||
|
if (!(word && word.id)) return;
|
||||||
|
try {
|
||||||
|
axios.delete("/words/" + word.id).then(() => {
|
||||||
|
words = deleteFromArray(words, word);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
fetchData();
|
||||||
|
fetchLevels();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
{#await wordResponse}
|
{#await promise}
|
||||||
<p>…</p>
|
<p>…</p>
|
||||||
{:then}
|
{:then}
|
||||||
<div class="grid grid-cols-3 gap-y-2 gap-x-1">
|
<form on:submit={handleSubmit}>
|
||||||
<div class="font-bold">Live</div>
|
<table class="w-full text-left">
|
||||||
<div class="font-bold">Ger</div>
|
<thead>
|
||||||
<div class="font-bold">Termenadur</div>
|
<tr
|
||||||
|
class="bg-slate-100 rounded-lg font-bold text-slate-700 border-separate border-b"
|
||||||
{#if !isFormNewShown}
|
|
||||||
<div />
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="bg-violet-600 hover:bg-violet-700 rounded-md text-white p-1 w-8 text-center"
|
|
||||||
on:click={toggleFormNew}
|
|
||||||
>
|
>
|
||||||
<span class="fa-regular fa-plus" />
|
<th class="font-bold p-2">Live</th>
|
||||||
</button>
|
<th class="font-bold p-2">Ger</th>
|
||||||
<div />
|
<th class="font-bold p-2">Termenadur</th>
|
||||||
{:else}
|
<th />
|
||||||
<form on:submit|preventDefault={newWord}>
|
</tr>
|
||||||
<div>
|
</thead>
|
||||||
<input
|
|
||||||
name="level"
|
<tbody>
|
||||||
placeholder="Live"
|
{#if !isFormNewShown}
|
||||||
class="p-1 rounded-md border w-1/2"
|
<tr>
|
||||||
|
<td colspan="4" class="text-center p-2 border-b">
|
||||||
|
<ButtonMain onClick={toggleFormNew}>
|
||||||
|
<span
|
||||||
|
class="fa-regular fa-plus align-top"
|
||||||
/>
|
/>
|
||||||
</div>
|
</ButtonMain>
|
||||||
<div>
|
</td>
|
||||||
|
</tr>
|
||||||
|
{:else}
|
||||||
|
<tr class="border-b">
|
||||||
|
<td class="p-2">
|
||||||
|
<select
|
||||||
|
id="level"
|
||||||
|
name="level"
|
||||||
|
on:change={handleChange}
|
||||||
|
bind:value={$form.level}
|
||||||
|
class="p-1 rounded-md border"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
{#await promiseLevels}<option>…</option>
|
||||||
|
{:then}
|
||||||
|
{#each levels as level}
|
||||||
|
<option value={level.levelNumber}
|
||||||
|
>{level.levelString}</option
|
||||||
|
>
|
||||||
|
{/each}
|
||||||
|
{/await}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td class="p-2">
|
||||||
<input
|
<input
|
||||||
name="word"
|
name="word"
|
||||||
placeholder="Ger"
|
placeholder="Ger"
|
||||||
|
on:change={handleChange}
|
||||||
|
bind:value={$form.word}
|
||||||
class="p-1 rounded-md border w-full"
|
class="p-1 rounded-md border w-full"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</td>
|
||||||
<div>
|
<td class="p-2">
|
||||||
<input
|
<input
|
||||||
name="definition"
|
name="definition"
|
||||||
placeholder="Termenadur"
|
placeholder="Termenadur"
|
||||||
|
on:change={handleChange}
|
||||||
|
bind:value={$form.definition}
|
||||||
class="p-1 rounded-md border w-full"
|
class="p-1 rounded-md border w-full"
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</td>
|
||||||
</form>
|
<td class="p-2">
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="bg-violet-600 hover:bg-violet-700 rounded-md text-white p-1 w-6 h-6 justify-center"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="fa-regular fa-plus align-top"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if words}
|
||||||
{#each words as word}
|
{#each words as word}
|
||||||
<WordForm {...word} />
|
<WordForm
|
||||||
|
{...word}
|
||||||
|
on:deleteWord={deleteWord(word)}
|
||||||
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
{/if}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
{:catch error}
|
||||||
|
{error}
|
||||||
{/await}
|
{/await}
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
|
import { vitePreprocess } from '@sveltejs/kit/vite'
|
||||||
import adapter from "@sveltejs/adapter-auto"
|
import adapter from "@sveltejs/adapter-auto"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
"extends": "./.svelte-kit/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
|
@ -15,6 +15,15 @@
|
||||||
"checkJs": true,
|
"checkJs": true,
|
||||||
"isolatedModules": true
|
"isolatedModules": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"],
|
"include": [
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
"src/**/*.d.ts",
|
||||||
|
"src/**/*.ts",
|
||||||
|
"src/**/*.js",
|
||||||
|
"src/**/*.svelte"
|
||||||
|
],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "./tsconfig.node.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
|
@ -10,10 +10,22 @@ class LevelSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class WordSerializer(serializers.ModelSerializer):
|
class WordSerializer(serializers.ModelSerializer):
|
||||||
level = LevelSerializer(many=False, read_only=True)
|
level = LevelSerializer(many=False, read_only=True)
|
||||||
|
level_id = serializers.PrimaryKeyRelatedField(
|
||||||
|
write_only=True, source="level", queryset=Level.objects.all()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Word
|
model = Word
|
||||||
fields = ["id", "word", "definition", "level"]
|
fields = ["id", "word", "definition", "level", "level_id"]
|
||||||
|
|
||||||
|
# def create(self, validated_data):
|
||||||
|
# print(validated_data)
|
||||||
|
# level_data = validated_data.pop("level")
|
||||||
|
# level = Level.objects.get(pk=level_data)
|
||||||
|
|
||||||
|
# word = Word.objects.create(level=level, **validated_data)
|
||||||
|
|
||||||
|
# return word
|
||||||
|
|
||||||
|
|
||||||
class GridSerializer(serializers.ModelSerializer):
|
class GridSerializer(serializers.ModelSerializer):
|
||||||
|
|
Loading…
Reference in a new issue