Skip to content

Commit

Permalink
added download/upload button
Browse files Browse the repository at this point in the history
  • Loading branch information
Leo-Nicolle committed Oct 1, 2023
1 parent d0b9cb8 commit d208fdb
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 13 deletions.
130 changes: 130 additions & 0 deletions client/src/components/UploadModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<template>
<n-button @click="showModal = true" round> {{ buttonText }} </n-button>
<n-modal v-model:show="showModal">
<n-card
style="width: 600px"
:title="title"
:bordered="false"
size="huge"
role="dialog"
aria-modal="true"
>
<template #footer>
<input type="file" ref="fileinput" @change="onChange" id="upload" />
<div
id="drop_zone"
@drop.prevent="onDrop"
@dragover="onDragOver"
@click="onDropClick"
@dragstart.prevent.stop
@dragend.prevent.stop
@dragover.prevent.stop
@drop.prevent.stop="onDrop"
@mouseout="onMouseout"
>
<p>{{ $t("buttons.dragdrop") }}</p>
</div>
<n-button v-for="f in filesNames" :key="f" @click="deleteFile(f)" class="file-button" >{{ f }}</n-button>
</template>
<template #action>
<span class="actions">
<n-button @click="onCancel"> {{ $t("buttons.cancel") }} </n-button>
<n-button type="primary" @click="onOK"> {{ $t("buttons.ok") }} </n-button>
</span>
</template>
</n-card>
</n-modal>
</template>

<script lang="ts" setup >
import { computed, defineEmits, defineProps, ref } from "vue";
const files = ref(new Map<string, string>());
const showModal = ref(false);
const fileinput = ref<HTMLInputElement>();
const props = defineProps<{
title: string;
buttonText: string;
}>();
const emit = defineEmits<{
(event: "ok", value: string[]): void;
(event: "cancel"): void;
}>();
const filesNames = computed(() => {
return [...files.value.keys()];
});
function onChange(evt) {
[...evt.target.files].forEach((file) => {
readFile(file);
});
}
function onDropClick() {
fileinput.value.click();
}
function onDragOver(ev) {
ev.target.classList.add("dragging");
}
function onDrop(ev: DragEvent) {
ev.preventDefault();
ev.target.classList.remove("dragging");
const fileList = ev.dataTransfer?.files;
if (!fileList) return;
[...fileList].forEach((item, i) => {
readFile(item);
});
}
function onMouseout(ev){
ev.target.classList.remove("dragging");
}
function deleteFile(filename: string) {
files.value.delete(filename);
}
function readFile(file) {
const fr = new FileReader();
fr.readAsText(file);
fr.onloadend = function () {
files.value.set(file.name, fr.result as string);
};
}
function onOK() {
showModal.value = false;
emit("ok", [...files.value.values()]);
}
function onCancel() {
showModal.value = false;
emit("cancel");
}
</script>

<style>
#drop_zone {
border: 2px dashed #ccc;
border-radius: 20px;
width: 480px;
height: 180px;
padding: 20px;
text-align: center;
font-size: 20px;
cursor: pointer;
}
#drop_zone.dragging {
border-color: #18a058;
}
#upload {
display: none;
}
.actions {
display: flex;
justify-content: space-between;
}
.file-button{
margin-top: 10px;
margin-right: 10px;
}
</style>
11 changes: 10 additions & 1 deletion client/src/components/forms/Words.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,26 @@
</template>

<script setup lang="ts">
import { computed, onMounted, ref, toRaw } from "vue";
import { computed, defineProps, onMounted, ref, toRaw, watch } from "vue";
import { api } from "../../api";
/**
* Component to add and delete words
* Also has a list of all the words
*/
const value = ref<string>("");
const words = ref<string[]>([]);
const props = defineProps<{
version?: number;
}>();
onMounted(() => {
getWords();
});
watch(
() => props.version,
() => {
getWords();
}
);
function getWords() {
api.db.getWords().then((ws) => {
words.value = ws.sort((a, b) => a.localeCompare(b));
Expand Down
6 changes: 6 additions & 0 deletions client/src/i18n/languages/en-en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export const lang = {
print: "Print",
exportsvg: "Export SVG",
support: "Support MotsFlex",
cancel: "Cancel",
ok: "Ok",
download: "Download",
uploadGrids: "Upload grids",
uploadWords: "Upload words",
dragdrop: "Drag files here (or click)"
},
suggestions: {
results: "Results",
Expand Down
7 changes: 6 additions & 1 deletion client/src/i18n/languages/es-es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ export const lang = {
print: "Imprimir",
exportsvg: "Exportar SVG",
support: "Support MotsFlex",

cancel: "Cancelar",
ok: "Ok",
download: "Descargar",
uploadGrids: "Subir cuadrículas",
uploadWords: "Subir palabras",
dragdrop: "Arrastrar ficheros aquí (o hacer clic)",
},
suggestions: {
results: "Resultados",
Expand Down
9 changes: 7 additions & 2 deletions client/src/i18n/languages/fr-fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export const lang = {
buttons: {
changeLanguage: "Traduire",
delete: "Supprimer",
cancel: 'Annuler',
create: "Créer",
yes: "Oui",
no: "Non",
Expand All @@ -22,6 +21,12 @@ export const lang = {
print: "Imprimer",
exportsvg: "Export SVG",
support: "Support MotsFlex",
cancel: "Annuler",
ok: "Ok",
download: "Télécharger",
uploadGrids: "Upload grilles",
uploadWords: "Upload mots",
dragdrop: "Drag & Drop vos fichiers ici (ou clickez)",
},
suggestions: {
results: "Résultats",
Expand Down Expand Up @@ -62,7 +67,7 @@ export const lang = {
pagination: "Pagination",
left: "Gauche",
center: 'Centre',
startIndex: 'Index première page',
startIndex: 'Index première page',
top: "Haut",
right: "Droite",
bottom: "Bas",
Expand Down
10 changes: 7 additions & 3 deletions client/src/layouts/GridLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<n-button @click="deleteVisible = false">{{
$t("buttons.no")
}}</n-button>
<n-button @click="onDelete(selectedElements)" type="warning">{{
<n-button @click="onDel" type="warning">{{
$t("buttons.yes")
}}</n-button>
</template>
Expand Down Expand Up @@ -113,7 +113,7 @@ const props = defineProps<{
/**
* Callback to delete selected elements
*/
onDelete: (selected: any[]) => void;
onDelete: (selected: any[]) => Promise<unknown>;
/**
* Callback when an element is clicked
*/
Expand All @@ -127,7 +127,11 @@ const deleteVisible = ref<boolean>(false);
const emit = defineEmits<{
(event: "select", value: any[]): void;
}>();
function onDel() {
props.onDelete(selectedElements.value).then(() => {
deleteVisible.value = false;
});
}
watchEffect(() => {
selected.value = props.eltList.map(() => false);
});
Expand Down
32 changes: 29 additions & 3 deletions client/src/views/Grids.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
:style="style"
:solutionsStyle="solutionsStyle"
/>
<n-button round @click="download"> {{ $t('buttons.download') }} </n-button>
<UploadModal
:title="$t('buttons.uploadGrids')"
:buttonText="$t('buttons.uploadGrids')"
@ok="onUpload"
/>
</template>
<template #card-title="{ elt }">
<span>
Expand Down Expand Up @@ -48,6 +54,7 @@ import { useRouter } from "vue-router";
import SVGGrid from "../components/svg-renderer/Grid.vue";
import ExportModal from "../components/ExportModal.vue";
import Layout from "../layouts/GridLayout.vue";
import UploadModal from "../components/UploadModal.vue";
import { defaultExportOptions } from "../types";
import { Grid, GridStyle, nullCell, SolutionStyle } from "grid";
import generate from "../js/maze-generator";
Expand Down Expand Up @@ -85,11 +92,30 @@ function fetch() {
}
function onDelete() {
Promise.all(selected.value.map((grid) => api.db.deleteGrid(grid.id))).then(
() => fetch()
);
return Promise.all(
selected.value.map((grid) => api.db.deleteGrid(grid.id))
).then(() => fetch());
}
function download() {
const toDl = selected.value.length ? selected.value : grids.value;
const a = document.createElement("a");
const file = new Blob([JSON.stringify(toDl)], { type: "text/plain" });
a.href = URL.createObjectURL(file);
a.download = "grids.json";
a.click();
}
function onUpload(filesContents: string[]) {
return Promise.all(
filesContents.map((json) => {
return Promise.all(
JSON.parse(json).map((grid) =>
api.db.pushGrid(Grid.unserialize(JSON.stringify(grid)))
)
);
})
).then(() => fetch());
}
function createGrid() {
const newGrid = new Grid(10, 10);
newGrid.title = "Nouvelle Grille";
Expand Down
2 changes: 1 addition & 1 deletion client/src/views/Styles.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function fetch() {
});
}
function onDelete() {
Promise.all(
return Promise.all(
selected.value.map((style, i) => api.db.deleteStyle(style.id))
).then(() => fetch());
}
Expand Down
34 changes: 33 additions & 1 deletion client/src/views/Words.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,46 @@
<template>
<Layout>
<template #body>
<Words />
<Words :version="version" />
</template>
<template v-slot:left-panel>
<n-button round @click="download"> {{ $t('buttons.download') }} </n-button>
<UploadModal
:title="$t('buttons.uploadWords')"
:buttonText="$t('buttons.uploadWords')"
@ok="onUpload"
/>
</template>
</Layout>
</template>

<script setup lang="ts">
import Layout from "../layouts/Main.vue";
import Words from "../components/forms/Words.vue";
import UploadModal from "../components/UploadModal.vue";
import { api } from "../api";
import {ref} from "vue";
const version = ref(0);
function download() {
api.db.getWords().then((words) => {
const a = document.createElement("a");
const file = new Blob([JSON.stringify(words)], { type: "text/plain" });
a.href = URL.createObjectURL(file);
a.download = "words.json";
a.click();
});
}
function onUpload(filesContents: string[]) {
return Promise.all(
filesContents.map((json) => {
return Promise.all(
JSON.parse(json).map((word) => api.db.pushWord(word.trim()))
);
})
)
.then(() => version.value = version.value + 1);
}
</script>

<style scoped>
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
"noEmit": true
},
Expand Down

0 comments on commit d208fdb

Please sign in to comment.