Sortable list.
This commit is contained in:
parent
f99deb2631
commit
a62285ee06
13
package-lock.json
generated
13
package-lock.json
generated
@ -13256,6 +13256,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"sortablejs": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz",
|
||||
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
|
||||
},
|
||||
"source-list-map": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
|
||||
@ -14719,6 +14724,14 @@
|
||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||
"dev": true
|
||||
},
|
||||
"vuedraggable": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz",
|
||||
"integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
|
||||
"requires": {
|
||||
"sortablejs": "1.14.0"
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||
|
@ -12,7 +12,8 @@
|
||||
"core-js": "^3.6.5",
|
||||
"vue": "^3.0.0",
|
||||
"vue-class-component": "^8.0.0-0",
|
||||
"vue-router": "^4.0.0-0"
|
||||
"vue-router": "^4.0.0-0",
|
||||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^4.18.0",
|
||||
|
48
src/components/ListItem.vue
Normal file
48
src/components/ListItem.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="panel-block" v-bind:class="{'disabled': element.loading}">
|
||||
<span class="icon is-pulled-left" v-if="canMove">
|
||||
<ion-icon name="move-outline"></ion-icon>
|
||||
</span>
|
||||
|
||||
<input type="checkbox" v-model="element.checked" v-on:change="updateItem(element)">
|
||||
<div class="field is-horizontal has-addons">
|
||||
<div class="control">
|
||||
<input class="input" type="text" v-bind:disabled="element.checked" v-model="element.content"
|
||||
v-on:blur="updateItem(element)">
|
||||
</div>
|
||||
<div class="control" v-if="!element.checked">
|
||||
<a class="button is-primary" v-on:click="updateItem(element)">
|
||||
Save
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ListItem",
|
||||
props: ['item', 'canMove'],
|
||||
data: function () {
|
||||
return {
|
||||
element: this.item
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateItem: function () {
|
||||
this.$emit('updateItem', this.element)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.panel-block.disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.field, .field .control:first-child {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="block">
|
||||
<ItemCreateModal v-if="addModalShown" v-bind:add-modal-shown="addModalShown" v-bind:list-id="listId"
|
||||
v-on:newItem="addItem" v-on:toggleModalItem="toggleModal"></ItemCreateModal>
|
||||
<div class="panel is-info" v-if="!loading">
|
||||
@ -27,28 +27,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-block" v-for="item in items" :key="item.id" v-bind:class="{'disabled': item.loading}">
|
||||
<input type="checkbox" v-model="item.checked" v-on:change="updateItem(item)">
|
||||
<div class="field is-horizontal has-addons">
|
||||
<div class="control">
|
||||
<input class="input" type="text" v-bind:disabled="item.checked" v-model="item.content" v-on:blur="updateItem(item)">
|
||||
</div>
|
||||
<div class="control" v-if="!item.checked">
|
||||
<a class="button is-primary" v-on:click="updateItem(item)">
|
||||
Save
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<draggable
|
||||
v-model="items"
|
||||
group="people"
|
||||
@change="onChange"
|
||||
item-key="id" v-if="searchQ.length <= 0">
|
||||
<template #item="{element}">
|
||||
<ListItem v-bind:item="element" v-bind:can-move="true" v-on:updateItem="updateItem"></ListItem>
|
||||
</template>
|
||||
</draggable>
|
||||
<div v-if="searchQ.length > 0">
|
||||
<ListItem v-for="element in items" v-bind:can-move="false" :key="element.id" v-bind:item="element" v-on:updateItem="updateItem"></ListItem>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ItemCreateModal from "@/components/ItemCreateModal";
|
||||
import draggable from 'vuedraggable'
|
||||
import ListItem from "@/components/ListItem";
|
||||
|
||||
export default {
|
||||
name: "List",
|
||||
components: {ItemCreateModal},
|
||||
components: {ListItem, ItemCreateModal, draggable},
|
||||
data: function () {
|
||||
return {
|
||||
listId: this.$route.params.id,
|
||||
@ -57,12 +60,15 @@ export default {
|
||||
items: [],
|
||||
initialItems: [],
|
||||
loading: true,
|
||||
addModalShown: false
|
||||
addModalShown: false,
|
||||
drag: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchListAndItems: function () {
|
||||
this.loading = true;
|
||||
fetchListAndItems: function (ignoreLoading) {
|
||||
if (!ignoreLoading) {
|
||||
this.loading = true;
|
||||
}
|
||||
fetch('http://localhost:7000/api/lists/' + this.listId + '/items', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
@ -79,7 +85,7 @@ export default {
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
updateItem: function (item) {
|
||||
updateItem: function (item, reloadAll) {
|
||||
item.loading = true;
|
||||
const itemCopy = Object.assign({}, item);
|
||||
delete itemCopy.loading;
|
||||
@ -91,6 +97,9 @@ export default {
|
||||
},
|
||||
body: JSON.stringify(itemCopy)
|
||||
}).finally(() => {
|
||||
if (reloadAll) {
|
||||
this.fetchListAndItems(true);
|
||||
}
|
||||
item.loading = false;
|
||||
})
|
||||
},
|
||||
@ -111,6 +120,14 @@ export default {
|
||||
addItem: function (item) {
|
||||
this.initialItems.push(item);
|
||||
this.recopyItemsObject();
|
||||
},
|
||||
onChange: function (event) {
|
||||
if (event.moved) {
|
||||
console.log(event.moved.newIndex)
|
||||
const i = this.initialItems.find(i => i.id === event.moved.element.id)
|
||||
i.position = event.moved.newIndex
|
||||
this.updateItem(i, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
@ -120,9 +137,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.panel-block.disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.field, .field .control:first-child {
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="block">
|
||||
<ListCreateUpdateModal v-if="addModalShown" v-bind:add-modal-shown="addModalShown" v-on:newList="addListItem"
|
||||
v-on:updatedItem="updateListItem"
|
||||
v-on:toggleModal="toggleModal" v-bind:item="selectedItem"></ListCreateUpdateModal>
|
||||
|
Loading…
Reference in New Issue
Block a user