Browse Source

Implement label import/export feature

pull/443/head
Hironsan 5 years ago
parent
commit
d861350377
6 changed files with 222 additions and 45 deletions
  1. 66
      frontend/components/containers/labels/LabelActionMenu.vue
  2. 30
      frontend/components/containers/labels/LabelCreationButton.vue
  3. 39
      frontend/components/containers/labels/LabelDeletionButton.vue
  4. 87
      frontend/components/organisms/labels/LabelImportForm.vue
  5. 10
      frontend/pages/projects/_id/labels/index.vue
  6. 35
      frontend/store/labels.js

66
frontend/components/containers/labels/LabelActionMenu.vue

@ -0,0 +1,66 @@
<template>
<div>
<action-menu
:items="menuItems"
@create="createDialog=true"
@upload="importDialog=true"
@download="handleDownload"
/>
<base-dialog :dialog="createDialog">
<label-creation-form
:create-label="createLabel"
@close="createDialog=false"
/>
</base-dialog>
<base-dialog :dialog="importDialog">
<label-import-form
:import-label="importLabels"
@close="importDialog=false"
/>
</base-dialog>
</div>
</template>
<script>
import { mapActions } from 'vuex'
import ActionMenu from '@/components/molecules/ActionMenu'
import BaseDialog from '@/components/molecules/BaseDialog'
import LabelCreationForm from '@/components/organisms/labels/LabelCreationForm'
import LabelImportForm from '@/components/organisms/labels/LabelImportForm'
export default {
components: {
ActionMenu,
BaseDialog,
LabelCreationForm,
LabelImportForm
},
data() {
return {
createDialog: false,
importDialog: false,
menuItems: [
{ title: 'Create a Label', icon: 'mdi-pencil', event: 'create' },
{ title: 'Import Labels', icon: 'mdi-upload', event: 'upload' },
{ title: 'Export Labels', icon: 'mdi-download', event: 'download' }
]
}
},
created() {
this.setCurrentProject(this.$route.params.id)
},
methods: {
...mapActions('labels', ['createLabel', 'importLabels', 'exportLabels']),
...mapActions('projects', ['setCurrentProject']),
handleDownload() {
this.exportLabels({
projectId: this.$route.params.id
})
}
}
}
</script>

30
frontend/components/containers/labels/LabelCreationButton.vue

@ -1,30 +0,0 @@
<template>
<base-modal
text="Create"
:is-create="true"
>
<template v-slot="slotProps">
<label-creation-form
:create-label="createLabel"
@close="slotProps.close"
/>
</template>
</base-modal>
</template>
<script>
import { mapActions } from 'vuex'
import BaseModal from '@/components/molecules/BaseModal'
import LabelCreationForm from '@/components/organisms/labels/LabelCreationForm'
export default {
components: {
BaseModal,
LabelCreationForm
},
methods: {
...mapActions('labels', ['createLabel'])
}
}
</script>

39
frontend/components/containers/labels/LabelDeletionButton.vue

@ -1,21 +1,40 @@
<template>
<confirm-dialog
title="Delete Label"
message="Are you sure you want to remove these labels from this project?"
item-key="text"
:disabled="!isLabelSelected"
:items="selected"
@ok="handleDeleteLabel()"
/>
<div>
<v-btn
class="text-capitalize"
outlined
:disabled="!isLabelSelected"
@click="dialog=true"
>
Delete
</v-btn>
<base-dialog :dialog="dialog">
<confirm-form
title="Delete Label"
message="Are you sure you want to delete these labels from this project?"
item-key="text"
:items="selected"
@ok="deleteLabel($route.params.id);dialog=false"
/>
</base-dialog>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex'
import ConfirmDialog from '@/components/organisms/utils/ConfirmDialog'
import BaseDialog from '@/components/molecules/BaseDialog'
import ConfirmForm from '@/components/organisms/utils/ConfirmForm'
export default {
components: {
ConfirmDialog
BaseDialog,
ConfirmForm
},
data() {
return {
dialog: false
}
},
computed: {

87
frontend/components/organisms/labels/LabelImportForm.vue

@ -0,0 +1,87 @@
<template>
<base-card
title="Upload Label"
agree-text="Upload"
cancel-text="Cancel"
:disabled="!valid"
@agree="create"
@cancel="cancel"
>
<template #content>
<v-form
ref="form"
v-model="valid"
>
<v-alert
v-show="showError"
v-model="showError"
type="error"
dismissible
>
The file could not be uploaded. Maybe invalid format.
Please check available formats carefully.
</v-alert>
<h2>Select a file</h2>
<v-file-input
v-model="file"
accept=".json"
:rules="uploadFileRules"
label="File input"
/>
</v-form>
</template>
</base-card>
</template>
<script>
import BaseCard from '@/components/molecules/BaseCard'
import { uploadFileRules } from '@/rules/index'
export default {
components: {
BaseCard
},
props: {
importLabel: {
type: Function,
default: () => {},
required: true
}
},
data() {
return {
valid: false,
file: null,
uploadFileRules,
showError: false
}
},
methods: {
cancel() {
this.$emit('close')
},
validate() {
return this.$refs.form.validate()
},
reset() {
this.$refs.form.reset()
},
create() {
if (this.validate()) {
this.importLabel({
projectId: this.$route.params.id,
file: this.file
})
.then((response) => {
this.reset()
this.cancel()
})
.catch(() => {
this.showError = true
})
}
}
}
}
</script>

10
frontend/pages/projects/_id/labels/index.vue

@ -1,8 +1,8 @@
<template>
<v-card>
<v-card-title>
<label-creation-button />
<label-deletion-button />
<v-card-title class="mb-2">
<label-action-menu />
<label-deletion-button class="ms-2" />
</v-card-title>
<label-list />
</v-card>
@ -10,7 +10,7 @@
<script>
import LabelList from '@/components/containers/labels/LabelList'
import LabelCreationButton from '@/components/containers/labels/LabelCreationButton'
import LabelActionMenu from '@/components/containers/labels/LabelActionMenu'
import LabelDeletionButton from '@/components/containers/labels/LabelDeletionButton'
export default {
@ -20,7 +20,7 @@ export default {
components: {
LabelList,
LabelCreationButton,
LabelActionMenu,
LabelDeletionButton
},

35
frontend/store/labels.js

@ -77,5 +77,40 @@ export const actions = {
})
}
commit('resetSelected')
},
importLabels({ commit }, payload) {
commit('setLoading', true)
const formData = new FormData()
formData.append('file', payload.file)
const reader = new FileReader()
reader.onload = (e) => {
const labels = JSON.parse(e.target.result)
for (const label of labels) {
LabelService.addLabel(payload.projectId, label)
.then((response) => {
commit('addLabel', response.data)
})
}
}
reader.readAsText(payload.file)
commit('setLoading', false)
},
exportLabels({ commit }, payload) {
commit('setLoading', true)
LabelService.getLabelList(payload.projectId)
.then((response) => {
const url = window.URL.createObjectURL(new Blob([JSON.stringify(response.data)]))
const link = document.createElement('a')
link.href = url
link.setAttribute('download', `project_${payload.projectId}_labels.json`)
document.body.appendChild(link)
link.click()
})
.catch((error) => {
alert(error)
})
.finally(() => {
commit('setLoading', false)
})
}
}
Loading…
Cancel
Save