mirror of https://github.com/doccano/doccano.git
6 changed files with 0 additions and 599 deletions
Split View
Diff Options
-
69frontend/components/containers/documents/DocumentActionMenu.vue
-
50frontend/components/containers/documents/DocumentBulkDeletionButton.vue
-
58frontend/components/containers/documents/DocumentDeletionButton.vue
-
161frontend/components/containers/documents/DocumentList.vue
-
118frontend/components/organisms/documents/DocumentExportForm.vue
-
143frontend/components/organisms/documents/DocumentUploadForm.vue
@ -1,69 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<action-menu |
|||
:items="menuItems" |
|||
:text="$t('dataset.actions')" |
|||
@upload="importDialog=true" |
|||
@download="exportDialog=true" |
|||
/> |
|||
<v-dialog |
|||
v-model="importDialog" |
|||
width="800" |
|||
> |
|||
<document-upload-form |
|||
:upload-document="uploadDocument" |
|||
:formats="getImportFormat" |
|||
@close="importDialog=false" |
|||
/> |
|||
</v-dialog> |
|||
<v-dialog |
|||
v-model="exportDialog" |
|||
width="800" |
|||
> |
|||
<document-export-form |
|||
:export-document="exportDocument" |
|||
:formats="getExportFormat" |
|||
@close="exportDialog=false" |
|||
/> |
|||
</v-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapActions, mapGetters } from 'vuex' |
|||
import ActionMenu from '@/components/molecules/ActionMenu' |
|||
import DocumentUploadForm from '@/components/organisms/documents/DocumentUploadForm' |
|||
import DocumentExportForm from '@/components/organisms/documents/DocumentExportForm' |
|||
|
|||
export default { |
|||
components: { |
|||
ActionMenu, |
|||
DocumentUploadForm, |
|||
DocumentExportForm |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
importDialog: false, |
|||
exportDialog: false, |
|||
menuItems: [ |
|||
{ title: this.$t('dataset.importDataset'), icon: 'mdi-upload', event: 'upload' }, |
|||
{ title: this.$t('dataset.exportDataset'), icon: 'mdi-download', event: 'download' } |
|||
] |
|||
} |
|||
}, |
|||
|
|||
computed: { |
|||
...mapGetters('projects', ['getImportFormat', 'getExportFormat']) |
|||
}, |
|||
|
|||
created() { |
|||
this.setCurrentProject(this.$route.params.id) |
|||
}, |
|||
|
|||
methods: { |
|||
...mapActions('documents', ['uploadDocument', 'exportDocument']), |
|||
...mapActions('projects', ['setCurrentProject']) |
|||
} |
|||
} |
|||
</script> |
@ -1,50 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<v-btn |
|||
:disabled="!total" |
|||
class="text-capitalize" |
|||
color="error" |
|||
@click="dialog=true" |
|||
> |
|||
{{ $t('generic.deleteAll') }} |
|||
</v-btn> |
|||
<v-dialog |
|||
v-model="dialog" |
|||
width="800" |
|||
> |
|||
<confirm-form |
|||
:title="$t('dataset.deleteBulkDocumentsTitle')" |
|||
:message="$t('dataset.deleteBulkDocumentsMessage')" |
|||
:button-true-text="$t('generic.yes')" |
|||
:button-false-text="$t('generic.cancel')" |
|||
@ok="deleteAllDocuments($route.params.id);dialog=false" |
|||
@cancel="dialog=false" |
|||
/> |
|||
</v-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapState, mapActions } from 'vuex' |
|||
import ConfirmForm from '@/components/organisms/utils/ConfirmForm' |
|||
|
|||
export default { |
|||
components: { |
|||
ConfirmForm |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
dialog: false |
|||
} |
|||
}, |
|||
|
|||
computed: { |
|||
...mapState('documents', ['total']) |
|||
}, |
|||
|
|||
methods: { |
|||
...mapActions('documents', ['deleteAllDocuments']) |
|||
} |
|||
} |
|||
</script> |
@ -1,58 +0,0 @@ |
|||
<template> |
|||
<div> |
|||
<v-btn |
|||
:disabled="!isDocumentSelected" |
|||
class="text-capitalize" |
|||
outlined |
|||
@click="dialog=true" |
|||
> |
|||
{{ $t('generic.delete') }} |
|||
</v-btn> |
|||
<v-dialog |
|||
v-model="dialog" |
|||
width="800" |
|||
> |
|||
<confirm-form |
|||
:items="selected" |
|||
:title="$t('dataset.deleteDocumentsTitle')" |
|||
:message="$t('dataset.deleteDocumentsMessage')" |
|||
:button-true-text="$t('generic.yes')" |
|||
:button-false-text="$t('generic.cancel')" |
|||
item-key="text" |
|||
@ok="deleteDocument($route.params.id);dialog=false" |
|||
@cancel="dialog=false" |
|||
/> |
|||
</v-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapState, mapGetters, mapActions } from 'vuex' |
|||
import ConfirmForm from '@/components/organisms/utils/ConfirmForm' |
|||
|
|||
export default { |
|||
components: { |
|||
ConfirmForm |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
dialog: false |
|||
} |
|||
}, |
|||
|
|||
computed: { |
|||
...mapState('documents', ['selected']), |
|||
...mapGetters('documents', ['isDocumentSelected']) |
|||
}, |
|||
|
|||
methods: { |
|||
...mapActions('documents', ['deleteDocument']), |
|||
|
|||
handleDeleteDocument() { |
|||
const projectId = this.$route.params.id |
|||
this.deleteDocument(projectId) |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -1,161 +0,0 @@ |
|||
<template> |
|||
<v-data-table |
|||
:value="selected" |
|||
:headers="headers" |
|||
:items="items" |
|||
:options.sync="options" |
|||
:server-items-length="total" |
|||
:search="search" |
|||
:loading="loading" |
|||
:no-data-text="$t('vuetify.noDataAvailable')" |
|||
:footer-props="{ |
|||
'showFirstLastPage': true, |
|||
'items-per-page-options': [10, 50, 100], |
|||
'items-per-page-text': $t('vuetify.itemsPerPageText') |
|||
}" |
|||
item-key="id" |
|||
:loading-text="$t('generic.loading')" |
|||
show-select |
|||
@input="updateSelected" |
|||
> |
|||
<template v-slot:top> |
|||
<v-text-field |
|||
v-model="search" |
|||
prepend-inner-icon="search" |
|||
:label="$t('generic.search')" |
|||
single-line |
|||
hide-details |
|||
filled |
|||
/> |
|||
</template> |
|||
<template v-slot:item.text="{ item }"> |
|||
<v-edit-dialog> |
|||
<span class="d-flex d-sm-none">{{ item.text | truncate(50) }}</span> |
|||
<span class="d-none d-sm-flex">{{ item.text | truncate(200) }}</span> |
|||
<template v-slot:input> |
|||
<v-textarea |
|||
:value="item.text" |
|||
:label="$t('generic.edit')" |
|||
autofocus |
|||
@change="handleUpdateDocument({ id: item.id, text: $event })" |
|||
/> |
|||
</template> |
|||
</v-edit-dialog> |
|||
</template> |
|||
<template v-slot:item.comment_count="{ item }"> |
|||
<span> {{ item.comment_count }} </span> |
|||
</template> |
|||
<template v-slot:item.action="{ item }"> |
|||
<v-btn |
|||
small |
|||
color="primary text-capitalize" |
|||
@click="toLabeling(item)" |
|||
> |
|||
{{ $t('dataset.annotate') }} |
|||
</v-btn> |
|||
</template> |
|||
</v-data-table> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapState, mapActions, mapMutations, mapGetters } from 'vuex' |
|||
|
|||
export default { |
|||
async fetch() { |
|||
await this.getDocumentList({ |
|||
projectId: this.$route.params.id, |
|||
...this.$route.query |
|||
}) |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
search: this.$route.query.q, |
|||
options: {}, |
|||
headers: [ |
|||
{ |
|||
text: this.$t('dataset.text'), |
|||
align: 'left', |
|||
value: 'text', |
|||
sortable: false |
|||
}, |
|||
{ |
|||
text: this.$t('dataset.metadata'), |
|||
align: 'left', |
|||
value: 'meta', |
|||
sortable: false |
|||
}, |
|||
{ |
|||
text: this.$t('comments.comments'), |
|||
align: 'left', |
|||
value: 'comment_count', |
|||
sortable: true |
|||
}, |
|||
{ |
|||
text: this.$t('dataset.action'), |
|||
align: 'left', |
|||
value: 'action', |
|||
sortable: false |
|||
} |
|||
] |
|||
} |
|||
}, |
|||
|
|||
computed: { |
|||
...mapState('documents', ['items', 'selected', 'loading', 'total']), |
|||
...mapGetters('projects', ['getLink']) |
|||
}, |
|||
|
|||
watch: { |
|||
'$route.query': '$fetch', |
|||
options: { |
|||
handler(newvalue, oldvalue) { |
|||
this.$router.push({ |
|||
query: { |
|||
limit: this.options.itemsPerPage, |
|||
offset: (this.options.page - 1) * this.options.itemsPerPage, |
|||
q: this.search |
|||
} |
|||
}) |
|||
}, |
|||
deep: true |
|||
}, |
|||
search() { |
|||
this.$router.push({ |
|||
query: { |
|||
limit: this.options.itemsPerPage, |
|||
offset: 0, |
|||
q: this.search |
|||
} |
|||
}) |
|||
this.options.page = 1 |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
...mapActions('documents', ['getDocumentList', 'updateDocument']), |
|||
...mapMutations('documents', ['updateSelected']), |
|||
|
|||
handleUpdateDocument(payload) { |
|||
const data = { |
|||
projectId: this.$route.params.id, |
|||
...payload |
|||
} |
|||
this.updateDocument(data) |
|||
}, |
|||
|
|||
toLabeling(doc) { |
|||
const index = this.items.findIndex(item => item.id === doc.id) |
|||
const offset = (this.options.page - 1) * this.options.itemsPerPage |
|||
const page = offset + index + 1 |
|||
this.$router.push({ |
|||
path: this.localePath(`/projects/${this.$route.params.id}/${this.getLink}`), |
|||
query: { |
|||
page, |
|||
q: this.search |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -1,118 +0,0 @@ |
|||
<template> |
|||
<base-card |
|||
:disabled="!valid" |
|||
title="Export Data" |
|||
agree-text="Export" |
|||
cancel-text="Cancel" |
|||
@agree="download" |
|||
@cancel="cancel" |
|||
> |
|||
<template #content> |
|||
<v-form |
|||
ref="form" |
|||
v-model="valid" |
|||
> |
|||
<h2>{{ $t('dataset.importDataMessage1') }}</h2> |
|||
<v-radio-group |
|||
ref="format" |
|||
v-model="selectedFormat" |
|||
:rules="fileFormatRules($t('rules.fileFormatRules'))" |
|||
> |
|||
<v-radio |
|||
v-for="(format, i) in formats" |
|||
:key="i" |
|||
:label="format.text" |
|||
:value="format" |
|||
/> |
|||
</v-radio-group> |
|||
<v-sheet |
|||
v-if="selectedFormat" |
|||
:dark="!$vuetify.theme.dark" |
|||
:light="$vuetify.theme.dark" |
|||
class="mb-5 pa-5" |
|||
> |
|||
<span v-for="(example, index) in selectedFormat.examples" :key="index"> |
|||
{{ example }}<br> |
|||
</span> |
|||
</v-sheet> |
|||
<h2>{{ $t('dataset.exportDataMessage2') }}</h2> |
|||
<v-text-field v-model="selectedFileName" placeholder="Name the file" /> |
|||
<v-checkbox |
|||
v-model="onlyApproved" |
|||
label="Export only approved documents" |
|||
color="success" |
|||
hide-details |
|||
/> |
|||
</v-form> |
|||
</template> |
|||
</base-card> |
|||
</template> |
|||
|
|||
<script> |
|||
import BaseCard from '@/components/molecules/BaseCard' |
|||
import { fileFormatRules, uploadFileRules } from '@/rules/index' |
|||
|
|||
export default { |
|||
components: { |
|||
BaseCard |
|||
}, |
|||
props: { |
|||
exportDocument: { |
|||
type: Function, |
|||
default: () => {}, |
|||
required: true |
|||
}, |
|||
formats: { |
|||
type: Array, |
|||
default: () => [], |
|||
required: true |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
valid: false, |
|||
file: null, |
|||
selectedFormat: null, |
|||
selectedFileName: 'project_' + this.$route.params.id + '_dataset', |
|||
onlyApproved: false, |
|||
fileFormatRules, |
|||
uploadFileRules |
|||
} |
|||
}, |
|||
|
|||
computed: { |
|||
acceptType() { |
|||
if (this.selectedFormat) { |
|||
return this.selectedFormat.accept |
|||
} else { |
|||
return '.txt,.csv,.json,.jsonl' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
cancel() { |
|||
this.$emit('close') |
|||
}, |
|||
validate() { |
|||
return this.$refs.form.validate() |
|||
}, |
|||
reset() { |
|||
this.$refs.format.reset() |
|||
}, |
|||
download() { |
|||
if (this.validate()) { |
|||
this.exportDocument({ |
|||
projectId: this.$route.params.id, |
|||
fileName: this.selectedFileName, |
|||
format: this.selectedFormat.type, |
|||
onlyApproved: this.onlyApproved, |
|||
suffix: this.selectedFormat.suffix |
|||
}) |
|||
this.reset() |
|||
this.cancel() |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -1,143 +0,0 @@ |
|||
<template> |
|||
<base-card |
|||
:disabled="!valid" |
|||
:title="$t('dataset.importDataTitle')" |
|||
:agree-text="$t('generic.upload')" |
|||
:cancel-text="$t('generic.cancel')" |
|||
@agree="create" |
|||
@cancel="cancel" |
|||
> |
|||
<template #content> |
|||
<v-form |
|||
ref="form" |
|||
v-model="valid" |
|||
> |
|||
<v-alert |
|||
v-show="showError" |
|||
v-model="showError" |
|||
type="error" |
|||
dismissible |
|||
> |
|||
{{ $t('errors.fileCannotUpload') + errorMsg }} |
|||
</v-alert> |
|||
<h2>{{ $t('dataset.importDataMessage1') }}</h2> |
|||
<v-radio-group |
|||
v-model="selectedFormat" |
|||
:rules="fileFormatRules($t('rules.fileFormatRules'))" |
|||
> |
|||
<v-radio |
|||
v-for="(format, i) in formats" |
|||
:key="i" |
|||
:label="format.text" |
|||
:value="format" |
|||
/> |
|||
</v-radio-group> |
|||
<v-sheet |
|||
v-if="selectedFormat" |
|||
:dark="!$vuetify.theme.dark" |
|||
:light="$vuetify.theme.dark" |
|||
class="mb-5 pa-5" |
|||
> |
|||
<span v-for="(example, index) in selectedFormat.examples" :key="index"> |
|||
{{ example }}<br> |
|||
</span> |
|||
</v-sheet> |
|||
<h2>{{ $t('dataset.importDataMessage2') }}</h2> |
|||
<v-file-input |
|||
v-model="file" |
|||
multiple |
|||
:accept="acceptType" |
|||
:rules="uploadFileRules($t('rules.uploadFileRules'))" |
|||
:label="$t('labels.filePlaceholder')" |
|||
/> |
|||
</v-form> |
|||
</template> |
|||
</base-card> |
|||
</template> |
|||
|
|||
<script> |
|||
import BaseCard from '@/components/molecules/BaseCard' |
|||
import { fileFormatRules, uploadFileRules } from '@/rules/index' |
|||
|
|||
export default { |
|||
components: { |
|||
BaseCard |
|||
}, |
|||
props: { |
|||
uploadDocument: { |
|||
type: Function, |
|||
default: () => {}, |
|||
required: true |
|||
}, |
|||
formats: { |
|||
type: Array, |
|||
default: () => [], |
|||
required: true |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
valid: false, |
|||
file: null, |
|||
selectedFormat: null, |
|||
fileFormatRules, |
|||
uploadFileRules, |
|||
showError: false, |
|||
errors: [], |
|||
errorMsg: '' |
|||
} |
|||
}, |
|||
|
|||
computed: { |
|||
acceptType() { |
|||
if (this.selectedFormat) { |
|||
return this.selectedFormat.accept |
|||
} else { |
|||
return '.txt,.csv,.json,.jsonl' |
|||
} |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
cancel() { |
|||
this.$emit('close') |
|||
}, |
|||
validate() { |
|||
return this.$refs.form.validate() |
|||
}, |
|||
reset() { |
|||
this.$refs.form.reset() |
|||
}, |
|||
create() { |
|||
if (this.validate()) { |
|||
this.errors = [] |
|||
const promises = [] |
|||
const id = this.$route.params.id |
|||
const type = this.selectedFormat.type |
|||
this.file.forEach((item) => { |
|||
promises.push({ |
|||
projectId: id, |
|||
format: type, |
|||
file: item |
|||
}) |
|||
}) |
|||
let p = Promise.resolve() |
|||
promises.forEach((item) => { |
|||
p = p.then(() => this.uploadDocument(item)).catch(() => { |
|||
this.errors.push(item.file.name) |
|||
this.showError = true |
|||
}) |
|||
}) |
|||
p.finally(() => { |
|||
if (!this.errors.length) { |
|||
this.reset() |
|||
this.cancel() |
|||
} else { |
|||
this.errorMsg = this.errors.join(', ') |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
Write
Preview
Loading…
Cancel
Save