mirror of https://github.com/doccano/doccano.git
7 changed files with 75 additions and 197 deletions
Split View
Diff Options
-
240frontend/components/project/FormUpdate.vue
-
3frontend/components/project/TagList.vue
-
6frontend/domain/models/tag/tagRepository.ts
-
2frontend/pages/projects/create.vue
-
10frontend/repositories/tag/apiTagRepository.ts
-
2frontend/services/application/project/projectApplicationService.ts
-
9frontend/services/application/tag/tagApplicationService.ts
@ -1,222 +1,92 @@ |
|||
<template> |
|||
<v-card> |
|||
<v-card-text v-if="isReady"> |
|||
<v-form ref="form" v-model="valid"> |
|||
<v-card-text v-if="!!project"> |
|||
<v-form ref="form" v-model="valid" :disabled="!isEditing"> |
|||
<v-row> |
|||
<v-col cols="12" sm="6"> |
|||
<h3>Name</h3> |
|||
<project-name-field v-model="project.name" :disabled="!edit.name" single-line /> |
|||
</v-col> |
|||
<v-col cols="12" sm="6"> |
|||
<v-btn |
|||
v-if="!edit.name" |
|||
outlined |
|||
color="grey" |
|||
class="text-capitalize" |
|||
@click="editProject('name')" |
|||
> |
|||
Edit |
|||
</v-btn> |
|||
<v-btn |
|||
v-if="edit.name" |
|||
outlined |
|||
color="primary" |
|||
class="text-capitalize" |
|||
@click="doneEdit()" |
|||
> |
|||
Save |
|||
</v-btn> |
|||
<v-btn |
|||
v-if="edit.name" |
|||
outlined |
|||
color="grey" |
|||
class="text-capitalize" |
|||
@click="cancelEdit()" |
|||
> |
|||
Cancel |
|||
</v-btn> |
|||
</v-col> |
|||
</v-row> |
|||
<v-row> |
|||
<v-col cols="12" sm="6"> |
|||
<h3>Description</h3> |
|||
<project-description-field |
|||
v-model="project.description" |
|||
:disabled="!edit.desc" |
|||
single-line |
|||
/> |
|||
</v-col> |
|||
<v-col cols="12" sm="6"> |
|||
<v-btn |
|||
v-if="!edit.desc" |
|||
outlined |
|||
color="grey" |
|||
class="text-capitalize" |
|||
@click="editProject('desc')" |
|||
> |
|||
Edit |
|||
</v-btn> |
|||
<v-btn |
|||
v-if="edit.desc" |
|||
outlined |
|||
color="primary" |
|||
class="text-capitalize" |
|||
@click="doneEdit()" |
|||
> |
|||
Save |
|||
</v-btn> |
|||
<v-btn |
|||
v-if="edit.desc" |
|||
outlined |
|||
color="grey" |
|||
class="text-capitalize" |
|||
@click="cancelEdit()" |
|||
> |
|||
Cancel |
|||
</v-btn> |
|||
</v-col> |
|||
</v-row> |
|||
<v-row> |
|||
<v-col cols="12" sm="6"> |
|||
<h3>Tags</h3> |
|||
<v-chip |
|||
v-for="tag in tags" |
|||
:key="tag.id" |
|||
close |
|||
outlined |
|||
@click:close="removeTag(tag.id)" |
|||
>{{ tag.text }} |
|||
</v-chip> |
|||
<v-text-field |
|||
v-model="tagInput" |
|||
clearable |
|||
:prepend-icon="mdiPlusCircle" |
|||
@keyup.enter="addTag" |
|||
@click:prepend="addTag" |
|||
> |
|||
</v-text-field> |
|||
</v-col> |
|||
</v-row> |
|||
<v-row> |
|||
<v-col cols="12" sm="6"> |
|||
<h3>Shuffle</h3> |
|||
<v-col cols="12" sm="12" md="6" lg="6" xl="6"> |
|||
<project-name-field v-model="project.name" /> |
|||
<project-description-field v-model="project.description" /> |
|||
<tag-list v-model="tags" /> |
|||
<random-order-field v-model="project.enableRandomOrder" /> |
|||
</v-col> |
|||
</v-row> |
|||
<v-row> |
|||
<v-col cols="12" sm="6"> |
|||
<h3>Collaboration</h3> |
|||
<sharing-mode-field v-model="project.enableSharingMode" /> |
|||
</v-col> |
|||
</v-row> |
|||
</v-form> |
|||
</v-card-text> |
|||
<v-card-actions class="ps-4 pt-0"> |
|||
<v-btn |
|||
v-if="!isEditing" |
|||
color="primary" |
|||
class="text-capitalize" |
|||
@click="isEditing = true" |
|||
v-text="`Edit`" |
|||
/> |
|||
<v-btn |
|||
v-show="isEditing" |
|||
color="primary" |
|||
:disabled="!valid || isUpdating" |
|||
class="mr-4 text-capitalize" |
|||
@click="save" |
|||
v-text="$t('generic.save')" |
|||
/> |
|||
<v-btn |
|||
v-show="isEditing" |
|||
:disabled="isUpdating" |
|||
class="text-capitalize" |
|||
@click="cancel" |
|||
v-text="$t('generic.cancel')" |
|||
/> |
|||
</v-card-actions> |
|||
</v-card> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mdiPlusCircle } from '@mdi/js' |
|||
<script lang="ts"> |
|||
import Vue from 'vue' |
|||
import ProjectDescriptionField from './ProjectDescriptionField.vue' |
|||
import ProjectNameField from './ProjectNameField.vue' |
|||
import RandomOrderField from './RandomOrderField.vue' |
|||
import SharingModeField from './SharingModeField.vue' |
|||
import TagList from './TagList.vue' |
|||
import { Project } from '~/domain/models/project/project' |
|||
|
|||
export default { |
|||
export default Vue.extend({ |
|||
components: { |
|||
ProjectNameField, |
|||
ProjectDescriptionField, |
|||
RandomOrderField, |
|||
SharingModeField |
|||
SharingModeField, |
|||
TagList |
|||
}, |
|||
|
|||
data() { |
|||
return { |
|||
project: {}, |
|||
tags: {}, |
|||
beforeEditCache: {}, |
|||
tagInput: '', |
|||
edit: { |
|||
name: false, |
|||
desc: false |
|||
}, |
|||
project: {} as Project, |
|||
tags: [] as string[], |
|||
valid: false, |
|||
mdiPlusCircle |
|||
isEditing: false, |
|||
isUpdating: false |
|||
} |
|||
}, |
|||
async fetch() { |
|||
this.project = await this.$services.project.findById(this.projectId) |
|||
console.log(this.project) |
|||
this.getTags() |
|||
}, |
|||
|
|||
computed: { |
|||
isReady() { |
|||
return !!this.project |
|||
}, |
|||
projectId() { |
|||
return this.$route.params.id |
|||
} |
|||
}, |
|||
|
|||
watch: { |
|||
'project.enableRandomOrder'() { |
|||
this.doneEdit() |
|||
}, |
|||
'project.enableSharingMode'() { |
|||
this.doneEdit() |
|||
} |
|||
async fetch() { |
|||
const projectId = this.$route.params.id |
|||
this.project = await this.$services.project.findById(projectId) |
|||
this.tags = this.project.tags.map((item: any) => item.text) |
|||
this.isEditing = false |
|||
}, |
|||
|
|||
methods: { |
|||
initEdit() { |
|||
Object.keys(this.edit).forEach((v) => { |
|||
this.edit[v] = false |
|||
}) |
|||
}, |
|||
|
|||
editProject(name) { |
|||
this.cancelEdit() |
|||
this.edit[name] = true |
|||
Object.assign(this.beforeEditCache, this.project) |
|||
}, |
|||
|
|||
cancelEdit() { |
|||
this.initEdit() |
|||
Object.assign(this.project, this.beforeEditCache) |
|||
}, |
|||
|
|||
async doneEdit() { |
|||
if (!this.validate()) { |
|||
this.cancelEdit() |
|||
return |
|||
} |
|||
try { |
|||
await this.$services.project.update(this.projectId, this.project) |
|||
this.beforeEditCache = {} |
|||
this.$fetch() |
|||
} finally { |
|||
this.initEdit() |
|||
} |
|||
}, |
|||
|
|||
validate() { |
|||
return this.$refs.form.validate() |
|||
}, |
|||
|
|||
async getTags() { |
|||
this.tags = await this.$services.tag.list(this.projectId) |
|||
}, |
|||
|
|||
async addTag() { |
|||
await this.$services.tag.create(this.projectId, this.tagInput) |
|||
this.tagInput = '' |
|||
this.getTags() |
|||
cancel() { |
|||
this.$fetch() |
|||
}, |
|||
|
|||
removeTag(id) { |
|||
this.$services.tag.delete(this.projectId, id) |
|||
this.tags = this.tags.filter((tag) => tag.id !== id) |
|||
async save() { |
|||
this.isUpdating = true |
|||
await this.$services.project.update(this.project.id, this.project) |
|||
await this.$services.tag.bulkUpdate(this.project.id, this.tags) |
|||
this.$fetch() |
|||
this.isUpdating = false |
|||
} |
|||
} |
|||
} |
|||
}) |
|||
</script> |
@ -1,9 +1,9 @@ |
|||
import { TagItem } from '~/domain/models/tag/tag' |
|||
|
|||
export interface TagRepository { |
|||
list(projectId: string): Promise<TagItem[]> |
|||
list(projectId: string | number): Promise<TagItem[]> |
|||
|
|||
create(projectId: string, item: string): Promise<TagItem> |
|||
create(projectId: string | number, item: string): Promise<TagItem> |
|||
|
|||
delete(projectId: string, tagId: number): Promise<void> |
|||
delete(projectId: string | number, tagId: number): Promise<void> |
|||
} |
Write
Preview
Loading…
Cancel
Save