From: ebelcrom Date: Thu, 26 Dec 2019 22:23:29 +0000 (+0100) Subject: features implemented expect notification settings X-Git-Tag: v1.0.0~2 X-Git-Url: http://www.binomiant.duckdns.org/9wAuyR5S/?a=commitdiff_plain;h=8ec88a4c4bf3922bfdce2c7d8f4b82c338c75b9d;p=garnod-pwa.git features implemented expect notification settings --- diff --git a/package-lock.json b/package-lock.json index 05f6ec8..85ea57a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2867,6 +2867,17 @@ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, "coa": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", @@ -5905,6 +5916,12 @@ } } }, + "interpret": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", + "dev": true + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -8449,6 +8466,15 @@ "readable-stream": "^2.0.2" } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -8801,6 +8827,36 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "sass": { + "version": "1.23.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.23.7.tgz", + "integrity": "sha512-cYgc0fanwIpi0rXisGxl+/wadVQ/HX3RhpdRcjLdj2o2ye/sxUTpAxIhbmJy3PLQgRFbf6Pn8Jsrta2vdXcoOQ==", + "dev": true, + "requires": { + "chokidar": ">=2.0.0 <4.0.0" + } + }, + "sass-loader": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.0.tgz", + "integrity": "sha512-+qeMu563PN7rPdit2+n5uuYVR0SSVwm0JsOUsaJXzgYcClWSlmX0iHDnmeOobPkf5kUglVot3QS6SyLyaQoJ4w==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", @@ -9015,6 +9071,15 @@ "safe-buffer": "^5.0.1" } }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -9036,6 +9101,17 @@ "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", "dev": true }, + "shelljs": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", + "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -10255,6 +10331,24 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz", "integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==" }, + "vue-cli-plugin-vuetify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/vue-cli-plugin-vuetify/-/vue-cli-plugin-vuetify-2.0.2.tgz", + "integrity": "sha512-OJ1YUSfDlQibj111QMGv4a44atmtWdrkynk4voiEuivUqLcZGCJyF/A8ae0VojpMU2jlvZydz0nXjmZmcg+Nqw==", + "dev": true, + "requires": { + "semver": "^6.0.0", + "shelljs": "^0.8.3" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "vue-hot-reload-api": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", @@ -10305,6 +10399,20 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "vuetify": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-2.1.14.tgz", + "integrity": "sha512-DZ1Jq2+PPEXYeh08FGJktB6St0ClZlcwzveCvJmkW16pYkUnimFlW6E3AQxSqxRpcGfZDsE53XkvZ2BGhy+m8Q==" + }, + "vuetify-loader": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/vuetify-loader/-/vuetify-loader-1.4.3.tgz", + "integrity": "sha512-fS0wRil682Ebsj2as+eruBoMPKaQYDhu/fDAndnTItzSY4RK4LOEIsssVL4vD6QY8dvUgoGL84SUQ6vGr777CA==", + "dev": true, + "requires": { + "loader-utils": "^1.2.0" + } + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", diff --git a/package.json b/package.json index 2dd3e22..2313148 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,29 @@ { - "name": "garnod-pwa.git", - "version": "0.1.0", - "private": true, + "name": "garnod-pwa", + "version": "1.0.0", + "description": "A garage door monitoring application (client).", "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build" }, + "author": "ebelcrom", + "license": "GPL-2.0-or-later", "dependencies": { "core-js": "^3.4.3", "register-service-worker": "^1.6.2", "vue": "^2.6.10", - "vue-router": "^3.1.3" + "vue-router": "^3.1.3", + "vuetify": "^2.1.0" }, "devDependencies": { "@vue/cli-plugin-babel": "^4.1.0", "@vue/cli-plugin-pwa": "^4.1.0", "@vue/cli-plugin-router": "^4.1.0", "@vue/cli-service": "^4.1.0", - "vue-template-compiler": "^2.6.10" + "sass": "^1.19.0", + "sass-loader": "^8.0.0", + "vue-cli-plugin-vuetify": "^2.0.2", + "vue-template-compiler": "^2.6.10", + "vuetify-loader": "^1.3.0" } } diff --git a/public/favicon.ico b/public/favicon.ico index df36fcf..55ef748 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/img/icons/android-chrome-192x192.png b/public/img/icons/android-chrome-192x192.png index b02aa64..2a78f13 100644 Binary files a/public/img/icons/android-chrome-192x192.png and b/public/img/icons/android-chrome-192x192.png differ diff --git a/public/img/icons/android-chrome-512x512.png b/public/img/icons/android-chrome-512x512.png index 06088b0..ffbd457 100644 Binary files a/public/img/icons/android-chrome-512x512.png and b/public/img/icons/android-chrome-512x512.png differ diff --git a/public/img/icons/apple-touch-icon-120x120.png b/public/img/icons/apple-touch-icon-120x120.png index 1427cf6..2704c84 100644 Binary files a/public/img/icons/apple-touch-icon-120x120.png and b/public/img/icons/apple-touch-icon-120x120.png differ diff --git a/public/img/icons/apple-touch-icon-152x152.png b/public/img/icons/apple-touch-icon-152x152.png index f24d454..6057af4 100644 Binary files a/public/img/icons/apple-touch-icon-152x152.png and b/public/img/icons/apple-touch-icon-152x152.png differ diff --git a/public/img/icons/apple-touch-icon-180x180.png b/public/img/icons/apple-touch-icon-180x180.png index 404e192..4ba873b 100644 Binary files a/public/img/icons/apple-touch-icon-180x180.png and b/public/img/icons/apple-touch-icon-180x180.png differ diff --git a/public/img/icons/apple-touch-icon-60x60.png b/public/img/icons/apple-touch-icon-60x60.png index cf10a56..7304ff2 100644 Binary files a/public/img/icons/apple-touch-icon-60x60.png and b/public/img/icons/apple-touch-icon-60x60.png differ diff --git a/public/img/icons/apple-touch-icon-76x76.png b/public/img/icons/apple-touch-icon-76x76.png index c500769..b727b14 100644 Binary files a/public/img/icons/apple-touch-icon-76x76.png and b/public/img/icons/apple-touch-icon-76x76.png differ diff --git a/public/img/icons/apple-touch-icon.png b/public/img/icons/apple-touch-icon.png index 03c0c5d..4ba873b 100644 Binary files a/public/img/icons/apple-touch-icon.png and b/public/img/icons/apple-touch-icon.png differ diff --git a/public/img/icons/favicon-16x16.png b/public/img/icons/favicon-16x16.png index 42af009..85f8bcb 100644 Binary files a/public/img/icons/favicon-16x16.png and b/public/img/icons/favicon-16x16.png differ diff --git a/public/img/icons/favicon-32x32.png b/public/img/icons/favicon-32x32.png index 46ca04d..bb65e60 100644 Binary files a/public/img/icons/favicon-32x32.png and b/public/img/icons/favicon-32x32.png differ diff --git a/public/img/icons/msapplication-icon-144x144.png b/public/img/icons/msapplication-icon-144x144.png index 7808237..58e3dd6 100644 Binary files a/public/img/icons/msapplication-icon-144x144.png and b/public/img/icons/msapplication-icon-144x144.png differ diff --git a/public/img/icons/mstile-150x150.png b/public/img/icons/mstile-150x150.png index 3b37a43..6037e48 100644 Binary files a/public/img/icons/mstile-150x150.png and b/public/img/icons/mstile-150x150.png differ diff --git a/public/index.html b/public/index.html index 6eb6e40..9cc8098 100644 --- a/public/index.html +++ b/public/index.html @@ -5,11 +5,13 @@ - garnod-pwa.git + Garage Node + +
diff --git a/src/App.vue b/src/App.vue index 8534514..5dae0f4 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,32 +1,36 @@ + + + - +export default { + name: 'App', + components: { + Navbar, + AboutDialog, + }, + data() { + return { + showAboutDialog: null, + }; + }, + methods: { + openAboutDialog() { + this.showAboutDialog = ['showDialog']; + }, + }, +}; + diff --git a/src/assets/images/closed.svg b/src/assets/images/closed.svg new file mode 100644 index 0000000..aa94fa0 --- /dev/null +++ b/src/assets/images/closed.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/src/assets/images/moving.svg b/src/assets/images/moving.svg new file mode 100644 index 0000000..0c5b607 --- /dev/null +++ b/src/assets/images/moving.svg @@ -0,0 +1,19 @@ + + + + background + + + + Layer 1 + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/images/open.svg b/src/assets/images/open.svg new file mode 100644 index 0000000..0a5dd8c --- /dev/null +++ b/src/assets/images/open.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/src/assets/images/unavailable.svg b/src/assets/images/unavailable.svg new file mode 100644 index 0000000..24d2644 --- /dev/null +++ b/src/assets/images/unavailable.svg @@ -0,0 +1,11 @@ + + + background + + + + + Layer 1 + + + \ No newline at end of file diff --git a/src/assets/logo.png b/src/assets/logo.png index f3d2503..5e977f9 100644 Binary files a/src/assets/logo.png and b/src/assets/logo.png differ diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..aa94fa0 --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/src/components/About.vue b/src/components/About.vue new file mode 100644 index 0000000..95346bd --- /dev/null +++ b/src/components/About.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/components/ApiKey.vue b/src/components/ApiKey.vue new file mode 100644 index 0000000..e7a16de --- /dev/null +++ b/src/components/ApiKey.vue @@ -0,0 +1,63 @@ + + + diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue deleted file mode 100644 index 49fc75f..0000000 --- a/src/components/HelloWorld.vue +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - diff --git a/src/components/Navbar.vue b/src/components/Navbar.vue new file mode 100644 index 0000000..64f4819 --- /dev/null +++ b/src/components/Navbar.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/lib/lib.js b/src/lib/lib.js new file mode 100644 index 0000000..9c213c1 --- /dev/null +++ b/src/lib/lib.js @@ -0,0 +1,210 @@ +function setItem(key, value) { + if (key === null) { + return; + } else { + localStorage.setItem(key, JSON.stringify(value)); + } +} + +function getItem(key) { + if (key === null) { + return null; + } else { + if (localStorage.getItem(key) === '') { + return ''; + } else { + return JSON.parse(localStorage.getItem(key)); + } + } +} + +function hasItem(key) { + if (key === null) { + return false; + } else { + return localStorage.getItem(key) !== null; + } +} + +export const storage = { + setItem: setItem, + getItem: getItem, + hasItem: hasItem, +}; + +export const notification = { +}; + +const url = 'https://binomiant.duckdns.org/mVk7Yr3k/v1'; +const prodStatus = '/status'; +const prodEvents = '/events'; +const prodControl = '/control'; +const testStatus = '/test/status'; +const testEvents = '/test/events'; +const testControl = '/test/control'; + +async function sendRequest(data) { + var init = { + method: data.method, + headers: {}, + } + if (data.requestContentType != null) { + init.headers['Content-Type'] = 'application/json'; + } + if (data.apiKey == null) { + init.headers['X-API-Key-Test'] = '2TTqCD4mNNny'; + } else { + init.headers['X-API-Key'] = data.apiKey; + } + + const response = await fetch(url + data.path + data.query, init); + if (response.status >= 200 && response.status <= 399) { + if (response.headers.get('Content-Type') != null) { + const result = await response.json(); + return result; + } else { + return {}; + } + } else { + return null; + } +} + +function getStatus() { + const testMode = getItem('testMode'); + var path = '', + apiKey = null; + var query = new URLSearchParams(''); + + if (testMode) { + path = testStatus + '?'; + } else { + path = prodStatus + '?'; + apiKey = getItem('apiKey'); + } + query.append('image', getItem('imageTransmission')); + + var data = { + path: path, + query: query.toString(), + method: 'GET', + apiKey: apiKey, + requestContentType: null, + responseContentType: 'json', + } + + return sendRequest(data); +} + +function getEvents() { + const testMode = getItem('testMode'); + var path = '', + apiKey = null; + var query = new URLSearchParams(''); + + if (testMode) { + path = testEvents + '?'; + } else { + path = prodEvents + '?'; + apiKey = getItem('apiKey'); + } + query.append('image', getItem('imageTransmission')); + query.append('timeout', 30); + + var data = { + path: path, + query: query.toString(), + method: 'GET', + apiKey: apiKey, + requestContentType: null, + responseContentType: 'json', + } + + return new Promise((resolve, reject) => { + sendRequest(data) + .then(response => { + if (response !== null) { + if (Object.entries(response).length === 0) { + // 304, request again + sendRequest(data) + .then(response => { + if (response !== null) { + if (Object.entries(response).length === 0) { + // 304, request again + sendRequest(data) + .then(response => { + if (response !== null) { + if (Object.entries(response).length === 0) { + // 304, abort + reject(null); + return; + } else { + resolve(response); + return; + } + } else { + throw new Error('server response not 2xx nor 3xx'); + } + }) + .catch(err => { + reject(null); + return; + }); + } else { + resolve(response); + return; + } + } else { + throw new Error('server response not 2xx nor 3xx'); + } + }) + .catch(err => { + reject(null); + return; + }); + } else { + resolve(response); + return; + } + } else { + throw new Error('server response not 2xx nor 3xx'); + } + }) + .catch(err => { + reject(null); + return; + }); + }); +} + +function postControl() { + const testMode = getItem('testMode'); + var path = '', + apiKey = null; + var query = new URLSearchParams(''); + + if (testMode) { + path = testControl + '?'; + } else { + path = prodControl + '?'; + apiKey = getItem('apiKey'); + } + query.append('command', 'move'); + + var data = { + path: path, + query: query.toString(), + method: 'POST', + apiKey: apiKey, + requestContentType: null, + responseContentType: null, + } + + return sendRequest(data); +} + +export const server = { + getStatus: getStatus, + getEvents: getEvents, + postControl: postControl, +} diff --git a/src/main.js b/src/main.js index 9f15ceb..7219cd9 100644 --- a/src/main.js +++ b/src/main.js @@ -2,10 +2,12 @@ import Vue from 'vue' import App from './App.vue' import './registerServiceWorker' import router from './router' +import vuetify from './plugins/vuetify'; Vue.config.productionTip = false new Vue({ router, + vuetify, render: h => h(App) }).$mount('#app') diff --git a/src/plugins/vuetify.js b/src/plugins/vuetify.js new file mode 100644 index 0000000..ec46adb --- /dev/null +++ b/src/plugins/vuetify.js @@ -0,0 +1,7 @@ +import Vue from 'vue'; +import Vuetify from 'vuetify/lib'; + +Vue.use(Vuetify); + +export default new Vuetify({ +}); diff --git a/src/registerServiceWorker.js b/src/registerServiceWorker.js index 76cede0..942c530 100644 --- a/src/registerServiceWorker.js +++ b/src/registerServiceWorker.js @@ -2,7 +2,7 @@ import { register } from 'register-service-worker' -if (process.env.NODE_ENV === 'production') { +//if (process.env.NODE_ENV === 'production') { register(`${process.env.BASE_URL}service-worker.js`, { ready () { console.log( @@ -29,4 +29,4 @@ if (process.env.NODE_ENV === 'production') { console.error('Error during service worker registration:', error) } }) -} +//} diff --git a/src/router/index.js b/src/router/index.js index 9d86d9d..5c06e42 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,8 +1,9 @@ -import Vue from 'vue' -import VueRouter from 'vue-router' -import Home from '../views/Home.vue' +import Vue from 'vue'; +import VueRouter from 'vue-router'; +import Home from '@/views/Home'; +import Settings from '@/views/Settings'; -Vue.use(VueRouter) +Vue.use(VueRouter); const routes = [ { @@ -11,17 +12,14 @@ const routes = [ component: Home }, { - path: '/about', - name: 'about', - // route level code-splitting - // this generates a separate chunk (about.[hash].js) for this route - // which is lazy-loaded when the route is visited. - component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') + path: '/settings', + name: 'settings', + component: Settings } ] const router = new VueRouter({ routes -}) +}); -export default router +export default router; diff --git a/src/views/About.vue b/src/views/About.vue deleted file mode 100644 index 3fa2807..0000000 --- a/src/views/About.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/src/views/Home.vue b/src/views/Home.vue index fc2e940..789cb70 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -1,18 +1,297 @@ diff --git a/src/views/Settings.vue b/src/views/Settings.vue new file mode 100644 index 0000000..1a59720 --- /dev/null +++ b/src/views/Settings.vue @@ -0,0 +1,178 @@ + + + diff --git a/vue.config.js b/vue.config.js new file mode 100644 index 0000000..9405fcc --- /dev/null +++ b/vue.config.js @@ -0,0 +1,13 @@ +module.exports = { + "transpileDependencies": [ + "vuetify" + ], + + pwa: { + name: 'Garage Node', + themeColor: '#1976D2', + msTileColor: '#424242' + }, + + publicPath: '' +}