mirror of https://github.com/doccano/doccano.git
6 changed files with 0 additions and 599 deletions
Unified 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