├── views
├── index.ejs
├── share
│ └── side-menu.ejs
├── err
│ ├── occurs-error.ejs
│ ├── e401.ejs
│ └── e404.ejs
├── layout.ejs
├── invocation
│ └── index.ejs
└── manager
│ └── invocation
│ └── index.ejs
├── Procfile
├── public
├── plugins
│ ├── clipboard
│ │ ├── .travis.yml
│ │ ├── .babelrc
│ │ ├── package.js
│ │ ├── bower.json
│ │ ├── .github
│ │ │ ├── issue_template.md
│ │ │ └── stale.yml
│ │ ├── .editorconfig
│ │ ├── composer.json
│ │ ├── demo
│ │ │ ├── target-div.html
│ │ │ ├── function-text.html
│ │ │ ├── target-textarea.html
│ │ │ ├── target-input.html
│ │ │ ├── constructor-node.html
│ │ │ ├── function-target.html
│ │ │ ├── constructor-selector.html
│ │ │ └── constructor-nodelist.html
│ │ ├── karma.conf.js
│ │ ├── LICENSE
│ │ ├── webpack.config.js
│ │ ├── contributing.md
│ │ └── package.json
│ └── datatables
│ │ ├── keyTable.dataTables.min.css
│ │ ├── autoFill.bootstrap4.min.js
│ │ ├── buttons.bootstrap4.min.js
│ │ ├── responsive.bootstrap4.min.js
│ │ ├── buttons.print.min.js
│ │ ├── dataTables.bootstrap4.min.js
│ │ ├── autoFill.bootstrap4.css
│ │ ├── buttons.colVis.min.js
│ │ ├── responsive.bootstrap4.min.css
│ │ └── buttons.bootstrap4.min.css
└── assets
│ ├── fonts
│ ├── test.ttf
│ ├── typicons.eot
│ ├── typicons.ttf
│ ├── typicons.woff
│ ├── themify9f24.eot
│ ├── themify9f24.ttf
│ ├── themifyd41d.eot
│ ├── Tangerine_Bold.ttf
│ ├── dripicons-v2.eot
│ ├── dripicons-v2.ttf
│ ├── dripicons-v2.woff
│ ├── fa-brands-400.eot
│ ├── fa-brands-400.ttf
│ ├── fa-brands-400.woff
│ ├── fa-regular-400.eot
│ ├── fa-regular-400.ttf
│ ├── fa-solid-900.eot
│ ├── fa-solid-900.ttf
│ ├── fa-solid-900.woff
│ ├── fa-solid-900.woff2
│ ├── ionicons6f46.eot
│ ├── ionicons6f46.ttf
│ ├── ionicons6f46.woff
│ ├── ionicons6f46.woff2
│ ├── themify9f24.woff
│ ├── typiconsd41d.eot
│ ├── dripicons-v2d41d.eot
│ ├── fa-brands-400.woff2
│ ├── fa-regular-400.woff
│ ├── fa-regular-400.woff2
│ ├── fa-solid-900d41d.eot
│ ├── GreatVibes-Regular.ttf
│ ├── RougeScript-Regular.ttf
│ ├── Tangerine_Regular.ttf
│ ├── fa-brands-400d41d.eot
│ ├── fa-regular-400d41d.eot
│ ├── wedding
│ │ ├── VfWedding01.ttf
│ │ ├── VfWedding03.ttf
│ │ ├── VfWedding04.ttf
│ │ ├── VfWedding05.ttf
│ │ ├── VfWedding06.ttf
│ │ ├── VfWedding07.ttf
│ │ ├── VfWedding08.ttf
│ │ ├── VfWedding09.ttf
│ │ ├── VfWedding10.ttf
│ │ ├── VfWedding11.ttf
│ │ ├── VfWedding12.ttf
│ │ ├── VfWedding14.ttf
│ │ ├── VfWedding15.ttf
│ │ ├── VfWedding16.ttf
│ │ ├── VfWedding17.ttf
│ │ ├── VfWedding18.ttf
│ │ ├── VfWedding19.ttf
│ │ ├── VfWedding21.ttf
│ │ ├── VfWedding24.ttf
│ │ ├── VfWedding25.ttf
│ │ ├── VfWedding26.ttf
│ │ ├── VfWedding27.ttf
│ │ ├── VfWedding28.ttf
│ │ ├── VfWedding29.ttf
│ │ ├── VfWedding30.ttf
│ │ ├── VfWedding31.ttf
│ │ ├── VfWedding32.ttf
│ │ ├── VfWedding33.ttf
│ │ ├── VfWedding34.ttf
│ │ ├── VfWedding01_0.ttf
│ │ ├── VfWedding01_1.ttf
│ │ ├── VfWedding03_0.ttf
│ │ ├── VfWedding03_1.ttf
│ │ ├── VfWedding04_0.ttf
│ │ ├── VfWedding04_1.ttf
│ │ ├── VfWedding05_0.ttf
│ │ ├── VfWedding05_1.ttf
│ │ ├── VfWedding06_0.ttf
│ │ ├── VfWedding06_1.ttf
│ │ ├── VfWedding07_0.ttf
│ │ ├── VfWedding07_1.ttf
│ │ ├── VfWedding08_0.ttf
│ │ ├── VfWedding08_1.ttf
│ │ ├── VfWedding09_0.ttf
│ │ ├── VfWedding09_1.ttf
│ │ ├── VfWedding10_0.ttf
│ │ ├── VfWedding10_1.ttf
│ │ ├── VfWedding11_0.ttf
│ │ ├── VfWedding11_1.ttf
│ │ ├── VfWedding12_0.ttf
│ │ ├── VfWedding12_1.ttf
│ │ ├── VfWedding14_0.ttf
│ │ ├── VfWedding14_1.ttf
│ │ ├── VfWedding15_0.ttf
│ │ ├── VfWedding15_1.ttf
│ │ ├── VfWedding16_0.ttf
│ │ ├── VfWedding16_1.ttf
│ │ ├── VfWedding17_0.ttf
│ │ ├── VfWedding17_1.ttf
│ │ ├── VfWedding18_0.ttf
│ │ ├── VfWedding18_1.ttf
│ │ ├── VfWedding19_0.ttf
│ │ ├── VfWedding19_1.ttf
│ │ ├── VfWedding21_0.ttf
│ │ ├── VfWedding21_1.ttf
│ │ ├── VfWedding22b.ttf
│ │ ├── VfWedding22n.ttf
│ │ ├── VfWedding23b.ttf
│ │ ├── VfWedding23n.ttf
│ │ ├── VfWedding24_0.ttf
│ │ ├── VfWedding24_1.ttf
│ │ ├── VfWedding25_0.ttf
│ │ ├── VfWedding25_1.ttf
│ │ ├── VfWedding26_0.ttf
│ │ ├── VfWedding26_1.ttf
│ │ ├── VfWedding27_0.ttf
│ │ ├── VfWedding27_1.ttf
│ │ ├── VfWedding28_0.ttf
│ │ ├── VfWedding28_1.ttf
│ │ ├── VfWedding29_0.ttf
│ │ ├── VfWedding29_1.ttf
│ │ ├── VfWedding30_0.ttf
│ │ ├── VfWedding30_1.ttf
│ │ ├── VfWedding31_0.ttf
│ │ ├── VfWedding31_1.ttf
│ │ ├── VfWedding32_0.ttf
│ │ ├── VfWedding32_1.ttf
│ │ ├── VfWedding33_0.ttf
│ │ ├── VfWedding33_1.ttf
│ │ ├── VfWedding34_0.ttf
│ │ ├── VfWedding34_1.ttf
│ │ ├── VfWedding02-Bold.ttf
│ │ ├── VfWedding13-Bold.ttf
│ │ ├── VfWedding20-Bold.ttf
│ │ ├── VfWedding22b_0.ttf
│ │ ├── VfWedding22b_1.ttf
│ │ ├── VfWedding22n_0.ttf
│ │ ├── VfWedding22n_1.ttf
│ │ ├── VfWedding23b_0.ttf
│ │ ├── VfWedding23b_1.ttf
│ │ ├── VfWedding23n_0.ttf
│ │ ├── VfWedding23n_1.ttf
│ │ ├── VfWedding02-Bold_0.ttf
│ │ ├── VfWedding02-Bold_1.ttf
│ │ ├── VfWedding02-Normal.ttf
│ │ ├── VfWedding13-Bold_0.ttf
│ │ ├── VfWedding13-Bold_1.ttf
│ │ ├── VfWedding13-Normal.ttf
│ │ ├── VfWedding20-Bold_0.ttf
│ │ ├── VfWedding20-Bold_1.ttf
│ │ ├── VfWedding20-Normal.ttf
│ │ ├── VfWedding02-Normal_0.ttf
│ │ ├── VfWedding02-Normal_1.ttf
│ │ ├── VfWedding13-Normal_0.ttf
│ │ ├── VfWedding13-Normal_1.ttf
│ │ ├── VfWedding20-Normal_0.ttf
│ │ └── VfWedding20-Normal_1.ttf
│ ├── PinyonScript-Regular.ttf
│ ├── materialdesignicons-webfont772b.eot
│ ├── materialdesignicons-webfont772b.ttf
│ ├── materialdesignicons-webfontd41d.eot
│ ├── materialdesignicons-webfont772b.woff
│ ├── materialdesignicons-webfont772b.woff2
│ └── FONTLOG.txt
│ ├── images
│ ├── bg.jpg
│ ├── err.gif
│ ├── bg-fb.jpg
│ ├── error.png
│ ├── favicon.ico
│ ├── logo-dark.png
│ ├── logo-light.png
│ ├── right-top.png
│ ├── flags
│ │ ├── us_flag.jpg
│ │ ├── french_flag.jpg
│ │ ├── germany_flag.jpg
│ │ ├── italy_flag.jpg
│ │ ├── russia_flag.jpg
│ │ └── spain_flag.jpg
│ ├── maintenance.png
│ └── lg.dual-ring-loader.gif
│ ├── js
│ ├── base
│ │ ├── config.js
│ │ ├── common.js
│ │ ├── form.js
│ │ ├── validate.js
│ │ ├── notify.js
│ │ └── ajax.js
│ ├── img.view.js
│ ├── live
│ │ ├── account
│ │ │ └── account.action.js
│ │ ├── login.admin.js
│ │ ├── chart.statistical.js
│ │ └── invocation
│ │ │ └── action.js
│ ├── imgPreview.min.js
│ ├── app.js
│ ├── history.char.js
│ └── layout.js
│ └── css
│ ├── metisMenu.min.css.map
│ ├── img.view.css
│ ├── metismenu.min.css
│ ├── custom.css
│ └── bootstrap-reboot.min.css
├── .gitignore
├── controllers
├── invitation
│ ├── invitation-validator.js
│ ├── invitation-router.js
│ └── invitation-controller.js
├── manager
│ ├── account
│ │ ├── account-validator.js
│ │ ├── account-router.js
│ │ └── account-controller.js
│ ├── invocation
│ │ ├── invocation-router.js
│ │ ├── invocation-validator.js
│ │ └── invocation-controller.js
│ ├── invitation
│ │ ├── invitation-validator.js
│ │ ├── invitation-router.js
│ │ └── invitation-controller.js
│ └── index.js
├── bank
│ ├── bank-router.js
│ └── bank-controller.js
├── setup
│ ├── setup-router.js
│ └── setup-controller.js
├── index.js
└── invocation
│ ├── invocation-validator.js
│ ├── invocation-router.js
│ └── invocation-controller.js
├── configs
├── data-config.js
├── mongo-db.js
└── system-configs.js
├── helpers
├── util.js
├── constants.js
└── time-util.js
├── core
├── base-entity.js
├── base-entity-mongodb.js
├── base-core.js
├── base-component.js
└── base-controller.js
├── domains
├── handleResult.js
└── mongodb
│ ├── schemas.js
│ ├── seed-db.js
│ └── seed-db.json
├── example.env
├── .github
└── workflows
│ ├── deploy-heroku.yml
│ └── quote_generator.yml
├── middlewares
└── authentication.js
├── business
├── entities
│ └── mongodb
│ │ ├── account-entity.js
│ │ ├── data-config-entity.js
│ │ ├── invitee-entity.js
│ │ └── invocation-entity.js
├── components
│ ├── data-config
│ │ └── data-config-component.js
│ ├── auth
│ │ └── auth-component.js
│ ├── account
│ │ └── account-component.js
│ ├── invitation
│ │ └── invitation-component.js
│ └── invocation
│ │ └── invocation-component.js
└── facade
│ └── facade.js
├── index.js
├── LICENSE
├── package.json
├── app.js
└── bin
└── www
/views/index.ejs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: npm run heroku-start
--------------------------------------------------------------------------------
/public/plugins/clipboard/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - stable
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /.idea
3 | /.nyc_output
4 | /npm-debug.log
5 | /.eslintrc.js
6 | /.env
7 | /.snyk
--------------------------------------------------------------------------------
/controllers/invitation/invitation-validator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const {body} = require('express-validator');
4 |
--------------------------------------------------------------------------------
/public/assets/fonts/test.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/test.ttf
--------------------------------------------------------------------------------
/public/assets/images/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/bg.jpg
--------------------------------------------------------------------------------
/public/assets/images/err.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/err.gif
--------------------------------------------------------------------------------
/controllers/manager/account/account-validator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const {body} = require('express-validator');
4 |
--------------------------------------------------------------------------------
/public/assets/images/bg-fb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/bg-fb.jpg
--------------------------------------------------------------------------------
/public/assets/images/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/error.png
--------------------------------------------------------------------------------
/public/assets/fonts/typicons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/typicons.eot
--------------------------------------------------------------------------------
/public/assets/fonts/typicons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/typicons.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/typicons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/typicons.woff
--------------------------------------------------------------------------------
/public/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/favicon.ico
--------------------------------------------------------------------------------
/public/assets/fonts/themify9f24.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/themify9f24.eot
--------------------------------------------------------------------------------
/public/assets/fonts/themify9f24.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/themify9f24.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/themifyd41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/themifyd41d.eot
--------------------------------------------------------------------------------
/public/assets/images/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/logo-dark.png
--------------------------------------------------------------------------------
/public/assets/images/logo-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/logo-light.png
--------------------------------------------------------------------------------
/public/assets/images/right-top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/right-top.png
--------------------------------------------------------------------------------
/configs/data-config.js:
--------------------------------------------------------------------------------
1 | const DataConfig = {
2 | URI: 'https://wedding.sauanla.com'
3 | };
4 |
5 | module.exports = DataConfig;
6 |
--------------------------------------------------------------------------------
/public/assets/fonts/Tangerine_Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/Tangerine_Bold.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/dripicons-v2.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/dripicons-v2.eot
--------------------------------------------------------------------------------
/public/assets/fonts/dripicons-v2.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/dripicons-v2.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/dripicons-v2.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/dripicons-v2.woff
--------------------------------------------------------------------------------
/public/assets/fonts/fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-brands-400.eot
--------------------------------------------------------------------------------
/public/assets/fonts/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-brands-400.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-brands-400.woff
--------------------------------------------------------------------------------
/public/assets/fonts/fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-regular-400.eot
--------------------------------------------------------------------------------
/public/assets/fonts/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-regular-400.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-solid-900.eot
--------------------------------------------------------------------------------
/public/assets/fonts/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-solid-900.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-solid-900.woff
--------------------------------------------------------------------------------
/public/assets/fonts/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-solid-900.woff2
--------------------------------------------------------------------------------
/public/assets/fonts/ionicons6f46.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/ionicons6f46.eot
--------------------------------------------------------------------------------
/public/assets/fonts/ionicons6f46.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/ionicons6f46.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/ionicons6f46.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/ionicons6f46.woff
--------------------------------------------------------------------------------
/public/assets/fonts/ionicons6f46.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/ionicons6f46.woff2
--------------------------------------------------------------------------------
/public/assets/fonts/themify9f24.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/themify9f24.woff
--------------------------------------------------------------------------------
/public/assets/fonts/typiconsd41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/typiconsd41d.eot
--------------------------------------------------------------------------------
/public/assets/images/flags/us_flag.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/flags/us_flag.jpg
--------------------------------------------------------------------------------
/public/assets/images/maintenance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/maintenance.png
--------------------------------------------------------------------------------
/public/assets/fonts/dripicons-v2d41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/dripicons-v2d41d.eot
--------------------------------------------------------------------------------
/public/assets/fonts/fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-brands-400.woff2
--------------------------------------------------------------------------------
/public/assets/fonts/fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-regular-400.woff
--------------------------------------------------------------------------------
/public/assets/fonts/fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-regular-400.woff2
--------------------------------------------------------------------------------
/public/assets/fonts/fa-solid-900d41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-solid-900d41d.eot
--------------------------------------------------------------------------------
/public/assets/fonts/GreatVibes-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/GreatVibes-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/RougeScript-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/RougeScript-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/Tangerine_Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/Tangerine_Regular.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/fa-brands-400d41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-brands-400d41d.eot
--------------------------------------------------------------------------------
/public/assets/fonts/fa-regular-400d41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/fa-regular-400d41d.eot
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding01.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding01.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding03.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding03.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding04.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding04.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding05.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding05.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding06.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding06.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding07.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding07.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding08.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding08.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding09.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding09.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding10.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding10.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding11.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding11.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding12.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding12.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding14.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding14.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding15.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding15.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding16.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding16.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding17.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding17.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding18.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding18.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding19.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding19.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding21.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding21.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding24.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding24.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding25.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding25.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding26.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding26.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding27.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding27.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding28.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding28.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding29.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding29.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding30.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding30.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding31.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding31.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding32.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding32.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding33.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding33.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding34.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding34.ttf
--------------------------------------------------------------------------------
/public/assets/images/flags/french_flag.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/flags/french_flag.jpg
--------------------------------------------------------------------------------
/public/assets/images/flags/germany_flag.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/flags/germany_flag.jpg
--------------------------------------------------------------------------------
/public/assets/images/flags/italy_flag.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/flags/italy_flag.jpg
--------------------------------------------------------------------------------
/public/assets/images/flags/russia_flag.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/flags/russia_flag.jpg
--------------------------------------------------------------------------------
/public/assets/images/flags/spain_flag.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/flags/spain_flag.jpg
--------------------------------------------------------------------------------
/public/assets/fonts/PinyonScript-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/PinyonScript-Regular.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding01_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding01_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding01_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding01_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding03_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding03_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding03_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding03_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding04_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding04_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding04_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding04_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding05_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding05_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding05_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding05_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding06_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding06_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding06_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding06_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding07_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding07_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding07_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding07_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding08_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding08_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding08_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding08_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding09_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding09_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding09_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding09_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding10_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding10_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding10_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding10_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding11_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding11_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding11_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding11_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding12_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding12_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding12_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding12_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding14_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding14_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding14_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding14_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding15_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding15_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding15_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding15_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding16_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding16_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding16_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding16_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding17_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding17_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding17_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding17_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding18_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding18_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding18_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding18_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding19_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding19_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding19_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding19_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding21_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding21_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding21_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding21_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding22b.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding22b.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding22n.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding22n.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding23b.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding23b.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding23n.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding23n.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding24_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding24_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding24_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding24_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding25_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding25_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding25_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding25_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding26_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding26_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding26_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding26_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding27_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding27_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding27_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding27_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding28_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding28_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding28_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding28_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding29_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding29_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding29_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding29_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding30_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding30_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding30_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding30_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding31_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding31_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding31_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding31_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding32_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding32_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding32_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding32_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding33_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding33_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding33_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding33_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding34_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding34_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding34_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding34_1.ttf
--------------------------------------------------------------------------------
/public/assets/images/lg.dual-ring-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/images/lg.dual-ring-loader.gif
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding02-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding02-Bold.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding13-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding13-Bold.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding20-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding20-Bold.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding22b_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding22b_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding22b_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding22b_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding22n_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding22n_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding22n_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding22n_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding23b_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding23b_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding23b_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding23b_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding23n_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding23n_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding23n_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding23n_1.ttf
--------------------------------------------------------------------------------
/public/plugins/datatables/keyTable.dataTables.min.css:
--------------------------------------------------------------------------------
1 | table.dataTable tbody th.focus,table.dataTable tbody td.focus{box-shadow:inset 0 0 1px 2px #3366FF}
2 |
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding02-Bold_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding02-Bold_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding02-Bold_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding02-Bold_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding02-Normal.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding02-Normal.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding13-Bold_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding13-Bold_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding13-Bold_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding13-Bold_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding13-Normal.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding13-Normal.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding20-Bold_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding20-Bold_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding20-Bold_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding20-Bold_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding20-Normal.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding20-Normal.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding02-Normal_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding02-Normal_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding02-Normal_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding02-Normal_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding13-Normal_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding13-Normal_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding13-Normal_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding13-Normal_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding20-Normal_0.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding20-Normal_0.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/wedding/VfWedding20-Normal_1.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/wedding/VfWedding20-Normal_1.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/materialdesignicons-webfont772b.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/materialdesignicons-webfont772b.eot
--------------------------------------------------------------------------------
/public/assets/fonts/materialdesignicons-webfont772b.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/materialdesignicons-webfont772b.ttf
--------------------------------------------------------------------------------
/public/assets/fonts/materialdesignicons-webfontd41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/materialdesignicons-webfontd41d.eot
--------------------------------------------------------------------------------
/public/assets/fonts/materialdesignicons-webfont772b.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/materialdesignicons-webfont772b.woff
--------------------------------------------------------------------------------
/public/assets/fonts/materialdesignicons-webfont772b.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sauanla/wedding-invitation/HEAD/public/assets/fonts/materialdesignicons-webfont772b.woff2
--------------------------------------------------------------------------------
/helpers/util.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 | class Util {
5 |
6 | static generateUuid() {
7 | const uuidv4 = require('uuid/v4');
8 | return uuidv4();
9 | }
10 |
11 | }
12 |
13 | module.exports = Util;
14 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "env",
5 | {
6 | "targets": {
7 | "uglify": true
8 | },
9 | "modules": false
10 | }
11 | ]
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/core/base-entity.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const BaseCore = require('../core/base-core');
4 |
5 | class BaseEntity extends BaseCore {
6 |
7 | constructor() {
8 | super();
9 | }
10 | }
11 |
12 | module.exports = BaseEntity;
13 |
--------------------------------------------------------------------------------
/public/assets/js/base/config.js:
--------------------------------------------------------------------------------
1 | const qrCodeSrc = 'https://barcode.tec-it.com/barcode.ashx?data={code}&code=MobileQRCode&multiplebarcodes=false&translate-esc=false&unit=Fit&dpi=96&imagetype=Gif&rotation=0&color=%23000000&bgcolor=%23ffffff&codepage=&qunit=Mm&quiet=0&eclevel=L';
--------------------------------------------------------------------------------
/public/assets/js/img.view.js:
--------------------------------------------------------------------------------
1 | $(() => $.imgPreview());
2 | $.imgPreview({
3 | el: "[data-pic]",
4 | attr: "data-pic",
5 | attrTitle: "data-pic-title",
6 | attrDesc: "data-pic-desc",
7 | mode: "single",
8 | isMaskShow: true,
9 | maskBgColor: "rgba(0,0,0,.5)"
10 | });
11 |
--------------------------------------------------------------------------------
/controllers/bank/bank-router.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | const express = require("express");
3 | const Controller = require("./bank-controller");
4 |
5 | const controller = new Controller();
6 | const router = express.Router();
7 |
8 | router.get("/", controller.bankPage);
9 |
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/controllers/setup/setup-router.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | const express = require("express");
3 | const Controller = require("./setup-controller");
4 |
5 | const controller = new Controller();
6 | const router = express.Router();
7 |
8 | router.get("/", controller.setupPage);
9 |
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/domains/handleResult.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | class HandleResult {
4 |
5 | constructor(success, data, messageList) {
6 | this.success = success || false;
7 | this.data = data || {};
8 | this.messageList = messageList || [];
9 | }
10 | }
11 |
12 | module.exports = HandleResult;
13 |
--------------------------------------------------------------------------------
/public/assets/js/base/common.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function () {
2 | var urlSplit = window.location.pathname.split('/');
3 | if (urlSplit.length == 4) {
4 | $('#menu-' + urlSplit[2]).addClass('active-sub active');
5 | } else {
6 | $('#menu-Dashboard').addClass('active-sub active');
7 | }
8 | });
--------------------------------------------------------------------------------
/core/base-entity-mongodb.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const mongoose = require('mongoose');
4 | const BaseCore = require('../core/base-core');
5 |
6 | class BaseEntityMongoDb extends BaseCore {
7 |
8 | constructor(model, schema) {
9 | super();
10 | this._model = mongoose.model(model, schema);
11 | }
12 | }
13 |
14 | module.exports = BaseEntityMongoDb;
--------------------------------------------------------------------------------
/public/plugins/clipboard/package.js:
--------------------------------------------------------------------------------
1 | // Package metadata for Meteor.js.
2 |
3 | Package.describe({
4 | name: "zenorocha:clipboard",
5 | summary: "Modern copy to clipboard. No Flash. Just 3kb.",
6 | version: "2.0.6",
7 | git: "https://github.com/zenorocha/clipboard.js"
8 | });
9 |
10 | Package.onUse(function(api) {
11 | api.addFiles("dist/clipboard.js", "client");
12 | });
13 |
--------------------------------------------------------------------------------
/example.env:
--------------------------------------------------------------------------------
1 | NODE_ENV = development
2 |
3 | PORT = 3001
4 | NAME = 'WEDDING-INVITATION'
5 |
6 | // https://cloud.mongodb.com/
7 | // https://i.imgur.com/Om20WQc.png
8 | URI_MONGO = 'URI'
9 | DOMAIN = 'http://localhost:3001'
10 |
11 | //https://www.google.com/recaptcha/admin
12 | SITE_KEY = 'SITE_KEY'
13 | SECRET_KEY = 'SECRET_KEY'
14 |
15 | BODY_PARSER_URLENCODED_LIMIT = '10mb'
16 | BODY_PARSER_JSON_LIMIT = '10mb'
17 |
--------------------------------------------------------------------------------
/controllers/invitation/invitation-router.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | const express = require("express");
3 | const Controller = require("./invitation-controller");
4 |
5 | const controller = new Controller();
6 | const router = express.Router();
7 |
8 | router.get("/", controller.defaultPage);
9 | router.get('/:id', controller.detailInvitation);
10 | router.get('/bank', controller.bankPage);
11 |
12 | module.exports = router;
13 |
--------------------------------------------------------------------------------
/controllers/manager/invocation/invocation-router.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | const express = require("express");
3 | const Controller = require("./invocation-controller");
4 | const validator = require("./invocation-validator");
5 |
6 | const controller = new Controller();
7 | const router = express.Router();
8 |
9 | router.get('/', controller.listInvocationRender);
10 | router.delete('/', controller.deleteInvocation);
11 |
12 | module.exports = router;
13 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "clipboard",
3 | "version": "2.0.6",
4 | "description": "Modern copy to clipboard. No Flash. Just 3kb",
5 | "license": "MIT",
6 | "main": "dist/clipboard.js",
7 | "ignore": [
8 | "/.*/",
9 | "/demo/",
10 | "/test/",
11 | "/.*",
12 | "/bower.json",
13 | "/karma.conf.js",
14 | "/src",
15 | "/lib"
16 | ],
17 | "keywords": [
18 | "clipboard",
19 | "copy",
20 | "cut"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/.github/issue_template.md:
--------------------------------------------------------------------------------
1 | ### Minimal example
2 |
3 | > Fork this [JSFiddle](https://jsfiddle.net/zenorocha/5kk0eysw/) and reproduce your issue.
4 |
5 | ### Expected behaviour
6 |
7 | I thought that by going to the page '...' and pressing the button '...' then '...' would happen.
8 |
9 | ### Actual behaviour
10 |
11 | Instead of '...', what I saw was that '...' happened instead.
12 |
13 | ### Browsers affected
14 |
15 | I tested on all major browsers and only IE 11 does not work.
16 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-heroku.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Heroku
2 |
3 | on:
4 | push:
5 | branches: [product]
6 | jobs:
7 |
8 | deploy:
9 | name: Deploy
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v2
13 | - uses: akhileshns/heroku-deploy@v3.12.12 # This is the action
14 | with:
15 | heroku_api_key: ${{secrets.HEROKU_API_KEY}}
16 | heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
17 | heroku_email: "phucnd.zit@gmail.com"
18 |
--------------------------------------------------------------------------------
/middlewares/authentication.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 |
4 | exports.requiresLogin = function (req, res, next) {
5 | if (req.session && req.session.user) {
6 | return next();
7 | } else {
8 | return res.redirect('/manager/account/login');
9 | }
10 | };
11 |
12 | exports.requiresLogout = function (req, res, next) {
13 | if (req.session && req.session.user) {
14 | return res.json({err: 'You must be Logout in to Login continue'});
15 | } else {
16 | return next();
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/public/assets/css/metisMenu.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["../src/metisMenu.scss"],"names":[],"mappings":"CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,kBACE,YACA,oBAEF,6BACE,WAQF,mCACE,YAEF,gDACE,YAQF,4BACE,YAEF,yCACE,YAQF,6BACE,YAEF,0CACE,YAEF,uBACE,YAEF,kCACE,WAEF,iCACE,YAEF,uCACE,wBAEF,uBACE,YAEF,kCACE,WAEF,iCACE,YAEF,8CACE,YAEF,sCACE,aAGF,0BACE,kBACA,SACA,gBACA,gCACA,yBACA,sCAGF,sBACE,kBAGF,6BACE,kBACA,WACA,WACA,YACA,yBACA,mBACA,qBACA,UACA,4CACA,qBACA,QACA,4BAGF,wCACE,WACA,SACA,4CAGF,yFAEE,6CAGF,+GAEE","file":"metisMenu.min.css"}
--------------------------------------------------------------------------------
/controllers/manager/invitation/invitation-validator.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const {body} = require('express-validator');
3 |
4 | exports.invitationValidator = [
5 | body('invitee')
6 | .exists().withMessage('invitee is required')
7 | .isObject().withMessage('invitee must be an object'),
8 | body('invitee.name').exists()
9 | .withMessage('name is required'),
10 | body('invitee.area')
11 | .exists().withMessage('Area a required')
12 | .isNumeric().withMessage('Area must be select')
13 |
14 | ];
15 |
16 |
--------------------------------------------------------------------------------
/public/assets/js/base/form.js:
--------------------------------------------------------------------------------
1 | const form = {
2 | serializeFormJSON: form => {
3 | var o = {};
4 | var a = form.serializeArray();
5 | $.each(a, function () {
6 | if (o[this.name]) {
7 | if (!o[this.name].push) {
8 | o[this.name] = [o[this.name]];
9 | }
10 | o[this.name].push(this.value || "");
11 | } else {
12 | o[this.name] = this.value || "";
13 | }
14 | });
15 | return o;
16 | }
17 | };
--------------------------------------------------------------------------------
/public/assets/js/base/validate.js:
--------------------------------------------------------------------------------
1 | const validator = {
2 | faIcon: {
3 | valid: 'fa fa-check-circle fa-lg text-success',
4 | invalid: 'fa fa-times-circle fa-lg',
5 | validating: 'fa fa-refresh'
6 | },
7 | valid: (formid, _fields, _callBack) => {
8 | $(`#${formid}`).bootstrapValidator({
9 | message: 'This value is not valid',
10 | excluded: [':disabled'],
11 | feedbackIcons: this.faIcon,
12 | fields: _fields
13 | }).on('success.form.bv', _callBack);
14 | }
15 | };
--------------------------------------------------------------------------------
/core/base-core.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const Util = require('../helpers/util');
4 | const TimeUtil = require('../helpers/time-util');
5 | const Constants = require('../helpers/constants');
6 | const sysConfig = require('../configs/system-configs');
7 | const log = sysConfig.log();
8 |
9 | class BaseCore {
10 |
11 | constructor() {
12 | this._config = sysConfig;
13 | this._util = Util;
14 | this._timeUtil = TimeUtil;
15 | this._constant = Constants;
16 | this._log = log;
17 | }
18 | }
19 |
20 | module.exports = BaseCore;
21 |
--------------------------------------------------------------------------------
/controllers/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const router = express.Router();
5 |
6 | /* GET home page. */
7 | router.get('/', (req, res) => {
8 | res.redirect("/invitation")
9 | });
10 |
11 | router.use('/invitation', require('./invitation/invitation-router'));
12 | router.use('/invocation', require('./invocation/invocation-router'));
13 |
14 | router.use('/bank', require('./bank/bank-router'));
15 |
16 | router.use('/manager', require('./manager'));
17 |
18 | router.use('/setup', require('./setup/setup-router'));
19 |
20 | module.exports = router;
21 |
--------------------------------------------------------------------------------
/helpers/constants.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | exports.ERROR_CODE = {
4 | CONTROLLER: '2000',
5 | FACADE: '2100',
6 | BUSINESS_COMPONENT: '2200',
7 | BUSINESS_ENTITIES: '2300',
8 | VALIDATOR: '3000',
9 | };
10 |
11 |
12 | exports.MONGODB = {
13 | INSTANCES: {
14 | ACCOUNT: 'account',
15 | INVITEE: 'invitee',
16 | INVOCATION: 'invocation',
17 | DATA_CONFIG: 'data_config'
18 | }
19 | };
20 |
21 |
22 | exports.AREA = {
23 | MALE: 1,
24 | FEMALE: 0
25 | };
26 |
27 | exports.MODE = {
28 | DEFAULT: 1,
29 | HAS_DATA: 2
30 | };
31 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | # Change these settings to your own preference
9 | indent_style = space
10 | indent_size = 4
11 |
12 | # We recommend you to keep these unchanged
13 | end_of_line = lf
14 | charset = utf-8
15 | trim_trailing_whitespace = true
16 | insert_final_newline = true
17 |
18 | [*.md]
19 | trim_trailing_whitespace = false
20 |
21 | [{package.json,bower.json}]
22 | indent_size = 2
23 |
--------------------------------------------------------------------------------
/public/plugins/datatables/autoFill.bootstrap4.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | Bootstrap integration for DataTables' AutoFill
3 | ©2015 SpryMedia Ltd - datatables.net/license
4 | */
5 | (function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs4","datatables.net-autofill"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,c){a||(a=window);c&&c.fn.dataTable||(c=require("datatables.net-bs4")(a,c).$);c.fn.dataTable.AutoFill||require("datatables.net-autofill")(a,c);return b(c,a,a.document)}:b(jQuery,window,document)})(function(b,a,c,d){b=b.fn.dataTable;b.AutoFill.classes.btn="btn btn-primary";return b});
6 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "zenorocha/clipboardjs",
3 | "description": "Modern copy to clipboard. No Flash. Just 3kb gzipped https://clipboardjs.com",
4 | "type": "component",
5 | "homepage": "https://clipboardjs.com/",
6 | "authors": [
7 | {
8 | "name": "Zeno Rocha",
9 | "homepage": "http://zenorocha.com/"
10 | }
11 | ],
12 | "require": {
13 | "oomphinc/composer-installers-extender": "*"
14 | },
15 | "extra": {
16 | "component": {
17 | "scripts": [
18 | "dist/clipboard.js"
19 | ],
20 | "files": [
21 | "dist/clipboard.min.js"
22 | ]
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/public/assets/css/img.view.css:
--------------------------------------------------------------------------------
1 | .img-preview-mask {
2 | width: 100%;
3 | height: 100%;
4 | position: fixed;
5 | top: 0;
6 | left: 0;
7 | z-index: 9998;
8 | background-color: rgba(0, 0, 0, 0.5);
9 | }
10 |
11 | .img-preview-popover {
12 | position: fixed;
13 | z-index: 9999;
14 | }
15 | .img-preview-foot {
16 | width: 96%;
17 | padding: 0 2%;
18 | position: absolute;
19 | bottom: 0;
20 | background-color: rgba(0, 0, 0, 0.5);
21 | }
22 |
23 | .img-foot-title {
24 | font-size: 16px;
25 | color: #fff;
26 | margin-top: 5px;
27 | }
28 |
29 | .img-foot-desc {
30 | font-size: 12px;
31 | color: #fff;
32 | margin-top: 5px;
33 | line-height: 24px;
34 | }
35 |
--------------------------------------------------------------------------------
/controllers/manager/invitation/invitation-router.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const express = require('express');
3 | const Controller = require('./invitation-controller');
4 | const validator = require('./invitation-validator');
5 |
6 | const controller = new Controller();
7 | const router = express.Router();
8 |
9 |
10 | //manager
11 | router.get('/', controller.list);
12 | router.get('/:id/detail', controller.detail);
13 |
14 | router.post('/create',
15 | validator.invitationValidator,
16 | controller.create);
17 |
18 | router.put('/update',
19 | validator.invitationValidator,
20 | controller.update);
21 |
22 | router.delete('/delete', controller.del);
23 |
24 |
25 | module.exports = router;
26 |
--------------------------------------------------------------------------------
/configs/mongo-db.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Import the mongoose module
4 | const mongoose = require('mongoose');
5 | const sysConfig = require('./system-configs');
6 | const log = sysConfig.log();
7 |
8 | // Get Mongoose to use the global promise library
9 | mongoose.Promise = global.Promise;
10 |
11 | // Connecting to the database
12 | mongoose.connect(sysConfig.uri, {
13 | useNewUrlParser: true,
14 | useUnifiedTopology: true,
15 | useFindAndModify: false,
16 | useCreateIndex: true,
17 | }).then(() => {
18 | log.info('Successfully connected to the mongodb database');
19 | }).catch(err => {
20 | log.info('Could not connect to the database. Exiting now...', err);
21 | process.exit();
22 | });
23 |
--------------------------------------------------------------------------------
/.github/workflows/quote_generator.yml:
--------------------------------------------------------------------------------
1 | name: quote_generator
2 |
3 | on:
4 | workflow_dispatch:
5 | schedule:
6 | - cron: "00 00 * * *"
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v2
14 | - uses: actions/setup-node@v1
15 | with:
16 | node-version: 12.21.0
17 | - run: npm ci
18 | - name: Generate quote
19 | run: npm run generate
20 | - name: Update README.md
21 | run: |
22 | git config --global user.email "minhphucpk.1997@gmail.com"
23 | git config --global user.name "dinhphuc"
24 | git add .
25 | git commit -m "Updated README.md" || echo "Random Quote to commit"
26 | git push
27 |
--------------------------------------------------------------------------------
/controllers/manager/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const router = express.Router();
5 |
6 | const auth = require('../../middlewares/authentication');
7 | /* GET login. */
8 | router.get('/', (req, res) => {
9 | if (req.session && req.session.user) {
10 | res.redirect('/manager/invitation');
11 | } else {
12 | return res.redirect('/manager/account/login');
13 | }
14 | });
15 |
16 | router.use('/invitation', auth.requiresLogin, require('./invitation/invitation-router'));
17 | router.use('/invocation', auth.requiresLogin, require('./invocation/invocation-router'));
18 | router.use('/account', require('./account/account-router'));
19 |
20 | module.exports = router;
21 |
--------------------------------------------------------------------------------
/controllers/invocation/invocation-validator.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 | const { body } = require('express-validator');
4 |
5 | exports.invocationValidator = [
6 | body('invocation')
7 | .exists().withMessage('invocation is required')
8 | .isObject().withMessage('invocation must be an object'),
9 | body('invocation.inviteeId').exists()
10 | .withMessage('name is required'),
11 | body('invocation.name').exists()
12 | .withMessage('Name a required'),
13 | body('invocation.phone').exists()
14 | .withMessage('Phone a required'),
15 | body('invocation.status').exists()
16 | .withMessage('Status a required')
17 | .isNumeric()
18 | .withMessage('Status must be select')
19 | ];
--------------------------------------------------------------------------------
/controllers/manager/invocation/invocation-validator.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 | const { body } = require('express-validator');
4 |
5 | exports.invocationValidator = [
6 | body('invocation')
7 | .exists().withMessage('invocation is required')
8 | .isObject().withMessage('invocation must be an object'),
9 | body('invocation.inviteeId').exists()
10 | .withMessage('name is required'),
11 | body('invocation.name').exists()
12 | .withMessage('Name a required'),
13 | body('invocation.phone').exists()
14 | .withMessage('Phone a required'),
15 | body('invocation.status').exists()
16 | .withMessage('Status a required')
17 | .isNumeric()
18 | .withMessage('Status must be select')
19 | ];
--------------------------------------------------------------------------------
/core/base-component.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const BaseCore = require('../core/base-core');
4 |
5 | class BaseComponent extends BaseCore {
6 |
7 | constructor() {
8 | super();
9 | }
10 |
11 | _handleResult(result, resolve) {
12 | return resolve(result);
13 | }
14 |
15 | _handleError(error, reject) {
16 | this._log.error(error);
17 |
18 | return reject(error);
19 | }
20 |
21 | _handleThrowError(error) {
22 | this._log.error(error);
23 | throw error;
24 | }
25 |
26 | _generateError(message) {
27 | const error = {code: this._constant.ERROR_CODE.BUSINESS_COMPONENT, message: message};
28 | return error;
29 | }
30 | }
31 |
32 | module.exports = BaseComponent;
--------------------------------------------------------------------------------
/business/entities/mongodb/account-entity.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const BaseEntityMongoDb = require('../../../core/base-entity-mongodb');
4 | const model = require('../../../helpers/constants').MONGODB.INSTANCES.ACCOUNT;
5 | const schema = require('../../../domains/mongodb/schemas').SCHEMAS.ACCOUNT;
6 |
7 | class AccountEntity extends BaseEntityMongoDb {
8 |
9 | constructor() {
10 | super(model, schema);
11 | }
12 |
13 |
14 | findOne(username, fieldObj = null) {
15 | return this._model.findOne({
16 | username: username
17 | }, fieldObj);
18 | }
19 |
20 | add(data) {
21 | let newObj = new this._model(data);
22 | return newObj.save();
23 | }
24 |
25 | }
26 |
27 | module.exports = AccountEntity;
28 |
--------------------------------------------------------------------------------
/controllers/invocation/invocation-router.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | const express = require("express");
3 | const Controller = require("./invocation-controller");
4 | const validator = require("./invocation-validator");
5 |
6 | const controller = new Controller();
7 | const router = express.Router();
8 |
9 | const recaptchaModel = require('express-recaptcha').RecaptchaV3;
10 | const recaptcha = new recaptchaModel(
11 | process.env.SITE_KEY,
12 | process.env.SECRET_KEY,
13 | {
14 | callback: 'cb',
15 | }
16 | );
17 | router.get('/:id', recaptcha.middleware.renderWith({hl: 'vi'}), controller.createInvocationRender);
18 | router.post('/',recaptcha.middleware.verify, validator.invocationValidator, controller.createInvocation);
19 |
20 | module.exports = router;
21 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 |
4 | # Number of days of inactivity before a stale issue is closed
5 | daysUntilClose: 7
6 |
7 | # Issues with these labels will never be considered stale
8 | exemptLabels:
9 | - pinned
10 |
11 | # Label to use when marking an issue as stale
12 | staleLabel: stale
13 |
14 | # Comment to post when marking an issue as stale. Set to `false` to disable
15 | markComment: >
16 | This issue has been automatically marked as stale because it has not had
17 | recent activity. It will be closed if no further activity occurs. Thank you
18 | for your contributions.
19 |
20 | # Comment to post when closing a stale issue. Set to `false` to disable
21 | closeComment: false
22 |
--------------------------------------------------------------------------------
/business/entities/mongodb/data-config-entity.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const BaseEntityMongoDb = require('../../../core/base-entity-mongodb');
4 | const model = require('../../../helpers/constants').MONGODB.INSTANCES.DATA_CONFIG;
5 | const schema = require('../../../domains/mongodb/schemas').SCHEMAS.DATA_CONFIG;
6 |
7 | class DataConfigEntity extends BaseEntityMongoDb {
8 |
9 | constructor() {
10 | super(model, schema);
11 | }
12 |
13 |
14 | getDefaultDataConfig(fieldObj = null) {
15 | return this._model.findOne({
16 | default: true
17 | }, fieldObj);
18 | }
19 |
20 | addDefaultDataConfig(data) {
21 | let newObj = new this._model(data);
22 | return newObj.save();
23 | }
24 | }
25 |
26 | module.exports = DataConfigEntity;
27 |
--------------------------------------------------------------------------------
/business/components/data-config/data-config-component.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseCore = require("../../../core/base-core");
4 | const DataConfigEntity = require("../../entities/mongodb/data-config-entity");
5 |
6 |
7 |
8 | class DataConfiComponent extends BaseCore {
9 | constructor() {
10 | super();
11 |
12 | this._dataConfigEntity = new DataConfigEntity;
13 | }
14 |
15 | async getDefaultDataConfig() {
16 |
17 | let configs = await this._dataConfigEntity.getDefaultDataConfig();
18 | return configs;
19 | }
20 |
21 | async addDefaultDataConfig(data) {
22 |
23 | let invitees = await this._dataConfigEntity.addDefaultDataConfig(data);
24 | return invitees;
25 | }
26 |
27 | }
28 |
29 | module.exports = DataConfiComponent;
30 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/demo/target-div.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | target-div
6 |
7 |
8 |
9 |
10 | hello
11 | Copy
12 |
13 |
14 |
15 |
16 |
17 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/karma.conf.js:
--------------------------------------------------------------------------------
1 | var webpackConfig = require('./webpack.config.js');
2 |
3 | module.exports = function (karma) {
4 | karma.set({
5 | plugins: ['karma-webpack', 'karma-chai', 'karma-sinon', 'karma-mocha', 'karma-chrome-launcher'],
6 |
7 | frameworks: ['chai', 'sinon', 'mocha'],
8 |
9 | files: [
10 | 'src/**/*.js',
11 | 'test/**/*.js',
12 | ],
13 |
14 | preprocessors: {
15 | 'src/**/*.js': ['webpack'],
16 | 'test/**/*.js': ['webpack']
17 | },
18 |
19 | webpack: {
20 | module: webpackConfig.module,
21 | plugins: webpackConfig.plugins
22 | },
23 |
24 | webpackMiddleware: {
25 | stats: 'errors-only'
26 | },
27 |
28 | browsers: ['ChromeHeadless']
29 | });
30 | };
31 |
--------------------------------------------------------------------------------
/helpers/time-util.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const sysConfig = require('../configs/system-configs');
4 | const log = sysConfig.log();
5 |
6 | class TimeUtil {
7 |
8 | constructor() {
9 | this._diffTime = 0;
10 | log.info('--------------- INIT TIME-UTIL CLASS ---------------');
11 | }
12 |
13 | setCurrentTime(serverTime) {
14 | let systemTime = new Date().getTime();
15 |
16 | this._diffTime = serverTime - systemTime;
17 | log.info(`systemTime: ${systemTime}, serverTime: ${serverTime}, diffTime: ${this._diffTime}`);
18 | }
19 |
20 | getCurrentTime() {
21 | let systemTime = new Date().getTime();
22 | let currentTime = systemTime + this._diffTime;
23 |
24 | log.info(`current time: ${currentTime}`);
25 |
26 | return currentTime;
27 | }
28 | }
29 |
30 | module.exports = new TimeUtil();
--------------------------------------------------------------------------------
/public/plugins/clipboard/demo/function-text.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | function-text
6 |
7 |
8 |
9 |
10 | Copy
11 |
12 |
13 |
14 |
15 |
16 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/demo/target-textarea.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | target-textarea
6 |
7 |
8 |
9 |
10 |
11 | Cut
12 |
13 |
14 |
15 |
16 |
17 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/demo/target-input.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | target-input
6 |
7 |
8 |
9 |
10 |
11 | Copy
12 |
13 |
14 |
15 |
16 |
17 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/demo/constructor-node.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | constructor-node
6 |
7 |
8 |
9 |
10 |
11 | Copy
12 |
13 |
14 |
15 |
16 |
17 |
18 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/controllers/manager/account/account-router.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const auth = require('../../../middlewares/authentication');
4 | const express = require("express");
5 | const Controller = require("./account-controller");
6 | const validator = require("./account-validator");
7 |
8 | const controller = new Controller();
9 | const router = express.Router();
10 |
11 | const recaptchaModel = require('express-recaptcha').RecaptchaV3;
12 |
13 | const recaptcha = new recaptchaModel(
14 | process.env.SITE_KEY,
15 | process.env.SECRET_KEY,
16 | {
17 | callback: 'cb',
18 | }
19 | );
20 |
21 |
22 | router.get("/login", recaptcha.middleware.renderWith({hl: 'vi'}), auth.requiresLogout, controller.loginRender);
23 | router.post("/login", recaptcha.middleware.verify, auth.requiresLogout, controller.login);
24 | router.get("/logout", auth.requiresLogin, controller.logout);
25 |
26 | module.exports = router;
27 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/demo/function-target.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | function-target
6 |
7 |
8 |
9 |
10 | Copy
11 | hello
12 |
13 |
14 |
15 |
16 |
17 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/public/plugins/datatables/buttons.bootstrap4.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | Bootstrap integration for DataTables' Buttons
3 | ©2016 SpryMedia Ltd - datatables.net/license
4 | */
5 | (function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs4","datatables.net-buttons"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net-bs4")(a,b).$;b.fn.dataTable.Buttons||require("datatables.net-buttons")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c){var a=c.fn.dataTable;c.extend(!0,a.Buttons.defaults,{dom:{container:{className:"dt-buttons btn-group"},
6 | button:{className:"btn btn-secondary"},collection:{tag:"div",className:"dt-button-collection dropdown-menu",button:{tag:"a",className:"dt-button dropdown-item",active:"active",disabled:"disabled"}}}});a.ext.buttons.collection.className+=" dropdown-toggle";return a.Buttons});
7 |
--------------------------------------------------------------------------------
/configs/system-configs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('dotenv').config();
4 | const bunyan = require('bunyan');
5 |
6 | const log = {
7 | development: () => {
8 | return bunyan.createLogger({name: 'development', level: 'debug'});
9 | },
10 | production: () => {
11 | return bunyan.createLogger({name: 'production', level: 'info'});
12 | },
13 | test: () => {
14 | return bunyan.createLogger({name: 'test', level: 'fatal'});
15 | }
16 | };
17 |
18 | module.exports = {
19 | name: process.env.NAME,
20 | siteKey: process.env.SITE_KEY,
21 | secretKey: process.env.SECRET_KEY,
22 | uri: process.env.URI_MONGO,
23 | domain: process.env.DOMAIN,
24 | bodyParserUrlencodedLimit: process.env.BODY_PARSER_URLENCODED_LIMIT,
25 | bodyParserJsonLimit: process.env.BODY_PARSER_JSON_LIMIT,
26 | log: (env) => {
27 | if (env) return log[env]();
28 | return log['development']();
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/demo/constructor-selector.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | constructor-selector
6 |
7 |
8 |
9 |
10 | Copy
11 | Copy
12 | Copy
13 |
14 |
15 |
16 |
17 |
18 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/demo/constructor-nodelist.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | constructor-nodelist
6 |
7 |
8 |
9 |
10 | Copy
11 | Copy
12 | Copy
13 |
14 |
15 |
16 |
17 |
18 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/business/entities/mongodb/invitee-entity.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const BaseEntityMongoDb = require('../../../core/base-entity-mongodb');
4 | const model = require('../../../helpers/constants').MONGODB.INSTANCES.INVITEE;
5 | const schema = require('../../../domains/mongodb/schemas').SCHEMAS.INVITEE;
6 |
7 | class AccountEntity extends BaseEntityMongoDb {
8 |
9 | constructor() {
10 | super(model, schema);
11 | }
12 |
13 | list() {
14 | return this._model.find({}).sort([['_id', -1]]);
15 |
16 | }
17 |
18 | findById(id) {
19 | return this._model.findById(id);
20 | }
21 |
22 | add(data) {
23 | let newObj = new this._model(data);
24 | return newObj.save();
25 | }
26 |
27 | remove(id) {
28 | return this._model.remove({ _id: id });
29 | }
30 |
31 | update(id, fieldObj) {
32 | return this._model.findByIdAndUpdate(id, {
33 | '$set': fieldObj
34 | }, { upsert: true });
35 | }
36 |
37 | }
38 |
39 | module.exports = AccountEntity;
40 |
--------------------------------------------------------------------------------
/business/entities/mongodb/invocation-entity.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const BaseEntityMongoDb = require('../../../core/base-entity-mongodb');
4 | const model = require('../../../helpers/constants').MONGODB.INSTANCES.INVOCATION;
5 | const schema = require('../../../domains/mongodb/schemas').SCHEMAS.INVOCATION;
6 |
7 | class InvocationEntity extends BaseEntityMongoDb {
8 |
9 | constructor() {
10 | super(model, schema);
11 | }
12 |
13 | list() {
14 | return this._model.find({}).sort([['_id', -1]]);
15 | }
16 |
17 | findById(id) {
18 | return this._model.findById(id);
19 | }
20 |
21 | add(data) {
22 | let newObj = new this._model(data);
23 | return newObj.save();
24 | }
25 |
26 | remove(id) {
27 | return this._model.remove({ _id: id });
28 | }
29 |
30 | update(id, fieldObj) {
31 | return this._model.findByIdAndUpdate(id, {
32 | '$set': fieldObj
33 | }, { upsert: true });
34 | }
35 |
36 | }
37 |
38 | module.exports = InvocationEntity;
39 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const axios = require("axios");
2 | const fs = require("fs");
3 |
4 | const getQuote = async () => {
5 | try {
6 | const { data } = await axios.get("https://api.goprogram.ai/inspiration");
7 | const quote = data.quote;
8 | const author = data.author;
9 |
10 | console.log("new quote", `"${quote}"`);
11 |
12 | return {
13 | quote,
14 | author,
15 | };
16 | } catch (err) {
17 | console.error(err.message);
18 | return {};
19 | }
20 | };
21 |
22 | const generate = async () => {
23 | const { quote, author } = await getQuote();
24 |
25 | if (!quote) return;
26 |
27 | const content = fs.readFileSync("README.md", "utf8");
28 |
29 | const lastIndex = content.indexOf("⚡");
30 | if (lastIndex !== -1) {
31 | let subContent = content.substring(0, lastIndex);
32 | subContent += `⚡ Quote: \n**${quote}**\n\n${author}`
33 | fs.writeFileSync("README.md", subContent);
34 | return;
35 | }
36 |
37 | fs.appendFileSync("README.md", `⚡ Quote: \n**${quote}**\n\n${author}`);
38 | };
39 |
40 | generate();
41 |
--------------------------------------------------------------------------------
/public/assets/js/base/notify.js:
--------------------------------------------------------------------------------
1 | const notify = {
2 | EType: {
3 | SUCCESS: 'success',
4 | DANGER: 'danger',
5 | WARNING: 'warning'
6 | },
7 | push: (messenger, type) => {
8 | let icon;
9 | switch (type) {
10 | case notify.EType.SUCCESS:
11 | toastr.success(messenger);
12 | break;
13 | case notify.EType.DANGER:
14 | toastr.error(messenger);
15 | break;
16 | default:
17 | icon = 'fa fa-check';
18 | break;
19 | }
20 |
21 | },
22 | loading: () => {
23 | let html =
24 | ``;
28 | $('body').append(html);
29 | },
30 | done: () => {
31 | $('#loading').remove();
32 | }
33 | };
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 sauanla
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Zeno Rocha
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/views/share/side-menu.ejs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/controllers/bank/bank-controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseController = require("../../core/base-controller");
4 | const { AREA, MODE } = require("../../helpers/constants");
5 |
6 |
7 | class BankController extends BaseController {
8 |
9 | constructor() {
10 | super();
11 | this.bankPage = this.bankPage.bind(this);
12 | }
13 |
14 |
15 | async bankPage(req, res) {
16 |
17 | try {
18 | let config = await this._facade.getDefaultDataConfig();
19 |
20 | if (!config) {
21 | return res.render('err/occurs-error', {
22 | layout: false,
23 | err: "could not load default data"
24 | });
25 | }
26 |
27 | res.render('invitation/bank', {
28 | layout: false,
29 | data: {
30 | cfg: config
31 | },
32 | });
33 | } catch (error) {
34 | res.render('err/occurs-error', {
35 | layout: false,
36 | err: error
37 | });
38 | }
39 | }
40 | }
41 |
42 | module.exports = BankController;
43 |
--------------------------------------------------------------------------------
/business/components/auth/auth-component.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseCore = require("../core/base-core");
4 | let jwt = require("jsonwebtoken");
5 |
6 | class AuthComponent extends BaseCore {
7 | constructor() {
8 | super();
9 | }
10 |
11 | verifyAccountToken(token) {
12 | if (token) {
13 | if (token.startsWith("Bearer ")) {
14 | // Remove Bearer from string
15 | token = token.slice(7, token.length);
16 | }
17 |
18 | jwt.verify(token, process.env.SECRET_KEY, (err, decoded) => {
19 | if (err) {
20 | return {
21 | success: false,
22 | message: "Token is not valid",
23 | };
24 | } else {
25 | return {
26 | success: true,
27 | data: decoded
28 | };
29 | }
30 | });
31 | } else {
32 | return {
33 | success: false,
34 | message: "Auth token is not supplied",
35 | };
36 | }
37 | }
38 | }
39 |
40 | module.exports = AuthComponent;
41 |
--------------------------------------------------------------------------------
/public/plugins/datatables/responsive.bootstrap4.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | Bootstrap 4 integration for DataTables' Responsive
3 | ©2016 SpryMedia Ltd - datatables.net/license
4 | */
5 | (function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs4","datatables.net-responsive"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net-bs4")(a,b).$;b.fn.dataTable.Responsive||require("datatables.net-responsive")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c){var a=c.fn.dataTable,b=a.Responsive.display,g=b.modal,e=c('');
6 | b.modal=function(a){return function(b,d,f){if(c.fn.modal){if(!d){if(a&&a.header){var d=e.find("div.modal-header"),h=d.find("button").detach();d.empty().append(''+a.header(b)+" ").append(h)}e.find("div.modal-body").empty().append(f());e.appendTo("body").modal()}}else g(b,d,f)}};return a.Responsive});
7 |
--------------------------------------------------------------------------------
/core/base-controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const BaseCore = require('../core/base-core');
4 | const HandleResult = require('../domains/handleResult');
5 | const Facade = require('../business/facade/facade');
6 | const {validationResult} = require('express-validator');
7 |
8 | class BaseController extends BaseCore {
9 |
10 | constructor() {
11 | super();
12 | this._facade = new Facade();
13 | }
14 |
15 | _handleResult(result, res) {
16 | res.send(new HandleResult(true, result));
17 | }
18 |
19 | _handleError(error, res) {
20 | this._log.error(error);
21 |
22 | res.send(new HandleResult(false, null, [{
23 | code: error.code || this._constant.ERROR_CODE.CONTROLLER,
24 | text: error.message || error
25 | }]));
26 | }
27 |
28 | _handleValidationResult(req, res) {
29 | const errors = validationResult(req);
30 |
31 | if (!errors.isEmpty()) {
32 | const errArr = errors.array().map(error => {
33 | return {code: this._constant.VALIDATOR, text: error.msg};
34 | });
35 |
36 | res.send(new HandleResult(false, null, errArr));
37 |
38 | return errArr;
39 | }
40 |
41 | return null;
42 | }
43 | }
44 |
45 | module.exports = BaseController;
--------------------------------------------------------------------------------
/controllers/setup/setup-controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseController = require("../../core/base-controller");
4 | const SeeDB = require("../../domains/mongodb/seed-db");
5 |
6 |
7 | class SetupController extends BaseController {
8 |
9 | constructor() {
10 | super();
11 | this.setupPage = this.setupPage.bind(this);
12 | }
13 |
14 | async setupPage(req, res) {
15 | try {
16 | let config = await this._facade.getDefaultDataConfig();
17 | if (!config) { // neu bang null == chua co du lieu
18 | let configInput = SeeDB.dataConfig;
19 | await this._facade.addDefaultDataConfig(configInput);
20 | // them user
21 |
22 | let userInput = SeeDB.user;
23 | await this._facade.addAccount(userInput);
24 |
25 | return res.redirect("/invitation")
26 | }else {
27 | let userInput = SeeDB.user;
28 | await this._facade.addAccount(userInput);
29 | }
30 | return res.redirect("/invitation")
31 | } catch (error) {
32 | res.render('err/occurs-error', {
33 | layout: false,
34 | err: error
35 | });
36 | }
37 | }
38 | }
39 |
40 | module.exports = SetupController;
41 |
--------------------------------------------------------------------------------
/public/assets/js/live/account/account.action.js:
--------------------------------------------------------------------------------
1 | function login() {
2 | notify.loading();
3 | $.ajax({
4 | type: 'POST',
5 | url: '/manager/account/login',
6 | dataType: 'json',
7 | data: {
8 | username: $('#username').val(),
9 | password: $('#password').val(),
10 | 'g-recaptcha-response': $('#recaptcha').val(),
11 | },
12 | success: function (response) {
13 | if (response.success) {
14 | notify.push("Login success", notify.EType.SUCCESS);
15 | var rtUrl = $('#rtUrl').val();
16 | if (rtUrl === '' || rtUrl === undefined) {
17 | rtUrl = '/manager/invitation';
18 | }
19 | setTimeout(function () {
20 | window.location.href = rtUrl;
21 | }, 1000);
22 | } else {
23 | notify.done();
24 | notify.push(response.messageList[0].text, notify.EType.DANGER);
25 | }
26 | },
27 | error: (jqXHR, textStatus) => {
28 | let mess = 'Request failed: ' + textStatus;
29 | notify.done();
30 | notify.push(mess, notify.EType.DANGER);
31 | },
32 | });
33 | }
34 |
35 | $(document).ready(function () {
36 | $('input').keypress(function (e) {
37 | if (e.which === 13) {
38 | e.preventDefault();
39 | login();
40 | return false;
41 | }
42 | });
43 | $('#btnLogin').click(function (e) {
44 | e.preventDefault();
45 | login();
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/public/assets/js/live/login.admin.js:
--------------------------------------------------------------------------------
1 | function login() {
2 | notify.loading();
3 | $.ajax({
4 | type: 'POST',
5 | url: '/admin/login/checkLogin',
6 | dataType: 'json',
7 | data: { userName: $('#Username').val(), passWord: $('#Password').val() },
8 | success: function (response) {
9 | if (response.status) {
10 | notify.push(response.mess, notify.EType.SUCCESS);
11 | var rtUrl = $('#rtUrl').val();
12 | if (rtUrl === "" || rtUrl === undefined) {
13 | rtUrl = "/Admin";
14 | }
15 | setTimeout(function () {
16 | window.location.href = rtUrl;
17 | }, 3000);
18 | } else {
19 | notify.done();
20 | notify.push(response.mess, notify.EType.DANGER);
21 | }
22 | },
23 | error: (jqXHR, textStatus) => {
24 | let mess = "Request failed: " + textStatus;
25 | notify.done();
26 | notify.push(mess, notify.EType.DANGER);
27 | }
28 | });
29 | };
30 | $(document).ready(function () {
31 | $('input').keypress(function (e) {
32 | if (e.which === 13) {
33 | e.preventDefault();
34 | login();
35 | return false;
36 | }
37 | });
38 | $('#btnLogin').click(function (e) {
39 | e.preventDefault();
40 | login();
41 | });
42 | });
--------------------------------------------------------------------------------
/controllers/manager/invocation/invocation-controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseController = require("../../../core/base-controller");
4 |
5 | class InvocationController extends BaseController {
6 |
7 | constructor() {
8 | super();
9 |
10 | this.listInvocationRender = this.listInvocationRender.bind(this);
11 | this.deleteInvocation = this.deleteInvocation.bind(this);
12 |
13 | }
14 | async listInvocationRender(req, res) {
15 | try {
16 | let invocations = await this._facade.getListInvocation();
17 |
18 | res.render('manager/invocation/index', {
19 | invocations
20 | });
21 |
22 | } catch (error) {
23 | res.render('err/occurs-error', {
24 | layout: false,
25 | err: error
26 | });
27 | }
28 | }
29 |
30 | async deleteInvocation(req, res) {
31 |
32 | const id = req.body.id;
33 | try {
34 |
35 | const invocation = await this._facade.getDetailInvocation(id);
36 |
37 | if(!invocation){
38 | return this._handleError('invocation does not exist', res);
39 | }
40 |
41 | let data = await this._facade.delInvocation(id);
42 | this._handleResult(data, res);
43 | } catch (error) {
44 | this._handleError(error.message, res);
45 | }
46 |
47 | }
48 | }
49 |
50 | module.exports = InvocationController;
51 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/webpack.config.js:
--------------------------------------------------------------------------------
1 | const pkg = require('./package.json');
2 | const path = require('path');
3 | const webpack = require('webpack');
4 | const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
5 |
6 | const production = process.env.NODE_ENV === 'production' || false;
7 |
8 | const banner = `clipboard.js v${pkg.version}
9 | https://clipboardjs.com/
10 |
11 | Licensed MIT © Zeno Rocha`;
12 |
13 | module.exports = {
14 | entry: './src/clipboard.js',
15 | mode: 'production',
16 | output: {
17 | filename: production ? 'clipboard.min.js' : 'clipboard.js',
18 | path: path.resolve(__dirname, 'dist'),
19 | library: 'ClipboardJS',
20 | globalObject: 'this',
21 | libraryExport: 'default',
22 | libraryTarget: 'umd'
23 | },
24 | module: {
25 | rules: [
26 | {test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'}
27 | ]
28 | },
29 | optimization: {
30 | minimize: production,
31 | minimizer: [
32 | new UglifyJSPlugin({
33 | parallel: require('os').cpus().length,
34 | uglifyOptions: {
35 | ie8: false,
36 | keep_fnames: false,
37 | output: {
38 | beautify: false,
39 | comments: (node, {value, type}) => type == 'comment2' && value.startsWith('!')
40 | }
41 | }
42 | })
43 | ]
44 | },
45 | plugins: [new webpack.BannerPlugin({ banner })]
46 | };
47 |
--------------------------------------------------------------------------------
/public/assets/js/live/chart.statistical.js:
--------------------------------------------------------------------------------
1 | const chart = {
2 | initChart: function (data, el, elLegend, labels, lineColors) {
3 | var chart = Morris.Area({
4 | element: el,
5 | data: data,
6 | gridEnabled: true,
7 | gridLineColor: 'rgba(0,0,0,.1)',
8 | gridTextColor: '#8f9ea6',
9 | gridTextSize: '11px',
10 | behaveLikeLine: true,
11 | smooth: true,
12 | xkey: 'month',
13 | ykeys: ['count'],
14 | labels: labels,
15 | lineColors: lineColors,
16 | pointSize: 0,
17 | pointStrokeColors: ['#045d97'],
18 | lineWidth: 0,
19 | resize: true,
20 | hideHover: 'auto',
21 | fillOpacity: 0.9,
22 | parseTime: false
23 | });
24 |
25 | chart.options.labels.forEach(function (label, i) {
26 | const legendItem = $("
").text(label);
27 | $(" ").css("background-color", chart.options.lineColors[i]).prependTo(legendItem);
28 | $(`#${elLegend}`).append(legendItem);
29 | });
30 | },
31 | initChartDoughnut: function (data, el) {
32 | Morris.Donut({
33 | element: el,
34 | data: data,
35 | colors: [
36 | '#ec407a',
37 | '#03a9f4',
38 | '#498aad',
39 | '#c6af5b',
40 | '#cc633b'
41 | ],
42 | resize: true
43 | });
44 | }
45 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wedding-invitation",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "generate": "node index.js",
7 | "test": "snyk test && nyc mocha --recursive test",
8 | "start": "node ./bin/www | \"node_modules/.bin/bunyan\"",
9 | "dev": "nodemon ./bin/www | \"node_modules/.bin/bunyan\"",
10 | "start-win": "TITLE Wedding Invitation && node ./bin/www | \"node_modules/.bin/bunyan\"",
11 | "heroku-start": "node ./bin/www"
12 | },
13 | "author": "sauanla",
14 | "license": "MIT",
15 | "dependencies": {
16 | "axios": "^0.21.1",
17 | "bcrypt": "^5.0.0",
18 | "body-parser": "^1.19.0",
19 | "bunyan": "^1.8.12",
20 | "connect-mongo": "^3.2.0",
21 | "connect-timeout": "^1.9.0",
22 | "cookie-parser": "~1.4.3",
23 | "debug": "~2.6.3",
24 | "dotenv": "^8.2.0",
25 | "ejs": "^2.7.1",
26 | "express": "^4.16.0",
27 | "express-ejs-layouts": "^2.5.0",
28 | "express-recaptcha": "^5.0.2",
29 | "express-session": "^1.17.1",
30 | "express-validator": "^6.0.0",
31 | "fs": "^0.0.1-security",
32 | "jsonwebtoken": "^8.5.1",
33 | "moment": "^2.29.1",
34 | "mongoose": "^5.9.27",
35 | "morgan": "^1.10.0",
36 | "request": "^2.88.0",
37 | "serve-favicon": "~2.4.2",
38 | "session": "^0.1.0",
39 | "uuid": "^3.1.0",
40 | "validator": "^13.5.2"
41 | },
42 | "devDependencies": {
43 | "babel-eslint": "^8.2.1",
44 | "eslint": "^4.11.0",
45 | "mocha": "^4.0.1",
46 | "nyc": "^11.3.0",
47 | "should": "^13.1.3",
48 | "snyk": "^1.50.0",
49 | "supertest": "^3.0.0"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/public/plugins/datatables/buttons.print.min.js:
--------------------------------------------------------------------------------
1 | (function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(c){return d(c,window,document)}):"object"===typeof exports?module.exports=function(c,a){c||(c=window);if(!a||!a.fn.dataTable)a=require("datatables.net")(c,a).$;a.fn.dataTable.Buttons||require("datatables.net-buttons")(c,a);return d(a,c,c.document)}:d(jQuery,window,document)})(function(d,c,a){var h=d.fn.dataTable,f=a.createElement("a");h.ext.buttons.print={className:"buttons-print",
2 | text:function(d){return d.i18n("buttons.print","Print")},action:function(a,b,i,e){a=b.buttons.exportData(e.exportOptions);i=function(a,b){for(var d="",c=0,e=a.length;c"+a[c]+""+b+">";return d+" "};b='';e.header&&(b+=""+i(a.header,"th")+" ");for(var b=b+"",j=0,h=a.body.length;j";e.footer&&(b+=""+i(a.footer,"th")+" ");var g=c.open("",""),a=e.title.replace("*",
3 | d("title").text());g.document.close();var k=""+a+" ";d("style, link").each(function(){var a=k,b=d(this).clone()[0],c;"link"===b.nodeName.toLowerCase()&&(f.href=b.href,c=f.host,-1===c.indexOf("/")&&0!==f.pathname.indexOf("/")&&(c+="/"),b.href=f.protocol+"//"+c+f.pathname+f.search);k=a+b.outerHTML});d(g.document.head).html(k);d(g.document.body).html(""+a+" "+e.message+"
"+b);e.customize&&e.customize(g);setTimeout(function(){e.autoPrint&&(g.print(),g.close())},250)},title:"*",
4 | message:"",exportOptions:{},header:!0,footer:!1,autoPrint:!0,customize:null};return h.Buttons});
5 |
--------------------------------------------------------------------------------
/public/assets/js/live/invocation/action.js:
--------------------------------------------------------------------------------
1 | function sendResponse() {
2 | const invocation = {
3 | name: $('#txtName').val(),
4 | inviteeId: $('#txtId').val(),
5 | message: $('#txtMessage').val(),
6 | phone: $('#txtPhone').val(),
7 | status: $('#slStatus').val(),
8 | };
9 | notify.loading();
10 | $.ajax({
11 | type: 'POST',
12 | url: '/invocation',
13 | data: {
14 | invocation: invocation,
15 | 'g-recaptcha-response': $('#recaptcha').val(),
16 | },
17 | success: function (response) {
18 | if (response.success) {
19 | notify.push('Success', notify.EType.SUCCESS);
20 |
21 | setTimeout(function () {
22 | window.location.href = '/invitation/'+ response.data.id;
23 | }, 2000);
24 | } else {
25 | notify.done();
26 | const msg = (response.messageList && response.messageList.length > 0) ? response.messageList[0].text: "Erros";
27 | notify.push(msg, notify.EType.DANGER);
28 | }
29 | },
30 | error: (request, jqXHR, textStatus) => {
31 | let mess = 'Request failed: ' + textStatus;
32 | notify.done();
33 | notify.push(request.responseJSON.error, notify.EType.DANGER);
34 | },
35 | });
36 | }
37 |
38 | $(document).ready(function () {
39 | $('input').keypress(function (e) {
40 | if (e.which === 13) {
41 | e.preventDefault();
42 | sendResponse();
43 | return false;
44 | }
45 | });
46 | $('#btnSend').click(function (e) {
47 | e.preventDefault();
48 | sendResponse();
49 | });
50 | });
51 |
52 | function onSubmit(token) {
53 | document.getElementById("frmSendRp").submit();
54 | }
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const express = require('express');
4 | const path = require('path');
5 | const logger = require('morgan');
6 | const cookieParser = require('cookie-parser');
7 | const bodyParser = require('body-parser');
8 | const config = require('./configs/system-configs');
9 | const timeout = require('connect-timeout'); //express v4
10 | const expressLayouts = require('express-ejs-layouts');
11 | const session = require('express-session');
12 |
13 | const app = express();
14 |
15 | require('./configs/mongo-db');
16 |
17 | // view engine setup
18 |
19 | app.use(express.static(__dirname + '/public'));
20 | app.use(timeout(120000));
21 | app.use(expressLayouts);
22 | app.set('view engine', 'ejs');
23 | app.set('views', './views');
24 | app.set('layout extractScripts', true);
25 |
26 | app.use(logger('dev', {}));
27 |
28 | app.use(bodyParser.urlencoded({ extended: true, limit: config.bodyParserUrlencodedLimit }));
29 | app.use(bodyParser.json({ limit: config.bodyParserJsonLimit }));
30 |
31 | app.use(cookieParser());
32 | app.use(express.static(path.join(__dirname, 'public')));
33 |
34 | app.use(
35 | session({
36 | secret: 'work hard',
37 | resave: true,
38 | saveUninitialized: false
39 | })
40 | );
41 |
42 | app.use('/', require('./controllers'));
43 |
44 | // catch 404 and forward to error handler
45 |
46 | app.use('*', function (req, res) {
47 | res.render('err/e404', {
48 | layout: false,
49 | });
50 | });
51 |
52 |
53 | // error handler
54 | app.use((err, req, res) => {
55 | // set locals, only providing error in development
56 | res.locals.message = err.message;
57 | res.locals.error = req.app.get('env') === 'development' ? err : {};
58 |
59 | // render the error page
60 | res.status(err.status || 500);
61 | res.render('error');
62 | });
63 |
64 |
65 | module.exports = app;
66 |
--------------------------------------------------------------------------------
/public/assets/js/base/ajax.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 |
4 | const ajax = {
5 | createOrUpdate: (_url, _data, _successCallBack, _errorCallBack) => {
6 | $.ajax({
7 | type: 'POST',
8 | url: _url,
9 | dataType: 'json',
10 | data: _data,
11 | success: _successCallBack,
12 | error: _errorCallBack,
13 | cache: false,
14 | contentType: false,
15 | processData: false
16 | });
17 | },
18 | createOrUpdateByJson: (_url, _data, _successCallBack, _errorCallBack) => {
19 | $.ajax({
20 | type: 'POST',
21 | url: _url,
22 | dataType: 'json',
23 | data: _data,
24 | contentType: "application/json; charset=utf-8",
25 | success: _successCallBack,
26 | error: _errorCallBack,
27 | cache: false
28 | });
29 | },
30 | get: (_url, _data, _successCallBack, _errorCallBack) => {
31 | $.ajax({
32 | type: 'GET',
33 | url: _url,
34 | dataType: 'json',
35 | data: _data,
36 | success: _successCallBack,
37 | error: _errorCallBack
38 | });
39 | },
40 | post: (_url, _data, _successCallBack, _errorCallBack) => {
41 | $.ajax({
42 | type: 'POST',
43 | url: _url,
44 | dataType: 'json',
45 | data: _data,
46 | success: _successCallBack,
47 | error: _errorCallBack
48 | });
49 | },
50 | del: (_url, _data, _successCallBack, _errorCallBack) => {
51 | $.ajax({
52 | type: 'POST',
53 | url: _url,
54 | dataType: 'json',
55 | data: _data,
56 | success: _successCallBack,
57 | error: _errorCallBack
58 | });
59 | }
60 | };
61 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing guide
2 |
3 | Want to contribute to Clipboard.js? Awesome!
4 | There are many ways you can contribute, see below.
5 |
6 | ## Opening issues
7 |
8 | Open an issue to report bugs or to propose new features.
9 |
10 | - Reporting bugs: describe the bug as clearly as you can, including steps to reproduce, what happened and what you were expecting to happen. Also include browser version, OS and other related software's (npm, Node.js, etc) versions when applicable.
11 |
12 | - Proposing features: explain the proposed feature, what it should do, why it is useful, how users should use it. Give us as much info as possible so it will be easier to discuss, access and implement the proposed feature. When you're unsure about a certain aspect of the feature, feel free to leave it open for others to discuss and find an appropriate solution.
13 |
14 | ## Proposing pull requests
15 |
16 | Pull requests are very welcome. Note that if you are going to propose drastic changes, be sure to open an issue for discussion first, to make sure that your PR will be accepted before you spend effort coding it.
17 |
18 | Fork the Clipboard.js repository, clone it locally and create a branch for your proposed bug fix or new feature. Avoid working directly on the master branch.
19 |
20 | Implement your bug fix or feature, write tests to cover it and make sure all tests are passing (run a final `npm test` to make sure everything is correct). Then commit your changes, push your bug fix/feature branch to the origin (your forked repo) and open a pull request to the upstream (the repository you originally forked)'s master branch.
21 |
22 | ## Documentation
23 |
24 | Documentation is extremely important and takes a fair deal of time and effort to write and keep updated. Please submit any and all improvements you can make to the repository's docs.
25 |
26 | ## Known issues
27 | If you're using npm@3 you'll probably face some issues related to peerDependencies.
28 | https://github.com/npm/npm/issues/9204
29 |
--------------------------------------------------------------------------------
/public/plugins/datatables/dataTables.bootstrap4.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | DataTables Bootstrap 4 integration
3 | ©2011-2017 SpryMedia Ltd - datatables.net/license
4 | */
5 | (function(b){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(a){return b(a,window,document)}):"object"===typeof exports?module.exports=function(a,d){a||(a=window);if(!d||!d.fn.dataTable)d=require("datatables.net")(a,d).$;return b(d,a,a.document)}:b(jQuery,window,document)})(function(b,a,d,m){var f=b.fn.dataTable;b.extend(!0,f.defaults,{dom:"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
6 | renderer:"bootstrap"});b.extend(f.ext.classes,{sWrapper:"dataTables_wrapper dt-bootstrap4",sFilterInput:"form-control form-control-sm",sLengthSelect:"custom-select custom-select-sm form-control form-control-sm",sProcessing:"dataTables_processing card",sPageButton:"paginate_button page-item"});f.ext.renderer.pageButton.bootstrap=function(a,h,r,s,j,n){var o=new f.Api(a),t=a.oClasses,k=a.oLanguage.oPaginate,u=a.oLanguage.oAria.paginate||{},e,g,p=0,q=function(d,f){var l,h,i,c,m=function(a){a.preventDefault();
7 | !b(a.currentTarget).hasClass("disabled")&&o.page()!=a.data.action&&o.page(a.data.action).draw("page")};l=0;for(h=f.length;l",
8 | {"class":t.sPageButton+" "+g,id:0===r&&"string"===typeof c?a.sTableId+"_"+c:null}).append(b("",{href:"#","aria-controls":a.sTableId,"aria-label":u[c],"data-dt-idx":p,tabindex:a.iTabIndex,"class":"page-link"}).html(e)).appendTo(d),a.oApi._fnBindAction(i,{action:c},m),p++)}},i;try{i=b(h).find(d.activeElement).data("dt-idx")}catch(v){}q(b(h).empty().html('').children("ul"),s);i!==m&&b(h).find("[data-dt-idx="+i+"]").focus()};return f});
9 |
--------------------------------------------------------------------------------
/controllers/invocation/invocation-controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseController = require("../../core/base-controller");
4 |
5 | class InvocationController extends BaseController {
6 |
7 | constructor() {
8 | super();
9 |
10 | this.createInvocationRender = this.createInvocationRender.bind(this);
11 | this.createInvocation = this.createInvocation.bind(this);
12 |
13 | }
14 | async createInvocationRender(req, res) {
15 | const id = req.params.id.trim();
16 | try {
17 | let invitee = await this._facade.getDetailInvitee(id);
18 |
19 | if (!invitee) {
20 | return res.render('err/e404', {
21 | layout: false,
22 | });
23 | }
24 |
25 | res.render('invocation/create', {
26 | layout: false,
27 | captcha: res.recaptcha,
28 | invitee: invitee,
29 | });
30 |
31 | } catch (error) {
32 | res.render('err/occurs-error', {
33 | layout: false,
34 | err: error
35 | });
36 | }
37 | }
38 | async createInvocation(req, res) {
39 | try {
40 | if (!req.recaptcha.error) {
41 |
42 | if (this._handleValidationResult(req, res)){
43 | return false;
44 | }
45 |
46 | const invocation = req.body.invocation;
47 | if (invocation) {
48 | let result = await this._facade.addInvocation(invocation);
49 | this._handleResult({
50 | id: invocation.inviteeId
51 | }, res);
52 | }else{
53 | this._handleError('Invalid data', res);
54 | }
55 | } else {
56 | this._handleError('Please valid reCaptcha', res);
57 | }
58 | } catch (error) {
59 | this._handleError(error, res);
60 | }
61 | }
62 | }
63 |
64 | module.exports = InvocationController;
65 |
--------------------------------------------------------------------------------
/controllers/manager/account/account-controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseController = require("../../../core/base-controller");
4 |
5 |
6 | const validator = require('validator');
7 |
8 |
9 | class AccountController extends BaseController {
10 |
11 | constructor() {
12 | super();
13 |
14 | this.loginRender = this.loginRender.bind(this);
15 | this.login = this.login.bind(this);
16 |
17 | }
18 |
19 |
20 | async loginRender(req, res) {
21 | res.render('manager/account/login', {
22 | layout: false,
23 | captcha: res.recaptcha
24 | });
25 | }
26 |
27 | async login(req, res) {
28 |
29 | try {
30 | if (!req.recaptcha.error) {
31 |
32 | let param = {
33 | username: req.body.username,
34 | password: req.body.password
35 | };
36 |
37 | let result = await this._facade.verifyAccount(param);
38 |
39 | let user = {
40 | email: result.user.email,
41 | username: result.user.username,
42 | }
43 |
44 | req.session.user = user;
45 |
46 | if (!result || !result.status) {
47 | this._handleError({
48 | code: 401,
49 | text: result.message
50 | }, res);
51 | }
52 |
53 | this._handleResult(user, res);
54 | } else {
55 | this._handleError('Please valid reCaptcha', res);
56 | }
57 | } catch (e) {
58 | this._handleError(e, res);
59 | }
60 | }
61 |
62 | async logout(req, res) {
63 | if (req.session) {
64 | // delete session object
65 | req.session.destroy(function (err) {
66 | if (err) {
67 | return res.json({ err });
68 | } else {
69 | return res.json({ logout: 'Success' });
70 | }
71 | });
72 | }
73 | }
74 | }
75 |
76 | module.exports = AccountController;
77 |
--------------------------------------------------------------------------------
/public/assets/css/metismenu.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * metismenu https://github.com/onokumus/metismenu#readme
3 | * A jQuery menu plugin
4 | * @version 3.0.4
5 | * @author Osman Nuri Okumus (https://github.com/onokumus)
6 | * @license: MIT
7 | */.metismenu .arrow{float:right;line-height:1.42857}[dir=rtl] .metismenu .arrow{float:left}.metismenu .glyphicon.arrow:before{content:"\e079"}.metismenu .mm-active>a>.glyphicon.arrow:before{content:"\e114"}.metismenu .fa.arrow:before{content:"\f104"}.metismenu .mm-active>a>.fa.arrow:before{content:"\f107"}.metismenu .ion.arrow:before{content:"\f3d2"}.metismenu .mm-active>a>.ion.arrow:before{content:"\f3d0"}.metismenu .plus-times{float:right}[dir=rtl] .metismenu .plus-times{float:left}.metismenu .fa.plus-times:before{content:"\f067"}.metismenu .mm-active>a>.fa.plus-times{-webkit-transform:rotate(45deg);transform:rotate(45deg)}.metismenu .plus-minus{float:right}[dir=rtl] .metismenu .plus-minus{float:left}.metismenu .fa.plus-minus:before{content:"\f067"}.metismenu .mm-active>a>.fa.plus-minus:before{content:"\f068"}.metismenu .mm-collapse:not(.mm-show){display:none}.metismenu .mm-collapsing{position:relative;height:0;overflow:hidden;transition-timing-function:ease;transition-duration:.35s;transition-property:height,visibility}.metismenu .has-arrow{position:relative}.metismenu .has-arrow:after{position:absolute;content:"";width:.5em;height:.5em;border-style:solid;border-width:1px 0 0 1px;border-color:initial;right:1em;-webkit-transform:rotate(-45deg) translateY(-50%);transform:rotate(-45deg) translateY(-50%);-webkit-transform-origin:top;transform-origin:top;top:50%;transition:all .3s ease-out}[dir=rtl] .metismenu .has-arrow:after{right:auto;left:1em;-webkit-transform:rotate(135deg) translateY(-50%);transform:rotate(135deg) translateY(-50%)}.metismenu .has-arrow[aria-expanded=true]:after,.metismenu .mm-active>.has-arrow:after{-webkit-transform:rotate(-135deg) translateY(-50%);transform:rotate(-135deg) translateY(-50%)}[dir=rtl] .metismenu .has-arrow[aria-expanded=true]:after,[dir=rtl] .metismenu .mm-active>.has-arrow:after{-webkit-transform:rotate(225deg) translateY(-50%);transform:rotate(225deg) translateY(-50%)}
8 | /*# sourceMappingURL=metisMenu.min.css.map */
--------------------------------------------------------------------------------
/business/components/account/account-component.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseCore = require("../../../core/base-core");
4 | const AccountEntity = require("../../entities/mongodb/account-entity");
5 | const bcrypt = require("bcrypt");
6 |
7 |
8 | class AccountComponent extends BaseCore {
9 | constructor() {
10 | super();
11 |
12 | this._accountEntity = new AccountEntity;
13 | }
14 |
15 | async verifyAccount(userInput) {
16 |
17 |
18 | if (!userInput) {
19 | return {
20 | status: false,
21 | message: 'Invalid input'
22 | }
23 | }
24 |
25 |
26 | let account = await this._accountEntity.findOne(userInput.username);
27 | if (!account) {
28 | return {
29 | status: false,
30 | message: 'Username and Password are incorrect'
31 | }
32 | }
33 |
34 |
35 | let isValidPass = await bcrypt.compareSync(userInput.password, account.password);
36 |
37 | if (isValidPass) {
38 | return {
39 | status: true,
40 | user: account,
41 | message: 'Success',
42 | };
43 |
44 | } else {
45 | return {
46 | status: false,
47 | message: 'Username and Password are incorrect',
48 | };
49 | }
50 |
51 | }
52 |
53 | async addAccount(userInput) {
54 |
55 |
56 | if (!userInput) {
57 | return {
58 | status: false,
59 | message: 'Invalid input'
60 | }
61 | }
62 |
63 |
64 | let account = await this._accountEntity.findOne(userInput.username);
65 | if (!account) {
66 | await this._accountEntity.add(userInput);
67 | return {
68 | status: false,
69 | message: 'Username and Password are incorrect'
70 | }
71 | }else{
72 | return {
73 | status: false,
74 | message: 'Username has exist'
75 | }
76 | }
77 | }
78 | }
79 |
80 | module.exports = AccountComponent;
81 |
--------------------------------------------------------------------------------
/business/components/invitation/invitation-component.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseCore = require("../../../core/base-core");
4 | const InviteeEntity = require("../../entities/mongodb/invitee-entity");
5 | const bcrypt = require("bcrypt");
6 |
7 |
8 | class InviationComponent extends BaseCore {
9 | constructor() {
10 | super();
11 |
12 | this._inviteeEntity = new InviteeEntity;
13 | }
14 |
15 | async getListInvitee() {
16 |
17 | let invitees = await this._inviteeEntity.list();
18 | return invitees;
19 | }
20 |
21 |
22 | async getDetailInvitee(id) {
23 | if (!id) {
24 | throw {
25 | message: "Invalid input"
26 | }
27 | }
28 |
29 | let invitee = await this._inviteeEntity.findById(id);
30 | return invitee;
31 | }
32 |
33 | async updateInvitee(id, invitee) {
34 | if (!invitee) {
35 | throw {
36 | message: "Invalid input"
37 | }
38 | }
39 |
40 | let result = await this._inviteeEntity.update(id, invitee);
41 |
42 | if (!result) {
43 | throw {
44 | message: "An occurs err"
45 | }
46 | }
47 |
48 | return result;
49 | }
50 | async addInvitee(invitee) {
51 | if (!invitee) {
52 | throw {
53 | message: "Invalid input"
54 | }
55 | }
56 |
57 | let result = await this._inviteeEntity.add(invitee);
58 |
59 | if (!result) {
60 | throw {
61 | message: "An occurs err"
62 | }
63 | }
64 |
65 | return result;
66 | }
67 | async delInvitee(id) {
68 | if (!id) {
69 | throw {
70 | message: "Invalid input"
71 | }
72 | }
73 |
74 | let invitee = await this._inviteeEntity.findById(id);
75 |
76 | if (!invitee) {
77 | throw {
78 | message: "Invitee does not exist"
79 | }
80 |
81 | }
82 |
83 | await this._inviteeEntity.remove(id);
84 | return true;
85 | }
86 |
87 | }
88 |
89 | module.exports = InviationComponent;
90 |
--------------------------------------------------------------------------------
/business/components/invocation/invocation-component.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseCore = require("../../../core/base-core");
4 | const InvocationEntity = require("../../entities/mongodb/invocation-entity");
5 |
6 |
7 | class InvocationComponent extends BaseCore {
8 | constructor() {
9 | super();
10 |
11 | this._invocationEntity = new InvocationEntity;
12 | }
13 |
14 | async getListInvocation() {
15 |
16 | let invocations = await this._invocationEntity.list();
17 | return invocations;
18 | }
19 |
20 |
21 | async getDetailInvocation(id) {
22 | if (!id) {
23 | throw {
24 | message: "Invalid input"
25 | }
26 | }
27 |
28 | let invocation = await this._invocationEntity.findById(id);
29 | return invocation;
30 | }
31 |
32 | async updateInvocation(id, invocation) {
33 | if (!invocation) {
34 | throw {
35 | message: "Invalid input"
36 | }
37 | }
38 |
39 | let result = await this._invocationEntity.update(id, invocation);
40 |
41 | if (!result) {
42 | throw {
43 | message: "An occurs err"
44 | }
45 | }
46 |
47 | return result;
48 | }
49 | async addInvocation(invocation) {
50 | if (!invocation) {
51 | throw {
52 | message: "Invalid input"
53 | }
54 | }
55 |
56 | let result = await this._invocationEntity.add(invocation);
57 |
58 | if (!result) {
59 | throw {
60 | message: "An occurs err"
61 | }
62 | }
63 |
64 | return result;
65 | }
66 | async delInvocation(id) {
67 | if (!id) {
68 | throw {
69 | message: "Invalid input"
70 | }
71 | }
72 |
73 | let invocation = await this._invocationEntity.findById(id);
74 |
75 | if (!invocation) {
76 | throw {
77 | message: "Invocation does not exist"
78 | }
79 | }
80 |
81 | await this._invocationEntity.remove(id);
82 | return true;
83 | }
84 |
85 | }
86 |
87 | module.exports = InvocationComponent;
88 |
--------------------------------------------------------------------------------
/public/plugins/clipboard/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "_from": "clipboard",
3 | "_id": "clipboard@2.0.6",
4 | "_inBundle": false,
5 | "_integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
6 | "_location": "/clipboard",
7 | "_phantomChildren": {},
8 | "_requested": {
9 | "type": "tag",
10 | "registry": true,
11 | "raw": "clipboard",
12 | "name": "clipboard",
13 | "escapedName": "clipboard",
14 | "rawSpec": "",
15 | "saveSpec": null,
16 | "fetchSpec": "latest"
17 | },
18 | "_requiredBy": [
19 | "#USER",
20 | "/"
21 | ],
22 | "_resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
23 | "_shasum": "52921296eec0fdf77ead1749421b21c968647376",
24 | "_spec": "clipboard",
25 | "_where": "C:\\Users\\ndphuc\\Downloads\\On\\Project\\wedding-invite",
26 | "bugs": {
27 | "url": "https://github.com/zenorocha/clipboard.js/issues"
28 | },
29 | "bundleDependencies": false,
30 | "dependencies": {
31 | "good-listener": "^1.2.2",
32 | "select": "^1.1.2",
33 | "tiny-emitter": "^2.0.0"
34 | },
35 | "deprecated": false,
36 | "description": "Modern copy to clipboard. No Flash. Just 2kb",
37 | "devDependencies": {
38 | "babel-core": "^6.26.0",
39 | "babel-loader": "^7.1.4",
40 | "babel-preset-env": "^1.7.0",
41 | "chai": "^4.2.0",
42 | "cross-env": "^5.2.0",
43 | "karma": "^3.1.1",
44 | "karma-chai": "^0.1.0",
45 | "karma-chrome-launcher": "^2.2.0",
46 | "karma-mocha": "^1.2.0",
47 | "karma-sinon": "^1.0.4",
48 | "karma-webpack": "^3.0.5",
49 | "mocha": "^5.2.0",
50 | "sinon": "^7.1.1",
51 | "uglifyjs-webpack-plugin": "^2.0.1",
52 | "webpack": "^4.5.0",
53 | "webpack-cli": "^3.1.2"
54 | },
55 | "homepage": "https://github.com/zenorocha/clipboard.js#readme",
56 | "keywords": [
57 | "clipboard",
58 | "copy",
59 | "cut"
60 | ],
61 | "license": "MIT",
62 | "main": "dist/clipboard.js",
63 | "name": "clipboard",
64 | "repository": {
65 | "type": "git",
66 | "url": "git+https://github.com/zenorocha/clipboard.js.git"
67 | },
68 | "scripts": {
69 | "build": "npm run build-debug && npm run build-min",
70 | "build-debug": "webpack",
71 | "build-min": "cross-env NODE_ENV=production webpack",
72 | "build-watch": "webpack --watch",
73 | "prepublish": "npm run build",
74 | "test": "karma start --single-run"
75 | },
76 | "version": "2.0.6"
77 | }
78 |
--------------------------------------------------------------------------------
/public/assets/fonts/FONTLOG.txt:
--------------------------------------------------------------------------------
1 | FONTLOG for the Pinyon Script font
2 |
3 | This file provides detailed information on Pinyon Script
4 | Font Software. This information should be distributed along with
5 | the Pinyon Script font and any derivative works.
6 |
7 | Basic Font Information
8 |
9 | Pinyon Script is a Unicode typeface family that supports languages
10 | that use the Latin script and its variants, and could be expanded
11 | to support other scripts.
12 |
13 | More specifically, this release supports the following Unicode
14 | ranges: Latin-1
15 |
16 | To contribute to the project contact Eben Sorkin at
17 | sorkineben@gmail.com
18 |
19 | ChangeLog
20 |
21 | 23 Sept 2011 (Eben Sorkin) Pinyon Script v1.007
22 | - Removed italic angle from TTF and TTF-SFD
23 | - Simplified curves to reduce filesize
24 |
25 | 6 Sept 2011 (Eben Sorkin) Pinyon Script v1.005
26 | - Mastered Font from Fontlab VBF to TTF
27 | - Made descders shorter so that they would not be
28 | chopped off in Windows
29 | - Set Grid Fitting to "No Grid Fit" to further smooth
30 | screen rendering in Windows
31 | - Adjusted the spacing of the punctuation
32 |
33 | 5 Sept 2011 (Eben Sorkin) Pinyon Script v1.004
34 | - Mastered Font from Fontlab VBF to TTF
35 | - Adjusted overall weight to be slightly heavier to avoid
36 | drop outs of then letter parts in Windows
37 | - Made similar heights more similar for better screen rendering.
38 |
39 | 5 Sept 2011 (Eben Sorkin) Pinyon Script v1.003
40 | - Mastered Font from Fontlab VBF to TTF
41 | - Adjusted thins for consistency especially in the caps,
42 | - Adjusted the slant of the lower loops of p,g,j,y
43 | - Adjusted the slant of the U by a lot and a few other caps
44 | very slightly
45 | - Adjusted the spacing of the punctuation
46 |
47 | 1 Sept 2011 (Eben Sorkin) Pinyon Script v1.002
48 | - Mastered Font from Fontlab VBF to TTF
49 | - Adjusted scale, joins, corrected outlines that
50 | created subpaths when merged.
51 |
52 | 28 August 2011 (Nicole Fally) Pinyon Script v1.000
53 | - Completed first complete version of Pinyon Script
54 | in Fontlab ( VBF format )
55 |
56 | Acknowledgements
57 |
58 | If you make modifications be sure to add your name (N),
59 | email (E), web-address (if you have one) (W) and
60 | description (D). This list is in alphabetical order.
61 |
62 | N: Nicole Fally
63 | E: nf@t-g-d.at
64 | W: www.t-g-d.at
65 | D: Designer
66 |
67 | N: Eben Sorkin
68 | E: sorkineben@gmail.com
69 | W: www.sorkintype.com
70 | D: Spacing and Mastering
71 |
--------------------------------------------------------------------------------
/public/plugins/datatables/autoFill.bootstrap4.css:
--------------------------------------------------------------------------------
1 | div.dt-autofill-handle {
2 | position: absolute;
3 | height: 8px;
4 | width: 8px;
5 | z-index: 102;
6 | box-sizing: border-box;
7 | background: #0275d8;
8 | cursor: pointer;
9 | }
10 |
11 | div.dtk-focus-alt div.dt-autofill-handle {
12 | background: #ff8b33;
13 | }
14 |
15 | div.dt-autofill-select {
16 | position: absolute;
17 | z-index: 1001;
18 | background-color: #0275d8;
19 | background-image: repeating-linear-gradient(45deg, transparent, transparent 5px, rgba(255, 255, 255, 0.5) 5px, rgba(255, 255, 255, 0.5) 10px);
20 | }
21 | div.dt-autofill-select.top, div.dt-autofill-select.bottom {
22 | height: 3px;
23 | margin-top: -1px;
24 | }
25 | div.dt-autofill-select.left, div.dt-autofill-select.right {
26 | width: 3px;
27 | margin-left: -1px;
28 | }
29 |
30 | div.dt-autofill-list {
31 | position: fixed;
32 | top: 50%;
33 | left: 50%;
34 | width: 500px;
35 | margin-left: -250px;
36 | background-color: white;
37 | border-radius: 6px;
38 | box-shadow: 0 0 5px #555;
39 | border: 2px solid #444;
40 | z-index: 11;
41 | box-sizing: border-box;
42 | padding: 1.5em 2em;
43 | }
44 | div.dt-autofill-list ul {
45 | display: table;
46 | margin: 0;
47 | padding: 0;
48 | list-style: none;
49 | width: 100%;
50 | }
51 | div.dt-autofill-list ul li {
52 | display: table-row;
53 | }
54 | div.dt-autofill-list ul li:last-child div.dt-autofill-question, div.dt-autofill-list ul li:last-child div.dt-autofill-button {
55 | border-bottom: none;
56 | }
57 | div.dt-autofill-list ul li:hover {
58 | background-color: #f6f6f6;
59 | }
60 | div.dt-autofill-list div.dt-autofill-question {
61 | display: table-cell;
62 | padding: 0.5em 0;
63 | border-bottom: 1px solid #ccc;
64 | }
65 | div.dt-autofill-list div.dt-autofill-question input[type=number] {
66 | padding: 6px;
67 | width: 30px;
68 | margin: -2px 0;
69 | }
70 | div.dt-autofill-list div.dt-autofill-button {
71 | display: table-cell;
72 | padding: 0.5em 0;
73 | border-bottom: 1px solid #ccc;
74 | }
75 |
76 | div.dt-autofill-background {
77 | position: fixed;
78 | top: 0;
79 | left: 0;
80 | width: 100%;
81 | height: 100%;
82 | background: rgba(0, 0, 0, 0.7);
83 | background: radial-gradient(ellipse farthest-corner at center, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
84 | z-index: 10;
85 | }
86 |
87 | div.dt-autofill-list div.dt-autofill-question input[type=number] {
88 | padding: 6px;
89 | width: 60px;
90 | margin: -2px 0;
91 | }
92 |
--------------------------------------------------------------------------------
/bin/www:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict';
3 |
4 | /**
5 | * Module dependencies.
6 | */
7 |
8 | const app = require('../app');
9 | const debug = require('debug')('introduce:services');
10 | const http = require('http');
11 |
12 | const sysConfig = require('../configs/system-configs');
13 | const log = sysConfig.log();
14 |
15 |
16 | /**
17 | * Get port from environment and store in Express.
18 | */
19 |
20 | const port = normalizePort(process.env.PORT || 3000);
21 | app.set('port', port);
22 |
23 | /**
24 | * Create HTTP services.
25 | */
26 |
27 | const server = http.createServer(app);
28 |
29 | /**
30 | * Listen on provided port, on all network interfaces.
31 | */
32 |
33 | server.listen(port, function () {
34 | log.info('✓ The bundle is now ready for serving!');
35 | log.info(
36 | 'Open in inline mode:',
37 | 'http://localhost:' + port
38 | );
39 | });
40 |
41 | server.on('error', onError);
42 | server.on('listening', onListening);
43 |
44 |
45 | /**
46 | * Normalize a port into a number, string, or false.
47 | */
48 |
49 | function normalizePort(val) {
50 | const port = parseInt(val, 10);
51 |
52 | if (isNaN(port)) {
53 | // named pipe
54 | return val;
55 | }
56 |
57 | if (port >= 0) {
58 | // port number
59 | return port;
60 | }
61 |
62 | return 3000;
63 | }
64 |
65 | /**
66 | * Event listener for HTTP services "error" event.
67 | */
68 |
69 | function onError(error) {
70 | if (error.syscall !== 'listen') {
71 | throw error;
72 | }
73 |
74 | const bind = typeof port === 'string'
75 | ? 'Pipe ' + port
76 | : 'Port ' + port;
77 |
78 | // handle specific listen errors with friendly messages
79 | switch (error.code) {
80 | case 'EACCES':
81 | log.error(bind + ' requires elevated privileges');
82 | process.exit(1);
83 | break;
84 | case 'EADDRINUSE':
85 | log.error(bind + ' is already in use');
86 | process.exit(1);
87 | break;
88 | default:
89 | throw error;
90 | }
91 | }
92 |
93 | /**
94 | * Event listener for HTTP services "listening" event.
95 | */
96 |
97 | function onListening() {
98 | const addr = server.address();
99 | const bind = typeof addr === 'string'
100 | ? 'pipe ' + addr
101 | : 'port ' + addr.port;
102 | debug('Listening on ' + bind);
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/public/plugins/datatables/buttons.colVis.min.js:
--------------------------------------------------------------------------------
1 | (function(g){"function"===typeof define&&define.amd?define(["jquery","datatables.net","datatables.net-buttons"],function(d){return g(d,window,document)}):"object"===typeof exports?module.exports=function(d,e){d||(d=window);if(!e||!e.fn.dataTable)e=require("datatables.net")(d,e).$;e.fn.dataTable.Buttons||require("datatables.net-buttons")(d,e);return g(e,d,d.document)}:g(jQuery,window,document)})(function(g,d,e,h){d=g.fn.dataTable;g.extend(d.ext.buttons,{colvis:function(a,b){return{extend:"collection",
2 | text:function(a){return a.i18n("buttons.colvis","Column visibility")},className:"buttons-colvis",buttons:[{extend:"columnsToggle",columns:b.columns}]}},columnsToggle:function(a,b){return a.columns(b.columns).indexes().map(function(a){return{extend:"columnToggle",columns:a}}).toArray()},columnToggle:function(a,b){return{extend:"columnVisibility",columns:b.columns}},columnsVisibility:function(a,b){return a.columns(b.columns).indexes().map(function(a){return{extend:"columnVisibility",columns:a,visibility:b.visibility}}).toArray()},
3 | columnVisibility:{columns:h,text:function(a,b,c){return c._columnText(a,c.columns)},className:"buttons-columnVisibility",action:function(a,b,c,f){a=b.columns(f.columns);b=a.visible();a.visible(f.visibility!==h?f.visibility:!(b.length&&b[0]))},init:function(a,b,c){var f=this,d=a.column(c.columns);a.on("column-visibility.dt"+c.namespace,function(a,b){b.bDestroying||f.active(d.visible())}).on("column-reorder.dt"+c.namespace,function(b,d,e){1===a.columns(c.columns).count()&&("number"===typeof c.columns&&
4 | (c.columns=e.mapping[c.columns]),b=a.column(c.columns),f.text(c._columnText(a,c.columns)),f.active(b.visible()))});this.active(d.visible())},destroy:function(a,b,c){a.off("column-visibility.dt"+c.namespace).off("column-reorder.dt"+c.namespace)},_columnText:function(a,b){var c=a.column(b).index();return a.settings()[0].aoColumns[c].sTitle.replace(/\n/g," ").replace(/<.*?>/g,"").replace(/^\s+|\s+$/g,"")}},colvisRestore:{className:"buttons-colvisRestore",text:function(a){return a.i18n("buttons.colvisRestore",
5 | "Restore visibility")},init:function(a,b,c){c._visOriginal=a.columns().indexes().map(function(b){return a.column(b).visible()}).toArray()},action:function(a,b,c,d){b.columns().every(function(a){a=b.colReorder&&b.colReorder.transpose?b.colReorder.transpose(a,"toOriginal"):a;this.visible(d._visOriginal[a])})}},colvisGroup:{className:"buttons-colvisGroup",action:function(a,b,c,d){b.columns(d.show).visible(!0,!1);b.columns(d.hide).visible(!1,!1);b.columns.adjust()},show:[],hide:[]}});return d.Buttons});
6 |
--------------------------------------------------------------------------------
/business/facade/facade.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const BaseCore = require('../../core/base-core');
4 | const AccountComponent = require('../components/account/account-component');
5 | const InvitationComponent = require('../components/invitation/invitation-component');
6 | const InvocationComponent = require('../components/invocation/invocation-component');
7 | const DataConfiComponent = require('../components/data-config/data-config-component');
8 |
9 | class Facade extends BaseCore {
10 |
11 | constructor() {
12 | super();
13 |
14 | this._accountComponent = new AccountComponent;
15 | this._invitationComponent = new InvitationComponent;
16 | this._dataConfiComponent = new DataConfiComponent;
17 | this._invocationComponent = new InvocationComponent;
18 | }
19 |
20 |
21 | // invitation
22 | async updateInvocation(id, invocation) {
23 | return this._invocationComponent.updateInvocation(id, invocation);
24 | }
25 | async addInvocation(invocation) {
26 | return this._invocationComponent.addInvocation(invocation);
27 | }
28 |
29 | async delInvocation(id) {
30 | return this._invocationComponent.delInvocation(id);
31 | }
32 |
33 | async getDetailInvocation(id) {
34 | return this._invocationComponent.getDetailInvocation(id);
35 | }
36 | async getListInvocation() {
37 | return this._invocationComponent.getListInvocation();
38 | }
39 |
40 | // invitation
41 | async updateInvitee(id, invitee) {
42 | return this._invitationComponent.updateInvitee(id, invitee);
43 | }
44 | async addInvitee(invitee) {
45 | return this._invitationComponent.addInvitee(invitee);
46 | }
47 |
48 | async delInvitee(id) {
49 | return this._invitationComponent.delInvitee(id);
50 | }
51 |
52 | async getDetailInvitee(id) {
53 | return this._invitationComponent.getDetailInvitee(id);
54 | }
55 | async getListInvitee() {
56 | return this._invitationComponent.getListInvitee();
57 | }
58 |
59 | // account
60 | async verifyAccount(input) {
61 | return this._accountComponent.verifyAccount(input);
62 | }
63 |
64 | async addAccount(input) {
65 | return this._accountComponent.addAccount(input);
66 | }
67 | // configuration
68 | async getDefaultDataConfig() {
69 | return this._dataConfiComponent.getDefaultDataConfig();
70 | }
71 |
72 | async addDefaultDataConfig(data) {
73 | return this._dataConfiComponent.addDefaultDataConfig(data);
74 | }
75 |
76 | }
77 |
78 | module.exports = Facade;
79 |
--------------------------------------------------------------------------------
/views/err/occurs-error.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 500 - An occurs error
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
500!
31 | Sorry, an occurs error
32 |
33 |
34 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/public/assets/js/imgPreview.min.js:
--------------------------------------------------------------------------------
1 | "use strict";function _classCallCheck(e,i){if(!(e instanceof i))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function e(e,i){for(var t=0;t'),o.imgPreviewPopover=e('
'),o.imgPreviewBox=e('
'),o.imgPreviewFoot=e(''),"single"===o.config.mode){var P=new Image,h=function(i,t){t=o.isPc()?parseInt(v*t/i):t>=l?l:t,i=i>=v?v:i;var n={width:i,height:o.isPc()?"auto":t,top:parseInt((l-t)/2),left:parseInt((v-i)/2)};o.imgPreviewBox.append(e(' ')).click(function(){o.hide()}),o.config.isMaskShow&&(a.append(o.imgPreviewMask),o.imgPreviewMask.click(function(){o.hide()})),o.config.attrTitle&&o.imgPreviewFoot.append(e('")),o.config.attrDesc&&o.imgPreviewFoot.append(e('")),o.imgPreviewPopover.append(o.imgPreviewBox),(g||u)&&o.imgPreviewPopover.append(o.imgPreviewFoot),a.append(o.imgPreviewPopover),e.fn&&e.fn.jquery?o.imgPreviewPopover.animate(n,300):o.imgPreviewPopover.css(n)};P.onload=function(){P.onload=null,h(P.width,P.height)},P.onerror=function(){alert("很抱歉,图片加载失败!")},P.src=d}}},{key:"isPc",value:function(){return/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)}},{key:"hide",value:function(){this.imgPreviewMask.remove(),this.imgPreviewPopover.remove()}},{key:"allDom",value:function(){return e(this.config.el)}}]),i}()});
--------------------------------------------------------------------------------
/views/err/e401.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 401 - You don't have access
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
401!
31 |
Sorry, you don't have access to this page
32 |
Please login system
Login
35 |
36 |
37 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/views/err/e404.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 404 - Page not found
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
404!
31 |
Sorry, page not found
32 |
It will be as simple as Occidental in fact, it will be
33 | Occidental to an English person
Back to Dashboard
36 |
37 |
38 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/public/assets/css/custom.css:
--------------------------------------------------------------------------------
1 | .lds-ellipsis {
2 | display: inline-block;
3 | position: relative;
4 | width: 80px;
5 | height: 80px;
6 | }
7 |
8 | .lds-ellipsis div {
9 | position: absolute;
10 | top: 33px;
11 | width: 13px;
12 | height: 13px;
13 | border-radius: 50%;
14 | background: #fff;
15 | animation-timing-function: cubic-bezier(0, 1, 1, 0);
16 | }
17 |
18 | .lds-ellipsis div:nth-child(1) {
19 | left: 8px;
20 | animation: lds-ellipsis1 0.6s infinite;
21 | }
22 |
23 | .lds-ellipsis div:nth-child(2) {
24 | left: 8px;
25 | animation: lds-ellipsis2 0.6s infinite;
26 | }
27 |
28 | .lds-ellipsis div:nth-child(3) {
29 | left: 32px;
30 | animation: lds-ellipsis2 0.6s infinite;
31 | }
32 |
33 | .lds-ellipsis div:nth-child(4) {
34 | left: 56px;
35 | animation: lds-ellipsis3 0.6s infinite;
36 | }
37 |
38 | @keyframes lds-ellipsis1 {
39 | 0% {
40 | transform: scale(0);
41 | }
42 | 100% {
43 | transform: scale(1);
44 | }
45 | }
46 |
47 | @keyframes lds-ellipsis3 {
48 | 0% {
49 | transform: scale(1);
50 | }
51 | 100% {
52 | transform: scale(0);
53 | }
54 | }
55 |
56 | @keyframes lds-ellipsis2 {
57 | 0% {
58 | transform: translate(0, 0);
59 | }
60 | 100% {
61 | transform: translate(24px, 0);
62 | }
63 | }
64 |
65 | .fade-loading {
66 | background: rgba(0, 0, 0, 0.75);
67 | display: flex;
68 | align-items: center;
69 | justify-content: center;
70 | position: fixed;
71 | top: 0;
72 | right: 0;
73 | bottom: 0;
74 | left: 0;
75 | z-index: 100000;
76 | }
77 |
78 | .close-loading {
79 | position: fixed;
80 | right: 15px;
81 | top: 15px;
82 | color: white;
83 | }
84 |
85 | .col-centered {
86 | float: none;
87 | margin: 0 auto;
88 | }
89 |
90 | .hide {
91 | display: none;
92 | }
93 |
94 | .ti-tiki:before {
95 | content: url("../images/icon/tiki.ico");
96 | }
97 |
98 | .ti-shopee:before {
99 | content: url("../images/icon/shopee.svg");
100 | }
101 |
102 | .blink_text {
103 | animation: 1s blinker linear infinite;
104 | -webkit-animation: 1s blinker linear infinite;
105 | -moz-animation: 1s blinker linear infinite;
106 |
107 | color: red;
108 | }
109 |
110 | @-moz-keyframes blinker {
111 | 0% {
112 | opacity: 1;
113 | }
114 | 50% {
115 | opacity: 0;
116 | }
117 | 100% {
118 | opacity: 1;
119 | }
120 | }
121 |
122 | @-webkit-keyframes blinker {
123 | 0% {
124 | opacity: 1;
125 | }
126 | 50% {
127 | opacity: 0;
128 | }
129 | 100% {
130 | opacity: 1;
131 | }
132 | }
133 |
134 | @keyframes blinker {
135 | 0% {
136 | opacity: 1;
137 | }
138 | 50% {
139 | opacity: 0;
140 | }
141 | 100% {
142 | opacity: 1;
143 | }
144 | }
145 |
146 | .btn {
147 | cursor: pointer;
148 | }
149 |
150 |
--------------------------------------------------------------------------------
/views/layout.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Happy wedding | Sauanla application
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | <%- include share/topbar.ejs %>
35 |
36 |
37 | <%- include share/side-menu.ejs %>
38 |
39 |
40 |
41 |
42 |
43 | <%- body %>
44 |
45 |
46 |
47 |
48 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | <%- script %>
81 |
82 |
83 |
--------------------------------------------------------------------------------
/domains/mongodb/schemas.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const mongoose = require('mongoose');
4 | const Schema = mongoose.Schema;
5 |
6 | const ACCOUNT = new Schema({
7 | email: { type: String, unique: true, required: true, trim: true },
8 | username: { type: String, required: true, trim: true, minlength: 2 },
9 | role: { type: String, enum: ['admin', 'customer'] },
10 | password: { type: String, required: true, trim: true, minlength: 6 },
11 | password_confirm: { type: String, required: true, trim: true, minlength: 6 },
12 | }).pre('save', (next) => {
13 | console.log('SAVE ACCOUNT');
14 | next();
15 | });
16 |
17 |
18 | const INVITEE = new Schema({
19 | name: String,
20 | message: String,
21 | level: String,
22 | area: Number, //1. male - 0. female
23 | }).pre('save', (next) => {
24 | console.log('SAVE INVITEE');
25 | next();
26 | });
27 |
28 | const INVOCATION = new Schema({
29 | name: String,
30 | status: Number, //1. go , 0. pending, -1. cancel
31 | phone: String,
32 | message: String,
33 | inviteeId: String,
34 | time: { type: Date, default: Date.now},
35 | }).pre('save', (next) => {
36 | console.log('SAVE INVOCATION');
37 | next();
38 | });
39 |
40 | const DATA_CONFIG = new Schema({
41 | male: {
42 | name: String,
43 | parent: {
44 | father: String,
45 | mother: String,
46 | },
47 | location: {
48 | text: String,
49 | map: String,
50 | },
51 | time_start: {
52 | date: {
53 | lunar: {
54 | day: String,
55 | month: String,
56 | year: String
57 | },
58 | solar: {
59 | day: String,
60 | month: String,
61 | year: String
62 | }
63 | },
64 | time: {
65 | hour: String,
66 | minute: String
67 | }
68 | },
69 | finances: Array ,
70 | email: String,
71 | phone: String,
72 | bg: String,
73 | bg_fb: String
74 | },
75 | female: {
76 | name: String,
77 | parent: {
78 | father: String,
79 | mother: String,
80 | },
81 | location: {
82 | text: String,
83 | map: String,
84 | },
85 | time_start: {
86 | date: {
87 | lunar: {
88 | day: String,
89 | month: String,
90 | year: String
91 | },
92 | solar: {
93 | day: String,
94 | month: String,
95 | year: String
96 | }
97 | },
98 | time: {
99 | hour: String,
100 | minute: String
101 | }
102 | },
103 | finances: Array,
104 | email: String,
105 | phone: String,
106 | bg: String,
107 | bg_fb: String
108 | },
109 | default: Boolean
110 | }).pre('save', (next) => {
111 | console.log('SAVE DATA_CONFIG');
112 | next();
113 | });
114 |
115 | exports.SCHEMAS = {
116 | ACCOUNT: ACCOUNT,
117 | INVITEE: INVITEE,
118 | INVOCATION: INVOCATION,
119 | DATA_CONFIG: DATA_CONFIG
120 | };
121 |
--------------------------------------------------------------------------------
/domains/mongodb/seed-db.js:
--------------------------------------------------------------------------------
1 |
2 | const SeedDB = {
3 | user: {
4 | email: "admin@invitation.com",
5 | username: "admin",
6 | password: "$2b$10$VhmfGtzS9/IZPQuLQhmXkeTZmXrHYjIV2HCRfsOEp66Yk/OJiwow2", //123qwe
7 | password_confirm: "$2b$10$VhmfGtzS9/IZPQuLQhmXkeTZmXrHYjIV2HCRfsOEp66Yk/OJiwow2",
8 | role: "admin"
9 | },
10 | dataConfig: {
11 | male: {
12 | name: "Nguyễn Văn An",
13 | parent: {
14 | father: "Họ Tên Bố",
15 | mother: "Họ Tên Mẹ"
16 | },
17 | location: {
18 | text: "Quảng Yên - Quảng Ninh - Việt Nam",
19 | map: "https://goo.gl/maps/tTZz4qKhaiqSL8Q66"
20 | },
21 | time_start: {
22 | date: {
23 | lunar: {
24 | day: "17",
25 | month: "12",
26 | year: "2020"
27 | },
28 | day_of_week: "5",
29 | solar: {
30 | day: "17",
31 | month: "12",
32 | year: "2020"
33 | }
34 | },
35 | time: {
36 | hour: "10",
37 | minute: "00"
38 | }
39 | },
40 | finances: [{
41 | provider_name: "MB Bank",
42 | provider_number: "9971997555555",
43 | holder_name: "NGUYEN VAN AN"
44 | }, {
45 | provider_name: "Techcombank",
46 | provider_number: "19034892842011",
47 | holder_name: "NGUYEN VAN AN"
48 | }, {
49 | provider_name: "Momo",
50 | provider_number: "0973699999",
51 | holder_name: "NGUYEN VAN AN"
52 | }, {
53 | provider_name: "Airpay",
54 | provider_number: "0973699999",
55 | holder_name: "NGUYEN VAN AN"
56 | }],
57 | email: "male@gmail.com",
58 | phone: "0973699999",
59 | bg: '/assets/images/bg.jpg',
60 | bg_fb: '/assets/images/bg-fb.jpg'
61 | },
62 | female: {
63 | name: "Nguyễn Thị Lan Anh",
64 | parent: {
65 | father: "Họ Tên Bố",
66 | mother: "Họ Tên Mẹ"
67 | },
68 | location: {
69 | text: "Quốc Oai - Hà Nội - Việt Nam",
70 | map: "https://goo.gl/maps/tRjKuVRNisqxhQaT7"
71 | },
72 | time_start: {
73 | date: {
74 | lunar: {
75 | day: "17",
76 | month: "12",
77 | year: "2020"
78 | },
79 | day_of_week: "5",
80 | solar: {
81 | day: "17",
82 | month: "12",
83 | year: "2020"
84 | }
85 | },
86 | time: {
87 | hour: "10",
88 | minute: "00"
89 | }
90 | },
91 | finances: [{
92 | provider_name: "Techcombank",
93 | provider_number: "19033799999999",
94 | holder_name: "NGUYEN THI LAN ANH"
95 | }, {
96 | provider_name: "Techcombank",
97 | provider_number: "19033799999999",
98 | holder_name: "NGUYEN THI LAN ANH"
99 | }, {
100 | provider_name: "Momo",
101 | provider_number: "09736",
102 | holder_name: "NGUYEN THI LAN ANH"
103 | }, {
104 | provider_name: "Airpay",
105 | provider_number: "0973699999",
106 | holder_name: "NGUYEN VAN AN"
107 | }],
108 | email: "female@gmail.com",
109 | phone: "0985123123",
110 | bg: '/assets/images/bg.jpg',
111 | bg_fb: '/assets/images/bg-fb.jpg'
112 | },
113 | default: true
114 | }
115 | };
116 |
117 | module.exports = SeedDB;
118 |
--------------------------------------------------------------------------------
/views/invocation/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Invocations
5 |
6 |
7 | Home
8 |
9 | Invocations
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | #
24 | Name
25 | Phone
26 | Status
27 | Time
28 | Message
29 | Action
30 |
31 |
32 |
33 | <% for (var i = 0, len = invocations.length ; i < len; i++) {%>
34 |
35 | <%= i+1 %>
36 |
37 | <%= invocations[i].name %>
39 |
40 | <%= invocations[i].phone %>
41 |
42 | <% if(invocations[i].status == 1){ %>
43 | Tham gia
44 | <% } else if(invocations[i].status == -1){ %>
45 | Không Tham gia
46 | <% } else { %>
47 | Không Tham gia
48 | <% } %>
49 |
50 |
51 |
52 |
53 |
54 | Delete
55 |
56 | <% } %>
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/public/assets/js/app.js:
--------------------------------------------------------------------------------
1 | !function (t) { "use strict"; var e = function () { this.$body = t("body"), this.$wrapper = t("#wrapper"), this.$btnFullScreen = t("#btn-fullscreen"), this.$leftMenuButton = t(".button-menu-mobile"), this.$menuItem = t(".has_sub > a") }; e.prototype.intSlimscrollmenu = function () { t(".slimscroll-menu").slimscroll({ height: "auto", position: "right", size: "5px", color: "#9ea5ab", wheelStep: 5, touchScrollStep: 50 }) }, e.prototype.initSlimscroll = function () { t(".slimscroll").slimscroll({ height: "auto", position: "right", size: "5px", color: "#9ea5ab", touchScrollStep: 50 }) }, e.prototype.initMetisMenu = function () { t("#side-menu").metisMenu() }, e.prototype.initLeftMenuCollapse = function () { t(".button-menu-mobile").on("click", function (e) { e.preventDefault(), t("body").toggleClass("enlarged") }) }, e.prototype.initEnlarge = function () { t(window).width() < 1025 ? t("body").addClass("enlarged") : t("body").removeClass("enlarged") }, e.prototype.initActiveMenu = function () { t("#sidebar-menu a").each(function () { var e = window.location.href.split(/[?#]/)[0]; this.href == e && (t(this).addClass("mm-active"), t(this).parent().addClass("mm-active"), t(this).parent().parent().addClass("mm-show"), t(this).parent().parent().prev().addClass("mm-active"), t(this).parent().parent().parent().addClass("mm-active"), t(this).parent().parent().parent().parent().addClass("mm-show"), t(this).parent().parent().parent().parent().parent().addClass("mm-active")) }) }, e.prototype.initComponents = function () { t('[data-toggle="tooltip"]').tooltip(), t('[data-toggle="popover"]').popover() }, e.prototype.initFullScreen = function () { this.$btnFullScreen.on("click", function (e) { e.preventDefault(), document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ? document.cancelFullScreen ? document.cancelFullScreen() : document.mozCancelFullScreen ? document.mozCancelFullScreen() : document.webkitCancelFullScreen && document.webkitCancelFullScreen() : document.documentElement.requestFullscreen ? document.documentElement.requestFullscreen() : document.documentElement.mozRequestFullScreen ? document.documentElement.mozRequestFullScreen() : document.documentElement.webkitRequestFullscreen && document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT) }) }, e.prototype.init = function () { this.intSlimscrollmenu(), this.initSlimscroll(), this.initMetisMenu(), this.initLeftMenuCollapse(), this.initEnlarge(), this.initActiveMenu(), this.initComponents(), this.initFullScreen(), Waves.init() }, t.MainApp = new e, t.MainApp.Constructor = e }(window.jQuery), function (e) { "use strict"; window.jQuery.MainApp.init() }();
2 | function colorLog(message, color) {
3 |
4 | color = color || "black";
5 |
6 | switch (color) {
7 | case "success":
8 | color = "Green";
9 | break;
10 | case "info":
11 | color = "DodgerBlue";
12 | break;
13 | case "error":
14 | color = "Red";
15 | break;
16 | case "warning":
17 | color = "Orange";
18 | break;
19 | default:
20 | color = color;
21 | }
22 |
23 | console.log("%c" + message, "color:" + color);
24 | }
25 |
26 | (function() {
27 |
28 | let sig = ` __
29 | (_ _ _ __ | _ _ _ __
30 | __)(_||_|(_|| | | (_| o (_ (_)|||`
31 |
32 |
33 |
34 | colorLog(sig,'success');
35 | colorLog('Github repo: https://github.com/sauanla/wedding-invitation','success');
36 |
37 | })();
38 |
39 |
--------------------------------------------------------------------------------
/views/manager/invocation/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Invocations
5 |
6 |
7 | Home
8 |
9 | Invocations
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | #
24 | Name
25 | Phone
26 | Status
27 | Time
28 | Message
29 | Action
30 |
31 |
32 |
33 | <% for (var i = 0, len = invocations.length ; i < len; i++) {%>
34 |
35 | <%= i+1 %>
36 |
37 | <%= invocations[i].name %>
39 |
40 | <%= invocations[i].phone %>
41 |
42 | <% if(invocations[i].status == 1){ %>
43 | Tham gia
44 | <% } else if(invocations[i].status == -1){ %>
45 | Không Tham gia
46 | <% } else { %>
47 | Không Tham gia
48 | <% } %>
49 |
50 |
51 |
52 |
53 |
54 | Delete
55 |
56 | <% } %>
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/controllers/manager/invitation/invitation-controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const systemConfigs = require("../../../configs/system-configs");
4 | const BaseController = require("../../../core/base-controller");
5 |
6 |
7 | class InvitationController extends BaseController {
8 |
9 | constructor() {
10 | super();
11 |
12 | this.list = this.list.bind(this);
13 | this.detail = this.detail.bind(this);
14 | this.create = this.create.bind(this);
15 | this.update = this.update.bind(this);
16 | this.del = this.del.bind(this);
17 | }
18 |
19 | async list(req, res) {
20 |
21 | try {
22 | let data = await this._facade.getListInvitee();
23 |
24 | res.render('manager/invitation/index', {
25 | invitees: data,
26 | uri: systemConfigs.domain
27 | });
28 | } catch (error) {
29 | res.render('err/occurs-error', {
30 | layout: false,
31 | err: error
32 | });
33 | }
34 |
35 | }
36 |
37 | async detail(req, res) {
38 | try {
39 | let id = req.params.id.trim();
40 | let data = await this._facade.getDetailInvitee(id);
41 |
42 | this._handleResult(data, res);
43 |
44 | } catch (error) {
45 | this._handleError(error.message, res);
46 | }
47 | }
48 |
49 | async create(req, res) {
50 | try {
51 | if (this._handleValidationResult(req, res)){
52 | return false;
53 | }
54 | let invitee = {
55 | name: req.body.invitee.name,
56 | message: req.body.invitee.message,
57 | level: req.body.invitee.level,
58 | area: Number(req.body.invitee.area),
59 | };
60 |
61 | let data = await this._facade.addInvitee(invitee);
62 |
63 | this._handleResult(data, res);
64 | } catch (error) {
65 | console.log(error);
66 | this._handleError({
67 | code: 500,
68 | message: error.message
69 | }, res);
70 | }
71 | }
72 |
73 | async update(req, res) {
74 | try {
75 | if (this._handleValidationResult(req, res)){
76 | return false;
77 | }
78 | let invitee = {
79 | id: req.body.invitee.id,
80 | name: req.body.invitee.name,
81 | message: req.body.invitee.message,
82 | level: req.body.invitee.level,
83 | area: Number(req.body.invitee.area),
84 | };
85 |
86 | let data = await this._facade.updateInvitee(invitee.id, invitee);
87 |
88 | this._handleResult(data, res);
89 | } catch (error) {
90 | this._handleError(error.message, res);
91 | }
92 | }
93 |
94 | async del(req, res) {
95 | const id = req.body.id;
96 | try {
97 |
98 | const invitee = await this._facade.getDetailInvitee(id);
99 |
100 | if(!invitee){
101 | return this._handleError('Invitee does not exist', res);
102 | }
103 |
104 | let data = await this._facade.delInvitee(id);
105 | this._handleResult(data, res);
106 | } catch (error) {
107 | this._handleError(error.message, res);
108 | }
109 |
110 | }
111 | }
112 |
113 | module.exports = InvitationController;
114 |
--------------------------------------------------------------------------------
/controllers/invitation/invitation-controller.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | const BaseController = require("../../core/base-controller");
4 | const { AREA, MODE } = require("../../helpers/constants");
5 |
6 |
7 | class InvitationController extends BaseController {
8 |
9 | constructor() {
10 | super();
11 |
12 | this.defaultPage = this.defaultPage.bind(this);
13 | this.detailInvitation = this.detailInvitation.bind(this);
14 | this.bankPage = this.bankPage.bind(this);
15 | }
16 |
17 | async defaultPage(req, res) {
18 |
19 | try {
20 | let data = await this._facade.getDefaultDataConfig();
21 |
22 | if (!data) {
23 | return res.redirect("/setup")
24 | }
25 | res.render('invitation/male', {
26 | layout: false,
27 | data: {
28 | mode: MODE.DEFAULT,
29 | cfg: data,
30 | invitee: null,
31 | },
32 | });
33 | } catch (error) {
34 | res.render('err/occurs-error', {
35 | layout: false,
36 | err: error
37 | });
38 | }
39 | }
40 |
41 | async detailInvitation(req, res) {
42 | const id = req.params.id.trim();
43 | try {
44 | let invitee = await this._facade.getDetailInvitee(id);
45 | let config = await this._facade.getDefaultDataConfig();
46 |
47 | if (!config) {
48 | return res.render('err/occurs-error', {
49 | layout: false,
50 | err: "could not load default data"
51 | });
52 | }
53 |
54 | if (!invitee) {
55 | return res.render('err/e404', {
56 | layout: false,
57 | });
58 | }
59 |
60 |
61 | if (invitee.area === AREA.FEMALE) {
62 | res.render('invitation/female', {
63 | layout: false,
64 | data: {
65 | mode: MODE.HAS_DATA,
66 | cfg: config,
67 | invitee: invitee,
68 | },
69 | });
70 | } else if (invitee.area === AREA.MALE) {
71 | res.render('invitation/male', {
72 | layout: false,
73 | data: {
74 | mode: MODE.HAS_DATA,
75 | cfg: config,
76 | invitee: invitee,
77 | },
78 | });
79 | }
80 |
81 |
82 | } catch (error) {
83 | res.render('err/occurs-error', {
84 | layout: false,
85 | err: error
86 | });
87 | }
88 | }
89 |
90 | async bankPage(req, res) {
91 | try {
92 | let data = await this._facade.getDefaultDataConfig();
93 |
94 | if (!data) {
95 | return res.render('err/occurs-error', {
96 | layout: false,
97 | err: "could not load default data"
98 | });
99 | }
100 |
101 | res.render('invitation/bank', {
102 | layout: false,
103 | data: {
104 | mode: 1
105 | },
106 | });
107 | } catch (error) {
108 | res.render('err/occurs-error', {
109 | layout: false,
110 | err: error
111 | });
112 | }
113 | }
114 | }
115 |
116 | module.exports = InvitationController;
117 |
--------------------------------------------------------------------------------
/public/assets/js/history.char.js:
--------------------------------------------------------------------------------
1 | var myChart;
2 | function formatDate(date) {
3 | var d = new Date(date);
4 | var curr_date = d.getDate();
5 | var curr_month = d.getMonth() + 1; //Months are zero based
6 | var curr_year = d.getFullYear();
7 | return curr_date + "-" + curr_month + "-" + curr_year;
8 | }
9 | format_curency = money => {
10 | money = money.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1.");
11 | return money + " VNĐ";
12 | };
13 |
14 | function cc(idItem, idShop, price) {
15 | $("#isLoading").hide();
16 | var id = "1__" + idItem + "__" + idShop;
17 | $("#myModal").modal("show");
18 | getData(id);
19 | }
20 |
21 | function genId(url) {
22 | try {
23 | const regex = /(i.)+[0-9]+(.)+[0-9]/g;
24 | const str = url;
25 | let m;
26 |
27 | while ((m = regex.exec(str)) !== null) {
28 | // This is necessary to avoid infinite loops with zero-width matches
29 | if (m.index === regex.lastIndex) {
30 | regex.lastIndex++;
31 | }
32 |
33 | // The result can be accessed through the `m`-variable.
34 | var ids = m[0].split(".");
35 | ids[0] = "1";
36 | var temp = ids[1];
37 | ids[1] = ids[2];
38 | ids[2] = temp;
39 | var id = ids.join("__");
40 | return id;
41 | }
42 | } catch (err) {
43 | console.log(err);
44 | return "";
45 | }
46 | }
47 |
48 | $("#detailItem").click(function(e) {
49 | e.preventDefault();
50 | $("#chart").show();
51 | $("#isLoading").hide();
52 | $("#isLoading").hide();
53 | var url = $("#url").val();
54 | var ref = $("#ref").val();
55 | $("#urlBuy").attr("href", ref+url);
56 | if (url && url !== "") {
57 | var id = genId(url);
58 | if (id == undefined || id === "") {
59 | $("#err").show();
60 | $("#err").text(
61 | "Chọn vào chi tiết sản phẩm trên shopee -> xong coppy Url nhé 🤔 "
62 | );
63 | $("#chartRender").hide();
64 | $("#isLoading").show();
65 | } else {
66 | $("#err").hide();
67 | getData(id);
68 | }
69 | }
70 | });
71 | var getData = function(id) {
72 | $.ajax({
73 | url: "/shopee/history/" + id,
74 | success: function(rp) {
75 | if (rp.status) {
76 | $("#chartRender").show();
77 | $("#isLoading").hide();
78 | renderChart(rp.data, rp.labels);
79 | } else {
80 | $("#chartRender").hide();
81 | $("#isLoading").show();
82 | if (myChart) {
83 | myChart.destroy();
84 | }
85 | }
86 | // re-render the chart
87 | }
88 | });
89 | };
90 |
91 | function renderChart(data, labels) {
92 | if (myChart) {
93 | myChart.destroy();
94 | }
95 | var ctx = document.getElementById("myChart").getContext("2d");
96 | myChart = new Chart(ctx, {
97 | type: "line",
98 | data: {
99 | labels: labels,
100 | datasets: [
101 | {
102 | label: "Giá sản phẩm",
103 | data: data,
104 | borderColor: "rgba(75, 192, 192, 1)",
105 | backgroundColor: "rgba(75, 192, 192, 0.2)"
106 | }
107 | ]
108 | },
109 | options: {
110 | scales: {
111 | yAxes: [
112 | {
113 | ticks: {
114 | beginAtZero: true,
115 | callback: function(value, index, values) {
116 | return format_curency(value);
117 | }
118 | }
119 | }
120 | ],
121 | xAxes: [
122 | {
123 | ticks: {
124 | beginAtZero: true,
125 | callback: function(value, index, values) {
126 | return formatDate(value);
127 | }
128 | }
129 | }
130 | ]
131 | }
132 | }
133 | });
134 | }
135 |
--------------------------------------------------------------------------------
/domains/mongodb/seed-db.json:
--------------------------------------------------------------------------------
1 | {
2 | "user": {
3 | "_id": {
4 | "$oid": "60a9f7f255d63b6640beb4a7"
5 | },
6 | "email": "admin@invitation.com",
7 | "username": "admin",
8 | "password": "$2b$10$VhmfGtzS9/IZPQuLQhmXkeTZmXrHYjIV2HCRfsOEp66Yk/OJiwow2",
9 | "password_confirm": "$2b$10$VhmfGtzS9/IZPQuLQhmXkeTZmXrHYjIV2HCRfsOEp66Yk/OJiwow2",
10 | "role": "admin",
11 | "__v": {
12 | "$numberInt": "0"
13 | }
14 | },
15 | "data-config": {
16 | "_id": {
17 | "$oid": "60a9f87655d63b6640beb4a8"
18 | },
19 | "male": {
20 | "name": "Nguyễn Văn An",
21 | "parent": {
22 | "father": "Họ Tên Bố",
23 | "mother": "Họ Tên Mẹ"
24 | },
25 | "location": {
26 | "text": "Quảng Yên - Quảng Ninh - Việt Nam",
27 | "map": "https://goo.gl/maps/tRjKuVRNisqxhQaT7"
28 | },
29 | "time_start": {
30 | "date": {
31 | "lunar": {
32 | "day": "17",
33 | "month": "12",
34 | "year": "2020"
35 | },
36 | "day_of_week": "5",
37 | "solar": {
38 | "day": "17",
39 | "month": "12",
40 | "year": "2020"
41 | }
42 | },
43 | "time": {
44 | "hour": "10",
45 | "minute": "00"
46 | }
47 | },
48 | "finances": [
49 | {
50 | "provider_name": "MB Bank",
51 | "provider_number": "9971997555555",
52 | "holder_name": "NGUYEN VAN AN"
53 | },
54 | {
55 | "provider_name": "Techcombank",
56 | "provider_number": "19034892842011",
57 | "holder_name": "NGUYEN VAN AN"
58 | },
59 | {
60 | "provider_name": "Momo",
61 | "provider_number": "0973999999",
62 | "holder_name": "NGUYEN VAN AN"
63 | },
64 | {
65 | "provider_name": "Airpay",
66 | "provider_number": "0973999999",
67 | "holder_name": "NGUYEN VAN AN"
68 | }
69 | ],
70 | "email": "male@gmail.com",
71 | "phone": "0973999999"
72 | },
73 | "female": {
74 | "name": "Nguyễn Thị Huyền Trang",
75 | "parent": {
76 | "father": "Họ Tên Bố",
77 | "mother": "Họ Tên Mẹ"
78 | },
79 | "location": {
80 | "text": "Quốc Oai - Hà Nội - Việt Nam",
81 | "map": "https://goo.gl/maps/tTZz4qKhaiqSL8Q66"
82 | },
83 | "time_start": {
84 | "date": {
85 | "lunar": {
86 | "day": "17",
87 | "month": "12",
88 | "year": "2020"
89 | },
90 | "day_of_week": "5",
91 | "solar": {
92 | "day": "17",
93 | "month": "12",
94 | "year": "2020"
95 | }
96 | },
97 | "time": {
98 | "hour": "10",
99 | "minute": "00"
100 | }
101 | },
102 | "finances": [
103 | {
104 | "provider_name": "Techcombank",
105 | "provider_number": "19033761344011",
106 | "holder_name": "NGUYEN HUYEN TRANG"
107 | },
108 | {
109 | "provider_name": "Techcombank",
110 | "provider_number": "19033761344011",
111 | "holder_name": "NGUYEN HUYEN TRANG"
112 | },
113 | {
114 | "provider_name": "Momo",
115 | "provider_number": "0973999999",
116 | "holder_name": "NGUYEN VAN AN"
117 | },
118 | {
119 | "provider_name": "Airpay",
120 | "provider_number": "0973999999",
121 | "holder_name": "NGUYEN VAN AN"
122 | }
123 | ],
124 | "email": "female@gmail.com",
125 | "phone": "0985123123"
126 | },
127 | "default": true
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/public/plugins/datatables/responsive.bootstrap4.min.css:
--------------------------------------------------------------------------------
1 | table.dataTable.dtr-inline.collapsed>tbody>tr>td.child,table.dataTable.dtr-inline.collapsed>tbody>tr>th.child,table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty{cursor:default !important}table.dataTable.dtr-inline.collapsed>tbody>tr>td.child:before,table.dataTable.dtr-inline.collapsed>tbody>tr>th.child:before,table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty:before{display:none !important}table.dataTable.dtr-inline.collapsed>tbody>tr>td:first-child,table.dataTable.dtr-inline.collapsed>tbody>tr>th:first-child{position:relative;padding-left:30px;cursor:pointer}table.dataTable.dtr-inline.collapsed>tbody>tr>td:first-child:before,table.dataTable.dtr-inline.collapsed>tbody>tr>th:first-child:before{top:12px;left:4px;height:14px;width:14px;display:block;position:absolute;color:white;border:2px solid white;border-radius:14px;box-shadow:0 0 3px #444;box-sizing:content-box;text-align:center;font-family:'Courier New', Courier, monospace;line-height:14px;content:'+';background-color:#0275d8}table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td:first-child:before,table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th:first-child:before{content:'-';background-color:#d33333}table.dataTable.dtr-inline.collapsed>tbody>tr.child td:before{display:none}table.dataTable.dtr-inline.collapsed.compact>tbody>tr>td:first-child,table.dataTable.dtr-inline.collapsed.compact>tbody>tr>th:first-child{padding-left:27px}table.dataTable.dtr-inline.collapsed.compact>tbody>tr>td:first-child:before,table.dataTable.dtr-inline.collapsed.compact>tbody>tr>th:first-child:before{top:5px;left:4px;height:14px;width:14px;border-radius:14px;line-height:14px;text-indent:3px}table.dataTable.dtr-column>tbody>tr>td.control,table.dataTable.dtr-column>tbody>tr>th.control{position:relative;cursor:pointer}table.dataTable.dtr-column>tbody>tr>td.control:before,table.dataTable.dtr-column>tbody>tr>th.control:before{top:50%;left:50%;height:16px;width:16px;margin-top:-10px;margin-left:-10px;display:block;position:absolute;color:white;border:2px solid white;border-radius:14px;box-shadow:0 0 3px #444;box-sizing:content-box;text-align:center;font-family:'Courier New', Courier, monospace;line-height:14px;content:'+';background-color:#0275d8}table.dataTable.dtr-column>tbody>tr.parent td.control:before,table.dataTable.dtr-column>tbody>tr.parent th.control:before{content:'-';background-color:#d33333}table.dataTable>tbody>tr.child{padding:0.5em 1em}table.dataTable>tbody>tr.child:hover{background:transparent !important}table.dataTable>tbody>tr.child ul{display:inline-block;list-style-type:none;margin:0;padding:0}table.dataTable>tbody>tr.child ul li{border-bottom:1px solid #efefef;padding:0.5em 0}table.dataTable>tbody>tr.child ul li:first-child{padding-top:0}table.dataTable>tbody>tr.child ul li:last-child{border-bottom:none}table.dataTable>tbody>tr.child span.dtr-title{display:inline-block;min-width:75px;font-weight:bold}div.dtr-modal{position:fixed;box-sizing:border-box;top:0;left:0;height:100%;width:100%;z-index:100;padding:10em 1em}div.dtr-modal div.dtr-modal-display{position:absolute;top:0;left:0;bottom:0;right:0;width:50%;height:50%;overflow:auto;margin:auto;z-index:102;overflow:auto;background-color:#f5f5f7;border:1px solid black;border-radius:0.5em;box-shadow:0 12px 30px rgba(0,0,0,0.6)}div.dtr-modal div.dtr-modal-content{position:relative;padding:1em}div.dtr-modal div.dtr-modal-close{position:absolute;top:6px;right:6px;width:22px;height:22px;border:1px solid #eaeaea;background-color:#f9f9f9;text-align:center;border-radius:3px;cursor:pointer;z-index:12}div.dtr-modal div.dtr-modal-close:hover{background-color:#eaeaea}div.dtr-modal div.dtr-modal-background{position:fixed;top:0;left:0;right:0;bottom:0;z-index:101;background:rgba(0,0,0,0.6)}@media screen and (max-width: 767px){div.dtr-modal div.dtr-modal-display{width:95%}}div.dtr-bs-modal table.table tr:first-child td{border-top:none}
2 |
--------------------------------------------------------------------------------
/public/assets/css/bootstrap-reboot.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
3 | * Copyright 2011-2019 The Bootstrap Authors
4 | * Copyright 2011-2019 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */
--------------------------------------------------------------------------------
/public/plugins/datatables/buttons.bootstrap4.min.css:
--------------------------------------------------------------------------------
1 | @keyframes dtb-spinner{100%{transform:rotate(360deg)}}@-o-keyframes dtb-spinner{100%{-o-transform:rotate(360deg);transform:rotate(360deg)}}@-ms-keyframes dtb-spinner{100%{-ms-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dtb-spinner{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-moz-keyframes dtb-spinner{100%{-moz-transform:rotate(360deg);transform:rotate(360deg)}}div.dt-button-info{position:fixed;top:50%;left:50%;width:400px;margin-top:-100px;margin-left:-200px;background-color:white;border:2px solid #111;box-shadow:3px 3px 8px rgba(0,0,0,0.3);border-radius:3px;text-align:center;z-index:21}div.dt-button-info h2{padding:0.5em;margin:0;font-weight:normal;border-bottom:1px solid #ddd;background-color:#f3f3f3}div.dt-button-info>div{padding:1em}ul.dt-button-collection.dropdown-menu{display:block;z-index:2002;-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}ul.dt-button-collection.dropdown-menu.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}ul.dt-button-collection.dropdown-menu.fixed.two-column{margin-left:-150px}ul.dt-button-collection.dropdown-menu.fixed.three-column{margin-left:-225px}ul.dt-button-collection.dropdown-menu.fixed.four-column{margin-left:-300px}ul.dt-button-collection.dropdown-menu>*{-webkit-column-break-inside:avoid;break-inside:avoid}ul.dt-button-collection.dropdown-menu.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}ul.dt-button-collection.dropdown-menu.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}ul.dt-button-collection.dropdown-menu.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}ul.dt-button-collection.dropdown-menu .dt-button{border-radius:0}ul.dt-button-collection{-webkit-column-gap:8px;-moz-column-gap:8px;-ms-column-gap:8px;-o-column-gap:8px;column-gap:8px}ul.dt-button-collection.fixed{position:fixed;top:50%;left:50%;margin-left:-75px;border-radius:0}ul.dt-button-collection.fixed.two-column{margin-left:-150px}ul.dt-button-collection.fixed.three-column{margin-left:-225px}ul.dt-button-collection.fixed.four-column{margin-left:-300px}ul.dt-button-collection>*{-webkit-column-break-inside:avoid;break-inside:avoid}ul.dt-button-collection.two-column{width:300px;padding-bottom:1px;-webkit-column-count:2;-moz-column-count:2;-ms-column-count:2;-o-column-count:2;column-count:2}ul.dt-button-collection.three-column{width:450px;padding-bottom:1px;-webkit-column-count:3;-moz-column-count:3;-ms-column-count:3;-o-column-count:3;column-count:3}ul.dt-button-collection.four-column{width:600px;padding-bottom:1px;-webkit-column-count:4;-moz-column-count:4;-ms-column-count:4;-o-column-count:4;column-count:4}ul.dt-button-collection .dt-button{border-radius:0}ul.dt-button-collection.fixed{max-width:none}ul.dt-button-collection.fixed:before,ul.dt-button-collection.fixed:after{display:none}div.dt-button-background{position:fixed;top:0;left:0;width:100%;height:100%;z-index:999}@media screen and (max-width: 767px){div.dt-buttons{float:none;width:100%;text-align:center;margin-bottom:0.5em}div.dt-buttons a.btn{float:none}}div.dt-buttons button.btn.processing,div.dt-buttons div.btn.processing,div.dt-buttons a.btn.processing{color:rgba(0,0,0,0.2)}div.dt-buttons button.btn.processing:after,div.dt-buttons div.btn.processing:after,div.dt-buttons a.btn.processing:after{position:absolute;top:50%;left:50%;width:16px;height:16px;margin:-8px 0 0 -8px;box-sizing:border-box;display:block;content:' ';border:2px solid #282828;border-radius:50%;border-left-color:transparent;border-right-color:transparent;animation:dtb-spinner 1500ms infinite linear;-o-animation:dtb-spinner 1500ms infinite linear;-ms-animation:dtb-spinner 1500ms infinite linear;-webkit-animation:dtb-spinner 1500ms infinite linear;-moz-animation:dtb-spinner 1500ms infinite linear}
2 |
--------------------------------------------------------------------------------
/public/assets/js/layout.js:
--------------------------------------------------------------------------------
1 | function pad(num, size) {
2 | var s = num + "";
3 | while (s.length < size) s = "0" + s;
4 | return s;
5 | }
6 |
7 | function updateTime() {
8 | var today = new Date();
9 | $("#hour").val(pad(today.getHours(), 2));
10 | $("#minutes").val(pad(today.getMinutes(), 2));
11 | }
12 |
13 |
14 | function clockUpdate() {
15 | var date = new Date();
16 |
17 | var h = pad(date.getHours(), 2);
18 | var m = pad(date.getMinutes(), 2);
19 | var s = pad(date.getSeconds(), 2);
20 |
21 | $('.digital-clock').text(h + ':' + m + ':' + s);
22 | }
23 |
24 | function init(){
25 | clockUpdate();
26 | setInterval(clockUpdate, 1000);
27 | }
28 |
29 | init();
30 |
31 |
32 |
33 |
34 |
35 | /*
36 | Template Name: Veltrix - Responsive Bootstrap 4 Admin Dashboard
37 | Author: Themesbrand
38 | File: table editable Init
39 | */
40 |
41 | (function ($) {
42 |
43 | var datatable = $('.table-editable').dataTable({
44 | "columns": [
45 | { "name": "id" },
46 | { "name": "age" },
47 | { "name": "qty" },
48 | { "name": "cost" },
49 | ],
50 | "bPaginate": false,
51 | "fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
52 | var setCell = function(response, newValue) {
53 | var table = new $.fn.dataTable.Api('.table');
54 | var cell = table.cell('td.focus');
55 | var cellData = cell.data();
56 |
57 | var div = document.createElement('div');
58 | div.innerHTML = cellData;
59 | var a = div.childNodes;
60 | a.innerHTML = newValue;
61 |
62 | console.log('jml a new ' + div.innerHTML);
63 | cell.data(div.innerHTML);
64 | highlightCell($(cell.node()));
65 |
66 | // This is huge cheese, but the a has lost it's editable nature. Do it again.
67 | $('td.focus a').editable({
68 | 'mode': 'inline',
69 | 'success' : setCell
70 | });
71 | };
72 | $('.editable').editable(
73 | {
74 | 'mode': 'inline',
75 | 'success' : setCell
76 | }
77 | );
78 | },
79 | "autoFill" : {
80 | "columns" : [1, 2]
81 | },
82 | "keys" : true
83 | });
84 |
85 | addCellChangeHandler();
86 | addAutoFillHandler();
87 |
88 | function highlightCell($cell) {
89 | var originalValue = $cell.attr('data-original-value');
90 | if (!originalValue) {
91 | return;
92 | }
93 | var actualValue = $cell.text();
94 | if (!isNaN(originalValue)) {
95 | originalValue = parseFloat(originalValue);
96 | }
97 | if (!isNaN(actualValue)) {
98 | actualValue = parseFloat(actualValue);
99 | }
100 | if ( originalValue === actualValue ) {
101 | $cell.removeClass('cat-cell-modified').addClass('cat-cell-original');
102 | } else {
103 | $cell.removeClass('cat-cell-original').addClass('cat-cell-modified');
104 | }
105 | }
106 |
107 | function addCellChangeHandler() {
108 | $('a[data-pk]').on('hidden', function (e, editable) {
109 | var $a = $(this);
110 | var $cell = $a.parent('td');
111 | highlightCell($cell);
112 | });
113 | }
114 |
115 | function addAutoFillHandler() {
116 | var table = $('.table').DataTable();
117 | table.on('autoFill', function (e, datatable, cells) {
118 | var datatableCellApis = $.each(cells, function(index, row) {
119 | var datatableCellApi = row[0].cell;
120 | var $jQueryObject = $(datatableCellApi.node());
121 | highlightCell($jQueryObject);
122 | });
123 | });
124 | }
125 |
126 | })(jQuery);
--------------------------------------------------------------------------------