mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 21:30:31 +00:00
Migrate from Vue to React framework.
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
|
||||
}
|
||||
}],
|
||||
"stage-2"
|
||||
],
|
||||
"plugins": [
|
||||
"transform-vue-jsx",
|
||||
"transform-runtime",
|
||||
[
|
||||
"component",
|
||||
{
|
||||
"libraryName": "element-ui",
|
||||
"styleLibraryName": "~node_modules/element-theme-chalk/src",
|
||||
"ext": ".scss"
|
||||
}
|
||||
]
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": ["env", "stage-2"],
|
||||
"plugins": ["transform-vue-jsx", "istanbul"],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,7 +0,0 @@
|
||||
/build/
|
||||
/config/
|
||||
/dist/
|
||||
/*.js
|
||||
{{#unit}}
|
||||
/test/unit/coverage/
|
||||
{{/unit}}
|
||||
@@ -1,53 +0,0 @@
|
||||
// https://eslint.org/docs/user-guide/configuring
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
|
||||
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
|
||||
extends: ['plugin:vue/essential', 'airbnb-base'],
|
||||
|
||||
// required to lint *.vue files
|
||||
plugins: [
|
||||
'vue'
|
||||
],
|
||||
// check if imports actually resolve
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
webpack: {
|
||||
config: 'build/webpack.base.conf.js'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// add your custom rules here
|
||||
rules: {
|
||||
// don't require .vue extension when importing
|
||||
'import/extensions': ['error', 'always', {
|
||||
js: 'never',
|
||||
vue: 'never'
|
||||
}],
|
||||
// disallow reassignment of function parameters
|
||||
// disallow parameter object manipulation except for specific exclusions
|
||||
'no-param-reassign': ['error', {
|
||||
props: true,
|
||||
ignorePropertyModificationsFor: [
|
||||
'state', // for vuex state
|
||||
's',
|
||||
'acc', // for reduce accumulators
|
||||
'e' // for e.returnvalue
|
||||
]
|
||||
}],
|
||||
// allow optionalDependencies
|
||||
'import/no-extraneous-dependencies': ['error', {
|
||||
optionalDependencies: ['test/unit/index.js']
|
||||
}],
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||
}
|
||||
}
|
||||
31
client/.gitignore
vendored
31
client/.gitignore
vendored
@@ -1,16 +1,23 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/dist/
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
/test/unit/coverage/
|
||||
/test/e2e/reports/
|
||||
selenium-debug.log
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||
|
||||
module.exports = {
|
||||
"plugins": {
|
||||
"postcss-import": {},
|
||||
"postcss-url": {},
|
||||
// to edit target browsers: use "browserslist" field in package.json
|
||||
"autoprefixer": {}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,68 @@
|
||||
# {{ name }}
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
> {{ description }}
|
||||
## Available Scripts
|
||||
|
||||
## Build Setup
|
||||
In the project directory, you can run:
|
||||
|
||||
``` bash
|
||||
# install dependencies
|
||||
npm install
|
||||
### `npm start`
|
||||
|
||||
# serve with hot reload at localhost:8080
|
||||
npm run dev
|
||||
Runs the app in the development mode.<br />
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
# build for production with minification
|
||||
npm run build
|
||||
The page will reload if you make edits.<br />
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
# build for production and view the bundle analyzer report
|
||||
npm run build --report
|
||||
{{#unit}}
|
||||
### `npm test`
|
||||
|
||||
# run unit tests
|
||||
npm run unit
|
||||
{{/unit}}
|
||||
{{#e2e}}
|
||||
Launches the test runner in the interactive watch mode.<br />
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
# run e2e tests
|
||||
npm run e2e
|
||||
{{/e2e}}
|
||||
{{#if_or unit e2e}}
|
||||
### `npm run build`
|
||||
|
||||
# run all tests
|
||||
npm test
|
||||
{{/if_or}}
|
||||
```
|
||||
Builds the app for production to the `build` folder.<br />
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
|
||||
The build is minified and the filenames include the hashes.<br />
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `npm run eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
|
||||
|
||||
### `npm run build` fails to minify
|
||||
|
||||
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
'use strict'
|
||||
require('./check-versions')()
|
||||
|
||||
process.env.NODE_ENV = 'production'
|
||||
|
||||
const ora = require('ora')
|
||||
const rm = require('rimraf')
|
||||
const path = require('path')
|
||||
const chalk = require('chalk')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const webpackConfig = require('./webpack.prod.conf')
|
||||
|
||||
const spinner = ora('building for production...')
|
||||
spinner.start()
|
||||
|
||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
||||
if (err) throw err
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
spinner.stop()
|
||||
if (err) throw err
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false, // if you are using ts-loader, setting this to true will make typescript errors show up during build
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n\n')
|
||||
|
||||
if (stats.hasErrors()) {
|
||||
console.log(chalk.red(' Build failed with errors.\n'))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(chalk.cyan(' Build complete.\n'))
|
||||
console.log(chalk.yellow(
|
||||
' Tip: built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
))
|
||||
})
|
||||
})
|
||||
@@ -1,54 +0,0 @@
|
||||
'use strict'
|
||||
const chalk = require('chalk')
|
||||
const semver = require('semver')
|
||||
const packageConfig = require('../package.json')
|
||||
const shell = require('shelljs')
|
||||
|
||||
function exec (cmd) {
|
||||
return require('child_process').execSync(cmd).toString().trim()
|
||||
}
|
||||
|
||||
const versionRequirements = [
|
||||
{
|
||||
name: 'node',
|
||||
currentVersion: semver.clean(process.version),
|
||||
versionRequirement: packageConfig.engines.node
|
||||
}
|
||||
]
|
||||
|
||||
if (shell.which('npm')) {
|
||||
versionRequirements.push({
|
||||
name: 'npm',
|
||||
currentVersion: exec('npm --version'),
|
||||
versionRequirement: packageConfig.engines.npm
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
const warnings = []
|
||||
|
||||
for (let i = 0; i < versionRequirements.length; i++) {
|
||||
const mod = versionRequirements[i]
|
||||
|
||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
||||
warnings.push(mod.name + ': ' +
|
||||
chalk.red(mod.currentVersion) + ' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (warnings.length) {
|
||||
console.log('')
|
||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
||||
console.log()
|
||||
|
||||
for (let i = 0; i < warnings.length; i++) {
|
||||
const warning = warnings[i]
|
||||
console.log(' ' + warning)
|
||||
}
|
||||
|
||||
console.log()
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
@@ -1,101 +0,0 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const config = require('../config')
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const packageConfig = require('../package.json')
|
||||
|
||||
exports.assetsPath = function (_path) {
|
||||
const assetsSubDirectory = process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsSubDirectory
|
||||
: config.dev.assetsSubDirectory
|
||||
|
||||
return path.posix.join(assetsSubDirectory, _path)
|
||||
}
|
||||
|
||||
exports.cssLoaders = function (options) {
|
||||
options = options || {}
|
||||
|
||||
const cssLoader = {
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: options.sourceMap
|
||||
}
|
||||
}
|
||||
|
||||
const postcssLoader = {
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
sourceMap: options.sourceMap
|
||||
}
|
||||
}
|
||||
|
||||
// generate loader string to be used with extract text plugin
|
||||
function generateLoaders (loader, loaderOptions) {
|
||||
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
|
||||
|
||||
if (loader) {
|
||||
loaders.push({
|
||||
loader: loader + '-loader',
|
||||
options: Object.assign({}, loaderOptions, {
|
||||
sourceMap: options.sourceMap
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Extract CSS when that option is specified
|
||||
// (which is the case during production build)
|
||||
if (options.extract) {
|
||||
return ExtractTextPlugin.extract({
|
||||
use: loaders,
|
||||
fallback: 'vue-style-loader'
|
||||
})
|
||||
} else {
|
||||
return ['vue-style-loader'].concat(loaders)
|
||||
}
|
||||
}
|
||||
|
||||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
|
||||
return {
|
||||
css: generateLoaders(),
|
||||
postcss: generateLoaders(),
|
||||
less: generateLoaders('less'),
|
||||
sass: generateLoaders('sass', { indentedSyntax: true }),
|
||||
scss: generateLoaders('sass'),
|
||||
stylus: generateLoaders('stylus'),
|
||||
styl: generateLoaders('stylus')
|
||||
}
|
||||
}
|
||||
|
||||
// Generate loaders for standalone style files (outside of .vue)
|
||||
exports.styleLoaders = function (options) {
|
||||
const output = []
|
||||
const loaders = exports.cssLoaders(options)
|
||||
|
||||
for (const extension in loaders) {
|
||||
const loader = loaders[extension]
|
||||
output.push({
|
||||
test: new RegExp('\\.' + extension + '$'),
|
||||
use: loader
|
||||
})
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
exports.createNotifierCallback = () => {
|
||||
const notifier = require('node-notifier')
|
||||
|
||||
return (severity, errors) => {
|
||||
if (severity !== 'error') return
|
||||
|
||||
const error = errors[0]
|
||||
const filename = error.file && error.file.split('!').pop()
|
||||
|
||||
notifier.notify({
|
||||
title: packageConfig.name,
|
||||
message: severity + ': ' + error.name,
|
||||
subtitle: filename || '',
|
||||
icon: path.join(__dirname, 'logo.png')
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
'use strict'
|
||||
const utils = require('./utils')
|
||||
const config = require('../config')
|
||||
const isProduction = process.env.NODE_ENV === 'production'
|
||||
const sourceMapEnabled = isProduction
|
||||
? config.build.productionSourceMap
|
||||
: config.dev.cssSourceMap
|
||||
|
||||
module.exports = {
|
||||
loaders: utils.cssLoaders({
|
||||
sourceMap: sourceMapEnabled,
|
||||
extract: isProduction
|
||||
}),
|
||||
cssSourceMap: sourceMapEnabled,
|
||||
cacheBusting: config.dev.cacheBusting,
|
||||
transformToRequire: {
|
||||
video: ['src', 'poster'],
|
||||
source: 'src',
|
||||
img: 'src',
|
||||
image: 'xlink:href'
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const utils = require('./utils')
|
||||
const config = require('../config')
|
||||
const vueLoaderConfig = require('./vue-loader.conf')
|
||||
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
const createLintingRule = () => ({
|
||||
test: /\.(js|vue)$/,
|
||||
loader: 'eslint-loader',
|
||||
enforce: 'pre',
|
||||
include: [resolve('src'), resolve('test')],
|
||||
options: {
|
||||
formatter: require('eslint-friendly-formatter'),
|
||||
emitWarning: !config.dev.showEslintErrorsInOverlay
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = {
|
||||
context: path.resolve(__dirname, '../'),
|
||||
entry: {
|
||||
app: './src/main.js'
|
||||
},
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: '[name].js',
|
||||
publicPath: process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsPublicPath
|
||||
: config.dev.assetsPublicPath
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.vue', '.json'],
|
||||
alias: {
|
||||
'@': resolve('src'),
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
...(config.dev.useEslint ? [createLintingRule()] : []),
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
options: vueLoaderConfig
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('img/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('media/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
node: {
|
||||
// prevent webpack from injecting useless setImmediate polyfill because Vue
|
||||
// source contains it (although only uses it if it's native).
|
||||
setImmediate: false,
|
||||
// prevent webpack from injecting mocks to Node native modules
|
||||
// that does not make sense for the client
|
||||
dgram: 'empty',
|
||||
fs: 'empty',
|
||||
net: 'empty',
|
||||
tls: 'empty',
|
||||
child_process: 'empty'
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
'use strict'
|
||||
const utils = require('./utils')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const merge = require('webpack-merge')
|
||||
const path = require('path')
|
||||
const baseWebpackConfig = require('./webpack.base.conf')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
|
||||
const portfinder = require('portfinder')
|
||||
|
||||
const HOST = process.env.HOST
|
||||
const PORT = process.env.PORT && Number(process.env.PORT)
|
||||
|
||||
const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
|
||||
},
|
||||
// cheap-module-eval-source-map is faster for development
|
||||
devtool: config.dev.devtool,
|
||||
|
||||
// these devServer options should be customized in /config/index.js
|
||||
devServer: {
|
||||
clientLogLevel: 'warning',
|
||||
historyApiFallback: {
|
||||
rewrites: [
|
||||
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
|
||||
],
|
||||
},
|
||||
hot: true,
|
||||
contentBase: false, // since we use CopyWebpackPlugin.
|
||||
compress: true,
|
||||
host: HOST || config.dev.host,
|
||||
port: PORT || config.dev.port,
|
||||
open: config.dev.autoOpenBrowser,
|
||||
overlay: config.dev.errorOverlay
|
||||
? { warnings: false, errors: true }
|
||||
: false,
|
||||
publicPath: config.dev.assetsPublicPath,
|
||||
proxy: config.dev.proxyTable,
|
||||
quiet: true, // necessary for FriendlyErrorsPlugin
|
||||
watchOptions: {
|
||||
poll: config.dev.poll,
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': require('../config/dev.env')
|
||||
}),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
// https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: 'index.html',
|
||||
inject: true
|
||||
}),
|
||||
// copy custom static assets
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.resolve(__dirname, '../static'),
|
||||
to: config.dev.assetsSubDirectory,
|
||||
ignore: ['.*']
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
|
||||
module.exports = new Promise((resolve, reject) => {
|
||||
portfinder.basePort = process.env.PORT || config.dev.port
|
||||
portfinder.getPort((err, port) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
// publish the new Port, necessary for e2e tests
|
||||
process.env.PORT = port
|
||||
// add port to devServer config
|
||||
devWebpackConfig.devServer.port = port
|
||||
|
||||
// Add FriendlyErrorsPlugin
|
||||
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
|
||||
compilationSuccessInfo: {
|
||||
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
|
||||
},
|
||||
onErrors: config.dev.notifyOnErrors
|
||||
? utils.createNotifierCallback()
|
||||
: undefined
|
||||
}))
|
||||
|
||||
resolve(devWebpackConfig)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -1,149 +0,0 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const utils = require('./utils')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const merge = require('webpack-merge')
|
||||
const baseWebpackConfig = require('./webpack.base.conf')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
|
||||
|
||||
const env = process.env.NODE_ENV === 'testing'
|
||||
? require('../config/test.env')
|
||||
: require('../config/prod.env')
|
||||
|
||||
const webpackConfig = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
rules: utils.styleLoaders({
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
extract: true,
|
||||
usePostCSS: true
|
||||
})
|
||||
},
|
||||
devtool: config.build.productionSourceMap ? config.build.devtool : false,
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: utils.assetsPath('js/[name].[chunkhash].js'),
|
||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
|
||||
},
|
||||
plugins: [
|
||||
// http://vuejs.github.io/vue-loader/en/workflow/production.html
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env
|
||||
}),
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
},
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
parallel: true
|
||||
}),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin({
|
||||
filename: utils.assetsPath('css/[name].[contenthash].css'),
|
||||
// Setting the following option to `false` will not extract CSS from codesplit chunks.
|
||||
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
|
||||
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
|
||||
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
|
||||
allChunks: true,
|
||||
}),
|
||||
// Compress extracted CSS. We are using this plugin so that possible
|
||||
// duplicated CSS from different components can be deduped.
|
||||
new OptimizeCSSPlugin({
|
||||
cssProcessorOptions: config.build.productionSourceMap
|
||||
? { safe: true, map: { inline: false } }
|
||||
: { safe: true }
|
||||
}),
|
||||
// generate dist index.html with correct asset hash for caching.
|
||||
// you can customize output by editing /index.html
|
||||
// see https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: process.env.NODE_ENV === 'testing'
|
||||
? 'index.html'
|
||||
: config.build.index,
|
||||
template: 'index.html',
|
||||
inject: true,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true
|
||||
// more options:
|
||||
// https://github.com/kangax/html-minifier#options-quick-reference
|
||||
},
|
||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||
chunksSortMode: 'dependency'
|
||||
}),
|
||||
// keep module.id stable when vendor modules does not change
|
||||
new webpack.HashedModuleIdsPlugin(),
|
||||
// enable scope hoisting
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
// split vendor js into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks (module) {
|
||||
// any required modules inside node_modules are extracted to vendor
|
||||
return (
|
||||
module.resource &&
|
||||
/\.js$/.test(module.resource) &&
|
||||
module.resource.indexOf(
|
||||
path.join(__dirname, '../node_modules')
|
||||
) === 0
|
||||
)
|
||||
}
|
||||
}),
|
||||
// extract webpack runtime and module manifest to its own file in order to
|
||||
// prevent vendor hash from being updated whenever app bundle is updated
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'manifest',
|
||||
minChunks: Infinity
|
||||
}),
|
||||
// This instance extracts shared chunks from code splitted chunks and bundles them
|
||||
// in a separate chunk, similar to the vendor chunk
|
||||
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'app',
|
||||
async: 'vendor-async',
|
||||
children: true,
|
||||
minChunks: 3
|
||||
}),
|
||||
|
||||
// copy custom static assets
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
from: path.resolve(__dirname, '../static'),
|
||||
to: config.build.assetsSubDirectory,
|
||||
ignore: ['.*']
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
|
||||
if (config.build.productionGzip) {
|
||||
const CompressionWebpackPlugin = require('compression-webpack-plugin')
|
||||
|
||||
webpackConfig.plugins.push(
|
||||
new CompressionWebpackPlugin({
|
||||
asset: '[path].gz[query]',
|
||||
algorithm: 'gzip',
|
||||
test: new RegExp(
|
||||
'\\.(' +
|
||||
config.build.productionGzipExtensions.join('|') +
|
||||
')$'
|
||||
),
|
||||
threshold: 10240,
|
||||
minRatio: 0.8
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (config.build.bundleAnalyzerReport) {
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
||||
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
|
||||
}
|
||||
|
||||
module.exports = webpackConfig
|
||||
@@ -1,32 +0,0 @@
|
||||
'use strict'
|
||||
// This is the webpack config used for unit tests.
|
||||
|
||||
const utils = require('./utils')
|
||||
const webpack = require('webpack')
|
||||
const merge = require('webpack-merge')
|
||||
const baseWebpackConfig = require('./webpack.base.conf')
|
||||
|
||||
const webpackConfig = merge(baseWebpackConfig, {
|
||||
// use inline sourcemap for karma-sourcemap-loader
|
||||
module: {
|
||||
rules: utils.styleLoaders()
|
||||
},
|
||||
devtool: '#inline-source-map',
|
||||
resolveLoader: {
|
||||
alias: {
|
||||
// necessary to to make lang="scss" work in test when using vue-loader's ?inject option
|
||||
// see discussion at https://github.com/vuejs/vue-loader/issues/724
|
||||
'scss-loader': 'sass-loader'
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': require('../config/test.env')
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
// no need for app entry during tests
|
||||
delete webpackConfig.entry
|
||||
|
||||
module.exports = webpackConfig
|
||||
@@ -1,7 +0,0 @@
|
||||
'use strict'
|
||||
const merge = require('webpack-merge')
|
||||
const prodEnv = require('./prod.env')
|
||||
|
||||
module.exports = merge(prodEnv, {
|
||||
NODE_ENV: '"development"'
|
||||
})
|
||||
@@ -1,74 +0,0 @@
|
||||
'use strict'
|
||||
// Template version: {{ template_version }}
|
||||
// see http://vuejs-templates.github.io/webpack for documentation.
|
||||
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
dev: {
|
||||
// Paths
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
proxyTable: {},
|
||||
|
||||
// Various Dev Server settings
|
||||
host: 'localhost', // can be overwritten by process.env.HOST
|
||||
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
||||
autoOpenBrowser: false,
|
||||
errorOverlay: true,
|
||||
notifyOnErrors: true,
|
||||
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
|
||||
|
||||
// If true, your code will be linted during bundling and
|
||||
// linting errors and warnings will be shown in the console.
|
||||
useEslint: false,
|
||||
// If true, eslint errors and warnings will also be shown in the error overlay
|
||||
// in the browser.
|
||||
showEslintErrorsInOverlay: false,
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
// https://webpack.js.org/configuration/devtool/#development
|
||||
devtool: 'cheap-module-eval-source-map',
|
||||
|
||||
// If you have problems debugging vue-files in devtools,
|
||||
// set this to false - it *may* help
|
||||
// https://vue-loader.vuejs.org/en/options.html#cachebusting
|
||||
cacheBusting: true,
|
||||
|
||||
cssSourceMap: true
|
||||
},
|
||||
|
||||
build: {
|
||||
// Template for index.html
|
||||
index: path.resolve(__dirname, '../dist/index.html'),
|
||||
|
||||
// Paths
|
||||
assetsRoot: path.resolve(__dirname, '../dist'),
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
productionSourceMap: true,
|
||||
// https://webpack.js.org/configuration/devtool/#production
|
||||
devtool: '#source-map',
|
||||
|
||||
// Gzip off by default as many popular static hosts such as
|
||||
// Surge or Netlify already gzip all static assets for you.
|
||||
// Before setting to `true`, make sure to:
|
||||
// npm install --save-dev compression-webpack-plugin
|
||||
productionGzip: false,
|
||||
productionGzipExtensions: ['js', 'css'],
|
||||
|
||||
// Run the build command with an extra argument to
|
||||
// View the bundle analyzer report after build finishes:
|
||||
// `npm run build --report`
|
||||
// Set to `true` or `false` to always turn it on or off
|
||||
bundleAnalyzerReport: process.env.npm_config_report
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
'use strict'
|
||||
module.exports = {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
'use strict'
|
||||
const merge = require('webpack-merge')
|
||||
const devEnv = require('./dev.env')
|
||||
|
||||
module.exports = merge(devEnv, {
|
||||
NODE_ENV: '"testing"'
|
||||
})
|
||||
@@ -1,12 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>{{ name }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
7
client/jsconfig.json
Normal file
7
client/jsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
21656
client/package-lock.json
generated
21656
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,105 +1,45 @@
|
||||
{
|
||||
"name": "Ratteb",
|
||||
"version": "1.0.0",
|
||||
"description": "Ratteb, sales and accounting software",
|
||||
"author": "Ahmed Bouhuolia <a.bouhuolia@gmail.com>",
|
||||
"name": "client",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
||||
"start": "npm run dev",
|
||||
"unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
|
||||
"e2e": "node test/e2e/runner.js",
|
||||
"test": "{{#unit}}npm run unit{{/unit}}{{#unit}}{{#e2e}} && {{/e2e}}{{/unit}}{{#e2e}}npm run e2e{{/e2e}}",
|
||||
"lint": "eslint --ext .js,.vue src{{#unit}} test/unit{{/unit}}{{#e2e}} test/e2e/specs{{/e2e}}",
|
||||
"build": "node build/build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.0",
|
||||
"element-ui": "^2.11.1",
|
||||
"vue": "^2.5.2",
|
||||
"vue-axios": "^2.1.4",
|
||||
"vue-router": "^3.0.1",
|
||||
"vuex": "^3.1.1",
|
||||
"vuex-i18n": "^1.13.1",
|
||||
"element-theme-chalk": "^2.12.0"
|
||||
"@blueprintjs/core": "^3.23.1",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.4.0",
|
||||
"@testing-library/user-event": "^7.2.1",
|
||||
"axios": "^0.19.2",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-hook-form": "^4.9.4",
|
||||
"react-redux": "^7.1.3",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-scripts": "3.4.0",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"yup": "^0.28.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.1.2",
|
||||
"babel-core": "^6.22.1",
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-component": "^1.1.1",
|
||||
"babel-plugin-istanbul": "^4.1.1",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"babel-plugin-transform-runtime": "^6.22.0",
|
||||
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
||||
"babel-preset-env": "^1.3.2",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"babel-register": "^6.22.0",
|
||||
"chai": "^4.1.2",
|
||||
"chalk": "^2.0.1",
|
||||
"chromedriver": "^2.27.2",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"cross-env": "^5.0.1",
|
||||
"cross-spawn": "^5.0.1",
|
||||
"css-loader": "^0.28.0",
|
||||
"eslint": "^4.15.0",
|
||||
"eslint-config-airbnb-base": "^11.3.0",
|
||||
"eslint-friendly-formatter": "^3.0.0",
|
||||
"eslint-import-resolver-webpack": "^0.8.3",
|
||||
"eslint-loader": "^1.7.1",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-vue": "^4.0.0",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^1.1.4",
|
||||
"friendly-errors-webpack-plugin": "^1.6.1",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"inject-loader": "^3.0.0",
|
||||
"karma": "^1.4.1",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-phantomjs-launcher": "^1.0.2",
|
||||
"karma-phantomjs-shim": "^1.4.0",
|
||||
"karma-sinon-chai": "^1.3.1",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.31",
|
||||
"karma-webpack": "^2.0.2",
|
||||
"mocha": "^3.2.0",
|
||||
"nightwatch": "^0.9.12",
|
||||
"node-notifier": "^5.1.2",
|
||||
"node-sass": "^4.12.0",
|
||||
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
||||
"ora": "^1.2.0",
|
||||
"phantomjs-prebuilt": "^2.1.14",
|
||||
"portfinder": "^1.0.13",
|
||||
"postcss-import": "^11.0.0",
|
||||
"postcss-loader": "^2.0.8",
|
||||
"postcss-url": "^7.2.1",
|
||||
"rimraf": "^2.6.0",
|
||||
"sass-loader": "^7.2.0",
|
||||
"selenium-server": "^3.0.1",
|
||||
"semver": "^5.3.0",
|
||||
"shelljs": "^0.7.6",
|
||||
"sinon": "^4.0.0",
|
||||
"sinon-chai": "^2.8.0",
|
||||
"uglifyjs-webpack-plugin": "^1.1.1",
|
||||
"url-loader": "^0.5.8",
|
||||
"vue-loader": "^13.3.0",
|
||||
"vue-style-loader": "^3.0.1",
|
||||
"vue-template-compiler": "^2.5.2",
|
||||
"webpack": "^3.6.0",
|
||||
"webpack-bundle-analyzer": "^2.9.0",
|
||||
"webpack-dev-server": "^2.9.1",
|
||||
"webpack-merge": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
"redux-devtools": "^3.5.0"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
client/public/favicon.ico
Normal file
BIN
client/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
43
client/public/index.html
Normal file
43
client/public/index.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
BIN
client/public/logo192.png
Normal file
BIN
client/public/logo192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
BIN
client/public/logo512.png
Normal file
BIN
client/public/logo512.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
25
client/public/manifest.json
Normal file
25
client/public/manifest.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
3
client/public/robots.txt
Normal file
3
client/public/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
@@ -1,19 +0,0 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App',
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import 'style/style.scss';
|
||||
|
||||
body{
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
2
client/src/actions/accounts/index.js
Normal file
2
client/src/actions/accounts/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const FETCH_ACCOUNTS_CHART = 'FETCH_ACCOUNTS_CHART';
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
18
client/src/components/DashboardContent/index.js
Normal file
18
client/src/components/DashboardContent/index.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import dashboardRoutes from 'routes/dashboard'
|
||||
|
||||
export default function() {
|
||||
return (
|
||||
<Switch>
|
||||
{ dashboardRoutes.map((route, index) => (
|
||||
<Route
|
||||
key={index}
|
||||
path={route.path}
|
||||
exact={route.exact}
|
||||
component={route.component}
|
||||
/>
|
||||
))}
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>\{{ msg }}</h1>
|
||||
<h2>Essential Links</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://vuejs.org"
|
||||
target="_blank"
|
||||
>
|
||||
Core Docs
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://forum.vuejs.org"
|
||||
target="_blank"
|
||||
>
|
||||
Forum
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://chat.vuejs.org"
|
||||
target="_blank"
|
||||
>
|
||||
Community Chat
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://twitter.com/vuejs"
|
||||
target="_blank"
|
||||
>
|
||||
Twitter
|
||||
</a>
|
||||
</li>
|
||||
<br>
|
||||
<li>
|
||||
<a
|
||||
href="http://vuejs-templates.github.io/webpack/"
|
||||
target="_blank"
|
||||
>
|
||||
Docs for This Template
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Ecosystem</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="http://router.vuejs.org/"
|
||||
target="_blank"
|
||||
>
|
||||
vue-router
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="http://vuex.vuejs.org/"
|
||||
target="_blank"
|
||||
>
|
||||
vuex
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="http://vue-loader.vuejs.org/"
|
||||
target="_blank"
|
||||
>
|
||||
vue-loader
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/awesome-vue"
|
||||
target="_blank"
|
||||
>
|
||||
awesome-vue
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
data() {
|
||||
return {
|
||||
msg: 'Welcome to Your Vue.js App',
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1, h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
9
client/src/components/Sideabr/SidebarContainer.js
Normal file
9
client/src/components/Sideabr/SidebarContainer.js
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
export default function() {
|
||||
return (
|
||||
<div class="sidebar" id="sidebar">
|
||||
|
||||
</div>
|
||||
)
|
||||
};
|
||||
19
client/src/components/Sideabr/SidebarHead.js
Normal file
19
client/src/components/Sideabr/SidebarHead.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function() {
|
||||
return (
|
||||
<div class="sidebar__head">
|
||||
<div class="sidebar__head-logo">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="sidebar__head-company-meta">
|
||||
<span class="comapny-name">
|
||||
|
||||
</span>
|
||||
|
||||
<span class="company-meta"></span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
30
client/src/components/Sideabr/index.js
Normal file
30
client/src/components/Sideabr/index.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Switch,
|
||||
Route,
|
||||
} from 'react-router-dom';
|
||||
import SidebarContainer from './SidebarContainer';
|
||||
import SidebarHead from './SidebarHead';
|
||||
import sidebarRoutes from '../../routes/sidebar';
|
||||
|
||||
export default function Sidebar() {
|
||||
return (
|
||||
<SidebarContainer>
|
||||
<SidebarHead />
|
||||
|
||||
<div className="sidebar__menu">
|
||||
<Menu>
|
||||
{ sidebarRoutes.map((route, index) => (
|
||||
<Route
|
||||
key={index}
|
||||
path={route.path}
|
||||
exact={route.exact}
|
||||
children={<route.sidebar />}
|
||||
/>
|
||||
))}
|
||||
</Menu>
|
||||
</div>
|
||||
</SidebarContainer>
|
||||
)
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<template>
|
||||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
|
||||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
||||
<use :xlink:href="iconName" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isExternal() {
|
||||
return Boolean(this.iconClass)
|
||||
},
|
||||
iconName() {
|
||||
return `#icon-${this.iconClass}`;
|
||||
},
|
||||
svgClass() {
|
||||
if (this.className) {
|
||||
return `svg-icon ${this.className}`;
|
||||
}
|
||||
return 'svg-icon';
|
||||
},
|
||||
styleExternalIcon() {
|
||||
return {
|
||||
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
||||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.svg-external-icon {
|
||||
background-color: currentColor;
|
||||
mask-size: cover!important;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
17
client/src/enhancers/monitorReducer.js
Normal file
17
client/src/enhancers/monitorReducer.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const round = number => Math.round(number * 100) / 100
|
||||
const monitorReducerEnhancer = createStore => (
|
||||
reducer,
|
||||
initialState,
|
||||
enhancer
|
||||
) => {
|
||||
const monitoredReducer = (state, action) => {
|
||||
const start = performance.now()
|
||||
const newState = reducer(state, action)
|
||||
const end = performance.now()
|
||||
const diff = round(end - start)
|
||||
console.log('reducer process time:', diff)
|
||||
return newState
|
||||
}
|
||||
return createStore(monitoredReducer, initialState, enhancer)
|
||||
}
|
||||
export default monitorReducerEnhancer
|
||||
30
client/src/index.js
Normal file
30
client/src/index.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createStore, applyMiddleware, compose } from 'redux';
|
||||
import { Provider } from 'react-redux';
|
||||
import rootReducer from './reducers';
|
||||
import thunkMiddleware from 'redux-thunk';
|
||||
import monitorReducerEnhancer from './enhancers/monitorReducer';
|
||||
// import axios from 'axios';
|
||||
import App from './pages/App';
|
||||
import * as serviceWorker from './serviceWorker';
|
||||
import loggerMiddleware from './middleware/logger'
|
||||
|
||||
const middlewareEnhancer = applyMiddleware(loggerMiddleware, thunkMiddleware)
|
||||
const composedEnhancers = compose(
|
||||
middlewareEnhancer,
|
||||
monitorReducerEnhancer,
|
||||
)
|
||||
const store = createStore(rootReducer, undefined, composedEnhancers);
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
||||
@@ -1,22 +0,0 @@
|
||||
export default {
|
||||
login: 'Login',
|
||||
password: 'Password',
|
||||
username_password: 'Username or Email',
|
||||
with_your_account: 'With your Ratteb account.',
|
||||
if_you_forget_your_password: 'If you forgot your password, well, enter your Moosher ID than secret key to reset your password.',
|
||||
sign_in: 'Sign in',
|
||||
dashboard: 'Dashboard',
|
||||
reset_the_password: 'Reset the Password',
|
||||
enter_your_new_password: 'Enter You New Password',
|
||||
reset_password_link_is_invalid: 'The link is invalid or expired. Please reset your password again.',
|
||||
your_password_has_been_changed: 'Success Your password has been changed.',
|
||||
username_password_do_not_match: 'The username and password you entered did not match our records.',
|
||||
the_account_suspended_please_contact: 'This account is suspended, Please contact the administrator.',
|
||||
email_has_been_sent: 'An e-mail has been sent to {email} with further instructions.',
|
||||
there_is_no_email_with_that_address: 'There is no email with that address, Please try again.',
|
||||
reset_your_password: 'Reset Your Password',
|
||||
return_to_login: 'Return to Login',
|
||||
forget_password: 'Forget your password?',
|
||||
reset_password: 'Reset Password',
|
||||
email_password_do_not_match: 'Email and password do not match.',
|
||||
};
|
||||
7
client/src/logo.svg
Normal file
7
client/src/logo.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
|
||||
<g fill="#61DAFB">
|
||||
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
|
||||
<circle cx="420.9" cy="296.5" r="45.7"/>
|
||||
<path d="M520.5 78.1z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -1,28 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
import {Form, FormItem, Input, Tabs, TabPane, Button, Alert} from 'element-ui';
|
||||
import App from '@/App';
|
||||
import router from '@/router';
|
||||
import store from '@/store';
|
||||
import '@/plugins/icons';
|
||||
|
||||
// Plugins
|
||||
import '@/plugins/i18n';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
Vue.use(Form);
|
||||
Vue.use(FormItem);
|
||||
Vue.use(Input);
|
||||
Vue.use(Tabs);
|
||||
Vue.use(TabPane);
|
||||
Vue.use(Button);
|
||||
Vue.use(Alert);
|
||||
|
||||
const app = new Vue({
|
||||
el: '#app',
|
||||
render: h => h(App),
|
||||
router,
|
||||
store,
|
||||
});
|
||||
|
||||
export default app;
|
||||
9
client/src/middleware/logger.js
Normal file
9
client/src/middleware/logger.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const logger = store => next => action => {
|
||||
console.group(action.type)
|
||||
console.info('dispatching', action)
|
||||
let result = next(action)
|
||||
console.log('next state', store.getState())
|
||||
console.groupEnd()
|
||||
return result
|
||||
}
|
||||
export default logger
|
||||
@@ -1,20 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'reloadable',
|
||||
created() {
|
||||
this.$eventBus.$on('reload-data', this.onReloadData);
|
||||
},
|
||||
methods: {
|
||||
async onReloadData() {
|
||||
this.$nprogress.start();
|
||||
await this.reloadData();
|
||||
this.$nprogress.done();
|
||||
},
|
||||
|
||||
reloadData() {},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$eventBus.$off('reload-data', this.onReloadData);
|
||||
},
|
||||
});
|
||||
12
client/src/pages/App.js
Normal file
12
client/src/pages/App.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import Authentication from 'pages/Authentication';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<h1>Hello World</h1>
|
||||
<Authentication />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default App;
|
||||
@@ -1,207 +0,0 @@
|
||||
<template>
|
||||
<div class="page-auth page-auth--login">
|
||||
<div class="page-auth__content-side">
|
||||
<div class="page-auth__content-header">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="page-auth__content-form">
|
||||
<transition name="fade" mode="out-in">
|
||||
<router-view></router-view>
|
||||
</transition>
|
||||
</div>
|
||||
|
||||
<AuthFooter></AuthFooter>
|
||||
</div>
|
||||
|
||||
<AuthMedia></AuthMedia>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AuthMedia from '@/pages/Auth/AuthMedia.vue';
|
||||
import AuthFooter from '@/pages/Auth/AuthFooter.vue';
|
||||
|
||||
export default {
|
||||
name: 'auth-container',
|
||||
components: {
|
||||
AuthMedia,
|
||||
AuthFooter,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.page-auth{
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
|
||||
&__content-side{
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
// @include media-breakpoint-up('lg'){
|
||||
width: 62%;
|
||||
// }
|
||||
|
||||
.remember-forget-wrapper{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 20px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.form-note{
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.btn-primary{
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&__content{
|
||||
|
||||
&-header{
|
||||
max-width: 440px;
|
||||
width: 100%;
|
||||
padding: 0 30px;
|
||||
margin: 0 auto;
|
||||
padding-top: 40px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
// @include media-breakpoint-down('xs'){
|
||||
// padding-top: 25px;
|
||||
// padding-left: 25px;
|
||||
// padding-right: 25px;
|
||||
// }
|
||||
|
||||
.icon-logo{
|
||||
// @include media-breakpoint-down('xs'){
|
||||
// width: 140px;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
&-title{
|
||||
font-size: 42px;
|
||||
font-weight: 300;
|
||||
letter-spacing: -0.025em;
|
||||
color: #253992;
|
||||
line-height: 1.2;
|
||||
padding-bottom: 23px;
|
||||
font-size: 2.4em;
|
||||
|
||||
// @include media-breakpoint-down('xs'){
|
||||
// font-size: 2.2rem;
|
||||
// }
|
||||
|
||||
small{
|
||||
font-size: 0.46em;
|
||||
display: block;
|
||||
font-weight: 400;
|
||||
color: #495463;
|
||||
letter-spacing: normal;
|
||||
margin-top: 10px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.text-success{
|
||||
color: #00d285;
|
||||
font-size: 0.41em;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&-form{
|
||||
width: 440px;
|
||||
max-width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 40px 30px 50px;
|
||||
|
||||
// @include media-breakpoint-down('xs'){
|
||||
// padding-left: 25px;
|
||||
// padding-right: 25px;
|
||||
// }
|
||||
}
|
||||
|
||||
&-footer{
|
||||
margin: 0 auto;
|
||||
width: 440px;
|
||||
max-width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0 30px;
|
||||
padding-bottom: 25px;
|
||||
|
||||
.footer-links{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li{
|
||||
padding: 2px 15px;
|
||||
font-size: 13px;
|
||||
color: #758698;
|
||||
display: inline-block;
|
||||
|
||||
&:first-child{
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&:last-child{
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
a{
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
|
||||
&:hover{
|
||||
color: #2c80ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Media Side **/
|
||||
&__media-side{
|
||||
display: flex;
|
||||
width: 38%;
|
||||
background-image: url('/images/cover.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
position: relative;
|
||||
background-position: 50% 0;
|
||||
|
||||
// @include media-breakpoint-down('md'){
|
||||
// width: 38%;
|
||||
// }
|
||||
|
||||
// @include media-breakpoint-down('xs'){
|
||||
// display: none;
|
||||
// }
|
||||
}
|
||||
|
||||
&__media-overlay{
|
||||
position: absolute;
|
||||
background: #202141;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
opacity: 0.65;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,15 +0,0 @@
|
||||
<template>
|
||||
<div class="page-auth__content-footer">
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">{{ $t('privacy_policy') }}</a></li>
|
||||
<li><a href="#">{{ $t('terms_and_conditions') }}</a></li>
|
||||
<li>© 2019 Moosher.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'auth-footer',
|
||||
}
|
||||
</script>
|
||||
@@ -1,11 +0,0 @@
|
||||
<template>
|
||||
<div class="page-auth__media-side">
|
||||
<div class="page-auth__media-overlay"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'auth-media',
|
||||
};
|
||||
</script>
|
||||
@@ -1,51 +0,0 @@
|
||||
<template>
|
||||
<div id="reset-password">
|
||||
<h2 class="page-auth__content-title">
|
||||
{{ $t('reset_your_password') }}
|
||||
<small>{{ $t('if_you_forget_your_password') }}</small>
|
||||
</h2>
|
||||
|
||||
<el-form ref="form" class="form-container">
|
||||
<el-form-item :label="$t('username_password')" prop="title">
|
||||
<el-input v-model="form.crediential" :maxlength="100" name="name" required />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-button type="primary">{{ $t('reset_password') }}</el-button>
|
||||
|
||||
<div class="form-note">
|
||||
<router-link :to="{name: 'login'}">{{ $t('return_to_login') }}</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'forget-password',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
crediential: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['login']),
|
||||
|
||||
/**
|
||||
* Handle the submitting the reset password form.
|
||||
*/
|
||||
onSubmit() {
|
||||
const form = {};
|
||||
|
||||
this.sendResetPassword({ form }).then(() => {
|
||||
// console.log(response);
|
||||
}).catch(() => {
|
||||
// console.log(error);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="login">
|
||||
<h2 class="page-auth__content-title">
|
||||
{{ $t('sign_in') }}
|
||||
<small>{{ $t('with_your_account') }}</small>
|
||||
</h2>
|
||||
|
||||
<el-alert :active="isCredentialError" :type="'error'">
|
||||
{{ $t('email_password_do_not_match') }}
|
||||
</el-alert>
|
||||
|
||||
<el-alert :isActive="isInactiveError" :type="'error'">
|
||||
{{ $t('the_account_suspended_please_contact') }}
|
||||
</el-alert>
|
||||
|
||||
<el-alert :isActive="isResetPasswordSuccess" type="success">
|
||||
{{ $t('your_password_has_been_changed') }}
|
||||
</el-alert>
|
||||
|
||||
<el-form ref="form" class="form-container">
|
||||
<el-form-item :label="$t('username_password')" prop="title">
|
||||
<el-input v-model="form.crediential" :maxlength="100" name="name" required />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('password')">
|
||||
<el-input v-model="form.password" name="password" />
|
||||
</el-form-item>
|
||||
|
||||
<el-button type="primary">{{ $t('login') }}</el-button>
|
||||
</el-form>
|
||||
|
||||
<div class="form-note">
|
||||
<div class="forget-password">
|
||||
<router-link :to="{name: 'forgetPassword'}">{{ $t('forget_password') }}</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
|
||||
const STATE = {
|
||||
USER_NOT_ACTIVE: 1,
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'login',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
username: '',
|
||||
password: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isCredentialError() {
|
||||
return false;
|
||||
},
|
||||
isInactiveError() {
|
||||
return false;
|
||||
},
|
||||
isResetPasswordSuccess() {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['login']),
|
||||
|
||||
/**
|
||||
* Handle the submitting the login form.
|
||||
*/
|
||||
onSubmit() {
|
||||
const form = {};
|
||||
|
||||
this.login({ form }).then(() => {
|
||||
this.$route.push({ name: 'dashboard.home' });
|
||||
}).catch((error) => {
|
||||
const { response } = error;
|
||||
const { data } = response;
|
||||
|
||||
if (data.error.type === 'USER_NOT_ACTIVE') {
|
||||
this.current_state = STATE.USER_NOT_ACTIVE;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,79 +0,0 @@
|
||||
|
||||
<template>
|
||||
<div class="reset-password" id="reset-password">
|
||||
<el-form ref="form" class="form-container">
|
||||
<el-form-item :label="$t('password')" prop="title">
|
||||
<el-input v-model="form.password" :maxlength="100" name="password" required />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('confirm_password')">
|
||||
<el-input v-model="form.confirm_password" name="confirm_password" />
|
||||
</el-form-item>
|
||||
|
||||
<el-button @click.prevent="onSubmit" type="primary">
|
||||
{{ $t('reset_the_password') }}
|
||||
</el-button>
|
||||
<el-link>{{ $t('forget_your_password') }}</el-link>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex';
|
||||
|
||||
const STATE = {
|
||||
SUCCESS: 1,
|
||||
TOKEN_INVALID: 2,
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'reset-password',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
password: '',
|
||||
confirm_password: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
props: {
|
||||
token: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
||||
isSuccess() {
|
||||
return this.current_state === STATE.SUCCESS;
|
||||
},
|
||||
isTokenInvalid() {
|
||||
return this.current_state === STATE.TOKEN_INVALID;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['newPassword']),
|
||||
|
||||
/**
|
||||
* Handle the submitting the reset password form.
|
||||
*/
|
||||
onSubmit() {
|
||||
const form = {
|
||||
...this.form,
|
||||
token: this.token,
|
||||
};
|
||||
|
||||
this.newPassword({ form }).then(() => {
|
||||
this.$router.push({ name: 'login' });
|
||||
}).catch((error) => {
|
||||
const { response } = error;
|
||||
const { data } = response;
|
||||
|
||||
if (data.error.type === 'token.invalid') {
|
||||
this.current_status = STATE.TOKEN_INVALID;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
25
client/src/pages/Authentication/Login.js
Normal file
25
client/src/pages/Authentication/Login.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Button,
|
||||
InputGroup,
|
||||
} from "@blueprintjs/core";
|
||||
|
||||
export default function Login() {
|
||||
return (
|
||||
<div class="login-page">
|
||||
<InputGroup
|
||||
leftIcon="filter"
|
||||
placeholder="Email or phone number"
|
||||
/>
|
||||
|
||||
<InputGroup
|
||||
leftIcon="filter"
|
||||
placeholder="Password"
|
||||
/>
|
||||
|
||||
<Button>
|
||||
{"Login"}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
20
client/src/pages/Authentication/ResetPassword.js
Normal file
20
client/src/pages/Authentication/ResetPassword.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Button,
|
||||
InputGroup,
|
||||
} from "@blueprintjs/core";
|
||||
|
||||
export default function Login() {
|
||||
return (
|
||||
<div class="login-page">
|
||||
<InputGroup
|
||||
leftIcon="filter"
|
||||
placeholder="Email or phone number"
|
||||
/>
|
||||
|
||||
<Button>
|
||||
{"Reset password"}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
25
client/src/pages/Authentication/index.js
Normal file
25
client/src/pages/Authentication/index.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom';
|
||||
import authenticationRoutes from 'routes/authentication';
|
||||
|
||||
export default function() {
|
||||
return (
|
||||
<div class="authentication-page">
|
||||
<Router>
|
||||
<Link to="/login">{ "Login" }</Link>
|
||||
<Link to="/reset_password">{ "Reset Password" }</Link>
|
||||
|
||||
<Switch>
|
||||
{ authenticationRoutes.map((route, index) => (
|
||||
<Route
|
||||
key={index}
|
||||
path={route.path}
|
||||
exact={route.exact}
|
||||
component={route.component}
|
||||
/>
|
||||
))}
|
||||
</Switch>
|
||||
</Router>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<div class="">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'account-form',
|
||||
data() {
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,11 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'accounts-list',
|
||||
};
|
||||
</script>
|
||||
@@ -1,31 +0,0 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
|
||||
const STATE = {
|
||||
LOADING: 1,
|
||||
EMPTY_LIST: 2,
|
||||
NO_SEARCH_RESULTS: 3,
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'customers-list',
|
||||
data() {
|
||||
return {
|
||||
current_state: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.current_state === STATE.LOADING;
|
||||
},
|
||||
emptyList() {
|
||||
return this.current_state === STATE.EMPTY_LIST;
|
||||
},
|
||||
noSearchResults() {
|
||||
return this.current_state === STATE.NO_SEARCH_RESULTS;
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,37 +0,0 @@
|
||||
<template>
|
||||
<div id="dashboard" class="dashboard">
|
||||
<DashboardSidebar />
|
||||
|
||||
<div class="dashboard__content">
|
||||
<DashboardTopbar></DashboardTopbar>
|
||||
|
||||
<div class="dashboard__content-inner">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DashboardSidebar from '@/views/Sidebar';
|
||||
import DashboardTopbar from '@/views/Topbar';
|
||||
|
||||
export default {
|
||||
name: 'dashboard',
|
||||
components: {
|
||||
DashboardTopbar,
|
||||
DashboardSidebar,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.dashboard{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
&__content{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +0,0 @@
|
||||
<template>
|
||||
<div>Home</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'home',
|
||||
};
|
||||
</script>
|
||||
@@ -1,34 +0,0 @@
|
||||
<template>
|
||||
<div class="item-form" id="item-form">
|
||||
<el-form ref="form" class="form-container">
|
||||
<el-form-item :label="$t('item_name')" prop="title">
|
||||
<el-input v-model="form.name" :maxlength="100" name="name" required />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('SKU')" prop="title">
|
||||
<el-input v-model="form.SKU" :maxlength="100" name="SKU" required />
|
||||
</el-form-item>
|
||||
|
||||
<el-button type="primary">{{ $t('login') }}</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'item-form',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
||||
onSubmit() {
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
<template>
|
||||
<el-table v-loading="isLoading" :data="items.list" border fit highlight-current-row>
|
||||
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
import Reloadable from '@/mixins/Reloadable';
|
||||
|
||||
const STATE = {
|
||||
LOADING: 1,
|
||||
};
|
||||
export default {
|
||||
name: 'items-datatable',
|
||||
mixins: [Reloadable],
|
||||
data() {
|
||||
return {
|
||||
current_state: 0,
|
||||
page: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
items: 'getItems',
|
||||
}),
|
||||
isLoading() {
|
||||
return this.current_state === STATE.LOADING;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.current_state = STATE.LOADING;
|
||||
this.fetchData();
|
||||
this.current_state = 0;
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['fetchItems']),
|
||||
|
||||
/**
|
||||
* Handle the reload data.
|
||||
*/
|
||||
reloadData() {
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle the fetch data of datatable.
|
||||
*/
|
||||
async fetchData() {
|
||||
await this.fetchItems({ page: this.page });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,27 +0,0 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane label="User" name="first" :lazy="true">User</el-tab-pane>
|
||||
<el-tab-pane label="Config" name="second" :lazy="true">Config</el-tab-pane>
|
||||
<el-tab-pane label="Role" name="third" :lazy="true">Role</el-tab-pane>
|
||||
<el-tab-pane label="Task" name="fourth" :lazy="true">Task</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'products-list',
|
||||
data() {
|
||||
return {
|
||||
activeName: 'first',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClick(tab, event) {
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<div class="">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'item-category-form',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
|
||||
},
|
||||
};
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,42 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-table v-loading="isLoading" :data="items.list" border fit highlight-current-row>
|
||||
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'items-categories',
|
||||
data() {
|
||||
return {
|
||||
current_state: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
categories: 'getItemsCategories',
|
||||
}),
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['fetchItemsCategories']),
|
||||
|
||||
/**
|
||||
* Handle the reload data of the current view.
|
||||
*/
|
||||
async reloadData() {
|
||||
await this.fetchData();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle the fetch data of the datatable.
|
||||
*/
|
||||
async fetchData() {
|
||||
await this.fetchItemsCategories();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<div>Users List</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'users-list',
|
||||
afterRouteEnter(to, from, next) {
|
||||
debugger;
|
||||
this.$store.commit('setPageTitle', this.$t('users_list'));
|
||||
next();
|
||||
},
|
||||
}
|
||||
</script>
|
||||
15
client/src/pages/Dashboard/index.js
Normal file
15
client/src/pages/Dashboard/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter as Router } from 'react-router-dom';
|
||||
import Sidebar from '../../components/Sidebar';
|
||||
import DashboardContent from '../../components/DashboardContent';
|
||||
|
||||
export default function() {
|
||||
return (
|
||||
<div class="dashboard" id="dashboard">
|
||||
<Router>
|
||||
<Sidebar />
|
||||
<DashboardContent />
|
||||
</Router>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
export default {
|
||||
|
||||
get(resource, params) {
|
||||
return Vue.axios.get(`api/${resource}`, params);
|
||||
},
|
||||
|
||||
post(resource, params) {
|
||||
return Vue.axios.post(`api/${resource}`, params);
|
||||
},
|
||||
|
||||
update(resource, slug, params) {
|
||||
return Vue.axios.put(`api/${resource}/${slug}`, params);
|
||||
},
|
||||
|
||||
put(resource, params) {
|
||||
return Vue.axios.put(`api/${resource}`, params);
|
||||
},
|
||||
|
||||
delete(resource) {
|
||||
return Vue.axios.delete(`api/${resource}`);
|
||||
}
|
||||
};
|
||||
@@ -1,59 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import store from '~/store';
|
||||
import swal from 'sweetalert2'
|
||||
import Vue from 'vue';
|
||||
import VueAxios from 'vue-axios';
|
||||
import router from '~/routes';
|
||||
|
||||
// Set config defaults when creating the instance
|
||||
const http = axios.create();
|
||||
|
||||
// request interceptor.
|
||||
http.interceptors.request.use((request) => {
|
||||
const token = store.getters.authToken;
|
||||
const locale = Vue.i18n.locale();
|
||||
|
||||
if (token) {
|
||||
request.headers.common['x-access-token'] = token;
|
||||
}
|
||||
if (locale) {
|
||||
request.headers.common['Accept-Language'] = locale;
|
||||
}
|
||||
return request;
|
||||
});
|
||||
|
||||
// response interceptor
|
||||
http.interceptors.response.use(response => response, (error) => {
|
||||
const { status } = error.response;
|
||||
|
||||
if (status >= 500) {
|
||||
swal({
|
||||
type: 'error',
|
||||
title: Vue.i18n.translate('error_alert_title'),
|
||||
text: Vue.i18n.translate('error_alert_text'),
|
||||
reverseButtons: true,
|
||||
confirmButtonText: Vue.i18n.translate('ok'),
|
||||
cancelButtonText: Vue.i18n.translate('cancel')
|
||||
});
|
||||
}
|
||||
|
||||
if (status === 401) {
|
||||
swal({
|
||||
type: 'warning',
|
||||
title: Vue.i18n.translate('token_expired_alert_title'),
|
||||
text: Vue.i18n.translate('token_expired_alert_text'),
|
||||
reverseButtons: true,
|
||||
confirmButtonText: Vue.i18n.translate('ok'),
|
||||
cancelButtonText: Vue.i18n.translate('cancel')
|
||||
}).then(() => {
|
||||
store.commit('removeToken');
|
||||
router.push({ name: 'login' });
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(error)
|
||||
});
|
||||
|
||||
Vue.use(VueAxios, http);
|
||||
|
||||
export default http;
|
||||
@@ -1,29 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
|
||||
const defaultLocale = 'en';
|
||||
const loadedLangauges = [];
|
||||
const currentLocale = Vue.i18n.locale();
|
||||
|
||||
function setLanguage(locale, messages) {
|
||||
const localeMessages = messages.default;
|
||||
|
||||
Vue.i18n.add(locale, { ...localeMessages });
|
||||
|
||||
loadedLangauges.push(locale);
|
||||
Vue.i18n.set(locale);
|
||||
}
|
||||
|
||||
async function loadAsyncLanguage(locale) {
|
||||
if (locale !== currentLocale) {
|
||||
if (!loadedLangauges.includes(locale)) {
|
||||
const messages = await import(/* webpackChunkName: "lang-[request]" */ `@/lang/${locale}/app`);
|
||||
setLanguage(locale, messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await loadAsyncLanguage(defaultLocale);
|
||||
})();
|
||||
|
||||
export default loadAsyncLanguage;
|
||||
@@ -1,9 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
|
||||
// register globally
|
||||
Vue.component('svg-icon', SvgIcon)
|
||||
|
||||
const req = require.context('../../static/icons', false, /\.svg$/);
|
||||
const requireAll = requireContext => requireContext.keys().map(requireContext);
|
||||
requireAll(req);
|
||||
10
client/src/reducers/index.js
Normal file
10
client/src/reducers/index.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import accounts from './accounts';
|
||||
import authentication from './authentication';
|
||||
import users from './users';
|
||||
|
||||
export default combineReducers({
|
||||
authentication,
|
||||
users,
|
||||
accounts,
|
||||
});
|
||||
@@ -1,43 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
import Router from 'vue-router';
|
||||
import store from '@/store';
|
||||
import routes from './routes';
|
||||
|
||||
Vue.use(Router);
|
||||
|
||||
const router = new Router({
|
||||
mode: 'hash',
|
||||
routes: [
|
||||
...routes,
|
||||
],
|
||||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const isAuthenticated = store.getters.authCheck;
|
||||
|
||||
if (to.matched.some(record => record.meta.requiresAuth)) {
|
||||
if (!isAuthenticated) {
|
||||
next({
|
||||
name: 'login',
|
||||
params: { nextUrl: to.fullPath },
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
} else if (to.matched.some(record => record.meta.guest)) {
|
||||
if (isAuthenticated) {
|
||||
next({
|
||||
name: 'dashboard.name',
|
||||
params: {
|
||||
nextUrl: to.fullPath,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -1,89 +0,0 @@
|
||||
|
||||
const routes = [
|
||||
{
|
||||
name: 'auth',
|
||||
path: '/',
|
||||
component: () => import(/* webpackChunkName: "auth_container" */
|
||||
'@/pages/Auth/AuthContainer.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'login',
|
||||
path: '/login',
|
||||
component: () => import(/* webpackChunkName: "login" */
|
||||
'@/pages/Auth/Login.vue'),
|
||||
},
|
||||
{
|
||||
name: 'forgetPassword',
|
||||
path: '/forget_password',
|
||||
component: () => import(/* webpackChunkName: "forget_password" */
|
||||
'@/pages/Auth/ForgetPassword.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'dashboard',
|
||||
path: '/dashboard',
|
||||
component: () => import(/* webpackChunkName: "dashboard" */
|
||||
'@/pages/Dashboard/Dashboard.vue'),
|
||||
children: [
|
||||
{
|
||||
name: 'dashboard.home',
|
||||
path: '/home',
|
||||
component: () => import(/* webpackChunkName: "dashboard_home" */
|
||||
'@/pages/Dashboard/Home.vue'),
|
||||
},
|
||||
|
||||
/**
|
||||
* Items. (Products/Services).
|
||||
* --------------------------------
|
||||
*/
|
||||
{
|
||||
name: 'dashboard.items.list',
|
||||
path: '/items',
|
||||
component: () => import(/* webpackChunkName: "items_list" */
|
||||
'@/pages/Dashboard/Items/ItemsList.vue'),
|
||||
accessControl: { resource: 'items', permissions: ['view'] },
|
||||
},
|
||||
{
|
||||
name: 'dashboard.items.new',
|
||||
path: '/items/new',
|
||||
component: () => import(/* webpackChunkName: "items_form" */
|
||||
'@/pages/Dashboard/Items/ItemForm.vue'),
|
||||
accessControl: { resource: 'items', permissions: ['create'] },
|
||||
},
|
||||
|
||||
/**
|
||||
* Accounts
|
||||
* ---------------------------
|
||||
*/
|
||||
{
|
||||
name: 'dashboard.accounts.list',
|
||||
path: '/accounts/list',
|
||||
component: () => import(/* webpackChunkName: "accounts_list" */
|
||||
'@/pages/Dashboard/Accounts/AccountsList.vue'),
|
||||
accessControl: { resource: 'accounts', permissions: ['view'] },
|
||||
},
|
||||
|
||||
/**
|
||||
* Users.
|
||||
* --------------------------------
|
||||
*/
|
||||
{
|
||||
name: 'dashboard.users.list',
|
||||
path: '/users',
|
||||
component: () => import(/* webpackChunkName: "users_list" */
|
||||
'@/pages/Dashboard/Users/UsersList.vue'),
|
||||
accessControl: { resource: 'users', permissions: ['view'] },
|
||||
},
|
||||
{
|
||||
name: 'dasboard.user.new',
|
||||
path: '/users',
|
||||
component: () => import(/* webpackChunkName: "user_form" */
|
||||
'@/pages/Dashboard/Users/UserForm.vue'),
|
||||
accessControl: { resource: 'users', permissions: ['create'] },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
||||
15
client/src/routes/authentication.js
Normal file
15
client/src/routes/authentication.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import Login from '../pages/Authentication/Login';
|
||||
import ResetPassword from '../pages/Authentication/ResetPassword';
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/login',
|
||||
exact: true,
|
||||
component: Login,
|
||||
},
|
||||
{
|
||||
path: '/reset_password',
|
||||
exact: true,
|
||||
component: ResetPassword,
|
||||
}
|
||||
];
|
||||
11
client/src/routes/dashboard.js
Normal file
11
client/src/routes/dashboard.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import AccountsChart from '../pages/Dashboard/AccountsChart';
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/accounts/list',
|
||||
component: AccountsChart,
|
||||
icon: 'cut',
|
||||
text: 'Chart of Accounts',
|
||||
label: 'Chart of Accounts'
|
||||
},
|
||||
];
|
||||
141
client/src/serviceWorker.js
Normal file
141
client/src/serviceWorker.js
Normal file
@@ -0,0 +1,141 @@
|
||||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' }
|
||||
})
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then(registration => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
5
client/src/setupTests.js
Normal file
5
client/src/setupTests.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom/extend-expect';
|
||||
@@ -1,25 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import vuexI18n from 'vuex-i18n';
|
||||
import sidebar from '@/store/modules/sidebar';
|
||||
import app from '@/store/modules/app';
|
||||
import items from '@/store/modules/items';
|
||||
import customers from '@/store/modules/customers';
|
||||
|
||||
const debug = process.env.NODE_ENV !== 'production';
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
app,
|
||||
sidebar,
|
||||
items,
|
||||
customers,
|
||||
},
|
||||
strict: debug,
|
||||
});
|
||||
|
||||
Vue.use(vuexI18n.plugin, store);
|
||||
|
||||
export default store;
|
||||
@@ -1,41 +0,0 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
||||
const state = {
|
||||
appName: 'Ratteb',
|
||||
appVersion: '1.0.0',
|
||||
appBuild: '1000',
|
||||
|
||||
pageTitle: 'Welcome',
|
||||
actions: [],
|
||||
|
||||
contentState: 0,
|
||||
sidebarOpened: true,
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getAppName: s => s.appName,
|
||||
getAppVersion: s => s.appVersion,
|
||||
getAppBuild: s => s.appBuild,
|
||||
getPageTitle: s => s.pageTitle,
|
||||
};
|
||||
|
||||
const actions = {
|
||||
|
||||
setPageTitle(s, title) {
|
||||
s.title = title;
|
||||
},
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
toggleSidebar() {
|
||||
state.sidebarOpened = !state.sidebarOpened;
|
||||
|
||||
if (state.sidebarOpened) {
|
||||
localStorage.set('sidebarStatus', 1)
|
||||
} else {
|
||||
localStorage.set('sidebarStatus', 0)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
export default { state, actions, mutations, getters };
|
||||
@@ -1,55 +0,0 @@
|
||||
import ApiService from '@/plugins/api-service';
|
||||
|
||||
const state = {
|
||||
token: localStorage.getItem('token') || '',
|
||||
errors: {},
|
||||
role: {},
|
||||
};
|
||||
|
||||
const getters = {
|
||||
authCheck: s => s.token,
|
||||
authToken: s => s.token,
|
||||
authorizedUserRole: s => s.role,
|
||||
};
|
||||
|
||||
const actions = {
|
||||
/**
|
||||
* User login login authentication request.
|
||||
*/
|
||||
async login({ commit }, { form }) {
|
||||
const response = await ApiService.post('auth/login', form);
|
||||
const { data } = response;
|
||||
|
||||
if (data.token) {
|
||||
commit('setToken', data.token);
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Send reset password via email or SMS.
|
||||
*/
|
||||
sendResetPassword({}, { email }) {
|
||||
return ApiService.post('auth/send_reset_password', { email });
|
||||
},
|
||||
|
||||
newPassword({}, { form }) {
|
||||
return ApiService.post('auth/new_password', form);
|
||||
},
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
|
||||
setToken(s, token) {
|
||||
localStorage.setItem('token', token);
|
||||
s.token = token;
|
||||
},
|
||||
|
||||
removeToken(s) {
|
||||
localStorage.removeItem('token');
|
||||
s.token = '';
|
||||
},
|
||||
};
|
||||
|
||||
export default { state, actions, mutations, getters };
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import ApiService from '@/plugins/api-service';
|
||||
|
||||
const state = {
|
||||
list: {},
|
||||
details: [],
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getCustomers: s => s.list,
|
||||
getCustomer: s => id => s.details.find(i => i.id === id),
|
||||
};
|
||||
|
||||
const actions = {
|
||||
/**
|
||||
* Fetches customers with current page.
|
||||
*/
|
||||
async fetchCustomers({ commit }, { query } = {}) {
|
||||
const response = await ApiService.post('customers', { params: query });
|
||||
const { data } = response;
|
||||
const { count } = data.pagination;
|
||||
|
||||
commit('setItems', data);
|
||||
|
||||
if (count) {
|
||||
commit('setSidebarItemCount', { name: 'customers', count });
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch the given customer details.
|
||||
*/
|
||||
async fetchCustomer({ commit }, { id }) {
|
||||
const response = await ApiService.get(`customers/${id}`);
|
||||
const { data } = response;
|
||||
|
||||
commit('setItem', data);
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete the given customer.
|
||||
*/
|
||||
async deleteCustomer({}, { id }) {
|
||||
return ApiService.delete(`customers/${id}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Submit the new customer.
|
||||
*/
|
||||
async newCustomer({}, { form }) {
|
||||
return ApiService.post('customers', form);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update details the given customer.
|
||||
*/
|
||||
async updateCustomer({}, { form, id }) {
|
||||
return ApiService.post(`customers/${id}`, form);
|
||||
},
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
|
||||
setCustomers(s, items) {
|
||||
s.list = items;
|
||||
},
|
||||
|
||||
setCustomer(s, item) {
|
||||
s.details = s.details.filter(i => i.id !== item.id);
|
||||
s.details.push(item);
|
||||
},
|
||||
};
|
||||
|
||||
export default { state, actions, mutations, getters };
|
||||
@@ -1,28 +0,0 @@
|
||||
const state = {
|
||||
logs: [],
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
ADD_ERROR_LOG: (s, log) => {
|
||||
s.logs.push(log);
|
||||
},
|
||||
CLEAR_ERROR_LOG: (s) => {
|
||||
s.logs.splice(0);
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
addErrorLog({ commit }, log) {
|
||||
commit('ADD_ERROR_LOG', log);
|
||||
},
|
||||
clearErrorLog({ commit }) {
|
||||
commit('CLEAR_ERROR_LOG');
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
};
|
||||
@@ -1,119 +0,0 @@
|
||||
import ApiService from '@/plugins/api-service';
|
||||
|
||||
const state = {
|
||||
list: {},
|
||||
details: [],
|
||||
categories: {},
|
||||
categoriesDetails: [],
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getItems: s => s.list,
|
||||
getItem: s => id => s.details.find(i => i.id === id),
|
||||
getItemsCategories: s => s.categories,
|
||||
getItemCategory: s => id => s.categoriesDetails.find(i => i.id === id),
|
||||
};
|
||||
|
||||
const actions = {
|
||||
/**
|
||||
* Fetches the products/services list.
|
||||
*/
|
||||
async fetchItems({ commit }, { query } = {}) {
|
||||
const response = await ApiService.post('items', { params: query });
|
||||
const { data } = response;
|
||||
const { count } = data.pagination;
|
||||
|
||||
commit('setItems', data);
|
||||
|
||||
if (count) {
|
||||
commit('setSidebarItemCount', {
|
||||
name: 'items', count,
|
||||
});
|
||||
}
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch the given product/service details.
|
||||
*/
|
||||
async fetchItem({ commit }, { id }) {
|
||||
const response = await ApiService.get(`${id}`);
|
||||
const { data } = response;
|
||||
|
||||
commit('setItem', data);
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete the given product/service.
|
||||
*/
|
||||
async deleteItem({ commit }, { id }) {
|
||||
return ApiService.delete(`items/${id}`);
|
||||
},
|
||||
|
||||
async newItem({}, { form }) {
|
||||
return ApiService.post('items', form);
|
||||
},
|
||||
|
||||
async updateItem({}, { form, id }) {
|
||||
return ApiService.post(`items/${id}`, form);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches items categories paged list.
|
||||
*/
|
||||
async fetchItemsCategories({}, { query }) {
|
||||
return ApiService.get('/items_categories', { params: query });
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch details of the given item category.
|
||||
*/
|
||||
async fetchItemCategory({}, { id }) {
|
||||
return ApiService.get(`/item/${id}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete the given item category.
|
||||
*/
|
||||
async deleteItemCategory({}, { id }) {
|
||||
return ApiService.delete(`/items_categories/${id}`);
|
||||
},
|
||||
|
||||
/**
|
||||
* Post a new item category.
|
||||
*/
|
||||
async newItemCategory({}, { form }) {
|
||||
return ApiService.post('/items_categories', form);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update details of the given item category.
|
||||
*/
|
||||
async updateItemCategory({}, { id, form }) {
|
||||
return ApiService.post(`/items_categories/${id}`, form);
|
||||
},
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
|
||||
setItems(s, items) {
|
||||
s.list = items;
|
||||
},
|
||||
|
||||
setItem(s, item) {
|
||||
s.details = s.details.filter(i => i.id !== item.id);
|
||||
s.details.push(item);
|
||||
},
|
||||
|
||||
setItemCategories(s, categories) {
|
||||
s.categories = categories;
|
||||
},
|
||||
|
||||
setItemCategory(s, category) {
|
||||
s.categoriesDetails = s.categoriesDetails.filter(i => i.id !== category.id);
|
||||
s.categoriesDetails.push(category);
|
||||
},
|
||||
};
|
||||
|
||||
export default { state, actions, mutations, getters };
|
||||
@@ -1,93 +0,0 @@
|
||||
|
||||
const state = {
|
||||
items: [
|
||||
{
|
||||
name: 'Home',
|
||||
to: 'dashboard.home',
|
||||
icon: 'home',
|
||||
count: null,
|
||||
},
|
||||
{
|
||||
name: 'Products',
|
||||
to: 'dashboard.items.list',
|
||||
},
|
||||
{
|
||||
name: 'Customers',
|
||||
to: 'dashboard.home',
|
||||
},
|
||||
{
|
||||
name: 'Suppliers',
|
||||
to: 'dashboard.home',
|
||||
},
|
||||
{
|
||||
name: 'Reports',
|
||||
to: 'dashboard.home',
|
||||
},
|
||||
{
|
||||
name: 'Users',
|
||||
to: 'dashboard.users.list',
|
||||
children: {
|
||||
name: 'New User',
|
||||
to: 'dashboard.user.new',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Accounting',
|
||||
to: 'dashboard.accounts.list',
|
||||
},
|
||||
],
|
||||
|
||||
quickActions: [
|
||||
{
|
||||
route: 'dashboard.items.list',
|
||||
actions: [
|
||||
{
|
||||
dialog: 'global-search',
|
||||
label: 'Search',
|
||||
icon: 'search',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
route: 'dashboard.items.list',
|
||||
actions: [
|
||||
{
|
||||
dialog: 'test',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const getters = {
|
||||
getSidebarItems: s => s.items,
|
||||
getSidebarItem: s => name => s.items.find(item => item.name === name),
|
||||
|
||||
getAllQuickActions: s => s.quickActions,
|
||||
getQuickActions: s => (route) => {
|
||||
const foundDefault = s.quickActions.find(q => q.default === true);
|
||||
const found = s.quickActions.find(q => q.route === route);
|
||||
const defaultActions = foundDefault ? foundDefault.actions : [];
|
||||
|
||||
return found ? [...defaultActions, found.actions] : defaultActions;
|
||||
},
|
||||
};
|
||||
|
||||
const actions = {
|
||||
|
||||
/**
|
||||
* Set count to the given sidebar item.
|
||||
*/
|
||||
setSidebarItemCount(s, { name, count }) {
|
||||
s.items = s.items.map((item) => {
|
||||
const mapped = { ...item };
|
||||
|
||||
if (item.name === name) {
|
||||
mapped.count = count;
|
||||
}
|
||||
return mapped;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default { state, getters, actions };
|
||||
38
client/src/style/App.css
Normal file
38
client/src/style/App.css
Normal file
@@ -0,0 +1,38 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -1,994 +0,0 @@
|
||||
/* Element Chalk Variables */
|
||||
|
||||
// Special comment for theme configurator
|
||||
// type|skipAutoTranslation|Category|Order
|
||||
// skipAutoTranslation 1
|
||||
|
||||
/* Transition
|
||||
-------------------------- */
|
||||
$--all-transition: all .3s cubic-bezier(.645,.045,.355,1) !default;
|
||||
$--fade-transition: opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
|
||||
$--fade-linear-transition: opacity 200ms linear !default;
|
||||
$--md-fade-transition: transform 300ms cubic-bezier(0.23, 1, 0.32, 1), opacity 300ms cubic-bezier(0.23, 1, 0.32, 1) !default;
|
||||
$--border-transition-base: border-color .2s cubic-bezier(.645,.045,.355,1) !default;
|
||||
$--color-transition-base: color .2s cubic-bezier(.645,.045,.355,1) !default;
|
||||
|
||||
/* Color
|
||||
-------------------------- */
|
||||
/// color|1|Brand Color|0
|
||||
$--color-primary: #409EFF !default;
|
||||
/// color|1|Background Color|4
|
||||
$--color-white: #FFFFFF !default;
|
||||
/// color|1|Background Color|4
|
||||
$--color-black: #000000 !default;
|
||||
$--color-primary-light-1: mix($--color-white, $--color-primary, 10%) !default; /* 53a8ff */
|
||||
$--color-primary-light-2: mix($--color-white, $--color-primary, 20%) !default; /* 66b1ff */
|
||||
$--color-primary-light-3: mix($--color-white, $--color-primary, 30%) !default; /* 79bbff */
|
||||
$--color-primary-light-4: mix($--color-white, $--color-primary, 40%) !default; /* 8cc5ff */
|
||||
$--color-primary-light-5: mix($--color-white, $--color-primary, 50%) !default; /* a0cfff */
|
||||
$--color-primary-light-6: mix($--color-white, $--color-primary, 60%) !default; /* b3d8ff */
|
||||
$--color-primary-light-7: mix($--color-white, $--color-primary, 70%) !default; /* c6e2ff */
|
||||
$--color-primary-light-8: mix($--color-white, $--color-primary, 80%) !default; /* d9ecff */
|
||||
$--color-primary-light-9: mix($--color-white, $--color-primary, 90%) !default; /* ecf5ff */
|
||||
/// color|1|Functional Color|1
|
||||
$--color-success: #67C23A !default;
|
||||
/// color|1|Functional Color|1
|
||||
$--color-warning: #E6A23C !default;
|
||||
/// color|1|Functional Color|1
|
||||
$--color-danger: #F56C6C !default;
|
||||
/// color|1|Functional Color|1
|
||||
$--color-info: #909399 !default;
|
||||
|
||||
$--color-success-light: mix($--color-white, $--color-success, 80%) !default;
|
||||
$--color-warning-light: mix($--color-white, $--color-warning, 80%) !default;
|
||||
$--color-danger-light: mix($--color-white, $--color-danger, 80%) !default;
|
||||
$--color-info-light: mix($--color-white, $--color-info, 80%) !default;
|
||||
|
||||
$--color-success-lighter: mix($--color-white, $--color-success, 90%) !default;
|
||||
$--color-warning-lighter: mix($--color-white, $--color-warning, 90%) !default;
|
||||
$--color-danger-lighter: mix($--color-white, $--color-danger, 90%) !default;
|
||||
$--color-info-lighter: mix($--color-white, $--color-info, 90%) !default;
|
||||
/// color|1|Font Color|2
|
||||
$--color-text-primary: #303133 !default;
|
||||
/// color|1|Font Color|2
|
||||
$--color-text-regular: #606266 !default;
|
||||
/// color|1|Font Color|2
|
||||
$--color-text-secondary: #909399 !default;
|
||||
/// color|1|Font Color|2
|
||||
$--color-text-placeholder: #C0C4CC !default;
|
||||
/// color|1|Border Color|3
|
||||
$--border-color-base: #DCDFE6 !default;
|
||||
/// color|1|Border Color|3
|
||||
$--border-color-light: #E4E7ED !default;
|
||||
/// color|1|Border Color|3
|
||||
$--border-color-lighter: #EBEEF5 !default;
|
||||
/// color|1|Border Color|3
|
||||
$--border-color-extra-light: #F2F6FC !default;
|
||||
|
||||
// Background
|
||||
/// color|1|Background Color|4
|
||||
$--background-color-base: #F5F7FA !default;
|
||||
|
||||
/* Link
|
||||
-------------------------- */
|
||||
$--link-color: $--color-primary-light-2 !default;
|
||||
$--link-hover-color: $--color-primary !default;
|
||||
|
||||
/* Border
|
||||
-------------------------- */
|
||||
$--border-width-base: 1px !default;
|
||||
$--border-style-base: solid !default;
|
||||
$--border-color-hover: $--color-text-placeholder !default;
|
||||
$--border-base: $--border-width-base $--border-style-base $--border-color-base !default;
|
||||
/// borderRadius|1|Radius|0
|
||||
$--border-radius-base: 4px !default;
|
||||
/// borderRadius|1|Radius|0
|
||||
$--border-radius-small: 2px !default;
|
||||
/// borderRadius|1|Radius|0
|
||||
$--border-radius-circle: 100% !default;
|
||||
/// borderRadius|1|Radius|0
|
||||
$--border-radius-zero: 0 !default;
|
||||
|
||||
// Box-shadow
|
||||
/// boxShadow|1|Shadow|1
|
||||
$--box-shadow-base: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04) !default;
|
||||
// boxShadow|1|Shadow|1
|
||||
$--box-shadow-dark: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .12) !default;
|
||||
/// boxShadow|1|Shadow|1
|
||||
$--box-shadow-light: 0 2px 12px 0 rgba(0, 0, 0, 0.1) !default;
|
||||
|
||||
/* Fill
|
||||
-------------------------- */
|
||||
$--fill-base: $--color-white !default;
|
||||
|
||||
/* Typography
|
||||
-------------------------- */
|
||||
$--font-path: 'fonts' !default;
|
||||
$--font-display: 'auto' !default;
|
||||
/// fontSize|1|Font Size|0
|
||||
$--font-size-extra-large: 20px !default;
|
||||
/// fontSize|1|Font Size|0
|
||||
$--font-size-large: 18px !default;
|
||||
/// fontSize|1|Font Size|0
|
||||
$--font-size-medium: 16px !default;
|
||||
/// fontSize|1|Font Size|0
|
||||
$--font-size-base: 14px !default;
|
||||
/// fontSize|1|Font Size|0
|
||||
$--font-size-small: 13px !default;
|
||||
/// fontSize|1|Font Size|0
|
||||
$--font-size-extra-small: 12px !default;
|
||||
/// fontWeight|1|Font Weight|1
|
||||
$--font-weight-primary: 500 !default;
|
||||
/// fontWeight|1|Font Weight|1
|
||||
$--font-weight-secondary: 100 !default;
|
||||
/// fontLineHeight|1|Line Height|2
|
||||
$--font-line-height-primary: 24px !default;
|
||||
/// fontLineHeight|1|Line Height|2
|
||||
$--font-line-height-secondary: 16px !default;
|
||||
$--font-color-disabled-base: #bbb !default;
|
||||
/* Size
|
||||
-------------------------- */
|
||||
$--size-base: 14px !default;
|
||||
|
||||
/* z-index
|
||||
-------------------------- */
|
||||
$--index-normal: 1 !default;
|
||||
$--index-top: 1000 !default;
|
||||
$--index-popper: 2000 !default;
|
||||
|
||||
/* Disable base
|
||||
-------------------------- */
|
||||
$--disabled-fill-base: $--background-color-base !default;
|
||||
$--disabled-color-base: $--color-text-placeholder !default;
|
||||
$--disabled-border-base: $--border-color-light !default;
|
||||
|
||||
/* Icon
|
||||
-------------------------- */
|
||||
$--icon-color: #666 !default;
|
||||
$--icon-color-base: $--color-info !default;
|
||||
|
||||
/* Checkbox
|
||||
-------------------------- */
|
||||
/// fontSize||Font|1
|
||||
$--checkbox-font-size: 14px !default;
|
||||
/// fontWeight||Font|1
|
||||
$--checkbox-font-weight: $--font-weight-primary !default;
|
||||
/// color||Color|0
|
||||
$--checkbox-font-color: $--color-text-regular !default;
|
||||
$--checkbox-input-height: 14px !default;
|
||||
$--checkbox-input-width: 14px !default;
|
||||
/// borderRadius||Border|2
|
||||
$--checkbox-border-radius: $--border-radius-small !default;
|
||||
/// color||Color|0
|
||||
$--checkbox-background-color: $--color-white !default;
|
||||
$--checkbox-input-border: $--border-base !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--checkbox-disabled-border-color: $--border-color-base !default;
|
||||
$--checkbox-disabled-input-fill: #edf2fc !default;
|
||||
$--checkbox-disabled-icon-color: $--color-text-placeholder !default;
|
||||
|
||||
$--checkbox-disabled-checked-input-fill: $--border-color-extra-light !default;
|
||||
$--checkbox-disabled-checked-input-border-color: $--border-color-base !default;
|
||||
$--checkbox-disabled-checked-icon-color: $--color-text-placeholder !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--checkbox-checked-font-color: $--color-primary !default;
|
||||
$--checkbox-checked-input-border-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--checkbox-checked-background-color: $--color-primary !default;
|
||||
$--checkbox-checked-icon-color: $--fill-base !default;
|
||||
|
||||
$--checkbox-input-border-color-hover: $--color-primary !default;
|
||||
/// height||Other|4
|
||||
$--checkbox-bordered-height: 40px !default;
|
||||
/// padding||Spacing|3
|
||||
$--checkbox-bordered-padding: 9px 20px 9px 10px !default;
|
||||
/// padding||Spacing|3
|
||||
$--checkbox-bordered-medium-padding: 7px 20px 7px 10px !default;
|
||||
/// padding||Spacing|3
|
||||
$--checkbox-bordered-small-padding: 5px 15px 5px 10px !default;
|
||||
/// padding||Spacing|3
|
||||
$--checkbox-bordered-mini-padding: 3px 15px 3px 10px !default;
|
||||
$--checkbox-bordered-medium-input-height: 14px !default;
|
||||
$--checkbox-bordered-medium-input-width: 14px !default;
|
||||
/// height||Other|4
|
||||
$--checkbox-bordered-medium-height: 36px !default;
|
||||
$--checkbox-bordered-small-input-height: 12px !default;
|
||||
$--checkbox-bordered-small-input-width: 12px !default;
|
||||
/// height||Other|4
|
||||
$--checkbox-bordered-small-height: 32px !default;
|
||||
$--checkbox-bordered-mini-input-height: 12px !default;
|
||||
$--checkbox-bordered-mini-input-width: 12px !default;
|
||||
/// height||Other|4
|
||||
$--checkbox-bordered-mini-height: 28px !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--checkbox-button-checked-background-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--checkbox-button-checked-font-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--checkbox-button-checked-border-color: $--color-primary !default;
|
||||
|
||||
|
||||
|
||||
/* Radio
|
||||
-------------------------- */
|
||||
/// fontSize||Font|1
|
||||
$--radio-font-size: $--font-size-base !default;
|
||||
/// fontWeight||Font|1
|
||||
$--radio-font-weight: $--font-weight-primary !default;
|
||||
/// color||Color|0
|
||||
$--radio-font-color: $--color-text-regular !default;
|
||||
$--radio-input-height: 14px !default;
|
||||
$--radio-input-width: 14px !default;
|
||||
/// borderRadius||Border|2
|
||||
$--radio-input-border-radius: $--border-radius-circle !default;
|
||||
/// color||Color|0
|
||||
$--radio-input-background-color: $--color-white !default;
|
||||
$--radio-input-border: $--border-base !default;
|
||||
/// color||Color|0
|
||||
$--radio-input-border-color: $--border-color-base !default;
|
||||
/// color||Color|0
|
||||
$--radio-icon-color: $--color-white !default;
|
||||
|
||||
$--radio-disabled-input-border-color: $--disabled-border-base !default;
|
||||
$--radio-disabled-input-fill: $--disabled-fill-base !default;
|
||||
$--radio-disabled-icon-color: $--disabled-fill-base !default;
|
||||
|
||||
$--radio-disabled-checked-input-border-color: $--disabled-border-base !default;
|
||||
$--radio-disabled-checked-input-fill: $--disabled-fill-base !default;
|
||||
$--radio-disabled-checked-icon-color: $--color-text-placeholder !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--radio-checked-font-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--radio-checked-input-border-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--radio-checked-input-background-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--radio-checked-icon-color: $--color-primary !default;
|
||||
|
||||
$--radio-input-border-color-hover: $--color-primary !default;
|
||||
|
||||
$--radio-bordered-height: 40px !default;
|
||||
$--radio-bordered-padding: 12px 20px 0 10px !default;
|
||||
$--radio-bordered-medium-padding: 10px 20px 0 10px !default;
|
||||
$--radio-bordered-small-padding: 8px 15px 0 10px !default;
|
||||
$--radio-bordered-mini-padding: 6px 15px 0 10px !default;
|
||||
$--radio-bordered-medium-input-height: 14px !default;
|
||||
$--radio-bordered-medium-input-width: 14px !default;
|
||||
$--radio-bordered-medium-height: 36px !default;
|
||||
$--radio-bordered-small-input-height: 12px !default;
|
||||
$--radio-bordered-small-input-width: 12px !default;
|
||||
$--radio-bordered-small-height: 32px !default;
|
||||
$--radio-bordered-mini-input-height: 12px !default;
|
||||
$--radio-bordered-mini-input-width: 12px !default;
|
||||
$--radio-bordered-mini-height: 28px !default;
|
||||
|
||||
/// fontSize||Font|1
|
||||
$--radio-button-font-size: $--font-size-base !default;
|
||||
/// color||Color|0
|
||||
$--radio-button-checked-background-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--radio-button-checked-font-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--radio-button-checked-border-color: $--color-primary !default;
|
||||
$--radio-button-disabled-checked-fill: $--border-color-extra-light !default;
|
||||
|
||||
/* Select
|
||||
-------------------------- */
|
||||
$--select-border-color-hover: $--border-color-hover !default;
|
||||
$--select-disabled-border: $--disabled-border-base !default;
|
||||
/// fontSize||Font|1
|
||||
$--select-font-size: $--font-size-base !default;
|
||||
$--select-close-hover-color: $--color-text-secondary !default;
|
||||
|
||||
$--select-input-color: $--color-text-placeholder !default;
|
||||
$--select-multiple-input-color: #666 !default;
|
||||
/// color||Color|0
|
||||
$--select-input-focus-border-color: $--color-primary !default;
|
||||
/// fontSize||Font|1
|
||||
$--select-input-font-size: 14px !default;
|
||||
|
||||
$--select-option-color: $--color-text-regular !default;
|
||||
$--select-option-disabled-color: $--color-text-placeholder !default;
|
||||
$--select-option-disabled-background: $--color-white !default;
|
||||
/// height||Other|4
|
||||
$--select-option-height: 34px !default;
|
||||
$--select-option-hover-background: $--background-color-base !default;
|
||||
/// color||Color|0
|
||||
$--select-option-selected-font-color: $--color-primary !default;
|
||||
$--select-option-selected-hover: $--background-color-base !default;
|
||||
|
||||
$--select-group-color: $--color-info !default;
|
||||
$--select-group-height: 30px !default;
|
||||
$--select-group-font-size: 12px !default;
|
||||
|
||||
$--select-dropdown-background: $--color-white !default;
|
||||
$--select-dropdown-shadow: $--box-shadow-light !default;
|
||||
$--select-dropdown-empty-color: #999 !default;
|
||||
/// height||Other|4
|
||||
$--select-dropdown-max-height: 274px !default;
|
||||
$--select-dropdown-padding: 6px 0 !default;
|
||||
$--select-dropdown-empty-padding: 10px 0 !default;
|
||||
$--select-dropdown-border: solid 1px $--border-color-light !default;
|
||||
|
||||
/* Alert
|
||||
-------------------------- */
|
||||
$--alert-padding: 8px 16px !default;
|
||||
/// borderRadius||Border|2
|
||||
$--alert-border-radius: $--border-radius-base !default;
|
||||
/// fontSize||Font|1
|
||||
$--alert-title-font-size: 13px !default;
|
||||
/// fontSize||Font|1
|
||||
$--alert-description-font-size: 12px !default;
|
||||
/// fontSize||Font|1
|
||||
$--alert-close-font-size: 12px !default;
|
||||
/// fontSize||Font|1
|
||||
$--alert-close-customed-font-size: 13px !default;
|
||||
|
||||
$--alert-success-color: $--color-success-lighter !default;
|
||||
$--alert-info-color: $--color-info-lighter !default;
|
||||
$--alert-warning-color: $--color-warning-lighter !default;
|
||||
$--alert-danger-color: $--color-danger-lighter !default;
|
||||
|
||||
/// height||Other|4
|
||||
$--alert-icon-size: 16px !default;
|
||||
/// height||Other|4
|
||||
$--alert-icon-large-size: 28px !default;
|
||||
|
||||
/* MessageBox
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--messagebox-title-color: $--color-text-primary !default;
|
||||
$--msgbox-width: 420px !default;
|
||||
$--msgbox-border-radius: 4px !default;
|
||||
/// fontSize||Font|1
|
||||
$--messagebox-font-size: $--font-size-large !default;
|
||||
/// fontSize||Font|1
|
||||
$--messagebox-content-font-size: $--font-size-base !default;
|
||||
/// color||Color|0
|
||||
$--messagebox-content-color: $--color-text-regular !default;
|
||||
/// fontSize||Font|1
|
||||
$--messagebox-error-font-size: 12px !default;
|
||||
$--msgbox-padding-primary: 15px !default;
|
||||
/// color||Color|0
|
||||
$--messagebox-success-color: $--color-success !default;
|
||||
/// color||Color|0
|
||||
$--messagebox-info-color: $--color-info !default;
|
||||
/// color||Color|0
|
||||
$--messagebox-warning-color: $--color-warning !default;
|
||||
/// color||Color|0
|
||||
$--messagebox-danger-color: $--color-danger !default;
|
||||
|
||||
/* Message
|
||||
-------------------------- */
|
||||
$--message-shadow: $--box-shadow-base !default;
|
||||
$--message-min-width: 380px !default;
|
||||
$--message-background-color: #edf2fc !default;
|
||||
$--message-padding: 15px 15px 15px 20px !default;
|
||||
/// color||Color|0
|
||||
$--message-close-icon-color: $--color-text-placeholder !default;
|
||||
/// height||Other|4
|
||||
$--message-close-size: 16px !default;
|
||||
/// color||Color|0
|
||||
$--message-close-hover-color: $--color-text-secondary !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--message-success-font-color: $--color-success !default;
|
||||
/// color||Color|0
|
||||
$--message-info-font-color: $--color-info !default;
|
||||
/// color||Color|0
|
||||
$--message-warning-font-color: $--color-warning !default;
|
||||
/// color||Color|0
|
||||
$--message-danger-font-color: $--color-danger !default;
|
||||
|
||||
/* Notification
|
||||
-------------------------- */
|
||||
$--notification-width: 330px !default;
|
||||
/// padding||Spacing|3
|
||||
$--notification-padding: 14px 26px 14px 13px !default;
|
||||
$--notification-radius: 8px !default;
|
||||
$--notification-shadow: $--box-shadow-light !default;
|
||||
/// color||Color|0
|
||||
$--notification-border-color: $--border-color-lighter !default;
|
||||
$--notification-icon-size: 24px !default;
|
||||
$--notification-close-font-size: $--message-close-size !default;
|
||||
$--notification-group-margin-left: 13px !default;
|
||||
$--notification-group-margin-right: 8px !default;
|
||||
/// fontSize||Font|1
|
||||
$--notification-content-font-size: $--font-size-base !default;
|
||||
/// color||Color|0
|
||||
$--notification-content-color: $--color-text-regular !default;
|
||||
/// fontSize||Font|1
|
||||
$--notification-title-font-size: 16px !default;
|
||||
/// color||Color|0
|
||||
$--notification-title-color: $--color-text-primary !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--notification-close-color: $--color-text-secondary !default;
|
||||
/// color||Color|0
|
||||
$--notification-close-hover-color: $--color-text-regular !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--notification-success-icon-color: $--color-success !default;
|
||||
/// color||Color|0
|
||||
$--notification-info-icon-color: $--color-info !default;
|
||||
/// color||Color|0
|
||||
$--notification-warning-icon-color: $--color-warning !default;
|
||||
/// color||Color|0
|
||||
$--notification-danger-icon-color: $--color-danger !default;
|
||||
|
||||
/* Input
|
||||
-------------------------- */
|
||||
$--input-font-size: $--font-size-base !default;
|
||||
/// color||Color|0
|
||||
$--input-font-color: $--color-text-regular !default;
|
||||
/// height||Other|4
|
||||
$--input-width: 140px !default;
|
||||
/// height||Other|4
|
||||
$--input-height: 40px !default;
|
||||
$--input-border: $--border-base !default;
|
||||
$--input-border-color: $--border-color-base !default;
|
||||
/// borderRadius||Border|2
|
||||
$--input-border-radius: $--border-radius-base !default;
|
||||
$--input-border-color-hover: $--border-color-hover !default;
|
||||
/// color||Color|0
|
||||
$--input-background-color: $--color-white !default;
|
||||
$--input-fill-disabled: $--disabled-fill-base !default;
|
||||
$--input-color-disabled: $--font-color-disabled-base !default;
|
||||
/// color||Color|0
|
||||
$--input-icon-color: $--color-text-placeholder !default;
|
||||
/// color||Color|0
|
||||
$--input-placeholder-color: $--color-text-placeholder !default;
|
||||
$--input-max-width: 314px !default;
|
||||
|
||||
$--input-hover-border: $--border-color-hover !default;
|
||||
$--input-clear-hover-color: $--color-text-secondary !default;
|
||||
|
||||
$--input-focus-border: $--color-primary !default;
|
||||
$--input-focus-fill: $--color-white !default;
|
||||
|
||||
$--input-disabled-fill: $--disabled-fill-base !default;
|
||||
$--input-disabled-border: $--disabled-border-base !default;
|
||||
$--input-disabled-color: $--disabled-color-base !default;
|
||||
$--input-disabled-placeholder-color: $--color-text-placeholder !default;
|
||||
|
||||
/// fontSize||Font|1
|
||||
$--input-medium-font-size: 14px !default;
|
||||
/// height||Other|4
|
||||
$--input-medium-height: 36px !default;
|
||||
/// fontSize||Font|1
|
||||
$--input-small-font-size: 13px !default;
|
||||
/// height||Other|4
|
||||
$--input-small-height: 32px !default;
|
||||
/// fontSize||Font|1
|
||||
$--input-mini-font-size: 12px !default;
|
||||
/// height||Other|4
|
||||
$--input-mini-height: 28px !default;
|
||||
|
||||
/* Cascader
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--cascader-menu-font-color: $--color-text-regular !default;
|
||||
/// color||Color|0
|
||||
$--cascader-menu-selected-font-color: $--color-primary !default;
|
||||
$--cascader-menu-fill: $--fill-base !default;
|
||||
$--cascader-menu-font-size: $--font-size-base !default;
|
||||
$--cascader-menu-radius: $--border-radius-base !default;
|
||||
$--cascader-menu-border: solid 1px $--border-color-light !default;
|
||||
$--cascader-menu-shadow: $--box-shadow-light !default;
|
||||
$--cascader-node-background-hover: $--background-color-base !default;
|
||||
$--cascader-node-color-disabled:$--color-text-placeholder !default;
|
||||
$--cascader-color-empty:$--color-text-placeholder !default;
|
||||
$--cascader-tag-background: #f0f2f5;
|
||||
|
||||
/* Group
|
||||
-------------------------- */
|
||||
$--group-option-flex: 0 0 (1/5) * 100% !default;
|
||||
$--group-option-offset-bottom: 12px !default;
|
||||
$--group-option-fill-hover: rgba($--color-black, 0.06) !default;
|
||||
$--group-title-color: $--color-black !default;
|
||||
$--group-title-font-size: $--font-size-base !default;
|
||||
$--group-title-width: 66px !default;
|
||||
|
||||
/* Tab
|
||||
-------------------------- */
|
||||
$--tab-font-size: $--font-size-base !default;
|
||||
$--tab-border-line: 1px solid #e4e4e4 !default;
|
||||
$--tab-header-color-active: $--color-text-secondary !default;
|
||||
$--tab-header-color-hover: $--color-text-regular !default;
|
||||
$--tab-header-color: $--color-text-regular !default;
|
||||
$--tab-header-fill-active: rgba($--color-black, 0.06) !default;
|
||||
$--tab-header-fill-hover: rgba($--color-black, 0.06) !default;
|
||||
$--tab-vertical-header-width: 90px !default;
|
||||
$--tab-vertical-header-count-color: $--color-white !default;
|
||||
$--tab-vertical-header-count-fill: $--color-text-secondary !default;
|
||||
|
||||
/* Button
|
||||
-------------------------- */
|
||||
/// fontSize||Font|1
|
||||
$--button-font-size: $--font-size-base !default;
|
||||
/// fontWeight||Font|1
|
||||
$--button-font-weight: $--font-weight-primary !default;
|
||||
/// borderRadius||Border|2
|
||||
$--button-border-radius: $--border-radius-base !default;
|
||||
/// padding||Spacing|3
|
||||
$--button-padding-vertical: 12px !default;
|
||||
/// padding||Spacing|3
|
||||
$--button-padding-horizontal: 20px !default;
|
||||
|
||||
/// fontSize||Font|1
|
||||
$--button-medium-font-size: $--font-size-base !default;
|
||||
/// borderRadius||Border|2
|
||||
$--button-medium-border-radius: $--border-radius-base !default;
|
||||
/// padding||Spacing|3
|
||||
$--button-medium-padding-vertical: 10px !default;
|
||||
/// padding||Spacing|3
|
||||
$--button-medium-padding-horizontal: 20px !default;
|
||||
|
||||
/// fontSize||Font|1
|
||||
$--button-small-font-size: 12px !default;
|
||||
$--button-small-border-radius: #{$--border-radius-base - 1} !default;
|
||||
/// padding||Spacing|3
|
||||
$--button-small-padding-vertical: 9px !default;
|
||||
/// padding||Spacing|3
|
||||
$--button-small-padding-horizontal: 15px !default;
|
||||
/// fontSize||Font|1
|
||||
$--button-mini-font-size: 12px !default;
|
||||
$--button-mini-border-radius: #{$--border-radius-base - 1} !default;
|
||||
/// padding||Spacing|3
|
||||
$--button-mini-padding-vertical: 7px !default;
|
||||
/// padding||Spacing|3
|
||||
$--button-mini-padding-horizontal: 15px !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--button-default-font-color: $--color-text-regular !default;
|
||||
/// color||Color|0
|
||||
$--button-default-background-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--button-default-border-color: $--border-color-base !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--button-disabled-font-color: $--color-text-placeholder !default;
|
||||
/// color||Color|0
|
||||
$--button-disabled-background-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--button-disabled-border-color: $--border-color-lighter !default;
|
||||
|
||||
/// color||Color|0
|
||||
$--button-primary-border-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--button-primary-font-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--button-primary-background-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--button-success-border-color: $--color-success !default;
|
||||
/// color||Color|0
|
||||
$--button-success-font-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--button-success-background-color: $--color-success !default;
|
||||
/// color||Color|0
|
||||
$--button-warning-border-color: $--color-warning !default;
|
||||
/// color||Color|0
|
||||
$--button-warning-font-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--button-warning-background-color: $--color-warning !default;
|
||||
/// color||Color|0
|
||||
$--button-danger-border-color: $--color-danger !default;
|
||||
/// color||Color|0
|
||||
$--button-danger-font-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--button-danger-background-color: $--color-danger !default;
|
||||
/// color||Color|0
|
||||
$--button-info-border-color: $--color-info !default;
|
||||
/// color||Color|0
|
||||
$--button-info-font-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--button-info-background-color: $--color-info !default;
|
||||
|
||||
$--button-hover-tint-percent: 20% !default;
|
||||
$--button-active-shade-percent: 10% !default;
|
||||
|
||||
|
||||
/* cascader
|
||||
-------------------------- */
|
||||
$--cascader-height: 200px !default;
|
||||
|
||||
/* Switch
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--switch-on-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--switch-off-color: $--border-color-base !default;
|
||||
/// fontSize||Font|1
|
||||
$--switch-font-size: $--font-size-base !default;
|
||||
$--switch-core-border-radius: 10px !default;
|
||||
// height||Other|4 TODO: width 代码写死的40px 所以下面这三个属性都没意义
|
||||
$--switch-width: 40px !default;
|
||||
// height||Other|4
|
||||
$--switch-height: 20px !default;
|
||||
// height||Other|4
|
||||
$--switch-button-size: 16px !default;
|
||||
|
||||
/* Dialog
|
||||
-------------------------- */
|
||||
$--dialog-background-color: $--color-white !default;
|
||||
$--dialog-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) !default;
|
||||
/// fontSize||Font|1
|
||||
$--dialog-title-font-size: $--font-size-large !default;
|
||||
/// fontSize||Font|1
|
||||
$--dialog-content-font-size: 14px !default;
|
||||
/// fontLineHeight||LineHeight|2
|
||||
$--dialog-font-line-height: $--font-line-height-primary !default;
|
||||
/// padding||Spacing|3
|
||||
$--dialog-padding-primary: 20px !default;
|
||||
|
||||
/* Table
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--table-border-color: $--border-color-lighter !default;
|
||||
$--table-border: 1px solid $--table-border-color !default;
|
||||
/// color||Color|0
|
||||
$--table-font-color: $--color-text-regular !default;
|
||||
/// color||Color|0
|
||||
$--table-header-font-color: $--color-text-secondary !default;
|
||||
/// color||Color|0
|
||||
$--table-row-hover-background-color: $--background-color-base !default;
|
||||
$--table-current-row-background-color: $--color-primary-light-9 !default;
|
||||
/// color||Color|0
|
||||
$--table-header-background-color: $--color-white !default;
|
||||
$--table-fixed-box-shadow: 0 0 10px rgba(0, 0, 0, .12) !default;
|
||||
|
||||
/* Pagination
|
||||
-------------------------- */
|
||||
/// fontSize||Font|1
|
||||
$--pagination-font-size: 13px !default;
|
||||
/// color||Color|0
|
||||
$--pagination-background-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--pagination-font-color: $--color-text-primary !default;
|
||||
$--pagination-border-radius: 3px !default;
|
||||
/// color||Color|0
|
||||
$--pagination-button-color: $--color-text-primary !default;
|
||||
/// height||Other|4
|
||||
$--pagination-button-width: 35.5px !default;
|
||||
/// height||Other|4
|
||||
$--pagination-button-height: 28px !default;
|
||||
/// color||Color|0
|
||||
$--pagination-button-disabled-color: $--color-text-placeholder !default;
|
||||
/// color||Color|0
|
||||
$--pagination-button-disabled-background-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--pagination-hover-color: $--color-primary !default;
|
||||
|
||||
/* Popup
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--popup-modal-background-color: $--color-black !default;
|
||||
/// opacity||Other|1
|
||||
$--popup-modal-opacity: 0.5 !default;
|
||||
|
||||
/* Popover
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--popover-background-color: $--color-white !default;
|
||||
/// fontSize||Font|1
|
||||
$--popover-font-size: $--font-size-base !default;
|
||||
/// color||Color|0
|
||||
$--popover-border-color: $--border-color-lighter !default;
|
||||
$--popover-arrow-size: 6px !default;
|
||||
/// padding||Spacing|3
|
||||
$--popover-padding: 12px !default;
|
||||
$--popover-padding-large: 18px 20px !default;
|
||||
/// fontSize||Font|1
|
||||
$--popover-title-font-size: 16px !default;
|
||||
/// color||Color|0
|
||||
$--popover-title-font-color: $--color-text-primary !default;
|
||||
|
||||
/* Tooltip
|
||||
-------------------------- */
|
||||
/// color|1|Color|0
|
||||
$--tooltip-fill: $--color-text-primary !default;
|
||||
/// color|1|Color|0
|
||||
$--tooltip-color: $--color-white !default;
|
||||
/// fontSize||Font|1
|
||||
$--tooltip-font-size: 12px !default;
|
||||
/// color||Color|0
|
||||
$--tooltip-border-color: $--color-text-primary !default;
|
||||
$--tooltip-arrow-size: 6px !default;
|
||||
/// padding||Spacing|3
|
||||
$--tooltip-padding: 10px !default;
|
||||
|
||||
/* Tag
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--tag-info-color: $--color-info !default;
|
||||
/// color||Color|0
|
||||
$--tag-primary-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--tag-success-color: $--color-success !default;
|
||||
/// color||Color|0
|
||||
$--tag-warning-color: $--color-warning !default;
|
||||
/// color||Color|0
|
||||
$--tag-danger-color: $--color-danger !default;
|
||||
/// fontSize||Font|1
|
||||
$--tag-font-size: 12px !default;
|
||||
$--tag-border-radius: 4px !default;
|
||||
$--tag-padding: 0 10px !default;
|
||||
|
||||
/* Tree
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--tree-node-hover-background-color: $--background-color-base !default;
|
||||
/// color||Color|0
|
||||
$--tree-font-color: $--color-text-regular !default;
|
||||
/// color||Color|0
|
||||
$--tree-expand-icon-color: $--color-text-placeholder !default;
|
||||
|
||||
/* Dropdown
|
||||
-------------------------- */
|
||||
$--dropdown-menu-box-shadow: $--box-shadow-light !default;
|
||||
$--dropdown-menuItem-hover-fill: $--color-primary-light-9 !default;
|
||||
$--dropdown-menuItem-hover-color: $--link-color !default;
|
||||
|
||||
/* Badge
|
||||
-------------------------- */
|
||||
/// color||Color|0
|
||||
$--badge-background-color: $--color-danger !default;
|
||||
$--badge-radius: 10px !default;
|
||||
/// fontSize||Font|1
|
||||
$--badge-font-size: 12px !default;
|
||||
/// padding||Spacing|3
|
||||
$--badge-padding: 6px !default;
|
||||
/// height||Other|4
|
||||
$--badge-size: 18px !default;
|
||||
|
||||
/* Card
|
||||
--------------------------*/
|
||||
/// color||Color|0
|
||||
$--card-border-color: $--border-color-lighter !default;
|
||||
$--card-border-radius: 4px !default;
|
||||
/// padding||Spacing|3
|
||||
$--card-padding: 20px !default;
|
||||
|
||||
/* Slider
|
||||
--------------------------*/
|
||||
/// color||Color|0
|
||||
$--slider-main-background-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--slider-runway-background-color: $--border-color-light !default;
|
||||
$--slider-button-hover-color: mix($--color-primary, black, 97%) !default;
|
||||
$--slider-stop-background-color: $--color-white !default;
|
||||
$--slider-disable-color: $--color-text-placeholder !default;
|
||||
$--slider-margin: 16px 0 !default;
|
||||
$--slider-border-radius: 3px !default;
|
||||
/// height|1|Other|4
|
||||
$--slider-height: 6px !default;
|
||||
/// height||Other|4
|
||||
$--slider-button-size: 16px !default;
|
||||
$--slider-button-wrapper-size: 36px !default;
|
||||
$--slider-button-wrapper-offset: -15px !default;
|
||||
|
||||
/* Steps
|
||||
--------------------------*/
|
||||
$--steps-border-color: $--disabled-border-base !default;
|
||||
$--steps-border-radius: 4px !default;
|
||||
$--steps-padding: 20px !default;
|
||||
|
||||
/* Menu
|
||||
--------------------------*/
|
||||
/// fontSize||Font|1
|
||||
$--menu-item-font-size: $--font-size-base !default;
|
||||
/// color||Color|0
|
||||
$--menu-item-font-color: $--color-text-primary !default;
|
||||
/// color||Color|0
|
||||
$--menu-background-color: $--color-white !default;
|
||||
$--menu-item-hover-fill: $--color-primary-light-9 !default;
|
||||
|
||||
/* Rate
|
||||
--------------------------*/
|
||||
$--rate-height: 20px !default;
|
||||
/// fontSize||Font|1
|
||||
$--rate-font-size: $--font-size-base !default;
|
||||
/// height||Other|3
|
||||
$--rate-icon-size: 18px !default;
|
||||
/// margin||Spacing|2
|
||||
$--rate-icon-margin: 6px !default;
|
||||
$--rate-icon-color: $--color-text-placeholder !default;
|
||||
|
||||
/* DatePicker
|
||||
--------------------------*/
|
||||
$--datepicker-font-color: $--color-text-regular !default;
|
||||
/// color|1|Color|0
|
||||
$--datepicker-off-font-color: $--color-text-placeholder !default;
|
||||
/// color||Color|0
|
||||
$--datepicker-header-font-color: $--color-text-regular !default;
|
||||
$--datepicker-icon-color: $--color-text-primary !default;
|
||||
$--datepicker-border-color: $--disabled-border-base !default;
|
||||
$--datepicker-inner-border-color: #e4e4e4 !default;
|
||||
/// color||Color|0
|
||||
$--datepicker-inrange-background-color: $--border-color-extra-light !default;
|
||||
/// color||Color|0
|
||||
$--datepicker-inrange-hover-background-color: $--border-color-extra-light !default;
|
||||
/// color||Color|0
|
||||
$--datepicker-active-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--datepicker-hover-font-color: $--color-primary !default;
|
||||
$--datepicker-cell-hover-color: #fff !default;
|
||||
|
||||
/* Loading
|
||||
--------------------------*/
|
||||
/// height||Other|4
|
||||
$--loading-spinner-size: 42px !default;
|
||||
/// height||Other|4
|
||||
$--loading-fullscreen-spinner-size: 50px !default;
|
||||
|
||||
/* Scrollbar
|
||||
--------------------------*/
|
||||
$--scrollbar-background-color: rgba($--color-text-secondary, .3) !default;
|
||||
$--scrollbar-hover-background-color: rgba($--color-text-secondary, .5) !default;
|
||||
|
||||
/* Carousel
|
||||
--------------------------*/
|
||||
/// fontSize||Font|1
|
||||
$--carousel-arrow-font-size: 12px !default;
|
||||
$--carousel-arrow-size: 36px !default;
|
||||
$--carousel-arrow-background: rgba(31, 45, 61, 0.11) !default;
|
||||
$--carousel-arrow-hover-background: rgba(31, 45, 61, 0.23) !default;
|
||||
/// width||Other|4
|
||||
$--carousel-indicator-width: 30px !default;
|
||||
/// height||Other|4
|
||||
$--carousel-indicator-height: 2px !default;
|
||||
$--carousel-indicator-padding-horizontal: 4px !default;
|
||||
$--carousel-indicator-padding-vertical: 12px !default;
|
||||
$--carousel-indicator-out-color: $--border-color-hover !default;
|
||||
|
||||
/* Collapse
|
||||
--------------------------*/
|
||||
/// color||Color|0
|
||||
$--collapse-border-color: $--border-color-lighter !default;
|
||||
/// height||Other|4
|
||||
$--collapse-header-height: 48px !default;
|
||||
/// color||Color|0
|
||||
$--collapse-header-background-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--collapse-header-font-color: $--color-text-primary !default;
|
||||
/// fontSize||Font|1
|
||||
$--collapse-header-font-size: 13px !default;
|
||||
/// color||Color|0
|
||||
$--collapse-content-background-color: $--color-white !default;
|
||||
/// fontSize||Font|1
|
||||
$--collapse-content-font-size: 13px !default;
|
||||
/// color||Color|0
|
||||
$--collapse-content-font-color: $--color-text-primary !default;
|
||||
|
||||
/* Transfer
|
||||
--------------------------*/
|
||||
$--transfer-border-color: $--border-color-lighter !default;
|
||||
$--transfer-border-radius: $--border-radius-base !default;
|
||||
/// height||Other|4
|
||||
$--transfer-panel-width: 200px !default;
|
||||
/// height||Other|4
|
||||
$--transfer-panel-header-height: 40px !default;
|
||||
/// color||Color|0
|
||||
$--transfer-panel-header-background-color: $--background-color-base !default;
|
||||
/// height||Other|4
|
||||
$--transfer-panel-footer-height: 40px !default;
|
||||
/// height||Other|4
|
||||
$--transfer-panel-body-height: 246px !default;
|
||||
/// height||Other|4
|
||||
$--transfer-item-height: 30px !default;
|
||||
/// height||Other|4
|
||||
$--transfer-filter-height: 32px !default;
|
||||
|
||||
/* Header
|
||||
--------------------------*/
|
||||
$--header-padding: 0 20px !default;
|
||||
|
||||
/* Footer
|
||||
--------------------------*/
|
||||
$--footer-padding: 0 20px !default;
|
||||
|
||||
/* Main
|
||||
--------------------------*/
|
||||
$--main-padding: 20px !default;
|
||||
|
||||
/* Timeline
|
||||
--------------------------*/
|
||||
$--timeline-node-size-normal: 12px !default;
|
||||
$--timeline-node-size-large: 14px !default;
|
||||
$--timeline-node-color: $--border-color-light !default;
|
||||
|
||||
/* Backtop
|
||||
--------------------------*/
|
||||
/// color||Color|0
|
||||
$--backtop-background-color: $--color-white !default;
|
||||
/// color||Color|0
|
||||
$--backtop-font-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--backtop-hover-background-color: $--border-color-extra-light !default;
|
||||
|
||||
/* Link
|
||||
--------------------------*/
|
||||
/// fontSize||Font|1
|
||||
$--link-font-size: $--font-size-base !default;
|
||||
/// fontWeight||Font|1
|
||||
$--link-font-weight: $--font-weight-primary !default;
|
||||
/// color||Color|0
|
||||
$--link-default-font-color: $--color-text-regular !default;
|
||||
/// color||Color|0
|
||||
$--link-default-active-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--link-disabled-font-color: $--color-text-placeholder !default;
|
||||
/// color||Color|0
|
||||
$--link-primary-font-color: $--color-primary !default;
|
||||
/// color||Color|0
|
||||
$--link-success-font-color: $--color-success !default;
|
||||
/// color||Color|0
|
||||
$--link-warning-font-color: $--color-warning !default;
|
||||
/// color||Color|0
|
||||
$--link-danger-font-color: $--color-danger !default;
|
||||
/// color||Color|0
|
||||
$--link-info-font-color: $--color-info !default;
|
||||
/* Calendar
|
||||
--------------------------*/
|
||||
/// border||Other|4
|
||||
$--calendar-border: $--table-border !default;
|
||||
/// color||Other|4
|
||||
$--calendar-selected-background-color: #F2F8FE !default;
|
||||
$--calendar-cell-width: 85px !default;
|
||||
|
||||
/* Form
|
||||
-------------------------- */
|
||||
/// fontSize||Font|1
|
||||
$--form-label-font-size: $--font-size-base !default;
|
||||
|
||||
/* Avatar
|
||||
--------------------------*/
|
||||
/// color||Color|0
|
||||
$--avatar-font-color: #fff !default;
|
||||
/// color||Color|0
|
||||
$--avatar-background-color: #C0C4CC !default;
|
||||
/// fontSize||Font Size|1
|
||||
$--avatar-text-font-size: 14px !default;
|
||||
/// fontSize||Font Size|1
|
||||
$--avatar-icon-font-size: 18px !default;
|
||||
/// borderRadius||Border|2
|
||||
$--avatar-border-radius: $--border-radius-base !default;
|
||||
/// size|1|Avatar Size|3
|
||||
$--avatar-large-size: 40px !default;
|
||||
/// size|1|Avatar Size|3
|
||||
$--avatar-medium-size: 36px !default;
|
||||
/// size|1|Avatar Size|3
|
||||
$--avatar-small-size: 28px !default;
|
||||
|
||||
/* Break-point
|
||||
--------------------------*/
|
||||
$--sm: 768px !default;
|
||||
$--md: 992px !default;
|
||||
$--lg: 1200px !default;
|
||||
$--xl: 1920px !default;
|
||||
|
||||
$--breakpoints: (
|
||||
'xs' : (max-width: $--sm - 1),
|
||||
'sm' : (min-width: $--sm),
|
||||
'md' : (min-width: $--md),
|
||||
'lg' : (min-width: $--lg),
|
||||
'xl' : (min-width: $--xl)
|
||||
);
|
||||
|
||||
$--breakpoints-spec: (
|
||||
'xs-only' : (max-width: $--sm - 1),
|
||||
'sm-and-up' : (min-width: $--sm),
|
||||
'sm-only': "(min-width: #{$--sm}) and (max-width: #{$--md - 1})",
|
||||
'sm-and-down': (max-width: $--md - 1),
|
||||
'md-and-up' : (min-width: $--md),
|
||||
'md-only': "(min-width: #{$--md}) and (max-width: #{$--lg - 1})",
|
||||
'md-and-down': (max-width: $--lg - 1),
|
||||
'lg-and-up' : (min-width: $--lg),
|
||||
'lg-only': "(min-width: #{$--lg}) and (max-width: #{$--xl - 1})",
|
||||
'lg-and-down': (max-width: $--xl - 1),
|
||||
'xl-only' : (min-width: $--xl),
|
||||
);
|
||||
13
client/src/style/index.css
Normal file
13
client/src/style/index.css
Normal file
@@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
@import 'element-variables';
|
||||
@import 'reboot';
|
||||
@@ -1,40 +0,0 @@
|
||||
const title = 'Ratteb';
|
||||
|
||||
export const getPageTitle = (pageTitle) => {
|
||||
if (pageTitle) {
|
||||
return `${pageTitle} - ${title}`;
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
// const clipboardSuccess = () => {
|
||||
// Vue.prototype.$message({
|
||||
// message: 'Copy successfully',
|
||||
// type: 'success',
|
||||
// duration: 1500,
|
||||
// });
|
||||
// };
|
||||
|
||||
// const clipboardError = () => {
|
||||
// Vue.prototype.$message({
|
||||
// message: 'Copy failed',
|
||||
// type: 'error',
|
||||
// });
|
||||
// };
|
||||
|
||||
export const handleClipboard = (text, event) => {
|
||||
// const clipboard = new Clipboard(event.target, {
|
||||
// text: () => text
|
||||
// })
|
||||
// clipboard.on('success', () => {
|
||||
// clipboardSuccess()
|
||||
// clipboard.destroy()
|
||||
// })
|
||||
// clipboard.on('error', () => {
|
||||
// clipboardError()
|
||||
// clipboard.destroy()
|
||||
// })
|
||||
// clipboard.onClick(event)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export const set = property => (store, payload) => (store[property] = payload)
|
||||
export const toggle = property => store => (store[property] = !store[property])
|
||||
@@ -1,14 +0,0 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'search-dialog',
|
||||
data() {
|
||||
return {
|
||||
current_state: 0,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user