removed typescript
23
.babelrc
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-syntax-dynamic-import"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"test": {
|
|
||||||
"plugins": [
|
|
||||||
"dynamic-import-node"
|
|
||||||
],
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"@babel/preset-env",
|
|
||||||
{
|
|
||||||
"modules": "commonjs",
|
|
||||||
"targets": {
|
|
||||||
"node": "current"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
|
@ -1,9 +0,0 @@
|
||||||
/dist
|
|
||||||
/src-bex/www
|
|
||||||
/src-capacitor
|
|
||||||
/src-cordova
|
|
||||||
/.quasar
|
|
||||||
/node_modules
|
|
||||||
.eslintrc.js
|
|
||||||
babel.config.js
|
|
||||||
/src-ssr
|
|
103
.eslintrc.js
|
@ -1,103 +0,0 @@
|
||||||
const { resolve } = require('path');
|
|
||||||
module.exports = {
|
|
||||||
// https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
|
|
||||||
// This option interrupts the configuration hierarchy at this file
|
|
||||||
// Remove this if you have an higher level ESLint config file (it usually happens into a monorepos)
|
|
||||||
root: true,
|
|
||||||
|
|
||||||
// https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
|
|
||||||
// Must use parserOptions instead of "parser" to allow vue-eslint-parser to keep working
|
|
||||||
// `parser: 'vue-eslint-parser'` is already included with any 'plugin:vue/**' config and should be omitted
|
|
||||||
parserOptions: {
|
|
||||||
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#configuration
|
|
||||||
// https://github.com/TypeStrong/fork-ts-checker-webpack-plugin#eslint
|
|
||||||
// Needed to make the parser take into account 'vue' files
|
|
||||||
extraFileExtensions: ['.vue'],
|
|
||||||
parser: '@typescript-eslint/parser',
|
|
||||||
project: resolve(__dirname, './tsconfig.json'),
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
|
|
||||||
sourceType: 'module', // Allows for the use of imports
|
|
||||||
},
|
|
||||||
|
|
||||||
env: {
|
|
||||||
browser: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Rules order is important, please avoid shuffling them
|
|
||||||
extends: [
|
|
||||||
// Base ESLint recommended rules
|
|
||||||
// 'eslint:recommended',
|
|
||||||
|
|
||||||
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage
|
|
||||||
// ESLint typescript rules
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
// consider disabling this class of rules if linting takes too long
|
|
||||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
|
||||||
|
|
||||||
// Uncomment any of the lines below to choose desired strictness,
|
|
||||||
// but leave only one uncommented!
|
|
||||||
// See https://eslint.vuejs.org/rules/#available-rules
|
|
||||||
// 'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention)
|
|
||||||
'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
|
|
||||||
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
|
|
||||||
|
|
||||||
// https://github.com/prettier/eslint-config-prettier#installation
|
|
||||||
// usage with Prettier, provided by 'eslint-config-prettier'.
|
|
||||||
'prettier',
|
|
||||||
],
|
|
||||||
|
|
||||||
plugins: [
|
|
||||||
// required to apply rules which need type information
|
|
||||||
'@typescript-eslint',
|
|
||||||
|
|
||||||
// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files
|
|
||||||
// required to lint *.vue files
|
|
||||||
'vue',
|
|
||||||
|
|
||||||
// https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674
|
|
||||||
// Prettier has not been included as plugin to avoid performance impact
|
|
||||||
// add it as an extension for your IDE
|
|
||||||
],
|
|
||||||
|
|
||||||
globals: {
|
|
||||||
ga: 'readonly', // Google Analytics
|
|
||||||
cordova: 'readonly',
|
|
||||||
__statics: 'readonly',
|
|
||||||
__QUASAR_SSR__: 'readonly',
|
|
||||||
__QUASAR_SSR_SERVER__: 'readonly',
|
|
||||||
__QUASAR_SSR_CLIENT__: 'readonly',
|
|
||||||
__QUASAR_SSR_PWA__: 'readonly',
|
|
||||||
process: 'readonly',
|
|
||||||
Capacitor: 'readonly',
|
|
||||||
chrome: 'readonly',
|
|
||||||
},
|
|
||||||
|
|
||||||
// add your custom rules here
|
|
||||||
rules: {
|
|
||||||
'prefer-promise-reject-errors': 'off',
|
|
||||||
|
|
||||||
// TypeScript
|
|
||||||
quotes: ['warn', 'single', { avoidEscape: true }],
|
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
||||||
'@typescript-eslint/unbound-method': 'off',
|
|
||||||
|
|
||||||
'@typescript-eslint/no-unsafe-assignment': 'off',
|
|
||||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
|
||||||
'@typescript-eslint/no-unsafe-call': 'off',
|
|
||||||
'@typescript-eslint/no-floating-promises': 'off',
|
|
||||||
|
|
||||||
// allow debugger during development only
|
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
|
||||||
},
|
|
||||||
overrides: [
|
|
||||||
{
|
|
||||||
files: ['**/*.spec.{js,ts}'],
|
|
||||||
extends: [
|
|
||||||
// Add Cypress-specific lint rules, globals and Cypress plugin
|
|
||||||
// See https://github.com/cypress-io/eslint-plugin-cypress#rules
|
|
||||||
'plugin:cypress/recommended',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
|
@ -1,34 +0,0 @@
|
||||||
.DS_Store
|
|
||||||
.thumbs.db
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
# Quasar core related directories
|
|
||||||
.quasar
|
|
||||||
/dist
|
|
||||||
|
|
||||||
# Cordova related directories and files
|
|
||||||
/src-cordova/node_modules
|
|
||||||
/src-cordova/platforms
|
|
||||||
/src-cordova/plugins
|
|
||||||
/src-cordova/www
|
|
||||||
|
|
||||||
# Capacitor related directories and files
|
|
||||||
/src-capacitor/www
|
|
||||||
/src-capacitor/node_modules
|
|
||||||
|
|
||||||
# BEX related directories and files
|
|
||||||
/src-bex/www
|
|
||||||
/src-bex/js/core
|
|
||||||
|
|
||||||
# Log files
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode
|
|
||||||
.idea
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
|
@ -1,8 +0,0 @@
|
||||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
plugins: [
|
|
||||||
// to edit target browsers: use "browserslist" field in package.json
|
|
||||||
require('autoprefixer'),
|
|
||||||
],
|
|
||||||
};
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"singleQuote": true,
|
|
||||||
"printWidth": 120,
|
|
||||||
"tabWidth": 4,
|
|
||||||
"semi": true,
|
|
||||||
"endOfLine": "auto"
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"editor.bracketPairColorization.enabled": true,
|
|
||||||
"editor.guides.bracketPairs": true,
|
|
||||||
"editor.formatOnSave": true,
|
|
||||||
"editor.codeActionsOnSave": ["source.fixAll.eslint"],
|
|
||||||
"eslint.validate": ["javascript", "javascriptreact", "typescript", "vue"]
|
|
||||||
}
|
|
37
README.md
|
@ -1,37 +0,0 @@
|
||||||
# Salix (salix-front)
|
|
||||||
|
|
||||||
Salix front-end
|
|
||||||
|
|
||||||
## Install the dependencies
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### Start the app in development mode (hot-code reloading, error reporting, etc.)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
quasar dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### Lint the files
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run lint
|
|
||||||
```
|
|
||||||
|
|
||||||
### Format the files
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run format
|
|
||||||
```
|
|
||||||
|
|
||||||
### Build the app for production
|
|
||||||
|
|
||||||
```bash
|
|
||||||
quasar build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Customize the configuration
|
|
||||||
|
|
||||||
See [Configuring quasar.conf.js](https://quasar.dev/quasar-cli/quasar-conf-js).
|
|
|
@ -1,18 +0,0 @@
|
||||||
/* eslint-env node */
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const fs = require('fs-extra');
|
|
||||||
let extend = undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The .babelrc file has been created to assist Jest for transpiling.
|
|
||||||
* You should keep your application's babel rules in this file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (fs.existsSync('./.babelrc')) {
|
|
||||||
extend = './.babelrc';
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
presets: ['@quasar/babel-preset-app'],
|
|
||||||
extends: extend,
|
|
||||||
};
|
|
15
cypress.json
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"baseUrl": "http://localhost:8080/",
|
|
||||||
"fixturesFolder": "test/cypress/fixtures",
|
|
||||||
"integrationFolder": "test/cypress/integration",
|
|
||||||
"pluginsFile": "test/cypress/plugins/index.js",
|
|
||||||
"screenshotsFolder": "test/cypress/screenshots",
|
|
||||||
"supportFile": "test/cypress/support/index.js",
|
|
||||||
"videosFolder": "test/cypress/videos",
|
|
||||||
"video": true,
|
|
||||||
"component": {
|
|
||||||
"componentFolder": "src",
|
|
||||||
"testFiles": "**/*.spec.js",
|
|
||||||
"supportFile": "test/cypress/support/unit.js"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
const esModules = ['quasar', 'quasar/lang', 'lodash-es'].join('|');
|
|
||||||
|
|
||||||
/* eslint-env node */
|
|
||||||
module.exports = {
|
|
||||||
globals: {
|
|
||||||
__DEV__: true,
|
|
||||||
// TODO: Remove if resolved natively
|
|
||||||
// See https://github.com/vuejs/vue-jest/issues/175
|
|
||||||
'vue-jest': {
|
|
||||||
pug: { doctype: 'html' },
|
|
||||||
},
|
|
||||||
// Remove if using `const enums`
|
|
||||||
// See https://huafu.github.io/ts-jest/user/config/isolatedModules#example
|
|
||||||
'ts-jest': {
|
|
||||||
isolatedModules: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// noStackTrace: true,
|
|
||||||
// bail: true,
|
|
||||||
// cache: false,
|
|
||||||
// verbose: true,
|
|
||||||
// watch: true,
|
|
||||||
collectCoverage: false,
|
|
||||||
coverageDirectory: '<rootDir>/test/jest/coverage',
|
|
||||||
collectCoverageFrom: [
|
|
||||||
'<rootDir>/src/**/*.vue',
|
|
||||||
'<rootDir>/src/**/*.js',
|
|
||||||
'<rootDir>/src/**/*.ts',
|
|
||||||
'<rootDir>/src/**/*.jsx',
|
|
||||||
'<rootDir>/src/**/*.tsx',
|
|
||||||
],
|
|
||||||
coveragePathIgnorePatterns: ['/node_modules/', '.d.ts$'],
|
|
||||||
coverageThreshold: {
|
|
||||||
global: {
|
|
||||||
// branches: 50,
|
|
||||||
// functions: 50,
|
|
||||||
// lines: 50,
|
|
||||||
// statements: 50
|
|
||||||
},
|
|
||||||
},
|
|
||||||
testMatch: [
|
|
||||||
// Matches tests in any subfolder of 'src' or into 'test/jest/__tests__'
|
|
||||||
// Matches all files with extension 'js', 'jsx', 'ts' and 'tsx'
|
|
||||||
// '<rootDir>/test/jest/__tests__/**/*.(spec|test).+(ts|js)?(x)',
|
|
||||||
'<rootDir>/src/**/__tests__/*.(spec|test).+(ts|js)?(x)',
|
|
||||||
],
|
|
||||||
// Extension-less imports of components are resolved to .ts files by TS,
|
|
||||||
// grating correct type-checking in test files.
|
|
||||||
// Being 'vue' the first moduleFileExtension option, the very same imports
|
|
||||||
// will be resolved to .vue files by Jest, if both .vue and .ts files are
|
|
||||||
// in the same folder.
|
|
||||||
// This guarantee a great dev experience both for testing and type-checking.
|
|
||||||
// See https://github.com/vuejs/vue-jest/issues/188#issuecomment-620750728
|
|
||||||
moduleFileExtensions: ['vue', 'js', 'jsx', 'json', 'ts', 'tsx'],
|
|
||||||
moduleNameMapper: {
|
|
||||||
'^quasar$': 'quasar/dist/quasar.esm.prod.js',
|
|
||||||
'^~/(.*)$': '<rootDir>/$1',
|
|
||||||
'^src/(.*)$': '<rootDir>/src/$1',
|
|
||||||
'^app/(.*)$': '<rootDir>/$1',
|
|
||||||
'^components/(.*)$': '<rootDir>/src/components/$1',
|
|
||||||
'^composables/(.*)$': '<rootDir>/src/composables/$1',
|
|
||||||
'^layouts/(.*)$': '<rootDir>/src/layouts/$1',
|
|
||||||
'^pages/(.*)$': '<rootDir>/src/pages/$1',
|
|
||||||
'^assets/(.*)$': '<rootDir>/src/assets/$1',
|
|
||||||
'^boot/(.*)$': '<rootDir>/src/boot/$1',
|
|
||||||
'.*css$': '@quasar/quasar-app-extension-testing-unit-jest/stub.css',
|
|
||||||
},
|
|
||||||
transform: {
|
|
||||||
// See https://jestjs.io/docs/en/configuration.html#transformignorepatterns-array-string
|
|
||||||
[`^(${esModules}).+\\.js$`]: 'babel-jest',
|
|
||||||
'^.+\\.(ts|js|html)$': 'ts-jest',
|
|
||||||
// vue-jest uses find-babel-file, which searches by this order:
|
|
||||||
// (async) .babelrc, .babelrc.js, package.json, babel.config.js
|
|
||||||
// (sync) .babelrc, .babelrc.js, babel.config.js, package.json
|
|
||||||
// https://github.com/tleunen/find-babel-config/issues/33
|
|
||||||
'.*\\.vue$': 'vue-jest',
|
|
||||||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
|
|
||||||
},
|
|
||||||
transformIgnorePatterns: [`node_modules/(?!(${esModules}))`],
|
|
||||||
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
|
|
||||||
};
|
|
60
package.json
|
@ -1,60 +0,0 @@
|
||||||
{
|
|
||||||
"name": "salix-front",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"description": "Salix front-end",
|
|
||||||
"productName": "Salix",
|
|
||||||
"author": "Salix",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"lint": "eslint --ext .js,.ts,.vue ./",
|
|
||||||
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
|
|
||||||
"test": "echo \"See package.json => scripts for available tests.\" && exit 0",
|
|
||||||
"test:unit:coverage": "jest --coverage",
|
|
||||||
"test:unit": "jest --watchAll",
|
|
||||||
"test:e2e": "cross-env E2E_TEST=true start-test \"quasar dev\" http-get://localhost:8080 \"cypress open --config-file cypress.json\"",
|
|
||||||
"test:e2e:ci": "cross-env E2E_TEST=true start-test \"quasar dev\" http-get://localhost:8080 \"cypress run\"",
|
|
||||||
"serve:test:coverage": "quasar serve test/jest/coverage/lcov-report/ --port 8788",
|
|
||||||
"concurrently:dev:jest": "concurrently \"quasar dev\" \"jest --watch\""
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@quasar/extras": "^1.0.0",
|
|
||||||
"axios": "^0.21.1",
|
|
||||||
"core-js": "^3.6.5",
|
|
||||||
"quasar": "^2.0.0",
|
|
||||||
"vue": "^3.0.0",
|
|
||||||
"vue-i18n": "^9.0.0",
|
|
||||||
"vue-router": "^4.0.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/eslint-parser": "^7.13.14",
|
|
||||||
"@intlify/vue-i18n-loader": "^4.1.0",
|
|
||||||
"@quasar/app": "^3.0.0",
|
|
||||||
"@quasar/quasar-app-extension-testing-e2e-cypress": "^4.0.1",
|
|
||||||
"@quasar/quasar-app-extension-testing-unit-jest": "^3.0.0-alpha.8",
|
|
||||||
"@types/node": "^12.20.21",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.10.0",
|
|
||||||
"@typescript-eslint/parser": "^5.10.0",
|
|
||||||
"eslint": "^7.14.0",
|
|
||||||
"eslint-config-prettier": "^8.1.0",
|
|
||||||
"eslint-plugin-jest": "^25.2.2",
|
|
||||||
"eslint-plugin-vue": "^7.0.0",
|
|
||||||
"prettier": "^2.5.1",
|
|
||||||
"eslint-plugin-cypress": "^2.11.3"
|
|
||||||
},
|
|
||||||
"browserslist": [
|
|
||||||
"last 10 Chrome versions",
|
|
||||||
"last 10 Firefox versions",
|
|
||||||
"last 4 Edge versions",
|
|
||||||
"last 7 Safari versions",
|
|
||||||
"last 8 Android versions",
|
|
||||||
"last 8 ChromeAndroid versions",
|
|
||||||
"last 8 FirefoxAndroid versions",
|
|
||||||
"last 10 iOS versions",
|
|
||||||
"last 5 Opera versions"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 12.22.1",
|
|
||||||
"npm": ">= 6.13.4",
|
|
||||||
"yarn": ">= 1.21.1"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 859 B |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 9.4 KiB |
233
quasar.conf.js
|
@ -1,233 +0,0 @@
|
||||||
/*
|
|
||||||
* This file runs in a Node context (it's NOT transpiled by Babel), so use only
|
|
||||||
* the ES6 features that are supported by your Node version. https://node.green/
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Configuration for your app
|
|
||||||
// https://quasar.dev/quasar-cli/quasar-conf-js
|
|
||||||
|
|
||||||
/* eslint-env node */
|
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
const { configure } = require('quasar/wrappers');
|
|
||||||
|
|
||||||
module.exports = configure(function (ctx) {
|
|
||||||
return {
|
|
||||||
// https://quasar.dev/quasar-cli/supporting-ts
|
|
||||||
supportTS: {
|
|
||||||
tsCheckerConfig: {
|
|
||||||
eslint: {
|
|
||||||
enabled: true,
|
|
||||||
files: './src/**/*.{ts,tsx,js,jsx,vue}',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// https://quasar.dev/quasar-cli/prefetch-feature
|
|
||||||
// preFetch: true,
|
|
||||||
|
|
||||||
// app boot file (/src/boot)
|
|
||||||
// --> boot files are part of "main.js"
|
|
||||||
// https://quasar.dev/quasar-cli/boot-files
|
|
||||||
boot: ['i18n', 'axios'],
|
|
||||||
|
|
||||||
// https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css
|
|
||||||
css: ['app.scss'],
|
|
||||||
|
|
||||||
// https://github.com/quasarframework/quasar/tree/dev/extras
|
|
||||||
extras: [
|
|
||||||
// 'ionicons-v4',
|
|
||||||
// 'mdi-v5',
|
|
||||||
// 'fontawesome-v5',
|
|
||||||
// 'eva-icons',
|
|
||||||
// 'themify',
|
|
||||||
// 'line-awesome',
|
|
||||||
// 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both!
|
|
||||||
|
|
||||||
'roboto-font', // optional, you are not bound to it
|
|
||||||
'material-icons', // optional, you are not bound to it
|
|
||||||
],
|
|
||||||
|
|
||||||
// Full list of options: https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build
|
|
||||||
build: {
|
|
||||||
vueRouterMode: 'hash', // available values: 'hash', 'history'
|
|
||||||
|
|
||||||
// transpile: false,
|
|
||||||
// publicPath: '/',
|
|
||||||
|
|
||||||
// Add dependencies for transpiling with Babel (Array of string/regex)
|
|
||||||
// (from node_modules, which are by default not transpiled).
|
|
||||||
// Applies only if "transpile" is set to true.
|
|
||||||
// transpileDependencies: [],
|
|
||||||
|
|
||||||
// rtl: true, // https://quasar.dev/options/rtl-support
|
|
||||||
// preloadChunks: true,
|
|
||||||
// showProgress: false,
|
|
||||||
// gzip: true,
|
|
||||||
// analyze: true,
|
|
||||||
|
|
||||||
// Options below are automatically set depending on the env, set them if you want to override
|
|
||||||
// extractCSS: false,
|
|
||||||
|
|
||||||
// https://quasar.dev/quasar-cli/handling-webpack
|
|
||||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
|
||||||
chainWebpack(/* chain */) {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// Full list of options: https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-devServer
|
|
||||||
devServer: {
|
|
||||||
server: {
|
|
||||||
type: 'http',
|
|
||||||
},
|
|
||||||
port: 8080,
|
|
||||||
open: true, // opens browser window automatically
|
|
||||||
proxy: {
|
|
||||||
'/api': {
|
|
||||||
target: 'http://localhost:3000',
|
|
||||||
logLevel: 'debug',
|
|
||||||
changeOrigin: true,
|
|
||||||
secure: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-framework
|
|
||||||
framework: {
|
|
||||||
config: {},
|
|
||||||
|
|
||||||
// iconSet: 'material-icons', // Quasar icon set
|
|
||||||
// lang: 'en-US', // Quasar language pack
|
|
||||||
|
|
||||||
// For special cases outside of where the auto-import strategy can have an impact
|
|
||||||
// (like functional components as one of the examples),
|
|
||||||
// you can manually specify Quasar components/directives to be available everywhere:
|
|
||||||
//
|
|
||||||
// components: [],
|
|
||||||
// directives: [],
|
|
||||||
|
|
||||||
// Quasar plugins
|
|
||||||
plugins: ['Notify'],
|
|
||||||
},
|
|
||||||
|
|
||||||
// animations: 'all', // --- includes all animations
|
|
||||||
// https://quasar.dev/options/animations
|
|
||||||
animations: [],
|
|
||||||
|
|
||||||
// https://quasar.dev/quasar-cli/developing-ssr/configuring-ssr
|
|
||||||
ssr: {
|
|
||||||
pwa: false,
|
|
||||||
|
|
||||||
// manualStoreHydration: true,
|
|
||||||
// manualPostHydrationTrigger: true,
|
|
||||||
|
|
||||||
prodPort: 3000, // The default port that the production server should use
|
|
||||||
// (gets superseded if process.env.PORT is specified at runtime)
|
|
||||||
|
|
||||||
maxAge: 1000 * 60 * 60 * 24 * 30,
|
|
||||||
// Tell browser when a file from the server should expire from cache (in ms)
|
|
||||||
|
|
||||||
chainWebpackWebserver(/* chain */) {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
|
|
||||||
middlewares: [
|
|
||||||
ctx.prod ? 'compression' : '',
|
|
||||||
'render', // keep this as last one
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
// https://quasar.dev/quasar-cli/developing-pwa/configuring-pwa
|
|
||||||
pwa: {
|
|
||||||
workboxPluginMode: 'GenerateSW', // 'GenerateSW' or 'InjectManifest'
|
|
||||||
workboxOptions: {}, // only for GenerateSW
|
|
||||||
|
|
||||||
// for the custom service worker ONLY (/src-pwa/custom-service-worker.[js|ts])
|
|
||||||
// if using workbox in InjectManifest mode
|
|
||||||
chainWebpackCustomSW(/* chain */) {
|
|
||||||
//
|
|
||||||
},
|
|
||||||
|
|
||||||
manifest: {
|
|
||||||
name: 'Salix',
|
|
||||||
short_name: 'Salix',
|
|
||||||
description: 'Salix front-end',
|
|
||||||
display: 'standalone',
|
|
||||||
orientation: 'portrait',
|
|
||||||
background_color: '#ffffff',
|
|
||||||
theme_color: '#027be3',
|
|
||||||
icons: [
|
|
||||||
{
|
|
||||||
src: 'icons/icon-128x128.png',
|
|
||||||
sizes: '128x128',
|
|
||||||
type: 'image/png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'icons/icon-192x192.png',
|
|
||||||
sizes: '192x192',
|
|
||||||
type: 'image/png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'icons/icon-256x256.png',
|
|
||||||
sizes: '256x256',
|
|
||||||
type: 'image/png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'icons/icon-384x384.png',
|
|
||||||
sizes: '384x384',
|
|
||||||
type: 'image/png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'icons/icon-512x512.png',
|
|
||||||
sizes: '512x512',
|
|
||||||
type: 'image/png',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// Full list of options: https://quasar.dev/quasar-cli/developing-cordova-apps/configuring-cordova
|
|
||||||
cordova: {
|
|
||||||
// noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing
|
|
||||||
},
|
|
||||||
|
|
||||||
// Full list of options: https://quasar.dev/quasar-cli/developing-capacitor-apps/configuring-capacitor
|
|
||||||
capacitor: {
|
|
||||||
hideSplashscreen: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Full list of options: https://quasar.dev/quasar-cli/developing-electron-apps/configuring-electron
|
|
||||||
electron: {
|
|
||||||
bundler: 'packager', // 'packager' or 'builder'
|
|
||||||
|
|
||||||
packager: {
|
|
||||||
// https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
|
|
||||||
// OS X / Mac App Store
|
|
||||||
// appBundleId: '',
|
|
||||||
// appCategoryType: '',
|
|
||||||
// osxSign: '',
|
|
||||||
// protocol: 'myapp://path',
|
|
||||||
// Windows only
|
|
||||||
// win32metadata: { ... }
|
|
||||||
},
|
|
||||||
|
|
||||||
builder: {
|
|
||||||
// https://www.electron.build/configuration/configuration
|
|
||||||
|
|
||||||
appId: 'salix-front',
|
|
||||||
},
|
|
||||||
|
|
||||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
|
||||||
chainWebpack(/* chain */) {
|
|
||||||
// do something with the Electron main process Webpack cfg
|
|
||||||
// extendWebpackMain also available besides this chainWebpackMain
|
|
||||||
},
|
|
||||||
|
|
||||||
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
|
|
||||||
chainWebpackPreload(/* chain */) {
|
|
||||||
// do something with the Electron main process Webpack cfg
|
|
||||||
// extendWebpackPreload also available besides this chainWebpackPreload
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"@quasar/testing-unit-jest": {
|
|
||||||
"babel": "babelrc",
|
|
||||||
"options": ["scripts", "typescript"]
|
|
||||||
},
|
|
||||||
"@quasar/testing-e2e-cypress": {
|
|
||||||
"options": ["scripts"]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"unit-jest": {
|
|
||||||
"runnerCommand": "jest --ci"
|
|
||||||
},
|
|
||||||
"e2e-cypress": {
|
|
||||||
"runnerCommand": "cross-env E2E_TEST=true start-test \"quasar dev\" http-get://localhost:8080 \"cypress run\""
|
|
||||||
},
|
|
||||||
"unit-cypress": {
|
|
||||||
"runnerCommand": "cypress run-ct"
|
|
||||||
}
|
|
||||||
}
|
|
24
src/App.vue
|
@ -1,24 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { useQuasar } from 'quasar';
|
|
||||||
const quasar = useQuasar();
|
|
||||||
|
|
||||||
quasar.iconMapFn = (iconName) => {
|
|
||||||
if (iconName.startsWith('vn:')) {
|
|
||||||
const name = iconName.substring(3);
|
|
||||||
|
|
||||||
return {
|
|
||||||
cls: `icon-${name}`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<router-view />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.body--light {
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,70 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1"
|
|
||||||
id="Capa_1" inkscape:version="0.91 r13725" sodipodi:docname="logo.svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:ns="&ns_sfw;" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 400 168.6"
|
|
||||||
style="enable-background:new 0 0 400 168.6;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#3D3D3F;}
|
|
||||||
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#8EBB27;}
|
|
||||||
.st2{fill:#8EBB27;}
|
|
||||||
.st3{fill:#F19300;}
|
|
||||||
</style>
|
|
||||||
<sodipodi:namedview bordercolor="#666666" borderopacity="1" fit-margin-bottom="0" fit-margin-left="0" fit-margin-right="0" fit-margin-top="0" gridtolerance="10" guidetolerance="10" id="namedview41" inkscape:current-layer="Capa_1" inkscape:cx="200" inkscape:cy="84.28212" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-height="1016" inkscape:window-maximized="1" inkscape:window-width="1920" inkscape:window-x="1920" inkscape:window-y="27" inkscape:zoom="3.09" objecttolerance="10" pagecolor="#ffffff" showgrid="false">
|
|
||||||
</sodipodi:namedview>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M106.1,40L92.3,0h10.9l5.6,20.6l0.5,1.7c0.7,2.5,1.2,4.5,1.6,6.2c0.2-0.8,0.4-1.8,0.7-2.9
|
|
||||||
c0.3-1.1,0.7-2.6,1.2-4.3L118.7,0h10.8l-13.9,40H106.1z"/>
|
|
||||||
<path class="st1" d="M386.1,40h-9.8c0-0.5,0.1-1,0.1-1.5l0.2-1.6c-1.7,1.4-3.5,2.4-5.2,3c-1.7,0.6-3.5,1-5.3,1
|
|
||||||
c-2.8,0-4.9-0.8-6.1-2.3c-1.2-1.6-1.5-3.7-0.7-6.3c0.7-2.4,1.9-4.4,3.6-6c1.7-1.5,4-2.6,6.8-3.2c1.5-0.3,3.5-0.7,5.8-1.1
|
|
||||||
c3.5-0.5,5.4-1.3,5.7-2.4l0.2-0.7c0.2-0.9,0.1-1.5-0.4-2c-0.5-0.4-1.4-0.7-2.7-0.7c-1.4,0-2.6,0.3-3.5,0.8c-1,0.6-1.7,1.4-2.2,2.5
|
|
||||||
h-8.9c1.4-3.3,3.5-5.8,6.2-7.5c2.7-1.6,6.2-2.4,10.5-2.4c2.6,0,4.7,0.3,6.4,1c1.6,0.6,2.8,1.6,3.4,2.9c0.4,0.9,0.6,2,0.6,3.3
|
|
||||||
c-0.1,1.3-0.5,3.3-1.3,6.2l-3.1,11.2c-0.4,1.3-0.5,2.4-0.5,3.2c0,0.8,0.2,1.3,0.7,1.5L386.1,40z M379.4,26.1
|
|
||||||
c-0.9,0.5-2.3,0.9-4.3,1.3c-1,0.2-1.7,0.3-2.2,0.5c-1.3,0.3-2.2,0.7-2.8,1.2c-0.6,0.5-1.1,1.2-1.3,2c-0.3,1.1-0.2,1.9,0.3,2.5
|
|
||||||
c0.5,0.6,1.2,1,2.3,1c1.7,0,3.1-0.5,4.4-1.4c1.3-1,2.2-2.2,2.6-3.7L379.4,26.1z"/>
|
|
||||||
<path class="st1" d="M337.3,40l8.3-29.5h9.3l-1.4,5.2c1.6-2,3.3-3.5,5.1-4.4c1.8-0.9,3.9-1.4,6.3-1.5l-2.7,9.6
|
|
||||||
c-0.4-0.1-0.8-0.1-1.2-0.1c-0.4,0-0.8,0-1.1,0c-1.5,0-2.8,0.2-3.9,0.7c-1.1,0.4-2.1,1.1-2.9,2.1c-0.5,0.6-1,1.5-1.5,2.6
|
|
||||||
c-0.5,1.1-1.1,3-1.8,5.6l-2.8,9.9H337.3z"/>
|
|
||||||
<path class="st1" d="M340.8,10.5L332.5,40h-9.5l1.1-4.1c-1.6,1.6-3.3,2.9-4.9,3.6c-1.7,0.8-3.5,1.2-5.4,1.2
|
|
||||||
c-3.3,0-5.5-0.8-6.7-2.5c-1.2-1.7-1.3-4.2-0.4-7.4l5.7-20.3h9.7L317.6,27c-0.7,2.4-0.8,4.1-0.5,5c0.4,0.9,1.3,1.4,2.8,1.4
|
|
||||||
c1.7,0,3.1-0.6,4.1-1.7c1.1-1.1,2-2.9,2.7-5.5l4.4-15.8H340.8z"/>
|
|
||||||
<path class="st1" d="M290.1,16.3l1.6-5.8h4l2.3-8.3h9.7l-2.3,8.3h5l-1.6,5.8h-5l-3.6,12.8c-0.5,2-0.7,3.3-0.3,3.9
|
|
||||||
c0.3,0.6,1.2,1,2.6,1l0.7,0l0.5,0l-1.7,6.2c-1.1,0.2-2.1,0.3-3.1,0.5c-1,0.1-2,0.2-2.9,0.2c-3.4,0-5.4-0.8-6.2-2.5
|
|
||||||
c-0.8-1.6-0.4-5.1,1.1-10.5l3.2-11.4H290.1z"/>
|
|
||||||
<path class="st1" d="M283.5,40h-9.8c0-0.5,0.1-1,0.1-1.5L274,37c-1.7,1.4-3.5,2.4-5.2,3c-1.7,0.6-3.5,1-5.3,1
|
|
||||||
c-2.8,0-4.9-0.8-6.1-2.3c-1.2-1.6-1.5-3.7-0.7-6.3c0.7-2.4,1.9-4.4,3.6-6c1.7-1.5,4-2.6,6.8-3.2c1.5-0.3,3.5-0.7,5.8-1.1
|
|
||||||
c3.5-0.5,5.4-1.3,5.7-2.4l0.2-0.7c0.2-0.9,0.1-1.5-0.4-2c-0.5-0.4-1.4-0.7-2.7-0.7c-1.4,0-2.6,0.3-3.5,0.8c-1,0.6-1.7,1.4-2.2,2.5
|
|
||||||
H261c1.4-3.3,3.5-5.8,6.2-7.5c2.7-1.6,6.2-2.4,10.5-2.4c2.6,0,4.7,0.3,6.4,1c1.6,0.6,2.8,1.6,3.4,2.9c0.4,0.9,0.6,2,0.6,3.3
|
|
||||||
c-0.1,1.3-0.5,3.3-1.3,6.2l-3.1,11.2c-0.4,1.3-0.5,2.4-0.5,3.2c0,0.8,0.2,1.3,0.7,1.5L283.5,40z M276.7,26.1
|
|
||||||
c-0.9,0.5-2.3,0.9-4.3,1.3c-1,0.2-1.7,0.3-2.2,0.5c-1.3,0.3-2.2,0.7-2.8,1.2c-0.6,0.5-1.1,1.2-1.3,2c-0.3,1.1-0.2,1.9,0.3,2.5
|
|
||||||
c0.5,0.6,1.2,1,2.3,1c1.7,0,3.1-0.5,4.4-1.4c1.3-1,2.2-2.2,2.6-3.7L276.7,26.1z"/>
|
|
||||||
<path class="st0" d="M219.6,0l-11.2,40h-9.7l1.1-3.9c-1.5,1.6-3.1,2.8-4.8,3.6c-1.6,0.8-3.4,1.2-5.3,1.2c-3.7,0-6.3-1.4-7.8-4.3
|
|
||||||
c-1.5-2.9-1.6-6.6-0.3-11.2c1.3-4.7,3.5-8.4,6.7-11.4c3.1-2.9,6.5-4.4,10.1-4.4c1.9,0,3.6,0.4,4.8,1.2c1.3,0.8,2.2,1.9,2.8,3.5
|
|
||||||
L210,0H219.6z M189.8,24.9c-0.7,2.6-0.8,4.7-0.2,6.1c0.6,1.4,1.8,2.1,3.7,2.1c1.8,0,3.4-0.7,4.8-2.1c1.3-1.4,2.4-3.4,3.1-6.1
|
|
||||||
c0.7-2.5,0.7-4.4,0.1-5.8c-0.6-1.4-1.8-2-3.7-2c-1.7,0-3.3,0.7-4.7,2.1C191.5,20.6,190.4,22.5,189.8,24.9z"/>
|
|
||||||
<path class="st0" d="M153.6,40l8.3-29.5h9.3l-1.4,5.2c1.6-2,3.3-3.5,5.1-4.4c1.8-0.9,7.9-1.4,10.3-1.5l-2.7,9.6
|
|
||||||
c-0.4-0.1-0.8-0.1-1.2-0.1c-0.4,0-0.8,0-1.1,0c-1.5,0-6.8,0.2-7.9,0.7c-1.1,0.4-2.1,1.1-2.9,2.1c-0.5,0.6-1,1.5-1.5,2.6
|
|
||||||
c-0.5,1.1-1.1,3-1.8,5.6l-2.8,9.9H153.6z"/>
|
|
||||||
<path class="st0" d="M143.5,30.7h9.3c-1.8,3.2-4.2,5.7-7.2,7.5c-3,1.8-6.4,2.7-10.2,2.7c-4.6,0-7.8-1.4-9.7-4.2
|
|
||||||
c-1.9-2.8-2.2-6.6-0.8-11.4c1.4-4.9,3.8-8.8,7.3-11.6c3.5-2.9,7.5-4.3,12-4.3c4.7,0,8,1.5,9.8,4.3c1.9,2.9,2.1,6.9,0.7,12
|
|
||||||
l-0.3,1.1l-0.2,0.6h-20c-0.6,2.1-0.6,3.7,0,4.8c0.6,1.1,1.8,1.6,3.5,1.6c1.3,0,2.4-0.3,3.4-0.8C142.1,32.6,142.9,31.8,143.5,30.7z
|
|
||||||
M135.4,22.1l11,0c0.5-1.9,0.4-3.4-0.3-4.4c-0.7-1.1-1.8-1.6-3.5-1.6c-1.6,0-3,0.5-4.3,1.6C137.1,18.6,136.1,20.1,135.4,22.1z"/>
|
|
||||||
<path class="st2" d="M241.2,40.4l-8.4-24.6l-8.5,24.6h-9.6l12.6-40h10.8L244,21l0.5,1.7c0.7,2.5,1.2,4.5,1.6,6.2l0.7-2.9
|
|
||||||
c0.3-1.1,0.7-2.6,1.2-4.3l5.9-21.2h10.8l-13.9,40H241.2z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st3" d="M106.1,54.4h4.8l48.9,113.9h-5.9L137,129H79.9l-16.8,39.3H57L106.1,54.4z M135.3,124.2l-26.8-62.7l-26.9,62.7
|
|
||||||
H135.3z"/>
|
|
||||||
<path class="st3" d="M178.1,168.3V54.4h5.6v108.7h69.8v5.1H178.1z"/>
|
|
||||||
<path class="st3" d="M271.1,168.3V54.4h5.6v113.9H271.1z"/>
|
|
||||||
<path class="st3" d="M300.2,54.4l42,53.6l42-53.6h6.4l-45.4,57.7l44.1,56.1H383l-40.7-52l-40.7,52h-6.7l44.1-56.1l-45.4-57.7
|
|
||||||
H300.2z"/>
|
|
||||||
<g>
|
|
||||||
<path class="st3" d="M5.8,168.3L5.3,163l0.2,2.7L5.3,163c0.4,0,10.4-1.1,18.9-11.8c10.5-13.1,14.1-35.2,10.5-63.9
|
|
||||||
C31,57.7,35.4,34.8,47.6,19.1C60.3,3,76.6,0.9,77.3,0.8l0.6,5.3c-0.1,0-11.9,1.6-22.4,12.1c-14,14-19.3,37.7-15.5,68.4
|
|
||||||
c3.8,30.7-0.1,53.6-11.8,68.1C18.3,167.1,6.3,168.2,5.8,168.3z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 6.2 KiB |
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="40mm" height="40mm" viewBox="0 0 40 40" version="1.1" id="svg823" inkscape:version="0.92.4 (5da689c313, 2019-01-14)" sodipodi:docname="logo.svg">
|
|
||||||
<defs id="defs817"/>
|
|
||||||
<sodipodi:namedview id="base" pagecolor="#2f2f2f" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:zoom="5.635625" inkscape:cx="70.551181" inkscape:cy="75.590551" inkscape:document-units="mm" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="1920" inkscape:window-height="1043" inkscape:window-x="1920" inkscape:window-y="0" inkscape:window-maximized="1"/>
|
|
||||||
<metadata id="metadata820">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
|
||||||
<dc:title/>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(0,-257)">
|
|
||||||
<path style="fill:#88bd32;stroke-width:0.83333331" inkscape:connector-curvature="0" id="path4" d="m 27.583333,261.08333 c 0.25,-0.0833 0.5,-0.16666 0.75,-0.16666 L 39,259.5 l -0.166667,6.08333 c -0.166666,5 -3.083333,9.5 -6.666666,10.5 -0.25,0.0833 -0.5,0.16667 -0.75,0.16667 L 20.75,277.66667 l 0.166667,-6.08334 c 0.166666,-5.08333 3.083333,-9.5 6.666666,-10.5 z" class="st0"/>
|
|
||||||
<path style="fill:#88bd32;stroke-width:0.83333331" inkscape:connector-curvature="0" id="path6" d="m 5.9166667,281.91667 c 0.1666667,-0.0833 0.4166667,-0.0833 0.5833334,-0.0833 L 14.25,280.75 14.16667,285.08333 C 14.08334,288.75 11.91667,292 9.3333364,292.75 c -0.25,0.0833 -0.4166667,0.0833 -0.5833334,0.0833 L 1.0000001,293.91667 1.0833334,289.5 c 0.1666667,-3.58333 2.25,-6.91667 4.8333333,-7.58333 z" class="st0"/>
|
|
||||||
<g id="g10" style="fill:#f7931e;fill-opacity:1;stroke:none;stroke-opacity:1" transform="matrix(0.83333333,0,0,0.83333333,8.0000002e-8,257)">
|
|
||||||
<path style="fill:#f7931e;fill-opacity:1;stroke:none;stroke-opacity:1" inkscape:connector-curvature="0" id="path8" d="m 12,48 c -0.4,0 -0.7,-0.3 -0.7,-0.6 0,-0.4 0.2,-0.7 0.6,-0.8 0,0 3,-0.3 5.5,-3.4 3,-3.8 4.1,-10.1 3,-18.4 C 19.3,16.3 20.6,9.7 24.1,5.3 27.8,0.6 32.5,0 32.7,0 c 0.4,0 0.7,0.2 0.8,0.6 0,0.4 -0.2,0.7 -0.6,0.8 0,0 -4.3,0.6 -7.6,4.7 -3.3,4.2 -4.4,10.4 -3.4,18.5 1.1,8.8 0,15.4 -3.4,19.5 -2.8,3.5 -6.2,3.9 -6.5,3.9 0.1,0 0.1,0 0,0 z" class="st1"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.8 KiB |
|
@ -1,48 +0,0 @@
|
||||||
import { boot } from 'quasar/wrappers';
|
|
||||||
import axios, { AxiosInstance } from 'axios';
|
|
||||||
|
|
||||||
import { useSession } from 'src/composables/useSession';
|
|
||||||
const { getToken } = useSession();
|
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
interface ComponentCustomProperties {
|
|
||||||
$axios: AxiosInstance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Be careful when using SSR for cross-request state pollution
|
|
||||||
// due to creating a Singleton instance here;
|
|
||||||
// If any client changes this (global) instance, it might be a
|
|
||||||
// good idea to move this instance creation inside of the
|
|
||||||
// "export default () => {}" function below (which runs individually
|
|
||||||
// for each client)
|
|
||||||
const api = axios.create({ baseURL: 'https://api.example.com' });
|
|
||||||
|
|
||||||
axios.interceptors.request.use(
|
|
||||||
function (context) {
|
|
||||||
const token = getToken();
|
|
||||||
|
|
||||||
if (token.length && context.headers) {
|
|
||||||
context.headers.Authorization = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
return context;
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export default boot(({ app }) => {
|
|
||||||
// for use inside Vue files (Options API) through this.$axios and this.$api
|
|
||||||
|
|
||||||
app.config.globalProperties.$axios = axios;
|
|
||||||
// ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form)
|
|
||||||
// so you won't necessarily have to import axios in each vue file
|
|
||||||
|
|
||||||
app.config.globalProperties.$api = api;
|
|
||||||
// ^ ^ ^ this will allow you to use this.$api (for Vue Options API form)
|
|
||||||
// so you can easily perform requests against your app's API
|
|
||||||
});
|
|
||||||
|
|
||||||
export { api };
|
|
|
@ -1,16 +0,0 @@
|
||||||
import { boot } from 'quasar/wrappers';
|
|
||||||
import { createI18n } from 'vue-i18n';
|
|
||||||
|
|
||||||
import messages from 'src/i18n';
|
|
||||||
|
|
||||||
const i18n = createI18n({
|
|
||||||
locale: 'en',
|
|
||||||
messages,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default boot(({ app }) => {
|
|
||||||
// Set i18n instance on app
|
|
||||||
app.use(i18n);
|
|
||||||
});
|
|
||||||
|
|
||||||
export { i18n };
|
|
|
@ -1,58 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-header class="bg-dark" color="white" elevated bordered>
|
|
||||||
<q-toolbar class="q-py-sm q-px-md">
|
|
||||||
<q-btn flat @click="$emit('toggle-drawer')" round dense icon="menu" />
|
|
||||||
<router-link to="/">
|
|
||||||
<q-btn flat round class="q-ml-xs" v-if="$q.screen.gt.xs">
|
|
||||||
<q-avatar square size="md">
|
|
||||||
<q-img src="~/assets/logo_icon.svg" alt="Logo" />
|
|
||||||
</q-avatar>
|
|
||||||
</q-btn>
|
|
||||||
</router-link>
|
|
||||||
<q-toolbar-title shrink class="text-weight-bold">Salix</q-toolbar-title>
|
|
||||||
<q-space></q-space>
|
|
||||||
<div class="q-pl-sm q-gutter-sm row items-center no-wrap">
|
|
||||||
<q-btn v-if="$q.screen.gt.xs" dense flat size="md" icon="add">
|
|
||||||
<q-icon name="arrow_drop_down" size="s" />
|
|
||||||
<q-menu>
|
|
||||||
<q-list style="min-width: 150px">
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section>New customer</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section>New ticket</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-menu>
|
|
||||||
</q-btn>
|
|
||||||
<q-btn v-if="$q.screen.gt.xs" dense flat round size="md" icon="notifications" />
|
|
||||||
<q-btn dense flat no-wrap>
|
|
||||||
<q-avatar size="lg">
|
|
||||||
<q-img
|
|
||||||
:src="`/api/Images/user/160x160/${user.id}/download?access_token=${token}`"
|
|
||||||
spinner-color="white"
|
|
||||||
/>
|
|
||||||
</q-avatar>
|
|
||||||
<q-tooltip>Account</q-tooltip>
|
|
||||||
<q-icon name="arrow_drop_down" size="s" />
|
|
||||||
<UserPanel />
|
|
||||||
</q-btn>
|
|
||||||
</div>
|
|
||||||
</q-toolbar>
|
|
||||||
</q-header>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { useState } from 'src/composables/useState';
|
|
||||||
import { useSession } from 'src/composables/useSession';
|
|
||||||
import UserPanel from 'src/components/UserPanel.vue';
|
|
||||||
|
|
||||||
const session = useSession();
|
|
||||||
const state = useState();
|
|
||||||
const user = state.getUser();
|
|
||||||
const token = session.getToken();
|
|
||||||
|
|
||||||
defineEmits<{
|
|
||||||
(event: 'toggle-drawer'): void;
|
|
||||||
}>();
|
|
||||||
</script>
|
|
|
@ -1,91 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-menu>
|
|
||||||
<div class="row no-wrap q-pa-md">
|
|
||||||
<div class="column">
|
|
||||||
<div class="text-h6 q-mb-md">{{ t('components.userPanel.settings') }}</div>
|
|
||||||
<q-toggle
|
|
||||||
:label="t(`globals.lang['${locale}']`)"
|
|
||||||
icon="public"
|
|
||||||
color="orange"
|
|
||||||
false-value="es"
|
|
||||||
true-value="en"
|
|
||||||
v-model="locale"
|
|
||||||
/>
|
|
||||||
<q-toggle v-model="darkMode" checked-icon="dark_mode" color="orange" unchecked-icon="light_mode" />
|
|
||||||
|
|
||||||
<q-btn color="orange" outline size="sm" label="Settings" icon="settings" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<q-separator vertical inset class="q-mx-lg" />
|
|
||||||
|
|
||||||
<div class="column items-center" style="min-width: 150px">
|
|
||||||
<q-avatar size="80px">
|
|
||||||
<q-img
|
|
||||||
:src="`/api/Images/user/160x160/${user.id}/download?access_token=${token}`"
|
|
||||||
spinner-color="white"
|
|
||||||
/>
|
|
||||||
</q-avatar>
|
|
||||||
|
|
||||||
<div class="text-subtitle1 q-mt-md">
|
|
||||||
<strong>{{ user.nickname }}</strong>
|
|
||||||
</div>
|
|
||||||
<div class="text-subtitle3 text-grey-7 q-mb-xs">@{{ user.username }}</div>
|
|
||||||
|
|
||||||
<q-btn color="orange" flat label="Log Out" size="sm" icon="logout" @click="logout()" v-close-popup />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</q-menu>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { onMounted, computed } from 'vue';
|
|
||||||
import { Dark, useQuasar } from 'quasar';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import { useState } from 'src/composables/useState';
|
|
||||||
import { useSession } from 'src/composables/useSession';
|
|
||||||
|
|
||||||
const quasar = useQuasar();
|
|
||||||
const state = useState();
|
|
||||||
const session = useSession();
|
|
||||||
const router = useRouter();
|
|
||||||
const { t, locale } = useI18n();
|
|
||||||
|
|
||||||
const darkMode = computed({
|
|
||||||
get(): boolean {
|
|
||||||
return Dark.isActive;
|
|
||||||
},
|
|
||||||
set(value: boolean): void {
|
|
||||||
Dark.set(value);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const user = state.getUser();
|
|
||||||
const token = session.getToken();
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
axios
|
|
||||||
.get('/api/accounts/acl')
|
|
||||||
.then(({ data }) => {
|
|
||||||
state.setUser({
|
|
||||||
id: data.user.id,
|
|
||||||
username: data.user.name,
|
|
||||||
nickname: data.user.nickname,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
quasar.notify({
|
|
||||||
message: t('errors.statusUnauthorized'),
|
|
||||||
type: 'negative',
|
|
||||||
});
|
|
||||||
logout();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function logout(): void {
|
|
||||||
session.destroy();
|
|
||||||
router.push('/login');
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { describe, expect, it } from '@jest/globals';
|
|
||||||
import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-unit-jest';
|
|
||||||
import { mount } from '@vue/test-utils';
|
|
||||||
import { i18n } from 'src/boot/i18n';
|
|
||||||
import UserPanel from '../UserPanel.vue';
|
|
||||||
|
|
||||||
// Specify here Quasar config you'll need to test your component
|
|
||||||
installQuasarPlugin();
|
|
||||||
const routerPushMock = jest.fn();
|
|
||||||
|
|
||||||
jest.mock('vue-router', () => ({
|
|
||||||
useRouter: () => ({
|
|
||||||
push: routerPushMock,
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('UserPanel', () => {
|
|
||||||
it('should have the function logout defined', () => {
|
|
||||||
const wrapper = mount(UserPanel, {
|
|
||||||
global: {
|
|
||||||
plugins: [i18n]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const { vm } = wrapper;
|
|
||||||
|
|
||||||
expect(vm.logout).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,8 +0,0 @@
|
||||||
export interface Todo {
|
|
||||||
id: number;
|
|
||||||
content: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Meta {
|
|
||||||
totalCount: number;
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
/* import store from '@/store';
|
|
||||||
|
|
||||||
export function useRole() {
|
|
||||||
function hasAny(roles: string[]): boolean {
|
|
||||||
const roleStore: string[] = store.state.roles;
|
|
||||||
|
|
||||||
for (const role of roles) {
|
|
||||||
if (roleStore.indexOf(role) !== -1) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
hasAny,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -1,57 +0,0 @@
|
||||||
import { useState } from './useState';
|
|
||||||
|
|
||||||
interface Session {
|
|
||||||
token: string;
|
|
||||||
keepLogin: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface useSession {
|
|
||||||
getToken: () => string;
|
|
||||||
setToken: (data: Session) => void;
|
|
||||||
destroy: () => void;
|
|
||||||
isLoggedIn: () => boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useSession(): useSession {
|
|
||||||
function getToken(): string {
|
|
||||||
const localToken = localStorage.getItem('token');
|
|
||||||
const sessionToken = sessionStorage.getItem('token');
|
|
||||||
|
|
||||||
return localToken || sessionToken || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function setToken(data: Session): void {
|
|
||||||
if (data.keepLogin) {
|
|
||||||
localStorage.setItem('token', data.token);
|
|
||||||
} else {
|
|
||||||
sessionStorage.setItem('token', data.token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function destroy(): void {
|
|
||||||
localStorage.removeItem('token');
|
|
||||||
sessionStorage.getItem('token');
|
|
||||||
|
|
||||||
const { setUser } = useState();
|
|
||||||
|
|
||||||
setUser({
|
|
||||||
id: 0,
|
|
||||||
username: '',
|
|
||||||
nickname: '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function isLoggedIn() {
|
|
||||||
const localToken = localStorage.getItem('token');
|
|
||||||
const sessionToken = sessionStorage.getItem('token');
|
|
||||||
|
|
||||||
return !!(localToken || sessionToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
getToken,
|
|
||||||
setToken,
|
|
||||||
destroy,
|
|
||||||
isLoggedIn,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
import { ref, Ref, computed, ComputedRef } from 'vue';
|
|
||||||
|
|
||||||
interface User {
|
|
||||||
id: number;
|
|
||||||
username: string;
|
|
||||||
nickname: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface useState {
|
|
||||||
getUser: () => ComputedRef<User>;
|
|
||||||
setUser: (data: User) => void;
|
|
||||||
getRoles: () => ComputedRef<string[]>;
|
|
||||||
setRoles: (data: string[]) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const user: Ref<User> = ref({
|
|
||||||
id: 0,
|
|
||||||
username: '',
|
|
||||||
nickname: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
const roles: Ref<string[]> = ref([]);
|
|
||||||
|
|
||||||
export function useState(): useState {
|
|
||||||
function getUser(): ComputedRef<User> {
|
|
||||||
return computed(() => {
|
|
||||||
return {
|
|
||||||
id: user.value.id,
|
|
||||||
username: user.value.username,
|
|
||||||
nickname: user.value.nickname,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setUser(data: User): void {
|
|
||||||
user.value = {
|
|
||||||
id: data.id,
|
|
||||||
username: data.username,
|
|
||||||
nickname: data.nickname,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRoles(): ComputedRef<string[]> {
|
|
||||||
return computed(() => {
|
|
||||||
return roles.value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setRoles(data: string[]): void {
|
|
||||||
roles.value = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
getUser,
|
|
||||||
setUser,
|
|
||||||
getRoles,
|
|
||||||
setRoles,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
// app global css in SCSS form
|
|
||||||
@import './icons.scss';
|
|
Before Width: | Height: | Size: 158 KiB |
|
@ -1,393 +0,0 @@
|
||||||
@font-face {
|
|
||||||
font-family: 'icomoon';
|
|
||||||
src: url('fonts/icomoon.eot?cjtmya');
|
|
||||||
src: url('fonts/icomoon.eot?cjtmya#iefix') format('embedded-opentype'),
|
|
||||||
url('fonts/icomoon.ttf?cjtmya') format('truetype'), url('fonts/icomoon.woff?cjtmya') format('woff'),
|
|
||||||
url('fonts/icomoon.svg?cjtmya#icomoon') format('svg');
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
font-display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
[class^='icon-'],
|
|
||||||
[class*=' icon-'] {
|
|
||||||
/* use !important to prevent issues with browser extensions that change fonts */
|
|
||||||
font-family: 'icomoon' !important;
|
|
||||||
speak: never;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
font-variant: normal;
|
|
||||||
text-transform: none;
|
|
||||||
line-height: 1;
|
|
||||||
|
|
||||||
/* Better Font Rendering =========== */
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-frozen:before {
|
|
||||||
content: '\e900';
|
|
||||||
}
|
|
||||||
.icon-Person:before {
|
|
||||||
content: '\e901';
|
|
||||||
}
|
|
||||||
.icon-handmadeArtificial:before {
|
|
||||||
content: '\e902';
|
|
||||||
}
|
|
||||||
.icon-fruit:before {
|
|
||||||
content: '\e903';
|
|
||||||
}
|
|
||||||
.icon-funeral:before {
|
|
||||||
content: '\e904';
|
|
||||||
}
|
|
||||||
.icon-noPayMethod:before {
|
|
||||||
content: '\e905';
|
|
||||||
}
|
|
||||||
.icon-preserved:before {
|
|
||||||
content: '\e906';
|
|
||||||
}
|
|
||||||
.icon-greenery:before {
|
|
||||||
content: '\e907';
|
|
||||||
}
|
|
||||||
.icon-planta:before {
|
|
||||||
content: '\e908';
|
|
||||||
}
|
|
||||||
.icon-handmade:before {
|
|
||||||
content: '\e909';
|
|
||||||
}
|
|
||||||
.icon-accessory:before {
|
|
||||||
content: '\e90a';
|
|
||||||
}
|
|
||||||
.icon-artificial:before {
|
|
||||||
content: '\e90b';
|
|
||||||
}
|
|
||||||
.icon-flower:before {
|
|
||||||
content: '\e90c';
|
|
||||||
}
|
|
||||||
.icon-fixedPrice:before {
|
|
||||||
content: '\e90d';
|
|
||||||
}
|
|
||||||
.icon-addperson:before {
|
|
||||||
content: '\e90e';
|
|
||||||
}
|
|
||||||
.icon-supplierfalse:before {
|
|
||||||
content: '\e90f';
|
|
||||||
}
|
|
||||||
.icon-invoice-out:before {
|
|
||||||
content: '\e910';
|
|
||||||
}
|
|
||||||
.icon-invoice-in:before {
|
|
||||||
content: '\e911';
|
|
||||||
}
|
|
||||||
.icon-invoice-in-create:before {
|
|
||||||
content: '\e912';
|
|
||||||
}
|
|
||||||
.icon-basketadd:before {
|
|
||||||
content: '\e913';
|
|
||||||
}
|
|
||||||
.icon-basket:before {
|
|
||||||
content: '\e914';
|
|
||||||
}
|
|
||||||
.icon-uniE915:before {
|
|
||||||
content: '\e915';
|
|
||||||
}
|
|
||||||
.icon-uniE916:before {
|
|
||||||
content: '\e916';
|
|
||||||
}
|
|
||||||
.icon-uniE917:before {
|
|
||||||
content: '\e917';
|
|
||||||
}
|
|
||||||
.icon-uniE918:before {
|
|
||||||
content: '\e918';
|
|
||||||
}
|
|
||||||
.icon-uniE919:before {
|
|
||||||
content: '\e919';
|
|
||||||
}
|
|
||||||
.icon-uniE91A:before {
|
|
||||||
content: '\e91a';
|
|
||||||
}
|
|
||||||
.icon-isTooLittle:before {
|
|
||||||
content: '\e91b';
|
|
||||||
}
|
|
||||||
.icon-deliveryprices:before {
|
|
||||||
content: '\e91c';
|
|
||||||
}
|
|
||||||
.icon-onlinepayment:before {
|
|
||||||
content: '\e91d';
|
|
||||||
}
|
|
||||||
.icon-risk:before {
|
|
||||||
content: '\e91e';
|
|
||||||
}
|
|
||||||
.icon-noweb:before {
|
|
||||||
content: '\e91f';
|
|
||||||
}
|
|
||||||
.icon-no036:before {
|
|
||||||
content: '\e920';
|
|
||||||
}
|
|
||||||
.icon-disabled:before {
|
|
||||||
content: '\e921';
|
|
||||||
}
|
|
||||||
.icon-treatments:before {
|
|
||||||
content: '\e922';
|
|
||||||
}
|
|
||||||
.icon-invoice:before {
|
|
||||||
content: '\e923';
|
|
||||||
}
|
|
||||||
.icon-photo:before {
|
|
||||||
content: '\e924';
|
|
||||||
}
|
|
||||||
.icon-supplier:before {
|
|
||||||
content: '\e925';
|
|
||||||
}
|
|
||||||
.icon-languaje:before {
|
|
||||||
content: '\e926';
|
|
||||||
}
|
|
||||||
.icon-credit:before {
|
|
||||||
content: '\e927';
|
|
||||||
}
|
|
||||||
.icon-client:before {
|
|
||||||
content: '\e928';
|
|
||||||
}
|
|
||||||
.icon-shipment-01:before {
|
|
||||||
content: '\e929';
|
|
||||||
}
|
|
||||||
.icon-account:before {
|
|
||||||
content: '\e92a';
|
|
||||||
}
|
|
||||||
.icon-inventory:before {
|
|
||||||
content: '\e92b';
|
|
||||||
}
|
|
||||||
.icon-unavailable:before {
|
|
||||||
content: '\e92c';
|
|
||||||
}
|
|
||||||
.icon-wiki:before {
|
|
||||||
content: '\e92d';
|
|
||||||
}
|
|
||||||
.icon-attach:before {
|
|
||||||
content: '\e92e';
|
|
||||||
}
|
|
||||||
.icon-exit:before {
|
|
||||||
content: '\e92f';
|
|
||||||
}
|
|
||||||
.icon-anonymous:before {
|
|
||||||
content: '\e930';
|
|
||||||
}
|
|
||||||
.icon-net:before {
|
|
||||||
content: '\e931';
|
|
||||||
}
|
|
||||||
.icon-buyrequest:before {
|
|
||||||
content: '\e932';
|
|
||||||
}
|
|
||||||
.icon-thermometer:before {
|
|
||||||
content: '\e933';
|
|
||||||
}
|
|
||||||
.icon-entry:before {
|
|
||||||
content: '\e934';
|
|
||||||
}
|
|
||||||
.icon-deletedTicket:before {
|
|
||||||
content: '\e935';
|
|
||||||
}
|
|
||||||
.icon-logout:before {
|
|
||||||
content: '\e936';
|
|
||||||
}
|
|
||||||
.icon-catalog:before {
|
|
||||||
content: '\e937';
|
|
||||||
}
|
|
||||||
.icon-agency:before {
|
|
||||||
content: '\e938';
|
|
||||||
}
|
|
||||||
.icon-delivery:before {
|
|
||||||
content: '\e939';
|
|
||||||
}
|
|
||||||
.icon-wand:before {
|
|
||||||
content: '\e93a';
|
|
||||||
}
|
|
||||||
.icon-buscaman:before {
|
|
||||||
content: '\e93b';
|
|
||||||
}
|
|
||||||
.icon-pbx:before {
|
|
||||||
content: '\e93c';
|
|
||||||
}
|
|
||||||
.icon-calendar:before {
|
|
||||||
content: '\e93d';
|
|
||||||
}
|
|
||||||
.icon-splitline:before {
|
|
||||||
content: '\e93e';
|
|
||||||
}
|
|
||||||
.icon-consignatarios:before {
|
|
||||||
content: '\e93f';
|
|
||||||
}
|
|
||||||
.icon-tax:before {
|
|
||||||
content: '\e940';
|
|
||||||
}
|
|
||||||
.icon-notes:before {
|
|
||||||
content: '\e941';
|
|
||||||
}
|
|
||||||
.icon-lines:before {
|
|
||||||
content: '\e942';
|
|
||||||
}
|
|
||||||
.icon-zone:before {
|
|
||||||
content: '\e943';
|
|
||||||
}
|
|
||||||
.icon-greuge:before {
|
|
||||||
content: '\e944';
|
|
||||||
}
|
|
||||||
.icon-ticketAdd:before {
|
|
||||||
content: '\e945';
|
|
||||||
}
|
|
||||||
.icon-components:before {
|
|
||||||
content: '\e946';
|
|
||||||
}
|
|
||||||
.icon-pets:before {
|
|
||||||
content: '\e947';
|
|
||||||
}
|
|
||||||
.icon-linesprepaired:before {
|
|
||||||
content: '\e948';
|
|
||||||
}
|
|
||||||
.icon-control:before {
|
|
||||||
content: '\e949';
|
|
||||||
}
|
|
||||||
.icon-revision:before {
|
|
||||||
content: '\e94a';
|
|
||||||
}
|
|
||||||
.icon-deaulter:before {
|
|
||||||
content: '\e94b';
|
|
||||||
}
|
|
||||||
.icon-services:before {
|
|
||||||
content: '\e94c';
|
|
||||||
}
|
|
||||||
.icon-albaran:before {
|
|
||||||
content: '\e94d';
|
|
||||||
}
|
|
||||||
.icon-solunion:before {
|
|
||||||
content: '\e94e';
|
|
||||||
}
|
|
||||||
.icon-stowaway:before {
|
|
||||||
content: '\e94f';
|
|
||||||
}
|
|
||||||
.icon-apps:before {
|
|
||||||
content: '\e951';
|
|
||||||
}
|
|
||||||
.icon-info:before {
|
|
||||||
content: '\e952';
|
|
||||||
}
|
|
||||||
.icon-columndelete:before {
|
|
||||||
content: '\e953';
|
|
||||||
}
|
|
||||||
.icon-columnadd:before {
|
|
||||||
content: '\e954';
|
|
||||||
}
|
|
||||||
.icon-deleteline:before {
|
|
||||||
content: '\e955';
|
|
||||||
}
|
|
||||||
.icon-item:before {
|
|
||||||
content: '\e956';
|
|
||||||
}
|
|
||||||
.icon-worker:before {
|
|
||||||
content: '\e957';
|
|
||||||
}
|
|
||||||
.icon-headercol:before {
|
|
||||||
content: '\e958';
|
|
||||||
}
|
|
||||||
.icon-reserva:before {
|
|
||||||
content: '\e959';
|
|
||||||
}
|
|
||||||
.icon-100:before {
|
|
||||||
content: '\e95a';
|
|
||||||
}
|
|
||||||
.icon-sign:before {
|
|
||||||
content: '\e95d';
|
|
||||||
}
|
|
||||||
.icon-polizon:before {
|
|
||||||
content: '\e95e';
|
|
||||||
}
|
|
||||||
.icon-solclaim:before {
|
|
||||||
content: '\e95f';
|
|
||||||
}
|
|
||||||
.icon-actions:before {
|
|
||||||
content: '\e960';
|
|
||||||
}
|
|
||||||
.icon-details:before {
|
|
||||||
content: '\e961';
|
|
||||||
}
|
|
||||||
.icon-traceability:before {
|
|
||||||
content: '\e962';
|
|
||||||
}
|
|
||||||
.icon-claims:before {
|
|
||||||
content: '\e963';
|
|
||||||
}
|
|
||||||
.icon-regentry:before {
|
|
||||||
content: '\e964';
|
|
||||||
}
|
|
||||||
.icon-transaction:before {
|
|
||||||
content: '\e966';
|
|
||||||
}
|
|
||||||
.icon-History:before {
|
|
||||||
content: '\e968';
|
|
||||||
}
|
|
||||||
.icon-mana:before {
|
|
||||||
content: '\e96a';
|
|
||||||
}
|
|
||||||
.icon-ticket:before {
|
|
||||||
content: '\e96b';
|
|
||||||
}
|
|
||||||
.icon-niche:before {
|
|
||||||
content: '\e96c';
|
|
||||||
}
|
|
||||||
.icon-tags:before {
|
|
||||||
content: '\e96d';
|
|
||||||
}
|
|
||||||
.icon-volume:before {
|
|
||||||
content: '\e96e';
|
|
||||||
}
|
|
||||||
.icon-bin:before {
|
|
||||||
content: '\e96f';
|
|
||||||
}
|
|
||||||
.icon-splur:before {
|
|
||||||
content: '\e970';
|
|
||||||
}
|
|
||||||
.icon-barcode:before {
|
|
||||||
content: '\e971';
|
|
||||||
}
|
|
||||||
.icon-botanical:before {
|
|
||||||
content: '\e972';
|
|
||||||
}
|
|
||||||
.icon-clone:before {
|
|
||||||
content: '\e973';
|
|
||||||
}
|
|
||||||
.icon-sms:before {
|
|
||||||
content: '\e975';
|
|
||||||
}
|
|
||||||
.icon-eye:before {
|
|
||||||
content: '\e976';
|
|
||||||
}
|
|
||||||
.icon-doc:before {
|
|
||||||
content: '\e977';
|
|
||||||
}
|
|
||||||
.icon-package:before {
|
|
||||||
content: '\e978';
|
|
||||||
}
|
|
||||||
.icon-settings:before {
|
|
||||||
content: '\e979';
|
|
||||||
}
|
|
||||||
.icon-bucket:before {
|
|
||||||
content: '\e97a';
|
|
||||||
}
|
|
||||||
.icon-mandatory:before {
|
|
||||||
content: '\e97b';
|
|
||||||
}
|
|
||||||
.icon-recovery:before {
|
|
||||||
content: '\e97c';
|
|
||||||
}
|
|
||||||
.icon-payment:before {
|
|
||||||
content: '\e97e';
|
|
||||||
}
|
|
||||||
.icon-grid:before {
|
|
||||||
content: '\e980';
|
|
||||||
}
|
|
||||||
.icon-web:before {
|
|
||||||
content: '\e982';
|
|
||||||
}
|
|
||||||
.icon-dfiscales:before {
|
|
||||||
content: '\e984';
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
// Quasar SCSS (& Sass) Variables
|
|
||||||
// --------------------------------------------------
|
|
||||||
// To customize the look and feel of this app, you can override
|
|
||||||
// the Sass/SCSS variables found in Quasar's source Sass/SCSS files.
|
|
||||||
|
|
||||||
// Check documentation for full list of Quasar variables
|
|
||||||
|
|
||||||
// Your own variables (that are declared here) and Quasar's own
|
|
||||||
// ones will be available out of the box in your .vue/.scss/.sass files
|
|
||||||
|
|
||||||
// It's highly recommended to change the default colors
|
|
||||||
// to match your app's branding.
|
|
||||||
// Tip: Use the "Theme Builder" on Quasar's documentation website.
|
|
||||||
|
|
||||||
$primary: #1976d2;
|
|
||||||
$secondary: #26a69a;
|
|
||||||
$accent: #9c27b0;
|
|
||||||
|
|
||||||
$dark: #1d1d1d;
|
|
||||||
|
|
||||||
$positive: #21ba45;
|
|
||||||
$negative: #c10015;
|
|
||||||
$info: #31ccec;
|
|
||||||
$warning: #f2c037;
|
|
|
@ -1,7 +0,0 @@
|
||||||
declare namespace NodeJS {
|
|
||||||
interface ProcessEnv {
|
|
||||||
NODE_ENV: string;
|
|
||||||
VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined;
|
|
||||||
VUE_ROUTER_BASE: string | undefined;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
import toLowerCase from './toLowerCase';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
toLowerCase,
|
|
||||||
};
|
|
|
@ -1,3 +0,0 @@
|
||||||
export default function toLowerCase(value: string): string {
|
|
||||||
return value.toLowerCase();
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
export default {
|
|
||||||
globals: {
|
|
||||||
lang: {
|
|
||||||
es: 'Spanish',
|
|
||||||
en: 'English',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
errors: {
|
|
||||||
statusUnauthorized: 'Access denied',
|
|
||||||
statusInternalServerError: 'An internal server error has ocurred',
|
|
||||||
},
|
|
||||||
login: {
|
|
||||||
title: 'Login',
|
|
||||||
username: 'Username',
|
|
||||||
password: 'Password',
|
|
||||||
submit: 'Log in',
|
|
||||||
keepLogin: 'Keep me logged in',
|
|
||||||
loginSuccess: 'You have successfully logged in',
|
|
||||||
loginError: 'Invalid username or password',
|
|
||||||
},
|
|
||||||
customer: {},
|
|
||||||
components: {
|
|
||||||
topbar: {},
|
|
||||||
userPanel: {
|
|
||||||
settings: 'Settings',
|
|
||||||
logOut: 'Log Out',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pages: {
|
|
||||||
logIn: 'Log In',
|
|
||||||
dashboard: 'Dashboard',
|
|
||||||
customers: 'Customers',
|
|
||||||
list: 'List',
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,29 +0,0 @@
|
||||||
export default {
|
|
||||||
globals: {
|
|
||||||
lang: {
|
|
||||||
es: 'Español',
|
|
||||||
en: 'Inglés',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
errors: {
|
|
||||||
statusUnauthorized: 'Acceso denegado',
|
|
||||||
statusInternalServerError: 'Ha ocurrido un error interno del servidor',
|
|
||||||
},
|
|
||||||
login: {
|
|
||||||
title: 'Iniciar sesión',
|
|
||||||
username: 'Nombre de usuario',
|
|
||||||
password: 'Contraseña',
|
|
||||||
submit: 'Iniciar sesión',
|
|
||||||
keepLogin: 'Mantener sesión iniciada',
|
|
||||||
loginSuccess: 'Inicio de sesión correcto',
|
|
||||||
loginError: 'Nombre de usuario o contraseña incorrectos',
|
|
||||||
},
|
|
||||||
customer: {},
|
|
||||||
components: {
|
|
||||||
topbar: {},
|
|
||||||
userPanel: {
|
|
||||||
settings: 'Configuración',
|
|
||||||
logOut: 'Cerrar sesión',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,7 +0,0 @@
|
||||||
import en from './en';
|
|
||||||
import es from './es';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
en: en,
|
|
||||||
es: es,
|
|
||||||
};
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title><%= productName %></title>
|
|
||||||
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="description" content="<%= productDescription %>" />
|
|
||||||
<meta name="format-detection" content="telephone=no" />
|
|
||||||
<meta name="msapplication-tap-highlight" content="no" />
|
|
||||||
<meta
|
|
||||||
name="viewport"
|
|
||||||
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<link rel="icon" type="image/png" sizes="128x128" href="icons/favicon-128x128.png" />
|
|
||||||
<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png" />
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png" />
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png" />
|
|
||||||
<link rel="icon" type="image/ico" href="favicon.ico" />
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!-- DO NOT touch the following DIV -->
|
|
||||||
<div id="q-app"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,79 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-layout view="hHh lpR fFf">
|
|
||||||
<Navbar @toggle-drawer="onToggleDrawer()" />
|
|
||||||
<q-drawer
|
|
||||||
v-model="drawer"
|
|
||||||
show-if-above
|
|
||||||
:mini="miniState"
|
|
||||||
@mouseover="miniState = false"
|
|
||||||
@mouseout="miniState = true"
|
|
||||||
mini-to-overlay
|
|
||||||
:width="200"
|
|
||||||
:breakpoint="500"
|
|
||||||
>
|
|
||||||
<q-scroll-area class="fit text-grey-8">
|
|
||||||
<q-list padding>
|
|
||||||
<q-item clickable v-ripple :to="{ path: '/dashboard' }" active-class="text-orange">
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon name="dashboard" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>Dashboard</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable v-ripple :to="{ path: '/customer' }" active-class="text-orange">
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon name="people" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>Customers</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable v-ripple :to="{ path: '/ticket' }" active-class="text-orange">
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon name="vn:ticket" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>Tickets</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable v-ripple>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon name="receipt" />
|
|
||||||
</q-item-section>
|
|
||||||
|
|
||||||
<q-item-section>Invoice Out</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
|
|
||||||
<q-item clickable v-ripple>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon name="shopping_cart" />
|
|
||||||
</q-item-section>
|
|
||||||
|
|
||||||
<q-item-section>Catalog</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
|
|
||||||
<q-separator />
|
|
||||||
|
|
||||||
<q-item clickable v-ripple>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon name="drafts" />
|
|
||||||
</q-item-section>
|
|
||||||
|
|
||||||
<q-item-section>Drafts</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-scroll-area>
|
|
||||||
</q-drawer>
|
|
||||||
<q-page-container>
|
|
||||||
<router-view></router-view>
|
|
||||||
</q-page-container>
|
|
||||||
</q-layout>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import Navbar from 'src/components/Navbar.vue';
|
|
||||||
const drawer = ref(false);
|
|
||||||
const miniState = ref(true);
|
|
||||||
|
|
||||||
function onToggleDrawer(): void {
|
|
||||||
drawer.value = !drawer.value;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
|
@ -1,15 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="row fit fixed">
|
|
||||||
<div class="col-2">
|
|
||||||
<q-card square>
|
|
||||||
<router-link :to="{ path: '/customer/list' }">
|
|
||||||
<q-icon name="arrow_back" size="md" color="primary" />
|
|
||||||
</router-link>
|
|
||||||
</q-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<q-card>asd</q-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,3 +0,0 @@
|
||||||
<template>
|
|
||||||
<router-view></router-view>
|
|
||||||
</template>
|
|
|
@ -1,145 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-page class="q-pa-md">
|
|
||||||
<div class="column items-center q-gutter-y-md">
|
|
||||||
<q-card v-for="customer in customers" :key="customer.id" class="card">
|
|
||||||
<!-- v-ripple :to="{ path: '/dashboard' }" -->
|
|
||||||
<q-item v-ripple class="q-pa-none items-start cursor-pointer q-hoverable">
|
|
||||||
<q-item-section class="q-pa-md">
|
|
||||||
<div class="text-h6">{{ customer.name }}</div>
|
|
||||||
<q-item-label caption>@{{ customer.username }}</q-item-label>
|
|
||||||
<div class="q-mt-md">
|
|
||||||
<q-list>
|
|
||||||
<q-item class="q-pa-none">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>Email</q-item-label>
|
|
||||||
<q-item-label>{{ customer.email }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item class="q-pa-none">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>Phone</q-item-label>
|
|
||||||
<q-item-label>{{ customer.phone }} </q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
</q-item-section>
|
|
||||||
<q-btn color="grey-7" round flat icon="more_vert">
|
|
||||||
<q-menu cover auto-close>
|
|
||||||
<q-list>
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section>Action 1</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section>Action 2</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-menu>
|
|
||||||
</q-btn>
|
|
||||||
<q-separator vertical />
|
|
||||||
<q-card-actions vertical class="justify-between">
|
|
||||||
<q-btn flat round color="orange" icon="arrow_circle_right" @click="navigate(customer.id)" />
|
|
||||||
<q-btn flat round color="accent" icon="preview" />
|
|
||||||
<q-btn flat round color="accent" icon="vn:ticket" />
|
|
||||||
<q-card-actions>
|
|
||||||
<q-btn
|
|
||||||
color="grey"
|
|
||||||
round
|
|
||||||
flat
|
|
||||||
dense
|
|
||||||
:icon="customer.expanded.value ? 'keyboard_arrow_up' : 'keyboard_arrow_down'"
|
|
||||||
@click="customer.expanded.value = !customer.expanded.value"
|
|
||||||
/>
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card-actions>
|
|
||||||
</q-item>
|
|
||||||
<q-slide-transition>
|
|
||||||
<div v-show="customer.expanded.value">
|
|
||||||
<q-separator />
|
|
||||||
<q-card-section class="text-subitle2">
|
|
||||||
<q-list>
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>Address</q-item-label>
|
|
||||||
<q-item-label caption>Avenue 11</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-card-section>
|
|
||||||
</div>
|
|
||||||
</q-slide-transition>
|
|
||||||
<!-- <q-card-section horizontal>
|
|
||||||
<q-card-section vertical class="col">
|
|
||||||
<div class="text-h6">{{ customer.name }}</div>
|
|
||||||
<div class="text-subtitle2">@{{ customer.username }}</div>
|
|
||||||
|
|
||||||
<q-card-section vertical>text</q-card-section>
|
|
||||||
</q-card-section>
|
|
||||||
|
|
||||||
<q-separator vertical />
|
|
||||||
|
|
||||||
<q-card-actions vertical class="justify-around">
|
|
||||||
<q-btn flat round color="red" icon="favorite" />
|
|
||||||
<q-btn flat round color="accent" icon="bookmark" />
|
|
||||||
<q-btn color="grey-7" round flat icon="more_vert">
|
|
||||||
<q-menu cover auto-close>
|
|
||||||
<q-list>
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section>Action 1</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item clickable>
|
|
||||||
<q-item-section>Action 2</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-menu>
|
|
||||||
</q-btn>
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card-section> -->
|
|
||||||
</q-card>
|
|
||||||
</div>
|
|
||||||
</q-page>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, Ref } from 'vue';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
interface Customer {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
username: string;
|
|
||||||
email: string;
|
|
||||||
phone: string;
|
|
||||||
expanded: Ref<boolean>;
|
|
||||||
}
|
|
||||||
const customers: Customer[] = [
|
|
||||||
{
|
|
||||||
id: 1101,
|
|
||||||
name: 'Bruce Wayne',
|
|
||||||
username: 'batman',
|
|
||||||
email: 'batman@gotham',
|
|
||||||
phone: '555-555-5555',
|
|
||||||
expanded: ref(false),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1102,
|
|
||||||
name: 'James Gordon',
|
|
||||||
username: 'jamesgordon',
|
|
||||||
email: 'jamesgordon@gotham',
|
|
||||||
phone: '555-555-1111',
|
|
||||||
expanded: ref(false),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function navigate(id: number) {
|
|
||||||
router.push({ path: `/customer/${id}` });
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.card {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 60em;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,84 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
const slide = ref('style');
|
|
||||||
const slideText = 'Description text';
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<q-page class="q-pa-md">
|
|
||||||
<q-banner
|
|
||||||
v-if="$q.screen.gt.xs"
|
|
||||||
inline-actions
|
|
||||||
rounded
|
|
||||||
class="bg-orange text-white q-mb-lg"
|
|
||||||
>
|
|
||||||
You have lost connection to the internet. This app is offline.
|
|
||||||
<template #action>
|
|
||||||
<q-btn flat label="Turn ON Wifi" />
|
|
||||||
<q-btn flat label="Dismiss" />
|
|
||||||
</template>
|
|
||||||
</q-banner>
|
|
||||||
|
|
||||||
<div class="row items-start wrap q-col-gutter-md q-mb-lg">
|
|
||||||
<div class="col-12 col-md">
|
|
||||||
<div class="text-h6 text-grey-8 q-mb-sm">Responsive monitor</div>
|
|
||||||
<q-carousel
|
|
||||||
v-model="slide"
|
|
||||||
transition-prev="scale"
|
|
||||||
transition-next="scale"
|
|
||||||
swipeable
|
|
||||||
animated
|
|
||||||
control-color="white"
|
|
||||||
navigation
|
|
||||||
padding
|
|
||||||
arrows
|
|
||||||
height="300px"
|
|
||||||
class="bg-orange-3 text-white shadow-1 rounded-borders"
|
|
||||||
>
|
|
||||||
<q-carousel-slide name="style" class="column no-wrap flex-center">
|
|
||||||
<q-icon name="style" size="56px" />
|
|
||||||
<div class="q-mt-md text-center">{{ slideText }}</div>
|
|
||||||
</q-carousel-slide>
|
|
||||||
<q-carousel-slide name="tv" class="column no-wrap flex-center">
|
|
||||||
<q-icon name="live_tv" size="56px" />
|
|
||||||
<div class="q-mt-md text-center">{{ slideText }}</div>
|
|
||||||
</q-carousel-slide>
|
|
||||||
<q-carousel-slide name="layers" class="column no-wrap flex-center">
|
|
||||||
<q-icon name="layers" size="56px" />
|
|
||||||
<div class="q-mt-md text-center">{{ slideText }}</div>
|
|
||||||
</q-carousel-slide>
|
|
||||||
<q-carousel-slide name="map" class="column no-wrap flex-center">
|
|
||||||
<q-icon name="terrain" size="56px" />
|
|
||||||
<div class="q-mt-md text-center">{{ slideText }}</div>
|
|
||||||
</q-carousel-slide>
|
|
||||||
</q-carousel>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md">
|
|
||||||
<div class="text-h6 text-grey-8 q-mb-sm">Responsive monitor</div>
|
|
||||||
<q-card class="q-pa-md">Dashboard page..</q-card>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md">
|
|
||||||
<div class="text-h6 text-grey-8 q-mb-sm">Responsive monitor</div>
|
|
||||||
<q-card class="q-pa-md">Dashboard page..</q-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row items-start q-col-gutter-md q-mb-lg">
|
|
||||||
<div class="col-12 col-md">
|
|
||||||
<div class="text-h6 text-grey-8 q-mb-sm">Responsive monitor</div>
|
|
||||||
<q-card class="q-pa-md">Dashboard page..</q-card>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-md">
|
|
||||||
<div class="text-h6 text-grey-8 q-mb-sm">Responsive monitor</div>
|
|
||||||
<q-card class="q-pa-md">Dashboard page..</q-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row items-start q-col-gutter-md q-mb-lg">
|
|
||||||
<div class="col">
|
|
||||||
<div class="text-h6 text-grey-8 q-mb-sm">Responsive monitor</div>
|
|
||||||
<q-card class="q-pa-md">Dashboard page..</q-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</q-page>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
|
|
@ -1,147 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-layout>
|
|
||||||
<q-header class="transparent">
|
|
||||||
<q-toolbar>
|
|
||||||
<q-space></q-space>
|
|
||||||
<q-toggle
|
|
||||||
:label="t(`globals.lang['${locale}']`)"
|
|
||||||
icon="public"
|
|
||||||
color="orange"
|
|
||||||
false-value="es"
|
|
||||||
true-value="en"
|
|
||||||
v-model="locale"
|
|
||||||
/>
|
|
||||||
<q-toggle
|
|
||||||
v-model="darkMode"
|
|
||||||
checked-icon="dark_mode"
|
|
||||||
color="orange"
|
|
||||||
unchecked-icon="light_mode"
|
|
||||||
/>
|
|
||||||
</q-toolbar>
|
|
||||||
</q-header>
|
|
||||||
<q-page-container>
|
|
||||||
<q-page>
|
|
||||||
<div id="login">
|
|
||||||
<q-card class="login q-pa-xl">
|
|
||||||
<q-img
|
|
||||||
src="~/assets/logo.svg"
|
|
||||||
alt="Logo"
|
|
||||||
fit="contain"
|
|
||||||
:ratio="16 / 9"
|
|
||||||
class="q-mb-md"
|
|
||||||
/>
|
|
||||||
<q-form @submit="onSubmit" class="q-gutter-md">
|
|
||||||
<q-input
|
|
||||||
filled
|
|
||||||
color="orange"
|
|
||||||
v-model="username"
|
|
||||||
:label="t('login.username')"
|
|
||||||
lazy-rules
|
|
||||||
:rules="[
|
|
||||||
(val) => (val && val.length > 0) || 'Please type something',
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
<q-input
|
|
||||||
filled
|
|
||||||
color="orange"
|
|
||||||
type="password"
|
|
||||||
v-model="password"
|
|
||||||
:label="t('login.password')"
|
|
||||||
lazy-rules
|
|
||||||
:rules="[
|
|
||||||
(val) => (val && val.length > 0) || 'Please type something',
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
<q-toggle
|
|
||||||
v-model="keepLogin"
|
|
||||||
:label="t('login.keepLogin')"
|
|
||||||
color="orange"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<q-btn :label="t('login.submit')" type="submit" color="orange" />
|
|
||||||
</div>
|
|
||||||
</q-form>
|
|
||||||
</q-card>
|
|
||||||
</div>
|
|
||||||
</q-page>
|
|
||||||
</q-page-container>
|
|
||||||
</q-layout>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed, ref } from 'vue';
|
|
||||||
import { Dark, useQuasar } from 'quasar';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import { useSession } from 'src/composables/useSession';
|
|
||||||
|
|
||||||
const quasar = useQuasar();
|
|
||||||
const session = useSession();
|
|
||||||
const router = useRouter();
|
|
||||||
const { t, locale } = useI18n();
|
|
||||||
|
|
||||||
let username = ref('');
|
|
||||||
let password = ref('');
|
|
||||||
let keepLogin = ref(true);
|
|
||||||
|
|
||||||
const darkMode = computed({
|
|
||||||
get(): boolean {
|
|
||||||
return Dark.isActive;
|
|
||||||
},
|
|
||||||
set(value: boolean): void {
|
|
||||||
Dark.set(value);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
async function onSubmit(): Promise<void> {
|
|
||||||
try {
|
|
||||||
const { data } = await axios.post('/api/accounts/login', {
|
|
||||||
user: username.value,
|
|
||||||
password: password.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
session.setToken({
|
|
||||||
token: data.token,
|
|
||||||
keepLogin: keepLogin.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
quasar.notify({
|
|
||||||
message: t('login.loginSuccess'),
|
|
||||||
type: 'positive',
|
|
||||||
});
|
|
||||||
|
|
||||||
await router.push({ path: '/dashboard' });
|
|
||||||
} catch (error) {
|
|
||||||
if (axios.isAxiosError(error)) {
|
|
||||||
const errorCode = error.response && error.response.status;
|
|
||||||
if (errorCode === 401) {
|
|
||||||
quasar.notify({
|
|
||||||
message: t('login.loginError'),
|
|
||||||
type: 'negative',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
quasar.notify({
|
|
||||||
message: t('errors.statusInternalServerError'),
|
|
||||||
type: 'negative',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
#login {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login {
|
|
||||||
width: 400px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,66 +0,0 @@
|
||||||
import { jest, describe, expect, it } from '@jest/globals';
|
|
||||||
import { mount } from '@vue/test-utils';
|
|
||||||
import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-unit-jest';
|
|
||||||
import { i18n } from 'src/boot/i18n';
|
|
||||||
import { Notify } from 'quasar';
|
|
||||||
import axios from 'axios';
|
|
||||||
import Login from '../Login.vue';
|
|
||||||
|
|
||||||
// Specify here Quasar config you'll need to test your component
|
|
||||||
installQuasarPlugin({
|
|
||||||
plugins: {
|
|
||||||
Notify
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const routerPushMock = jest.fn();
|
|
||||||
|
|
||||||
jest.mock('vue-router', () => ({
|
|
||||||
useRouter: () => ({
|
|
||||||
push: routerPushMock,
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
describe('Login', () => {
|
|
||||||
it('should successfully set the token into session', async () => {
|
|
||||||
const wrapper = mount(Login, {
|
|
||||||
global: {
|
|
||||||
plugins: [i18n]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const { vm } = wrapper;
|
|
||||||
|
|
||||||
jest.spyOn(axios, 'post').mockResolvedValue({ data: { token: 'token' } });
|
|
||||||
jest.spyOn(vm.quasar, 'notify')
|
|
||||||
|
|
||||||
expect(vm.session.getToken()).toEqual('');
|
|
||||||
|
|
||||||
await vm.onSubmit();
|
|
||||||
|
|
||||||
expect(vm.session.getToken()).toEqual('token');
|
|
||||||
expect(vm.quasar.notify).toHaveBeenCalledWith(expect.objectContaining(
|
|
||||||
{ 'type': 'positive' }
|
|
||||||
));
|
|
||||||
vm.session.destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not set the token into session if any error occurred', async () => {
|
|
||||||
const wrapper = mount(Login, {
|
|
||||||
global: {
|
|
||||||
plugins: [i18n]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const { vm } = wrapper;
|
|
||||||
|
|
||||||
jest.spyOn(axios, 'post').mockRejectedValue(new Error('error'));
|
|
||||||
jest.spyOn(vm.quasar, 'notify')
|
|
||||||
|
|
||||||
expect(vm.session.getToken()).toEqual('');
|
|
||||||
|
|
||||||
await vm.onSubmit();
|
|
||||||
|
|
||||||
expect(vm.quasar.notify).toHaveBeenCalledWith(expect.objectContaining(
|
|
||||||
{ 'type': 'negative' }
|
|
||||||
));
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,19 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center">
|
|
||||||
<div>
|
|
||||||
<div style="font-size: 30vh">404</div>
|
|
||||||
|
|
||||||
<div class="text-h2" style="opacity: 0.4">Oops. Nothing here...</div>
|
|
||||||
|
|
||||||
<q-btn class="q-mt-xl" color="white" text-color="blue" unelevated to="/" label="Go Home" no-caps />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'Error404',
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,7 +0,0 @@
|
||||||
// Forces TS to apply `@quasar/app` augmentations of `quasar` package
|
|
||||||
// Removing this would break `quasar/wrappers` imports as those typings are declared
|
|
||||||
// into `@quasar/app`
|
|
||||||
// As a side effect, since `@quasar/app` reference `quasar` to augment it,
|
|
||||||
// this declaration also apply `quasar` own
|
|
||||||
// augmentations (eg. adds `$q` into Vue component context)
|
|
||||||
/// <reference types="@quasar/app" />
|
|
|
@ -1,71 +0,0 @@
|
||||||
import { route } from 'quasar/wrappers';
|
|
||||||
import { createMemoryHistory, createRouter, createWebHashHistory, createWebHistory } from 'vue-router';
|
|
||||||
import routes from './routes';
|
|
||||||
import { i18n } from 'src/boot/i18n';
|
|
||||||
import { useSession } from 'src/composables/useSession';
|
|
||||||
const session = useSession();
|
|
||||||
/*
|
|
||||||
* If not building with SSR mode, you can
|
|
||||||
* directly export the Router instantiation;
|
|
||||||
*
|
|
||||||
* The function below can be async too; either use
|
|
||||||
* async/await or return a Promise which resolves
|
|
||||||
* with the Router instance.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default route(function (/* { store, ssrContext } */) {
|
|
||||||
const createHistory = process.env.SERVER
|
|
||||||
? createMemoryHistory
|
|
||||||
: process.env.VUE_ROUTER_MODE === 'history'
|
|
||||||
? createWebHistory
|
|
||||||
: createWebHashHistory;
|
|
||||||
|
|
||||||
const Router = createRouter({
|
|
||||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
|
||||||
routes,
|
|
||||||
|
|
||||||
// Leave this as is and make changes in quasar.conf.js instead!
|
|
||||||
// quasar.conf.js -> build -> vueRouterMode
|
|
||||||
// quasar.conf.js -> build -> publicPath
|
|
||||||
history: createHistory(process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE),
|
|
||||||
});
|
|
||||||
|
|
||||||
Router.beforeEach((to, from, next) => {
|
|
||||||
const { isLoggedIn } = session;
|
|
||||||
|
|
||||||
if (!isLoggedIn && to.name !== 'Login') {
|
|
||||||
next({ path: '/login', query: { redirect: to.fullPath } });
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Router.afterEach((to) => {
|
|
||||||
interface Meta {
|
|
||||||
title?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { t } = i18n.global;
|
|
||||||
let title = '';
|
|
||||||
|
|
||||||
const parent = to.matched[1];
|
|
||||||
if (parent) {
|
|
||||||
const parentMeta: Meta = parent.meta;
|
|
||||||
if (parentMeta && parentMeta.title) {
|
|
||||||
title += t(`pages.${parentMeta.title}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//const childTitle: string = childMeta.title;
|
|
||||||
|
|
||||||
const childMeta: Meta = to.meta;
|
|
||||||
if (childMeta && childMeta.title) {
|
|
||||||
if (title != '') title += ' - ';
|
|
||||||
|
|
||||||
title += t(`pages.${childMeta.title}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.title = title;
|
|
||||||
});
|
|
||||||
|
|
||||||
return Router;
|
|
||||||
});
|
|
|
@ -1,51 +0,0 @@
|
||||||
import { RouteRecordRaw } from 'vue-router';
|
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
|
||||||
{
|
|
||||||
path: '/login',
|
|
||||||
name: 'Login',
|
|
||||||
meta: { title: 'logIn' },
|
|
||||||
component: () => import('../pages/Login/Login.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/',
|
|
||||||
name: 'Main',
|
|
||||||
component: () => import('../layouts/Main.vue'),
|
|
||||||
redirect: { name: 'Dashboard' },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/dashboard',
|
|
||||||
name: 'Dashboard',
|
|
||||||
meta: { title: 'dashboard' },
|
|
||||||
component: () => import('../pages/Dashboard/Dashboard.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/customer',
|
|
||||||
name: 'Customer',
|
|
||||||
meta: { title: 'customers' },
|
|
||||||
component: () => import('../pages/Customer/Customer.vue'),
|
|
||||||
redirect: { name: 'List' },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'list',
|
|
||||||
name: 'List',
|
|
||||||
meta: { title: 'list' },
|
|
||||||
component: () => import('../pages/Customer/List.vue'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
name: 'Card',
|
|
||||||
component: () => import('../pages/Customer/Card/Card.vue'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/:pathMatch(.*)*',
|
|
||||||
name: 'NotFound',
|
|
||||||
component: () => import('../pages/NotFound.vue'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default routes;
|
|
|
@ -1,7 +0,0 @@
|
||||||
// Mocks all files ending in `.vue` showing them as plain Vue instances
|
|
||||||
/* eslint-disable */
|
|
||||||
declare module '*.vue' {
|
|
||||||
import type { DefineComponent } from 'vue';
|
|
||||||
const component: DefineComponent<{}, {}, any>;
|
|
||||||
export default component;
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
videos/*
|
|
||||||
screenshots/*
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"name": "Using fixtures to represent data",
|
|
||||||
"email": "hello@cypress.io",
|
|
||||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
/// <reference types="cypress" />
|
|
||||||
// Use `cy.dataCy` custom command for more robust tests
|
|
||||||
// See https://docs.cypress.io/guides/references/best-practices.html#Selecting-Elements
|
|
||||||
|
|
||||||
// ** This file is an example of how to write Cypress tests, you can safely delete it **
|
|
||||||
|
|
||||||
// This test will pass when run against a clean Quasar project
|
|
||||||
describe('Landing', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.visit('/#/login');
|
|
||||||
});
|
|
||||||
it('should log in', () => {
|
|
||||||
cy.get('input[aria-label="Username"]').type('developer')
|
|
||||||
cy.get('input[aria-label="Password"]').type('nightmare')
|
|
||||||
cy.get('button[type="submit"]').click()
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,31 +0,0 @@
|
||||||
/// <reference types="cypress" />
|
|
||||||
/* eslint-env node */
|
|
||||||
// ***********************************************************
|
|
||||||
// This example plugins/index.js can be used to load plugins
|
|
||||||
//
|
|
||||||
// You can change the location of this file or turn off loading
|
|
||||||
// the plugins file with the 'pluginsFile' configuration option.
|
|
||||||
//
|
|
||||||
// You can read more here:
|
|
||||||
// https://on.cypress.io/plugins-guide
|
|
||||||
// ***********************************************************
|
|
||||||
|
|
||||||
// This function is called when a project is opened or re-opened (e.g. due to
|
|
||||||
// the project's config changing)
|
|
||||||
|
|
||||||
// cypress/plugins/index.js
|
|
||||||
|
|
||||||
const { injectDevServer } = require('@quasar/quasar-app-extension-testing-e2e-cypress/cct-dev-server');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {Cypress.PluginConfig}
|
|
||||||
*/
|
|
||||||
module.exports = async (on, config) => {
|
|
||||||
// Enable component testing, you can safely remove this
|
|
||||||
// if you don't plan to use Cypress for unit tests
|
|
||||||
// if (config.testingType === 'component') {
|
|
||||||
// await injectDevServer(on, config);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return config;
|
|
||||||
};
|
|
|
@ -1,30 +0,0 @@
|
||||||
// ***********************************************
|
|
||||||
// This example commands.js shows you how to
|
|
||||||
// create various custom commands and overwrite
|
|
||||||
// existing commands.
|
|
||||||
//
|
|
||||||
// For more comprehensive examples of custom
|
|
||||||
// commands please read more here:
|
|
||||||
// https://on.cypress.io/custom-commands
|
|
||||||
// ***********************************************
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// -- This is a parent command --
|
|
||||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// -- This is a child command --
|
|
||||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// -- This is a dual command --
|
|
||||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// -- This is will overwrite an existing command --
|
|
||||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
|
||||||
|
|
||||||
// DO NOT REMOVE
|
|
||||||
// Imports Quasar Cypress AE predefined commands
|
|
||||||
import { registerCommands } from '@quasar/quasar-app-extension-testing-e2e-cypress';
|
|
||||||
registerCommands();
|
|
|
@ -1,16 +0,0 @@
|
||||||
// ***********************************************************
|
|
||||||
// This example support/index.js is processed and
|
|
||||||
// loaded automatically before your e2e test files.
|
|
||||||
//
|
|
||||||
// This is a great place to put global configuration and
|
|
||||||
// behavior that modifies Cypress.
|
|
||||||
//
|
|
||||||
// You can change the location of this file or turn off
|
|
||||||
// automatically serving support files with the
|
|
||||||
// 'supportFile' configuration option.
|
|
||||||
//
|
|
||||||
// You can read more here:
|
|
||||||
// https://on.cypress.io/configuration
|
|
||||||
// ***********************************************************
|
|
||||||
|
|
||||||
import './commands';
|
|
|
@ -1,46 +0,0 @@
|
||||||
// ***********************************************************
|
|
||||||
// This example support/unit.js is processed and
|
|
||||||
// loaded automatically before your unit test files.
|
|
||||||
//
|
|
||||||
// This is a great place to put global configuration and
|
|
||||||
// behavior that modifies Cypress.
|
|
||||||
//
|
|
||||||
// You can change the location of this file or turn off
|
|
||||||
// automatically serving support files with the
|
|
||||||
// 'supportFile' configuration option.
|
|
||||||
//
|
|
||||||
// You can read more here:
|
|
||||||
// https://on.cypress.io/configuration
|
|
||||||
// ***********************************************************
|
|
||||||
|
|
||||||
import './commands';
|
|
||||||
|
|
||||||
// Change this if you have a different entrypoint for the main scss.
|
|
||||||
import 'src/css/app.scss';
|
|
||||||
// Quasar styles
|
|
||||||
import 'quasar/src/css/index.sass';
|
|
||||||
|
|
||||||
// ICON SETS
|
|
||||||
// If you use multiple or different icon-sets then the default, be sure to import them here.
|
|
||||||
import 'quasar/dist/icon-set/material-icons.umd.prod';
|
|
||||||
import '@quasar/extras/material-icons/material-icons.css';
|
|
||||||
|
|
||||||
import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-e2e-cypress';
|
|
||||||
import { config } from '@vue/test-utils';
|
|
||||||
import { Dialog } from 'quasar';
|
|
||||||
|
|
||||||
// Example to import i18n from boot and use as plugin
|
|
||||||
// import { i18n } from 'src/boot/i18n';
|
|
||||||
|
|
||||||
// You can modify the global config here for all tests or pass in the configuration per test
|
|
||||||
// For example use the actual i18n instance or mock it
|
|
||||||
// config.global.plugins.push(i18n);
|
|
||||||
config.global.mocks = {
|
|
||||||
$t: () => '',
|
|
||||||
};
|
|
||||||
|
|
||||||
// Overwrite the transition and transition-group stubs which are stubbed by test-utils by default.
|
|
||||||
// We do want transitions to show when doing visual testing :)
|
|
||||||
config.global.stubs = {};
|
|
||||||
|
|
||||||
installQuasarPlugin({ plugins: { Dialog } });
|
|
|
@ -1,26 +0,0 @@
|
||||||
<script>
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { Dialog } from 'quasar';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'DialogWrapper',
|
|
||||||
props: {
|
|
||||||
component: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
componentProps: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
setup(props) {
|
|
||||||
Dialog.create({
|
|
||||||
component: props.component,
|
|
||||||
|
|
||||||
// props forwarded to your custom component
|
|
||||||
componentProps: props.componentProps,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,20 +0,0 @@
|
||||||
<template>
|
|
||||||
<q-layout>
|
|
||||||
<component :is="component" v-bind="$attrs" />
|
|
||||||
</q-layout>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'LayoutContainer',
|
|
||||||
inheritAttrs: false,
|
|
||||||
props: {
|
|
||||||
component: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,10 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
extends: [
|
|
||||||
// Removes 'no-undef' lint errors for Jest global functions (`describe`, `it`, etc),
|
|
||||||
// add Jest-specific lint rules and Jest plugin
|
|
||||||
// See https://github.com/jest-community/eslint-plugin-jest#recommended
|
|
||||||
'plugin:jest/recommended',
|
|
||||||
// Uncomment following line to apply style rules
|
|
||||||
// 'plugin:jest/style',
|
|
||||||
],
|
|
||||||
};
|
|
|
@ -1 +0,0 @@
|
||||||
coverage/*
|
|
|
@ -1,41 +0,0 @@
|
||||||
import { describe, expect, it } from '@jest/globals';
|
|
||||||
import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-unit-jest';
|
|
||||||
import { mount, shallowMount } from '@vue/test-utils';
|
|
||||||
import { QBtn } from 'quasar';
|
|
||||||
import MyButton from './demo/MyButton.vue';
|
|
||||||
|
|
||||||
// Specify here Quasar config you'll need to test your component
|
|
||||||
installQuasarPlugin();
|
|
||||||
|
|
||||||
describe('MyButton', () => {
|
|
||||||
it('has increment method', () => {
|
|
||||||
const wrapper = mount(MyButton);
|
|
||||||
const { vm } = wrapper;
|
|
||||||
|
|
||||||
expect(typeof vm.increment).toBe('function');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can check the inner text content', () => {
|
|
||||||
const wrapper = mount(MyButton);
|
|
||||||
const { vm } = wrapper;
|
|
||||||
|
|
||||||
expect(vm.$el.textContent).toContain('rocket muffin');
|
|
||||||
expect(wrapper.find('.content').text()).toContain('rocket muffin');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets the correct default data', () => {
|
|
||||||
const wrapper = mount(MyButton);
|
|
||||||
const { vm } = wrapper;
|
|
||||||
|
|
||||||
expect(typeof vm.counter).toBe('number');
|
|
||||||
expect(vm.counter).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('correctly updates counter when button is pressed', async () => {
|
|
||||||
const wrapper = shallowMount(MyButton);
|
|
||||||
const { vm } = wrapper;
|
|
||||||
const button = wrapper.findComponent(QBtn);
|
|
||||||
await button.trigger('click');
|
|
||||||
expect(vm.counter).toBe(1);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,18 +0,0 @@
|
||||||
import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-unit-jest';
|
|
||||||
import { describe, expect, it } from '@jest/globals';
|
|
||||||
import { mount } from '@vue/test-utils';
|
|
||||||
import MyDialog from './demo/MyDialog.vue';
|
|
||||||
|
|
||||||
installQuasarPlugin();
|
|
||||||
|
|
||||||
describe('MyDialog', () => {
|
|
||||||
it('should mount MyDialog', () => {
|
|
||||||
const wrapper = mount(MyDialog, {
|
|
||||||
data: () => ({
|
|
||||||
isDialogOpen: true,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(wrapper.exists()).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,23 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
const props = defineProps({
|
|
||||||
incrementStep: {
|
|
||||||
type: Number,
|
|
||||||
default: 1,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const counter = ref(0);
|
|
||||||
const input = ref('rocket muffin');
|
|
||||||
function increment() {
|
|
||||||
counter.value += props.incrementStep;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<p class="content">{{ input }}</p>
|
|
||||||
<span>{{ counter }}</span>
|
|
||||||
<q-btn class="button" @click="increment()"></q-btn>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
const isDialogOpen = ref(false);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<q-dialog v-model="isDialogOpen">
|
|
||||||
<q-card>
|
|
||||||
<q-card-section>Custom dialog which should be tested</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
</q-dialog>
|
|
||||||
</template>
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "@quasar/app/tsconfig-preset",
|
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": "."
|
|
||||||
}
|
|
||||||
}
|
|