draggable
This commit is contained in:
@ -38,10 +38,11 @@
|
||||
<!-- model isn't paginated and loads in one API call -->
|
||||
<div v-if="!paginated">
|
||||
<generic-horizontal-card v-for="i in items_left" v-bind:key="i.id"
|
||||
:item=i
|
||||
:model="this_model"
|
||||
@item-action="startAction($event, 'left')"/>
|
||||
</div>
|
||||
:item=i
|
||||
:model="this_model"
|
||||
@item-action="startAction($event, 'left')"
|
||||
@finish-action="finishAction"/>
|
||||
</div>
|
||||
<!-- model is paginated and needs managed -->
|
||||
<generic-infinite-cards v-if="paginated"
|
||||
:card_counts="left_counts"
|
||||
@ -53,7 +54,8 @@
|
||||
v-for="i in items_left" v-bind:key="i.id"
|
||||
:item=i
|
||||
:model="this_model"
|
||||
@item-action="startAction($event, 'left')"/>
|
||||
@item-action="startAction($event, 'left')"
|
||||
@finish-action="finishAction"/>
|
||||
</template>
|
||||
</generic-infinite-cards>
|
||||
</div>
|
||||
@ -68,7 +70,8 @@
|
||||
v-for="i in items_right" v-bind:key="i.id"
|
||||
:item=i
|
||||
:model="this_model"
|
||||
@item-action="startAction($event, 'right')"/>
|
||||
@item-action="startAction($event, 'right')"
|
||||
@finish-action="finishAction"/>
|
||||
</template>
|
||||
</generic-infinite-cards>
|
||||
</div>
|
||||
@ -197,6 +200,12 @@ export default {
|
||||
},
|
||||
finishAction: function (e) {
|
||||
let update = undefined
|
||||
switch (e?.action) {
|
||||
case 'save':
|
||||
console.log(e.form_data)
|
||||
this.saveThis(e.form_data)
|
||||
break;
|
||||
}
|
||||
if (e !== 'cancel') {
|
||||
switch (this.this_action) {
|
||||
case this.Actions.DELETE:
|
||||
|
@ -1,14 +1,15 @@
|
||||
<template>
|
||||
<div row style="margin: 4px">
|
||||
<!-- @[useDrag&&`dragover`] <== this syntax completely shuts off draggable -->
|
||||
<b-card no-body d-flex flex-column :class="{'border border-primary' : over, 'shake': isError}"
|
||||
:style="{'cursor:grab' : useDrag}"
|
||||
@dragover.prevent
|
||||
@dragenter.prevent
|
||||
:draggable="useDrag"
|
||||
@dragstart="handleDragStart($event)"
|
||||
@dragenter="handleDragEnter($event)"
|
||||
@dragleave="handleDragLeave($event)"
|
||||
@drop="handleDragDrop($event)">
|
||||
@[useDrag&&`dragover`].prevent
|
||||
@[useDrag&&`dragenter`].prevent
|
||||
@[useDrag&&`dragstart`]="handleDragStart($event)"
|
||||
@[useDrag&&`dragenter`]="handleDragEnter($event)"
|
||||
@[useDrag&&`dragleave`]="handleDragLeave($event)"
|
||||
@[useDrag&&`drop`]="handleDragDrop($event)">
|
||||
<b-row no-gutters >
|
||||
<b-col no-gutters class="col-sm-3">
|
||||
<b-card-img-lazy style="object-fit: cover; height: 6em;" :src="item_image" v-bind:alt="$t('Recipe_Image')"></b-card-img-lazy>
|
||||
@ -23,6 +24,13 @@
|
||||
:item_list="item[x.field]"
|
||||
:label="x.label"
|
||||
:color="x.color"/>
|
||||
<generic-ordered-pill v-for="x in itemOrderedTags" :key="x.field"
|
||||
:item_list="item[x.field]"
|
||||
:label="x.label"
|
||||
:color="x.color"
|
||||
:field="x.field"
|
||||
:item="item"
|
||||
@finish-action="finishAction"/>
|
||||
<div class="mt-auto mb-1" align="right">
|
||||
<span v-if="item[child_count]" class="mx-2 btn btn-link btn-sm"
|
||||
style="z-index: 800;" v-on:click="$emit('item-action',{'action':'get-children','source':item})">
|
||||
@ -90,13 +98,14 @@
|
||||
import GenericContextMenu from "@/components/GenericContextMenu";
|
||||
import Badges from "@/components/Badges";
|
||||
import GenericPill from "@/components/GenericPill";
|
||||
import GenericOrderedPill from "@/components/GenericOrderedPill";
|
||||
import RecipeCard from "@/components/RecipeCard";
|
||||
import { mixin as clickaway } from 'vue-clickaway';
|
||||
import { createPopper } from '@popperjs/core';
|
||||
|
||||
export default {
|
||||
name: "GenericHorizontalCard",
|
||||
components: { GenericContextMenu, RecipeCard, Badges, GenericPill},
|
||||
components: { GenericContextMenu, RecipeCard, Badges, GenericPill, GenericOrderedPill},
|
||||
mixins: [clickaway],
|
||||
props: {
|
||||
item: {type: Object},
|
||||
@ -142,6 +151,9 @@ export default {
|
||||
},
|
||||
itemTags: function() {
|
||||
return this.model?.tags ?? []
|
||||
},
|
||||
itemOrderedTags: function() {
|
||||
return this.model?.ordered_tags ?? []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -206,6 +218,10 @@ export default {
|
||||
closeMenu: function(){
|
||||
this.show_menu = false
|
||||
},
|
||||
finishAction: function(e){
|
||||
this.$emit('finish-action', e)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
72
vue/src/components/GenericOrderedPill.vue
Normal file
72
vue/src/components/GenericOrderedPill.vue
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
<template>
|
||||
<draggable v-if="itemList" v-model="this_list" tag="span" group="ordered_items" z-index="500"
|
||||
@change="orderChanged">
|
||||
<span :key="k.id" v-for="k in itemList" class="pl-1">
|
||||
<b-badge pill :variant="color">{{thisLabel(k)}}</b-badge>
|
||||
</span>
|
||||
</draggable>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
// you can't use this component with a horizontal card that is also draggable
|
||||
import draggable from 'vuedraggable'
|
||||
|
||||
export default {
|
||||
name: 'GenericOrderedPill',
|
||||
components: {draggable},
|
||||
props: {
|
||||
item_list: {required: true, type: Array},
|
||||
label: {type: String, default: 'name'},
|
||||
color: {type: String, default: 'light'},
|
||||
field: {type: String, required: true},
|
||||
item: {type: Object},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
this_list: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
itemList: function() {
|
||||
if(Array.isArray(this.this_list)) {
|
||||
return this.this_list
|
||||
} else if (!this.this_list?.name) {
|
||||
return false
|
||||
} else {
|
||||
return [this.this_list]
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.this_list = this.item_list
|
||||
},
|
||||
watch: {
|
||||
'item_list': function (newVal) {
|
||||
this.this_list = newVal
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
thisLabel: function (item) {
|
||||
let fields = this.label.split('::')
|
||||
let value = item
|
||||
fields.forEach(x => {
|
||||
value = value[x]
|
||||
});
|
||||
return value
|
||||
},
|
||||
orderChanged: function(e){
|
||||
let order = 0
|
||||
this.this_list.forEach(x => {
|
||||
x['order'] = order
|
||||
order++
|
||||
})
|
||||
let new_order = {...this.item}
|
||||
new_order[this.field] = this.this_list
|
||||
this.$emit('finish-action', {'action':'save','form_data': new_order })
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
@ -254,7 +254,7 @@ export class Models {
|
||||
static SUPERMARKET = {
|
||||
'name': i18n.t('Supermarket'),
|
||||
'apiName': 'Supermarket',
|
||||
'tags': [{'field': 'category_to_supermarket', 'label': 'category::name', 'color': 'info'}],
|
||||
'ordered_tags': [{'field': 'category_to_supermarket', 'label': 'category::name', 'color': 'info'}],
|
||||
'create': {
|
||||
'params': [['name', 'description', 'category_to_supermarket']],
|
||||
'form': {
|
||||
|
Reference in New Issue
Block a user