mirror of
https://gitlab.com/bmcgonag/get_my.git
synced 2026-03-27 00:08:49 +00:00
Merge branch 'dev' into 'main'
Merge to add Menu Item to List Item linking See merge request bmcgonag/get_my!1
This commit is contained in:
commit
bc04c509a5
18 changed files with 453 additions and 14 deletions
46
README.md
46
README.md
|
|
@ -5,6 +5,52 @@ Open source shopping / list app.
|
||||||
If you were using this previously, the new updates change the data structure. Please remove your old database if you find odd behavior or errors. The data structures may simply be incompatible.
|
If you were using this previously, the new updates change the data structure. Please remove your old database if you find odd behavior or errors. The data structures may simply be incompatible.
|
||||||
I apologize for any inconvenince as I simplify the app a bit.
|
I apologize for any inconvenince as I simplify the app a bit.
|
||||||
|
|
||||||
|
## Install and Run
|
||||||
|
NOTE: if you have a cpu without the AVX instruction set, you can change the line 'image: mongo' to be 'image: mongo:4.4'in the docker compose below.
|
||||||
|
|
||||||
|
### Docker / Docker Compose
|
||||||
|
You can use this docker compose file to get the system up and running.
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
services:
|
||||||
|
get_my:
|
||||||
|
container_name: get_my
|
||||||
|
image: bmcgonag/get_my:latest
|
||||||
|
ports:
|
||||||
|
- "80:3000" # you can change the left side to a less common port number if needed
|
||||||
|
healthcheck:
|
||||||
|
test: curl --fail -s http://localhost:3000/ || exit 1
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
links:
|
||||||
|
- mongo
|
||||||
|
depends_on:
|
||||||
|
- mongo
|
||||||
|
restart: unless-stopped
|
||||||
|
mongo:
|
||||||
|
container_name: get_my-mongo
|
||||||
|
image: mongo
|
||||||
|
volumes:
|
||||||
|
- ./data:/data/db # this will store the application data in the same directory where you have the docker-compose.yml file.
|
||||||
|
restart: unless-stopped
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Host using NodeJS
|
||||||
|
1. You need to have a mongo database instance installed and ready to use. You also need to know the port it uses, as well as create a database in mongo for the 'Get My' application. I recommend naming the database 'get-my'.
|
||||||
|
2. You need to have NodeJS installed (the hard part is that this application is build in MeteorJS, and currently uses a node version of 14.21.4 - which you'll find isn't available for download from node themselves anymore). You need 14.21.4 and can get a tar.gz file of it here: https://guide.meteor.com/using-node-v14.21.4
|
||||||
|
3. Once setup. you need to set some environment variables
|
||||||
|
- `ROOT_URL=`(whatever you want your node application to accessed at, e.g. `http://localhost`, etc)
|
||||||
|
- `MONGO_URL=`(ip and port for your mongodb in this format `mongodb://localhost:27017/get-my`) This is the url for the application to reach the mongo database, and does not have to exist on the same machine, but must be reachable by IP or hostname, and port. The 'get-my' in this url is the database name you setup.
|
||||||
|
- `PORT=3000`
|
||||||
|
- `MAIL_URL=` not a working feature yet, but if you want smtp email to work you'd need to set this to be something like `smtp://USERNAME:PASSWORD@HOST:PORT`
|
||||||
|
4. Download the source bundle (I'll add a url to release bundle soon)
|
||||||
|
5. unzip the source bundle
|
||||||
|
5. Move into the bundle/program/server folder, and run `npm install`. This should install all needed dependancies.
|
||||||
|
6. move back to the bundle folder, and run `node main.js`. This will start the application running.
|
||||||
|
7. There are multiple node applications to help keep a node js app running in the background, like PM2, etc...but I'll leave that up to you to get going.
|
||||||
|
|
||||||
## Keeping it Simple
|
## Keeping it Simple
|
||||||
- Registration / Login System built in
|
- Registration / Login System built in
|
||||||
- 1st user to register is the system admin by default.
|
- 1st user to register is the system admin by default.
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ Template.taskForm.onRendered(function() {
|
||||||
secondaryPlaceholder: '+Task Name',
|
secondaryPlaceholder: '+Task Name',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
instances = M.FormSelect.init(elems, {});
|
||||||
|
}, 350);
|
||||||
|
|
||||||
Session.set("taskNameErr", false);
|
Session.set("taskNameErr", false);
|
||||||
Session.set("taskUserErr", false);
|
Session.set("taskUserErr", false);
|
||||||
Session.set("taskDateErr", false);
|
Session.set("taskDateErr", false);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
{{itemName}}
|
{{itemName}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</span>
|
</span>
|
||||||
<i class="material-icons clickable deleteListItem right">delete</i>
|
<i class="material-icons clickable deleteListItem right modal-trigger" href="#modalDelete">delete</i>
|
||||||
<i class="material-icons clickable markListItemReceived right">check</i>
|
<i class="material-icons clickable markListItemReceived right">check</i>
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { ListItems } from '../../imports/api/listItems.js';
|
import { ListItems } from '../../imports/api/listItems.js';
|
||||||
|
import { M } from '../lib/assets/materialize.js';
|
||||||
|
|
||||||
Template.listItemsTbl.onCreated(function() {
|
Template.listItemsTbl.onCreated(function() {
|
||||||
this.autorun( () => {
|
this.autorun( () => {
|
||||||
|
|
@ -7,8 +8,9 @@ Template.listItemsTbl.onCreated(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.listItemsTbl.onRendered(function() {
|
Template.listItemsTbl.onRendered(function() {
|
||||||
// new modal init here
|
var elems = document.querySelectorAll('.modal');
|
||||||
// $('.modal').modal();
|
var instances = M.Modal.init(elems, {});
|
||||||
|
|
||||||
Session.set("showReceivedItems", false);
|
Session.set("showReceivedItems", false);
|
||||||
Session.set("searchVal", "");
|
Session.set("searchVal", "");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
47
client/MenuItems/addProdToListModal.html
Normal file
47
client/MenuItems/addProdToListModal.html
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<template name="addProdToListModal">
|
||||||
|
<div class="modal" id="addProdToList">
|
||||||
|
<div class="modal-content">
|
||||||
|
<h2>Add Items to List</h2>
|
||||||
|
<form class="row" style="gap: 1em;">
|
||||||
|
<div class="col s12 input-field outlined" id="chooseListDiv">
|
||||||
|
<select name="chooseList" id="chooseList">
|
||||||
|
{{#each setOfLists}}
|
||||||
|
<option value="{{_id}}">{{listName}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col s12">
|
||||||
|
<ul class="collection with-header">
|
||||||
|
<li class="collection-header">
|
||||||
|
<h4>Products to Add</h4>
|
||||||
|
</li>
|
||||||
|
{{#each productToChoose}}
|
||||||
|
<li class="collection-item" id="{{prodId}}">
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" class="productListing" id="{{prodId}}" />
|
||||||
|
<span class="my-text">{{prodName}}</span>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s12 m6 l6">
|
||||||
|
<a class="left btn waves-effect waves-light orange white-text modal-close">Cancel</a>
|
||||||
|
</div>
|
||||||
|
<div class="col s12 m6 l6">
|
||||||
|
<a class="btn waves-effect waves-light green white-text saveProdsToList" id="saveProdsToList">Save to List</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{> snackbar}}
|
||||||
|
</template>
|
||||||
64
client/MenuItems/addProdToListModal.js
Normal file
64
client/MenuItems/addProdToListModal.js
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { M } from '../lib/assets/materialize.js';
|
||||||
|
import { MenuProdLinks } from '../../imports/api/menuProdLinks';
|
||||||
|
import { Products } from '../../imports/api/products.js';
|
||||||
|
import { Lists } from '../../imports/api/lists.js';
|
||||||
|
import { ListItems } from '../../imports/api/listItems';
|
||||||
|
|
||||||
|
Template.addProdToListModal.onCreated(function() {
|
||||||
|
this.subscribe("myProducts");
|
||||||
|
this.subscribe("myLists");
|
||||||
|
this.subscribe("myListItems");
|
||||||
|
this.subscribe("menuProdLinkData");
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.addProdToListModal.onRendered(function() {
|
||||||
|
var elems = document.querySelectorAll('select');
|
||||||
|
var instances = M.FormSelect.init(elems, {});
|
||||||
|
|
||||||
|
Session.set("itemsSelected", []);
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.addProdToListModal.helpers({
|
||||||
|
assocProds: function() {
|
||||||
|
let menuItemId = Session.get("menuItemId");
|
||||||
|
let assocProds = MenuProdLinks.find({ menuItemId: menuItemId });
|
||||||
|
if (typeof assocProds != 'undefined' && assocProds != '' && assocProds != null) {
|
||||||
|
return assocProds;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setOfLists: function() {
|
||||||
|
return Lists.find({});
|
||||||
|
},
|
||||||
|
productToChoose: function() {
|
||||||
|
let prodLinkLIst = MenuProdLinks.find({ menuId: Session.get("menuItemId")});
|
||||||
|
if (typeof prodLinkLIst != 'undefined' && prodLinkLIst != "" && prodLinkLIst != null) {
|
||||||
|
return prodLinkLIst;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.addProdToListModal.events({
|
||||||
|
'click .productListing' (event) {
|
||||||
|
let itemId = event.currentTarget.id;
|
||||||
|
let selected = Session.get("itemsSelected");
|
||||||
|
console.log("Item clicked: " + itemId);
|
||||||
|
selected.push(itemId);
|
||||||
|
console.dir(selected);
|
||||||
|
Session.set("itemsSelected", selected);
|
||||||
|
},
|
||||||
|
'click #saveProdsToList' (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
let selectedItems = Session.get("itemsSelected");
|
||||||
|
let listId = $("#chooseList").val();
|
||||||
|
// console.log(" calling meteor method with items: ");
|
||||||
|
// console.dir(selectedItems);
|
||||||
|
// console.log(" and list id: "+ listId);
|
||||||
|
Meteor.call('add.itemsFromMenuItem', selectedItems, listId, function(err, result) {
|
||||||
|
if (err) {
|
||||||
|
console.log(" ERROR adding menu components to list: " + err);
|
||||||
|
} else {
|
||||||
|
showSnackbar("Items Added to List!", "green");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -5,7 +5,7 @@ import { M } from '../lib/assets/materialize.js';
|
||||||
|
|
||||||
Template.menuItemsForm.onCreated(function() {
|
Template.menuItemsForm.onCreated(function() {
|
||||||
this.subscribe("myMenus");
|
this.subscribe("myMenus");
|
||||||
this.subscribe("myMenuItems", Session.get("menuId"));
|
this.subscribe("allMenuItems", Session.get("menuId"));
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.menuItemsForm.onRendered(function() {
|
Template.menuItemsForm.onRendered(function() {
|
||||||
|
|
@ -13,6 +13,15 @@ Template.menuItemsForm.onRendered(function() {
|
||||||
var instances = M.Datepicker.init(elems, {});
|
var instances = M.Datepicker.init(elems, {});
|
||||||
|
|
||||||
Session.set("menuItemErr", false);
|
Session.set("menuItemErr", false);
|
||||||
|
Session.set("menuListItems", {});
|
||||||
|
|
||||||
|
this.autorun(() => {
|
||||||
|
var elema = document.querySelectorAll('.autocomplete');
|
||||||
|
var instancea = M.Autocomplete.init(elema, {
|
||||||
|
minlength: 0,
|
||||||
|
data: Session.get("menuListItems"),
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.menuItemsForm.helpers({
|
Template.menuItemsForm.helpers({
|
||||||
|
|
@ -65,5 +74,20 @@ Template.menuItemsForm.events({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
'keyup #menuItemInp' (event) {
|
||||||
|
if (event.which != 13) {
|
||||||
|
let findMenuItem = $("#menuItemInp").val();
|
||||||
|
let menuItemInfo = MenuItems.find({ itemName: {$regex: findMenuItem + '.*', $options: 'i' }}).fetch();
|
||||||
|
if (typeof menuItemInfo != 'undefined' && menuItemInfo != '' && menuItemInfo != null) {
|
||||||
|
getMenuItemList(menuItemInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
getMenuItemList = function(menuItemInfo) {
|
||||||
|
let menuItemObjArray = [];
|
||||||
|
menuItemObjArray = menuItemInfo.map(info => ({ id: info._id, text: info.itemName }));
|
||||||
|
Session.set("menuListItems", menuItemObjArray);
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,16 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<table>
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Menu Item</th>
|
||||||
|
<th>Date to Serve</th>
|
||||||
|
<th>Has Product Links</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
{{#each thisMenuItems}}
|
{{#each thisMenuItems}}
|
||||||
<tr class="clickable">
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span>
|
<span>
|
||||||
{{#if $eq itemMade true}}
|
{{#if $eq itemMade true}}
|
||||||
|
|
@ -17,12 +25,20 @@
|
||||||
{{serveDate}}
|
{{serveDate}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<i class="material-icons clickable deleteMenuItem right modal-trigger" data-target="modalDelete">delete</i>
|
{{#if $eq isLinked true}}<a class="waves-effect waves-light blue darken-3 white-text btn addProdsToList modal-trigger" href="#addProdToList">+ Shopping List</a>{{/if}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<i class="material-icons tooltipped modal-trigger deleteMenuItem clickable" href="#modalDelete" data-position="top" data-tooltip-id="deleteMenuTip">delete</i>
|
||||||
|
<i class="material-icons tooltipped modal-trigger linkToProducts clickable" href="#modalLinkProducts" data-position="top" data-tooltip-id="linkMenuTip">link</i>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</table>
|
</table>
|
||||||
|
<div class="tooltip-content" style="display: none;" id="deleteMenuTip">Delete this menu item</div>
|
||||||
|
<div class="tooltip-content" style="display: none;" id="linkMenuTip">Link Products that make up this menu item</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{> deleteConfirmationModal}}
|
{{> deleteConfirmationModal}}
|
||||||
|
{{> modalLinkProducts}}
|
||||||
|
{{> addProdToListModal}}
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -10,11 +10,19 @@ Template.menuItemsTbl.onCreated(function() {
|
||||||
Template.menuItemsTbl.onRendered(function() {
|
Template.menuItemsTbl.onRendered(function() {
|
||||||
var elems = document.querySelectorAll('.modal');
|
var elems = document.querySelectorAll('.modal');
|
||||||
var instances = M.Modal.init(elems, {});
|
var instances = M.Modal.init(elems, {});
|
||||||
|
|
||||||
|
var elemt = document.querySelectorAll('.tooltipped');
|
||||||
|
var instancet = M.Tooltip.init(elemt, {});
|
||||||
|
|
||||||
|
Meteor.setTimeout(function() {
|
||||||
|
var instances = M.Modal.init(elems, {});
|
||||||
|
var instancet = M.Tooltip.init(elemt, {});
|
||||||
|
}, 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.menuItemsTbl.helpers({
|
Template.menuItemsTbl.helpers({
|
||||||
thisMenuItems: function() {
|
thisMenuItems: function() {
|
||||||
return MenuItems.find({}, { sort: { serveDateActual: 1 }});
|
return MenuItems.find({ menuId: Session.get("menuId") }, { sort: { serveDateActual: 1 }});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -26,4 +34,12 @@ Template.menuItemsTbl.events({
|
||||||
Session.set("item", this.itemName);
|
Session.set("item", this.itemName);
|
||||||
Session.set("view", "Menu Items");
|
Session.set("view", "Menu Items");
|
||||||
},
|
},
|
||||||
|
'click .linkToProducts' (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
Session.set("menuItemId", this._id);
|
||||||
|
},
|
||||||
|
'click .addProdsToList' (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
Session.set("menuItemId", this._id);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -2,8 +2,11 @@
|
||||||
<h5>{{menuName}}</h5>
|
<h5>{{menuName}}</h5>
|
||||||
<form class="menuItemFrm row" style="gap: 1em;" id="menuItemFrm">
|
<form class="menuItemFrm row" style="gap: 1em;" id="menuItemFrm">
|
||||||
<div class="col s12 m6 l9 input-field outlined">
|
<div class="col s12 m6 l9 input-field outlined">
|
||||||
<input type="text" class="menuItemInp" style="{{#if $eq menuItemErr true}}border: 2px solid red{{/if}}" id="menuItemInp" />
|
<input type="text" class="autocomplete" id="menuItemInp" autocomplete="off" />
|
||||||
<label for="menuItemInp">Add Menu Item</label>
|
<label for="menuItemInp">Item</label>
|
||||||
|
|
||||||
|
<!-- <input type="text" class="menuItemInp" style="{{#if $eq menuItemErr true}}border: 2px solid red{{/if}}" id="menuItemInp" />
|
||||||
|
<label for="menuItemInp">Add Menu Item</label> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="col s12 m6 l3 input-field outlined">
|
<div class="col s12 m6 l3 input-field outlined">
|
||||||
<input type="text" class="datepicker" id="dateServed" />
|
<input type="text" class="datepicker" id="dateServed" />
|
||||||
|
|
|
||||||
29
client/MenuItems/modalLinkProducts.html
Normal file
29
client/MenuItems/modalLinkProducts.html
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template name="modalLinkProducts">
|
||||||
|
<div id="modalLinkProducts" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<p class="flow-text">Choose Product Items below that are used to make this menu item.</p>
|
||||||
|
<div class="col s12 input-field outlined" id="prouctsForMenudiv">
|
||||||
|
<select name="" id="prodForMenu" class="prodForMenu" multiple>
|
||||||
|
<option value="" disabled>Choose...</option>
|
||||||
|
{{#each products}}
|
||||||
|
<option value="{{prodName}}">{{prodName}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s6">
|
||||||
|
<a id="cancelLInk" class="btn waves-effect wave-light orange white-text left modal-close">Cancel</a>
|
||||||
|
</div>
|
||||||
|
<div class="col s6">
|
||||||
|
<a id="saveLink" class="btn waves-effect waves-light green white-text right modal-close">Save</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{> snackbar}}
|
||||||
|
</template>
|
||||||
57
client/MenuItems/modalLinkProducts.js
Normal file
57
client/MenuItems/modalLinkProducts.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { M } from '../lib/assets/materialize.js';
|
||||||
|
import { Products } from '../../imports/api/products.js';
|
||||||
|
import { MenuItems } from '../../imports/api/menuItems';
|
||||||
|
import { MenuProdLinks } from '../../imports/api/menuProdLinks.js';
|
||||||
|
|
||||||
|
Template.modalLinkProducts.onCreated(function() {
|
||||||
|
this.subscribe("myMenuItems");
|
||||||
|
this.subscribe("myProducts");
|
||||||
|
this.subscribe("menuProdLinkData");
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.modalLinkProducts.onRendered(function() {
|
||||||
|
var elems = document.querySelectorAll('.modal');
|
||||||
|
var instances = M.Modal.init(elems, {});
|
||||||
|
|
||||||
|
var elemse = document.querySelectorAll('select');
|
||||||
|
var instancese = M.FormSelect.init(elemse, {
|
||||||
|
dropdownOptions: 4,
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
var instances = M.Modal.init(elems, {});
|
||||||
|
var instancese = M.FormSelect.init(elemse, {
|
||||||
|
dropdownOptions: 4,
|
||||||
|
});
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.modalLinkProducts.helpers({
|
||||||
|
products: function() {
|
||||||
|
return Products.find({});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.modalLinkProducts.events({
|
||||||
|
'click #saveLink' (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
let menuItemId = Session.get("menuItemId");
|
||||||
|
let linkSelect = document.getElementById('prodForMenu');
|
||||||
|
let links = M.FormSelect.getInstance(linkSelect).getSelectedValues();
|
||||||
|
if (typeof links != undefined && links != [] && links != null) {
|
||||||
|
Meteor.call("add.menuProdLinks", menuItemId, links, function(err, result) {
|
||||||
|
if (err) {
|
||||||
|
console.log(" ERROR adding product links to this menu item: " + err);
|
||||||
|
} else {
|
||||||
|
Meteor.call('update.menuItemLinked', menuItemId, true, function(err, result) {
|
||||||
|
if (err) {
|
||||||
|
console.log(" ERROR adding link exists to menu item: " + err);
|
||||||
|
} else {
|
||||||
|
showSnackbar("Products added to Menu Item successfully!", "green");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -25,3 +25,7 @@ strike {
|
||||||
text-decoration-thickness: 3px;
|
text-decoration-thickness: 3px;
|
||||||
text-decoration-color: red;
|
text-decoration-color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.my-text {
|
||||||
|
font-size: 1.3em !important;
|
||||||
|
}
|
||||||
|
|
@ -54,9 +54,39 @@ Meteor.methods({
|
||||||
dateAddedToList: new Date(),
|
dateAddedToList: new Date(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
'add.itemsFromMenuItem' (itemIds, listId) {
|
||||||
|
check(itemIds, [String]);
|
||||||
|
check(listId, String);
|
||||||
|
|
||||||
|
if (!this.userId) {
|
||||||
|
throw new Meteor.Error('You are not allowed to add items from a menu. Make sure you are logged in with valid user credentials.');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.dir(itemIds);
|
||||||
|
|
||||||
|
for (i=0; i < itemIds.length; i++) {
|
||||||
|
// let's check and make sure the product isn't already on the list
|
||||||
|
let onList = ListItems.find({ listId: listId, prodId: itemIds[i] }).count();
|
||||||
|
console.log("Number On List: " + onList);
|
||||||
|
if (onList == 0) {
|
||||||
|
// now pull the product
|
||||||
|
let prodInfo = Products.findOne({ _id: itemIds[i] });
|
||||||
|
ListItems.insert({
|
||||||
|
itemName: prodInfo.prodName,
|
||||||
|
listId: listId,
|
||||||
|
prodId: prodInfo._id,
|
||||||
|
addedBy: this.userId,
|
||||||
|
itemStore: prodInfo.prodStore,
|
||||||
|
itemOrdered: false,
|
||||||
|
itemReceived: false,
|
||||||
|
dateAddedToList: new Date(),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// product exists on list, move on to next
|
||||||
|
console.log("Product Exists on Selected List.");
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'setOrdered.listItem' (itemId) {
|
'setOrdered.listItem' (itemId) {
|
||||||
check(itemId, String);
|
check(itemId, String);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,21 @@ Meteor.methods({
|
||||||
addedBy: this.userId,
|
addedBy: this.userId,
|
||||||
itemMade: false,
|
itemMade: false,
|
||||||
dateAddedtoMenu: new Date(),
|
dateAddedtoMenu: new Date(),
|
||||||
|
isLinked: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
'update.menuItemLinked' (itemId, isLinked) {
|
||||||
|
check(itemId, String);
|
||||||
|
check(isLinked, Boolean);
|
||||||
|
|
||||||
|
if (!this.userId) {
|
||||||
|
throw new Meteor.Error('You are not allowed to set this menu item as linked to products. Make sure you are logged in with valid user credentials.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return MenuItems.update({ _id: itemId }, {
|
||||||
|
$set: {
|
||||||
|
isLinked: isLinked,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
'setMade.menuItem' (itemId) {
|
'setMade.menuItem' (itemId) {
|
||||||
|
|
|
||||||
44
imports/api/menuProdLinks.js
Normal file
44
imports/api/menuProdLinks.js
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { Mongo } from 'meteor/mongo';
|
||||||
|
import { check } from 'meteor/check';
|
||||||
|
import { Products } from './products';
|
||||||
|
|
||||||
|
export const MenuProdLinks = new Mongo.Collection('menuProdLinks');
|
||||||
|
|
||||||
|
MenuProdLinks.allow({
|
||||||
|
insert: function(userId, doc){
|
||||||
|
// if use id exists, allow insert
|
||||||
|
return !!userId;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Meteor.methods({
|
||||||
|
'add.menuProdLinks' (menuItemId, prodNameArray) {
|
||||||
|
check(menuItemId, String);
|
||||||
|
check(prodNameArray, [String]);
|
||||||
|
|
||||||
|
if (!this.userId) {
|
||||||
|
throw new Meteor.Error('You are not allowed to add menu and product links. Make sure you are logged in with valid user credentials.');
|
||||||
|
}
|
||||||
|
|
||||||
|
let productObj = {};
|
||||||
|
|
||||||
|
let prodNameLength = prodNameArray.length;
|
||||||
|
|
||||||
|
for (i=0; i<prodNameLength; i++) {
|
||||||
|
let product = Products.findOne({ prodName: prodNameArray[i] });
|
||||||
|
if (typeof product != 'undefined' && product != null && product != "") {
|
||||||
|
let prodId = product._id;
|
||||||
|
MenuProdLinks.insert({
|
||||||
|
menuItemId: menuItemId,
|
||||||
|
prodName: prodNameArray[i],
|
||||||
|
prodId: prodId,
|
||||||
|
dateCreated: Date(),
|
||||||
|
createdBy: this.userId
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(" ERROR - unable to find a matching product by name: " + prodName[i] + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { SysConfig } from '../imports/api/systemConfig';
|
import { SysConfig } from '../imports/api/systemConfig';
|
||||||
|
import { MenuItems } from '../imports/api/menuItems';
|
||||||
|
|
||||||
Meteor.startup(() => {
|
Meteor.startup(() => {
|
||||||
// code to run on server at startup
|
// code to run on server at startup
|
||||||
|
|
@ -18,4 +19,24 @@ Meteor.startup(() => {
|
||||||
} else {
|
} else {
|
||||||
console.log("Registration policy already set.");
|
console.log("Registration policy already set.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if the isLInked item exists on menuitems, and if not, add it (data cleanup task)
|
||||||
|
let itemInfoNoLink = MenuItems.find({ isLinked: { $exists: false } }).fetch();
|
||||||
|
console.log("No Ites with isLinked not set: " + itemInfoNoLink.length);
|
||||||
|
if (itemInfoNoLink.length > 0) {
|
||||||
|
console.log("found items with isLinked not set.");
|
||||||
|
console.dir(itemInfoNoLink);
|
||||||
|
let infoLength = itemInfoNoLink.length;
|
||||||
|
for (i=0; i < infoLength; i++) {
|
||||||
|
MenuItems.update({ _id: itemInfoNoLink[i]._id }, {
|
||||||
|
$set: {
|
||||||
|
isLinked: false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// this will show if all items are found to have isLInked set.
|
||||||
|
console.log("No itesm with isLinked not set.");
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { MenuItems } from '../imports/api/menuItems.js';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { TaskItems } from '../imports/api/tasks.js';
|
import { TaskItems } from '../imports/api/tasks.js';
|
||||||
import { UserConfig } from '../imports/api/userConfig.js';
|
import { UserConfig } from '../imports/api/userConfig.js';
|
||||||
|
import { MenuProdLinks } from '../imports/api/menuProdLinks.js';
|
||||||
|
|
||||||
Meteor.publish("SystemConfig", function() {
|
Meteor.publish("SystemConfig", function() {
|
||||||
try {
|
try {
|
||||||
|
|
@ -82,10 +83,18 @@ Meteor.publish("myMenuItems", function(menuId) {
|
||||||
try {
|
try {
|
||||||
return MenuItems.find({ menuId: menuId });
|
return MenuItems.find({ menuId: menuId });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(" ERROR pulling list items for this list: " + error);
|
console.log(" ERROR pulling menu items for this list: " + error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Meteor.publish("allMenuItems", function() {
|
||||||
|
try {
|
||||||
|
return MenuItems.find({});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(" ERROR pulling all menu items from collection: " + error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
Meteor.publish("todayMenuItems", function() {
|
Meteor.publish("todayMenuItems", function() {
|
||||||
try {
|
try {
|
||||||
let todayDate = new Date();
|
let todayDate = new Date();
|
||||||
|
|
@ -118,4 +127,12 @@ Meteor.publish("rolesAvailable", function() {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(" ERROR publishing roles: " + error);
|
console.log(" ERROR publishing roles: " + error);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
|
Meteor.publish("menuProdLinkData", function() {
|
||||||
|
try {
|
||||||
|
return MenuProdLinks.find({});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(" ERROR publishing menu product links: " + error);
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue