diff --git a/README.md b/README.md
index 5aba949..86c59e2 100644
--- a/README.md
+++ b/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.
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
- Registration / Login System built in
- 1st user to register is the system admin by default.
diff --git a/client/AdminMgmt/Tasks/taskForm.js b/client/AdminMgmt/Tasks/taskForm.js
index 28fad17..c445eac 100644
--- a/client/AdminMgmt/Tasks/taskForm.js
+++ b/client/AdminMgmt/Tasks/taskForm.js
@@ -18,6 +18,10 @@ Template.taskForm.onRendered(function() {
placeholder: 'Task Name',
secondaryPlaceholder: '+Task Name',
});
+
+ setTimeout(function() {
+ instances = M.FormSelect.init(elems, {});
+ }, 350);
Session.set("taskNameErr", false);
Session.set("taskUserErr", false);
diff --git a/client/ListItems/listItemsTbl.html b/client/ListItems/listItemsTbl.html
index de728f8..cd2d486 100644
--- a/client/ListItems/listItemsTbl.html
+++ b/client/ListItems/listItemsTbl.html
@@ -11,7 +11,7 @@
{{itemName}}
{{/if}}
- delete
+ delete
check
{{/each}}
diff --git a/client/ListItems/listItemsTbl.js b/client/ListItems/listItemsTbl.js
index ee70b7c..4cc47a1 100644
--- a/client/ListItems/listItemsTbl.js
+++ b/client/ListItems/listItemsTbl.js
@@ -1,4 +1,5 @@
import { ListItems } from '../../imports/api/listItems.js';
+import { M } from '../lib/assets/materialize.js';
Template.listItemsTbl.onCreated(function() {
this.autorun( () => {
@@ -7,8 +8,9 @@ Template.listItemsTbl.onCreated(function() {
});
Template.listItemsTbl.onRendered(function() {
- // new modal init here
- // $('.modal').modal();
+ var elems = document.querySelectorAll('.modal');
+ var instances = M.Modal.init(elems, {});
+
Session.set("showReceivedItems", false);
Session.set("searchVal", "");
});
diff --git a/client/MenuItems/addProdToListModal.html b/client/MenuItems/addProdToListModal.html
new file mode 100644
index 0000000..c5b7029
--- /dev/null
+++ b/client/MenuItems/addProdToListModal.html
@@ -0,0 +1,47 @@
+
+
+ {{> snackbar}}
+
\ No newline at end of file
diff --git a/client/MenuItems/addProdToListModal.js b/client/MenuItems/addProdToListModal.js
new file mode 100644
index 0000000..1b58f17
--- /dev/null
+++ b/client/MenuItems/addProdToListModal.js
@@ -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");
+ }
+ });
+ }
+});
\ No newline at end of file
diff --git a/client/MenuItems/menuItemsForm.js b/client/MenuItems/menuItemsForm.js
index ff27a5e..17f1b5e 100644
--- a/client/MenuItems/menuItemsForm.js
+++ b/client/MenuItems/menuItemsForm.js
@@ -5,7 +5,7 @@ import { M } from '../lib/assets/materialize.js';
Template.menuItemsForm.onCreated(function() {
this.subscribe("myMenus");
- this.subscribe("myMenuItems", Session.get("menuId"));
+ this.subscribe("allMenuItems", Session.get("menuId"));
});
Template.menuItemsForm.onRendered(function() {
@@ -13,6 +13,15 @@ Template.menuItemsForm.onRendered(function() {
var instances = M.Datepicker.init(elems, {});
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({
@@ -65,5 +74,20 @@ Template.menuItemsForm.events({
}
});
}
- }
-});
\ No newline at end of file
+ },
+ '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);
+}
\ No newline at end of file
diff --git a/client/MenuItems/menuItemsTbl.html b/client/MenuItems/menuItemsTbl.html
index 9e671fa..ee1da76 100644
--- a/client/MenuItems/menuItemsTbl.html
+++ b/client/MenuItems/menuItemsTbl.html
@@ -2,8 +2,16 @@
+
+
+ | Menu Item |
+ Date to Serve |
+ Has Product Links |
+ Actions |
+
+
{{#each thisMenuItems}}
-
+
|
{{#if $eq itemMade true}}
@@ -17,12 +25,20 @@
{{serveDate}}
|
-
+ {{#if $eq isLinked true}}+ Shopping List{{/if}}
+ |
+
+
+ link
|
{{/each}}
+
+
{{> deleteConfirmationModal}}
+ {{> modalLinkProducts}}
+ {{> addProdToListModal}}
\ No newline at end of file
diff --git a/client/MenuItems/menuItemsTbl.js b/client/MenuItems/menuItemsTbl.js
index b859532..2347b7f 100644
--- a/client/MenuItems/menuItemsTbl.js
+++ b/client/MenuItems/menuItemsTbl.js
@@ -10,11 +10,19 @@ Template.menuItemsTbl.onCreated(function() {
Template.menuItemsTbl.onRendered(function() {
var elems = document.querySelectorAll('.modal');
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({
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("view", "Menu Items");
},
+ 'click .linkToProducts' (event) {
+ event.preventDefault();
+ Session.set("menuItemId", this._id);
+ },
+ 'click .addProdsToList' (event) {
+ event.preventDefault();
+ Session.set("menuItemId", this._id);
+ }
});
\ No newline at end of file
diff --git a/client/MenuItems/menuitemsForm.html b/client/MenuItems/menuitemsForm.html
index 1a6fc07..a9f22a6 100644
--- a/client/MenuItems/menuitemsForm.html
+++ b/client/MenuItems/menuitemsForm.html
@@ -2,8 +2,11 @@
{{menuName}}