stubbed out new shopping list
This commit is contained in:
parent
a140813a67
commit
17cedf17b5
1
cookbook/static/vue/checklist_view.html
Normal file
1
cookbook/static/vue/checklist_view.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Vue App</title><link href="css/chunk-vendors.css" rel="preload" as="style"><link href="js/checklist_view.js" rel="preload" as="script"><link href="js/chunk-vendors.js" rel="preload" as="script"><link href="css/chunk-vendors.css" rel="stylesheet"><link rel="icon" type="image/png" sizes="32x32" href="img/icons/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="img/icons/favicon-16x16.png"><link rel="manifest" href="manifest.json"><meta name="theme-color" content="#4DBA87"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="apple-mobile-web-app-title" content="Recipes"><link rel="apple-touch-icon" href="img/icons/apple-touch-icon-152x152.png"><link rel="mask-icon" href="img/icons/safari-pinned-tab.svg" color="#4DBA87"><meta name="msapplication-TileImage" content="img/icons/msapplication-icon-144x144.png"><meta name="msapplication-TileColor" content="#000000"></head><body><div id="app"></div><script src="js/chunk-vendors.js"></script></body></html>
|
1
cookbook/static/vue/js/checklist_view.js
Normal file
1
cookbook/static/vue/js/checklist_view.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
32
cookbook/templates/generic/checklist_template.html
Normal file
32
cookbook/templates/generic/checklist_template.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load render_bundle from webpack_loader %}
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% comment %} {% load l10n %} {% endcomment %}
|
||||||
|
{% block title %}{{ title }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content_fluid %}
|
||||||
|
|
||||||
|
<div id="app" >
|
||||||
|
<checklist-view></checklist-view>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
{{ config | json_script:"model_config" }}
|
||||||
|
|
||||||
|
{% if debug %}
|
||||||
|
<script src="{% url 'js_reverse' %}"></script>
|
||||||
|
{% else %}
|
||||||
|
<script src="{% static 'django_js_reverse/reverse.js' %}"></script>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
window.IMAGE_PLACEHOLDER = "{% static 'assets/recipe_no_image.svg' %}"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{% render_bundle 'checklist_view' %}
|
||||||
|
{% endblock %}
|
@ -8,7 +8,7 @@
|
|||||||
{% block content_fluid %}
|
{% block content_fluid %}
|
||||||
|
|
||||||
<div id="app" >
|
<div id="app" >
|
||||||
<food-list-view></food-list-view>
|
<model-list-view></model-list-view>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,9 +25,16 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col col-md-9">
|
<span class="col col-md-9">
|
||||||
<h2>{% trans 'Shopping List' %}</h2>
|
<h2>{% trans 'Shopping List' %}</h2>
|
||||||
</div>
|
</span>
|
||||||
|
<span class="col-md-3">
|
||||||
|
<a href="{% url 'view_shopping_new' %}" class="float-right">
|
||||||
|
<button class="btn btn-outline-secondary shadow-none">
|
||||||
|
<i class="fas fa-star"></i> {% trans 'Try the new shopping list' %}
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
<div class="col col-mdd-3 text-right">
|
<div class="col col-mdd-3 text-right">
|
||||||
<b-form-checkbox switch size="lg" v-model="edit_mode"
|
<b-form-checkbox switch size="lg" v-model="edit_mode"
|
||||||
@change="$forceUpdate()">{% trans 'Edit' %}</b-form-checkbox>
|
@change="$forceUpdate()">{% trans 'Edit' %}</b-form-checkbox>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -63,6 +63,7 @@ urlpatterns = [
|
|||||||
path('shopping/', views.shopping_list, name='view_shopping'),
|
path('shopping/', views.shopping_list, name='view_shopping'),
|
||||||
path('shopping/<int:pk>', views.shopping_list, name='view_shopping'),
|
path('shopping/<int:pk>', views.shopping_list, name='view_shopping'),
|
||||||
path('shopping/latest/', views.latest_shopping_list, name='view_shopping_latest'),
|
path('shopping/latest/', views.latest_shopping_list, name='view_shopping_latest'),
|
||||||
|
path('shopping/new/', lists.shopping_list_new, name='view_shopping_new'),
|
||||||
path('settings/', views.user_settings, name='view_settings'),
|
path('settings/', views.user_settings, name='view_settings'),
|
||||||
path('history/', views.history, name='view_history'),
|
path('history/', views.history, name='view_history'),
|
||||||
path('supermarket/', views.supermarket, name='view_supermarket'),
|
path('supermarket/', views.supermarket, name='view_supermarket'),
|
||||||
|
@ -198,3 +198,19 @@ def automation(request):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@group_required('user')
|
||||||
|
def shopping_list_new(request):
|
||||||
|
# recipe-param is the name of the parameters used when filtering recipes by this attribute
|
||||||
|
# model-name is the models.js name of the model, probably ALL-CAPS
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
'generic/checklist_template.html',
|
||||||
|
{
|
||||||
|
"title": _("New Shopping List"),
|
||||||
|
"config": {
|
||||||
|
'model': "SHOPPING_LIST", # *REQUIRED* name of the model in models.js
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
196
vue/src/apps/ChecklistView/ChecklistView.vue
Normal file
196
vue/src/apps/ChecklistView/ChecklistView.vue
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app" style="margin-bottom: 4vh" v-if="this_model">
|
||||||
|
<generic-modal-form v-if="this_model"
|
||||||
|
:model="this_model"
|
||||||
|
:action="this_action"
|
||||||
|
:item1="this_item"
|
||||||
|
:item2="this_target"
|
||||||
|
:show="show_modal"
|
||||||
|
@finish-action="finishAction"/>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-2 d-none d-md-block">
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-8 col-12">
|
||||||
|
<div class="container-fluid d-flex flex-column flex-grow-1">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6" style="margin-top: 1vh">
|
||||||
|
<h3>
|
||||||
|
<!-- <model-menu/> Replace with a List Menu or a Checklist Menu? -->
|
||||||
|
<span>{{ this.this_model.name }}</span>
|
||||||
|
<span><b-button variant="link" @click="startAction({'action':'new'})"><i
|
||||||
|
class="fas fa-plus-circle fa-2x"></i></b-button></span>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-md-12">
|
||||||
|
this is where shopping list items go
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import Vue from 'vue'
|
||||||
|
import {BootstrapVue} from 'bootstrap-vue'
|
||||||
|
|
||||||
|
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||||
|
|
||||||
|
import {ApiMixin} from "@/utils/utils";
|
||||||
|
import {StandardToasts, ToastMixin} from "@/utils/utils";
|
||||||
|
|
||||||
|
import GenericModalForm from "@/components/Modals/GenericModalForm";
|
||||||
|
|
||||||
|
Vue.use(BootstrapVue)
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// TODO ApiGenerator doesn't capture and share error information - would be nice to share error details when available
|
||||||
|
// or i'm capturing it incorrectly
|
||||||
|
name: 'ModelListView',
|
||||||
|
mixins: [ApiMixin, ToastMixin],
|
||||||
|
components: {GenericModalForm},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// this.Models and this.Actions inherited from ApiMixin
|
||||||
|
items: [],
|
||||||
|
this_model: undefined,
|
||||||
|
model_menu: undefined,
|
||||||
|
this_action: undefined,
|
||||||
|
this_item: {},
|
||||||
|
show_modal: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// value is passed from lists.py
|
||||||
|
let model_config = JSON.parse(document.getElementById('model_config').textContent)
|
||||||
|
this.this_model = this.Models[model_config?.model]
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// this.genericAPI inherited from ApiMixin
|
||||||
|
startAction: function (e, param) {
|
||||||
|
let source = e?.source ?? {}
|
||||||
|
this.this_item = source
|
||||||
|
// remove recipe from shopping list
|
||||||
|
// mark on-hand
|
||||||
|
// mark puchased
|
||||||
|
// edit shopping category on food
|
||||||
|
// delete food from shopping list
|
||||||
|
// add food to shopping list
|
||||||
|
// add other to shopping list
|
||||||
|
// edit unit conversion
|
||||||
|
// edit purchaseable unit
|
||||||
|
switch (e.action) {
|
||||||
|
case 'delete':
|
||||||
|
this.this_action = this.Actions.DELETE
|
||||||
|
this.show_modal = true
|
||||||
|
break;
|
||||||
|
case 'new':
|
||||||
|
this.this_action = this.Actions.CREATE
|
||||||
|
this.show_modal = true
|
||||||
|
break;
|
||||||
|
case 'edit':
|
||||||
|
this.this_item = e.source
|
||||||
|
this.this_action = this.Actions.UPDATE
|
||||||
|
this.show_modal = true
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
finishAction: function (e) {
|
||||||
|
let update = undefined
|
||||||
|
switch (e?.action) {
|
||||||
|
case 'save':
|
||||||
|
this.saveThis(e.form_data)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (e !== 'cancel') {
|
||||||
|
switch (this.this_action) {
|
||||||
|
case this.Actions.DELETE:
|
||||||
|
this.deleteThis(this.this_item.id)
|
||||||
|
break;
|
||||||
|
case this.Actions.CREATE:
|
||||||
|
this.saveThis(e.form_data)
|
||||||
|
break;
|
||||||
|
case this.Actions.UPDATE:
|
||||||
|
update = e.form_data
|
||||||
|
update.id = this.this_item.id
|
||||||
|
console.log('form', update)
|
||||||
|
this.saveThis(update)
|
||||||
|
break;
|
||||||
|
case this.Actions.MERGE:
|
||||||
|
this.mergeThis(this.this_item, e.form_data.target, false)
|
||||||
|
break;
|
||||||
|
case this.Actions.MOVE:
|
||||||
|
this.moveThis(this.this_item.id, e.form_data.target.id)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.clearState()
|
||||||
|
},
|
||||||
|
getItems: function (params) {
|
||||||
|
this.genericAPI(this.this_model, this.Actions.LIST, params).then((results) => {
|
||||||
|
if (results?.length) {
|
||||||
|
this.items = results.data
|
||||||
|
} else {
|
||||||
|
console.log('no data returned')
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
StandardToasts.makeStandardToast(StandardToasts.FAIL_FETCH)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getThis: function (id) {
|
||||||
|
return this.genericAPI(this.this_model, this.Actions.FETCH, {'id': id})
|
||||||
|
},
|
||||||
|
saveThis: function (thisItem) {
|
||||||
|
if (!thisItem?.id) { // if there is no item id assume it's a new item
|
||||||
|
this.genericAPI(this.this_model, this.Actions.CREATE, thisItem).then((result) => {
|
||||||
|
// this.items = result.data - refresh the list here
|
||||||
|
StandardToasts.makeStandardToast(StandardToasts.SUCCESS_CREATE)
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
StandardToasts.makeStandardToast(StandardToasts.FAIL_CREATE)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.genericAPI(this.this_model, this.Actions.UPDATE, thisItem).then((result) => {
|
||||||
|
// this.refreshThis(thisItem.id) refresh the list here
|
||||||
|
StandardToasts.makeStandardToast(StandardToasts.SUCCESS_UPDATE)
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err, err.response)
|
||||||
|
StandardToasts.makeStandardToast(StandardToasts.FAIL_UPDATE)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getRecipe: function (item) {
|
||||||
|
// change to get pop up card? maybe same for unit and food?
|
||||||
|
},
|
||||||
|
deleteThis: function (id) {
|
||||||
|
this.genericAPI(this.this_model, this.Actions.DELETE, {'id': id}).then((result) => {
|
||||||
|
StandardToasts.makeStandardToast(StandardToasts.SUCCESS_DELETE)
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
StandardToasts.makeStandardToast(StandardToasts.FAIL_DELETE)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
clearState: function () {
|
||||||
|
this.show_modal = false
|
||||||
|
this.this_action = undefined
|
||||||
|
this.this_item = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
10
vue/src/apps/ChecklistView/main.js
Normal file
10
vue/src/apps/ChecklistView/main.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import App from './ChecklistView'
|
||||||
|
import i18n from '@/i18n'
|
||||||
|
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
i18n,
|
||||||
|
render: h => h(App),
|
||||||
|
}).$mount('#app')
|
@ -158,5 +158,6 @@
|
|||||||
"Key_Ctrl": "Ctrl",
|
"Key_Ctrl": "Ctrl",
|
||||||
"Key_Shift": "Shift",
|
"Key_Shift": "Shift",
|
||||||
"Time": "Time",
|
"Time": "Time",
|
||||||
"Text": "Text"
|
"Text": "Text",
|
||||||
|
"Shopping_list": "Shopping List"
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,10 @@ export class Models {
|
|||||||
},
|
},
|
||||||
'merge': true
|
'merge': true
|
||||||
}
|
}
|
||||||
static SHOPPING_LIST = {}
|
static SHOPPING_LIST = {
|
||||||
|
'name': i18n.t('Shopping_list'),
|
||||||
|
'apiName': 'ShoppingListEntry',
|
||||||
|
}
|
||||||
static RECIPE_BOOK = {
|
static RECIPE_BOOK = {
|
||||||
'name': i18n.t('Recipe_Book'),
|
'name': i18n.t('Recipe_Book'),
|
||||||
'apiName': 'RecipeBook',
|
'apiName': 'RecipeBook',
|
||||||
|
@ -40,7 +40,11 @@ const pages = {
|
|||||||
'meal_plan_view': {
|
'meal_plan_view': {
|
||||||
entry: './src/apps/MealPlanView/main.js',
|
entry: './src/apps/MealPlanView/main.js',
|
||||||
chunks: ['chunk-vendors']
|
chunks: ['chunk-vendors']
|
||||||
}
|
},
|
||||||
|
'checklist_view': {
|
||||||
|
entry: './src/apps/ChecklistView/main.js',
|
||||||
|
chunks: ['chunk-vendors']
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
"name": "../../templates/sw.js",
|
"name": "../../templates/sw.js",
|
||||||
"path": "../../templates/sw.js"
|
"path": "../../templates/sw.js"
|
||||||
},
|
},
|
||||||
|
"js/checklist_view.js": {
|
||||||
|
"name": "js/checklist_view.js",
|
||||||
|
"path": "js/checklist_view.js"
|
||||||
|
},
|
||||||
"js/chunk-2d0da313.js": {
|
"js/chunk-2d0da313.js": {
|
||||||
"name": "js/chunk-2d0da313.js",
|
"name": "js/chunk-2d0da313.js",
|
||||||
"path": "js/chunk-2d0da313.js"
|
"path": "js/chunk-2d0da313.js"
|
||||||
@ -121,6 +125,10 @@
|
|||||||
"name": "meal_plan_view.html",
|
"name": "meal_plan_view.html",
|
||||||
"path": "meal_plan_view.html"
|
"path": "meal_plan_view.html"
|
||||||
},
|
},
|
||||||
|
"checklist_view.html": {
|
||||||
|
"name": "checklist_view.html",
|
||||||
|
"path": "checklist_view.html"
|
||||||
|
},
|
||||||
"manifest.json": {
|
"manifest.json": {
|
||||||
"name": "manifest.json",
|
"name": "manifest.json",
|
||||||
"path": "manifest.json"
|
"path": "manifest.json"
|
||||||
@ -182,6 +190,11 @@
|
|||||||
"js/chunk-vendors.js",
|
"js/chunk-vendors.js",
|
||||||
"css/meal_plan_view.css",
|
"css/meal_plan_view.css",
|
||||||
"js/meal_plan_view.js"
|
"js/meal_plan_view.js"
|
||||||
|
],
|
||||||
|
"checklist_view": [
|
||||||
|
"css/chunk-vendors.css",
|
||||||
|
"js/chunk-vendors.js",
|
||||||
|
"js/checklist_view.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user