|
|
@@ -1,14 +1,190 @@
|
|
|
<template>
|
|
|
- <MainPage/>
|
|
|
+ <div class="card-container">
|
|
|
+ <ConfirmDialog></ConfirmDialog>
|
|
|
+ <ConfirmDialog group="editing">
|
|
|
+ <template #message="prop">
|
|
|
+ <div class="flex flex-column">
|
|
|
+
|
|
|
+ <label for="edit-title">Title</label>
|
|
|
+ <InputText id="edit-title" v-model="prop.message.item[3].title"/>
|
|
|
+
|
|
|
+ <label for="edit-source">Title</label>
|
|
|
+ <InputText id="edit-source" v-model="prop.message.item[3].source"/>
|
|
|
+
|
|
|
+ <label>Paragraph</label>
|
|
|
+ <Textarea v-model="prop.message.item[2]" auto-resize rows="5" style="width: 100%"/>
|
|
|
+
|
|
|
+ <label>ID: <i>{{ prop.message.item[0] }}</i></label>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </template>
|
|
|
+ </ConfirmDialog>
|
|
|
+ <form @submit="onSubmit">
|
|
|
+ <Card>
|
|
|
+ <template #title>IPT Question Search</template>
|
|
|
+ <template #content>
|
|
|
+ <span class="p-float-label">
|
|
|
+ <Textarea v-model="text_area" auto-resize rows="10" style="width: 100%"/>
|
|
|
+ <label>Paragraph</label>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <template #footer>
|
|
|
+ <div class="flex flex-row">
|
|
|
+ <Button :loading="search_loading" class="flex align-items-center justify-content-center m-2" icon="pi pi-search" type="submit" label="Search" />
|
|
|
+ <div class="p-inputgroup flex align-items-center justify-content-center m-2">
|
|
|
+ <span class="p-float-label">
|
|
|
+ <InputText id="source_field" v-model="source" />
|
|
|
+ <label for="source_field">Source</label>
|
|
|
+ </span>
|
|
|
+ <Button :disabled="source.length === 0" icon="pi pi-plus" severity="secondary" label="Add" @click="onAdd"/>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </Card>
|
|
|
+ </form>
|
|
|
+ <Card>
|
|
|
+ <template #title>Results</template>
|
|
|
+ <template #content>
|
|
|
+
|
|
|
+ <DataView :value="results">
|
|
|
+ <template #list="item">
|
|
|
+ <div class="col-12">
|
|
|
+ <div class="flex flex-column">
|
|
|
+ <div class="flex justify-content-between flex-wrap">
|
|
|
+ <div class="flex align-items-center justify-content-center">
|
|
|
+ <Tag :severity="tag_colour(item.data[1])" :value="item.data[1].toFixed(4)" class="mr-2"></Tag>
|
|
|
+ <span>
|
|
|
+ <b>{{ item.data[3].title }}</b>
|
|
|
+ {{ item.data[3].source }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <div class="flex align-items-center justify-content-center">
|
|
|
+ <Button icon="pi pi-file-edit" severity="primary" @click="edit_item(item.data)" text rounded></Button>
|
|
|
+ <Button icon="pi pi-trash" severity="danger" @click="confirm_delete(item.data[0])" text rounded></Button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <p class="flex align-items-center"> {{ item.data[2] }}</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </DataView>
|
|
|
+ </template>
|
|
|
+ </Card>
|
|
|
+ <ProgressSpinner v-show="uploading_db"/>
|
|
|
+ <Accordion :activeIndex="-1" style="width: 100%" class="m-3" v-show="!uploading_db">
|
|
|
+ <AccordionTab header="Options">
|
|
|
+ <div class="flex flex-row">
|
|
|
+ <Button label="Download database" icon="pi pi-download" class="mr-2" @click="download_db"/>
|
|
|
+ <FileUpload mode="basic" name="database" url="/api/v1/database" accept="text/csv"
|
|
|
+ chooseLabel="Upload database" @before-upload="uploading_db = true" @upload="uploading_db = false"/>
|
|
|
+ </div>
|
|
|
+ </AccordionTab>
|
|
|
+ </Accordion>
|
|
|
+</div>
|
|
|
</template>
|
|
|
|
|
|
-<script>
|
|
|
-import MainPage from './components/MainPage.vue'
|
|
|
+<script setup>
|
|
|
+import Card from "primevue/card"
|
|
|
+import Tag from "primevue/tag"
|
|
|
+import Button from "primevue/button"
|
|
|
+import Textarea from "primevue/textarea"
|
|
|
+import InputText from "primevue/inputtext"
|
|
|
+import DataView from 'primevue/dataview';
|
|
|
+import ConfirmDialog from 'primevue/confirmdialog';
|
|
|
+import { useConfirm } from "primevue/useconfirm";
|
|
|
+import AccordionTab from 'primevue/accordiontab';
|
|
|
+import Accordion from 'primevue/accordion';
|
|
|
+import FileUpload from 'primevue/fileupload';
|
|
|
+import ProgressSpinner from 'primevue/progressspinner';
|
|
|
|
|
|
-export default {
|
|
|
- name: 'App',
|
|
|
- components: {
|
|
|
- MainPage
|
|
|
- },
|
|
|
+import { ref, reactive } from "vue";
|
|
|
+
|
|
|
+const text_area = ref("");
|
|
|
+const source = ref("");
|
|
|
+const search_loading = ref(false);
|
|
|
+const results = reactive([]);
|
|
|
+const confirm = useConfirm();
|
|
|
+const uploading_db = ref(false);
|
|
|
+
|
|
|
+
|
|
|
+const confirm_delete = (item_id) => {
|
|
|
+ confirm.require({
|
|
|
+ message: 'Do you want to delete this record?',
|
|
|
+ header: 'Delete Confirmation',
|
|
|
+ icon: 'pi pi-info-circle',
|
|
|
+ acceptClass: 'p-button-danger',
|
|
|
+ accept: async () => {
|
|
|
+ await fetch(`/api/v1/item?id=${item_id}`, { method: "DELETE"} )
|
|
|
+ },
|
|
|
+ });
|
|
|
+};
|
|
|
+const tag_colour = (dist) => {
|
|
|
+ if (dist < 0.30) return 'success';
|
|
|
+ if (dist < 0.35) return 'warning';
|
|
|
+ return 'danger';
|
|
|
}
|
|
|
+
|
|
|
+const download_db = () => {
|
|
|
+ window.open('/api/v1/database');
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const edit_item = (item) => {
|
|
|
+ confirm.require({
|
|
|
+ group: 'editing',
|
|
|
+ item: item,
|
|
|
+ header: `Editing "${item[3].title}"`,
|
|
|
+ acceptClass: 'p-button-primal',
|
|
|
+ acceptLabel: 'Edit',
|
|
|
+ rejectLabel: 'Cancel',
|
|
|
+ accept: async () => {
|
|
|
+ await fetch(`/api/v1/item?id=${item[0]}`, { method: "PUT", headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ }, body: JSON.stringify({document: item[2], metadata: item[3] })} )
|
|
|
+ },
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+async function onSubmit(event) {
|
|
|
+ event.preventDefault()
|
|
|
+ event.stopPropagation()
|
|
|
+ search_loading.value = true
|
|
|
+ results.length = 0
|
|
|
+ const response = await fetch('/api/v1/search', {
|
|
|
+ method: "POST",
|
|
|
+ headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ }, body: JSON.stringify({text: text_area.value })
|
|
|
+ })
|
|
|
+ let data = await response.json()
|
|
|
+ data.forEach(a => results.push(a))
|
|
|
+ search_loading.value = false
|
|
|
+}
|
|
|
+
|
|
|
+async function onAdd() {
|
|
|
+ await fetch('/api/v1/item', {
|
|
|
+ method: "POST",
|
|
|
+ headers: {
|
|
|
+ "Content-Type": "application/json",
|
|
|
+ }, body: JSON.stringify({body: text_area.value, source: source.value})
|
|
|
+ })
|
|
|
+ text_area.value = ''
|
|
|
+}
|
|
|
+
|
|
|
</script>
|
|
|
+
|
|
|
+<style>
|
|
|
+.card-container {
|
|
|
+ display: flex;
|
|
|
+ flex-flow: row wrap;
|
|
|
+ justify-content: center;
|
|
|
+ padding-bottom: 5em;
|
|
|
+}
|
|
|
+.card-container .p-card {
|
|
|
+ width: calc(50vw - 2em);
|
|
|
+ min-width: calc(min(600px, 100vw));
|
|
|
+ margin: 0.5em 0.5em 0.5em 0.5em;
|
|
|
+
|
|
|
+}
|
|
|
+</style>
|