├── .gitignore ├── bootstrap ├── configure │ ├── buttons.js │ ├── crud.js │ ├── dashboard.js │ ├── device.js │ ├── field.js │ ├── form.js │ ├── grid.js │ ├── http.js │ ├── operations.js │ ├── path.js │ ├── permission.js │ ├── search.js │ ├── token.js │ ├── tooltip.js │ └── user.js ├── i18n │ └── index.js └── populate │ ├── form.js │ └── grid.js ├── components ├── @mixins │ ├── MixinNavigation.js │ ├── MixinNavigationTabs.js │ ├── MixinNavigationWizard.js │ └── MixinPermission.js ├── breadcrumb │ └── AppBreadcrumb.vue ├── button │ ├── AppButton.vue │ └── AppButtonBar.vue ├── calendar │ └── AppCalendar.vue ├── card │ └── AppCard.vue ├── collapsible │ └── AppCollapsible.vue ├── crud │ ├── Form.vue │ ├── Grid.vue │ ├── Index.vue │ ├── components │ │ └── grid │ │ │ ├── AppGridFilter.vue │ │ │ └── AppGridToolbar.vue │ └── model │ │ ├── form │ │ ├── MixinForm.js │ │ └── index.js │ │ ├── general │ │ ├── MixinComputed.js │ │ ├── MixinData.js │ │ ├── MixinMethods.js │ │ └── MixinProps.js │ │ ├── grid │ │ ├── MixinFilter.js │ │ ├── MixinGrid.js │ │ └── index.js │ │ └── index.js ├── data-table │ ├── AppDataTable.vue │ └── model │ │ ├── index.js │ │ └── mixins │ │ ├── MixinComputed.js │ │ ├── MixinData.js │ │ ├── MixinMethods.js │ │ └── MixinProps.js ├── debugger │ └── AppDebugger.vue ├── fields │ ├── abstract.js │ ├── components │ │ ├── base.vue │ │ ├── checkbox.vue │ │ ├── color.vue │ │ ├── date.vue │ │ ├── file.vue │ │ ├── html.vue │ │ ├── input.vue │ │ ├── money.vue │ │ ├── numeric.vue │ │ ├── password.vue │ │ ├── phone.vue │ │ ├── pivot.vue │ │ ├── radio.vue │ │ ├── search.vue │ │ ├── select.vue │ │ ├── separator.vue │ │ ├── text.vue │ │ ├── textarea.vue │ │ ├── time.vue │ │ ├── toggle.vue │ │ └── wysiwyg.vue │ ├── functional.js │ └── index.js ├── form │ ├── AppForm.vue │ ├── AppFormTabs.vue │ ├── AppWizard.vue │ └── model │ │ ├── index.js │ │ └── mixins │ │ ├── MixinData.js │ │ ├── MixinMethods.js │ │ ├── MixinProps.js │ │ └── MixinWatch.js ├── index.js ├── layout │ ├── AppLayout.vue │ └── drawer │ │ ├── DrawerMenu.vue │ │ └── DrawerMenuItem.vue ├── link │ └── AppLink.vue ├── table │ └── AppTable.vue ├── tooltip │ └── AppTooltip.vue └── transition │ └── AppTransitionSlide.vue ├── index.js ├── infra ├── router │ ├── guard.js │ ├── index.js │ └── resources.js ├── services │ └── http │ │ ├── configure.js │ │ ├── index.js │ │ ├── plugin.js │ │ └── resource.js ├── storage │ └── index.js └── store │ ├── index.js │ ├── schema │ ├── actions.js │ ├── getters.js │ ├── modules.js │ ├── mutations.js │ └── state.js │ └── types.js ├── modules ├── auth │ ├── index.js │ ├── services │ │ └── index.js │ └── store │ │ └── index.js ├── dashboard │ ├── helper │ │ ├── button.js │ │ ├── group.js │ │ ├── item.js │ │ └── menu.js │ ├── index.js │ └── store │ │ └── index.js └── permission │ ├── index.js │ ├── services │ └── index.js │ └── store │ └── index.js ├── package.json ├── plugin └── index.js ├── settings ├── auth.js ├── crud.js ├── data.js ├── http.js ├── model.js ├── navigation.js ├── routes.js └── view.js ├── support ├── date │ └── index.js ├── format │ └── index.js ├── i18n │ └── index.js ├── index.js ├── message │ └── index.js ├── model │ ├── fields.js │ └── index.js ├── transform │ └── index.js └── utils │ └── index.js └── themes ├── fonts ├── index.styl └── play │ ├── Play-Bold.ttf │ └── Play-Regular.ttf ├── index.styl ├── ios.styl ├── mat.styl ├── modules ├── button.styl ├── calendar.styl ├── data-table.styl ├── field.styl ├── form.styl ├── grid.styl ├── info.styl ├── layout.styl ├── link.styl ├── popover.styl ├── reset.styl ├── scrollbar.styl ├── tabs.styl └── util.styl └── variables.styl /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | \.idea 3 | -------------------------------------------------------------------------------- /bootstrap/configure/buttons.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | import { button } from 'genesis/modules/dashboard/index' 3 | import { view, edit, add, create, read, update, destroy } from './operations' 4 | 5 | const color = 'positive' 6 | 7 | /** 8 | * @param {Object} $this 9 | * @return {Array} 10 | */ 11 | export const buttons = ($this) => { 12 | return [ 13 | // ********************************* middle ********************************* 14 | 15 | button('view', 1, 'Detalhes', view($this), 'search', 'Visualize detalhes deste registro').$middle(), 16 | 17 | button('edit', 3, 'Editar', edit($this), 'edit', 'Edite este registro', 'primary').$middle(), 18 | 19 | button('destroy', 4, 'Apagar', destroy($this, null, 'Confirmação', 'Deseja apagar este registro?'), 'delete', 20 | 'Envie este registro para a lixeira', 'negative').$middle(), 21 | 22 | // ********************************* grid ********************************* 23 | 24 | button('refresh', 1, '', read($this), 'refresh', 'Recarregar os dados', 'primary').$grid(), 25 | 26 | button('add-inline', 2, '', add($this), 'add', 'Inicie a criação de um novo registro', 'primary').$grid(), 27 | 28 | button('retry', 1, 'Tentar novamente', () => $this.read(), 'add', 29 | 'Realizar uma nova tentativa de recuperação de dados', 'primary').$render(['retry'], ['center']), 30 | 31 | button('first', 2, 'Criar um novo registro', add($this), 'add', 'Inicie a criação de um novo registro', 32 | 'primary').$render(['empty'], ['center']), 33 | 34 | // ********************************* form ********************************* 35 | 36 | button('create', 2, 'Salvar', create($this), '', 'Salvar as alterações feitas a este registro', 'primary') 37 | .$validate().$form(['create']), 38 | 39 | button('update', 3, 'Salvar', update($this), '', 'Salvar as alterações feitas a este registro', 'primary') 40 | .$validate().$form(['edit']), 41 | 42 | button('save-and-add', $this.scope === 'create' ? 2 : 3, 'Salvar & Novo', 43 | (record) => $this.save(record, () => $this.browse($this.path + '/' + 'create')), '', 44 | 'Salva este registro e abre nova tela para criação de um novo registro').$validate().$form(['create', 'edit']), 45 | 46 | button('save-and-back', $this.scope === 'create' ? 2 : 3, 'Salvar & Voltar', 47 | (record) => $this.save(record, () => $this.browse($this.path)), '', 48 | 'Salva este registro e volta para a lista principal de registros').$validate().$form(['create', 'edit']), 49 | 50 | button('editing', 3, 'Editar', edit($this), '', 'Editar este registro').$form(['view']), 51 | 52 | button('destructing', 4, 'Apagar', destroy($this, () => { 53 | $this.browse($this.path) 54 | }, 'Confirmação', 'Deseja apagar este registro?'), '', 'Apagar este registro').$form(['view', 'edit']), 55 | 56 | // ********************************* general ********************************* 57 | 58 | button('add', 2, '', add($this), 'add', 'Inicie a criação de um novo registro', 'primary') 59 | .$all(['floating'], {round: true}), 60 | 61 | button('back', 1, 'Voltar', () => $this.$router.go(-1), '', 'Voltar para a tela anterior').$all(['top', 'bottom']), 62 | 63 | // ********************************* last buttons ********************************* 64 | 65 | button('start', 1, '', () => $this.browse($this.path, false), 'apps', 'Abre a lista de registros', color) 66 | .$options({rotate: false}).$form(), 67 | 68 | button('filter', 1, '', () => $this.filterOpen(), 'filter_list', 'Abre o painel de filtros', color) 69 | .$options({rotate: false, 'class': '--button-filter'}).$grid() 70 | ] 71 | } 72 | 73 | /** 74 | * @type {Object} 75 | */ 76 | export default storage({ 77 | buttons: buttons 78 | }) 79 | -------------------------------------------------------------------------------- /bootstrap/configure/crud.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {string} 3 | */ 4 | export const path = 'app/components/crud' 5 | 6 | /** 7 | * @param {string} component 8 | * @param {string} path 9 | * @returns {string} 10 | */ 11 | export default (component) => { 12 | return `${path}/${component}` 13 | } 14 | -------------------------------------------------------------------------------- /bootstrap/configure/dashboard.js: -------------------------------------------------------------------------------- 1 | import store from 'genesis/infra/store' 2 | import { Navigation } from 'genesis' 3 | 4 | /** 5 | * @param {Vue} $component 6 | */ 7 | export default ($component) => { 8 | const menu = Navigation.get('drawer') 9 | const options = Navigation.get('options') 10 | const path = Navigation.get('path') 11 | 12 | store.dispatch('setAppMenu', menu(path)) 13 | store.dispatch('setDashboardOptions', options(path)) 14 | } 15 | -------------------------------------------------------------------------------- /bootstrap/configure/device.js: -------------------------------------------------------------------------------- 1 | import { get as __get } from 'lodash' 2 | import { uid, LocalStorage } from 'quasar-framework' 3 | 4 | /** 5 | * @param {string} alias 6 | * @returns {string} 7 | */ 8 | export default (alias) => { 9 | let device = LocalStorage.get.item(alias) 10 | if (!device) { 11 | const appVersion = __get(window, 'navigator.appVersion', 'unknown') 12 | const appId = uid() 13 | device = `[${appId}] ${appVersion}` 14 | LocalStorage.set(alias, device) 15 | } 16 | return device 17 | } 18 | -------------------------------------------------------------------------------- /bootstrap/configure/form.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Resource} service 3 | * @param {string} scope 4 | * @param {string} path 5 | * @param {string} id 6 | * @param {Array} schemas 7 | * @param {Array} actions 8 | * @param {Object} options 9 | * @returns {Object} 10 | */ 11 | export default (service, scope, path, id, schemas, actions = null, options = {}) => { 12 | const base = { 13 | changer: '~' 14 | } 15 | 16 | const settings = {service, scope, path, id, schemas, actions} 17 | 18 | return Object.assign({}, base, settings, options) 19 | } 20 | -------------------------------------------------------------------------------- /bootstrap/configure/grid.js: -------------------------------------------------------------------------------- 1 | import { get } from 'lodash' 2 | 3 | /** 4 | * @param {Resource} service 5 | * @param {string} path 6 | * @param {string} id 7 | * @param {Array} schemas 8 | * @param {Array} filters 9 | * @param {Array|Function} actions 10 | * @param {Object} options 11 | * @returns {Object} 12 | */ 13 | export default (service, path, id, schemas, filters, actions = null, options = {}) => { 14 | const primaryKey = get(schemas.find(schema => schema.primaryKey), 'field') 15 | const base = { 16 | slots: [ 17 | { 18 | field: primaryKey, 19 | component: 'AppLink', 20 | props: { 21 | path: `${path}/{_id}`, 22 | label: '' 23 | } 24 | } 25 | ], 26 | timeout: 150, 27 | top: false, 28 | bottom: true, 29 | styles: { 30 | height: 'calc(100vh - 225px)', 31 | minHeight: '200px' 32 | }, 33 | bodyStyle: { 34 | height: 'calc(100vh - 275px)', 35 | minHeight: '150px' 36 | }, 37 | rule: 'like', 38 | separator: '~>', 39 | changer: '$', 40 | debug: false 41 | } 42 | const settings = {service, path, id, schemas, filters, actions} 43 | 44 | return Object.assign({}, base, settings, options) 45 | } 46 | -------------------------------------------------------------------------------- /bootstrap/configure/http.js: -------------------------------------------------------------------------------- 1 | import { serialize } from 'genesis/infra/services/http/resource' 2 | const ttl = 60000 // one minute 3 | 4 | /** 5 | * @param {AxiosRequestConfig} request 6 | * @param {Cache} cache 7 | * @returns {AxiosRequestConfig} 8 | */ 9 | export const httpRequest = (request, cache) => { 10 | // Only cache GET requests 11 | if (request.method !== 'get') { 12 | return request 13 | } 14 | 15 | if (request.noCache) { 16 | return request 17 | } 18 | 19 | let url = request.baseURL + request.url 20 | if (request.params) { 21 | url += '?' + serialize(request.params) 22 | } 23 | 24 | const data = cache.get(url) 25 | if (!data) { 26 | return request 27 | } 28 | 29 | data.__fromCache = true 30 | request.data = data 31 | 32 | request.adapter = () => { 33 | return Promise.resolve({ 34 | data: data, 35 | status: request.status, 36 | statusText: request.statusText, 37 | headers: request.headers, 38 | config: request, 39 | request: request 40 | }) 41 | } 42 | return request 43 | } 44 | 45 | /** 46 | * @param {AxiosResponse} response 47 | * @param {Cache} cache 48 | * @returns {AxiosResponse} 49 | */ 50 | export const httpResponse = (response, cache) => { 51 | // Only cache GET responses 52 | if (response.config.method !== 'get') { 53 | return response 54 | } 55 | 56 | if (response.config.noCache) { 57 | return response 58 | } 59 | 60 | let url = response.config.url 61 | if (response.config.params) { 62 | url += '?' + serialize(response.config.params) 63 | } 64 | 65 | cache.set(url, response.data, ttl) 66 | 67 | return response 68 | } 69 | 70 | /** 71 | * @param {AxiosError} error 72 | * @param {AppRouter} router 73 | * @param {AppStore} store 74 | * @returns {AxiosError} 75 | */ 76 | export const httpError = (error, router, store) => { 77 | return error 78 | } 79 | 80 | /** 81 | * @param {AxiosResponse} response 82 | * @param {string} property 83 | * @param {*} fallback 84 | * @returns {*} 85 | */ 86 | export const $extract = (response, property, fallback = {}) => { 87 | if (!response.data) { 88 | return {} 89 | } 90 | if (typeof response.data.body !== 'object') { 91 | return fallback 92 | } 93 | if (!response.data.hasOwnProperty(property)) { 94 | return fallback 95 | } 96 | return response.data[property] 97 | } 98 | 99 | /** 100 | * @param {AxiosResponse} response 101 | * @param {*} fallback 102 | * @returns {*} 103 | */ 104 | export const $body = (response, fallback = {}) => { 105 | return $extract(response, 'body', fallback) 106 | } 107 | 108 | /** 109 | * @param {AxiosResponse} response 110 | * @param {*} fallback 111 | * @returns {*} 112 | */ 113 | export const $meta = (response, fallback = {}) => { 114 | return $extract(response, 'meta', fallback) 115 | } 116 | 117 | /** 118 | * @param {AxiosResponse} response 119 | * @returns {*} 120 | */ 121 | export const $first = (response) => { 122 | const content = $body(response) 123 | if (Array.isArray(content)) { 124 | return content.shift() 125 | } 126 | return {} 127 | } 128 | -------------------------------------------------------------------------------- /bootstrap/configure/operations.js: -------------------------------------------------------------------------------- 1 | import { confirm } from 'genesis/support/message' 2 | import { $first } from './http' 3 | 4 | /** 5 | * @param {AppCrudGrid|AppCrudForm} $this 6 | * @returns {Function} 7 | */ 8 | export const view = ($this) => { 9 | return (record, schemas, $component) => $this.browse($this.path + '/' + record[$this.id]) 10 | } 11 | 12 | /** 13 | * @param {AppCrudGrid|AppCrudForm} $this 14 | * @returns {Function} 15 | */ 16 | export const edit = ($this) => { 17 | return (record, schemas, $component) => $this.browse($this.path + '/' + record[$this.id] + '/edit') 18 | } 19 | 20 | /** 21 | * @param {AppCrudGrid|AppCrudForm} $this 22 | * @returns {Function} 23 | */ 24 | export const add = ($this) => { 25 | return (record, schemas, $component) => $this.browse($this.path + '/' + 'create') 26 | } 27 | 28 | /** 29 | * @param {AppCrudGrid|AppCrudForm} $this 30 | * @returns {Function} 31 | */ 32 | export const read = ($this) => { 33 | return (record, schemas, $component) => $this.fetchData() 34 | } 35 | 36 | /** 37 | * @param {AppCrudGrid|AppCrudForm} $this 38 | * @param {Function} callback 39 | * @returns {Function} 40 | */ 41 | export const create = ($this, callback = null) => { 42 | callback = callback || ((response) => $this.browse($this.path + '/' + $first(response)[$this.id] + '/' + 'edit')) 43 | return (record, schemas, $component) => $this.create(record, callback) 44 | } 45 | 46 | /** 47 | * @param {AppCrudGrid|AppCrudForm} $this 48 | * @param {Function} callback 49 | * @returns {Function} 50 | */ 51 | export const update = ($this, callback = (() => null)) => { 52 | return (record, schemas, $component) => $this.update(record, callback) 53 | } 54 | 55 | /** 56 | * @param {AppCrudGrid|AppCrudForm} $this 57 | * @param {Function} callback 58 | * @param {string} title 59 | * @param {string} message 60 | * @returns {Function} 61 | */ 62 | export const destroy = ($this, callback = (() => null), title, message) => { 63 | return (record, schemas, $component) => { 64 | confirm(title, message, () => $this.delete(record[$this.id], callback)) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /bootstrap/configure/path.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} path 3 | * @param {Object} query 4 | * @returns {{path: *, query: {}}} 5 | */ 6 | export default (path, query = {}) => { 7 | return { 8 | path: path, 9 | query: query 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /bootstrap/configure/permission.js: -------------------------------------------------------------------------------- 1 | import { get } from 'lodash' 2 | 3 | /** 4 | * @param {Object} $user 5 | * @param {Route} $route 6 | * @param {Object} action 7 | * @returns {boolean} 8 | */ 9 | export default ($user, $route, action = null) => { 10 | // get namespace from meta, if don't have namespace in meta property confirm 11 | const namespace = get($route, 'meta.namespace', false) 12 | if (!namespace) { 13 | return true 14 | } 15 | // get permissions of current user, again confirm when is not defined 16 | const permissions = get($user, 'permissions', false) 17 | if (!permissions) { 18 | return true 19 | } 20 | // extract of permissions the access level 21 | const expected = parseInt(get(permissions[namespace], 'permission')) 22 | // intercept in meta the required access level 23 | let required = parseInt(get($route, 'meta.permission')) 24 | if (action) { 25 | // when the is to action, get from action the access level required 26 | required = parseInt(action.permission) 27 | } 28 | // return granted or not access 29 | return required <= expected 30 | } 31 | -------------------------------------------------------------------------------- /bootstrap/configure/search.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {int} page 3 | * @param {int} limit 4 | * @param {Object} filters 5 | * @returns {Object} 6 | */ 7 | export default (page, limit, filters) => { 8 | let pagination = {} 9 | if (page) { 10 | pagination = {page: page} 11 | } 12 | 13 | let limiting = {} 14 | if (limit) { 15 | limiting = {limit: limit} 16 | } 17 | 18 | return Object.assign({}, filters, limiting, pagination) 19 | } 20 | -------------------------------------------------------------------------------- /bootstrap/configure/token.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} token 3 | * @returns {string} 4 | */ 5 | export default (token) => { 6 | return `${token}` // `Bearer ${token}` 7 | } 8 | -------------------------------------------------------------------------------- /bootstrap/configure/tooltip.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true to show tooltips or false to disable 3 | * 4 | * @param {AppTooltip} $this 5 | * @return {boolean} 6 | */ 7 | export default ($this) => { 8 | return !$this.$q.platform.is.mobile 9 | } 10 | -------------------------------------------------------------------------------- /bootstrap/configure/user.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Object} user 3 | * @returns {*} 4 | */ 5 | export default (user) => { 6 | /* 7 | * Configure the property permissions to access control 8 | * Example: 9 | * permissions: { 10 | * namespaces: { 11 | * permission: [1 to 4] 12 | * } 13 | * } 14 | */ 15 | 16 | return { 17 | institution: user['ist_nome'], 18 | user: user['usr_login'], 19 | name: user['usr_nome'], 20 | profile: user['usr_perfil'] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /bootstrap/i18n/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {Object} 3 | */ 4 | export const date = { 5 | days: { 6 | week: [ 7 | 'domingo', 'segunda', 'terça', 'quarta', 'quinta', 'sexta', 'sábado' 8 | ] 9 | }, 10 | months: [ 11 | 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 12 | 'Dezembro' 13 | ] 14 | } 15 | 16 | /** 17 | * @type {Object} 18 | */ 19 | export const events = { 20 | modified: { 21 | title: 'Modificações pendentes', 22 | message: 'Você possui modificações pendentes.Deseja descartar estas modificações?' 23 | } 24 | } 25 | 26 | /** 27 | * @type {Object} 28 | */ 29 | export const validation = { 30 | required: 'Campo obrigatório', 31 | minLength: 'Informe pelo menos {min} caracteres', 32 | email: 'Informe um e-mail válido', 33 | time: 'Informe uma hora entre 00:00 e 23:59' 34 | } 35 | 36 | /** 37 | * @type {Object} 38 | */ 39 | export const crud = { 40 | save: { 41 | success: 'Registro salvo com sucesso', 42 | error: 'Houve um problema ao salvar o registro', 43 | cancel: { 44 | title: 'Cancelar', 45 | message: 'Deseja descartar as alterações?' 46 | } 47 | }, 48 | fetch: { 49 | error: 'Houve um problema ao recuperar o registro' 50 | }, 51 | run: { 52 | error: 'Erro ao processar a solicitação', 53 | success: 'Operação realizada com sucesso' 54 | } 55 | } 56 | 57 | /** 58 | * @type {Object} 59 | */ 60 | export const locales = { 61 | date, events, validation, crud 62 | } 63 | 64 | /** 65 | * @type {Object} 66 | */ 67 | export default { 68 | // process.env.LOCALE 69 | pt_BR: locales 70 | } 71 | -------------------------------------------------------------------------------- /bootstrap/populate/form.js: -------------------------------------------------------------------------------- 1 | import { Http } from 'genesis' 2 | import { getDotNotation } from 'genesis/support/transform' 3 | 4 | /** 5 | * @param {AppCrudForm} $component 6 | * @param {AxiosResponse} response 7 | * @param {Function} callback 8 | */ 9 | export default ($component, response, callback = null) => { 10 | const $body = Http.get('$body') 11 | 12 | let body = $body(response) 13 | if (!Array.isArray(body)) { 14 | $component.data = getDotNotation($component.fields, body) 15 | return 16 | } 17 | $component.data = getDotNotation($component.fields, body[0]) 18 | 19 | if (typeof callback === 'function') { 20 | callback() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /bootstrap/populate/grid.js: -------------------------------------------------------------------------------- 1 | import { Http } from 'genesis' 2 | import { getDotNotation } from 'genesis/support/transform' 3 | 4 | /** 5 | * @param {AppCrudGrid} $component 6 | * @param {AxiosResponse} response 7 | */ 8 | export default ($component, response) => { 9 | const $body = Http.get('$body') 10 | const $meta = Http.get('$meta') 11 | 12 | if (!$component.isPaginated()) { 13 | let data = response 14 | if (!Array.isArray(data)) { 15 | data = $body(response) 16 | } 17 | $component.data = data 18 | return 19 | } 20 | 21 | const body = $body(response) 22 | const meta = $meta(response) 23 | 24 | if (!Array.isArray(body)) { 25 | $component.data = [] 26 | return 27 | } 28 | 29 | $component.pages = parseInt(Math.ceil(meta.total / $component.limit)) 30 | $component.total = parseInt(meta.total) 31 | $component.data = body.map(record => getDotNotation($component.columns, record)) 32 | } 33 | -------------------------------------------------------------------------------- /components/@mixins/MixinNavigation.js: -------------------------------------------------------------------------------- 1 | import { uniqid } from 'genesis/support/utils' 2 | 3 | export default { 4 | props: { 5 | changer: { 6 | type: String, 7 | default: () => '~' 8 | } 9 | }, 10 | methods: { 11 | /** 12 | * @param {string} path 13 | * @param {Object} query 14 | */ 15 | browse (path, query = {}) { 16 | let remove = false 17 | if (query === false) { 18 | query = {} 19 | } 20 | 21 | if (query !== undefined) { 22 | query = Object.assign({}, this.$route.query, query) 23 | } 24 | if (query === undefined) { 25 | query = {} 26 | } 27 | if (path === this.$route.path) { 28 | query[this.changer] = uniqid() 29 | } 30 | if (remove) { 31 | delete query[this.changer] 32 | } 33 | 34 | const browse = () => this.$router.push({path, query}) 35 | 36 | window.setTimeout(browse, 100) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /components/@mixins/MixinNavigationTabs.js: -------------------------------------------------------------------------------- 1 | import { uniqid } from 'genesis/support/utils' 2 | 3 | export default { 4 | props: {}, 5 | methods: {} 6 | } 7 | -------------------------------------------------------------------------------- /components/@mixins/MixinNavigationWizard.js: -------------------------------------------------------------------------------- 1 | import { uniqid } from 'genesis/support/utils' 2 | 3 | export default { 4 | props: {}, 5 | methods: { 6 | nextStep () { 7 | this.$refs.form.$refs.stepper.next() 8 | }, 9 | previousStep () { 10 | this.$refs.form.$refs.stepper.previous() 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /components/@mixins/MixinPermission.js: -------------------------------------------------------------------------------- 1 | import { get } from 'lodash' 2 | import { mapGetters } from 'vuex' 3 | import { Auth } from 'genesis' 4 | 5 | export default { 6 | computed: { 7 | ...mapGetters(['getAuthUser']) 8 | }, 9 | methods: { 10 | /** 11 | * @param {Object} action 12 | * @param {Object} record 13 | */ 14 | permissionCheck (action, record) { 15 | // test if the mixin has access to $route 16 | const $route = get(this, '$route') 17 | if (!$route) { 18 | return false 19 | } 20 | // verify if permission was override with a function 21 | if (typeof action.permission === 'function') { 22 | return action.permission(record, this, this.getAuthUser) 23 | } 24 | 25 | const permission = Auth.get('permission') 26 | 27 | // test the permission using the criteria defined in configure 28 | const access = permission(this.getAuthUser, $route, action) 29 | if (!access) { 30 | return false 31 | } 32 | // last layer of verification 33 | if (typeof action.access === 'function') { 34 | return action.access(record, this, this.getAuthUser) 35 | } 36 | // all right! move on 37 | return true 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /components/breadcrumb/AppBreadcrumb.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | {{ displayIcon.caracter }} 14 | {{ item.label }} 15 | 16 | {{ item.tooltip }} 17 | 18 | 19 | 20 | 21 | 104 | 105 | 119 | -------------------------------------------------------------------------------- /components/button/AppButton.vue: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 69 | 70 | 74 | -------------------------------------------------------------------------------- /components/button/AppButtonBar.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | {{ button.tooltip }} 8 | 9 | 10 | 11 | 12 | 14 | 15 | {{ button.tooltip }} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 62 | 63 | 83 | -------------------------------------------------------------------------------- /components/calendar/AppCalendar.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 180 | 181 | 183 | -------------------------------------------------------------------------------- /components/card/AppCard.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 38 | 39 | 49 | -------------------------------------------------------------------------------- /components/collapsible/AppCollapsible.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 52 | 53 | 76 | -------------------------------------------------------------------------------- /components/crud/Form.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 68 | 69 | 75 | -------------------------------------------------------------------------------- /components/crud/Grid.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 73 | 74 | 85 | -------------------------------------------------------------------------------- /components/crud/Index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 36 | 37 | 39 | -------------------------------------------------------------------------------- /components/crud/components/grid/AppGridFilter.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Fechar o painel de filtros 7 | 8 | 9 | 10 | 11 | Filtros 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | Pesquisar 23 | Aplica a pesquisa a lista 24 | 25 | 26 | Limpar 27 | Limpa os dados da pesquisa 28 | 29 | 30 | 31 | 32 | 33 | 34 | 49 | 50 | 71 | -------------------------------------------------------------------------------- /components/crud/components/grid/AppGridToolbar.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 12 | 13 | 14 | 17 | {{ counter.start }} - {{ counter.end }} de {{ counter.total }} 18 | Exibindo {{ counter.end }} registros 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 171 | 172 | 201 | -------------------------------------------------------------------------------- /components/crud/model/form/index.js: -------------------------------------------------------------------------------- 1 | export { default as MixinForm } from 'genesis/components/crud/model/form/MixinForm' 2 | -------------------------------------------------------------------------------- /components/crud/model/general/MixinComputed.js: -------------------------------------------------------------------------------- 1 | import { APP_DEV } from 'genesis/support/index' 2 | 3 | export default { 4 | computed: { 5 | debugging () { 6 | if (!APP_DEV) { 7 | return false 8 | } 9 | return this.debug 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /components/crud/model/general/MixinData.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data: () => ({ 3 | buttons: { 4 | top: [], 5 | middle: [], 6 | bottom: [], 7 | floating: [] 8 | } 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /components/crud/model/general/MixinMethods.js: -------------------------------------------------------------------------------- 1 | import { get } from 'lodash' 2 | import { actions } from '../../model' 3 | import { setDotNotation } from 'genesis/support/transform' 4 | 5 | export default { 6 | methods: { 7 | /** 8 | * @param {Object} record 9 | * @param {Function} callback 10 | */ 11 | create (record, callback = null) { 12 | this.service 13 | .post(setDotNotation(record)) 14 | .then(response => this.then(response, 'create', callback)) 15 | .catch(error => this.catch(error, 'create', [record])) 16 | }, 17 | /** 18 | * @param {string} id 19 | * @param {Function} callback 20 | */ 21 | read (id = '', callback = null) { 22 | this.service 23 | .get(id) 24 | .then(response => this.then(response, 'read', callback)) 25 | .catch(error => this.catch(error, 'read', [id])) 26 | }, 27 | /** 28 | * @param {Object} record 29 | * @param {Function} callback 30 | */ 31 | update (record, callback = null) { 32 | this.service 33 | .put(record[this.id], setDotNotation(record)) 34 | .then(response => this.then(response, 'update', callback)) 35 | .catch(error => this.catch(error, 'update', [record])) 36 | }, 37 | /** 38 | * @param {string} id 39 | * @param {Function} callback 40 | */ 41 | delete (id = '', callback = null) { 42 | this.service 43 | .delete(id) 44 | .then(response => this.then(response, 'delete', callback)) 45 | .catch(error => this.catch(error, 'delete', [id])) 46 | }, 47 | /** 48 | * @param {Object} parameters 49 | * @param {Object} config 50 | */ 51 | search (parameters = {}, config = {}) { 52 | this.service 53 | .get('', parameters, config) 54 | .then(response => this.then(response, 'read')) 55 | .catch(error => this.catch(error, 'search', [parameters])) 56 | }, 57 | /** 58 | * @param {AxiosError} error 59 | * @param {string} method 60 | * @param {Array} parameters 61 | */ 62 | catch (error, method, parameters) { 63 | const handler = get(this.error, method, undefined) 64 | if (typeof handler === 'function') { 65 | return handler(error, parameters) 66 | } 67 | console.error(error) 68 | }, 69 | /** 70 | * @param {Object} record 71 | * @param {Function} callback 72 | * @returns {record} 73 | */ 74 | save (record, callback) { 75 | const scope = this.scopes[this.scope] 76 | if (scope.method && typeof this[scope.method] === 'function') { 77 | return this[scope.method](record, callback) 78 | } 79 | }, 80 | /** 81 | * @param {string} component 82 | * @returns {string} 83 | */ 84 | componentName (component) { 85 | return this.component + '-' + component 86 | }, 87 | /** 88 | */ 89 | renderElements () { 90 | // override 91 | }, 92 | /** 93 | */ 94 | renderActions () { 95 | // noinspection JSCheckFunctionSignatures 96 | const _actions = actions(this, this.actions) 97 | if (!Array.isArray(_actions)) { 98 | return 99 | } 100 | const buttons = _actions 101 | .filter(button => button.scopes && button.scopes.includes(this.scope)) 102 | .map(button => { 103 | if (typeof button.validate === 'function') { 104 | button.disabled = button.validate(this.record, this.schemas, this) 105 | } 106 | return button 107 | }) 108 | 109 | this.buttons.top = buttons.filter(button => button.positions.includes('top')) 110 | this.buttons.middle = buttons.filter(button => button.positions.includes('middle')) 111 | this.buttons.bottom = buttons.filter(button => button.positions.includes('bottom')) 112 | this.buttons.floating = buttons.filter(button => button.positions.includes('floating')) 113 | }, 114 | /** 115 | */ 116 | renderAll () { 117 | this.renderActions() 118 | this.renderElements() 119 | }, 120 | /** 121 | * @param {Object} action 122 | */ 123 | handler (action) { 124 | if (typeof action.handler === 'function') { 125 | action.handler(this.data, this.fields, this, action) 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /components/crud/model/general/MixinProps.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | scopes: { 4 | type: Object, 5 | default: () => ({ 6 | index: {}, 7 | create: { 8 | method: 'create' 9 | }, 10 | edit: { 11 | method: 'update' 12 | }, 13 | view: { 14 | readonly: true 15 | } 16 | }) 17 | }, 18 | scope: { 19 | type: String 20 | }, 21 | service: { 22 | type: Object, 23 | required: true, 24 | default: () => ({}) 25 | }, 26 | path: { 27 | type: String, 28 | required: true, 29 | default: () => '' 30 | }, 31 | schemas: { 32 | type: Array, 33 | required: true, 34 | default: () => ([]) 35 | }, 36 | actions: { 37 | default: () => null 38 | }, 39 | component: { 40 | type: String, 41 | default: () => 'field' 42 | }, 43 | id: { 44 | type: String, 45 | default: () => 'id' 46 | }, 47 | bottom: { 48 | type: Boolean, 49 | default: () => true 50 | }, 51 | top: { 52 | type: Boolean, 53 | default: () => true 54 | }, 55 | floating: { 56 | type: Boolean, 57 | default: () => true 58 | }, 59 | timeout: { 60 | type: Number, 61 | default: () => 100 62 | }, 63 | watches: { 64 | type: Object, 65 | default: () => ({}) 66 | }, 67 | direction: { 68 | type: String, 69 | default: () => 'right' 70 | }, 71 | className: { 72 | type: Array, 73 | default: () => ([]) 74 | }, 75 | error: { 76 | type: Object, 77 | default: () => ({ 78 | create: (error, parameters) => console.error(error, parameters), 79 | read: (error, parameters) => console.error(error, parameters), 80 | update: (error, parameters) => console.error(error, parameters), 81 | destroy: (error, parameters) => console.error(error, parameters) 82 | }) 83 | }, 84 | debug: { 85 | type: Boolean, 86 | default: () => false 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /components/crud/model/grid/index.js: -------------------------------------------------------------------------------- 1 | export { default as MixinFilter } from 'genesis/components/crud/model/grid/MixinFilter' 2 | 3 | export { default as MixinGrid } from 'genesis/components/crud/model/grid/MixinGrid' 4 | -------------------------------------------------------------------------------- /components/crud/model/index.js: -------------------------------------------------------------------------------- 1 | import { Crud } from 'genesis' 2 | 3 | export { default as MixinComputed } from 'genesis/components/crud/model/general/MixinComputed' 4 | export { default as MixinData } from 'genesis/components/crud/model/general/MixinData' 5 | export { default as MixinMethods } from 'genesis/components/crud/model/general/MixinMethods' 6 | export { default as MixinProps } from 'genesis/components/crud/model/general/MixinProps' 7 | 8 | /** 9 | * @param {Vue} $this 10 | * @param {*} actions 11 | * @returns {Array} 12 | */ 13 | export const actions = ($this, actions) => { 14 | if (Array.isArray(actions)) { 15 | return actions 16 | } 17 | const buttons = Crud.get('buttons') 18 | if (typeof actions === 'function') { 19 | return actions($this, buttons($this)) 20 | } 21 | return buttons($this) 22 | } 23 | -------------------------------------------------------------------------------- /components/data-table/AppDataTable.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | {{ action.tooltip }} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 34 | 35 | 37 | -------------------------------------------------------------------------------- /components/data-table/model/index.js: -------------------------------------------------------------------------------- 1 | export { default as computed } from './mixins/MixinComputed' 2 | 3 | export { default as data } from './mixins/MixinData' 4 | 5 | export { default as methods } from './mixins/MixinMethods' 6 | 7 | export { default as props } from './mixins/MixinProps' 8 | -------------------------------------------------------------------------------- /components/data-table/model/mixins/MixinComputed.js: -------------------------------------------------------------------------------- 1 | import { mapGetters } from 'vuex' 2 | 3 | export default { 4 | computed: { 5 | direction () { 6 | return this.position === 'left' ? 'right' : 'left' 7 | }, 8 | ...mapGetters(['getAuthUser']) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /components/data-table/model/mixins/MixinData.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data () { 3 | return { 4 | config: { 5 | styles: this.styles, 6 | refresh: false, 7 | noHeader: false, 8 | columnPicker: false, 9 | leftStickyColumns: 0, 10 | rightStickyColumns: 0, 11 | bodyStyle: this.bodyStyle, 12 | rowHeight: '50px', 13 | responsive: false, 14 | pagination: undefined, 15 | messages: this.messages, 16 | labels: this.labels 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/data-table/model/mixins/MixinMethods.js: -------------------------------------------------------------------------------- 1 | export default { 2 | methods: { 3 | /** 4 | * @param {Function} done 5 | */ 6 | refresh (done) { 7 | this.$emit('grid.refresh', done) 8 | }, 9 | /** 10 | * @param {Object} row 11 | */ 12 | rowclick (row) { 13 | this.$emit('grid.rowclick', row) 14 | }, 15 | /** 16 | * @param {Object} action 17 | * @param {Object} row 18 | */ 19 | handler (action, row) { 20 | if (typeof action.handler === 'function') { 21 | action.handler(row, this.columns, this) 22 | } 23 | }, 24 | /** 25 | * @param slot 26 | * @param cell 27 | * @returns {Object} 28 | */ 29 | on (slot, cell) { 30 | if (typeof slot.on !== 'object') { 31 | return {} 32 | } 33 | return Object.keys(slot.on).reduce((accumulate, key) => { 34 | const handler = slot.on[key] 35 | if (typeof handler === 'function') { 36 | accumulate[key] = (event) => handler(cell.row, this.columns, this, event) 37 | } 38 | return accumulate 39 | }, {}) 40 | }, 41 | /** 42 | * @param slot 43 | * @param cell 44 | * @returns {Object} 45 | */ 46 | props (slot, cell) { 47 | const props = slot.props || {} 48 | return {...props, value: cell.data, record: cell.row, user: this.getAuthUser} 49 | }, 50 | /** 51 | * @param {string} method 52 | * @param {AxiosResponse} response 53 | */ 54 | fireAfter (method, response) { 55 | if (this.after[method] && typeof this.after[method] === 'function') { 56 | this.after[method](this.record, this.schemas, this, response) 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /components/data-table/model/mixins/MixinProps.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | columns: { 4 | type: Array, 5 | default: () => ([]) 6 | }, 7 | slots: { 8 | type: Array, 9 | default: () => ([]) 10 | }, 11 | data: { 12 | type: Array, 13 | default: () => ([]) 14 | }, 15 | actions: { 16 | type: Array, 17 | default: () => ([]) 18 | }, 19 | watches: { 20 | type: Object, 21 | default: () => ({}) 22 | }, 23 | position: { 24 | type: String, 25 | default: () => 'left' 26 | }, 27 | styles: { 28 | type: Object, 29 | default: () => ({ 30 | height: 'calc(100vh - 270px)' 31 | }) 32 | }, 33 | bodyStyle: { 34 | type: Object, 35 | default: () => ({ 36 | height: 'calc(100vh - 320px)' 37 | }) 38 | }, 39 | messages: { 40 | type: Object, 41 | default: () => ({ 42 | noData: 'error Nenhum dado para exibir', 43 | noDataAfterFiltering: 'error Nenhum resultado. Por favor revise os dados informados' 44 | }) 45 | }, 46 | labels: { 47 | type: Object, 48 | default: () => ({ 49 | columns: 'Colunas', 50 | allCols: 'Todas', 51 | rows: 'Linhas', 52 | selected: { 53 | singular: 'item selecionado', 54 | plural: 'itens selecionados' 55 | }, 56 | clear: 'Limpar', 57 | search: 'Pesquisar', 58 | all: 'Todos' 59 | }) 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /components/debugger/AppDebugger.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ label }} 5 | 6 | 7 | 8 | 9 | 10 | 59 | 60 | 96 | -------------------------------------------------------------------------------- /components/fields/abstract.js: -------------------------------------------------------------------------------- 1 | import { uid } from 'quasar-framework' 2 | import { unMask } from 'genesis/support/utils/index' 3 | 4 | export default { 5 | props: { 6 | value: { 7 | default: undefined 8 | }, 9 | label: { 10 | type: String, 11 | default: '' 12 | }, 13 | type: { 14 | type: String, 15 | default: 'text' 16 | }, 17 | field: { 18 | type: String, 19 | default: 'text' 20 | }, 21 | placeholder: { 22 | type: String, 23 | default: '' 24 | }, 25 | small: { 26 | type: String, 27 | default: '' 28 | }, 29 | width: { 30 | default: '100' 31 | }, 32 | validate: { 33 | default: undefined 34 | }, 35 | tooltip: { 36 | default: '' 37 | }, 38 | title: { 39 | type: String, 40 | default: 'Este campo possui critérios de validação' 41 | }, 42 | mask: { 43 | type: String, 44 | default: '' 45 | }, 46 | className: { 47 | type: Array, 48 | default: () => ([]) 49 | }, 50 | inline: { 51 | type: Boolean, 52 | default: false 53 | }, 54 | disabled: { 55 | type: Boolean, 56 | default: false 57 | }, 58 | editable: { 59 | type: Boolean, 60 | default: true 61 | }, 62 | errors: { 63 | type: Array, 64 | default: () => ([]) 65 | }, 66 | visible: { 67 | type: Boolean, 68 | default: true 69 | }, 70 | events: { 71 | type: Object, 72 | default: () => ({}) 73 | }, 74 | max: { 75 | default: () => undefined 76 | }, 77 | cleanable: { 78 | type: Boolean, 79 | default: () => true 80 | }, 81 | cleaning: { 82 | default: () => undefined 83 | } 84 | }, 85 | computed: { 86 | /** 87 | */ 88 | classNames () { 89 | const classNames = [] 90 | const width = 'field has-' + String(this.inline ? '100' : this.width) 91 | classNames.push(width) 92 | classNames.push(this.$options.name) 93 | return classNames 94 | }, 95 | /** 96 | * @return {Array} 97 | */ 98 | problems () { 99 | if (!Array.isArray(this.errors)) { 100 | return [] 101 | } 102 | return this.errors.filter(error => !error.status).map(error => ({ 103 | path: 'validation.' + error.rule, 104 | parameters: error.parameters 105 | })) 106 | }, 107 | /** 108 | * @returns {string} 109 | */ 110 | name () { 111 | return this.field 112 | } 113 | }, 114 | data: () => ({ 115 | id: '', 116 | maxlength: '' 117 | }), 118 | methods: { 119 | /** 120 | * @param {*} value 121 | */ 122 | updateValue (value) { 123 | if (this.mask) { 124 | value = unMask(this.mask, value) 125 | } 126 | if (this.pattern) { 127 | value = unMask(this.pattern, value) 128 | } 129 | this.$emit('input', value, this) 130 | }, 131 | /** 132 | * @param {Object} $event 133 | */ 134 | focus ($event) { 135 | if (this.events.focus && typeof this.events.focus === 'function') { 136 | this.$emit('event', 'focus', this) 137 | } 138 | }, 139 | /** 140 | * @param {Object} $event 141 | */ 142 | blur ($event) { 143 | if (this.events.blur && typeof this.events.blur === 'function') { 144 | this.$emit('event', 'blur', this) 145 | } 146 | }, 147 | /** 148 | * @param {Object} $event 149 | */ 150 | keypress ($event) { 151 | if (this.events.keypress && typeof this.events.keypress === 'function') { 152 | this.$emit('event', 'keypress', this) 153 | } 154 | }, 155 | /** 156 | * @param {Object} $event 157 | */ 158 | keyup ($event) { 159 | if (this.events.keyup && typeof this.events.keyup === 'function') { 160 | this.$emit('event', 'keyup', this) 161 | } 162 | }, 163 | /** 164 | * @param {Object} $event 165 | */ 166 | enter ($event) { 167 | if (this.events.enter && typeof this.events.enter === 'function') { 168 | this.$emit('event', 'enter', this) 169 | } 170 | } 171 | }, 172 | created () { 173 | this.id = uid() 174 | this.maxlength = this.max 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /components/fields/components/base.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ label }} * 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {{ $t(problem.path, problem.parameters) }} 18 | help_outline 19 | 20 | 21 | 22 | 23 | 24 | 25 | 66 | 67 | 88 | -------------------------------------------------------------------------------- /components/fields/components/checkbox.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 78 | 79 | 88 | -------------------------------------------------------------------------------- /components/fields/components/color.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 57 | 58 | 79 | -------------------------------------------------------------------------------- /components/fields/components/file.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{ download }} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 123 | 124 | 132 | -------------------------------------------------------------------------------- /components/fields/components/html.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 37 | 38 | 45 | -------------------------------------------------------------------------------- /components/fields/components/input.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 65 | 66 | 75 | -------------------------------------------------------------------------------- /components/fields/components/money.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 99 | 100 | 111 | -------------------------------------------------------------------------------- /components/fields/components/numeric.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | remove 8 | 9 | add 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 117 | 118 | 148 | -------------------------------------------------------------------------------- /components/fields/components/password.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 55 | 56 | 65 | -------------------------------------------------------------------------------- /components/fields/components/phone.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 85 | 86 | 106 | -------------------------------------------------------------------------------- /components/fields/components/radio.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 69 | 70 | 96 | -------------------------------------------------------------------------------- /components/fields/components/select.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 137 | 138 | 182 | -------------------------------------------------------------------------------- /components/fields/components/separator.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ label }} 5 | 6 | 7 | 8 | 9 | 10 | 22 | 23 | 33 | -------------------------------------------------------------------------------- /components/fields/components/text.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 65 | 66 | 75 | -------------------------------------------------------------------------------- /components/fields/components/textarea.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 51 | 52 | 68 | -------------------------------------------------------------------------------- /components/fields/components/toggle.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 74 | 75 | 84 | -------------------------------------------------------------------------------- /components/fields/components/wysiwyg.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 80 | 81 | 103 | -------------------------------------------------------------------------------- /components/fields/functional.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'field-funcional', 3 | functional: true, 4 | render (h, context) { 5 | const {component, props, on} = context.props 6 | return h(component, {props: props, on: on}) 7 | }, 8 | props: { 9 | component: String, 10 | props: Object, 11 | on: Object 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /components/fields/index.js: -------------------------------------------------------------------------------- 1 | export { default as FieldCheckbox } from './components/checkbox.vue' 2 | export { default as FieldColor } from './components/color.vue' 3 | export { default as FieldDate } from './components/date.vue' 4 | export { default as FieldFile } from './components/file.vue' 5 | export { default as FieldHtml } from './components/html.vue' 6 | export { default as FieldMoney } from './components/money.vue' 7 | export { default as FieldNumeric } from './components/numeric.vue' 8 | export { default as FieldPassword } from './components/password.vue' 9 | export { default as FieldPhone } from './components/phone.vue' 10 | export { default as FieldPivot } from './components/pivot.vue' 11 | export { default as FieldRadio } from './components/radio.vue' 12 | export { default as FieldSearch } from './components/search' 13 | export { default as FieldSelect } from './components/select.vue' 14 | export { default as FieldSeparator } from './components/separator.vue' 15 | export { default as FieldText } from './components/text.vue' 16 | export { default as FieldTextarea } from './components/textarea.vue' 17 | export { default as FieldTime } from './components/time.vue' 18 | export { default as FieldToggle } from './components/toggle.vue' 19 | export { default as FieldWysiwyg } from './components/wysiwyg.vue' 20 | 21 | export { default as FieldFunctional } from './functional' 22 | -------------------------------------------------------------------------------- /components/form/AppForm.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 43 | 44 | 48 | -------------------------------------------------------------------------------- /components/form/AppFormTabs.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 34 | 35 | 41 | -------------------------------------------------------------------------------- /components/form/AppWizard.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | Voltar 12 | Avançar 14 | 15 | 16 | 17 | Back 18 | Next 19 | 20 | 21 | 22 | 23 | 24 | 40 | 41 | 51 | -------------------------------------------------------------------------------- /components/form/model/index.js: -------------------------------------------------------------------------------- 1 | export { default as data } from './mixins/MixinData' 2 | 3 | export { default as methods } from './mixins/MixinMethods' 4 | 5 | export { default as props } from './mixins/MixinProps' 6 | 7 | export { default as watch } from './mixins/MixinWatch' 8 | -------------------------------------------------------------------------------- /components/form/model/mixins/MixinData.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data: () => ({ 3 | components: {}, 4 | schemas: {}, 5 | record: {}, 6 | tabSeletecd: '', 7 | currentStep: '', 8 | modified: false 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /components/form/model/mixins/MixinProps.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | tabs: { 4 | type: Array, 5 | default: () => ([]) 6 | }, 7 | tab: { 8 | type: String, 9 | default: () => '' 10 | }, 11 | steps: { 12 | type: Array, 13 | default: () => ([]) 14 | }, 15 | step: { 16 | type: String, 17 | default: () => '' 18 | }, 19 | fields: { 20 | type: Array, 21 | default: () => ([]) 22 | }, 23 | data: { 24 | type: Object, 25 | default: () => ({}) 26 | }, 27 | readonly: { 28 | type: Boolean, 29 | default: () => (false) 30 | }, 31 | watches: { 32 | type: Object, 33 | default: () => ({}) 34 | }, 35 | change: { 36 | type: Function 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /components/form/model/mixins/MixinWatch.js: -------------------------------------------------------------------------------- 1 | import { isEqual } from 'lodash' 2 | 3 | export default { 4 | watch: { 5 | /** 6 | * @param {Object} record 7 | * @param {Object} previous 8 | */ 9 | data (record, previous) { 10 | if (!isEqual(record, previous)) { 11 | this.setRecord(record) 12 | this.fireWatch('set/record') 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /components/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import * as fields from './fields' 3 | import AppDebugger from './debugger/AppDebugger.vue' 4 | import AppLink from './link/AppLink.vue' 5 | import AppTooltip from './tooltip/AppTooltip.vue' 6 | 7 | const components = Object.assign({}, fields, {AppDebugger, AppLink, AppTooltip}) 8 | 9 | Object.keys(components).forEach(key => { 10 | Vue.component(key, components[key]) 11 | }) 12 | -------------------------------------------------------------------------------- /components/layout/drawer/DrawerMenu.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 51 | 52 | 58 | -------------------------------------------------------------------------------- /components/link/AppLink.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ value }} 4 | {{ tooltip }} 5 | 6 | 7 | 8 | 42 | -------------------------------------------------------------------------------- /components/table/AppTable.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 62 | 63 | 65 | -------------------------------------------------------------------------------- /components/tooltip/AppTooltip.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 50 | 51 | 53 | -------------------------------------------------------------------------------- /components/transition/AppTransitionSlide.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 66 | 67 | 88 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./themes/fonts/index.styl') 2 | 3 | export { default as Http } from 'genesis/settings/http' 4 | export { default as Auth } from 'genesis/settings/auth' 5 | export { default as Crud } from 'genesis/settings/crud' 6 | export { default as Routes } from 'genesis/settings/routes' 7 | export { default as Model } from 'genesis/settings/model' 8 | export { default as Navigation } from 'genesis/settings/navigation' 9 | export { default as Data } from 'genesis/settings/data' 10 | export { default as View } from 'genesis/settings/view' 11 | -------------------------------------------------------------------------------- /infra/router/guard.js: -------------------------------------------------------------------------------- 1 | import { Events } from 'quasar-framework' 2 | import { Auth, View } from 'genesis' 3 | import store from 'genesis/infra/store' 4 | import { abort } from 'genesis/infra/services/http' 5 | import { PATH_NO_ACCESS, PATH_LOGIN } from 'genesis/support' 6 | import { confirm } from 'genesis/support/message' 7 | import { unRegister } from 'genesis/modules/auth/services/index' 8 | 9 | /** 10 | * @param {Array} routes 11 | * @returns {Array} 12 | */ 13 | export const protect = (routes) => { 14 | const security = {security: true} 15 | 16 | if (Array.isArray(routes)) { 17 | return routes.map(route => { 18 | if (!route.meta) { 19 | route.meta = security 20 | } 21 | if (route.meta.security === undefined) { 22 | route.meta.security = true 23 | } 24 | if (route.children) { 25 | route.children = protect(route.children) 26 | } 27 | return route 28 | }) 29 | } 30 | return routes 31 | } 32 | 33 | /** 34 | * @return {boolean} 35 | */ 36 | export const checkSession = () => { 37 | // noinspection JSUnresolvedVariable 38 | return store.getters.getAuthToken 39 | } 40 | 41 | /** 42 | * @return {boolean} 43 | */ 44 | export const checkPermission = ($route) => { 45 | const permission = Auth.get('permission') 46 | // noinspection JSUnresolvedVariable 47 | return permission(store.getters.getAuthUser, $route) 48 | } 49 | 50 | /** 51 | * @param {function} next 52 | * @returns {*} 53 | */ 54 | export const checkModified = (next) => { 55 | const modified = store.getters.AppModified 56 | if (modified) { 57 | const moveOn = () => { 58 | store.dispatch('setAppModified', false) 59 | next() 60 | } 61 | const ask = () => { 62 | confirm(View.get('locales.events.modified.title'), View.get('locales.events.modified.message'), moveOn) 63 | } 64 | window.setTimeout(ask, 100) 65 | return true 66 | } 67 | return false 68 | } 69 | 70 | /** 71 | * @param {Function} next 72 | * @returns {*} 73 | */ 74 | export const exit = (next) => { 75 | return unRegister(() => next(PATH_LOGIN)) 76 | } 77 | 78 | /** 79 | * @param {Function} next 80 | * @param {string} blocked 81 | * @returns {*} 82 | */ 83 | export const restrict = (next, blocked = '') => { 84 | return next(Object.assign({}, PATH_NO_ACCESS, {query: {blocked}})) 85 | } 86 | 87 | /** 88 | * @param {Route} to 89 | * @param {Route} from 90 | * @param {Function} next 91 | * @returns {*} 92 | */ 93 | export const beforeEach = (to, from, next) => { 94 | // noinspection JSUnresolvedVariable 95 | const security = to.meta.security 96 | // abort all requests xhr 97 | abort('The route where request was started was leaved, all requests was canceled') 98 | // the target is not protected 99 | if (!security) { 100 | return toNext(to, next) 101 | } 102 | // test if app is with state modified 103 | if (checkModified(next)) { 104 | return next(false) 105 | } 106 | // if there is no session exit app 107 | if (!checkSession()) { 108 | return exit(next) 109 | } 110 | // when target is not allowed the access will be restricted 111 | if (!checkPermission(to)) { 112 | return restrict(next, to.path) 113 | } 114 | // all right, move on 115 | return toNext(to, next) 116 | } 117 | 118 | /** 119 | * @param {Route} to 120 | * @param {Function} next 121 | * @param {string} path 122 | * @returns {*} 123 | */ 124 | const toNext = (to, next, path = '') => { 125 | Events.$emit('app.route.before', to, path) 126 | if (path) { 127 | return next(path) 128 | } 129 | next() 130 | } 131 | 132 | /** 133 | * @param {Route} to 134 | * @param {Route} from 135 | * @returns {*} 136 | */ 137 | export const afterEach = (to, from) => { 138 | const updateInfo = () => { 139 | // update app title 140 | setTitle(to.meta.title) 141 | // update app tooltip 142 | setTooltip(to.meta.tooltip) 143 | } 144 | // clear messages 145 | store.dispatch('setAppMessages', []).then(updateInfo) 146 | } 147 | 148 | /** 149 | * @param {string} title 150 | */ 151 | const setTitle = (title) => { 152 | // noinspection JSIgnoredPromiseFromCall 153 | store.dispatch('setAppTitle', title || store.getters.AppName) 154 | } 155 | 156 | /** 157 | * @param {string} tooltip 158 | */ 159 | const setTooltip = (tooltip) => { 160 | // noinspection JSIgnoredPromiseFromCall 161 | store.dispatch('setAppTooltip', tooltip || '') 162 | } 163 | -------------------------------------------------------------------------------- /infra/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import { Routes } from 'genesis' 4 | 5 | Vue.use(Router) 6 | 7 | /** 8 | * @type {VueRouter} 9 | */ 10 | const AppRouter = new Router({routes: []}) 11 | 12 | /** 13 | * @type {Function} 14 | */ 15 | export const load = Routes.get('load') 16 | 17 | /** 18 | * @type {Array} 19 | */ 20 | export const routes = Routes.get('routes') 21 | 22 | /** 23 | * @param {Array} news 24 | */ 25 | export const add = (news) => { 26 | routes.push(...news) 27 | AppRouter.addRoutes(configure(news)) 28 | } 29 | 30 | /** 31 | * @param {Array} routes 32 | */ 33 | export const configure = (routes) => { 34 | return routes.map(route => { 35 | route.component = load(route.component) 36 | if (route.children) { 37 | route.children = configure(route.children) 38 | } 39 | return route 40 | }) 41 | } 42 | 43 | AppRouter.addRoutes(configure(routes)) 44 | 45 | AppRouter.beforeEach(Routes.get('beforeEach')) 46 | AppRouter.afterEach(Routes.get('afterEach')) 47 | 48 | export default AppRouter 49 | -------------------------------------------------------------------------------- /infra/router/resources.js: -------------------------------------------------------------------------------- 1 | import { Crud } from 'genesis' 2 | 3 | /** 4 | * @param {string} path 5 | * @param {string} name 6 | * @param {string} component 7 | * @param {Function|Object|boolean} props 8 | * @param {Object} meta 9 | * @param {Array} children 10 | * @returns {Object} 11 | */ 12 | export const route = (path, name, component, props = null, meta = {}, children = []) => { 13 | return {path, name, component, props, meta, children} 14 | } 15 | 16 | /** 17 | * 18 | * namespace: 'app.user', // ACL 19 | * permission: [1 to 4], // ACL 20 | * icon: 'add', // breadcrumb 21 | * label: 'Criar', // breadcrumb 22 | * title: 'Criar / ' + label, // window title 23 | * tooltip: 'Cria um novo registro no(a) ' + title // sub header on layout 24 | * 25 | * @param {string} path 26 | * @param {string} namespace 27 | * @param {Function} props 28 | * @param {string} uri 29 | * @param {string} scope 30 | * @param {string} component 31 | * @param {Object} meta 32 | * @param {string} name 33 | * @returns {Object} 34 | */ 35 | export const child = (path, namespace, props, uri, scope, component, meta = {}, name = '') => { 36 | return route(uri, name || (namespace + '.' + scope), component, (route) => props(scope, route), meta) 37 | } 38 | 39 | /** 40 | * @param {string} path 41 | * @param {string} namespace 42 | * @param {Function} grid 43 | * @param {Function} form 44 | * @param {Object} meta 45 | * @param {string} id 46 | * @param {string} components 47 | * @returns {Array} 48 | */ 49 | export const crud = (path, namespace, grid, form, meta, id = 'id') => { 50 | const resources = factory(path, namespace, grid, form, meta) 51 | const configure = Crud.get('configure') 52 | return [ 53 | route(path, '', configure('Index'), {title: meta.label}, meta, [ 54 | child(path, namespace, grid, '', 'index', configure('Grid'), resources.$read()), 55 | child(path, namespace, form, 'create', 'create', configure('Form'), resources.$create()), 56 | child(path, namespace, form, ':' + id, 'view', configure('Form'), resources.$view()), 57 | child(path, namespace, form, ':' + id + '/edit', 'edit', configure('Form'), resources.$edit()) 58 | ]) 59 | ] 60 | } 61 | 62 | /** 63 | * @param {string} path 64 | * @param {string} namespace 65 | * @param {Function} grid 66 | * @param {Function} form 67 | * @param {Object} meta 68 | * @returns {*} 69 | */ 70 | export const factory = (path, namespace, grid, form, meta) => { 71 | return { 72 | /** 73 | * @param {int} permission 74 | * @param {string} icon 75 | * @param {string} label 76 | * @param {string} title 77 | * @param {string} tooltip 78 | * @returns {Object} 79 | */ 80 | $meta (permission, icon, label, title, tooltip) { 81 | return {namespace, permission, icon, label, title, tooltip} 82 | }, 83 | /** 84 | * @param {Object} options 85 | * @returns {Object} 86 | */ 87 | $read (options = {}) { 88 | return Object.assign({}, meta, {namespace: namespace, permission: 1, noBreadcrumb: true}, options) 89 | }, 90 | /** 91 | * @param {Object} options 92 | * @returns {Object} 93 | */ 94 | $create (options = {}) { 95 | const create = this.$meta( 96 | 2, 'add', 'Criar', `${meta.label} / Criar`, 'Cria um novo registro no(a) ' + meta.title 97 | ) 98 | return Object.assign({}, create, options) 99 | }, 100 | /** 101 | * @param {Object} options 102 | * @returns {Object} 103 | */ 104 | $view (options = {}) { 105 | const view = this.$meta( 106 | 1, 'search', 'Visualizar', `${meta.label} / Visualizar`, 'Visualiza um registro do(a) ' + meta.title 107 | ) 108 | return Object.assign({}, view, options) 109 | }, 110 | /** 111 | * @param {Object} options 112 | * @returns {Object} 113 | */ 114 | $edit (options = {}) { 115 | // permission, icon, label, title, tooltip 116 | const edit = this.$meta( 117 | 3, 'edit', 'Editar', `${meta.label} / Editar`, 'Edita um novo registro do(a) ' + meta.title 118 | ) 119 | return Object.assign({}, edit, options) 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /infra/services/http/configure.js: -------------------------------------------------------------------------------- 1 | import { uid } from 'quasar-framework' 2 | import { Http } from 'genesis' 3 | 4 | /** 5 | * @param {Object} http 6 | */ 7 | export default http => { 8 | const $extract = Http.get('$extract') 9 | 10 | const _request = http.request 11 | http.request = function (config) { 12 | return _request(Object.assign({}, {requestId: uid()}, config)) 13 | } 14 | 15 | const _get = http.get 16 | http.get = function (url, config) { 17 | return _get(url, Object.assign({}, {requestId: uid()}, config)) 18 | } 19 | 20 | const _delete = http.delete 21 | http.delete = function (url, config) { 22 | return _delete(url, Object.assign({}, {requestId: uid()}, config)) 23 | } 24 | 25 | const _head = http.head 26 | http.head = function (url, config) { 27 | return _head(url, Object.assign({}, {requestId: uid()}, config)) 28 | } 29 | 30 | const _options = http.options 31 | http.options = function (url, config) { 32 | return _options(url, Object.assign({}, {requestId: uid()}, config)) 33 | } 34 | 35 | const _post = http.post 36 | http.post = function (url, data, config) { 37 | return _post(url, data, Object.assign({}, {requestId: uid()}, config)) 38 | } 39 | 40 | const _put = http.put 41 | http.put = function (url, data, config) { 42 | return _put(url, data, Object.assign({}, {requestId: uid()}, config)) 43 | } 44 | 45 | const _patch = http.patch 46 | http.patch = function (url, data, config) { 47 | return _patch(url, data, Object.assign({}, {requestId: uid()}, config)) 48 | } 49 | 50 | /** 51 | * @param {AxiosResponse} response 52 | * @param {string} property 53 | * @param {*} fallback 54 | * @returns {*} 55 | */ 56 | http.$extract = (response, property, fallback = {}) => { 57 | return $extract(response, property, fallback) 58 | } 59 | 60 | /** 61 | * @param {AxiosResponse} response 62 | * @param {*} fallback 63 | * @returns {*} 64 | */ 65 | http.$body = (response, fallback = {}) => { 66 | return $extract(response, 'body', fallback) 67 | } 68 | 69 | /** 70 | * @param {AxiosResponse} response 71 | * @param {*} fallback 72 | * @returns {*} 73 | */ 74 | http.$meta = (response, fallback = {}) => { 75 | return $extract(response, 'meta', fallback) 76 | } 77 | 78 | /** 79 | * @param {AxiosResponse} response 80 | * @returns {*} 81 | */ 82 | http.$first = (response) => { 83 | const content = http.$body(response) 84 | if (Array.isArray(content)) { 85 | return content.shift() 86 | } 87 | return {} 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /infra/services/http/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import canceler from 'axios-cancel' 3 | import { Auth } from 'genesis' 4 | import { URL_API } from 'genesis/support' 5 | import { loading } from 'genesis/support/message' 6 | 7 | import configure from './configure' 8 | 9 | /** 10 | * @type {Axios} 11 | */ 12 | export const http = axios.create({ 13 | baseURL: URL_API, 14 | headers: { 15 | 'Accept': 'application/json', 16 | 'Content-Type': 'application/json' 17 | } 18 | }) 19 | 20 | /** 21 | * @returns {Axios} 22 | */ 23 | export const install = () => { 24 | configure(http) 25 | 26 | canceler(http, { 27 | debug: false // process.env.DEV 28 | }) 29 | return http 30 | } 31 | 32 | /** 33 | * @param {string} token 34 | */ 35 | export const setToken = token => { 36 | const configureToken = Auth.get('token') 37 | configureToken(http, token) 38 | } 39 | 40 | /** 41 | * @param {string} reason 42 | */ 43 | export const abort = reason => { 44 | http.cancelAll(reason) 45 | loading(false) 46 | } 47 | 48 | /** 49 | * @param {string} requestId 50 | */ 51 | export const cancel = (requestId) => { 52 | http.cancel(requestId) 53 | loading(false) 54 | } 55 | 56 | /** 57 | * @type {Axios} 58 | */ 59 | export default http 60 | -------------------------------------------------------------------------------- /infra/services/http/plugin.js: -------------------------------------------------------------------------------- 1 | import { Http } from 'genesis' 2 | import { loading } from 'genesis/support/message/index' 3 | import { PATH_LOGIN } from 'genesis/support/index' 4 | import { default as http, install } from 'genesis/infra/services/http' 5 | import Cache from 'js-cache' 6 | 7 | /** 8 | * @param http 9 | * @param store 10 | * @param router 11 | * @param cache 12 | */ 13 | export const interceptors = (http, store, router, cache) => { 14 | const httpRequest = Http.get('httpRequest') 15 | const httpResponse = Http.get('httpResponse') 16 | const httpError = Http.get('httpError') 17 | /** 18 | * @param request 19 | * @returns {*} 20 | */ 21 | const request = (request) => { 22 | // noinspection JSUnresolvedVariable 23 | if (!request.noLoading) { 24 | loading(true, 100) 25 | } 26 | return httpRequest(request, cache) 27 | } 28 | http.interceptors.request.use(request) 29 | 30 | /** 31 | * @param response 32 | * @returns {*} 33 | */ 34 | const response = (response) => { 35 | loading(false) 36 | // noinspection JSUnresolvedVariable 37 | if (response.headers && response.headers.authorization) { 38 | // noinspection JSUnresolvedVariable 39 | store.dispatch('setAuthToken', response.headers.authorization) 40 | } 41 | return httpResponse(response, cache) 42 | } 43 | 44 | /** 45 | * @param error 46 | * @returns {Promise | Promise.<*>} 47 | */ 48 | const error = (error) => { 49 | loading(false) 50 | const {response} = error 51 | if (response && [401, 402].indexOf(response.status) > -1) { 52 | router.push(PATH_LOGIN) 53 | } 54 | return Promise.reject(httpError(error, router, store)) 55 | } 56 | 57 | http.interceptors.response.use(response, error) 58 | } 59 | 60 | /** 61 | * @param Vue 62 | * @param store 63 | * @param router 64 | * @returns {AxiosInstance} 65 | */ 66 | export default (Vue, {store, router}) => { 67 | install() 68 | interceptors(http, store, router, new Cache) 69 | Object.defineProperty(Vue.prototype, '$http', { 70 | get () { 71 | return http 72 | } 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /infra/services/http/resource.js: -------------------------------------------------------------------------------- 1 | import http from 'genesis/infra/services/http/index' 2 | import { Http } from 'genesis' 3 | 4 | /** 5 | * @param {object} object 6 | * @param {string} prefix 7 | * @returns {string} 8 | */ 9 | export const serialize = (object, prefix = '') => { 10 | const string = [] 11 | for (let property in object) { 12 | if (!object.hasOwnProperty(property)) { 13 | continue 14 | } 15 | let key = prefix ? prefix + '[' + property + ']' : property 16 | let value = object[property] 17 | let serialized = '' 18 | if (value && typeof value === 'object') { 19 | serialized = serialize(value, key) 20 | } 21 | else { 22 | serialized = encodeURIComponent(key) + '=' + encodeURIComponent(value) 23 | } 24 | string.push(serialized) 25 | } 26 | return string.join('&') 27 | } 28 | 29 | /** 30 | * @param {string} base 31 | * @param {string} uri 32 | * @param {object} parameters 33 | * @returns {string} 34 | */ 35 | export const url = (base, uri, parameters) => { 36 | return base + (uri ? '/' + uri : '') + (parameters ? '?' + serialize(parameters) : '') 37 | } 38 | 39 | /** 40 | * @param {string} path 41 | * @param {Object} fixed 42 | * @returns {Function} 43 | */ 44 | export const create = (path, fixed = {}) => { 45 | if (typeof fixed !== 'object') { 46 | fixed = {} 47 | } 48 | /** 49 | * @param {object} data 50 | * @param {string} uri 51 | * @param {object} parameters 52 | * @param {object} config 53 | */ 54 | return (data, uri, parameters, config) => { 55 | return http.post(url(path, uri, Object.assign({}, parameters, fixed)), data, config) 56 | } 57 | } 58 | 59 | /** 60 | * @param {string} path 61 | * @param {Object} fixed 62 | * @returns {Function} 63 | */ 64 | export const read = (path, fixed = {}) => { 65 | if (typeof fixed !== 'object') { 66 | fixed = {} 67 | } 68 | /** 69 | * @param {string} uri 70 | * @param {object} parameters 71 | * @param {object} config 72 | */ 73 | return (uri, parameters, config) => { 74 | return http.get(url(path, uri, Object.assign({}, parameters, fixed)), config) 75 | } 76 | } 77 | 78 | /** 79 | * @param {string} path 80 | * @param {Object} fixed 81 | * @returns {Function} 82 | */ 83 | export const update = (path, fixed = {}) => { 84 | if (typeof fixed !== 'object') { 85 | fixed = {} 86 | } 87 | /** 88 | * @param {string} id 89 | * @param {object} data 90 | * @param {object} parameters 91 | * @param {object} config 92 | */ 93 | return (id, data, parameters, config) => { 94 | return http.put(url(path, id, Object.assign({}, parameters, fixed)), data, config) 95 | } 96 | } 97 | 98 | /** 99 | * @param {string} path 100 | * @param {Object} fixed 101 | * @returns {Function} 102 | */ 103 | export const destroy = (path, fixed = {}) => { 104 | if (typeof fixed !== 'object') { 105 | fixed = {} 106 | } 107 | /** 108 | * @param {object} path 109 | * @param {string} id 110 | * @param {object} parameters 111 | */ 112 | return (id, parameters, config) => { 113 | return http.delete(url(path, id, Object.assign({}, parameters, fixed)), config) 114 | } 115 | } 116 | 117 | /** 118 | * @param {string} api - endpoint of api 119 | * @param {string} value - property what is the value in options 120 | * @param {string} label - property what is the label in options 121 | * @param {Object} more - properties do be mapped 122 | * @return {Function} 123 | */ 124 | export const source = (api, value, label, more = {}) => { 125 | const map = (item) => { 126 | const reduce = (accumulate, key) => { 127 | if (item[more[key]]) { 128 | accumulate[key] = item[more[key]] 129 | } 130 | return accumulate 131 | } 132 | const others = Object.keys(more).reduce(reduce, {}) 133 | const base = { 134 | value: item[value], 135 | label: item[label] 136 | } 137 | return Object.assign({}, base, others) 138 | } 139 | const success = (response, callback) => { 140 | const $body = Http.get('$body') 141 | 142 | const data = $body(response) 143 | let source = [] 144 | if (Array.isArray(data)) { 145 | source = data.map(map) 146 | } 147 | callback(source) 148 | } 149 | /** 150 | * @param {Function} callback 151 | */ 152 | return (callback) => read(api)('').then(response => success(response, callback)) 153 | } 154 | 155 | /** 156 | * @param {string} path 157 | * @param {Object} fixed 158 | * @returns {Resource} 159 | */ 160 | export const resource = (path, fixed = {}) => { 161 | return new Resource(path, fixed) 162 | } 163 | 164 | /** 165 | * @type {Resource} 166 | */ 167 | class Resource { 168 | /** 169 | * @param {string} path 170 | * @param {Object} fixed 171 | */ 172 | constructor (path, fixed) { 173 | this.post = create(path, fixed) 174 | this.get = read(path, fixed) 175 | this.put = update(path, fixed) 176 | this.patch = update(path, fixed) 177 | this.delete = destroy(path, fixed) 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /infra/storage/index.js: -------------------------------------------------------------------------------- 1 | // quasar wrappers 2 | import {LocalStorage, SessionStorage} from 'quasar-framework' 3 | 4 | const parse = value => value === 'undefined' ? undefined : value 5 | 6 | const isValid = value => value !== 'undefined' && value !== undefined && value !== null 7 | 8 | /** 9 | * @param {string} index 10 | * @param {*} keep 11 | * @returns {*} 12 | */ 13 | export const get = (index, keep = null) => { 14 | if (keep === true) { 15 | return parse(LocalStorage.get.item(index)) 16 | } 17 | if (keep === false) { 18 | return parse(LocalStorage.get.item(index)) 19 | } 20 | const local = LocalStorage.get.item(index) 21 | if (isValid(local)) { 22 | return local 23 | } 24 | const session = SessionStorage.get.item(index) 25 | if (isValid(session)) { 26 | return session 27 | } 28 | } 29 | 30 | /** 31 | * @param {string} index 32 | * @param {*} value 33 | * @param {boolean} keep 34 | * @returns {*} 35 | */ 36 | export const set = (index, value, keep = false) => { 37 | if (value === undefined) { 38 | if (keep) { 39 | return LocalStorage.remove(index) 40 | } 41 | return SessionStorage.remove(index) 42 | } 43 | if (keep) { 44 | return LocalStorage.set(index, value) 45 | } 46 | return SessionStorage.set(index, value) 47 | } 48 | -------------------------------------------------------------------------------- /infra/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import state from 'genesis/infra/store/schema/state' 5 | import mutations from 'genesis/infra/store/schema/mutations' 6 | 7 | import * as actions from 'genesis/infra/store/schema/actions' 8 | import * as getters from 'genesis/infra/store/schema/getters' 9 | 10 | import modules from 'genesis/infra/store/schema/modules' 11 | 12 | Vue.use(Vuex) 13 | 14 | const strict = process.env.DEV 15 | 16 | const AppStore = new Vuex.Store({state, mutations, actions, getters, modules, strict}) 17 | 18 | export default AppStore 19 | -------------------------------------------------------------------------------- /infra/store/schema/actions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Vuex actions 3 | */ 4 | import * as types from 'genesis/infra/store/types' 5 | 6 | /** 7 | * @param context 8 | * @param {string} title 9 | */ 10 | export const setAppTitle = (context, title) => { 11 | context.commit(types.setAppTitle, title) 12 | } 13 | 14 | /** 15 | * @param context 16 | * @param {string} tooltip 17 | */ 18 | export const setAppTooltip = (context, tooltip) => { 19 | context.commit(types.setAppTooltip, tooltip) 20 | } 21 | 22 | /** 23 | * @param context 24 | * @param {Object} width 25 | */ 26 | export const setAppWidth = (context, width) => { 27 | context.commit(types.setAppWidth, width) 28 | } 29 | 30 | /** 31 | * @param context 32 | * @param {Object} height 33 | */ 34 | export const setAppHeight = (context, height) => { 35 | context.commit(types.setAppHeight, height) 36 | } 37 | 38 | /** 39 | * @param context 40 | * @param {Object} modified 41 | */ 42 | export const setAppModified = (context, modified) => { 43 | context.commit(types.setAppModified, modified) 44 | } 45 | 46 | /** 47 | * @param context 48 | * @param {Array} menu 49 | */ 50 | export const setAppMenu = (context, menu) => { 51 | context.commit(types.setAppMenu, menu) 52 | } 53 | 54 | /** 55 | * @param context 56 | * @param messages 57 | */ 58 | export const setAppMessages = (context, messages) => { 59 | context.commit(types.setAppMessages, messages) 60 | } 61 | -------------------------------------------------------------------------------- /infra/store/schema/getters.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Vuex getters 3 | */ 4 | 5 | /** 6 | * @param app 7 | */ 8 | export const AppName = ({ app }) => app.name 9 | 10 | /** 11 | * @param app 12 | */ 13 | export const AppTitle = ({ app }) => app.title 14 | 15 | /** 16 | * @param app 17 | */ 18 | export const AppTooltip = ({ app }) => app.tooltip 19 | 20 | /** 21 | * @param app 22 | */ 23 | export const AppWidth = ({ app }) => app.width 24 | 25 | /** 26 | * @param app 27 | */ 28 | export const AppHeight = ({ app }) => app.height 29 | 30 | /** 31 | * @param app 32 | */ 33 | export const AppModified = ({ app }) => app.modified 34 | 35 | /** 36 | * @param app 37 | */ 38 | export const AppMenu = ({ app }) => app.menu 39 | 40 | /** 41 | * @param app 42 | */ 43 | export const AppMessages = ({ app }) => app.messages 44 | -------------------------------------------------------------------------------- /infra/store/schema/modules.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Vuex modules 3 | */ 4 | import { store as auth } from 'genesis/modules/auth/index' 5 | import { store as permission } from 'genesis/modules/permission/index' 6 | import { store as dashboard } from 'genesis/modules/dashboard/index' 7 | 8 | export default { 9 | auth, permission, dashboard 10 | } 11 | -------------------------------------------------------------------------------- /infra/store/schema/mutations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Vuex mutations 3 | */ 4 | import * as types from 'genesis/infra/store/types' 5 | 6 | export default { 7 | /** 8 | * @param state 9 | * @param name 10 | */ 11 | [types.setAppName] (state, name) { 12 | state.app.name = name 13 | }, 14 | /** 15 | * @param state 16 | * @param title 17 | */ 18 | [types.setAppTitle] (state, title) { 19 | state.app.title = title 20 | }, 21 | /** 22 | * @param state 23 | * @param tooltip 24 | */ 25 | [types.setAppTooltip] (state, tooltip) { 26 | state.app.tooltip = tooltip 27 | }, 28 | /** 29 | * @param state 30 | * @param width 31 | */ 32 | [types.setAppWidth] (state, width) { 33 | state.app.width = width 34 | }, 35 | /** 36 | * @param state 37 | * @param height 38 | */ 39 | [types.setAppHeight] (state, height) { 40 | state.app.height = height 41 | }, 42 | /** 43 | * @param state 44 | * @param modified 45 | */ 46 | [types.setAppModified] (state, modified) { 47 | state.app.modified = modified 48 | }, 49 | /** 50 | * @param state 51 | * @param menu 52 | */ 53 | [types.setAppMenu] (state, menu) { 54 | state.app.menu = menu 55 | }, 56 | /** 57 | * @param state 58 | * @param modified 59 | */ 60 | [types.setAppMessages] (state, modified) { 61 | state.app.messages = modified 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /infra/store/schema/state.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Vuex state 3 | */ 4 | import { APP_NAME } from 'genesis/support/index' 5 | 6 | const label = APP_NAME 7 | 8 | export default { 9 | app: { 10 | name: label, 11 | title: label, 12 | tooltip: '', 13 | width: 0, 14 | height: 0, 15 | modified: false, 16 | menu: [], 17 | messages: [] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /infra/store/types.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {string} 3 | */ 4 | export const setAppName = 'app/setAppName' 5 | 6 | /** 7 | * @type {string} 8 | */ 9 | export const setAppTitle = 'app/setAppTitle' 10 | 11 | /** 12 | * @type {string} 13 | */ 14 | export const setAppTooltip = 'app/setAppTooltip' 15 | 16 | /** 17 | * @type {string} 18 | */ 19 | export const setAppWidth = 'app/setAppWidth' 20 | 21 | /** 22 | * @type {string} 23 | */ 24 | export const setAppHeight = 'app/setAppHeight' 25 | 26 | /** 27 | * @type {string} 28 | */ 29 | export const setAppModified = 'app/setAppModified' 30 | 31 | /** 32 | * @type {string} 33 | */ 34 | export const setAppMenu = 'app/setAppMenu' 35 | 36 | /** 37 | * @type {string} 38 | */ 39 | export const setAppMessages = 'app/setAppMessages' 40 | -------------------------------------------------------------------------------- /modules/auth/index.js: -------------------------------------------------------------------------------- 1 | export { default as store } from 'genesis/modules/auth/store' 2 | -------------------------------------------------------------------------------- /modules/auth/services/index.js: -------------------------------------------------------------------------------- 1 | import { Auth } from 'genesis' 2 | import store from 'genesis/infra/store' 3 | import { promise } from 'genesis/support/utils' 4 | 5 | /** 6 | * @param {string} token 7 | * @param {boolean} remember 8 | * @param {Function} success 9 | * @returns {Promise} 10 | */ 11 | export const registerToken = (token, remember, success = () => ({})) => { 12 | return store.dispatch('setAuthRemember', remember).then(store.dispatch('setAuthToken', token).then(success)) 13 | } 14 | 15 | /** 16 | * @param {Object} user 17 | * @param {Function} success 18 | * @returns {Promise} 19 | */ 20 | export const registerUser = (user, success = () => ({})) => { 21 | const configure = Auth.get('user') 22 | return store.dispatch('setAuthUser', configure(user)).then(success) 23 | } 24 | 25 | /** 26 | * @param {Function} success 27 | * @returns {Promise} 28 | */ 29 | export const unRegister = (success) => { 30 | return promise((resolve, reject) => { 31 | const solver = () => { 32 | success() 33 | resolve() 34 | } 35 | store 36 | .dispatch('setAuthUser', undefined) 37 | .then(store.dispatch('setAuthToken', undefined).then(solver).catch(reject)) 38 | .catch(reject) 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /modules/auth/store/index.js: -------------------------------------------------------------------------------- 1 | import { APP_USER, APP_TOKEN, APP_REMEMBER } from 'genesis/support/index' 2 | import { set, get } from 'genesis/infra/storage' 3 | import { setToken } from 'genesis/infra/services/http/index' 4 | 5 | export const CHANGE_USER = 'setAuthUser' 6 | 7 | export const CHANGE_TOKEN = 'setAuthToken' 8 | 9 | export const CHANGE_REMEMBER = 'setAuthRemember' 10 | 11 | const state = { 12 | remember: get(APP_REMEMBER), 13 | user: undefined, 14 | token: undefined 15 | } 16 | 17 | const getters = { 18 | getAuthRemember: (state) => state.remember, 19 | getAuthUser: (state) => state.user, 20 | getAuthToken: (state) => state.token 21 | } 22 | 23 | const actions = { 24 | setAuthRemember: (store, remember) => { 25 | store.commit(CHANGE_REMEMBER, remember) 26 | set(APP_REMEMBER, remember, true) 27 | }, 28 | setAuthUser: (store, user) => { 29 | store.commit(CHANGE_USER, user) 30 | set(APP_USER, user, store.getters.getAuthRemember) 31 | }, 32 | setAuthToken: (store, token) => { 33 | store.commit(CHANGE_TOKEN, token) 34 | set(APP_TOKEN, token, store.getters.getAuthRemember) 35 | if (token) { 36 | setToken(token) 37 | } 38 | } 39 | } 40 | 41 | const mutations = { 42 | [CHANGE_REMEMBER] (state, remember) { 43 | state.remember = remember 44 | }, 45 | [CHANGE_USER] (state, user) { 46 | state.user = user 47 | }, 48 | [CHANGE_TOKEN] (state, token) { 49 | state.token = token 50 | } 51 | } 52 | 53 | export default { 54 | state, 55 | getters, 56 | actions, 57 | mutations 58 | } 59 | -------------------------------------------------------------------------------- /modules/dashboard/helper/button.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} id 3 | * @param {int} permission 4 | * @param {string} label 5 | * @param {Function} handler 6 | * @param {string} icon 7 | * @param {string} tooltip 8 | * @param {string} color 9 | * @returns {Object} 10 | */ 11 | export default (id, permission, label, handler, icon = '', tooltip = '', color = 'white') => { 12 | const base = { 13 | id, permission, label, handler, icon, tooltip, color 14 | } 15 | // const scopes = ['index', 'create', 'edit', 'view'] 16 | // const positions = ['top', 'bottom', 'middle', 'floating'] 17 | 18 | return { 19 | /** 20 | * @param {Object} options 21 | * @returns {Object} 22 | */ 23 | $options (options) { 24 | Object.keys(options).forEach(key => (base[key] = options[key])) 25 | return this 26 | }, 27 | /** 28 | * @param {Function} [validate] 29 | * @returns {Object} 30 | */ 31 | $validate (validate = null) { 32 | base.validate = validate || ((record, schemas, $component) => !$component.status) 33 | return this 34 | }, 35 | /** 36 | * @param {Array} scopes 37 | * @param {Array} positions 38 | * @returns {Object} 39 | */ 40 | $middle (scopes = ['index'], positions = ['middle']) { 41 | return Object.assign({}, base, {scopes, positions}) 42 | }, 43 | /** 44 | * @param {Array} scopes 45 | * @param {Array} positions 46 | * @returns {Object} 47 | */ 48 | $grid (scopes = ['index'], positions = ['top', 'bottom']) { 49 | return Object.assign({}, base, {scopes, positions}) 50 | }, 51 | /** 52 | * @param {Array} scopes 53 | * @param {Array} positions 54 | * @returns {Object} 55 | */ 56 | $form (scopes = ['create', 'view', 'edit'], positions = ['top', 'bottom']) { 57 | return Object.assign({}, base, {scopes, positions}) 58 | }, 59 | /** 60 | * @param {Array} scopes 61 | * @param {Array} positions 62 | * @param {Object} options 63 | * @returns {Object} 64 | */ 65 | $render (scopes = [], positions = [], options = {}) { 66 | return Object.assign({}, base, {scopes, positions}, options) 67 | }, 68 | /** 69 | * @param {Array} positions 70 | * @param {Object} options 71 | * @returns {Object} 72 | */ 73 | $all (positions = [], options = {}) { 74 | return Object.assign({}, base, {scopes: ['index', 'create', 'view', 'edit'], positions}, options) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /modules/dashboard/helper/group.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} label 3 | * @param {Array} children 4 | */ 5 | export default (label, children) => ({label, children, group: true}) 6 | -------------------------------------------------------------------------------- /modules/dashboard/helper/item.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} id 3 | * @param {Route|string} to 4 | * @param {string} label 5 | * @param {string} icon 6 | * @param {boolean} exact 7 | * @param {string} tooltip 8 | * @param {string} namespace 9 | * @param {int} permission 10 | * @param {string} color 11 | */ 12 | export default (id, to, label, icon, exact = false, tooltip = '', namespace = '', permission = 1, color = '') => { 13 | const item = {to, label, exact, id, tooltip, namespace, permission} 14 | if (icon) { 15 | item.left = {icon, color} 16 | } 17 | return item 18 | } 19 | -------------------------------------------------------------------------------- /modules/dashboard/helper/menu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} id 3 | * @param {string} label 4 | * @param {string} icon 5 | * @param {Array} children 6 | * @param {string} namespace 7 | * @param {string} color 8 | */ 9 | export default (id, label, icon, children, namespace = '', color = '') => ({id, label, icon, children, namespace, color}) 10 | -------------------------------------------------------------------------------- /modules/dashboard/index.js: -------------------------------------------------------------------------------- 1 | export { default as store } from 'genesis/modules/dashboard/store' 2 | 3 | /** 4 | * @param {string} label 5 | * @param {Array} items 6 | */ 7 | export { default as group } from './helper/group' 8 | 9 | /** 10 | * @param {string} id 11 | * @param {string} label 12 | * @param {string} icon 13 | * @param {Array} children 14 | */ 15 | export { default as menu } from './helper/menu' 16 | 17 | /** 18 | * @param {string} id 19 | * @param {Route} to 20 | * @param {string} label 21 | * @param {string} icon 22 | * @param {boolean} exact 23 | * @param {string} tooltip 24 | */ 25 | export { default as item } from './helper/item' 26 | 27 | /** 28 | * @param {string} id 29 | * @param {int} permission 30 | * @param {string} label 31 | * @param {Function} handler 32 | * @param {string} icon 33 | * @param {string} tooltip 34 | * @param {string} color 35 | * @returns {Object} 36 | */ 37 | export { default as button } from './helper/button' 38 | -------------------------------------------------------------------------------- /modules/dashboard/store/index.js: -------------------------------------------------------------------------------- 1 | export const CHANGE_OPTIONS = 'setDashboardOptions' 2 | export const CHANGE_BADGES = 'setDashboardBadges' 3 | 4 | const state = { 5 | options: [], 6 | badges: [] 7 | } 8 | 9 | const getters = { 10 | getDashboardOptions (state) { 11 | return state.options 12 | }, 13 | getDashboardBadges (state) { 14 | return state.badges 15 | } 16 | } 17 | 18 | const actions = { 19 | setDashboardOptions ({commit}, options) { 20 | commit(CHANGE_OPTIONS, options) 21 | }, 22 | setDashboardBadges ({commit}, badges) { 23 | commit(CHANGE_BADGES, badges) 24 | } 25 | } 26 | 27 | const mutations = { 28 | [CHANGE_OPTIONS] (state, options) { 29 | state.options = options 30 | }, 31 | [CHANGE_BADGES] (state, badges) { 32 | state.badges = badges 33 | } 34 | } 35 | 36 | export default { 37 | state, 38 | getters, 39 | actions, 40 | mutations 41 | } 42 | -------------------------------------------------------------------------------- /modules/permission/index.js: -------------------------------------------------------------------------------- 1 | export { default as store } from 'genesis/modules/permission/store' 2 | -------------------------------------------------------------------------------- /modules/permission/services/index.js: -------------------------------------------------------------------------------- 1 | import store from 'genesis/infra/store' 2 | import { promise } from 'genesis/support/utils' 3 | 4 | /** 5 | * @param {Object} user 6 | * @param {Function} success 7 | * @returns {Promise} 8 | */ 9 | export const setPermissions = (permissions, success = () => ({})) => { 10 | return store.dispatch('setAuthPermission', permissions).then(success) 11 | } 12 | 13 | /** 14 | * @param {Function} success 15 | * @returns {Promise} 16 | */ 17 | export const unPermissions = (success) => { 18 | return promise((resolve, reject) => { 19 | const solver = () => { 20 | success() 21 | resolve() 22 | } 23 | store 24 | .dispatch('setAuthPermission', undefined) 25 | .then(store.dispatch('setAppMenu', []).then(solver).catch(reject)) 26 | .catch(reject) 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /modules/permission/store/index.js: -------------------------------------------------------------------------------- 1 | import { APP_PERMISSIONS } from 'genesis/support/index' 2 | import { set } from 'genesis/infra/storage' 3 | 4 | export const SET_PERMISSION = 'setAuthPermission' 5 | 6 | const state = { 7 | permissions: undefined 8 | } 9 | 10 | const getters = { 11 | getAuthPermission: (state) => state.permissions 12 | } 13 | 14 | const actions = { 15 | setAuthPermission: (store, permissions) => { 16 | store.commit(SET_PERMISSION, permissions) 17 | set(APP_PERMISSIONS, permissions, false) 18 | } 19 | } 20 | 21 | const mutations = { 22 | [SET_PERMISSION] (state, permissions) { 23 | state.permissions = permissions 24 | } 25 | } 26 | 27 | export default { 28 | state, 29 | getters, 30 | actions, 31 | mutations 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "genesis", 3 | "version": "0.1.3", 4 | "description": "RAD dashboard tools using Quasar", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "William Correa ", 10 | "license": "MIT" 11 | } -------------------------------------------------------------------------------- /plugin/index.js: -------------------------------------------------------------------------------- 1 | import { Events } from 'quasar-framework' 2 | import { get, set } from 'lodash' 3 | import { uniqid } from 'genesis/support/utils' 4 | import router from 'genesis/infra/router' 5 | 6 | /** 7 | * @param {string} path 8 | * @param {Object} query 9 | * @param {string} changer 10 | */ 11 | const browse = (path, query = {}, changer = '~') => { 12 | let remove = false 13 | if (query === false) { 14 | query = {} 15 | } 16 | const route = router.currentRoute 17 | if (query !== undefined) { 18 | query = Object.assign({}, route.query, query) 19 | } 20 | if (query === undefined) { 21 | query = {} 22 | } 23 | if (path === route.path) { 24 | query[changer] = uniqid() 25 | } 26 | if (remove) { 27 | delete query[changer] 28 | } 29 | window.setTimeout(() => router.push({path, query}), 100) 30 | } 31 | 32 | const on = (name, callback) => Events.$on(name, callback) 33 | const off = (name) => Events.$off(name) 34 | const emit = (name, parameters) => Events.$emit(name, parameters) 35 | 36 | const genesis = { 37 | get, set, browse, on, off, emit 38 | } 39 | 40 | /** 41 | * @param Vue 42 | * @returns {*} 43 | */ 44 | export default Vue => { 45 | Object.defineProperty(Vue.prototype, '$g', { 46 | get () { 47 | return genesis 48 | } 49 | }) 50 | } 51 | -------------------------------------------------------------------------------- /settings/auth.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | import { get } from 'lodash' 3 | import permission from 'genesis/bootstrap/configure/permission' 4 | import user from 'genesis/bootstrap/configure/user' 5 | import token from 'genesis/bootstrap/configure/token' 6 | 7 | /** 8 | * @type {Object} 9 | */ 10 | export default storage({ 11 | permission, user, token 12 | }) 13 | -------------------------------------------------------------------------------- /settings/crud.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | import configure from 'genesis/bootstrap/configure/crud' 3 | import buttons from 'genesis/bootstrap/configure/buttons' 4 | 5 | /** 6 | * @type {Object} 7 | */ 8 | export default storage({ 9 | configure, buttons 10 | }) 11 | -------------------------------------------------------------------------------- /settings/data.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | 3 | import search from 'genesis/bootstrap/configure/search' 4 | import grid from 'genesis/bootstrap/populate/grid' 5 | import form from 'genesis/bootstrap/populate/form' 6 | 7 | /** 8 | * @type {Object} 9 | */ 10 | export default storage({ 11 | form, grid, search 12 | }) 13 | -------------------------------------------------------------------------------- /settings/http.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | import { $body, $meta, $extract, $first, httpError, httpRequest, httpResponse } from 'genesis/bootstrap/configure/http' 3 | 4 | /** 5 | * @type {Object} 6 | */ 7 | export default storage({ 8 | $body, $meta, $extract, $first, httpError, httpRequest, httpResponse 9 | }) 10 | -------------------------------------------------------------------------------- /settings/model.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | import field from 'genesis/bootstrap/configure/field' 3 | import grid from 'genesis/bootstrap/configure/grid' 4 | import form from 'genesis/bootstrap/configure/form' 5 | 6 | /** 7 | * @type {Object} 8 | */ 9 | export default storage({ 10 | field, grid, form 11 | }) 12 | -------------------------------------------------------------------------------- /settings/navigation.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | 3 | import path from 'genesis/bootstrap/configure/path' 4 | 5 | /** 6 | * @type {Object} 7 | */ 8 | export default storage({ 9 | drawer: [], options: [], path 10 | }) 11 | -------------------------------------------------------------------------------- /settings/routes.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | import { beforeEach, afterEach } from 'genesis/infra/router/guard' 3 | 4 | /** 5 | * @type {Object} 6 | */ 7 | export default storage({ 8 | routes: [], 9 | load: (component) => { 10 | if (!component) { 11 | return 12 | } 13 | return () => System.import(`src/${component}.vue`) 14 | }, 15 | beforeEach: beforeEach, 16 | afterEach: beforeEach 17 | }) 18 | -------------------------------------------------------------------------------- /settings/view.js: -------------------------------------------------------------------------------- 1 | import { storage } from 'genesis/support/utils' 2 | 3 | import tooltip from 'genesis/bootstrap/configure/tooltip' 4 | import { locales } from 'genesis/bootstrap/i18n' 5 | 6 | /** 7 | * @type {Object} 8 | */ 9 | export default storage({ 10 | tooltip, locales 11 | }) 12 | -------------------------------------------------------------------------------- /support/date/index.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment' 2 | 3 | /** 4 | * @param {string} format 5 | * @returns {string} 6 | */ 7 | export const today = (format = 'YYYY-MM-DD') => { 8 | return moment(new Date()).startOf('day').format(format) 9 | } 10 | -------------------------------------------------------------------------------- /support/format/index.js: -------------------------------------------------------------------------------- 1 | import moment from 'moment' 2 | import { get } from 'lodash' 3 | import { money, mask } from 'genesis/support/utils' 4 | 5 | /** 6 | * @param value 7 | * @param format 8 | * @return {string} 9 | */ 10 | export const parseDate = (value, format = 'DD/MM/YYYY') => { 11 | if (!String(value).substring(0, 10).match(/^\d{4}-\d{2}-\d{2}$/)) { 12 | return '' 13 | } 14 | const date = moment(value) 15 | if (!date.isValid()) { 16 | return '' 17 | } 18 | return moment(value).format(format) 19 | } 20 | 21 | /** 22 | * @param value 23 | * @return {string} 24 | */ 25 | export const formatDate = (value) => { 26 | return parseDate(value) 27 | } 28 | 29 | /** 30 | * @param value 31 | * @return {string} 32 | */ 33 | export const formatDateTime = (value) => { 34 | return parseDate(value, 'DD/MM/YYYY HH:mm') 35 | } 36 | 37 | /** 38 | * @param value 39 | * @return {string} 40 | */ 41 | export const formatBoolean = (value) => { 42 | let icon = 'check_box_outline_blank' 43 | if (value) { 44 | icon = 'check_box' 45 | } 46 | return '' + icon + '' 47 | } 48 | 49 | /** 50 | * @param value 51 | * @return {string} 52 | */ 53 | export const formatMoney = (value) => { 54 | return '' + money(value) + '' 55 | } 56 | 57 | /** 58 | * @param value 59 | * @return {string} 60 | */ 61 | export const formatPhone = (value) => { 62 | let pattern = '(##) ####-####' 63 | if (length > 13) { 64 | pattern = '(##) #-####-####' 65 | } 66 | return mask(pattern, value) 67 | } 68 | 69 | /** 70 | * @param options 71 | * @returns {Function} 72 | */ 73 | export const formatOptions = (options) => { 74 | return (value) => { 75 | if (Array.isArray(options)) { 76 | const option = options.find(option => String(option.value) === String(value)) 77 | return get(option, 'label', '') 78 | } 79 | return value 80 | } 81 | } 82 | 83 | /** 84 | * @param {string} query 85 | * @param {int} split 86 | * @returns {Function} 87 | */ 88 | export const formatHighLight = (query, split = 0) => { 89 | return (value) => { 90 | if (query) { 91 | let string = String(value) 92 | if (split && string.length > split) { 93 | string = generateEllipsis(string, string.toLowerCase().indexOf(query.toLowerCase())) 94 | } 95 | return stripAccent(string).replace(new RegExp(query, 'ig'), function (match) { 96 | return `${match}` 97 | }) 98 | } 99 | return value 100 | } 101 | } 102 | 103 | /** 104 | * @param {string} string 105 | * @param {int} start 106 | * @returns {string} 107 | */ 108 | const generateEllipsis = (string, start) => { 109 | if (start > 5) { 110 | start = start - 5 111 | } 112 | string = string.substring(start) 113 | if (start > 5) { 114 | string = '... ' + string 115 | } 116 | return string 117 | } 118 | 119 | /** 120 | * @param string 121 | * @returns {string} 122 | */ 123 | const stripAccent = (string) => { 124 | const specials = [ 125 | {regex: /[\xC0-\xC6]/g, char: 'A'}, 126 | {regex: /[\xE0-\xE6]/g, char: 'a'}, 127 | {regex: /[\xC8-\xCB]/g, char: 'E'}, 128 | {regex: /[\xE8-\xEB]/g, char: 'e'}, 129 | {regex: /[\xCC-\xCF]/g, char: 'I'}, 130 | {regex: /[\xEC-\xEF]/g, char: 'i'}, 131 | {regex: /[\xD2-\xD6]/g, char: 'O'}, 132 | {regex: /[\xF2-\xF6]/g, char: 'o'}, 133 | {regex: /[\xD9-\xDC]/g, char: 'U'}, 134 | {regex: /[\xF9-\xFC]/g, char: 'u'}, 135 | {regex: /[\xD1]/g, char: 'N'}, 136 | {regex: /[\xF1]/g, char: 'n'} 137 | ] 138 | const reduce = (accumulate, item) => { 139 | return accumulate.replace(item.regex, item.char) 140 | } 141 | return specials.reduce(reduce, string) 142 | } 143 | -------------------------------------------------------------------------------- /support/i18n/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueI18n from 'vue-i18n' 3 | 4 | Vue.use(VueI18n) 5 | 6 | /** 7 | * @param {string} locale 8 | * @param {Object} messages 9 | * @returns {VueI18n} 10 | */ 11 | export default (locale, messages) => { 12 | return new VueI18n({ 13 | locale, messages 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /support/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Environment variables 3 | */ 4 | const env = process.env 5 | 6 | export const strict = env.NODE_ENV !== 'production' 7 | 8 | export const APP_NAME = env.APP.NAME 9 | 10 | export const APP_USER = env.APP.USER 11 | 12 | export const APP_PERMISSIONS = env.APP.PERMISSIONS 13 | 14 | export const APP_TOKEN = env.APP.TOKEN 15 | 16 | export const APP_REMEMBER = env.APP.REMEMBER 17 | 18 | export const APP_DEV = env.DEV 19 | 20 | /** 21 | * Basic routes 22 | */ 23 | const routes = env.ROUTES 24 | 25 | export const PATH_LOGIN = routes.LOGIN 26 | 27 | export const PATH_NO_ACCESS = routes.NO_ACCESS 28 | 29 | export const PATH_HOME = routes.HOME 30 | 31 | /** 32 | * API settings 33 | */ 34 | const api = env.API 35 | 36 | export const URL_API = api.PROTOCOL + '://' + api.DOMAIN + (api.PORT ? ':' + api.PORT : '') + api.PATH 37 | 38 | export const URL_IMAGE_MANAGER = URL_API + '/image/manager' 39 | 40 | export const URL_IMAGE_UPLOAD = URL_API + '/image/upload' 41 | 42 | export const URL_FILE_UPLOAD = URL_API + '/file/upload' 43 | -------------------------------------------------------------------------------- /support/message/index.js: -------------------------------------------------------------------------------- 1 | import { Dialog, Loading, Toast } from 'quasar-framework' 2 | 3 | /** 4 | * @param {String} title 5 | * @param {String} message 6 | * @param {Array} [actions] 7 | */ 8 | export const alert = (title, message, actions) => { 9 | const buttons = [ 10 | 'Ok' 11 | ] 12 | 13 | Dialog.create({ 14 | title: title, 15 | message: message, 16 | buttons: actions || buttons 17 | }) 18 | } 19 | 20 | /** 21 | * @param {String} title 22 | * @param {String} message 23 | * @param {Function} ok 24 | * @param {Function} cancel 25 | */ 26 | export const confirm = (title, message, ok, cancel = null) => { 27 | const buttons = [ 28 | { 29 | label: 'Cancelar', 30 | handler () { 31 | if (cancel) { 32 | cancel() 33 | } 34 | } 35 | }, 36 | { 37 | label: 'Ok', 38 | handler: ok 39 | } 40 | ] 41 | 42 | Dialog.create({ 43 | title: title, 44 | message: message, 45 | buttons: buttons 46 | }) 47 | } 48 | 49 | /** 50 | * @param {Boolean} status 51 | * @param {String} message 52 | * @param {Number} delay 53 | */ 54 | export const loading = (status = true, delay = 0, message = '') => { 55 | if (status) { 56 | return Loading.show({ 57 | message, 58 | delay 59 | }) 60 | } 61 | return Loading.hide() 62 | } 63 | 64 | /** 65 | * @param {String} html 66 | * @param {String} icon 67 | * @param {Number} timeout 68 | * @param {String} color 69 | * @param {String} bgColor 70 | */ 71 | export const toast = (html, icon = 'done', timeout = 6000, color = '#ffffff', bgColor = 'rgba(50, 50, 50, 0.95)') => { 72 | Toast.create({ 73 | html, icon, timeout, color, bgColor 74 | }) 75 | } 76 | 77 | /** 78 | * @param {String} type 79 | * @param {String} html 80 | */ 81 | export const toastType = (type, html) => { 82 | return Toast.create[type](html) 83 | } 84 | 85 | /** 86 | * @param {String} html 87 | */ 88 | export const toastPositive = (html) => { 89 | return toastType('positive', html) 90 | } 91 | 92 | /** 93 | * @param {String} html 94 | */ 95 | export const toastNegative = (html) => { 96 | return toastType('negative', html) 97 | } 98 | 99 | /** 100 | * @param {String} html 101 | */ 102 | export const toastInfo = (html) => { 103 | return toastType('info', html) 104 | } 105 | 106 | /** 107 | * @param {String} html 108 | */ 109 | export const toastWarning = (html) => { 110 | return toastType('warning', html) 111 | } 112 | 113 | /** 114 | * @param {String} html 115 | * @param {Object} button 116 | * @param {String} icon 117 | * @param {Number} timeout 118 | * @param {String} color 119 | * @param {String} bgColor 120 | */ 121 | export const toastWithButton = (html, button, icon = 'warning', timeout = 6000, color = '#ffffff', bgColor = '#515151') => { 122 | Toast.create({ 123 | html, button, icon, timeout, color, bgColor 124 | }) 125 | } 126 | 127 | /** 128 | * @param {String} html 129 | * @param {Function} handler 130 | * @param {String} icon 131 | * @param {Number} timeout 132 | * @param {String} color 133 | * @param {String} bgColor 134 | */ 135 | export const undo = (html, handler, icon = 'warning', timeout = 6000, color = '#ffffff', bgColor = '#515151') => { 136 | const button = { 137 | label: 'Desfazer', 138 | handler: handler, 139 | color: color 140 | } 141 | return toastWithButton(html, button, icon, timeout, color, bgColor) 142 | } 143 | 144 | /** 145 | * @param {String} html 146 | * @param {Function} handler 147 | * @param {String} icon 148 | * @param {Number} timeout 149 | * @param {String} color 150 | * @param {String} bgColor 151 | */ 152 | export const repeat = (html, handler, icon = 'error', timeout = 6000, color = '#ffffff', bgColor = '#515151') => { 153 | const button = { 154 | label: 'Tentar Novamente', 155 | handler: handler, 156 | color: color 157 | } 158 | return toastWithButton(html, button, icon, timeout, color, bgColor) 159 | } 160 | -------------------------------------------------------------------------------- /support/model/index.js: -------------------------------------------------------------------------------- 1 | import { Model } from 'genesis' 2 | import item from 'genesis/modules/dashboard/helper/item' 3 | import { uniqid } from 'genesis/support/utils' 4 | 5 | /** 6 | * @type {Function} 7 | * 8 | * @param field 9 | * @param label 10 | * @param component 11 | * @param scopes 12 | * @returns {object} 13 | */ 14 | export const field = (field, label, component = 'text', scopes = []) => { 15 | /** 16 | * @type {Function} 17 | * @private 18 | */ 19 | const _field = Model.get('field') 20 | return _field(field, label, component, scopes) 21 | } 22 | 23 | /** 24 | * @type {Function} 25 | * 26 | * @param {Resource} service 27 | * @param {string} path 28 | * @param {string} id 29 | * @param {Array} schemas 30 | * @param {Array|Function} filters 31 | * @param {Array|Function} actions 32 | * @param {Object} options 33 | * @returns {Object} 34 | */ 35 | export const grid = (service, path, id, schemas, filters, actions = null, options = {}) => { 36 | /** 37 | * @type {Function} 38 | * @private 39 | */ 40 | const _grid = Model.get('grid') 41 | return _grid(service, path, id, schemas, filters, actions, options) 42 | } 43 | 44 | /** 45 | * @type {Function} 46 | * 47 | * @param {Resource} service 48 | * @param {string} scope 49 | * @param {string} path 50 | * @param {string} id 51 | * @param {Array} schemas 52 | * @param {Array} actions 53 | * @param {Object} options 54 | * @returns {Object} 55 | */ 56 | export const form = (service, scope, path, id, schemas, actions = null, options = {}) => { 57 | const _form = Model.get('form') 58 | return _form(service, scope, path, id, schemas, actions, options) 59 | } 60 | 61 | /** 62 | * @type {Function} 63 | * 64 | * @param {Array} fields 65 | * @param {string} scope 66 | * @returns {Array} 67 | */ 68 | export const filter = (fields, scope) => { 69 | return fields.filter(field => scope ? field.scopes && field.scopes.includes(scope) : true) 70 | } 71 | 72 | /** 73 | * @type {Function} 74 | * 75 | * @param {string} icon 76 | * @param {string} label 77 | * @param {string} title 78 | * @param {string} tooltip 79 | * @param {string} namespace 80 | * @param {int} permission 81 | * @returns {Object} 82 | */ 83 | export const meta = (icon, label, title, tooltip = '', namespace = '', permission = 1) => { 84 | return {icon, label, title, tooltip, namespace, permission} 85 | } 86 | 87 | /** 88 | * @type {Function} 89 | * 90 | * @param {string} icon 91 | * @param {string} label 92 | * @param {string} path 93 | * @param {Boolean} exact 94 | * @param {string} tooltip 95 | * @param {string} id 96 | * @param {string} namespace 97 | * @param {int} permission 98 | * @param {string} color 99 | * @returns {Function} 100 | */ 101 | export const menu = (icon, label, path, exact = false, tooltip = '', id = '', namespace = '', permission = 1, color = '') => { 102 | const identification = id || uniqid() 103 | return (to) => item(identification, to(path), label, icon, exact, tooltip, namespace, permission, color) 104 | } 105 | 106 | /** 107 | * @type {Function} 108 | * 109 | * @param {string} uri 110 | * @param {Object} reference 111 | * @param {string} referenced 112 | */ 113 | export const pivot = (uri, reference, referenced) => ({uri, reference, referenced}) 114 | 115 | /** 116 | * @type {Function} 117 | * 118 | * @param {string} icon 119 | * @param {string} label 120 | * @param {string} path 121 | * @param {string} tooltip 122 | * @param {string} description 123 | * @param {int} width 124 | * @returns {Function} 125 | */ 126 | export const card = (icon, label, path, tooltip, description, width) => { 127 | return (to) => ({icon, label, to: to(path), tooltip, description, width}) 128 | } 129 | 130 | /** 131 | * @type {Object} 132 | */ 133 | export default { 134 | grid, form, field, filter, meta, menu, pivot, card 135 | } 136 | -------------------------------------------------------------------------------- /support/transform/index.js: -------------------------------------------------------------------------------- 1 | import { get, set } from 'lodash' 2 | 3 | /** 4 | * @param schema 5 | * @param data 6 | * @returns {*} 7 | */ 8 | export const getDotNotation = (schema, data) => { 9 | const reduce = (accumulate, key) => { 10 | accumulate[schema[key].field] = get(data, schema[key].field, undefined) 11 | return accumulate 12 | } 13 | return Object.assign({}, data, Object.keys(schema).reduce(reduce, {})) 14 | } 15 | 16 | /** 17 | * @param data 18 | * @returns {*} 19 | */ 20 | export const setDotNotation = (data) => { 21 | const reduce = (accumulate, key) => { 22 | set(accumulate, key, data[key]) 23 | return accumulate 24 | } 25 | return Object.keys(data).reduce(reduce, {}) 26 | } 27 | -------------------------------------------------------------------------------- /themes/fonts/index.styl: -------------------------------------------------------------------------------- 1 | @font-face 2 | font-family play 3 | src url(play/Play-Regular.ttf) 4 | 5 | @font-face 6 | font-family play-bold 7 | src url(play/Play-Bold.ttf) 8 | -------------------------------------------------------------------------------- /themes/fonts/play/Play-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phpzm/genesis/0aa6f82d2193a7c2a52065fc0788866fe9f2957f/themes/fonts/play/Play-Bold.ttf -------------------------------------------------------------------------------- /themes/fonts/play/Play-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phpzm/genesis/0aa6f82d2193a7c2a52065fc0788866fe9f2957f/themes/fonts/play/Play-Regular.ttf -------------------------------------------------------------------------------- /themes/index.styl: -------------------------------------------------------------------------------- 1 | @import 'modules/button.styl' 2 | 3 | @import 'modules/calendar.styl' 4 | 5 | @import 'modules/data-table.styl' 6 | 7 | @import 'modules/field.styl' 8 | 9 | @import 'modules/form.styl' 10 | 11 | @import 'modules/grid.styl' 12 | 13 | @import 'modules/info.styl' 14 | 15 | @import 'modules/layout.styl' 16 | 17 | @import 'modules/link.styl' 18 | 19 | @import 'modules/popover.styl' 20 | 21 | @import 'modules/reset.styl' 22 | 23 | @import 'modules/scrollbar.styl' 24 | 25 | @import 'modules/tabs.styl' 26 | 27 | @import 'modules/util.styl' 28 | -------------------------------------------------------------------------------- /themes/ios.styl: -------------------------------------------------------------------------------- 1 | 2 | @import 'index.styl' 3 | -------------------------------------------------------------------------------- /themes/mat.styl: -------------------------------------------------------------------------------- 1 | 2 | @import 'index.styl' 3 | -------------------------------------------------------------------------------- /themes/modules/button.styl: -------------------------------------------------------------------------------- 1 | 2 | .q-btn 3 | &.bg-white .q-btn-inner 4 | color #515151 5 | i 6 | color #515151 7 | &.btn-x-small 8 | padding 1px 9 | width 24px 10 | min-width 24px 11 | height 24px 12 | min-height 24px 13 | i.q-icon 14 | font-size 14px 15 | .white 16 | background white 17 | 18 | .primary 19 | background $primary 20 | color white 21 | .secondary 22 | background $secondary 23 | color white 24 | .tertiary 25 | background $tertiary 26 | color white 27 | 28 | .neutral 29 | background $neutral 30 | color #515151 31 | .positive 32 | background $positive 33 | color white 34 | .negative 35 | background $negative 36 | color white 37 | .info 38 | background $info 39 | color white 40 | .warning 41 | background $warning 42 | color #515151 43 | 44 | .q-btn.rotate > .q-btn-inner > i, .rotate .q-btn > .q-btn-inner > i 45 | transition transform .6s 46 | transform rotate(0deg) 47 | .q-btn.rotate:hover > .q-btn-inner > i, .rotate .q-btn:hover > .q-btn-inner > i 48 | transform rotate(360deg) 49 | -------------------------------------------------------------------------------- /themes/modules/calendar.styl: -------------------------------------------------------------------------------- 1 | 2 | #calendar-widget { 3 | margin-bottom: 30px; 4 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); 5 | } 6 | 7 | #fc-actions { 8 | position: absolute; 9 | bottom: 10px; 10 | right: 12px; 11 | } 12 | 13 | .fc { 14 | background-color: #fff; 15 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); 16 | margin-bottom: 30px; 17 | } 18 | 19 | .fc td, 20 | .fc th { 21 | border-color: #f0f0f0; 22 | } 23 | 24 | .fc th { 25 | font-weight: 400; 26 | } 27 | 28 | .fc table { 29 | background: transparent; 30 | } 31 | 32 | .fc table tr > td:first-child { 33 | border-left-width: 0; 34 | } 35 | 36 | #calendar-widget .fc-toolbar { 37 | background: #009688; 38 | } 39 | 40 | #calendar-widget .fc-day-header { 41 | color: #fff; 42 | background: #007d71; 43 | padding: 5px 0; 44 | border-width: 0; 45 | } 46 | 47 | #calendar-widget .fc-day-number { 48 | text-align: center; 49 | color: #ADADAD; 50 | padding: 5px 0; 51 | } 52 | 53 | #calendar-widget .fc-day-grid-event { 54 | margin: 1px 3px 1px; 55 | } 56 | 57 | #calendar-widget .ui-widget-header th, 58 | #calendar-widget .ui-widget-header { 59 | border-width: 0; 60 | } 61 | 62 | #calendar 63 | margin 16px 0 0 0 64 | border 1px solid $primary 65 | border-radius 2px 66 | 67 | #calendar .fc-toolbar { 68 | height: 115px; 69 | background $primary 70 | color $primary-color 71 | background-repeat: no-repeat; 72 | -webkit-background-size: cover; 73 | -moz-background-size: cover; 74 | -o-background-size: cover; 75 | background-size: cover; 76 | background-position: center; 77 | background-position: inherit; 78 | } 79 | 80 | #calendar .fc-toolbar:before { 81 | content: ""; 82 | height: 50px; 83 | width: 100%; 84 | background: rgba(0, 0, 0, 0.36); 85 | position: absolute; 86 | bottom: 0; 87 | left: 0; 88 | } 89 | 90 | #calendar .fc-toolbar .fc-center { 91 | // margin-top: 238px; 92 | position: relative; 93 | } 94 | 95 | @media screen and (max-width: 991px) { 96 | #calendar .fc-toolbar { 97 | height: 200px; 98 | } 99 | 100 | #calendar .fc-toolbar .fc-center { 101 | margin-top: 138px; 102 | } 103 | } 104 | 105 | #calendar .fc-day-header { 106 | color: #ADADAD; 107 | text-align: left; 108 | font-size: 14px; 109 | border-bottom-width: 0; 110 | border-right-color: #eee; 111 | padding: 10px 12px; 112 | } 113 | 114 | #calendar .fc-day-number { 115 | padding-left: 10px !important; 116 | color: #CCC; 117 | text-align: left !important; 118 | } 119 | 120 | @media screen and (min-width: 991px) { 121 | #calendar .fc-day-number { 122 | font-size: 25px; 123 | letter-spacing: -2px; 124 | } 125 | } 126 | 127 | #calendar .fc-day-grid-event { 128 | margin: 1px 9px 0; 129 | } 130 | 131 | .fc-today { 132 | color: #ffc107; 133 | } 134 | 135 | .fc-toolbar { 136 | margin-bottom: 0; 137 | padding: 20px 7px 19px; 138 | position: relative; 139 | } 140 | 141 | .fc-toolbar h2 { 142 | margin-top: 7px; 143 | font-size: 20px; 144 | font-weight: 400; 145 | text-transform: uppercase; 146 | color: $primary-color; 147 | } 148 | 149 | .fc-toolbar .ui-button { 150 | border: 0; 151 | background: 0 0; 152 | padding: 0; 153 | outline: none !important; 154 | text-align: center; 155 | width: 30px; 156 | height: 30px; 157 | border-radius: 50%; 158 | margin-top: 2px; 159 | color: #fff; 160 | } 161 | 162 | .fc-toolbar .ui-button:hover { 163 | background: #fff; 164 | color: #009688; 165 | } 166 | 167 | .fc-toolbar .ui-button > span { 168 | position: relative; 169 | font-family: 'Material-Design-Iconic-Font'; 170 | font-size: 20px; 171 | line-height: 100%; 172 | width: 30px; 173 | display: block; 174 | margin-top: 2px; 175 | } 176 | 177 | .fc-toolbar .ui-button > span:before { 178 | position: relative; 179 | z-index: 1; 180 | } 181 | 182 | .fc-toolbar .ui-button > span.ui-icon-circle-triangle-w:before { 183 | content: "\f2fa"; 184 | } 185 | 186 | .fc-toolbar .ui-button > span.ui-icon-circle-triangle-e:before { 187 | content: "\f2fb"; 188 | } 189 | 190 | .fc-event { 191 | padding: 0; 192 | font-size: 11px; 193 | border-radius: 0; 194 | border: 0; 195 | } 196 | 197 | .fc-event .fc-title { 198 | padding: 2px 8px; 199 | display: block; 200 | } 201 | 202 | .fc-event .fc-time { 203 | float: left; 204 | background: rgba(0, 0, 0, 0.2); 205 | padding: 2px 6px; 206 | margin: 0 0 0 -1px; 207 | } 208 | 209 | .fc-view, 210 | .fc-view > table { 211 | border: 0; 212 | overflow: hidden; 213 | } 214 | 215 | .fc-view > table > tbody > tr > .ui-widget-content { 216 | border-top: 0; 217 | } 218 | 219 | div.fc-row { 220 | margin-right: 0 !important; 221 | border: 0 !important; 222 | } 223 | 224 | .fc-today { 225 | color: #ffc107 !important; 226 | } 227 | -------------------------------------------------------------------------------- /themes/modules/data-table.styl: -------------------------------------------------------------------------------- 1 | 2 | .app-data-table 3 | font-family Roboto 4 | .app-data-table-options 5 | position absolute 6 | margin-top -20px 7 | .q-btn-round.q-btn-standard 8 | height 40px 9 | width 40px 10 | q-icon, .q-spinner 11 | font-size 20px 12 | .q-data-table 13 | border 1px #ddd solid 14 | display flex 15 | .q-data-table-toolbar.upper-toolbar 16 | display none 17 | .q-data-table-container 18 | overflow auto 19 | .q-data-table-head 20 | overflow visible 21 | min-width 500px 22 | .q-data-table-body 23 | overflow visible 24 | min-width 500px 25 | 26 | .production 27 | .app-data-table-options 28 | .q-btn-round.q-btn-standard 29 | .q-fab-icon.q-icon, .q-fab-active-icon.q-icon 30 | margin 6px 0 0 0 31 | -------------------------------------------------------------------------------- /themes/modules/field.styl: -------------------------------------------------------------------------------- 1 | .input 2 | background-attachment scroll 3 | background-clip border-box 4 | background-color rgb(255, 255, 255) 5 | background-image none 6 | background-origin padding-box 7 | background-position-x 0 8 | background-position-y 0 9 | background-size auto 10 | border-bottom-color rgb(232, 229, 229) 11 | border-bottom-left-radius 1px 12 | border-bottom-right-radius 1px 13 | border-bottom-style solid 14 | border-bottom-width 0 15 | border-image-outset 0 16 | border-image-repeat stretch 17 | border-image-slice 100% 18 | border-image-source none 19 | border-image-width 1 20 | border-left-color rgb(232, 229, 229) 21 | border-left-style solid 22 | border-left-width 0 23 | border-right-color rgb(232, 229, 229) 24 | border-right-style solid 25 | border-right-width 0 26 | border-top-color rgb(232, 229, 229) 27 | border-top-left-radius 1px 28 | border-top-right-radius 1px 29 | border-top-style solid 30 | border-top-width 1px 31 | box-shadow rgba(0, 0, 0, 0.12) 0px 1px 3px 0px, rgba(0, 0, 0, 0.24) 0px 1px 2px 0px 32 | box-sizing border-box 33 | color rgb(0, 0, 0) 34 | cursor auto 35 | display inline-block 36 | font-family Roboto 37 | font-size 14.4px 38 | font-stretch normal 39 | font-style normal 40 | font-variant-caps normal 41 | font-variant-ligatures normal 42 | font-variant-numeric normal 43 | font-weight normal 44 | height 37px 45 | letter-spacing normal 46 | line-height 20.16px 47 | margin-bottom 2px 48 | margin-left 0 49 | margin-right 0 50 | margin-top 0 51 | max-width 100% 52 | outline-color rgb(0, 0, 0) 53 | outline-style none 54 | outline-width 0px 55 | overflow-x visible 56 | overflow-y visible 57 | padding-bottom 8px 58 | padding-left 8px 59 | padding-right 8px 60 | padding-top 8px 61 | text-align start 62 | text-indent 0 63 | text-rendering auto 64 | text-shadow none 65 | text-size-adjust 100% 66 | text-transform none 67 | transition-delay 0s 68 | transition-duration 0.5s 69 | transition-property all 70 | transition-timing-function ease 71 | user-select text 72 | vertical-align top 73 | width 956px 74 | word-spacing 0 75 | writing-mode horizontal-tb 76 | -webkit-appearance none 77 | -webkit-box-direction normal 78 | -webkit-font-smoothing antialiased 79 | -webkit-rtl-ordering logical 80 | -webkit-tap-highlight-color rgba(0, 0, 0, 0) 81 | -webkit-border-image none 82 | 83 | .input-bar 84 | position: relative 85 | display: block 86 | margin-bottom -1px 87 | .input-bar:before, .input-bar:after 88 | content: " " 89 | background: $primary 90 | height: 2px 91 | width: 0 92 | position: absolute 93 | bottom: 2px 94 | transition: all 95 | transition-duration: 300ms 96 | .input-bar:before 97 | left: 50% 98 | .input-bar:after 99 | right: 50% 100 | .input:focus ~ .input-bar:before, .input:focus ~ .input-bar:after 101 | width: 50% 102 | .input.has-error ~ .input-bar:before, .input.has-error ~ .input-bar:after 103 | background: $negative 104 | 105 | .q-if.input:hover:before 106 | color transparent 107 | -------------------------------------------------------------------------------- /themes/modules/form.styl: -------------------------------------------------------------------------------- 1 | 2 | .form 3 | display flex 4 | min-width 260px 5 | width 100% 6 | flex-wrap wrap 7 | flex-flow row wrap 8 | .field 9 | padding 5px 10 | width 100% 11 | .primary-label 12 | display block 13 | text-align left 14 | font-size 14px 15 | padding 2px 0 4px 0 16 | color #474747 17 | margin 0 0 5px 0 18 | 19 | @media (max-width 768px) 20 | .form 21 | .field 22 | for width in (1..20) 23 | &.xs-{width * 5} 24 | max-width width * 5% 25 | min-width width * 5% 26 | 27 | @media (min-width 768px) 28 | .form 29 | .field 30 | for width in (1..20) 31 | &.has-{width * 5} 32 | max-width width * 5% 33 | 34 | .field-label 35 | // font-weight bold 36 | margin 0 0 3px 0 37 | color darken($primary, 20%) 38 | 39 | .q-btn-round.q-btn-small.field-clear 40 | width 28px 41 | height 28px 42 | -------------------------------------------------------------------------------- /themes/modules/grid.styl: -------------------------------------------------------------------------------- 1 | 2 | .grid 3 | display flex 4 | min-width 260px 5 | width 100% 6 | .cell 7 | padding 5px 8 | width 100% 9 | display block 10 | .primary-label 11 | display block 12 | text-align left 13 | font-size 14px 14 | padding 2px 0 4px 0 15 | color #474747 16 | margin 0 0 5px 0 17 | 18 | .grid-avatar-image, .grid-simple-image 19 | width 50x 20 | .grid-avatar-image 21 | height 50px 22 | border-radius 50% 23 | 24 | @media (max-width 768px) 25 | .grid 26 | flex-wrap wrap 27 | flex-flow row wrap 28 | .cell 29 | max-width 100% !important 30 | min-width 100% !important 31 | width 100% !important 32 | 33 | .grid 34 | .cell 35 | for width in (1..20) 36 | &.xs-{width * 5} 37 | max-width width * 5% 38 | min-width width * 5% 39 | 40 | @media (min-width 768px) 41 | .grid 42 | .cell 43 | for width in (1..20) 44 | &.has-{width * 5} 45 | max-width width * 5% 46 | min-width width * 5% 47 | -------------------------------------------------------------------------------- /themes/modules/info.styl: -------------------------------------------------------------------------------- 1 | 2 | .info 3 | color white 4 | &.orange 5 | background orange 6 | color #ffffff 7 | &.pulse 8 | animation pulse-orange 3s infinite 9 | &.red 10 | background #ec2121 11 | color #ffffff 12 | &.pulse 13 | animation pulse-red 3s infinite 14 | &.yellow 15 | background #fbf501 16 | color #000000 17 | &.pulse 18 | animation pulse-yellow 3s infinite 19 | &.green 20 | background #4eb32f 21 | color #ffffff 22 | &.pulse 23 | animation pulse-green 3s infinite 24 | &.blue 25 | background #438cb3 26 | color #ffffff 27 | &.pulse 28 | animation pulse-blue 3s infinite 29 | &.black 30 | background #000000 31 | color #ffffff 32 | &.pulse 33 | animation pulse-black 3s infinite 34 | &.grey 35 | background #8a8a8a 36 | color #ffffff 37 | &.pulse 38 | animation pulse-grey 3s infinite 39 | 40 | @keyframes pulse-orange { 41 | 0% { 42 | box-shadow 0 0 0 0 rgba(220, 217, 31, 0.7) 43 | } 44 | 70% { 45 | box-shadow 0 0 0 30px rgba(220, 217, 31, 0.05) 46 | } 47 | 100% { 48 | box-shadow 0 0 0 0 rgba(220, 217, 31, 0) 49 | } 50 | } 51 | 52 | @keyframes pulse-red { 53 | 0% { 54 | box-shadow 0 0 0 0 rgba(139, 0, 0, 0.7) 55 | } 56 | 70% { 57 | box-shadow 0 0 0 30px rgba(139, 0, 0, 0.05) 58 | } 59 | 100% { 60 | box-shadow 0 0 0 0 rgba(139, 0, 0, 0) 61 | } 62 | } 63 | 64 | @keyframes pulse-yellow { 65 | 0% { 66 | box-shadow 0 0 0 0 rgba(220, 217, 31, 0.7) 67 | } 68 | 70% { 69 | box-shadow 0 0 0 30px rgba(220, 217, 31, 0.05) 70 | } 71 | 100% { 72 | box-shadow 0 0 0 0 rgba(220, 217, 31, 0) 73 | } 74 | } 75 | 76 | @keyframes pulse-green { 77 | 0% { 78 | box-shadow 0 0 0 0 rgba(78, 179, 47, 0.7) 79 | } 80 | 70% { 81 | box-shadow 0 0 0 30px rgba(78, 179, 47, 0.05) 82 | } 83 | 100% { 84 | box-shadow 0 0 0 0 rgba(78, 179, 47, 0) 85 | } 86 | } 87 | 88 | @keyframes pulse-blue { 89 | 0% { 90 | box-shadow 0 0 0 0 rgba(67, 140, 179, 0.7) 91 | } 92 | 70% { 93 | box-shadow 0 0 0 30px rgba(67, 140, 179, 0.05) 94 | } 95 | 100% { 96 | box-shadow 0 0 0 0 rgba(67, 140, 179, 0) 97 | } 98 | } 99 | 100 | @keyframes pulse-black { 101 | 0% { 102 | box-shadow 0 0 0 0 rgba(0, 0, 0, 0.7) 103 | } 104 | 70% { 105 | box-shadow 0 0 0 30px rgba(0, 0, 0, 0.05) 106 | } 107 | 100% { 108 | box-shadow 0 0 0 0 rgba(0, 0, 0, 0) 109 | } 110 | } 111 | 112 | @keyframes pulse-grey { 113 | 0% { 114 | box-shadow 0 0 0 0 rgba(138, 138, 138, 0.7) 115 | } 116 | 70% { 117 | box-shadow 0 0 0 30px rgba(138, 138, 138, 0.05) 118 | } 119 | 100% { 120 | box-shadow 0 0 0 0 rgba(138, 138, 138, 0) 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /themes/modules/layout.styl: -------------------------------------------------------------------------------- 1 | .layout-aside.fixed 2 | // z-index 3000 3 | 4 | .layout-page 5 | overflow-x hidden 6 | background #eaeaea 7 | 8 | .desktop 9 | .q-loading 10 | z-index 3001 11 | -------------------------------------------------------------------------------- /themes/modules/link.styl: -------------------------------------------------------------------------------- 1 | a 2 | color darken($primary, 20%) 3 | 4 | .q-item.active, .q-item.router-link-active, .q-item:focus 5 | // background lighten($primary, 80%) 6 | background rgba(0,0,0,0.16) 7 | -------------------------------------------------------------------------------- /themes/modules/popover.styl: -------------------------------------------------------------------------------- 1 | 2 | .q-popover-menu 3 | box-shadow 0 5px 9px -7px rgba(0,0,0,0.2), 0 3px 17px 3px rgba(0,0,0,0.14), 0 9px 20px 8px rgba(0,0,0,0.12) 4 | border-radius 3px 5 | min-width 250px 6 | -------------------------------------------------------------------------------- /themes/modules/reset.styl: -------------------------------------------------------------------------------- 1 | 2 | body 3 | font-family play 4 | background #eaeaea 5 | 6 | hr 7 | margin 20px 0 8 | border 0 9 | height 1px 10 | background-image linear-gradient(to right, rgba(0, 0, 0, 0.04), #dddddd, #dddddd, rgba(0, 0, 0, 0.04)) 11 | 12 | hr.light 13 | margin 10px 0 14 | -------------------------------------------------------------------------------- /themes/modules/scrollbar.styl: -------------------------------------------------------------------------------- 1 | 2 | ::-webkit-scrollbar 3 | width 6px 4 | height 6px 5 | ::-webkit-scrollbar-track 6 | border-radius 4px 7 | box-shadow inset 0 0 6px rgba(0, 0, 0, .1) 8 | ::-webkit-scrollbar-thumb 9 | border-radius 4px 10 | background rgba(0, 0, 0, .4) 11 | ::-webkit-scrollbar-thumb:window-inactive 12 | background rgba(0, 0, 0, .3) 13 | 14 | .q-scrollarea-thumb 15 | width 4px 16 | border-radius 4px 17 | -------------------------------------------------------------------------------- /themes/modules/tabs.styl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phpzm/genesis/0aa6f82d2193a7c2a52065fc0788866fe9f2957f/themes/modules/tabs.styl -------------------------------------------------------------------------------- /themes/modules/util.styl: -------------------------------------------------------------------------------- 1 | 2 | .clear-fix 3 | clear both 4 | 5 | @media all and (max-width 480px) 6 | .hidden-tiny 7 | display none 8 | @media all and (max-width 768px) 9 | .hidden-small 10 | display none 11 | @media all and (max-width 1024px) 12 | .hidden-medium 13 | display none 14 | @media all and (max-width 1200px) 15 | .hidden-big 16 | display none 17 | 18 | @media all and (min-width 480px) 19 | .show-tiny 20 | display none 21 | @media all and (min-width 768px) 22 | .show-small 23 | display none 24 | @media all and (min-width 1024px) 25 | .show-medium 26 | display none 27 | @media all and (min-width 1200px) 28 | .show-big 29 | display none 30 | -------------------------------------------------------------------------------- /themes/variables.styl: -------------------------------------------------------------------------------- 1 | 2 | $light = #f4f4f4 3 | $dark = #333 4 | $faded = #777 5 | 6 | $primary-color = #777001 7 | 8 | $text-color = lighten(black, 17%) 9 | $background-color = white 10 | 11 | $link-color = lighten($primary, 25%) 12 | $link-color-active = $primary 13 | 14 | $layout-aside-left-width = 280px 15 | 16 | $app-layout-drawer = #ffffff 17 | 18 | $app-layout-drawer-logo = #f7f7f7 19 | $app-layout-drawer-logo-border-bottom = 1px #dddddd solid 20 | 21 | $app-layout-breadcrumb-wrapper = #ffffff 22 | 23 | $app-drawer-menu-color = #313131 24 | $app-drawer-menu-icon = #777777 25 | 26 | $app-drawer-menu-active = #b5b5b5 27 | $app-drawer-menu-active-color = #000 28 | $app-drawer-menu-active-icon = #565656 29 | 30 | $app-drawer-menu-item-open = #fafafa 31 | $app-drawer-menu-item-shadow = inset 1px 1px 3px 1px rgba(0, 0, 0, 0.16), inset 1px -1px 3px 1px rgba(0, 0, 0, 0.1) 32 | $app-drawer-menu-item-border = #b5b5b5 33 | 34 | $field-button-background = $primary 35 | $field-button-color = $primary-color 36 | --------------------------------------------------------------------------------