├── static
├── .gitkeep
└── app.js
├── src
├── plugins
│ └── index.js
├── assets
│ ├── logo.png
│ ├── avatar.jpg
│ └── page-cannot-be-found.jpg
├── store
│ └── index.js
├── stylesheets
│ └── rtl.css
├── langs
│ └── langs.js
├── components
│ ├── Unavailable.vue
│ ├── Login.vue
│ ├── Sidebar.vue
│ ├── Dashboard.vue
│ ├── App.vue
│ └── ModelList.vue
├── filters
│ └── index.js
└── main.js
├── api
├── .eslintignore
├── .eslintrc
├── .yo-rc.json
├── README.md
├── client
│ └── README.md
├── common
│ ├── models
│ │ ├── posts.js
│ │ ├── enquiries.js
│ │ ├── uploads.js
│ │ ├── uploads.json
│ │ ├── enquiries.json
│ │ └── posts.json
│ └── User.json
├── uploads
│ └── files
│ │ ├── as.jpg
│ │ └── 5d4f5de8-39b2-43f4-8e3a-6909c15722c6.jpg
├── server
│ ├── models
│ │ ├── uploads.js
│ │ └── uploads.json
│ ├── component-config.json
│ ├── boot
│ │ ├── authentication.js
│ │ ├── debug.js
│ │ ├── upload.js
│ │ ├── script.js
│ │ └── root.js
│ ├── middleware.development.json
│ ├── config.json
│ ├── datasources.json
│ ├── middleware.json
│ ├── server.js
│ └── model-config.json
├── .editorconfig
└── package.json
├── _config.yml
├── config
├── prod.env.js
├── test.env.js
├── configs.js
├── dev.env.js
└── index.js
├── docs
├── vue.png
├── demo.jpg
├── image.png
├── mongo.png
├── .gitignore
├── loopback.png
├── objects.inv
├── _static
│ ├── up.png
│ ├── demo.jpg
│ ├── down.png
│ ├── file.png
│ ├── image.png
│ ├── minus.png
│ ├── plus.png
│ ├── comment.png
│ ├── up-pressed.png
│ ├── ajax-loader.gif
│ ├── comment-close.png
│ ├── down-pressed.png
│ ├── comment-bright.png
│ ├── fonts
│ │ ├── Lato-Bold.ttf
│ │ ├── Lato-Regular.ttf
│ │ ├── Inconsolata-Bold.ttf
│ │ ├── RobotoSlab-Bold.ttf
│ │ ├── Inconsolata-Regular.ttf
│ │ ├── RobotoSlab-Regular.ttf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.ttf
│ │ └── fontawesome-webfont.woff
│ ├── css
│ │ └── badge_only.css
│ ├── pygments.css
│ ├── js
│ │ ├── theme.js
│ │ └── modernizr.min.js
│ ├── doctools.js
│ ├── underscore.js
│ └── basic.css
├── .vscode
│ └── settings.json
├── index.html
├── getting.html
├── project.html
└── start.html
├── .gitignore
├── .editorconfig
├── .babelrc
├── index.html
├── npm-debug.log.746407735
├── package.json
└── README.md
/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/app.js:
--------------------------------------------------------------------------------
1 | an
--------------------------------------------------------------------------------
/src/plugins/index.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/api/.eslintignore:
--------------------------------------------------------------------------------
1 | /client/
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/api/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "loopback"
3 | }
--------------------------------------------------------------------------------
/api/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-loopback": {}
3 | }
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
4 |
--------------------------------------------------------------------------------
/docs/vue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/vue.png
--------------------------------------------------------------------------------
/docs/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/demo.jpg
--------------------------------------------------------------------------------
/docs/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/image.png
--------------------------------------------------------------------------------
/docs/mongo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/mongo.png
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | _site/
2 | .sass-cache/
3 | .jekyll-metadata
4 | _pdf
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/docs/loopback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/loopback.png
--------------------------------------------------------------------------------
/docs/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/objects.inv
--------------------------------------------------------------------------------
/docs/_static/up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/up.png
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/api/README.md:
--------------------------------------------------------------------------------
1 | # My Application
2 |
3 | The project is generated by [LoopBack](http://loopback.io).
--------------------------------------------------------------------------------
/docs/_static/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/demo.jpg
--------------------------------------------------------------------------------
/docs/_static/down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/down.png
--------------------------------------------------------------------------------
/docs/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/file.png
--------------------------------------------------------------------------------
/docs/_static/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/image.png
--------------------------------------------------------------------------------
/docs/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/minus.png
--------------------------------------------------------------------------------
/docs/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/plus.png
--------------------------------------------------------------------------------
/src/assets/avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/src/assets/avatar.jpg
--------------------------------------------------------------------------------
/api/client/README.md:
--------------------------------------------------------------------------------
1 | ## Client
2 |
3 | This is the place for your application front-end files.
4 |
--------------------------------------------------------------------------------
/api/common/models/posts.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Posts) {
4 |
5 | };
6 |
--------------------------------------------------------------------------------
/api/uploads/files/as.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/api/uploads/files/as.jpg
--------------------------------------------------------------------------------
/docs/_static/comment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/comment.png
--------------------------------------------------------------------------------
/api/common/models/enquiries.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Enquiries) {
4 |
5 | };
6 |
--------------------------------------------------------------------------------
/api/common/models/uploads.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Uploads) {
4 |
5 | };
6 |
--------------------------------------------------------------------------------
/api/server/models/uploads.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Uploads) {
4 |
5 | };
6 |
--------------------------------------------------------------------------------
/docs/_static/up-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/up-pressed.png
--------------------------------------------------------------------------------
/docs/_static/ajax-loader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/ajax-loader.gif
--------------------------------------------------------------------------------
/docs/_static/comment-close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/comment-close.png
--------------------------------------------------------------------------------
/docs/_static/down-pressed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/down-pressed.png
--------------------------------------------------------------------------------
/docs/_static/comment-bright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/comment-bright.png
--------------------------------------------------------------------------------
/docs/_static/fonts/Lato-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/Lato-Bold.ttf
--------------------------------------------------------------------------------
/docs/_static/fonts/Lato-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/Lato-Regular.ttf
--------------------------------------------------------------------------------
/src/assets/page-cannot-be-found.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/src/assets/page-cannot-be-found.jpg
--------------------------------------------------------------------------------
/api/server/component-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "loopback-component-explorer": {
3 | "mountPath": "/explorer"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/docs/_static/fonts/Inconsolata-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/Inconsolata-Bold.ttf
--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/RobotoSlab-Bold.ttf
--------------------------------------------------------------------------------
/docs/_static/fonts/Inconsolata-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/Inconsolata-Regular.ttf
--------------------------------------------------------------------------------
/docs/_static/fonts/RobotoSlab-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/RobotoSlab-Regular.ttf
--------------------------------------------------------------------------------
/docs/_static/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/docs/_static/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/docs/_static/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/docs/_static/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | api/uploads
5 | npm-debug.log
6 | test/unit/coverage
7 | test/e2e/reports
8 | selenium-debug.log
9 |
--------------------------------------------------------------------------------
/api/uploads/files/5d4f5de8-39b2-43f4-8e3a-6909c15722c6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vah7id/flashboard/HEAD/api/uploads/files/5d4f5de8-39b2-43f4-8e3a-6909c15722c6.jpg
--------------------------------------------------------------------------------
/config/test.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var devEnv = require('./dev.env')
3 |
4 | module.exports = merge(devEnv, {
5 | NODE_ENV: '"testing"'
6 | })
7 |
--------------------------------------------------------------------------------
/api/server/boot/authentication.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function enableAuthentication(server) {
4 | // enable authentication
5 | server.enableAuth();
6 | };
7 |
--------------------------------------------------------------------------------
/docs/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.associations": {
4 | "*.html": "liquid"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-2"],
3 | "plugins": ["transform-runtime"],
4 | "comments": false,
5 | "env": {
6 | "test": {
7 | "plugins": [ "istanbul" ]
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/api/server/middleware.development.json:
--------------------------------------------------------------------------------
1 | {
2 | "final:after": {
3 | "strong-error-handler": {
4 | "params": {
5 | "debug": true,
6 | "log": true
7 | }
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/config/configs.js:
--------------------------------------------------------------------------------
1 |
2 | var env = 'development'//process.env.APP_ENV ||
3 |
4 | var config = {
5 | development: require('./dev.env.js'),
6 | production: require('./prod.env.js'),
7 | staging: require('./test.env.js')
8 | }
9 |
10 | module.exports = config[env]
--------------------------------------------------------------------------------
/api/server/models/uploads.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Uploads",
3 | "base": "PersistedModel",
4 | "idInjection": true,
5 | "options": {
6 | "validateUpsert": true
7 | },
8 | "properties": {},
9 | "validations": [],
10 | "relations": {},
11 | "acls": [],
12 | "methods": {}
13 | }
14 |
--------------------------------------------------------------------------------
/api/common/models/uploads.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "uploads",
3 | "base": "Model",
4 | "idInjection": true,
5 | "options": {
6 | "validateUpsert": true,
7 | "hidden":true
8 | },
9 | "properties": {},
10 | "validations": [],
11 | "relations": {},
12 | "acls": [],
13 | "methods": {}
14 | }
15 |
--------------------------------------------------------------------------------
/api/server/boot/debug.js:
--------------------------------------------------------------------------------
1 | module.exports = function(app) {
2 | var User = app.loopback.getModel('User');
3 | User.settings.acls = [
4 | {
5 | "accessType": "EXECUTE",
6 | "principalType": "ROLE",
7 | "principalId": "$owner",
8 | "permission": "ALLOW",
9 | "property": "__get__orders"
10 | }];
11 | };
--------------------------------------------------------------------------------
/api/.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 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 |
5 | module.exports = merge(prodEnv, {
6 | //Application Configs Json
7 | NODE_ENV: '"development"',
8 | API_BASE_URL: 'http://127.0.0.1',
9 | API_PORT: 3000,
10 | THEME: 'carbon',
11 | LOGO: 'src/assets/logo.png',
12 | BRAND: 'FLASHBOARD',
13 | forbidden_download: false,
14 | disable_admin:false,
15 | lang: "en",
16 | rtl: false,
17 | GOOGLE_VIEWID: '157657595'
18 | })
19 |
--------------------------------------------------------------------------------
/api/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "restApiRoot": "/api",
3 | "host": "0.0.0.0",
4 | "port": 3000,
5 | "remoting": {
6 | "context": false,
7 | "rest": {
8 | "normalizeHttpPath": false,
9 | "xml": false
10 | },
11 | "json": {
12 | "strict": false,
13 | "limit": "10000kb"
14 | },
15 | "urlencoded": {
16 | "extended": true,
17 | "limit": "10000kb"
18 | },
19 | "cors": true,
20 | "handleErrors": false
21 | },
22 | "legacyExplorer": false
23 | }
24 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FLASHBOARD
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/api/server/datasources.json:
--------------------------------------------------------------------------------
1 | {
2 | "db": {
3 | "name": "db",
4 | "connector": "remote"
5 | },
6 | "flashDB": {
7 | "host": "198.199.102.94",
8 | "port": 27017,
9 | "url": "mongodb://198.199.102.94:27017/flashboard",
10 | "database": "flashboard",
11 | "password": "",
12 | "name": "flashDB",
13 | "user": "",
14 | "connector": "mongodb"
15 | },
16 | "container": {
17 | "name": "container",
18 | "connector": "loopback-component-storage",
19 | "provider": "filesystem",
20 | "maxFileSize": "1000048576",
21 | "root": "uploads"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | // User object will let us check authentication status
4 | store: {} ,
5 | localStorage: window.localStorage,
6 |
7 | get(key){
8 | return this.localStorage.getItem(key);
9 | },
10 |
11 | set(key,value){
12 | this.localStorage.setItem(key,value);
13 | this.store[key] = value;
14 | },
15 |
16 | remove(key){
17 | this.localStorage.removeItem(key);
18 | delete this.store[key];
19 | },
20 |
21 | clearAll(){
22 | console.log('deletre kon dgee')
23 | this.localStorage.clear();
24 | },
25 |
26 | state(){
27 | return this.store;
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/api/server/boot/upload.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Uploads) {
4 |
5 | Uploads.upload = function(req, res, Uploads_id, cb) {
6 |
7 | var StorageContainer = Uploads.app.models.StorageContainer;
8 |
9 | StorageContainer.getContainers(function (err, containers) {
10 | if (containers.some(function(e) { return e.name == Uploads_id; })) {
11 | StorageContainer.upload(req, res, {container: Uploads_id}, cb);
12 | }
13 | else {
14 | StorageContainer.createContainer({name: Uploads_id}, function(err, c) {
15 | StorageContainer.upload(req, res, {container: c.name}, cb);
16 | });
17 | }
18 | });
19 | };
20 |
21 | };
--------------------------------------------------------------------------------
/api/common/models/enquiries.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "enquiries",
3 | "base": "PersistedModel",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true,
8 | "nocreate": true
9 | },
10 | "properties": {
11 | "id": {
12 | "type": "string",
13 | "id": true,
14 | "index": true
15 | },
16 | "title": {
17 | "type": "string",
18 | "required": true,
19 | "defaultColumn": true
20 | },
21 | "message": {
22 | "type": "string",
23 | "uiType": "textarea"
24 | },
25 | "type": {
26 | "type": "string",
27 | "uiType": "select",
28 | "options": [{"value":"emergency","label":"Emergency"},{"value":"not_emergency","label":"Not Emergency"}]
29 | }
30 | },
31 | "validations": [],
32 | "relations": {},
33 | "acls": [],
34 | "methods": {}
35 | }
36 |
--------------------------------------------------------------------------------
/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lemon-api",
3 | "version": "1.0.0",
4 | "main": "server/server.js",
5 | "scripts": {
6 | "lint": "eslint .",
7 | "start": "node .",
8 | "posttest": "npm run lint && nsp check"
9 | },
10 | "dependencies": {
11 | "compression": "^1.0.3",
12 | "cors": "^2.5.2",
13 | "googleapis": "^20.1.0",
14 | "helmet": "^1.3.0",
15 | "loopback": "^2.22.0",
16 | "loopback-boot": "^2.6.5",
17 | "loopback-component-explorer": "^2.4.0",
18 | "loopback-component-storage": "^3.2.0",
19 | "loopback-connector-mongodb": "^3.0.1",
20 | "loopback-connector-mysql": "^3.0.0",
21 | "loopback-datasource-juggler": "^2.39.0",
22 | "serve-favicon": "^2.0.1",
23 | "strong-error-handler": "^1.0.1"
24 | },
25 | "devDependencies": {
26 | "eslint": "^2.13.1",
27 | "eslint-config-loopback": "^4.0.0",
28 | "nsp": "^2.1.0"
29 | },
30 | "repository": {
31 | "type": "",
32 | "url": ""
33 | },
34 | "license": "UNLICENSED",
35 | "description": "lemon-api"
36 | }
37 |
--------------------------------------------------------------------------------
/api/server/middleware.json:
--------------------------------------------------------------------------------
1 | {
2 | "initial:before": {
3 | "loopback#favicon": {}
4 | },
5 | "initial": {
6 | "compression": {},
7 | "cors": {
8 | "params": {
9 | "origin": true,
10 | "credentials": true,
11 | "maxAge": 86400
12 | }
13 | },
14 | "helmet#xssFilter": {},
15 | "helmet#frameguard": {
16 | "params": [
17 | "deny"
18 | ]
19 | },
20 | "helmet#hsts": {
21 | "params": {
22 | "maxAge": 0,
23 | "includeSubdomains": true
24 | }
25 | },
26 | "helmet#hidePoweredBy": {},
27 | "helmet#ieNoOpen": {},
28 | "helmet#noSniff": {},
29 | "helmet#noCache": {
30 | "enabled": false
31 | }
32 | },
33 | "session": {},
34 | "auth": {},
35 | "parse": {},
36 | "routes": {
37 | "loopback#rest": {
38 | "paths": [
39 | "${restApiRoot}"
40 | ]
41 | }
42 | },
43 | "files": {},
44 | "final": {
45 | "loopback#urlNotFound": {}
46 | },
47 | "final:after": {
48 | "strong-error-handler": {}
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/api/server/boot/script.js:
--------------------------------------------------------------------------------
1 | module.exports = function (app) {
2 | var _ = require('lodash');
3 | var User = app.models.User;
4 | var Role = app.models.Role;
5 | var RoleMapping = app.models.RoleMapping;
6 | var ACL = app.models.ACL;
7 |
8 | User.create([{
9 | username: 'flashboard',
10 | email: 'admin@flashboard.com',
11 | password: 'qwertyuiop',
12 | type: 'admin'
13 | }], function(err, users) {
14 |
15 | Role.find({ name: 'admin' }, function(err, results) {
16 | //if (err) console.log(err);
17 |
18 | // Create the admin role
19 | Role.create({
20 | name: 'admin'
21 | }, function(err, role) {
22 | if (err);
23 | //debug(role);
24 | role.principals.create({
25 | principalType: RoleMapping.USER,
26 | principalId: users[0].id
27 | }, function(err, principal) {
28 | if (err) console.log(err);
29 |
30 | });
31 | });
32 |
33 | //if (results.length < 1) {
34 | // now we know the DB doesn't have it already, so do the Role creation...
35 | // }
36 | });
37 |
38 | });
39 | };
40 |
41 |
--------------------------------------------------------------------------------
/api/server/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var loopback = require('loopback');
4 | var boot = require('loopback-boot');
5 |
6 | var app = module.exports = loopback();
7 |
8 | app.start = function() {
9 | // start the web server
10 | return app.listen(function() {
11 | app.emit('started');
12 | var baseUrl = app.get('url').replace(/\/$/, '');
13 |
14 | console.log('\x1b[32m', '\n******************************************* \n')
15 | console.log('\x1b[32m', 'FLASHBOARD Services started successfully :) \n');
16 | console.log('\x1b[32m', '******************************************* \n');
17 |
18 | console.log('Web server listening at: %s', baseUrl);
19 |
20 | if (app.get('loopback-component-explorer')) {
21 | var explorerPath = app.get('loopback-component-explorer').mountPath;
22 | console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
23 | }
24 | });
25 | };
26 |
27 | // Bootstrap the application, configure models, datasources and middleware.
28 | // Sub-apps like REST API are mounted via boot scripts.
29 | boot(app, __dirname, function(err) {
30 | if (err) throw err;
31 |
32 | // start the server if `$ node server.js`
33 | if (require.main === module)
34 | app.start();
35 | });
36 |
--------------------------------------------------------------------------------
/api/common/models/posts.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "posts",
3 | "base": "PersistedModel",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "id": {
11 | "type": "string",
12 | "id": true,
13 | "index": true
14 | },
15 | "title": {
16 | "type": "string",
17 | "required": true,
18 | "defaultColumn": true
19 | },
20 | "thumbnail": {
21 | "type": "Object",
22 | "uiType": "file",
23 | "options": {
24 | "maxSize": "20000"
25 | }
26 | },
27 | "author": {
28 | "label": "author",
29 | "type": "string",
30 | "uiType": "Relationship",
31 | "options": {
32 | "ref": "Users",
33 | "filter": { "type": "user" },
34 | "key": "email"
35 | }
36 | },
37 | "description": {
38 | "type": "string",
39 | "uiType": "html",
40 | "options": { "placeholder": "Some text...", "theme": "snow" }
41 | },
42 | "published_date": {
43 | "type": "string",
44 | "uiType": "date",
45 | "defaultColumn": true
46 |
47 | }
48 | },
49 | "validations": [],
50 | "relations": {},
51 | "acls": [],
52 | "methods": {}
53 | }
54 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: 'dist/static',
10 | assetsPublicPath: 'dist',
11 | productionSourceMap: false,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css']
18 | },
19 | dev: {
20 | env: require('./dev.env'),
21 | port: 8080,
22 | assetsSubDirectory: 'static',
23 | assetsPublicPath: '/',
24 | proxyTable: {},
25 | // CSS Sourcemaps off by default because relative paths are "buggy"
26 | // with this option, according to the CSS-Loader README
27 | // (https://github.com/webpack/css-loader#sourcemaps)
28 | // In our experience, they generally work as expected,
29 | // just be aware of this issue when enabling this option.
30 | cssSourceMap: false
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/stylesheets/rtl.css:
--------------------------------------------------------------------------------
1 |
2 | .mu-raised-button-wrapper{
3 | padding: 10px !important;
4 | }
5 |
6 | a{color: #2196f3}
7 | body{
8 | direction: rtl;
9 | text-align: right;
10 | font-family: Vazir !important;
11 | }
12 | .count{
13 | font-family: Vazir !important;
14 | }
15 | h1,h2,h3,h4{
16 | font-weight: 900;
17 | }
18 | .mu-text-field-input{
19 | text-align: right !important;
20 | }
21 | .mu-drawer{
22 | right: 0 !important;
23 | left: initial !important;
24 | }
25 | .page--title{
26 | float: right !important;
27 | }
28 | #page--title{
29 | padding-left: 0 !important;
30 | }
31 |
32 | .ripple,.ripple i{
33 | float: right !important;
34 | }
35 | .ripple i{
36 | padding-right: 10px !important;
37 | }
38 | .mu-content-block-board{
39 | float: left;
40 | }
41 |
42 | .mu-paper{
43 | float: right;
44 | }
45 | .focus-state .mu-text-field-label,.no-empty-state .mu-text-field-label{
46 | right: -20px !important;
47 | }
48 | .btn-add{
49 | float: left;
50 | margin-left: 30px !important;
51 | }
52 | .item-uploaded{
53 | float: right;
54 | }
55 | .mu-drawer .mu-avatar{
56 | float: right;
57 | }
58 | #btn-delete{
59 | right: initial !important;
60 | left: 30px !important;
61 | }
62 | .mu-snackbar{
63 | right: initial !important;
64 | left: 5% !important;
65 | }
66 | .mu-appbar-title{
67 | padding-right: 55px !important;
68 | }
69 |
70 | /*# sourceMappingURL=rtl.css.map */
--------------------------------------------------------------------------------
/api/server/model-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "sources": [
4 | "loopback/common/models",
5 | "loopback/server/models",
6 | "../common/models",
7 | "./models"
8 | ],
9 | "mixins": [
10 | "loopback/common/mixins",
11 | "loopback/server/mixins",
12 | "../common/mixins",
13 | "./mixins"
14 | ]
15 | },
16 | "User": {
17 | "dataSource": "flashDB",
18 | "public": true
19 | },
20 | "AccessToken": {
21 | "dataSource": "flashDB",
22 | "public": false
23 | },
24 | "ACL": {
25 | "dataSource": "flashDB",
26 | "public": true
27 | },
28 | "RoleMapping": {
29 | "dataSource": "flashDB",
30 | "public": false
31 | },
32 | "Role": {
33 | "dataSource": "flashDB",
34 | "public": true,
35 | "$options": {
36 | "base": "Role",
37 | "relations": {
38 | "principals": {
39 | "type": "hasMany",
40 | "model": "roleMapping",
41 | "foreignKey": "roleId"
42 | }
43 | }
44 | }
45 | },
46 | "posts": {
47 | "dataSource": "flashDB",
48 | "public": true,
49 | "$promise": {},
50 | "$resolved": true
51 | },
52 | "enquiries": {
53 | "dataSource": "flashDB",
54 | "public": true,
55 | "$promise": {},
56 | "$resolved": true
57 | },
58 | "uploads": {
59 | "dataSource": "container",
60 | "public": true
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/api/server/boot/root.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var google = require('googleapis');
4 | //const key = require('google.json');
5 |
6 | var env = require("../../../config/configs.js");
7 |
8 | module.exports = function(server) {
9 | // Install a `/` route that returns server status
10 | var router = server.loopback.Router();
11 | router.get('/', server.loopback.status());
12 |
13 | router.get('/googleAnalytics', function(req, res) {
14 |
15 | const VIEW_ID = 'ga:'+env.GOOGLE_VIEWID;
16 |
17 | if(require.resolve('google.json')){
18 | var key = require('google.json');
19 | } else {
20 | console.log('google json file dosn"t exist');
21 | return;
22 | }
23 | let jwtClient = new google.auth.JWT(
24 | key.client_email, null, key.private_key,
25 | ['https://www.googleapis.com/auth/analytics.readonly'], null);
26 |
27 | jwtClient.authorize(function (err, tokens) {
28 |
29 | if (err) {
30 | console.log(err);
31 | return;
32 | }
33 |
34 | let analytics = google.analytics('v3');
35 |
36 | analytics.data.ga.get({
37 | 'auth': jwtClient,
38 | 'ids': VIEW_ID,
39 | 'metrics': 'ga:users,ga:pageviews',
40 | 'dimensions': 'ga:date',
41 | 'start-date': '30daysAgo',
42 | 'end-date': 'today',
43 | 'max-results': 31
44 | }, function (err, response) {
45 | if (err) {
46 | console.log(err);
47 | return;
48 | }
49 | res.status(200).json(response);
50 | });
51 |
52 | });
53 |
54 | });
55 |
56 | server.use(router);
57 | };
58 |
--------------------------------------------------------------------------------
/npm-debug.log.746407735:
--------------------------------------------------------------------------------
1 | 0 info it worked if it ends with ok
2 | 1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'run', 'de' ]
3 | 2 info using npm@4.1.2
4 | 3 info using node@v7.6.0
5 | 4 verbose stack Error: missing script: de
6 | 4 verbose stack at run (/usr/local/lib/node_modules/npm/lib/run-script.js:151:19)
7 | 4 verbose stack at /usr/local/lib/node_modules/npm/lib/run-script.js:61:5
8 | 4 verbose stack at /usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:356:5
9 | 4 verbose stack at checkBinReferences_ (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:320:45)
10 | 4 verbose stack at final (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:354:3)
11 | 4 verbose stack at then (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:124:5)
12 | 4 verbose stack at /usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:311:12
13 | 4 verbose stack at /usr/local/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:78:16
14 | 4 verbose stack at tryToString (fs.js:447:3)
15 | 4 verbose stack at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:434:12)
16 | 5 verbose cwd /Users/vahid/Documents/Development/flashboard
17 | 6 error Darwin 14.0.0
18 | 7 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "de"
19 | 8 error node v7.6.0
20 | 9 error npm v4.1.2
21 | 10 error missing script: de
22 | 11 error If you need help, you may report this error at:
23 | 11 error
24 | 12 verbose exit [ 1, true ]
25 |
--------------------------------------------------------------------------------
/src/langs/langs.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = {
4 |
5 | "en":{
6 | "sign_in": "Sign In",
7 | "sign_in_msg": "Sign In To",
8 | "email":"email",
9 | "password":"password",
10 | "username or email is required":"username or email is required",
11 | "login failed": "login failed",
12 | "edit_profile":"Edit Profile",
13 | "sign_out":"Sign Out",
14 | "Dashboard": "Dashboard",
15 | "api_explorer":"Api Explorer",
16 | "api_docs":"API Documentation",
17 | "items": "items",
18 | "create_item": "Create Item",
19 | "edit_item":"Edit Item",
20 | "upload_now": "Upload Now",
21 | "save_item": "Save Item",
22 | "actions": "Actions",
23 | "total":"Total",
24 | "columns": "Columns",
25 | "search":"Search",
26 | "download":"Download",
27 | "json_object":"JSON Object",
28 | "csv_format":"CSV Format",
29 | "edit":"Edit",
30 | "empty_list":"Empty list items"
31 | },
32 | "fa": {
33 | "sign_in": "ورود به پیشخوان",
34 | "sign_in_msg": "ورود به",
35 | "email":"پست الکترونیکی",
36 | "password":"کلمه عبور",
37 | "username or email is required":"پست الکترونیکی یا کلمه عب.ر اشتباه وارد شده است",
38 | "login failed": "مشکل در ورود به سیستم",
39 | "edit_profile":"ویرایش پروفایل",
40 | "sign_out":"خروج",
41 | "dashboard": "پیشخوان",
42 | "api_explorer":"لیست سرویس ها",
43 | "api_docs":"مستندات فنی",
44 | "items": "مورد",
45 | "create_item": "اضافه کردن",
46 | "edit_item":"ویرایش اطلاعات",
47 | "upload_now": "بارگذاری فایل",
48 | "save_item": "دخیره اطلاعات",
49 | "actions": "عملیات",
50 | "total":"مورد",
51 | "columns": "ستون ها",
52 | "search":"جستجو",
53 | "download":"دانلود",
54 | "json_object":"JSON Object",
55 | "csv_format":"CSV Format",
56 | "edit":"ویرایش",
57 | "empty_list":"اطلاعاتی موجود نیست"
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/src/components/Unavailable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | WHoops!
7 | Please make sure all service are run and alive :)
8 |
9 |
10 |
11 |
12 |
13 |
30 |
31 |
--------------------------------------------------------------------------------
/src/filters/index.js:
--------------------------------------------------------------------------------
1 | const urlParser = document.createElement('a');
2 | const request = require("browser-request");
3 |
4 | import store from '../store';
5 |
6 | export function checkAuth (url) {
7 |
8 | var token = store.get('flashboard_token');
9 |
10 | if(token != null){
11 | request({method:'GET',
12 | url: url+'Users/findOne',
13 | headers: {
14 | 'Authorization': token,
15 | 'origin-when-cross-origin':'*'
16 | },
17 | "xhrFields": { "withCredentials": true }
18 | }, function (er, response, body) {
19 | if(er){
20 | window.offline_mode = true;
21 | window.location.assign('#/unavailable?url='+window.location.hash);
22 | throw er
23 | }
24 |
25 | if(typeof JSON.parse(body).error != "undefined"){
26 | window.offline_mode = false;
27 |
28 | if(JSON.parse(body).error['statusCode']==401){
29 | window.location.assign('#/login');
30 | } else{
31 | }
32 | }
33 |
34 | });
35 | } else {
36 | console.log('boro berim')
37 | window.location.assign('#/login');
38 | }
39 |
40 | }
41 |
42 | export function loading(mode){
43 | if(mode!='start')
44 | document.querySelector('.mu-linear-progress').classList.add('hide');
45 | else
46 | document.querySelector('.mu-linear-progress').classList.remove('hide');
47 | }
48 |
49 | export function domain (url) {
50 | urlParser.href = url
51 | return urlParser.hostname
52 | }
53 |
54 | export function fromNow (time) {
55 | const between = Date.now() / 1000 - Number(time)
56 | if (between < 3600) {
57 | return pluralize(~~(between / 60), ' minute')
58 | } else if (between < 86400) {
59 | return pluralize(~~(between / 3600), ' hour')
60 | } else {
61 | return pluralize(~~(between / 86400), ' day')
62 | }
63 | }
64 |
65 | function pluralize(time, label) {
66 | if (time === 1) {
67 | return time + label
68 | }
69 |
70 | return time + label + 's';
71 | }
72 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "flashboard",
3 | "version": "1.0.0",
4 | "description": "flashboard handle the back end, you handle the front",
5 | "author": "VT ",
6 | "private": false,
7 | "scripts": {
8 | "service": "cd api && node .",
9 | "preinstall": "cd api && npm install",
10 | "build": "node build/build.js",
11 | "postinstall": "npm install --dev && npm run build",
12 | "dev": "node build/dev-server.js"
13 | },
14 | "dependencies": {
15 | "hchs-vue-charts": "^1.2.8",
16 | "vue": "^2.1.0",
17 | "vue-router": "^2.2.0"
18 | },
19 | "devDependencies": {
20 | "autoprefixer": "^6.4.0",
21 | "babel-core": "^6.0.0",
22 | "babel-loader": "^6.0.0",
23 | "babel-plugin-istanbul": "^3.0.0",
24 | "babel-plugin-transform-runtime": "^6.0.0",
25 | "babel-preset-es2015": "^6.0.0",
26 | "babel-preset-stage-2": "^6.0.0",
27 | "babel-register": "^6.0.0",
28 | "chai": "^3.5.0",
29 | "chalk": "^1.1.3",
30 | "connect-history-api-fallback": "^1.1.0",
31 | "cross-env": "^3.1.3",
32 | "cross-spawn": "^4.0.2",
33 | "css-loader": "^0.25.0",
34 | "eventsource-polyfill": "^0.9.6",
35 | "express": "^4.13.3",
36 | "extract-text-webpack-plugin": "^1.0.1",
37 | "file-loader": "^0.9.0",
38 | "friendly-errors-webpack-plugin": "^1.1.2",
39 | "function-bind": "^1.0.2",
40 | "html-webpack-plugin": "^2.8.1",
41 | "http-proxy-middleware": "^0.17.2",
42 | "inject-loader": "^2.0.1",
43 | "json-loader": "^0.5.4",
44 | "lolex": "^1.4.0",
45 | "nightwatch": "^0.9.8",
46 | "opn": "^4.0.2",
47 | "ora": "^0.3.0",
48 | "cors": "^2.8.3",
49 | "phantomjs-prebuilt": "^2.1.3",
50 | "selenium-server": "2.53.1",
51 | "semver": "^5.3.0",
52 | "shelljs": "^0.7.4",
53 | "codemirror": "^5.25.0",
54 | "simple-color-picker": "^0.1.2",
55 | "whatwg-fetch": "^2.0.3",
56 | "browser-request": "^0.3.3",
57 | "muse-ui": "^2.0.3",
58 | "url-loader": "^0.5.7",
59 | "vue-quill-editor": "^2.0.0",
60 | "vue-loader": "^10.0.0",
61 | "vue-style-loader": "^1.0.0",
62 | "vue-template-compiler": "^2.1.0",
63 | "webpack": "^1.13.2",
64 | "webpack-dev-middleware": "^1.8.3",
65 | "webpack-hot-middleware": "^2.12.2",
66 | "webpack-merge": "^0.14.1"
67 | },
68 | "engines": {
69 | "node": ">= 4.0.0",
70 | "npm": ">= 3.0.0"
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/docs/_static/css/badge_only.css:
--------------------------------------------------------------------------------
1 | .fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
2 | /*# sourceMappingURL=badge_only.css.map */
3 |
--------------------------------------------------------------------------------
/api/common/User.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "User",
3 | "properties": {
4 | "realm": {
5 | "type": "string"
6 | },
7 | "username": {
8 | "type": "string",
9 | "defaultColumn":true
10 | },
11 | "type": {
12 | "type": "string",
13 | "uiType": "select",
14 | "default": "user",
15 | "options": [
16 | {
17 | "value": "admin",
18 | "label": "Administrator"
19 | },
20 | {
21 | "value": "user",
22 | "label": "User"
23 | }
24 | ]
25 | },
26 | "password": {
27 | "type": "string",
28 | "uiType": "password",
29 | "required": true
30 | },
31 | "email": {
32 | "type": "string",
33 | "required": true,
34 | "defaultColumn":true
35 | },
36 | "emailVerified": {"type":"boolean"},
37 | "verificationToken": {"type":"string"}
38 | },
39 | "options": {
40 | "caseSensitiveEmail": true
41 | },
42 | "hidden": ["verificationToken","realm"],
43 | "acls": [
44 | {
45 | "principalType": "ROLE",
46 | "principalId": "$everyone",
47 | "permission": "DENY"
48 | },
49 | {
50 | "principalType": "ROLE",
51 | "principalId": "$everyone",
52 | "permission": "ALLOW",
53 | "property": "create"
54 | },
55 | {
56 | "principalType": "ROLE",
57 | "principalId": "$owner",
58 | "permission": "ALLOW",
59 | "property": "deleteById"
60 | },
61 | {
62 | "principalType": "ROLE",
63 | "principalId": "$everyone",
64 | "permission": "ALLOW",
65 | "property": "login"
66 | },
67 | {
68 | "principalType": "ROLE",
69 | "principalId": "$everyone",
70 | "permission": "ALLOW",
71 | "property": "logout"
72 | },
73 | {
74 | "principalType": "ROLE",
75 | "principalId": "$owner",
76 | "permission": "ALLOW",
77 | "property": "findById"
78 | },
79 | {
80 | "principalType": "ROLE",
81 | "principalId": "$owner",
82 | "permission": "ALLOW",
83 | "property": "patchAttributes"
84 | },
85 | {
86 | "principalType": "ROLE",
87 | "principalId": "$owner",
88 | "permission": "ALLOW",
89 | "property": "replaceById"
90 | },
91 | {
92 | "principalType": "ROLE",
93 | "principalId": "$everyone",
94 | "permission": "ALLOW",
95 | "property": "verify",
96 | "accessType": "EXECUTE"
97 | },
98 | {
99 | "principalType": "ROLE",
100 | "principalId": "$everyone",
101 | "permission": "ALLOW",
102 | "property": "confirm"
103 | },
104 | {
105 | "principalType": "ROLE",
106 | "principalId": "$everyone",
107 | "permission": "ALLOW",
108 | "property": "resetPassword",
109 | "accessType": "EXECUTE"
110 | },
111 | {
112 | "principalType": "ROLE",
113 | "principalId": "$authenticated",
114 | "permission": "ALLOW",
115 | "property": "changePassword",
116 | "accessType": "EXECUTE"
117 | },
118 | {
119 | "principalType": "ROLE",
120 | "principalId": "$authenticated",
121 | "permission": "ALLOW",
122 | "property": "setPassword",
123 | "accessType": "EXECUTE"
124 | }
125 | ],
126 | "methodes": ["login","logout"],
127 | "relations": {
128 | "accessTokens": {
129 | "type": "hasMany",
130 | "model": "AccessToken",
131 | "foreignKey": "userId",
132 | "options": {
133 | "disableInclude": true
134 | }
135 | }
136 | }
137 | }
--------------------------------------------------------------------------------
/src/components/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ _t('sign_in_msg') }} {{ brand }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
41 |
42 |
--------------------------------------------------------------------------------
/src/components/Sidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 |
17 |
18 |
19 |
53 |
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # flashboard handle the back end, you handle the front
2 |
3 | > flashboard can handle your whole back-end includes services, rest-full api and admin dashboard based on loopback node.js framework.
4 | Simply can define your models with several options and get your rest-full api and admin dashboard automatically.
5 |
6 | Documentations: [https://vah7id.github.io/flashboard/start.html](https://vah7id.github.io/flashboard/start.html)
7 |
8 | Admin demo : [http://138.68.46.113/flashboard](http://138.68.46.113/flashboard)
9 | credentials:
10 | email: ``` admin@flashboard.com ```
11 | password: ``` qwertyuiop ```
12 |
13 | 
14 |
15 | ## Getting Started
16 | The getting started guide walks you through how to manually setup a admin dashboard. flashboard actually create your back-end package services such as rest-full api of your models based on loopback node.js framework and generate admin dashboard automatically for data moderation.
17 |
18 | ## Models
19 | In this part we can learn how to create own models and start to build your back-end project. there are several options to create your models and configurations options.
20 |
21 | ## Configuration
22 | Flashboard create a admin dashboard based on configuration of loopback models. there are several settings and options on your models and user interface generation types and formats.
23 |
24 | ## Rest-full API
25 | After create your models you have a rest-full api based on your models. In this section we want to learn how to use generated api’s. Also there are options to create your own remote functions.
26 |
27 |
28 | ## Installation
29 |
30 | Before you begin, make sure you have Node.js and MongoDB installed. For best results, use the latest LTS (long-term support) release of Node.js.
31 |
32 | Running below command in your empty project directory path :
33 | ``` $ git clone https://github.com/vah7id/flashboard.git ```
34 |
35 | First install your services packages by run below command on your project directory :
36 | ``` $ npm run preinstall ```
37 |
38 | Install your admin generator packages by run below command on root directory:
39 | ``` $ npm install ```
40 |
41 | Running back-end services first before running admin dashboard :
42 | ``` $ npm run service ```
43 |
44 | At last you can run your admin dashboard by running below command:
45 | ``` $ npm run dev ```
46 |
47 | for deploy on production you can run build command :
48 | ``` $ npm run build ```
49 |
50 | ## Changelogs
51 |
52 | Google Analytics Integration for reports
53 | Responsive Admin UI layouts
54 | Add rtl support
55 | Add Multi language support
56 | Fix build issues for production
57 | Add Relational model support for admin
58 |
59 | ## Articles
60 | New generation of back-end services:
61 | https://medium.com/@vah7id/new-generation-of-back-end-services-53b0922ed8e2
62 |
63 | ## Contribute
64 |
65 | Contributions welcome! Like seriously
66 |
67 | If you have a any issue with flashboard feel free to report it in github
68 |
69 | We need to improve the admin dashboard with more options and features.
70 | Next step is creating the GUI for creating and managing models and API's.
71 |
72 | ## License
73 |
74 | (The MIT License) Copyright (c) 2016 Vahid Taghizadeh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
75 |
--------------------------------------------------------------------------------
/docs/_static/pygments.css:
--------------------------------------------------------------------------------
1 | .highlight .hll { background-color: #ffffcc }
2 | .highlight { background: #eeffcc; }
3 | .highlight .c { color: #408090; font-style: italic } /* Comment */
4 | .highlight .err { border: 1px solid #FF0000 } /* Error */
5 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */
6 | .highlight .o { color: #666666 } /* Operator */
7 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
8 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
9 | .highlight .cp { color: #007020 } /* Comment.Preproc */
10 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
11 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
12 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */
14 | .highlight .ge { font-style: italic } /* Generic.Emph */
15 | .highlight .gr { color: #FF0000 } /* Generic.Error */
16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */
18 | .highlight .go { color: #333333 } /* Generic.Output */
19 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
20 | .highlight .gs { font-weight: bold } /* Generic.Strong */
21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */
23 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
24 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
25 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
26 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */
27 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
28 | .highlight .kt { color: #902000 } /* Keyword.Type */
29 | .highlight .m { color: #208050 } /* Literal.Number */
30 | .highlight .s { color: #4070a0 } /* Literal.String */
31 | .highlight .na { color: #4070a0 } /* Name.Attribute */
32 | .highlight .nb { color: #007020 } /* Name.Builtin */
33 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
34 | .highlight .no { color: #60add5 } /* Name.Constant */
35 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
36 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
37 | .highlight .ne { color: #007020 } /* Name.Exception */
38 | .highlight .nf { color: #06287e } /* Name.Function */
39 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
40 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
41 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
42 | .highlight .nv { color: #bb60d5 } /* Name.Variable */
43 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */
45 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */
46 | .highlight .mf { color: #208050 } /* Literal.Number.Float */
47 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */
48 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */
49 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */
50 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */
51 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
52 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */
53 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
54 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
55 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */
56 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
57 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
58 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
59 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */
60 | .highlight .sr { color: #235388 } /* Literal.String.Regex */
61 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */
62 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */
63 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
64 | .highlight .fm { color: #06287e } /* Name.Function.Magic */
65 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
66 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
67 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
68 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
69 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 |
4 | import ModelListView from './components/ModelList.vue'
5 | import ModelEditView from './components/ModelEdit.vue'
6 | import ModelCreateView from './components/ModelCreate.vue'
7 |
8 | import VueQuillEditor from 'vue-quill-editor'
9 | import 'chart.js';
10 | import VueCharts from 'hchs-vue-charts'
11 |
12 | import store from './store';
13 |
14 | import LoginView from './components/Login.vue'
15 | import DashboardView from './components/Dashboard.vue'
16 | import UnavailableView from './components/Unavailable.vue'
17 |
18 | import { checkAuth, domain, fromNow } from './filters'
19 |
20 | import App from './components/App.vue'
21 |
22 | import 'whatwg-fetch'
23 |
24 | import env from "../config/configs.js"
25 | import keys from "./langs/langs.js"
26 |
27 | import MuseUI from 'muse-ui'
28 | import 'muse-ui/dist/muse-ui.css'
29 |
30 | require('muse-ui/dist/theme-'+env.THEME+'.css')
31 |
32 | if( env.rtl ){
33 | require('../src/stylesheets/rtl.css')
34 | }
35 |
36 | Vue.use(MuseUI)
37 | Vue.use(VueQuillEditor)
38 | Vue.use(window.VueCharts);
39 |
40 | store.set('env',JSON.stringify(env));
41 |
42 | window.api_url = env.API_BASE_URL +':'+env.API_PORT+'/api/';
43 |
44 | if(env.disable_admin){
45 | window.location.assign('#/unavailable');
46 | }
47 |
48 | // install router
49 |
50 | fetch('api/server/model-config.json')
51 | .then(function(response) {
52 | response.json().then(function(models) {
53 |
54 | var _models = models, _counter = 0;
55 |
56 | delete _models.ACL;
57 | delete _models.AccessToken;
58 | delete _models.Role;
59 | delete _models._meta;
60 | delete _models.RoleMapping;
61 |
62 | for(var m in _models){
63 | var model = _models[m];
64 | model['name'] = m;
65 | model['icon'] = 'folder';
66 |
67 | if(m=='User')
68 | model['icon'] = 'people';
69 |
70 | if(m=='enquiries')
71 | model['icon'] = 'phone';
72 |
73 | _counter++;
74 | }
75 |
76 | store.set('models',JSON.stringify(_models))
77 | store.set('models_count',_counter)
78 |
79 |
80 | var _routes = {
81 | routes: [
82 | { path: '', component: DashboardView, name: 'Dashboard' },
83 | { path: '/dashboard', component: DashboardView, name: 'dashboard' },
84 | { path: '/login', component: LoginView, name: 'login' },
85 | { path: '/unavailable', component: UnavailableView, name: 'unavailable' }
86 | ]
87 | };
88 |
89 | for(var model in models){
90 | _routes.routes.push({ path: '/'+model, component: ModelListView, name: model });
91 | _routes.routes.push({ path: '/'+model+'/create', component: ModelCreateView, name: model+'-create' });
92 | _routes.routes.push({ path: '/'+model+'/:id', component: ModelEditView , name: model+'-edit' });
93 | }
94 |
95 | _routes.routes.push({
96 | path: '*',
97 | redirect: ''
98 | });
99 |
100 | Vue.use(VueRouter);
101 |
102 | // Create the router instance and pass the `routes` option
103 | // You can pass in additional options here, but let's
104 | // keep it simple for now.
105 | const router = new VueRouter({
106 | routes: _routes.routes,
107 | history:true
108 | })
109 |
110 | router.beforeEach(function (to, from, next) {
111 |
112 | window.scrollTo(0, 0);
113 |
114 | if(document.querySelector('.mu-linear-progress') != null)
115 | document.querySelector('.mu-linear-progress').classList.remove('hide');
116 |
117 | next();
118 |
119 | });
120 |
121 | router.afterEach(function (route) {
122 |
123 | var name = route.name;
124 |
125 | if(name.indexOf('-')>0)
126 | name = name.split('-')[0];
127 |
128 | if(name.toLowerCase() == 'dashboard')
129 | document.querySelector('.mu-linear-progress').classList.add('hide');
130 |
131 | store.set('current_model',name);
132 | document.title = route.name;
133 |
134 | });
135 |
136 | //instatinat the vue instance
137 | new Vue({
138 | //define the selector for the root component
139 | el: '#app',
140 | data(){
141 | return {
142 | models: [],
143 | keys: keys[env.lang]
144 | }
145 | },
146 | watch:{
147 | models: function(val){
148 | this.$root.models = val;
149 | return val;
150 | },
151 | $route: function(val){
152 | if( store.get('flashboard_token') == null ){
153 | window.location.assign('#/login');
154 | document.querySelector('.mu-appbar').classList.add('hide')
155 | document.querySelector('.mu-linear-progress').classList.add('hide');
156 | }
157 | }
158 | },
159 | //pass the template to the root component
160 | template: ' ',
161 | //declare components that the root component can access
162 | components: { App },
163 | //pass in the router to the vue instance
164 | router
165 | }).$mount('#app')//mount the router on the app
166 |
167 | });
168 |
169 | }).then(function(json) {
170 |
171 | }).catch(function(ex) {
172 | console.log('parsing failed', ex)
173 | });
174 |
175 |
176 |
--------------------------------------------------------------------------------
/src/components/Dashboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
49 |
50 |
51 |
125 |
126 |
--------------------------------------------------------------------------------
/docs/_static/js/theme.js:
--------------------------------------------------------------------------------
1 | require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o");
80 |
81 | // Add expand links to all parents of nested ul
82 | $('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () {
83 | var link = $(this);
84 | expand = $(' ');
85 | expand.on('click', function (ev) {
86 | self.toggleCurrent(link);
87 | ev.stopPropagation();
88 | return false;
89 | });
90 | link.prepend(expand);
91 | });
92 | };
93 |
94 | nav.reset = function () {
95 | // Get anchor from URL and open up nested nav
96 | var anchor = encodeURI(window.location.hash);
97 | if (anchor) {
98 | try {
99 | var link = $('.wy-menu-vertical')
100 | .find('[href="' + anchor + '"]');
101 | // If we didn't find a link, it may be because we clicked on
102 | // something that is not in the sidebar (eg: when using
103 | // sphinxcontrib.httpdomain it generates headerlinks but those
104 | // aren't picked up and placed in the toctree). So let's find
105 | // the closest header in the document and try with that one.
106 | if (link.length === 0) {
107 | var doc_link = $('.document a[href="' + anchor + '"]');
108 | var closest_section = doc_link.closest('div.section');
109 | // Try again with the closest section entry.
110 | link = $('.wy-menu-vertical')
111 | .find('[href="#' + closest_section.attr("id") + '"]');
112 |
113 | }
114 | $('.wy-menu-vertical li.toctree-l1 li.current')
115 | .removeClass('current');
116 | link.closest('li.toctree-l2').addClass('current');
117 | link.closest('li.toctree-l3').addClass('current');
118 | link.closest('li.toctree-l4').addClass('current');
119 | }
120 | catch (err) {
121 | console.log("Error expanding nav for anchor", err);
122 | }
123 | }
124 | };
125 |
126 | nav.onScroll = function () {
127 | this.winScroll = false;
128 | var newWinPosition = this.win.scrollTop(),
129 | winBottom = newWinPosition + this.winHeight,
130 | navPosition = this.navBar.scrollTop(),
131 | newNavPosition = navPosition + (newWinPosition - this.winPosition);
132 | if (newWinPosition < 0 || winBottom > this.docHeight) {
133 | return;
134 | }
135 | this.navBar.scrollTop(newNavPosition);
136 | this.winPosition = newWinPosition;
137 | };
138 |
139 | nav.onResize = function () {
140 | this.winResize = false;
141 | this.winHeight = this.win.height();
142 | this.docHeight = $(document).height();
143 | };
144 |
145 | nav.hashChange = function () {
146 | this.linkScroll = true;
147 | this.win.one('hashchange', function () {
148 | this.linkScroll = false;
149 | });
150 | };
151 |
152 | nav.toggleCurrent = function (elem) {
153 | var parent_li = elem.closest('li');
154 | parent_li.siblings('li.current').removeClass('current');
155 | parent_li.siblings().find('li.current').removeClass('current');
156 | parent_li.find('> ul li.current').removeClass('current');
157 | parent_li.toggleClass('current');
158 | }
159 |
160 | return nav;
161 | };
162 |
163 | module.exports.ThemeNav = ThemeNav();
164 |
165 | if (typeof(window) != 'undefined') {
166 | window.SphinxRtdTheme = { StickyNav: module.exports.ThemeNav };
167 | }
168 |
169 | },{"jquery":"jquery"}]},{},["sphinx-rtd-theme"]);
170 |
--------------------------------------------------------------------------------
/src/components/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{ brand }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
52 |
53 |
--------------------------------------------------------------------------------
/docs/_static/doctools.js:
--------------------------------------------------------------------------------
1 | /*
2 | * doctools.js
3 | * ~~~~~~~~~~~
4 | *
5 | * Sphinx JavaScript utilities for all documentation.
6 | *
7 | * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | /**
13 | * select a different prefix for underscore
14 | */
15 | $u = _.noConflict();
16 |
17 | /**
18 | * make the code below compatible with browsers without
19 | * an installed firebug like debugger
20 | if (!window.console || !console.firebug) {
21 | var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
22 | "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
23 | "profile", "profileEnd"];
24 | window.console = {};
25 | for (var i = 0; i < names.length; ++i)
26 | window.console[names[i]] = function() {};
27 | }
28 | */
29 |
30 | /**
31 | * small helper function to urldecode strings
32 | */
33 | jQuery.urldecode = function(x) {
34 | return decodeURIComponent(x).replace(/\+/g, ' ');
35 | };
36 |
37 | /**
38 | * small helper function to urlencode strings
39 | */
40 | jQuery.urlencode = encodeURIComponent;
41 |
42 | /**
43 | * This function returns the parsed url parameters of the
44 | * current request. Multiple values per key are supported,
45 | * it will always return arrays of strings for the value parts.
46 | */
47 | jQuery.getQueryParameters = function(s) {
48 | if (typeof s == 'undefined')
49 | s = document.location.search;
50 | var parts = s.substr(s.indexOf('?') + 1).split('&');
51 | var result = {};
52 | for (var i = 0; i < parts.length; i++) {
53 | var tmp = parts[i].split('=', 2);
54 | var key = jQuery.urldecode(tmp[0]);
55 | var value = jQuery.urldecode(tmp[1]);
56 | if (key in result)
57 | result[key].push(value);
58 | else
59 | result[key] = [value];
60 | }
61 | return result;
62 | };
63 |
64 | /**
65 | * highlight a given string on a jquery object by wrapping it in
66 | * span elements with the given class name.
67 | */
68 | jQuery.fn.highlightText = function(text, className) {
69 | function highlight(node) {
70 | if (node.nodeType == 3) {
71 | var val = node.nodeValue;
72 | var pos = val.toLowerCase().indexOf(text);
73 | if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
74 | var span = document.createElement("span");
75 | span.className = className;
76 | span.appendChild(document.createTextNode(val.substr(pos, text.length)));
77 | node.parentNode.insertBefore(span, node.parentNode.insertBefore(
78 | document.createTextNode(val.substr(pos + text.length)),
79 | node.nextSibling));
80 | node.nodeValue = val.substr(0, pos);
81 | }
82 | }
83 | else if (!jQuery(node).is("button, select, textarea")) {
84 | jQuery.each(node.childNodes, function() {
85 | highlight(this);
86 | });
87 | }
88 | }
89 | return this.each(function() {
90 | highlight(this);
91 | });
92 | };
93 |
94 | /*
95 | * backward compatibility for jQuery.browser
96 | * This will be supported until firefox bug is fixed.
97 | */
98 | if (!jQuery.browser) {
99 | jQuery.uaMatch = function(ua) {
100 | ua = ua.toLowerCase();
101 |
102 | var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
103 | /(webkit)[ \/]([\w.]+)/.exec(ua) ||
104 | /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
105 | /(msie) ([\w.]+)/.exec(ua) ||
106 | ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
107 | [];
108 |
109 | return {
110 | browser: match[ 1 ] || "",
111 | version: match[ 2 ] || "0"
112 | };
113 | };
114 | jQuery.browser = {};
115 | jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
116 | }
117 |
118 | /**
119 | * Small JavaScript module for the documentation.
120 | */
121 | var Documentation = {
122 |
123 | init : function() {
124 | this.fixFirefoxAnchorBug();
125 | this.highlightSearchWords();
126 | this.initIndexTable();
127 |
128 | },
129 |
130 | /**
131 | * i18n support
132 | */
133 | TRANSLATIONS : {},
134 | PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
135 | LOCALE : 'unknown',
136 |
137 | // gettext and ngettext don't access this so that the functions
138 | // can safely bound to a different name (_ = Documentation.gettext)
139 | gettext : function(string) {
140 | var translated = Documentation.TRANSLATIONS[string];
141 | if (typeof translated == 'undefined')
142 | return string;
143 | return (typeof translated == 'string') ? translated : translated[0];
144 | },
145 |
146 | ngettext : function(singular, plural, n) {
147 | var translated = Documentation.TRANSLATIONS[singular];
148 | if (typeof translated == 'undefined')
149 | return (n == 1) ? singular : plural;
150 | return translated[Documentation.PLURALEXPR(n)];
151 | },
152 |
153 | addTranslations : function(catalog) {
154 | for (var key in catalog.messages)
155 | this.TRANSLATIONS[key] = catalog.messages[key];
156 | this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
157 | this.LOCALE = catalog.locale;
158 | },
159 |
160 | /**
161 | * add context elements like header anchor links
162 | */
163 | addContextElements : function() {
164 | $('div[id] > :header:first').each(function() {
165 | $('').
166 | attr('href', '#' + this.id).
167 | attr('title', _('Permalink to this headline')).
168 | appendTo(this);
169 | });
170 | $('dt[id]').each(function() {
171 | $('').
172 | attr('href', '#' + this.id).
173 | attr('title', _('Permalink to this definition')).
174 | appendTo(this);
175 | });
176 | },
177 |
178 | /**
179 | * workaround a firefox stupidity
180 | * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
181 | */
182 | fixFirefoxAnchorBug : function() {
183 | if (document.location.hash)
184 | window.setTimeout(function() {
185 | document.location.href += '';
186 | }, 10);
187 | },
188 |
189 | /**
190 | * highlight the search words provided in the url in the text
191 | */
192 | highlightSearchWords : function() {
193 | var params = $.getQueryParameters();
194 | var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
195 | if (terms.length) {
196 | var body = $('div.body');
197 | if (!body.length) {
198 | body = $('body');
199 | }
200 | window.setTimeout(function() {
201 | $.each(terms, function() {
202 | body.highlightText(this.toLowerCase(), 'highlighted');
203 | });
204 | }, 10);
205 | $('' + _('Hide Search Matches') + '
')
207 | .appendTo($('#searchbox'));
208 | }
209 | },
210 |
211 | /**
212 | * init the domain index toggle buttons
213 | */
214 | initIndexTable : function() {
215 | var togglers = $('img.toggler').click(function() {
216 | var src = $(this).attr('src');
217 | var idnum = $(this).attr('id').substr(7);
218 | $('tr.cg-' + idnum).toggle();
219 | if (src.substr(-9) == 'minus.png')
220 | $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
221 | else
222 | $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
223 | }).css('display', '');
224 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
225 | togglers.click();
226 | }
227 | },
228 |
229 | /**
230 | * helper function to hide the search marks again
231 | */
232 | hideSearchWords : function() {
233 | $('#searchbox .highlight-link').fadeOut(300);
234 | $('span.highlighted').removeClass('highlighted');
235 | },
236 |
237 | /**
238 | * make the url absolute
239 | */
240 | makeURL : function(relativeURL) {
241 | return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
242 | },
243 |
244 | /**
245 | * get the current relative url
246 | */
247 | getCurrentURL : function() {
248 | var path = document.location.pathname;
249 | var parts = path.split(/\//);
250 | $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
251 | if (this == '..')
252 | parts.pop();
253 | });
254 | var url = parts.join('/');
255 | return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
256 | },
257 |
258 | initOnKeyListeners: function() {
259 | $(document).keyup(function(event) {
260 | var activeElementType = document.activeElement.tagName;
261 | // don't navigate when in search box or textarea
262 | if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
263 | switch (event.keyCode) {
264 | case 37: // left
265 | var prevHref = $('link[rel="prev"]').prop('href');
266 | if (prevHref) {
267 | window.location.href = prevHref;
268 | return false;
269 | }
270 | case 39: // right
271 | var nextHref = $('link[rel="next"]').prop('href');
272 | if (nextHref) {
273 | window.location.href = nextHref;
274 | return false;
275 | }
276 | }
277 | }
278 | });
279 | }
280 | };
281 |
282 | // quick alias for translations
283 | _ = Documentation.gettext;
284 |
285 | $(document).ready(function() {
286 | Documentation.init();
287 | });
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Flashboard
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
FLASHBOARD
53 |
54 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
flashboard can handle your whole back-end includes services, rest-full api and admin dashboard based on loopback node.js framework.
66 |
67 | Getting Started
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
"Simply can define your models with several options and get your rest-full api and admin dashboard automatically."
82 |
83 |
84 |
85 |
86 |
87 |
email: admin@flashboard.com | password: qwertyuiop
88 |
89 |
90 |
95 |
96 |
97 |
98 |
99 |
100 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/docs/getting.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Flashboard documentation
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | FLASHBOARD DOCS
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | Docs »
125 |
126 | Flashboard documentation
127 |
128 |
129 |
130 |
131 |
132 |
133 | Edit on GitHub
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
Let’s jump in
150 | Use the sidebar on the left to navigate the docs.
151 |
Getting Started
152 | The getting started guide walks you through how to manually setup a admin dashboard. flashboard actually create your back-end package services such as rest-full api of your models based on loopback node.js framework and generate admin dashboard automatically for data moderation.
153 |
Models
154 | In this part we can learn how to create own models and start to build your back-end project. there are several options to create your models and configurations options.
155 |
156 |
Configuration
157 | Flashboard create a admin dashboard based on configuration of loopback models. there are several settings and options on your models and user interface generation types and formats.
158 |
Rest-full API
159 | After create your models you have a rest-full api based on your models. In this section we want to learn how to use generated api’s. Also there are options to create your own remote functions.
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 | Read the Docs
202 | v: stable
203 |
204 |
205 |
206 |
207 | Versions
208 |
209 | latest
210 |
211 | stable
212 |
213 |
214 |
215 | Downloads
216 |
217 |
218 |
219 | On Read the Docs
220 |
221 | Project Home
222 |
223 |
224 | Builds
225 |
226 |
227 |
228 | Free document hosting provided by
Read the Docs .
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
263 |
264 |
265 |
266 |
--------------------------------------------------------------------------------
/docs/project.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Flashboard documentation
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | FLASHBOARD DOCS
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Docs »
126 |
127 | Flashboard documentation
128 |
129 |
130 |
131 |
132 |
133 |
134 | Edit on GitHub
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
Contribute
151 |
152 |
Contributions welcome! Like seriously
153 |
If you have a any issue with flashboard feel free to report it in github
154 |
We need to improve the admin dashboard with more options and features.
155 |
156 | Next step is creating the GUI for creating and managing models and API's.
157 |
158 |
159 |
License
160 |
161 | (The MIT License)
162 |
163 | Copyright (c) 2016 Vahid Taghizadeh
164 |
165 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
166 |
167 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
168 |
169 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
170 |
171 |
172 |
173 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 | Read the Docs
203 | v: stable
204 |
205 |
206 |
207 |
208 | Versions
209 |
210 | latest
211 |
212 | stable
213 |
214 |
215 |
216 | Downloads
217 |
218 |
219 |
220 | On Read the Docs
221 |
222 | Project Home
223 |
224 |
225 | Builds
226 |
227 |
228 |
229 | Free document hosting provided by
Read the Docs .
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
264 |
265 |
266 |
267 |
--------------------------------------------------------------------------------
/docs/_static/underscore.js:
--------------------------------------------------------------------------------
1 | // Underscore.js 1.3.1
2 | // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
3 | // Underscore is freely distributable under the MIT license.
4 | // Portions of Underscore are inspired or borrowed from Prototype,
5 | // Oliver Steele's Functional, and John Resig's Micro-Templating.
6 | // For all details and documentation:
7 | // http://documentcloud.github.com/underscore
8 | (function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
9 | c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,
10 | h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each=
11 | b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e2;a==
12 | null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=
13 | function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=
14 | e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
15 | function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;bd?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,
17 | c,d){d||(d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};
24 | b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments,
25 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};
26 | b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};
27 | b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e /g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),
28 | function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+
29 | u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]=
30 | function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=
31 | true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
32 |
--------------------------------------------------------------------------------
/docs/start.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Flashboard documentation
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | FLASHBOARD DOCS
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Docs »
126 |
127 | Flashboard documentation
128 |
129 |
130 |
131 |
132 |
133 |
134 | Edit on GitHub
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
Getting Started
149 |
The getting started guide walks you through how to manually setup a admin dashboard. flashboard actually create your back-end package services such as rest-full api of your models based on loopback node.js framework and generate admin dashboard automatically for data moderation.
150 |
151 |
Introduction
152 |
flashboard can handle your whole back-end includes services, rest-full api and admin dashboard based on loopback node.js framework.
153 | Simply can define your models with several options and get your rest-full api and admin dashboard automatically.
154 | Admin dashboard implemented by vue.js 2 framework and muse-ui as ui-component library that allows you have a multiple themes for your user interface.
155 | You have a database-connector options that allows you to connect your back-end to each database you want such as mongodb or mysql and etc.
156 |
Admin demo : http://138.68.46.113/flashboard
157 | demo admin credential:
158 | email: admin@flashboard.com
159 | password: qwertyuiop
160 |
Let’s start to build your own back-end services.
161 |
162 |
Installation
163 |
164 | Before you begin, make sure you have Node.js and MongoDB installed. For best results, use the latest LTS (long-term support) release of Node.js.
165 | Running below command in your empty project directory path :
166 |
167 |
$ git clone https://github.com/vah7id/flashboard.git
168 |
169 |
170 | First install your services packages by run below command on your project directory :
171 |
172 |
$ npm run preinstall
173 |
174 |
175 | Install your admin generator packages by run below command on root directory:
176 |
177 |
$ npm install
178 |
179 |
180 | Running back-end services first before running admin dashboard :
181 |
182 |
$ npm run service
183 |
184 |
185 | At last you can run your admin dashboard by running below command:
186 |
187 |
$ npm run dev
188 |
189 |
for deploy on production you can run build command :
190 |
$ npm run build
191 |
192 |
193 |
Admin Default User
194 |
In first-time you start the project api/server/boot/script.js create default admin account as you can see below :
195 |
196 | module.exports = function (app) {
197 | var _ = require('lodash');
198 | var User = app.models.User;
199 | var Role = app.models.Role;
200 | var RoleMapping = app.models.RoleMapping;
201 | var ACL = app.models.ACL;
202 |
203 | User.create([{
204 | username: 'flashboard',
205 | email: 'admin@flashboard.com',
206 | password: 'qwertyuiop',
207 | type: 'admin'
208 | }], function(err, users) {
209 |
210 | Role.find({ name: 'admin' }, function(err, results) {
211 | if (err) console.log(err);
212 | Role.create({
213 | name: 'admin'
214 | }, function(err, role) {
215 | if (err);
216 | //debug(role);
217 | role.principals.create({
218 | principalType: RoleMapping.USER,
219 | principalId: users[0].id
220 | }, function(err, principal) {
221 | if (err) console.log(err);
222 |
223 | });
224 | });
225 | });
226 |
227 | });
228 | };
229 |
230 |
You can change the initial credential in script.js before start your project.
231 | If you miss this step nevermind, you can login by default admin credentials then create new admin account in dashboard from users section for yourself and manage accounts in there.
232 |
233 |
234 |
Models
235 |
After run your project you can see built-in models on your dashboard such as posts, galleries and etc. for starting to create your own website models you should go to next section of documentation.
236 |
237 |
238 |
239 |
240 |
241 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 | Read the Docs
271 | v: stable
272 |
273 |
274 |
275 |
276 | Versions
277 |
278 | latest
279 |
280 | stable
281 |
282 |
283 |
284 | Downloads
285 |
286 |
287 |
288 | On Read the Docs
289 |
290 | Project Home
291 |
292 |
293 | Builds
294 |
295 |
296 |
297 | Free document hosting provided by
Read the Docs .
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
333 |
334 |
335 |
336 |
341 |
342 |
343 |
344 |
345 |
--------------------------------------------------------------------------------
/docs/_static/basic.css:
--------------------------------------------------------------------------------
1 | /*
2 | * basic.css
3 | * ~~~~~~~~~
4 | *
5 | * Sphinx stylesheet -- basic theme.
6 | *
7 | * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
8 | * :license: BSD, see LICENSE for details.
9 | *
10 | */
11 |
12 | /* -- main layout ----------------------------------------------------------- */
13 |
14 | div.clearer {
15 | clear: both;
16 | }
17 |
18 | /* -- relbar ---------------------------------------------------------------- */
19 |
20 | div.related {
21 | width: 100%;
22 | font-size: 90%;
23 | }
24 |
25 | div.related h3 {
26 | display: none;
27 | }
28 |
29 | div.related ul {
30 | margin: 0;
31 | padding: 0 0 0 10px;
32 | list-style: none;
33 | }
34 |
35 | div.related li {
36 | display: inline;
37 | }
38 |
39 | div.related li.right {
40 | float: right;
41 | margin-right: 5px;
42 | }
43 |
44 | /* -- sidebar --------------------------------------------------------------- */
45 |
46 | div.sphinxsidebarwrapper {
47 | padding: 10px 5px 0 10px;
48 | }
49 |
50 | div.sphinxsidebar {
51 | float: left;
52 | width: 230px;
53 | margin-left: -100%;
54 | font-size: 90%;
55 | word-wrap: break-word;
56 | overflow-wrap : break-word;
57 | }
58 |
59 | div.sphinxsidebar ul {
60 | list-style: none;
61 | }
62 |
63 | div.sphinxsidebar ul ul,
64 | div.sphinxsidebar ul.want-points {
65 | margin-left: 20px;
66 | list-style: square;
67 | }
68 |
69 | div.sphinxsidebar ul ul {
70 | margin-top: 0;
71 | margin-bottom: 0;
72 | }
73 |
74 | div.sphinxsidebar form {
75 | margin-top: 10px;
76 | }
77 |
78 | div.sphinxsidebar input {
79 | border: 1px solid #98dbcc;
80 | font-family: sans-serif;
81 | font-size: 1em;
82 | }
83 |
84 | div.sphinxsidebar #searchbox input[type="text"] {
85 | width: 170px;
86 | }
87 |
88 | img {
89 | border: 0;
90 | max-width: 100%;
91 | }
92 |
93 | /* -- search page ----------------------------------------------------------- */
94 |
95 | ul.search {
96 | margin: 10px 0 0 20px;
97 | padding: 0;
98 | }
99 |
100 | ul.search li {
101 | padding: 5px 0 5px 20px;
102 | background-image: url(file.png);
103 | background-repeat: no-repeat;
104 | background-position: 0 7px;
105 | }
106 |
107 | ul.search li a {
108 | font-weight: bold;
109 | }
110 |
111 | ul.search li div.context {
112 | color: #888;
113 | margin: 2px 0 0 30px;
114 | text-align: left;
115 | }
116 |
117 | ul.keywordmatches li.goodmatch a {
118 | font-weight: bold;
119 | }
120 |
121 | /* -- index page ------------------------------------------------------------ */
122 |
123 | table.contentstable {
124 | width: 90%;
125 | margin-left: auto;
126 | margin-right: auto;
127 | }
128 |
129 | table.contentstable p.biglink {
130 | line-height: 150%;
131 | }
132 |
133 | a.biglink {
134 | font-size: 1.3em;
135 | }
136 |
137 | span.linkdescr {
138 | font-style: italic;
139 | padding-top: 5px;
140 | font-size: 90%;
141 | }
142 |
143 | /* -- general index --------------------------------------------------------- */
144 |
145 | table.indextable {
146 | width: 100%;
147 | }
148 |
149 | table.indextable td {
150 | text-align: left;
151 | vertical-align: top;
152 | }
153 |
154 | table.indextable ul {
155 | margin-top: 0;
156 | margin-bottom: 0;
157 | list-style-type: none;
158 | }
159 |
160 | table.indextable > tbody > tr > td > ul {
161 | padding-left: 0em;
162 | }
163 |
164 | table.indextable tr.pcap {
165 | height: 10px;
166 | }
167 |
168 | table.indextable tr.cap {
169 | margin-top: 10px;
170 | background-color: #f2f2f2;
171 | }
172 |
173 | img.toggler {
174 | margin-right: 3px;
175 | margin-top: 3px;
176 | cursor: pointer;
177 | }
178 |
179 | div.modindex-jumpbox {
180 | border-top: 1px solid #ddd;
181 | border-bottom: 1px solid #ddd;
182 | margin: 1em 0 1em 0;
183 | padding: 0.4em;
184 | }
185 |
186 | div.genindex-jumpbox {
187 | border-top: 1px solid #ddd;
188 | border-bottom: 1px solid #ddd;
189 | margin: 1em 0 1em 0;
190 | padding: 0.4em;
191 | }
192 |
193 | /* -- domain module index --------------------------------------------------- */
194 |
195 | table.modindextable td {
196 | padding: 2px;
197 | border-collapse: collapse;
198 | }
199 |
200 | /* -- general body styles --------------------------------------------------- */
201 |
202 | div.body p, div.body dd, div.body li, div.body blockquote {
203 | -moz-hyphens: auto;
204 | -ms-hyphens: auto;
205 | -webkit-hyphens: auto;
206 | hyphens: auto;
207 | }
208 |
209 | a.headerlink {
210 | visibility: hidden;
211 | }
212 |
213 | h1:hover > a.headerlink,
214 | h2:hover > a.headerlink,
215 | h3:hover > a.headerlink,
216 | h4:hover > a.headerlink,
217 | h5:hover > a.headerlink,
218 | h6:hover > a.headerlink,
219 | dt:hover > a.headerlink,
220 | caption:hover > a.headerlink,
221 | p.caption:hover > a.headerlink,
222 | div.code-block-caption:hover > a.headerlink {
223 | visibility: visible;
224 | }
225 |
226 | div.body p.caption {
227 | text-align: inherit;
228 | }
229 |
230 | div.body td {
231 | text-align: left;
232 | }
233 |
234 | .first {
235 | margin-top: 0 !important;
236 | }
237 |
238 | p.rubric {
239 | margin-top: 30px;
240 | font-weight: bold;
241 | }
242 |
243 | img.align-left, .figure.align-left, object.align-left {
244 | clear: left;
245 | float: left;
246 | margin-right: 1em;
247 | }
248 |
249 | img.align-right, .figure.align-right, object.align-right {
250 | clear: right;
251 | float: right;
252 | margin-left: 1em;
253 | }
254 |
255 | img.align-center, .figure.align-center, object.align-center {
256 | display: block;
257 | margin-left: auto;
258 | margin-right: auto;
259 | }
260 |
261 | .align-left {
262 | text-align: left;
263 | }
264 |
265 | .align-center {
266 | text-align: center;
267 | }
268 |
269 | .align-right {
270 | text-align: right;
271 | }
272 |
273 | /* -- sidebars -------------------------------------------------------------- */
274 |
275 | div.sidebar {
276 | margin: 0 0 0.5em 1em;
277 | border: 1px solid #ddb;
278 | padding: 7px 7px 0 7px;
279 | background-color: #ffe;
280 | width: 40%;
281 | float: right;
282 | }
283 |
284 | p.sidebar-title {
285 | font-weight: bold;
286 | }
287 |
288 | /* -- topics ---------------------------------------------------------------- */
289 |
290 | div.topic {
291 | border: 1px solid #ccc;
292 | padding: 7px 7px 0 7px;
293 | margin: 10px 0 10px 0;
294 | }
295 |
296 | p.topic-title {
297 | font-size: 1.1em;
298 | font-weight: bold;
299 | margin-top: 10px;
300 | }
301 |
302 | /* -- admonitions ----------------------------------------------------------- */
303 |
304 | div.admonition {
305 | margin-top: 10px;
306 | margin-bottom: 10px;
307 | padding: 7px;
308 | }
309 |
310 | div.admonition dt {
311 | font-weight: bold;
312 | }
313 |
314 | div.admonition dl {
315 | margin-bottom: 0;
316 | }
317 |
318 | p.admonition-title {
319 | margin: 0px 10px 5px 0px;
320 | font-weight: bold;
321 | }
322 |
323 | div.body p.centered {
324 | text-align: center;
325 | margin-top: 25px;
326 | }
327 |
328 | /* -- tables ---------------------------------------------------------------- */
329 |
330 | table.docutils {
331 | border: 0;
332 | border-collapse: collapse;
333 | }
334 |
335 | table caption span.caption-number {
336 | font-style: italic;
337 | }
338 |
339 | table caption span.caption-text {
340 | }
341 |
342 | table.docutils td, table.docutils th {
343 | padding: 1px 8px 1px 5px;
344 | border-top: 0;
345 | border-left: 0;
346 | border-right: 0;
347 | border-bottom: 1px solid #aaa;
348 | }
349 |
350 | table.footnote td, table.footnote th {
351 | border: 0 !important;
352 | }
353 |
354 | th {
355 | text-align: left;
356 | padding-right: 5px;
357 | }
358 |
359 | table.citation {
360 | border-left: solid 1px gray;
361 | margin-left: 1px;
362 | }
363 |
364 | table.citation td {
365 | border-bottom: none;
366 | }
367 |
368 | /* -- figures --------------------------------------------------------------- */
369 |
370 | div.figure {
371 | margin: 0.5em;
372 | padding: 0.5em;
373 | }
374 |
375 | div.figure p.caption {
376 | padding: 0.3em;
377 | }
378 |
379 | div.figure p.caption span.caption-number {
380 | font-style: italic;
381 | }
382 |
383 | div.figure p.caption span.caption-text {
384 | }
385 |
386 | /* -- field list styles ----------------------------------------------------- */
387 |
388 | table.field-list td, table.field-list th {
389 | border: 0 !important;
390 | }
391 |
392 | .field-list ul {
393 | margin: 0;
394 | padding-left: 1em;
395 | }
396 |
397 | .field-list p {
398 | margin: 0;
399 | }
400 |
401 | /* -- other body styles ----------------------------------------------------- */
402 |
403 | ol.arabic {
404 | list-style: decimal;
405 | }
406 |
407 | ol.loweralpha {
408 | list-style: lower-alpha;
409 | }
410 |
411 | ol.upperalpha {
412 | list-style: upper-alpha;
413 | }
414 |
415 | ol.lowerroman {
416 | list-style: lower-roman;
417 | }
418 |
419 | ol.upperroman {
420 | list-style: upper-roman;
421 | }
422 |
423 | dl {
424 | margin-bottom: 15px;
425 | }
426 |
427 | dd p {
428 | margin-top: 0px;
429 | }
430 |
431 | dd ul, dd table {
432 | margin-bottom: 10px;
433 | }
434 |
435 | dd {
436 | margin-top: 3px;
437 | margin-bottom: 10px;
438 | margin-left: 30px;
439 | }
440 |
441 | dt:target, .highlighted {
442 | background-color: #fbe54e;
443 | }
444 |
445 | dl.glossary dt {
446 | font-weight: bold;
447 | font-size: 1.1em;
448 | }
449 |
450 | .optional {
451 | font-size: 1.3em;
452 | }
453 |
454 | .sig-paren {
455 | font-size: larger;
456 | }
457 |
458 | .versionmodified {
459 | font-style: italic;
460 | }
461 |
462 | .system-message {
463 | background-color: #fda;
464 | padding: 5px;
465 | border: 3px solid red;
466 | }
467 |
468 | .footnote:target {
469 | background-color: #ffa;
470 | }
471 |
472 | .line-block {
473 | display: block;
474 | margin-top: 1em;
475 | margin-bottom: 1em;
476 | }
477 |
478 | .line-block .line-block {
479 | margin-top: 0;
480 | margin-bottom: 0;
481 | margin-left: 1.5em;
482 | }
483 |
484 | .guilabel, .menuselection {
485 | font-family: sans-serif;
486 | }
487 |
488 | .accelerator {
489 | text-decoration: underline;
490 | }
491 |
492 | .classifier {
493 | font-style: oblique;
494 | }
495 |
496 | abbr, acronym {
497 | border-bottom: dotted 1px;
498 | cursor: help;
499 | }
500 |
501 | /* -- code displays --------------------------------------------------------- */
502 |
503 | pre {
504 | overflow: auto;
505 | overflow-y: hidden; /* fixes display issues on Chrome browsers */
506 | }
507 |
508 | span.pre {
509 | -moz-hyphens: none;
510 | -ms-hyphens: none;
511 | -webkit-hyphens: none;
512 | hyphens: none;
513 | }
514 |
515 | td.linenos pre {
516 | padding: 5px 0px;
517 | border: 0;
518 | background-color: transparent;
519 | color: #aaa;
520 | }
521 |
522 | table.highlighttable {
523 | margin-left: 0.5em;
524 | }
525 |
526 | table.highlighttable td {
527 | padding: 0 0.5em 0 0.5em;
528 | }
529 |
530 | div.code-block-caption {
531 | padding: 2px 5px;
532 | font-size: small;
533 | }
534 |
535 | div.code-block-caption code {
536 | background-color: transparent;
537 | }
538 |
539 | div.code-block-caption + div > div.highlight > pre {
540 | margin-top: 0;
541 | }
542 |
543 | div.code-block-caption span.caption-number {
544 | padding: 0.1em 0.3em;
545 | font-style: italic;
546 | }
547 |
548 | div.code-block-caption span.caption-text {
549 | }
550 |
551 | div.literal-block-wrapper {
552 | padding: 1em 1em 0;
553 | }
554 |
555 | div.literal-block-wrapper div.highlight {
556 | margin: 0;
557 | }
558 |
559 | code.descname {
560 | background-color: transparent;
561 | font-weight: bold;
562 | font-size: 1.2em;
563 | }
564 |
565 | code.descclassname {
566 | background-color: transparent;
567 | }
568 |
569 | code.xref, a code {
570 | background-color: transparent;
571 | font-weight: bold;
572 | }
573 |
574 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
575 | background-color: transparent;
576 | }
577 |
578 | .viewcode-link {
579 | float: right;
580 | }
581 |
582 | .viewcode-back {
583 | float: right;
584 | font-family: sans-serif;
585 | }
586 |
587 | div.viewcode-block:target {
588 | margin: -1px -10px;
589 | padding: 0 10px;
590 | }
591 |
592 | /* -- math display ---------------------------------------------------------- */
593 |
594 | img.math {
595 | vertical-align: middle;
596 | }
597 |
598 | div.body div.math p {
599 | text-align: center;
600 | }
601 |
602 | span.eqno {
603 | float: right;
604 | }
605 |
606 | span.eqno a.headerlink {
607 | position: relative;
608 | left: 0px;
609 | z-index: 1;
610 | }
611 |
612 | div.math:hover a.headerlink {
613 | visibility: visible;
614 | }
615 |
616 | /* -- printout stylesheet --------------------------------------------------- */
617 |
618 | @media print {
619 | div.document,
620 | div.documentwrapper,
621 | div.bodywrapper {
622 | margin: 0 !important;
623 | width: 100%;
624 | }
625 |
626 | div.sphinxsidebar,
627 | div.related,
628 | div.footer,
629 | #top-link {
630 | display: none;
631 | }
632 | }
--------------------------------------------------------------------------------
/docs/_static/js/modernizr.min.js:
--------------------------------------------------------------------------------
1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD
2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
3 | */
4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML=" ",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | {{ count }} {{ label }}
14 | {{ note }}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | {{ _t('download') }}
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Download As :
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
{{ _t('empty_list') }} :(
58 |
59 |
60 |
61 |
62 | {{ column }}
63 | {{ _t('actions') }}
64 |
65 |
66 |
67 |
68 | {{ val }}
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
175 |
176 |
--------------------------------------------------------------------------------