| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- <template>
- <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 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';
- 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>
|