This commit is contained in:
Pig Fang 2020-05-15 11:31:30 +08:00
parent 291efe730f
commit dfeff83b5e
19 changed files with 27 additions and 1543 deletions

View File

@ -1,39 +0,0 @@
{
"env": {
"production": {
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": false,
"loose": true
}
]
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"helpers": true,
"regenerator": true
}
]
]
},
"test": {
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
],
"plugins": [
"babel-plugin-dynamic-import-node"
]
}
}
}

View File

@ -12,11 +12,10 @@
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack --mode=production -p --progress",
"lint": "eslint --ext=js,vue,ts -f=beauty .",
"lint": "eslint --ext=ts -f=beauty .",
"test": "jest"
},
"dependencies": {
"@babel/runtime": "^7.8.0",
"@fortawesome/fontawesome-free": "^5.12.0",
"@hot-loader/react-dom": "^16.11.0",
"@tweenjs/tween.js": "^18.4.2",
@ -40,15 +39,10 @@
"skinview3d": "^1.2.1",
"spectre.css": "^0.5.8",
"use-immer": "^0.3.5",
"vue": "^2.6.11",
"vue-good-table": "^2.18.1",
"xterm": "^4.4.0",
"xterm-addon-fit": "^0.3.0"
},
"devDependencies": {
"@babel/core": "^7.8.7",
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/preset-env": "^7.8.7",
"@gplane/tsconfig": "^1.0.0",
"@testing-library/jest-dom": "^5.3.0",
"@testing-library/react": "^10.0.1",
@ -65,17 +59,11 @@
"@types/webpack": "^4.41.2",
"@typescript-eslint/eslint-plugin": "^2.8.0",
"@typescript-eslint/parser": "^2.8.0",
"@vue/test-utils": "^1.0.0-beta.29",
"autoprefixer": "^9.7.3",
"babel-jest": "^25.2.3",
"babel-loader": "^8.0.6",
"babel-plugin-dynamic-import-node": "^2.3.0",
"cache-loader": "^4.1.0",
"css-loader": "^3.4.2",
"eslint": "^6.7.1",
"eslint-config-gplane": "^6.2.1",
"eslint-formatter-beauty": "^3.0.0",
"eslint-plugin-vue": "^6.1.2",
"file-loader": "^5.0.2",
"jest": "^25.2.3",
"jest-extended": "^0.11.5",
@ -93,9 +81,6 @@
"ts-loader": "^7.0.4",
"typescript": "^3.9.2",
"url-loader": "^3.0.0",
"vue-jest": "^4.0.0-beta.2",
"vue-loader": "^15.8.3",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1",
@ -121,10 +106,8 @@
"eslintConfig": {
"root": true,
"extends": [
"gplane",
"gplane/vue"
"gplane"
],
"parser": "vue-eslint-parser",
"env": {
"node": true,
"es6": true,
@ -154,8 +137,7 @@
],
"extends": [
"gplane",
"gplane/typescript",
"gplane/vue"
"gplane/typescript"
],
"parserOptions": {
"parser": "@typescript-eslint/parser"
@ -190,14 +172,6 @@
120
]
}
},
{
"files": [
"resources/assets/src/components/mixins/*.ts"
],
"rules": {
"@typescript-eslint/no-extra-parens": 0
}
}
]
},
@ -206,15 +180,12 @@
"resetMocks": true,
"timers": "fake",
"transform": {
".*\\.js$": "babel-jest",
".*\\.tsx?$": "ts-jest",
".*\\.vue$": "vue-jest"
".*\\.tsx?$": "ts-jest"
},
"moduleFileExtensions": [
"js",
"ts",
"tsx",
"vue",
"json",
"node"
],

View File

@ -1,8 +0,0 @@
import Vue from 'vue'
import * as emitter from '../../scripts/event'
export default Vue.extend({
mounted() {
emitter.emit('mounted', { el: this.$root.$options.el })
},
})

View File

@ -1,40 +0,0 @@
import Vue from 'vue'
export default Vue.extend({
data: () => ({
columns: [{ field: 'id' }],
totalRecords: 0,
serverParams: {
sortField: 'id',
sortType: 'asc',
page: 1,
perPage: 10,
search: '',
},
}),
created() {
this.serverParams.sortField = this.columns[0].field
},
methods: {
fetchData(): Promise<void> {
return Promise.resolve()
},
onPageChange(params: { currentPage: number }) {
this.serverParams.page = params.currentPage
this.fetchData()
},
onPerPageChange(params: { currentPerPage: number }) {
this.serverParams.perPage = params.currentPerPage
this.fetchData()
},
onSortChange([params]: Array<{ type: 'asc' | 'desc', field: string }>) {
this.serverParams.sortType = params.type
this.serverParams.sortField = params.field
this.fetchData()
},
onSearch(params: { searchTerm: string }) {
this.serverParams.search = params.searchTerm
this.fetchData()
},
},
})

View File

@ -1,22 +0,0 @@
import Vue from 'vue'
export default Vue.extend({
data() {
return {
tableOptions: {
search: {
enabled: true,
placeholder: this.$t('vendor.datatable.search'),
},
pagination: {
enabled: true,
nextLabel: this.$t('vendor.datatable.next'),
prevLabel: this.$t('vendor.datatable.prev'),
rowsPerPageLabel: this.$t('vendor.datatable.rowsPerPage'),
allLabel: this.$t('vendor.datatable.all'),
ofLabel: this.$t('vendor.datatable.of'),
},
},
}
},
})

View File

@ -45,18 +45,5 @@ async function loadModules() {
setTimeout(() => emitter.emit('mounted', { el: route.el }), 0)
})
}
if (route.component) {
const { default: Vue } = await import('vue')
const { default: inject } = await import('./scripts/injectVue')
inject(Vue)
Vue.prototype.$route = new RegExp(`^${route.path}$`, 'i').exec(
blessing.route,
)
// eslint-disable-next-line no-new
new Vue({
el: route.el,
render: (h) => h(route.component),
})
}
}
}

View File

@ -1,42 +0,0 @@
import type { VueConstructor } from 'vue'
import { t } from './i18n'
import * as fetch from './net'
export default function (Vue: VueConstructor) {
injectI18n(Vue)
injectFetch(Vue)
}
function injectI18n(Vue: VueConstructor) {
Vue.use((_Vue) => {
// eslint-disable-next-line @typescript-eslint/unbound-method
_Vue.prototype.$t = t
_Vue.directive('t', (el, { value }) => {
if (typeof value === 'string') {
el.textContent = t(value)
} else if (typeof value === 'object') {
el.textContent = t(value.path, value.args)
} else {
/* istanbul ignore next */
// eslint-disable-next-line no-lonely-if
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.warn('[i18n] Invalid arguments in `v-t` directive.')
}
}
})
})
}
function injectFetch(Vue: VueConstructor) {
Vue.use((_Vue) => {
Object.defineProperty(_Vue.prototype, '$http', {
get: () => ({
get: fetch.get,
post: fetch.post,
put: fetch.put,
del: fetch.del,
}),
})
})
}

View File

@ -1,4 +1,3 @@
import Vue from 'vue'
import JQuery from 'jquery'
import { ModalOptions, ModalResult } from './components/Modal'
import { Toast } from './scripts/toast'
@ -35,18 +34,3 @@ declare global {
}
}
}
declare module 'vue/types/vue' {
interface Vue {
$t(key: string, parameters?: object): string
$http: {
get(url: string, params?: object): Promise<any>
post(url: string, data?: object): Promise<{ code?: number, message?: string }>
put(url: string, data?: object): Promise<{ code?: number, message?: string }>
del(url: string, data?: object): Promise<{ code?: number, message?: string }>
}
$route: RegExpExecArray | null
}
}

View File

@ -1,9 +1,3 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
declare module '*.styl' {
export default {} as Record<string, string>
}

View File

@ -1,47 +0,0 @@
<template>
<div class="vgt-table">
<input
v-model="search"
class="vgt-input"
@input="$emit('on-search', { searchTerm: search })"
>
<div v-if="rows.length === 0">No data</div>
<table v-else>
<tbody>
<tr v-for="(row, i) in rows" :key="i" :class="getRowClass(row)">
<td v-for="col in columns" :key="col.field">
<slot
name="table-row"
:row="Object.assign(row, { originalIndex: i })"
:column="{ field: col.field }"
:formattedRow="{ [col.field]: row[col.field] }"
/>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: 'VueGoodTable',
// eslint-disable-next-line vue/require-prop-types
props: ['rows', 'columns', 'rowStyleClass'],
data() {
return {
search: '',
}
},
methods: {
getRowClass(row) {
if (typeof this.rowStyleClass === 'function') {
return { [this.rowStyleClass(row)]: true }
} else if (typeof this.rowStyleClass === 'string') {
return { [this.rowStyleClass]: true }
}
return {}
},
},
}
</script>

View File

@ -1,3 +0,0 @@
import VueGoodTable from './vgt.vue'
export { VueGoodTable }

View File

@ -1,42 +0,0 @@
import { mount } from '@vue/test-utils'
import serverTable from '@/components/mixins/serverTable'
test('change current page', () => {
const wrapper = mount(serverTable)
jest.spyOn(wrapper.vm, 'fetchData')
wrapper.vm.onPageChange({ currentPage: 2 })
expect(wrapper.vm.fetchData).toBeCalled()
expect(wrapper.vm.serverParams.page).toBe(2)
})
test('change per page', () => {
const wrapper = mount(serverTable)
jest.spyOn(wrapper.vm, 'fetchData')
wrapper.vm.onPerPageChange({ currentPerPage: 2 })
expect(wrapper.vm.fetchData).toBeCalled()
expect(wrapper.vm.serverParams.perPage).toBe(2)
})
test('change sort type', () => {
const wrapper = mount(serverTable)
jest.spyOn(wrapper.vm, 'fetchData')
wrapper.setData({
columns: [
{ field: '0' },
{ field: '1' },
{ field: '2' },
],
})
wrapper.vm.onSortChange([{ type: 'desc', field: '2' }])
expect(wrapper.vm.fetchData).toBeCalled()
expect(wrapper.vm.serverParams.sortType).toBe('desc')
expect(wrapper.vm.serverParams.sortField).toBe('2')
})
test('search', () => {
const wrapper = mount(serverTable)
jest.spyOn(wrapper.vm, 'fetchData')
wrapper.vm.onSearch({ searchTerm: 'q' })
expect(wrapper.vm.fetchData).toBeCalled()
expect(wrapper.vm.serverParams.search).toBe('q')
})

View File

@ -1,5 +1,4 @@
import { trans } from '@/scripts/i18n'
import Vue from 'vue'
test('mount to global', () => {
expect(window.trans).toBe(trans)
@ -12,47 +11,3 @@ test('translate text', () => {
expect(trans('a.b.d', { name: 'me' })).toBe('Hi, me!')
expect(trans('d.e')).toBe('d.e')
})
test('Vue directive', () => {
const byString = Vue.extend({
render(h) {
return h('div', {
directives: [
{
name: 't',
value: 'abc',
},
],
})
},
})
expect((new Vue(byString)).$mount().$el.textContent).toBe('abc')
const byObject = Vue.extend({
render(h) {
return h('div', {
directives: [
{
name: 't',
value: { path: 'abc', args: '123' },
},
],
})
},
})
expect((new Vue(byObject)).$mount().$el.textContent).toBe('abc')
const invalid = Vue.extend({
render(h) {
return h('div', {
directives: [
{
name: 't',
value: 123,
},
],
})
},
})
expect((new Vue(invalid)).$mount().$el.textContent).toBe('')
})

View File

@ -1,4 +1,3 @@
import Vue from 'vue'
import * as net from '@/scripts/net'
import { on } from '@/scripts/event'
import { trans, t } from '@/scripts/i18n'
@ -261,8 +260,3 @@ test('process backend errors', async () => {
okButtonType: 'outline-light',
})
})
test('inject to Vue instance', () => {
expect(typeof Vue.prototype.$http.get).toBe('function')
expect(typeof Vue.prototype.$http.post).toBe('function')
})

View File

@ -2,7 +2,6 @@
import * as fs from 'fs'
import 'jest-extended'
import '@testing-library/jest-dom'
import Vue from 'vue'
import yaml from 'js-yaml'
window.blessing = {
@ -41,22 +40,3 @@ Object.assign(console, {
warn: noop,
error: noop,
})
Vue.prototype.$t = key => key
Vue.directive('t', (el: Element, { value }) => {
if (typeof value === 'string') {
el.innerHTML = value
} else if (typeof value === 'object') {
el.innerHTML = value.path
} else {
throw new Error('[i18n] Invalid arguments in `v-t` directive.')
}
})
Vue.prototype.$http = {
get: jest.fn(),
post: jest.fn(),
put: jest.fn(),
del: jest.fn(),
}

View File

@ -1,15 +0,0 @@
import Vue from 'vue'
declare module 'vue/types/vue' {
interface VueConstructor {
prototype: Vue & {
$http: {
get: jest.Mock<any>
post: jest.Mock<any>
put: jest.Mock<any>
del: jest.Mock<any>
}
$t(key: string, parameters?: object): string
}
}
}

View File

@ -1,9 +1,3 @@
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
declare module '*.styl' {
export default {} as Record<string, string>
}

View File

@ -1,6 +1,5 @@
const path = require('path')
const webpack = require('webpack')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
@ -31,11 +30,6 @@ const config = {
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ['cache-loader', 'babel-loader'],
},
{
test: /\.tsx?$/,
loader: 'ts-loader',
@ -44,19 +38,6 @@ const config = {
transpileOnly: true,
},
},
{
test: /\.vue$/,
use: ['cache-loader', 'vue-loader'],
},
{
test: /\.vue.*\.stylus$/,
use: [
'vue-style-loader',
{ loader: 'css-loader', options: { importLoaders: 2 } },
'postcss-loader',
'stylus-loader',
],
},
{
test: /\.scss$/,
exclude: /\.module\.scss$/,
@ -120,17 +101,15 @@ const config = {
loader: devMode ? 'url-loader' : 'file-loader',
},
],
noParse: /^(vue|jquery)$/,
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: devMode ? '[name].css' : '[name].[contenthash:7].css',
chunkFilename: devMode ? '[id].css' : '[id].[contenthash:7].css',
}),
],
resolve: {
extensions: ['.js', '.ts', '.tsx', '.vue', '.json'],
extensions: ['.js', '.ts', '.tsx', '.json'],
alias: {
'react-dom': '@hot-loader/react-dom',
'@': path.resolve(__dirname, 'resources/assets/src'),

1140
yarn.lock

File diff suppressed because it is too large Load Diff