Add list duplicate (#172)
Add list duplicate Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/172
This commit is contained in:
parent
2693b49e69
commit
a9e8a3969b
4 changed files with 156 additions and 0 deletions
67
src/components/namespace/namespace-search.vue
Normal file
67
src/components/namespace/namespace-search.vue
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<template>
|
||||||
|
<multiselect
|
||||||
|
v-model="namespace"
|
||||||
|
:options="namespaces"
|
||||||
|
:multiple="false"
|
||||||
|
:searchable="true"
|
||||||
|
:loading="namespaceService.loading"
|
||||||
|
:internal-search="true"
|
||||||
|
@search-change="findNamespaces"
|
||||||
|
@select="select"
|
||||||
|
placeholder="Search for a namespace..."
|
||||||
|
label="title"
|
||||||
|
track-by="id">
|
||||||
|
<template slot="clear" slot-scope="props">
|
||||||
|
<div
|
||||||
|
class="multiselect__clear" v-if="namespace.id !== 0"
|
||||||
|
@mousedown.prevent.stop="clearAll(props.search)"></div>
|
||||||
|
</template>
|
||||||
|
<span slot="noResult">No namespace found. Consider changing the search query.</span>
|
||||||
|
</multiselect>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import multiselect from 'vue-multiselect'
|
||||||
|
|
||||||
|
import NamespaceService from '../../services/namespace'
|
||||||
|
import NamespaceModel from '../../models/namespace'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'namespace-search',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
namespaceService: NamespaceService,
|
||||||
|
namespace: NamespaceModel,
|
||||||
|
namespaces: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
multiselect,
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.namespaceService = new NamespaceService()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
findNamespaces(query) {
|
||||||
|
if (query === '') {
|
||||||
|
this.clearAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.namespaceService.getAll({}, {s: query})
|
||||||
|
.then(response => {
|
||||||
|
this.$set(this, 'namespaces', response)
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.error(e, this)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
clearAll() {
|
||||||
|
this.$set(this, 'namespaces', [])
|
||||||
|
},
|
||||||
|
select(namespace) {
|
||||||
|
this.$emit('selected', namespace)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
17
src/models/listDuplicateModel.js
Normal file
17
src/models/listDuplicateModel.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import AbstractModel from './abstractModel'
|
||||||
|
import ListModel from './list'
|
||||||
|
|
||||||
|
export default class ListDuplicateModel extends AbstractModel {
|
||||||
|
constructor(data) {
|
||||||
|
super(data)
|
||||||
|
this.list = new ListModel(this.list)
|
||||||
|
}
|
||||||
|
|
||||||
|
defaults() {
|
||||||
|
return {
|
||||||
|
listId: 0,
|
||||||
|
namespaceId: 0,
|
||||||
|
list: ListModel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
src/services/listDuplicateService.js
Normal file
20
src/services/listDuplicateService.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import AbstractService from './abstractService'
|
||||||
|
import listDuplicateModel from '../models/listDuplicateModel'
|
||||||
|
|
||||||
|
export default class ListDuplicateService extends AbstractService {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
create: '/lists/{listId}/duplicate',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeCreate(model) {
|
||||||
|
|
||||||
|
model.list = null
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
modelFactory(data) {
|
||||||
|
return new listDuplicateModel(data)
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,6 +98,32 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<header class="card-header">
|
||||||
|
<p class="card-header-title">
|
||||||
|
Duplicate this list
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="content">
|
||||||
|
<p>Select a namespace which should hold the duplicated list:</p>
|
||||||
|
<div class="field is-grouped">
|
||||||
|
<p class="control is-expanded">
|
||||||
|
<namespace-search @selected="selectNamespace"/>
|
||||||
|
</p>
|
||||||
|
<p class="control">
|
||||||
|
<button type="submit" class="button is-success" @click="duplicateList">
|
||||||
|
<span class="icon is-small">
|
||||||
|
<icon icon="plus"/>
|
||||||
|
</span>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<background :list-id="$route.params.id"/>
|
<background :list-id="$route.params.id"/>
|
||||||
|
|
||||||
<component
|
<component
|
||||||
|
@ -137,6 +163,9 @@
|
||||||
import Background from '../../components/list/partials/background-settings'
|
import Background from '../../components/list/partials/background-settings'
|
||||||
import {CURRENT_LIST} from '../../store/mutation-types'
|
import {CURRENT_LIST} from '../../store/mutation-types'
|
||||||
import ColorPicker from '../../components/input/colorPicker'
|
import ColorPicker from '../../components/input/colorPicker'
|
||||||
|
import NamespaceSearch from '../../components/namespace/namespace-search'
|
||||||
|
import ListDuplicateService from '../../services/listDuplicateService'
|
||||||
|
import ListDuplicateModel from '../../models/listDuplicateModel'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'EditList',
|
name: 'EditList',
|
||||||
|
@ -149,9 +178,13 @@
|
||||||
|
|
||||||
manageUsersComponent: '',
|
manageUsersComponent: '',
|
||||||
manageTeamsComponent: '',
|
manageTeamsComponent: '',
|
||||||
|
|
||||||
|
listDuplicateService: ListDuplicateService,
|
||||||
|
selectedNamespace: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
NamespaceSearch,
|
||||||
ColorPicker,
|
ColorPicker,
|
||||||
Background,
|
Background,
|
||||||
Fancycheckbox,
|
Fancycheckbox,
|
||||||
|
@ -160,6 +193,7 @@
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.listService = new ListService()
|
this.listService = new ListService()
|
||||||
|
this.listDuplicateService = new ListDuplicateService()
|
||||||
this.loadList()
|
this.loadList()
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -209,6 +243,24 @@
|
||||||
this.error(e, this)
|
this.error(e, this)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
selectNamespace(namespace) {
|
||||||
|
this.selectedNamespace = namespace
|
||||||
|
},
|
||||||
|
duplicateList() {
|
||||||
|
const listDuplicate = new ListDuplicateModel({
|
||||||
|
listId: this.list.id,
|
||||||
|
namespaceId: this.selectedNamespace.id,
|
||||||
|
})
|
||||||
|
this.listDuplicateService.create(listDuplicate)
|
||||||
|
.then(r => {
|
||||||
|
this.$store.commit('namespaces/addListToNamespace', r.list)
|
||||||
|
this.success({message: 'The list was successfully duplicated.'}, this)
|
||||||
|
router.push({name: 'list.index', params: {listId: r.list.id}})
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
this.error(e, this)
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue