mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-10 09:55:48 +02:00
chore: migrate to ESlint v9
This commit is contained in:
parent
8c00292fa1
commit
4f25a0c670
142 changed files with 4387 additions and 2052 deletions
0
.editorconfig
Executable file → Normal file
0
.editorconfig
Executable file → Normal file
10
.idea/inspectionProfiles/Project_Default.xml
generated
10
.idea/inspectionProfiles/Project_Default.xml
generated
|
@ -2,5 +2,15 @@
|
|||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="myValues">
|
||||
<value>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="vue-dompurify-html" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myCustomValuesEnabled" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
|
@ -1,257 +0,0 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
},
|
||||
extends: [
|
||||
'@antfu/eslint-config-vue',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:import/recommended',
|
||||
'plugin:import/typescript',
|
||||
'plugin:sonarjs/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
|
||||
// 'plugin:unicorn/recommended',
|
||||
],
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 13,
|
||||
parser: '@typescript-eslint/parser',
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: [
|
||||
'vue',
|
||||
'@typescript-eslint',
|
||||
'regex',
|
||||
],
|
||||
ignorePatterns: ['src/@iconify/*.js', 'node_modules', 'dist', '*.d.ts'],
|
||||
rules: {
|
||||
'vue/no-v-html': 'off',
|
||||
|
||||
'vue/block-tag-newline': 'off',
|
||||
// eslint-disable-next-line n/prefer-global/process
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
// eslint-disable-next-line n/prefer-global/process
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
|
||||
// indentation (Already present in TypeScript)
|
||||
'comma-spacing': ['error', {
|
||||
before: false,
|
||||
after: true,
|
||||
}],
|
||||
'key-spacing': ['error', {afterColon: true}],
|
||||
|
||||
'vue/first-attribute-linebreak': ['error', {
|
||||
singleline: 'beside',
|
||||
multiline: 'below',
|
||||
}],
|
||||
|
||||
'antfu/top-level-function': 'off',
|
||||
|
||||
// Enforce trailing comma (Already present in TypeScript)
|
||||
'comma-dangle': ['error', 'always-multiline'],
|
||||
|
||||
// Disable max-len
|
||||
'max-len': 'off',
|
||||
|
||||
// we don't want it
|
||||
'semi': ['error', 'never'],
|
||||
|
||||
// add parens ony when required in arrow function
|
||||
'arrow-parens': ['error', 'as-needed'],
|
||||
|
||||
// add new line above comment
|
||||
'newline-before-return': 'error',
|
||||
|
||||
// add new line above comment
|
||||
'lines-around-comment': [
|
||||
'error',
|
||||
{
|
||||
beforeBlockComment: true,
|
||||
beforeLineComment: true,
|
||||
allowBlockStart: true,
|
||||
allowClassStart: true,
|
||||
allowObjectStart: true,
|
||||
allowArrayStart: true,
|
||||
},
|
||||
],
|
||||
|
||||
// Ignore _ as unused variable
|
||||
'@typescript-eslint/no-unused-vars': ['error', {argsIgnorePattern: '^_+$'}],
|
||||
|
||||
'array-element-newline': ['error', 'consistent'],
|
||||
'array-bracket-newline': ['error', 'consistent'],
|
||||
|
||||
'vue/multi-word-component-names': 'off',
|
||||
|
||||
'padding-line-between-statements': [
|
||||
'error',
|
||||
{
|
||||
blankLine: 'always',
|
||||
prev: 'expression',
|
||||
next: 'const',
|
||||
},
|
||||
{
|
||||
blankLine: 'always',
|
||||
prev: 'const',
|
||||
next: 'expression',
|
||||
},
|
||||
{
|
||||
blankLine: 'always',
|
||||
prev: 'multiline-const',
|
||||
next: '*',
|
||||
},
|
||||
{
|
||||
blankLine: 'always',
|
||||
prev: '*',
|
||||
next: 'multiline-const',
|
||||
},
|
||||
],
|
||||
|
||||
// Plugin: eslint-plugin-import
|
||||
'import/prefer-default-export': 'off',
|
||||
'import/newline-after-import': ['error', {count: 1}],
|
||||
'no-restricted-imports': ['error', 'vuetify/components'],
|
||||
|
||||
// For omitting extension for ts files
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'ignorePackages',
|
||||
{
|
||||
mjs: 'never',
|
||||
js: 'never',
|
||||
jsx: 'never',
|
||||
ts: 'never',
|
||||
tsx: 'never',
|
||||
},
|
||||
],
|
||||
|
||||
// ignore virtual files
|
||||
'import/no-unresolved': [2, {
|
||||
ignore: [
|
||||
'~pages$',
|
||||
'virtual:generated-layouts',
|
||||
|
||||
// Ignore vite's ?raw imports
|
||||
'.*\?raw',
|
||||
],
|
||||
}],
|
||||
|
||||
// Thanks: https://stackoverflow.com/a/63961972/10796681
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
|
||||
// Plugin: eslint-plugin-promise
|
||||
'promise/always-return': 'off',
|
||||
'promise/catch-or-return': 'off',
|
||||
|
||||
// ESLint plugin vue
|
||||
'vue/component-api-style': 'error',
|
||||
'vue/component-name-in-template-casing': ['error', 'PascalCase', {registeredComponentsOnly: false}],
|
||||
'vue/custom-event-name-casing': ['error', 'camelCase', {
|
||||
ignores: [
|
||||
'/^(click):[a-z]+((\d)|([A-Z0-9][a-z0-9]+))*([A-Z])?/',
|
||||
],
|
||||
}],
|
||||
'vue/define-macros-order': 'error',
|
||||
'vue/html-comment-content-newline': 'error',
|
||||
'vue/html-comment-content-spacing': 'error',
|
||||
'vue/html-comment-indent': 'error',
|
||||
'vue/match-component-file-name': 'error',
|
||||
'vue/no-child-content': 'error',
|
||||
'vue/require-default-prop': 'off',
|
||||
|
||||
// NOTE this rule only supported in SFC, Users of the unplugin-vue-define-options should disable that rule: https://github.com/vuejs/eslint-plugin-vue/issues/1886
|
||||
// 'vue/no-duplicate-attr-inheritance': 'error',
|
||||
'vue/no-multiple-objects-in-class': 'error',
|
||||
'vue/no-reserved-component-names': 'error',
|
||||
'vue/no-template-target-blank': 'error',
|
||||
'vue/no-useless-mustaches': 'error',
|
||||
'vue/no-useless-v-bind': 'error',
|
||||
'vue/padding-line-between-blocks': 'error',
|
||||
'vue/prefer-separate-static-class': 'error',
|
||||
'vue/prefer-true-attribute-shorthand': 'error',
|
||||
'vue/v-on-function-call': 'error',
|
||||
'vue/valid-v-slot': ['error', {
|
||||
allowModifiers: true,
|
||||
}],
|
||||
|
||||
// -- Extension Rules
|
||||
'vue/no-irregular-whitespace': 'error',
|
||||
|
||||
// -- Sonarlint
|
||||
'sonarjs/no-duplicate-string': 'off',
|
||||
'sonarjs/no-nested-template-literals': 'off',
|
||||
|
||||
// -- Unicorn
|
||||
// 'unicorn/filename-case': 'off',
|
||||
// 'unicorn/prevent-abbreviations': ['error', {
|
||||
// replacements: {
|
||||
// props: false,
|
||||
// },
|
||||
// }],
|
||||
// https://github.com/gmullerb/eslint-plugin-regex
|
||||
'regex/invalid': [
|
||||
'error',
|
||||
[
|
||||
{
|
||||
regex: '@/assets/images',
|
||||
replacement: '@images',
|
||||
message: 'Use \'@images\' path alias for image imports',
|
||||
},
|
||||
{
|
||||
regex: '@/styles',
|
||||
replacement: '@styles',
|
||||
message: 'Use \'@styles\' path alias for importing styles from \'src/styles\'',
|
||||
},
|
||||
|
||||
// {
|
||||
// id: 'Disallow icon of icon library',
|
||||
// regex: 'tabler-\\w',
|
||||
// message: 'Only \'mdi\' icons are allowed',
|
||||
// },
|
||||
|
||||
{
|
||||
regex: '@core/\\w',
|
||||
message: 'You can\'t use @core when you are in @layouts module',
|
||||
files: {
|
||||
inspect: '@layouts/.*',
|
||||
},
|
||||
},
|
||||
{
|
||||
regex: 'useLayouts\\(',
|
||||
message: '`useLayouts` composable is only allowed in @layouts & @core directory. Please use `useThemeConfig` composable instead.',
|
||||
files: {
|
||||
inspect: '^(?!.*(@core|@layouts)).*',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
// Ignore files
|
||||
'\.eslintrc\.js',
|
||||
],
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.ts', '.js', '.tsx', '.jsx', '.mjs', '.png', '.jpg'],
|
||||
},
|
||||
typescript: {},
|
||||
alias: {
|
||||
map: [
|
||||
['@', './src'],
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.json'],
|
||||
rules: {
|
||||
'no-invalid-meta': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
3
app/env.d.ts
vendored
3
app/env.d.ts
vendored
|
@ -1,5 +1,6 @@
|
|||
declare module '*.svg' {
|
||||
import React from 'react'
|
||||
import type React from 'react'
|
||||
|
||||
const content: React.FC<React.SVGProps<SVGElement>>
|
||||
export default content
|
||||
}
|
||||
|
|
52
app/eslint.config.mjs
Normal file
52
app/eslint.config.mjs
Normal file
|
@ -0,0 +1,52 @@
|
|||
import createConfig from '@antfu/eslint-config'
|
||||
import sonarjs from 'eslint-plugin-sonarjs'
|
||||
|
||||
export default createConfig(
|
||||
{
|
||||
stylistic: true,
|
||||
ignores: ['**/version.json', 'tsconfig.json', 'tsconfig.node.json'],
|
||||
},
|
||||
sonarjs.configs.recommended,
|
||||
{
|
||||
name: '@nginx-ui/eslint-config',
|
||||
rules: {
|
||||
'no-console': 'warn',
|
||||
'no-alert': 'warn',
|
||||
'ts/no-explicit-any': 'warn',
|
||||
'vue/no-unused-refs': 'warn',
|
||||
'vue/prop-name-casing': 'warn',
|
||||
'node/prefer-global/process': 'off',
|
||||
'unused-imports/no-unused-vars': 'warn',
|
||||
|
||||
// https://eslint.org/docs/latest/rules/dot-notation
|
||||
'style/dot-notation': 'off',
|
||||
|
||||
// https://eslint.org/docs/latest/rules/arrow-parens
|
||||
'style/arrow-parens': ['error', 'as-needed'],
|
||||
|
||||
// https://eslint.org/docs/latest/rules/prefer-template
|
||||
'prefer-template': 'error',
|
||||
|
||||
// https://eslint.style/rules/js/arrow-spacing
|
||||
'style/arrow-spacing': ['error', { before: true, after: true }],
|
||||
|
||||
// https://github.com/un-ts/eslint-plugin-import-x/blob/master/docs/rules/prefer-default-export.md
|
||||
'import/prefer-default-export': 'off',
|
||||
|
||||
// https://eslint.vuejs.org/rules/require-typed-ref
|
||||
'vue/require-typed-ref': 'warn',
|
||||
|
||||
// https://eslint.vuejs.org/rules/require-prop-types
|
||||
'vue/require-prop-types': 'warn',
|
||||
|
||||
// https://eslint.vuejs.org/rules/no-ref-as-operand.html
|
||||
'vue/no-ref-as-operand': 'error',
|
||||
|
||||
// -- Sonarlint
|
||||
'sonarjs/no-duplicate-string': 'off',
|
||||
'sonarjs/no-nested-template-literals': 'off',
|
||||
'sonarjs/pseudo-random': 'warn',
|
||||
'sonarjs/no-nested-functions': 'off',
|
||||
},
|
||||
},
|
||||
)
|
|
@ -1,4 +1,3 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const i18n = require('./i18n.json')
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
{
|
||||
"name": "nginx-ui-app-next",
|
||||
"version": "2.0.0-beta.36",
|
||||
"type": "module",
|
||||
"version": "2.0.0-beta.36",
|
||||
"packageManager": "pnpm@9.10.0",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"typecheck": "vue-tsc --noEmit",
|
||||
"lint": "eslint . -c .eslintrc.cjs --fix --ext .ts,.vue,.tsx,.d.ts",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"gettext:extract": "vue-gettext-extract"
|
||||
|
@ -39,6 +41,7 @@
|
|||
"universal-cookie": "^7.2.1",
|
||||
"vite-plugin-build-id": "0.4.2",
|
||||
"vue": "^3.5.12",
|
||||
"vue-dompurify-html": "^5.1.0",
|
||||
"vue-router": "^4.4.5",
|
||||
"vue3-ace-editor": "2.2.4",
|
||||
"vue3-apexcharts": "1.5.3",
|
||||
|
@ -47,26 +50,19 @@
|
|||
"vuedraggable": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config-vue": "^0.43.1",
|
||||
"@antfu/eslint-config": "^3.8.0",
|
||||
"@simplewebauthn/types": "^11.0.0",
|
||||
"@types/lodash": "^4.17.12",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"@vitejs/plugin-vue": "^5.1.4",
|
||||
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
||||
"@vue/compiler-sfc": "^3.5.12",
|
||||
"@vue/tsconfig": "^0.5.1",
|
||||
"ace-builds": "^1.36.3",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-import-resolver-typescript": "^3.6.3",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-regex": "^1.10.0",
|
||||
"eslint-plugin-sonarjs": "^0.23.0",
|
||||
"eslint-plugin-vue": "^9.29.1",
|
||||
"eslint": "^9.13.0",
|
||||
"eslint-plugin-sonarjs": "^2.0.4",
|
||||
"less": "^4.2.0",
|
||||
"postcss": "^8.4.47",
|
||||
"tailwindcss": "^3.4.14",
|
||||
|
@ -74,9 +70,8 @@
|
|||
"unplugin-auto-import": "^0.18.3",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"unplugin-vue-define-options": "^1.5.2",
|
||||
"vite": "^5.4.9",
|
||||
"vite": "^5.4.10",
|
||||
"vite-svg-loader": "^5.1.0",
|
||||
"vue-tsc": "^2.1.6"
|
||||
},
|
||||
"packageManager": "pnpm@9.10.0"
|
||||
}
|
||||
}
|
||||
|
|
4351
app/pnpm-lock.yaml
generated
4351
app/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
@ -1,22 +1,21 @@
|
|||
<script setup lang="ts">
|
||||
import loadTranslations from '@/api/translations'
|
||||
import gettext from '@/gettext'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import { theme } from 'ant-design-vue'
|
||||
import en_US from 'ant-design-vue/es/locale/en_US'
|
||||
|
||||
import zh_CN from 'ant-design-vue/es/locale/zh_CN'
|
||||
import zh_TW from 'ant-design-vue/es/locale/zh_TW'
|
||||
// This starter template is using Vue 3 <script setup> SFCs
|
||||
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
||||
import { computed, provide } from 'vue'
|
||||
import { theme } from 'ant-design-vue'
|
||||
import zh_CN from 'ant-design-vue/es/locale/zh_CN'
|
||||
import zh_TW from 'ant-design-vue/es/locale/zh_TW'
|
||||
import en_US from 'ant-design-vue/es/locale/en_US'
|
||||
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import gettext from '@/gettext'
|
||||
import loadTranslations from '@/api/translations'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const media = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
|
||||
const callback = () => {
|
||||
function callback() {
|
||||
const settings = useSettingsStore()
|
||||
if (settings.preference_theme === 'auto') {
|
||||
if (media.matches)
|
||||
|
|
|
@ -23,7 +23,7 @@ const twoFA = {
|
|||
begin_start_secure_session_by_passkey() {
|
||||
return http.get('/2fa_secure_session/passkey')
|
||||
},
|
||||
finish_start_secure_session_by_passkey(data: { session_id: string; options: AuthenticationResponseJSON }): Promise<{
|
||||
finish_start_secure_session_by_passkey(data: { session_id: string, options: AuthenticationResponseJSON }): Promise<{
|
||||
session_id: string
|
||||
}> {
|
||||
return http.post('/2fa_secure_session/passkey', data.options, {
|
||||
|
|
|
@ -41,7 +41,7 @@ const auth = {
|
|||
begin_passkey_login() {
|
||||
return http.get('/begin_passkey_login')
|
||||
},
|
||||
finish_passkey_login(data: { session_id: string; options: AuthenticationResponseJSON }) {
|
||||
finish_passkey_login(data: { session_id: string, options: AuthenticationResponseJSON }) {
|
||||
return http.post('/finish_passkey_login', data.options, {
|
||||
headers: {
|
||||
'X-Passkey-Session-Id': data.session_id,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import type { ModelBase } from '@/api/curd'
|
||||
import Curd from '@/api/curd'
|
||||
import type { DnsCredential } from '@/api/dns_credential'
|
||||
import type { AcmeUser } from '@/api/acme_user'
|
||||
import type { ModelBase } from '@/api/curd'
|
||||
import type { DnsCredential } from '@/api/dns_credential'
|
||||
import type { PrivateKeyType } from '@/constants'
|
||||
import Curd from '@/api/curd'
|
||||
|
||||
export interface Cert extends ModelBase {
|
||||
name: string
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Curd from '@/api/curd'
|
||||
import type { ChatComplicationMessage } from '@/api/openai'
|
||||
import Curd from '@/api/curd'
|
||||
import http from '@/lib/http'
|
||||
|
||||
export interface Config {
|
||||
|
|
|
@ -34,27 +34,27 @@ class Curd<T> {
|
|||
this.plural = plural ?? `${this.baseUrl}s`
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
_get_list(params: any = null): Promise<GetListResponse<T>> {
|
||||
return http.get(this.plural, { params })
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
_get(id: any = null, params: any = {}): Promise<T> {
|
||||
return http.get(this.baseUrl + (id ? `/${id}` : ''), { params })
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
_save(id: any = null, data: any, config: any = undefined): Promise<T> {
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
_save(id: any = null, data: any = undefined, config: any = undefined): Promise<T> {
|
||||
return http.post(this.baseUrl + (id ? `/${id}` : ''), data, config)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
_destroy(id: any = null, params: any = {}) {
|
||||
return http.delete(`${this.baseUrl}/${id}`, { params })
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
_recover(id: any = null) {
|
||||
return http.patch(`${this.baseUrl}/${id}`)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { DNSProvider } from '@/api/auto_cert'
|
||||
import type { ModelBase } from '@/api/curd'
|
||||
import Curd from '@/api/curd'
|
||||
import type { DNSProvider } from '@/api/auto_cert'
|
||||
|
||||
export interface DnsCredential extends ModelBase {
|
||||
name: string
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import Curd from '@/api/curd'
|
||||
import http from '@/lib/http'
|
||||
import type { ChatComplicationMessage } from '@/api/openai'
|
||||
import type { CertificateInfo } from '@/api/cert'
|
||||
import type { NgxConfig } from '@/api/ngx'
|
||||
import type { ChatComplicationMessage } from '@/api/openai'
|
||||
import type { PrivateKeyType } from '@/constants'
|
||||
import Curd from '@/api/curd'
|
||||
import http from '@/lib/http'
|
||||
|
||||
export interface Site {
|
||||
modified_at: string
|
||||
|
@ -26,7 +26,7 @@ export interface AutoCertRequest {
|
|||
}
|
||||
|
||||
class Domain extends Curd<Site> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
enable(name: string, config?: any) {
|
||||
return http.post(`${this.baseUrl}/${name}/enable`, undefined, config)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import http from '@/lib/http'
|
||||
import type { ModelBase } from '@/api/curd'
|
||||
import Curd from '@/api/curd'
|
||||
import http from '@/lib/http'
|
||||
|
||||
export interface Environment extends ModelBase {
|
||||
name: string
|
||||
|
|
|
@ -8,7 +8,7 @@ export interface INginxLogData {
|
|||
}
|
||||
|
||||
const nginx_log = {
|
||||
page(page = 0, data: INginxLogData) {
|
||||
page(page = 0, data: INginxLogData | undefined = undefined) {
|
||||
return http.post(`/nginx_log?page=${page}`, data)
|
||||
},
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ const ngx = {
|
|||
return http.post('/ngx/format_code', { content })
|
||||
},
|
||||
|
||||
status(): Promise<{ running: boolean; message: string; level: number }> {
|
||||
status(): Promise<{ running: boolean, message: string, level: number }> {
|
||||
return http.get('/nginx/status')
|
||||
},
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ export interface ChatComplicationMessage {
|
|||
}
|
||||
|
||||
const openai = {
|
||||
store_record(data: { file_name?: string; messages?: ChatComplicationMessage[] }) {
|
||||
store_record(data: { file_name?: string, messages?: ChatComplicationMessage[] }) {
|
||||
return http.post('/chatgpt_record', data)
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { ModelBase } from '@/api/curd'
|
||||
import type { RegistrationResponseJSON } from '@simplewebauthn/types'
|
||||
import http from '@/lib/http'
|
||||
import type { ModelBase } from '@/api/curd'
|
||||
|
||||
export interface Passkey extends ModelBase {
|
||||
name: string
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { NgxConfig } from '@/api/ngx'
|
||||
import type { ChatComplicationMessage } from '@/api/openai'
|
||||
import Curd from '@/api/curd'
|
||||
import http from '@/lib/http'
|
||||
import type { ChatComplicationMessage } from '@/api/openai'
|
||||
import type { NgxConfig } from '@/api/ngx'
|
||||
|
||||
export interface Stream {
|
||||
modified_at: string
|
||||
|
@ -15,7 +15,7 @@ export interface Stream {
|
|||
}
|
||||
|
||||
class StreamCurd extends Curd<Stream> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
enable(name: string, config?: any) {
|
||||
return http.post(`${this.baseUrl}/${name}/enable`, undefined, config)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import type { NgxDirective, NgxLocation, NgxServer } from '@/api/ngx'
|
||||
import Curd from '@/api/curd'
|
||||
import http from '@/lib/http'
|
||||
import type { NgxDirective, NgxLocation, NgxServer } from '@/api/ngx'
|
||||
|
||||
export interface Variable {
|
||||
type?: string
|
||||
name?: Record<string, string>
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
value?: any
|
||||
mask?: Record<string, Record<string, string>>
|
||||
}
|
||||
|
|
2
app/src/components/Breadcrumb/types.d.ts
vendored
2
app/src/components/Breadcrumb/types.d.ts
vendored
|
@ -1,4 +1,4 @@
|
|||
import {LocationQueryRaw} from "vue-router";
|
||||
import type { LocationQueryRaw } from 'vue-router'
|
||||
|
||||
export interface Bread {
|
||||
name: string
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import VueApexCharts from 'vue3-apexcharts'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import type { Series } from '@/components/Chart/types'
|
||||
import type { Ref } from 'vue'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import type { Series } from '@/components/Chart/types'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import VueApexCharts from 'vue3-apexcharts'
|
||||
|
||||
const { series, max, yFormatter } = defineProps<{
|
||||
series: Series[]
|
||||
|
@ -14,7 +14,7 @@ const { series, max, yFormatter } = defineProps<{
|
|||
const settings = useSettingsStore()
|
||||
const { theme } = storeToRefs(settings)
|
||||
|
||||
const fontColor = () => {
|
||||
function fontColor() {
|
||||
return theme.value === 'dark' ? '#b4b4b4' : undefined
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ let chartOptions = {
|
|||
},
|
||||
}
|
||||
|
||||
const callback = () => {
|
||||
function callback() {
|
||||
chartOptions = {
|
||||
...chartOptions,
|
||||
...{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import VueApexCharts from 'vue3-apexcharts'
|
||||
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import type { Series } from '@/components/Chart/types'
|
||||
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import VueApexCharts from 'vue3-apexcharts'
|
||||
|
||||
const props = defineProps<{
|
||||
series: Series[] | number[]
|
||||
centerText?: string
|
||||
|
@ -17,7 +17,7 @@ const settings = useSettingsStore()
|
|||
|
||||
const { theme } = storeToRefs(settings)
|
||||
|
||||
const fontColor = () => {
|
||||
function fontColor() {
|
||||
return theme.value === 'dark' ? '#fcfcfc' : undefined
|
||||
}
|
||||
|
||||
|
|
2
app/src/components/Chart/types.d.ts
vendored
2
app/src/components/Chart/types.d.ts
vendored
|
@ -1,4 +1,4 @@
|
|||
import type {Usage} from '@/api/analytic'
|
||||
import type { Usage } from '@/api/analytic'
|
||||
|
||||
export interface Series {
|
||||
name: string
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<script setup lang="ts">
|
||||
import nginx from 'highlight.js/lib/languages/nginx'
|
||||
import Icon, { SendOutlined } from '@ant-design/icons-vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { Marked } from 'marked'
|
||||
import hljs from 'highlight.js'
|
||||
import { markedHighlight } from 'marked-highlight'
|
||||
import type { Ref } from 'vue'
|
||||
import { urlJoin } from '@/lib/helper'
|
||||
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||
import 'highlight.js/styles/vs2015.css'
|
||||
|
||||
import type { ChatComplicationMessage } from '@/api/openai'
|
||||
import type { Ref } from 'vue'
|
||||
import openai from '@/api/openai'
|
||||
import ChatGPT_logo from '@/assets/svg/ChatGPT_logo.svg?component'
|
||||
import { urlJoin } from '@/lib/helper'
|
||||
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||
import Icon, { SendOutlined } from '@ant-design/icons-vue'
|
||||
import hljs from 'highlight.js'
|
||||
import nginx from 'highlight.js/lib/languages/nginx'
|
||||
import { Marked } from 'marked'
|
||||
|
||||
import { markedHighlight } from 'marked-highlight'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import 'highlight.js/styles/vs2015.css'
|
||||
|
||||
const props = defineProps<{
|
||||
content: string
|
||||
|
@ -40,7 +40,6 @@ watch(history_messages, () => {
|
|||
const loading = ref(false)
|
||||
const ask_buffer = ref('')
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
async function request() {
|
||||
loading.value = true
|
||||
|
||||
|
@ -82,7 +81,7 @@ async function request() {
|
|||
}
|
||||
apply(value!)
|
||||
}
|
||||
catch (e) {
|
||||
catch {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +171,8 @@ const marked = new Marked(
|
|||
|
||||
return `<pre><code class="hljs ${language}">${highlightedCode}</code></pre>`
|
||||
},
|
||||
}))
|
||||
}),
|
||||
)
|
||||
|
||||
marked.setOptions({
|
||||
pedantic: false,
|
||||
|
@ -238,8 +238,8 @@ const show = computed(() => !messages.value || messages.value?.length === 0)
|
|||
<template #content>
|
||||
<div
|
||||
v-if="item.role === 'assistant' || editing_idx !== index"
|
||||
v-dompurify-html="marked.parse(item.content)"
|
||||
class="content"
|
||||
v-html="marked.parse(item.content)"
|
||||
/>
|
||||
<AInput
|
||||
v-else
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import ace from 'ace-builds'
|
||||
import extSearchboxUrl from 'ace-builds/src-noconflict/ext-searchbox?url'
|
||||
import { VAceEditor } from 'vue3-ace-editor'
|
||||
import 'ace-builds/src-noconflict/mode-nginx'
|
||||
import ace from 'ace-builds'
|
||||
import 'ace-builds/src-noconflict/theme-monokai'
|
||||
import extSearchboxUrl from 'ace-builds/src-noconflict/ext-searchbox?url'
|
||||
|
||||
const props = defineProps<{
|
||||
content?: string
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import { CloseOutlined, DashboardOutlined, DatabaseOutlined } from '@ant-design/icons-vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
|
||||
const settingsStore = useSettingsStore()
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import logo from '@/assets/img/logo.png'</script>
|
||||
import logo from '@/assets/img/logo.png'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="logo">
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import { ReloadOutlined } from '@ant-design/icons-vue'
|
||||
import ngx from '@/api/ngx'
|
||||
import { logLevel } from '@/views/config/constants'
|
||||
import { NginxStatus } from '@/constants'
|
||||
import { useGlobalStore } from '@/pinia/moudule/global'
|
||||
import { logLevel } from '@/views/config/constants'
|
||||
import { ReloadOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const global = useGlobalStore()
|
||||
const { nginxStatus: status } = storeToRefs(global)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { Ref } from 'vue'
|
||||
import type { Environment } from '@/api/environment'
|
||||
import type { Ref } from 'vue'
|
||||
import environment from '@/api/environment'
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { BellOutlined, CheckCircleOutlined, CloseCircleOutlined, DeleteOutlined, InfoCircleOutlined, WarningOutlined } from '@ant-design/icons-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import notification from '@/api/notification'
|
||||
import type { Notification } from '@/api/notification'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Ref } from 'vue'
|
||||
import notification from '@/api/notification'
|
||||
import { detailRender } from '@/components/Notification/detailRender'
|
||||
import { NotificationTypeT } from '@/constants'
|
||||
import { useUserStore } from '@/pinia'
|
||||
import { detailRender } from '@/components/Notification/detailRender'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { BellOutlined, CheckCircleOutlined, CloseCircleOutlined, DeleteOutlined, InfoCircleOutlined, WarningOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
|
@ -112,7 +112,7 @@ function viewAll() {
|
|||
</template>
|
||||
<AListItemMeta
|
||||
:title="$gettext(item.title)"
|
||||
:description="detailRender({ text: item.details, record: item } as customRender)"
|
||||
:description="detailRender({ text: item.details, record: item } as CustomRenderProps)"
|
||||
>
|
||||
<template #avatar>
|
||||
<div>
|
||||
|
|
|
@ -1,18 +1,15 @@
|
|||
export function syncCertificateSuccess(text: string) {
|
||||
const data = JSON.parse(text)
|
||||
|
||||
return $gettext('Sync Certificate %{cert_name} to %{env_name} successfully',
|
||||
{ cert_name: data.cert_name, env_name: data.env_name })
|
||||
return $gettext('Sync Certificate %{cert_name} to %{env_name} successfully', { cert_name: data.cert_name, env_name: data.env_name })
|
||||
}
|
||||
|
||||
export function syncCertificateError(text: string) {
|
||||
const data = JSON.parse(text)
|
||||
|
||||
if (data.status_code === 404) {
|
||||
return $gettext('Sync Certificate %{cert_name} to %{env_name} failed, please upgrade the remote Nginx UI to the latest version',
|
||||
{ cert_name: data.cert_name, env_name: data.env_name }, true)
|
||||
return $gettext('Sync Certificate %{cert_name} to %{env_name} failed, please upgrade the remote Nginx UI to the latest version', { cert_name: data.cert_name, env_name: data.env_name }, true)
|
||||
}
|
||||
|
||||
return $gettext('Sync Certificate %{cert_name} to %{env_name} failed, response: %{resp}',
|
||||
{ cert_name: data.cert_name, env_name: data.env_name, resp: data.resp_body }, true)
|
||||
return $gettext('Sync Certificate %{cert_name} to %{env_name} failed, response: %{resp}', { cert_name: data.cert_name, env_name: data.env_name, resp: data.resp_body }, true)
|
||||
}
|
||||
|
|
|
@ -1,37 +1,31 @@
|
|||
export function syncConfigSuccess(text: string) {
|
||||
const data = JSON.parse(text)
|
||||
|
||||
return $gettext('Sync Config %{config_name} to %{env_name} successfully',
|
||||
{ config_name: data.config_name, env_name: data.env_name })
|
||||
return $gettext('Sync Config %{config_name} to %{env_name} successfully', { config_name: data.config_name, env_name: data.env_name })
|
||||
}
|
||||
|
||||
export function syncConfigError(text: string) {
|
||||
const data = JSON.parse(text)
|
||||
|
||||
if (data.status_code === 404) {
|
||||
return $gettext('Sync config %{config_name} to %{env_name} failed, please upgrade the remote Nginx UI to the latest version',
|
||||
{ config_name: data.config_name, env_name: data.env_name }, true)
|
||||
return $gettext('Sync config %{config_name} to %{env_name} failed, please upgrade the remote Nginx UI to the latest version', { config_name: data.config_name, env_name: data.env_name }, true)
|
||||
}
|
||||
|
||||
return $gettext('Sync config %{config_name} to %{env_name} failed, response: %{resp}',
|
||||
{ config_name: data.cert_name, env_name: data.env_name, resp: data.resp_body }, true)
|
||||
return $gettext('Sync config %{config_name} to %{env_name} failed, response: %{resp}', { config_name: data.cert_name, env_name: data.env_name, resp: data.resp_body }, true)
|
||||
}
|
||||
|
||||
export function syncRenameConfigSuccess(text: string) {
|
||||
const data = JSON.parse(text)
|
||||
|
||||
return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} successfully',
|
||||
{ orig_path: data.orig_path, new_path: data.orig_path, env_name: data.env_name })
|
||||
return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} successfully', { orig_path: data.orig_path, new_path: data.orig_path, env_name: data.env_name })
|
||||
}
|
||||
|
||||
export function syncRenameConfigError(text: string) {
|
||||
const data = JSON.parse(text)
|
||||
|
||||
if (data.status_code === 404) {
|
||||
return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} failed, please upgrade the remote Nginx UI to the latest version',
|
||||
{ orig_path: data.orig_path, new_path: data.orig_path, env_name: data.env_name }, true)
|
||||
return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} failed, please upgrade the remote Nginx UI to the latest version', { orig_path: data.orig_path, new_path: data.orig_path, env_name: data.env_name }, true)
|
||||
}
|
||||
|
||||
return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} failed, response: %{resp}',
|
||||
{ orig_path: data.orig_path, new_path: data.orig_path, resp: data.resp_body, env_name: data.env_name }, true)
|
||||
return $gettext('Rename %{orig_path} to %{new_path} on %{env_name} failed, response: %{resp}', { orig_path: data.orig_path, new_path: data.orig_path, resp: data.resp_body, env_name: data.env_name }, true)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { syncCertificateError, syncCertificateSuccess } from '@/components/Notification/cert'
|
||||
import {
|
||||
syncConfigError,
|
||||
|
@ -7,7 +7,7 @@ import {
|
|||
syncRenameConfigSuccess,
|
||||
} from '@/components/Notification/config'
|
||||
|
||||
export const detailRender = (args: customRender) => {
|
||||
export function detailRender(args: CustomRenderProps) {
|
||||
switch (args.record.title) {
|
||||
case 'Sync Certificate Success':
|
||||
return syncCertificateSuccess(args.text)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import dayjs from 'dayjs'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import gettext from '@/gettext'
|
||||
import loadTranslations from '@/api/translations'
|
||||
import gettext from '@/gettext'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import 'dayjs/locale/fr'
|
||||
import 'dayjs/locale/ja'
|
||||
|
@ -29,7 +29,7 @@ const current = computed({
|
|||
|
||||
const languageAvailable = gettext.available
|
||||
|
||||
const updateTitle = () => {
|
||||
function updateTitle() {
|
||||
const name = route.meta.name as never as () => string
|
||||
|
||||
document.title = `${name()} | Nginx UI`
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const props = defineProps<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
api: (ids: number[], data: any) => Promise<void>
|
||||
beforeSave?: () => Promise<void>
|
||||
}>()
|
||||
|
@ -15,7 +15,7 @@ const batchColumns = ref([])
|
|||
const visible = ref(false)
|
||||
|
||||
const selectedRowKeys = ref([])
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function showModal(c: any, rowKeys: any) {
|
||||
visible.value = true
|
||||
selectedRowKeys.value = rowKeys
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script setup lang="ts" generic="T=any">
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { StdTableSlots } from '@/components/StdDesign/StdDataDisplay/types'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import type { ComputedRef } from 'vue'
|
||||
import type { StdTableProps } from './StdTable.vue'
|
||||
import StdTable from './StdTable.vue'
|
||||
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import StdCurdDetail from '@/components/StdDesign/StdDataDisplay/StdCurdDetail.vue'
|
||||
import type { StdTableSlots } from '@/components/StdDesign/StdDataDisplay/types'
|
||||
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
||||
import { message } from 'ant-design-vue'
|
||||
import StdTable from './StdTable.vue'
|
||||
|
||||
export interface StdCurdProps<T> extends StdTableProps<T> {
|
||||
cardTitleKey?: string
|
||||
|
@ -19,13 +19,13 @@ export interface StdCurdProps<T> extends StdTableProps<T> {
|
|||
onClickAdd?: () => void
|
||||
|
||||
onClickEdit?: (id: number | string, record: T, index: number) => void
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
beforeSave?: (data: any) => Promise<void>
|
||||
}
|
||||
|
||||
const props = defineProps<StdTableProps<T> & StdCurdProps<T>>()
|
||||
const visible = ref(false)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const data: any = reactive({ id: null })
|
||||
const modifyMode = ref(true)
|
||||
const editMode = ref<string>()
|
||||
|
@ -35,11 +35,11 @@ provide('data', data)
|
|||
provide('editMode', editMode)
|
||||
provide('shouldRefetchList', shouldRefetchList)
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const error: any = reactive({})
|
||||
const selected = ref([])
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function onSelect(keys: any) {
|
||||
selected.value = keys
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ const editableColumns = computed(() => {
|
|||
})
|
||||
}) as ComputedRef<Column[]>
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function add(preset: any = undefined) {
|
||||
if (props.onClickAdd)
|
||||
return
|
||||
|
@ -69,12 +69,12 @@ function add(preset: any = undefined) {
|
|||
|
||||
const table = ref()
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const selectedRowKeys = defineModel<any[]>('selectedRowKeys', {
|
||||
default: () => [],
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const selectedRows = defineModel<any[]>('selectedRows', {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
|
@ -84,8 +84,8 @@ const getParams = reactive({
|
|||
trash: false,
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const setParams = (k: string, v: any) => {
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function setParams(k: string, v: any) {
|
||||
getParams[k] = v
|
||||
}
|
||||
|
||||
|
@ -117,17 +117,15 @@ async function ok() {
|
|||
await formRef.validateFields()
|
||||
props?.beforeSave?.(data)
|
||||
props
|
||||
.api!.save(data.id, { ...data, ...props.overwriteParams }, { params: { ...props.overwriteParams } })
|
||||
.then(r => {
|
||||
message.success($gettext('Save successfully'))
|
||||
Object.assign(data, r)
|
||||
get_list()
|
||||
visible.value = false
|
||||
})
|
||||
.catch(e => {
|
||||
message.error($gettext(e?.message ?? 'Server error'), 5)
|
||||
Object.assign(error, e.errors)
|
||||
})
|
||||
.api!.save(data.id, { ...data, ...props.overwriteParams }, { params: { ...props.overwriteParams } }).then(r => {
|
||||
message.success($gettext('Save successfully'))
|
||||
Object.assign(data, r)
|
||||
get_list()
|
||||
visible.value = false
|
||||
}).catch(e => {
|
||||
message.error($gettext(e?.message ?? 'Server error'), 5)
|
||||
Object.assign(error, e.errors)
|
||||
})
|
||||
}
|
||||
catch {
|
||||
message.error($gettext('Please fill in the required fields'))
|
||||
|
@ -169,18 +167,19 @@ function view(id: number | string) {
|
|||
|
||||
async function get(id: number | string) {
|
||||
return props
|
||||
.api!.get(id, { ...props.overwriteParams })
|
||||
.then(async r => {
|
||||
Object.keys(data).forEach(k => {
|
||||
delete data[k]
|
||||
})
|
||||
data.id = null
|
||||
Object.assign(data, r)
|
||||
.api!.get(id, { ...props.overwriteParams }).then(async r => {
|
||||
Object.keys(data).forEach(k => {
|
||||
delete data[k]
|
||||
})
|
||||
data.id = null
|
||||
Object.assign(data, r)
|
||||
})
|
||||
}
|
||||
|
||||
const modalTitle = computed(() => {
|
||||
return data.id ? modifyMode.value ? $gettext('Modify') : $gettext('View Details') : $gettext('Add')
|
||||
if (data.id)
|
||||
return modifyMode.value ? $gettext('Modify') : $gettext('View Details')
|
||||
return $gettext('Add')
|
||||
})
|
||||
|
||||
const localOverwriteParams = reactive(props.overwriteParams ?? {})
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import type { ComputedRef } from 'vue'
|
||||
import _ from 'lodash'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import { labelRender } from '@/components/StdDesign/StdDataEntry'
|
||||
import type { ComputedRef } from 'vue'
|
||||
import { CustomRender } from '@/components/StdDesign/StdDataDisplay/components/CustomRender'
|
||||
import { labelRender } from '@/components/StdDesign/StdDataEntry'
|
||||
import _ from 'lodash'
|
||||
|
||||
const props = defineProps<{
|
||||
columns: Column[]
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
data: any
|
||||
}>()
|
||||
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
<script setup lang="ts" generic="T=any">
|
||||
import type { Pagination } from '@/api/curd'
|
||||
import type Curd from '@/api/curd'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import type { TableProps } from 'ant-design-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { HolderOutlined } from '@ant-design/icons-vue'
|
||||
import type { ComputedRef, Ref } from 'vue'
|
||||
import type { SorterResult, TablePaginationConfig } from 'ant-design-vue/lib/table/interface'
|
||||
import type { FilterValue } from 'ant-design-vue/es/table/interface'
|
||||
import type { Key } from 'ant-design-vue/es/_util/type'
|
||||
import type { FilterValue } from 'ant-design-vue/es/table/interface'
|
||||
import type { SorterResult, TablePaginationConfig } from 'ant-design-vue/lib/table/interface'
|
||||
import type { ComputedRef, Ref } from 'vue'
|
||||
import type { RouteParams } from 'vue-router'
|
||||
import useSortable from '@/components/StdDesign/StdDataDisplay/methods/sortable'
|
||||
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
||||
import { HolderOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import _ from 'lodash'
|
||||
import StdPagination from './StdPagination.vue'
|
||||
import StdDataEntry from '@/components/StdDesign/StdDataEntry'
|
||||
import type { Pagination } from '@/api/curd'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import useSortable from '@/components/StdDesign/StdDataDisplay/methods/sortable'
|
||||
import type Curd from '@/api/curd'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export interface StdTableProps<T = any> {
|
||||
title?: string
|
||||
mode?: string
|
||||
rowKey?: string
|
||||
api: Curd<T>
|
||||
columns: Column[]
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
getParams?: Record<string, any>
|
||||
size?: string
|
||||
disableQueryParams?: boolean
|
||||
|
@ -30,7 +30,7 @@ export interface StdTableProps<T = any> {
|
|||
pithy?: boolean
|
||||
exportExcel?: boolean
|
||||
exportMaterial?: boolean
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
overwriteParams?: Record<string, any>
|
||||
disableView?: boolean
|
||||
disableModify?: boolean
|
||||
|
@ -40,7 +40,7 @@ export interface StdTableProps<T = any> {
|
|||
disablePagination?: boolean
|
||||
sortableMoveHook?: (oldRow: number[], newRow: number[]) => boolean
|
||||
scrollX?: string | number
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
getCheckboxProps?: (record: any) => any
|
||||
}
|
||||
|
||||
|
@ -71,10 +71,10 @@ watch(dataSource, () => {
|
|||
expandKeysList.value = res
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const rowsKeyIndexMap: Ref<Record<number, any>> = ref({})
|
||||
const loading = ref(true)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const selectedRecords: Ref<Record<any, any>> = ref({})
|
||||
|
||||
// This can be useful if there are more than one StdTable in the same page.
|
||||
|
@ -93,12 +93,12 @@ const params = reactive({
|
|||
...props.getParams,
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const selectedRowKeys = defineModel<any[]>('selectedRowKeys', {
|
||||
default: () => [],
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const selectedRows = defineModel<any[]>('selectedRows', {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
|
@ -213,10 +213,10 @@ function recover(id: number | string) {
|
|||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function buildIndexMap(data: any, level: number = 0, index: number = 0, total: number[] = []) {
|
||||
if (data && data.length > 0) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
data.forEach((v: any) => {
|
||||
v.level = level
|
||||
|
||||
|
@ -253,7 +253,7 @@ async function _get_list(page_num = null, page_size = 20) {
|
|||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function onTableChange(_pagination: TablePaginationConfig, filters: Record<string, FilterValue>, sorter: SorterResult | SorterResult<any>[]) {
|
||||
if (sorter) {
|
||||
sorter = sorter as SorterResult
|
||||
|
@ -286,7 +286,7 @@ function expandedTable(keys: Key[]) {
|
|||
expandKeysList.value = keys
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any,sonarjs/cognitive-complexity
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
async function onSelect(record: any, selected: boolean, _selectedRows: any[]) {
|
||||
if (props.selectionType === 'checkbox' || props.exportExcel) {
|
||||
if (selected) {
|
||||
|
@ -300,13 +300,13 @@ async function onSelect(record: any, selected: boolean, _selectedRows: any[]) {
|
|||
})
|
||||
}
|
||||
else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
selectedRowKeys.value = selectedRowKeys.value.filter((v: any) => v !== record[props.rowKey])
|
||||
delete selectedRecords.value[record[props.rowKey]]
|
||||
}
|
||||
|
||||
await nextTick(async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const filteredRows: any[] = []
|
||||
|
||||
selectedRowKeys.value.forEach(v => {
|
||||
|
@ -325,10 +325,10 @@ async function onSelect(record: any, selected: boolean, _selectedRows: any[]) {
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
async function onSelectAll(selected: boolean, _selectedRows: any[], changeRows: any[]) {
|
||||
// console.log(selected, selectedRows, changeRows)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
changeRows.forEach((v: any) => {
|
||||
if (v) {
|
||||
if (selected) {
|
||||
|
@ -350,7 +350,7 @@ async function onSelectAll(selected: boolean, _selectedRows: any[], changeRows:
|
|||
// console.log(selectedRowKeysBuffer.value, selectedRecords.value)
|
||||
|
||||
await nextTick(async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const filteredRows: any[] = []
|
||||
|
||||
selectedRowKeys.value.forEach(v => {
|
||||
|
@ -362,7 +362,7 @@ async function onSelectAll(selected: boolean, _selectedRows: any[], changeRows:
|
|||
|
||||
const router = useRouter()
|
||||
|
||||
const resetSearch = async () => {
|
||||
async function resetSearch() {
|
||||
Object.keys(params).forEach(v => {
|
||||
delete params[v]
|
||||
})
|
||||
|
@ -460,7 +460,6 @@ const paginationSize = computed(() => {
|
|||
else
|
||||
return 'default'
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
// text, record, index, column
|
||||
import dayjs from 'dayjs'
|
||||
import type { JSX } from 'vue/jsx-runtime'
|
||||
import { Tag } from 'ant-design-vue'
|
||||
// text, record, index, column
|
||||
import dayjs from 'dayjs'
|
||||
import { get } from 'lodash'
|
||||
|
||||
export interface customRender {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export interface CustomRenderProps {
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
text: any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
record: any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
index: any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
column: any
|
||||
isExport?: boolean
|
||||
isDetail?: boolean
|
||||
}
|
||||
|
||||
export const datetime = (args: customRender) => {
|
||||
export function datetime(args: CustomRenderProps) {
|
||||
return dayjs(args.text).format('YYYY-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
export const date = (args: customRender) => {
|
||||
export function date(args: CustomRenderProps) {
|
||||
return args.text ? dayjs(args.text).format('YYYY-MM-DD') : '-'
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,10 @@ export const date = (args: customRender) => {
|
|||
date.isDate = true
|
||||
datetime.isDatetime = true
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const mask = (maskObj: any): (args: customRender) => JSX.Element => {
|
||||
return (args: customRender) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function mask(maskObj: any): (args: CustomRenderProps) => JSX.Element {
|
||||
return (args: CustomRenderProps) => {
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
let v: any
|
||||
|
||||
if (typeof maskObj?.[args.text] === 'function')
|
||||
|
@ -45,15 +45,15 @@ export const mask = (maskObj: any): (args: customRender) => JSX.Element => {
|
|||
}
|
||||
}
|
||||
|
||||
export const arrayToTextRender = (args: customRender) => {
|
||||
export function arrayToTextRender(args: CustomRenderProps) {
|
||||
return args.text?.join(', ')
|
||||
}
|
||||
export const actualValueRender = (args: customRender, actualDataIndex: string | string[]) => {
|
||||
export function actualValueRender(args: CustomRenderProps, actualDataIndex: string | string[]) {
|
||||
return get(args.record, actualDataIndex)
|
||||
}
|
||||
|
||||
export const longTextWithEllipsis = (len: number): (args: customRender) => JSX.Element => {
|
||||
return (args: customRender) => {
|
||||
export function longTextWithEllipsis(len: number): (args: CustomRenderProps) => JSX.Element {
|
||||
return (args: CustomRenderProps) => {
|
||||
if (args.isExport || args.isDetail)
|
||||
return args.text
|
||||
|
||||
|
@ -61,29 +61,31 @@ export const longTextWithEllipsis = (len: number): (args: customRender) => JSX.E
|
|||
}
|
||||
}
|
||||
|
||||
export const year = (args: customRender) => {
|
||||
export function year(args: CustomRenderProps) {
|
||||
return dayjs(args.text).format('YYYY')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const maskRenderWithColor = (maskObj: any) => (args: customRender) => {
|
||||
let label: string
|
||||
if (typeof maskObj[args.text] === 'function')
|
||||
label = maskObj[args.text]()
|
||||
else if (typeof maskObj[args.text] === 'string')
|
||||
label = maskObj[args.text]
|
||||
else label = args.text
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function maskRenderWithColor(maskObj: any) {
|
||||
return (args: CustomRenderProps) => {
|
||||
let label: string
|
||||
if (typeof maskObj[args.text] === 'function')
|
||||
label = maskObj[args.text]()
|
||||
else if (typeof maskObj[args.text] === 'string')
|
||||
label = maskObj[args.text]
|
||||
else label = args.text
|
||||
|
||||
if (args.isExport)
|
||||
return label
|
||||
if (args.isExport)
|
||||
return label
|
||||
|
||||
const colorMap = {
|
||||
0: '',
|
||||
1: 'blue',
|
||||
2: 'green',
|
||||
3: 'red',
|
||||
4: 'cyan',
|
||||
const colorMap = {
|
||||
0: '',
|
||||
1: 'blue',
|
||||
2: 'green',
|
||||
3: 'red',
|
||||
4: 'cyan',
|
||||
}
|
||||
|
||||
return args.text ? h(Tag, { color: colorMap[args.text] }, maskObj[args.text]) : '-'
|
||||
}
|
||||
|
||||
return args.text ? h(Tag, { color: colorMap[args.text] }, maskObj[args.text]) : '-'
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import _ from 'lodash'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
|
||||
export function CustomRender(props: customRender) {
|
||||
export function CustomRender(props: CustomRenderProps) {
|
||||
return props.column.customRender
|
||||
? props.column.customRender(props)
|
||||
: _.get(props.record, props.column.dataIndex!)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import StdTable from './StdTable.vue'
|
||||
import StdCurd from './StdCurd.vue'
|
||||
import StdBatchEdit from './StdBatchEdit.vue'
|
||||
import StdCurd from './StdCurd.vue'
|
||||
import StdTable from './StdTable.vue'
|
||||
|
||||
export {
|
||||
StdTable,
|
||||
StdCurd,
|
||||
StdBatchEdit,
|
||||
StdCurd,
|
||||
StdTable,
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import type { StdTableProps } from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import type { Column, StdTableResponse } from '@/components/StdDesign/types'
|
||||
import type { ComputedRef } from 'vue'
|
||||
import { downloadCsv } from '@/lib/helper'
|
||||
import { message } from 'ant-design-vue'
|
||||
import dayjs from 'dayjs'
|
||||
import type { ComputedRef } from 'vue'
|
||||
import _ from 'lodash'
|
||||
import { downloadCsv } from '@/lib/helper'
|
||||
import type { Column, StdTableResponse } from '@/components/StdDesign/types'
|
||||
import type { StdTableProps } from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
|
||||
async function exportCsv(props: StdTableProps, pithyColumns: ComputedRef<Column[]>) {
|
||||
const header: { title?: string; key: Column['dataIndex'] }[] = []
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const header: { title?: string, key: Column['dataIndex'] }[] = []
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const headerKeys: any[] = []
|
||||
const showColumnsMap: Record<string, Column> = {}
|
||||
|
||||
|
@ -26,33 +26,31 @@ async function exportCsv(props: StdTableProps, pithyColumns: ComputedRef<Column[
|
|||
showColumnsMap[column?.dataIndex?.toString() as string] = column
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const dataSource: any[] = []
|
||||
let hasMore = true
|
||||
let page = 1
|
||||
while (hasMore) {
|
||||
// 准备 DataSource
|
||||
await props
|
||||
.api!.get_list({ page })
|
||||
.then((r: StdTableResponse) => {
|
||||
if (r.data.length === 0) {
|
||||
hasMore = false
|
||||
|
||||
return
|
||||
}
|
||||
dataSource.push(...r.data)
|
||||
})
|
||||
.catch((e: { message?: string }) => {
|
||||
message.error(e.message ?? $gettext('Server error'))
|
||||
.api!.get_list({ page }).then((r: StdTableResponse) => {
|
||||
if (r.data.length === 0) {
|
||||
hasMore = false
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
dataSource.push(...r.data)
|
||||
}).catch((e: { message?: string }) => {
|
||||
message.error(e.message ?? $gettext('Server error'))
|
||||
hasMore = false
|
||||
})
|
||||
page += 1
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const data: any[] = []
|
||||
|
||||
dataSource.forEach(row => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const obj: Record<string, any> = {}
|
||||
|
||||
headerKeys.forEach(key => {
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { message } from 'ant-design-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import sortable from 'sortablejs'
|
||||
import type { Key } from 'ant-design-vue/es/_util/type'
|
||||
import type { StdTableProps } from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import type { Key } from 'ant-design-vue/es/_util/type'
|
||||
import type { Ref } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import sortable from 'sortablejs'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function getRowKey(item: any) {
|
||||
return item.dataset.rowKey
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function getTargetData(data: any, indexList: number[]): any {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
let target: any = { children: data }
|
||||
indexList.forEach((index: number) => {
|
||||
target.children[index].parent = target
|
||||
|
@ -21,112 +21,116 @@ function getTargetData(data: any, indexList: number[]): any {
|
|||
return target
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function useSortable(props: StdTableProps, randomId: Ref<string>, dataSource: Ref<any[]>,
|
||||
rowsKeyIndexMap: Ref<Record<number, number[]>>, expandKeysList: Ref<Key[]>) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function useSortable(props: StdTableProps, randomId: Ref<string>, dataSource: Ref<any[]>, rowsKeyIndexMap: Ref<Record<number, number[]>>, expandKeysList: Ref<Key[]>) {
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const table: any = document.querySelector(`#std-table-${randomId.value} tbody`)
|
||||
|
||||
// eslint-disable-next-line no-new,new-cap
|
||||
new sortable(table, {
|
||||
handle: '.ant-table-drag-icon',
|
||||
animation: 150,
|
||||
sort: true,
|
||||
forceFallback: true,
|
||||
setData(dataTransfer) {
|
||||
dataTransfer.setData('Text', '')
|
||||
},
|
||||
onStart({ item }) {
|
||||
const targetRowKey = Number(getRowKey(item))
|
||||
if (targetRowKey)
|
||||
expandKeysList.value = expandKeysList.value.filter((_item: Key) => _item !== targetRowKey)
|
||||
},
|
||||
onMove({
|
||||
dragged,
|
||||
related,
|
||||
}) {
|
||||
const oldRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(dragged))]
|
||||
const newRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(related))]
|
||||
try {
|
||||
// eslint-disable-next-line no-new,new-cap
|
||||
new sortable(table, {
|
||||
handle: '.ant-table-drag-icon',
|
||||
animation: 150,
|
||||
sort: true,
|
||||
forceFallback: true,
|
||||
setData(dataTransfer) {
|
||||
dataTransfer.setData('Text', '')
|
||||
},
|
||||
onStart({ item }) {
|
||||
const targetRowKey = Number(getRowKey(item))
|
||||
if (targetRowKey)
|
||||
expandKeysList.value = expandKeysList.value.filter((_item: Key) => _item !== targetRowKey)
|
||||
},
|
||||
onMove({
|
||||
dragged,
|
||||
related,
|
||||
}) {
|
||||
const oldRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(dragged))]
|
||||
const newRow: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(related))]
|
||||
|
||||
if (oldRow.length !== newRow.length || oldRow[oldRow.length - 2] !== newRow[newRow.length - 2])
|
||||
return false
|
||||
if (oldRow.length !== newRow.length || oldRow[oldRow.length - 2] !== newRow[newRow.length - 2])
|
||||
return false
|
||||
|
||||
if (props.sortableMoveHook)
|
||||
return props.sortableMoveHook(oldRow, newRow)
|
||||
},
|
||||
async onEnd({
|
||||
item,
|
||||
newIndex,
|
||||
oldIndex,
|
||||
}) {
|
||||
if (newIndex === oldIndex)
|
||||
return
|
||||
if (props.sortableMoveHook)
|
||||
return props.sortableMoveHook(oldRow, newRow)
|
||||
},
|
||||
async onEnd({
|
||||
item,
|
||||
newIndex,
|
||||
oldIndex,
|
||||
}) {
|
||||
if (newIndex === oldIndex || newIndex === undefined)
|
||||
return
|
||||
|
||||
const indexDelta: number = Number(oldIndex) - Number(newIndex)
|
||||
const direction: number = indexDelta > 0 ? +1 : -1
|
||||
const indexDelta: number = Number(oldIndex) - Number(newIndex)
|
||||
const direction: number = indexDelta > 0 ? +1 : -1
|
||||
|
||||
const rowIndex: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(item))]
|
||||
const newRow = getTargetData(dataSource.value, rowIndex)
|
||||
const newRowParent = newRow.parent
|
||||
const level: number = newRow.level
|
||||
const rowIndex: number[] = rowsKeyIndexMap.value?.[Number(getRowKey(item))]
|
||||
const newRow = getTargetData(dataSource.value, rowIndex)
|
||||
const newRowParent = newRow.parent
|
||||
const level: number = newRow.level
|
||||
|
||||
const currentRowIndex: number[] = [...rowsKeyIndexMap.value?.
|
||||
[Number(getRowKey(table.children[Number(newIndex) + direction]))]]
|
||||
const currentRowIndex: number[] = [...rowsKeyIndexMap.value?.
|
||||
[Number(getRowKey(table.children[Number(newIndex) + direction]))]]
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const currentRow: any = getTargetData(dataSource.value, currentRowIndex)
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const currentRow: any = getTargetData(dataSource.value, currentRowIndex)
|
||||
|
||||
// Reset parent
|
||||
currentRow.parent = newRow.parent = null
|
||||
newRowParent.children.splice(rowIndex[level], 1)
|
||||
newRowParent.children.splice(currentRowIndex[level], 0, toRaw(newRow))
|
||||
// Reset parent
|
||||
currentRow.parent = newRow.parent = null
|
||||
newRowParent.children.splice(rowIndex[level], 1)
|
||||
newRowParent.children.splice(currentRowIndex[level], 0, toRaw(newRow))
|
||||
|
||||
const changeIds: number[] = []
|
||||
const changeIds: number[] = []
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function processChanges(row: any, children = false, _newIndex: number | undefined = undefined) {
|
||||
// Build changes ID list expect new row
|
||||
if (children || _newIndex === undefined)
|
||||
changeIds.push(row.id)
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function processChanges(row: any, children = false, _newIndex: number | undefined = undefined) {
|
||||
// Build changes ID list expect new row
|
||||
if (children || _newIndex === undefined)
|
||||
changeIds.push(row.id)
|
||||
|
||||
if (_newIndex !== undefined)
|
||||
rowsKeyIndexMap.value[row.id][level] = _newIndex
|
||||
else if (children)
|
||||
rowsKeyIndexMap.value[row.id][level] += direction
|
||||
if (_newIndex !== undefined)
|
||||
rowsKeyIndexMap.value[row.id][level] = _newIndex
|
||||
else if (children)
|
||||
rowsKeyIndexMap.value[row.id][level] += direction
|
||||
|
||||
row.parent = null
|
||||
if (row.children) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
row.children.forEach((v: any) => processChanges(v, true, _newIndex))
|
||||
row.parent = null
|
||||
if (row.children) {
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
row.children.forEach((v: any) => processChanges(v, true, _newIndex))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace row index for new row
|
||||
processChanges(newRow, false, currentRowIndex[level])
|
||||
// Replace row index for new row
|
||||
processChanges(newRow, false, currentRowIndex[level])
|
||||
|
||||
// Rebuild row index maps for changes row
|
||||
for (let i = Number(oldIndex); i !== newIndex; i -= direction) {
|
||||
const _rowIndex: number[] = rowsKeyIndexMap.value?.[getRowKey(table.children[i])]
|
||||
// Rebuild row index maps for changes row
|
||||
for (let i = Number(oldIndex); i >= newIndex; i -= direction) {
|
||||
const _rowIndex: number[] = rowsKeyIndexMap.value?.[getRowKey(table.children[i])]
|
||||
|
||||
_rowIndex[level] += direction
|
||||
processChanges(getTargetData(dataSource.value, _rowIndex))
|
||||
}
|
||||
_rowIndex[level] += direction
|
||||
processChanges(getTargetData(dataSource.value, _rowIndex))
|
||||
}
|
||||
|
||||
// console.log('Change row id', newRow.id, 'order', newRow.id, '=>', currentRow.id, ', direction: ', direction,
|
||||
// ', changes IDs:', changeIds
|
||||
// console.log('Change row id', newRow.id, 'order', newRow.id, '=>', currentRow.id, ', direction: ', direction,
|
||||
// ', changes IDs:', changeIds
|
||||
|
||||
props.api.update_order({
|
||||
target_id: newRow.id,
|
||||
direction,
|
||||
affected_ids: changeIds,
|
||||
}).then(() => {
|
||||
message.success($gettext('Updated successfully'))
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
}).catch((e: any) => {
|
||||
message.error(e?.message ?? $gettext('Server error'))
|
||||
})
|
||||
},
|
||||
})
|
||||
props.api.update_order({
|
||||
target_id: newRow.id,
|
||||
direction,
|
||||
affected_ids: changeIds,
|
||||
}).then(() => {
|
||||
message.success($gettext('Updated successfully'))
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
}).catch((e: any) => {
|
||||
message.error(e?.message ?? $gettext('Server error'))
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
export default useSortable
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* eslint-disable ts/no-explicit-any */
|
||||
|
||||
export interface StdTableSlots {
|
||||
'append-search': ({}) => any
|
||||
actions: ({}: Record<string, any>) => any
|
||||
'append-search': (action) => any
|
||||
'actions': (actions: Record<string, any>) => any
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<script setup lang="tsx">
|
||||
import { Form } from 'ant-design-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import type { Column, JSXElements, StdDesignEdit } from '@/components/StdDesign/types'
|
||||
import StdFormItem from '@/components/StdDesign/StdDataEntry/StdFormItem.vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { labelRender } from '@/components/StdDesign/StdDataEntry'
|
||||
import StdFormItem from '@/components/StdDesign/StdDataEntry/StdFormItem.vue'
|
||||
import { Form } from 'ant-design-vue'
|
||||
|
||||
const props = defineProps<{
|
||||
dataList: Column[]
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
dataSource: Record<string, any>
|
||||
errors?: Record<string, string>
|
||||
type?: 'search' | 'edit'
|
||||
|
@ -15,7 +15,7 @@ const props = defineProps<{
|
|||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
'update:dataSource': [data: Record<string, any>]
|
||||
}>()
|
||||
|
||||
|
@ -95,7 +95,7 @@ function Render() {
|
|||
})
|
||||
|
||||
if (slots.action)
|
||||
template.push(<div class={'std-data-entry-action'}>{slots.action()}</div>)
|
||||
template.push(<div class="std-data-entry-action">{slots.action()}</div>)
|
||||
|
||||
return <Form ref={formRef} model={dataSource.value} layout={props.layout || 'vertical'}>{template}</Form>
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import type { SelectProps } from 'ant-design-vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
mask?: Record<string | number, string | (() => string)> | (() => Promise<Record<string | number, string>>)
|
||||
placeholder?: string
|
||||
multiple?: boolean
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
defaultValue?: any
|
||||
}>()
|
||||
|
||||
const selectedValue = defineModel<string | number | string[] | number[]>('value')
|
||||
const options = ref<SelectProps['options']>([])
|
||||
|
||||
const loadOptions = async () => {
|
||||
async function loadOptions() {
|
||||
options.value = []
|
||||
let actualValue: number | string
|
||||
if (typeof props.mask === 'function') {
|
||||
|
@ -45,7 +45,7 @@ const loadOptions = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
const init = () => {
|
||||
function init() {
|
||||
loadOptions()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
<script setup lang="ts">
|
||||
import _ from 'lodash'
|
||||
import type { Ref } from 'vue'
|
||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import type Curd from '@/api/curd'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import type { Ref } from 'vue'
|
||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import _ from 'lodash'
|
||||
|
||||
const props = defineProps<{
|
||||
label?: string
|
||||
selectedKey: number | number[] | undefined | null
|
||||
selectionType: 'radio' | 'checkbox'
|
||||
recordValueIndex: string // to index the value of the record
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
api: Curd<any>
|
||||
columns: Column[]
|
||||
disableSearch?: boolean
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
getParams?: any
|
||||
description?: string
|
||||
errorMessages?: string
|
||||
itemKey?: string // default: id
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
value?: any | any[]
|
||||
disabled?: boolean
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
valueApi?: Curd<any>
|
||||
}>()
|
||||
|
||||
|
@ -33,7 +33,7 @@ const getParams = computed(() => {
|
|||
})
|
||||
|
||||
const visible = ref(false)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const M_values = ref([]) as any
|
||||
|
||||
const init = _.debounce(_init, 500, {
|
||||
|
@ -45,7 +45,7 @@ onMounted(() => {
|
|||
init()
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
const records = ref([]) as Ref<any[]>
|
||||
|
||||
async function _init() {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { h } from 'vue'
|
||||
import type { StdDesignEdit } from '@/components/StdDesign/types'
|
||||
import type { Dayjs } from 'dayjs'
|
||||
import { DATE_FORMAT } from '@/constants'
|
||||
import {
|
||||
DatePicker,
|
||||
Input,
|
||||
|
@ -7,16 +9,14 @@ import {
|
|||
Switch,
|
||||
Textarea,
|
||||
} from 'ant-design-vue'
|
||||
import type { Dayjs } from 'dayjs'
|
||||
import dayjs from 'dayjs'
|
||||
import StdDataEntry from './StdDataEntry.vue'
|
||||
import StdSelector from './components/StdSelector.vue'
|
||||
import StdSelect from './components/StdSelect.vue'
|
||||
import { h } from 'vue'
|
||||
import StdPassword from './components/StdPassword.vue'
|
||||
import type { StdDesignEdit } from '@/components/StdDesign/types'
|
||||
import { DATE_FORMAT } from '@/constants'
|
||||
import StdSelect from './components/StdSelect.vue'
|
||||
import StdSelector from './components/StdSelector.vue'
|
||||
import StdDataEntry from './StdDataEntry.vue'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function readonly(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
return h('p', dataSource?.[dataIndex] ?? edit?.config?.defaultValue)
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export function placeholderHelper(edit: StdDesignEdit) {
|
|||
return typeof edit.config?.placeholder === 'function' ? edit.config?.placeholder() : edit.config?.placeholder
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function input(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
return h(Input, {
|
||||
'autocomplete': 'off',
|
||||
|
@ -44,7 +44,7 @@ export function input(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
|||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function inputNumber(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
if (edit.config?.defaultValue !== undefined)
|
||||
dataSource[dataIndex] = edit.config.defaultValue
|
||||
|
@ -64,7 +64,7 @@ export function inputNumber(edit: StdDesignEdit, dataSource: any, dataIndex: any
|
|||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function textarea(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
return h(Textarea, {
|
||||
'placeholder': placeholderHelper(edit),
|
||||
|
@ -75,7 +75,7 @@ export function textarea(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
|||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function password(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
return (
|
||||
<StdPassword
|
||||
|
@ -87,7 +87,7 @@ export function password(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
|||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function select(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
const actualDataIndex = edit?.actualDataIndex ?? dataIndex
|
||||
|
||||
|
@ -102,7 +102,7 @@ export function select(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
|||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function selector(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
return (
|
||||
<StdSelector
|
||||
|
@ -119,18 +119,18 @@ export function selector(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
|||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function switcher(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
return h(Switch, {
|
||||
'checked': dataSource?.[dataIndex] ?? edit?.config?.defaultValue,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
'onUpdate:checked': (value: any) => {
|
||||
dataSource[dataIndex] = value
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function datePicker(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
const date: Dayjs | undefined = dataSource?.[dataIndex] ? dayjs(dataSource?.[dataIndex]) : undefined
|
||||
|
||||
|
@ -143,7 +143,7 @@ export function datePicker(edit: StdDesignEdit, dataSource: any, dataIndex: any)
|
|||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
export function dateRangePicker(edit: StdDesignEdit, dataSource: any, dataIndex: any) {
|
||||
const dates: [Dayjs, Dayjs] = dataSource
|
||||
?.[dataIndex]
|
||||
|
|
27
app/src/components/StdDesign/types.d.ts
vendored
27
app/src/components/StdDesign/types.d.ts
vendored
|
@ -1,7 +1,8 @@
|
|||
import Curd, {Pagination} from '@/api/curd'
|
||||
import {Ref} from 'vue'
|
||||
import type {JSX} from 'vue/jsx'
|
||||
import {TableColumnType} from "ant-design-vue"
|
||||
import type { Pagination } from '@/api/curd'
|
||||
import type Curd from '@/api/curd'
|
||||
import type { TableColumnType } from 'ant-design-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import type { JSX } from 'vue/jsx'
|
||||
|
||||
export type JSXElements = JSX.Element[]
|
||||
|
||||
|
@ -25,7 +26,7 @@ export interface StdDesignEdit {
|
|||
}
|
||||
|
||||
selector?: {
|
||||
getParams?: {}
|
||||
getParams?: object
|
||||
recordValueIndex: any // relative to api return
|
||||
selectionType: any
|
||||
api: Curd
|
||||
|
@ -52,7 +53,7 @@ export interface StdDesignEdit {
|
|||
max?: number // max value for input number
|
||||
error_messages?: Ref
|
||||
required?: boolean
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
defaultValue?: any
|
||||
addonBefore?: string // for inputNumber
|
||||
addonAfter?: string // for inputNumber
|
||||
|
@ -63,12 +64,14 @@ export interface StdDesignEdit {
|
|||
flex?: Flex
|
||||
}
|
||||
|
||||
type FlexType = string | number | boolean
|
||||
|
||||
export interface Flex {
|
||||
sm?: string | number | boolean
|
||||
md?: string | number | boolean
|
||||
lg?: string | number | boolean
|
||||
xl?: string | number | boolean
|
||||
xxl?: string | number | boolean
|
||||
sm?: FlexType
|
||||
md?: FlexType
|
||||
lg?: FlexType
|
||||
xl?: FlexType
|
||||
xxl?: FlexType
|
||||
}
|
||||
|
||||
export interface Column extends TableColumnType {
|
||||
|
@ -88,7 +91,7 @@ export interface Column extends TableColumnType {
|
|||
batch?: boolean
|
||||
customRender?: function
|
||||
selector?: {
|
||||
getParams?: {}
|
||||
getParams?: object
|
||||
recordValueIndex: any // relative to api return
|
||||
selectionType: any
|
||||
api: Curd
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script lang="ts" setup>
|
||||
import type { Ref } from 'vue'
|
||||
import VPIconMoon from './icons/VPIconMoon.vue'
|
||||
import VPIconSun from './icons/VPIconSun.vue'
|
||||
import VPSwitch from '@/components/VPSwitch/VPSwitch.vue'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import VPIconMoon from './icons/VPIconMoon.vue'
|
||||
import VPIconSun from './icons/VPIconSun.vue'
|
||||
|
||||
const settings = useSettingsStore()
|
||||
const devicePrefersTheme = inject('devicePrefersTheme') as Ref<string>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import type { TwoFAStatusResponse } from '@/api/2fa'
|
||||
import twoFA from '@/api/2fa'
|
||||
import OTPInput from '@/components/OTPInput/OTPInput.vue'
|
||||
import { useUserStore } from '@/pinia'
|
||||
import { KeyOutlined } from '@ant-design/icons-vue'
|
||||
import { startAuthentication } from '@simplewebauthn/browser'
|
||||
import { message } from 'ant-design-vue'
|
||||
import OTPInput from '@/components/OTPInput/OTPInput.vue'
|
||||
import type { TwoFAStatusResponse } from '@/api/2fa'
|
||||
import twoFA from '@/api/2fa'
|
||||
import { useUserStore } from '@/pinia'
|
||||
|
||||
defineProps<{
|
||||
twoFAStatus: TwoFAStatusResponse
|
||||
|
@ -55,7 +55,7 @@ async function passkeyAuthenticate() {
|
|||
|
||||
emit('submitSecureSessionID', r.session_id)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
catch (e: any) {
|
||||
message.error($gettext(e.message ?? 'Server error'))
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { createVNode, render } from 'vue'
|
||||
import { Modal, message } from 'ant-design-vue'
|
||||
import Authorization from '@/components/TwoFA/Authorization.vue'
|
||||
import twoFA from '@/api/2fa'
|
||||
import Authorization from '@/components/TwoFA/Authorization.vue'
|
||||
import { useUserStore } from '@/pinia'
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
import { createVNode, render } from 'vue'
|
||||
|
||||
const use2FAModal = () => {
|
||||
function use2FAModal() {
|
||||
const refOTPAuthorization = ref<typeof Authorization>()
|
||||
const randomId = Math.random().toString(36).substring(2, 8)
|
||||
const { secureSessionId } = storeToRefs(useUserStore())
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Bread } from '@/components/Breadcrumb/types'
|
||||
|
||||
export const useBreadcrumbs = () => {
|
||||
export function useBreadcrumbs() {
|
||||
return inject('breadList') as Ref<Bread[]>
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import settings from '@/api/settings'
|
||||
import PageHeader from '@/components/PageHeader/PageHeader.vue'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import _ from 'lodash'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import FooterLayout from './FooterLayout.vue'
|
||||
import SideBar from './SideBar.vue'
|
||||
import HeaderLayout from './HeaderLayout.vue'
|
||||
import PageHeader from '@/components/PageHeader/PageHeader.vue'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import settings from '@/api/settings'
|
||||
import SideBar from './SideBar.vue'
|
||||
|
||||
const drawer_visible = ref(false)
|
||||
const collapsed = ref(collapse())
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import { HomeOutlined, LogoutOutlined, MenuUnfoldOutlined } from '@ant-design/icons-vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
|
||||
import auth from '@/api/auth'
|
||||
import NginxControl from '@/components/NginxControl/NginxControl.vue'
|
||||
import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
|
||||
import Notification from '@/components/Notification/Notification.vue'
|
||||
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
|
||||
import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
|
||||
import { HomeOutlined, LogoutOutlined, MenuUnfoldOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const emit = defineEmits<{
|
||||
clickUnFold: [void]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import type { ComputedRef, Ref } from 'vue'
|
||||
import type { AntdIconType } from '@ant-design/icons-vue/lib/components/AntdIcon'
|
||||
import type { IconComponentProps } from '@ant-design/icons-vue/es/components/Icon'
|
||||
import type { AntdIconType } from '@ant-design/icons-vue/lib/components/AntdIcon'
|
||||
import type { Key } from 'ant-design-vue/es/_util/type'
|
||||
import type { ComputedRef, Ref } from 'vue'
|
||||
import EnvIndicator from '@/components/EnvIndicator/EnvIndicator.vue'
|
||||
import Logo from '@/components/Logo/Logo.vue'
|
||||
import { routes } from '@/routes'
|
||||
import EnvIndicator from '@/components/EnvIndicator/EnvIndicator.vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
|
@ -33,41 +33,43 @@ const sidebars = computed(() => {
|
|||
return routes[0].children
|
||||
})
|
||||
|
||||
interface meta {
|
||||
interface Meta {
|
||||
icon: AntdIconType
|
||||
hiddenInSidebar: boolean
|
||||
hideChildren: boolean
|
||||
name: () => string
|
||||
}
|
||||
|
||||
interface sidebar {
|
||||
interface Sidebar {
|
||||
path: string
|
||||
name: string
|
||||
meta: meta
|
||||
children: sidebar[]
|
||||
meta: Meta
|
||||
children: Sidebar[]
|
||||
}
|
||||
|
||||
const visible: ComputedRef<sidebar[]> = computed(() => {
|
||||
const res: sidebar[] = [];
|
||||
const visible: ComputedRef<Sidebar[]> = computed(() => {
|
||||
const res: Sidebar[] = [];
|
||||
|
||||
(sidebars.value || []).forEach(s => {
|
||||
if (s.meta && ((typeof s.meta.hiddenInSidebar === 'boolean' && s.meta.hiddenInSidebar)
|
||||
|| (typeof s.meta.hiddenInSidebar === 'function' && s.meta.hiddenInSidebar())))
|
||||
|| (typeof s.meta.hiddenInSidebar === 'function' && s.meta.hiddenInSidebar()))) {
|
||||
return
|
||||
}
|
||||
|
||||
const t: sidebar = {
|
||||
const t: Sidebar = {
|
||||
path: s.path,
|
||||
name: s.name as string,
|
||||
meta: s.meta as unknown as meta,
|
||||
meta: s.meta as unknown as Meta,
|
||||
children: [],
|
||||
};
|
||||
|
||||
(s.children || []).forEach(c => {
|
||||
if (c.meta && ((typeof c.meta.hiddenInSidebar === 'boolean' && c.meta.hiddenInSidebar)
|
||||
|| (typeof c.meta.hiddenInSidebar === 'function' && c.meta.hiddenInSidebar())))
|
||||
|| (typeof c.meta.hiddenInSidebar === 'function' && c.meta.hiddenInSidebar()))) {
|
||||
return
|
||||
}
|
||||
|
||||
t.children.push((c as unknown as sidebar))
|
||||
t.children.push((c as unknown as Sidebar))
|
||||
})
|
||||
res.push(t)
|
||||
})
|
||||
|
|
|
@ -13,7 +13,7 @@ function bytesToSize(bytes: number) {
|
|||
|
||||
return `${(bytes / k ** i).toFixed(2)} ${sizes[i]}`
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
function downloadCsv(header: any, data: any[], fileName: string) {
|
||||
if (!header || !Array.isArray(header) || !Array.isArray(data) || !header.length)
|
||||
return
|
||||
|
@ -25,8 +25,8 @@ function downloadCsv(header: any, data: any[], fileName: string) {
|
|||
csvContent += `${_header}\n`
|
||||
data.forEach((item, index) => {
|
||||
let dataString = ''
|
||||
for (let i = 0; i < keys.length; i++)
|
||||
dataString += `${item[keys[i]]},`
|
||||
for (const element of keys)
|
||||
dataString += `${item[element]},`
|
||||
|
||||
csvContent += index < data.length ? dataString.replace(/,$/, '\n') : dataString.replace(/,$/, '')
|
||||
})
|
||||
|
@ -39,15 +39,16 @@ function downloadCsv(header: any, data: any[], fileName: string) {
|
|||
window.URL.revokeObjectURL(csvContent)
|
||||
}
|
||||
|
||||
const urlJoin = (...args: string[]) =>
|
||||
args
|
||||
function urlJoin(...args: string[]) {
|
||||
return args
|
||||
.join('/')
|
||||
.replace(/[\/]+/g, '/')
|
||||
.replace(/\/+/g, '/')
|
||||
.replace(/^(.+):\//, '$1://')
|
||||
.replace(/^file:/, 'file:/')
|
||||
.replace(/\/(\?|&|#[^!])/g, '$1')
|
||||
.replace(/\?/g, '&')
|
||||
.replace('&', '?')
|
||||
}
|
||||
|
||||
function fromNow(t: string) {
|
||||
dayjs.extend(relativeTime)
|
||||
|
@ -66,8 +67,8 @@ function formatDateTime(t: string) {
|
|||
export {
|
||||
bytesToSize,
|
||||
downloadCsv,
|
||||
urlJoin,
|
||||
fromNow,
|
||||
formatDate,
|
||||
formatDateTime,
|
||||
fromNow,
|
||||
urlJoin,
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import type { AxiosRequestConfig } from 'axios'
|
||||
import axios from 'axios'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import NProgress from 'nprogress'
|
||||
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||
import 'nprogress/nprogress.css'
|
||||
|
||||
import router from '@/routes'
|
||||
import use2FAModal from '@/components/TwoFA/use2FAModal'
|
||||
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||
import router from '@/routes'
|
||||
import axios from 'axios'
|
||||
import NProgress from 'nprogress'
|
||||
|
||||
import { storeToRefs } from 'pinia'
|
||||
import 'nprogress/nprogress.css'
|
||||
|
||||
const user = useUserStore()
|
||||
const settings = useSettingsStore()
|
||||
|
@ -30,17 +30,17 @@ instance.interceptors.request.use(
|
|||
config => {
|
||||
NProgress.start()
|
||||
if (token.value) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
(config.headers as any).Authorization = token.value
|
||||
}
|
||||
|
||||
if (settings.environment.id) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
(config.headers as any)['X-Node-ID'] = settings.environment.id
|
||||
}
|
||||
|
||||
if (secureSessionId.value) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
(config.headers as any)['X-Secure-Session-ID'] = secureSessionId.value
|
||||
}
|
||||
|
||||
|
@ -78,25 +78,25 @@ instance.interceptors.response.use(
|
|||
|
||||
const http = {
|
||||
get(url: string, config: AxiosRequestConfig = {}) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
return instance.get<any, any>(url, config)
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
post(url: string, data: any = undefined, config: AxiosRequestConfig = {}) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
return instance.post<any, any>(url, data, config)
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
put(url: string, data: any = undefined, config: AxiosRequestConfig = {}) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
return instance.put<any, any>(url, data, config)
|
||||
},
|
||||
delete(url: string, config: AxiosRequestConfig = {}) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
return instance.delete<any, any>(url, config)
|
||||
},
|
||||
patch(url: string, config: AxiosRequestConfig = {}) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
return instance.patch<any, any>(url, config)
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import ReconnectingWebSocket from 'reconnecting-websocket'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||
import { urlJoin } from '@/lib/helper'
|
||||
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket'
|
||||
|
||||
function ws(url: string, reconnect: boolean = true): ReconnectingWebSocket | WebSocket {
|
||||
const user = useUserStore()
|
||||
|
@ -12,8 +12,7 @@ function ws(url: string, reconnect: boolean = true): ReconnectingWebSocket | Web
|
|||
|
||||
const node_id = (settings.environment.id > 0) ? (`&x_node_id=${settings.environment.id}`) : ''
|
||||
|
||||
const _url = urlJoin(protocol + window.location.host, window.location.pathname,
|
||||
url, `?token=${btoa(token.value)}`, node_id)
|
||||
const _url = urlJoin(protocol + window.location.host, window.location.pathname, url, `?token=${btoa(token.value)}`, node_id)
|
||||
|
||||
if (reconnect)
|
||||
return new ReconnectingWebSocket(_url, undefined, { maxRetries: 10 })
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { createApp } from 'vue'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import { autoAnimatePlugin } from '@formkit/auto-animate/vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||
import { autoAnimatePlugin } from '@formkit/auto-animate/vue'
|
||||
import gettext from './gettext'
|
||||
import { createApp } from 'vue'
|
||||
import VueDOMPurifyHTML from 'vue-dompurify-html'
|
||||
import App from './App.vue'
|
||||
import gettext from './gettext'
|
||||
import router from './routes'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import './style.css'
|
||||
|
||||
const pinia = createPinia()
|
||||
|
@ -15,6 +16,7 @@ const app = createApp(App)
|
|||
pinia.use(piniaPluginPersistedstate)
|
||||
app.use(pinia)
|
||||
app.use(gettext)
|
||||
app.use(VueDOMPurifyHTML)
|
||||
|
||||
// after pinia created
|
||||
const settings = useSettingsStore()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useUserStore } from './moudule/user'
|
||||
import { useSettingsStore } from './moudule/settings'
|
||||
import { useUserStore } from './moudule/user'
|
||||
|
||||
export {
|
||||
useUserStore,
|
||||
useSettingsStore,
|
||||
useUserStore,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import type { NginxStatus } from '@/constants'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useGlobalStore = defineStore('global', () => {
|
||||
const nginxStatus:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { useCookies } from '@vueuse/integrations/useCookies'
|
||||
import type { CookieChangeOptions } from 'universal-cookie'
|
||||
import { useCookies } from '@vueuse/integrations/useCookies'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const cookies = useCookies(['nginx-ui'])
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||
|
||||
import {
|
||||
BellOutlined,
|
||||
|
@ -17,7 +17,7 @@ import {
|
|||
} from '@ant-design/icons-vue'
|
||||
import NProgress from 'nprogress'
|
||||
|
||||
import { useSettingsStore, useUserStore } from '@/pinia'
|
||||
import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
|
||||
import 'nprogress/nprogress.css'
|
||||
|
||||
|
|
4
app/src/routes/type.d.ts
vendored
4
app/src/routes/type.d.ts
vendored
|
@ -1,8 +1,8 @@
|
|||
import type { AntDesignOutlinedIconType } from '@ant-design/icons-vue/lib/icons/AntDesignOutlined'
|
||||
|
||||
// src/types/vue-router.d.ts
|
||||
import 'vue-router'
|
||||
|
||||
import type {AntDesignOutlinedIconType} from '@ant-design/icons-vue/lib/icons/AntDesignOutlined'
|
||||
|
||||
/**
|
||||
* @description Extend the types of router meta
|
||||
*/
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script setup lang="tsx">
|
||||
import { Tag, message } from 'ant-design-vue'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import { StdCurd } from '@/components/StdDesign/StdDataDisplay'
|
||||
import type { AcmeUser } from '@/api/acme_user'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import acme_user from '@/api/acme_user'
|
||||
import { input, switcher } from '@/components/StdDesign/StdDataEntry'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { StdCurd } from '@/components/StdDesign/StdDataDisplay'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { input, switcher } from '@/components/StdDesign/StdDataEntry'
|
||||
import { message, Tag } from 'ant-design-vue'
|
||||
|
||||
const columns: Column[] = [
|
||||
{
|
||||
|
@ -20,7 +20,8 @@ const columns: Column[] = [
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: () => $gettext('Email'),
|
||||
dataIndex: 'email',
|
||||
sorter: true,
|
||||
|
@ -31,7 +32,8 @@ const columns: Column[] = [
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: () => $gettext('CA Dir'),
|
||||
dataIndex: 'ca_dir',
|
||||
sorter: true,
|
||||
|
@ -44,7 +46,8 @@ const columns: Column[] = [
|
|||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: () => $gettext('Proxy'),
|
||||
dataIndex: 'proxy',
|
||||
hiddenInTable: true,
|
||||
|
@ -57,10 +60,11 @@ const columns: Column[] = [
|
|||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: () => $gettext('Status'),
|
||||
dataIndex: ['registration', 'body', 'status'],
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
if (args.text === 'valid')
|
||||
return <Tag color="green">{$gettext('Valid')}</Tag>
|
||||
|
||||
|
@ -68,7 +72,8 @@ const columns: Column[] = [
|
|||
},
|
||||
sorter: true,
|
||||
pithy: true,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: () => $gettext('Register On Startup'),
|
||||
dataIndex: 'register_on_startup',
|
||||
hiddenInTable: true,
|
||||
|
@ -76,15 +81,17 @@ const columns: Column[] = [
|
|||
edit: {
|
||||
type: switcher,
|
||||
hint: $gettext('When Enabled, Nginx UI will automatically re-register users upon startup. '
|
||||
+ 'Generally, do not enable this unless you are in a dev environment and using Pebble as CA.'),
|
||||
+ 'Generally, do not enable this unless you are in a dev environment and using Pebble as CA.'),
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: () => $gettext('Updated at'),
|
||||
dataIndex: 'updated_at',
|
||||
customRender: datetime,
|
||||
sorter: true,
|
||||
pithy: true,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
title: () => $gettext('Action'),
|
||||
dataIndex: 'action',
|
||||
},
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import type { AcmeUser } from '@/api/acme_user'
|
||||
import type { AutoCertOptions } from '@/api/auto_cert'
|
||||
import type { SelectProps } from 'ant-design-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import type { AcmeUser } from '@/api/acme_user'
|
||||
import acme_user from '@/api/acme_user'
|
||||
import type { AutoCertOptions } from '@/api/auto_cert'
|
||||
|
||||
const users = ref([]) as Ref<AcmeUser[]>
|
||||
|
||||
|
@ -51,7 +51,7 @@ onMounted(async () => {
|
|||
break
|
||||
page++
|
||||
}
|
||||
catch (e) {
|
||||
catch {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ const options = computed<SelectProps['options']>(() => {
|
|||
return list
|
||||
})
|
||||
|
||||
const filterOption = (input: string, option: { label: string }) => {
|
||||
function filterOption(input: string, option: { label: string }) {
|
||||
return option.label.toLowerCase().includes(input.toLowerCase())
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import type { Cert } from '@/api/cert'
|
||||
import type { Ref } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import cert from '@/api/cert'
|
||||
import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import NodeSelector from '@/components/NodeSelector/NodeSelector.vue'
|
||||
import { AutoCertState } from '@/constants'
|
||||
import RenewCert from '@/views/certificate/RenewCert.vue'
|
||||
import CertInfo from '@/views/site/cert/CertInfo.vue'
|
||||
import AutoCertStepOne from '@/views/site/cert/components/AutoCertStepOne.vue'
|
||||
import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
|
||||
import type { Cert } from '@/api/cert'
|
||||
import cert from '@/api/cert'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import RenewCert from '@/views/certificate/RenewCert.vue'
|
||||
import NodeSelector from '@/components/NodeSelector/NodeSelector.vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
|
@ -235,10 +235,9 @@ const isManaged = computed(() => {
|
|||
:md="12"
|
||||
>
|
||||
<ACard :title="$gettext('Log')">
|
||||
<pre
|
||||
class="log-container"
|
||||
v-html="log"
|
||||
/>
|
||||
<pre class="log-container">
|
||||
{{ log }}
|
||||
</pre>
|
||||
</ACard>
|
||||
</ACol>
|
||||
</ARow>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="tsx">
|
||||
import cert from '@/api/cert'
|
||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import WildcardCertificate from '@/views/certificate/WildcardCertificate.vue'
|
||||
import { CloudUploadOutlined, SafetyCertificateOutlined } from '@ant-design/icons-vue'
|
||||
import certColumns from './certColumns'
|
||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import cert from '@/api/cert'
|
||||
import WildcardCertificate from '@/views/certificate/WildcardCertificate.vue'
|
||||
|
||||
const refWildcard = ref()
|
||||
const refTable = ref()
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import dayjs from 'dayjs'
|
||||
import { Badge, Tag } from 'ant-design-vue'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Column, JSXElements } from '@/components/StdDesign/types'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { datetime, mask } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { input } from '@/components/StdDesign/StdDataEntry'
|
||||
import { PrivateKeyTypeMask } from '@/constants'
|
||||
import { Badge, Tag } from 'ant-design-vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const columns: Column[] = [{
|
||||
title: () => $gettext('Name'),
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
pithy: true,
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
const { text, record } = args
|
||||
if (!text)
|
||||
return h('div', record.domain)
|
||||
|
@ -24,26 +24,34 @@ const columns: Column[] = [{
|
|||
}, {
|
||||
title: () => $gettext('Type'),
|
||||
dataIndex: 'auto_cert',
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
const template: JSXElements = []
|
||||
const { text } = args
|
||||
const sync = $gettext('Sync Certificate')
|
||||
const managed = $gettext('Managed Certificate')
|
||||
const general = $gettext('General Certificate')
|
||||
if (text === true || text === 1) {
|
||||
template.push(<Tag bordered={false} color="processing">
|
||||
{ managed }
|
||||
</Tag>)
|
||||
template.push(
|
||||
<Tag bordered={false} color="processing">
|
||||
{ managed }
|
||||
</Tag>,
|
||||
)
|
||||
}
|
||||
else if (text === 2) {
|
||||
template.push(<Tag bordered={false} color="success">
|
||||
{ sync }
|
||||
</Tag>)
|
||||
template.push(
|
||||
<Tag bordered={false} color="success">
|
||||
{ sync }
|
||||
</Tag>,
|
||||
)
|
||||
}
|
||||
else {
|
||||
template.push(<Tag bordered={false} color="purple">{
|
||||
general }
|
||||
</Tag>)
|
||||
template.push(
|
||||
<Tag bordered={false} color="purple">
|
||||
{
|
||||
general
|
||||
}
|
||||
</Tag>,
|
||||
)
|
||||
}
|
||||
|
||||
return h('div', template)
|
||||
|
@ -60,7 +68,7 @@ const columns: Column[] = [{
|
|||
title: () => $gettext('Status'),
|
||||
dataIndex: 'certificate_info',
|
||||
pithy: true,
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
const template: JSXElements = []
|
||||
|
||||
const text = args.text?.not_before
|
||||
|
@ -69,11 +77,11 @@ const columns: Column[] = [{
|
|||
&& !dayjs().isAfter(args.text?.not_after)
|
||||
|
||||
if (text) {
|
||||
template.push(<Badge status="success"/>)
|
||||
template.push(<Badge status="success" />)
|
||||
template.push($gettext('Valid'))
|
||||
}
|
||||
else {
|
||||
template.push(<Badge status="error"/>)
|
||||
template.push(<Badge status="error" />)
|
||||
template.push($gettext('Expired'))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import type { DNSProvider } from '@/api/auto_cert'
|
||||
import type { SelectProps } from 'ant-design-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import type { DNSProvider } from '@/api/auto_cert'
|
||||
import auto_cert from '@/api/auto_cert'
|
||||
|
||||
const providers = ref([]) as Ref<DNSProvider[]>
|
||||
|
@ -62,7 +62,7 @@ const options = computed<SelectProps['options']>(() => {
|
|||
return list
|
||||
})
|
||||
|
||||
const filterOption = (input: string, option: { label: string }) => {
|
||||
function filterOption(input: string, option: { label: string }) {
|
||||
return option.label.toLowerCase().includes(input.toLowerCase())
|
||||
}
|
||||
</script>
|
||||
|
@ -78,6 +78,7 @@ const filterOption = (input: string, option: { label: string }) => {
|
|||
/>
|
||||
</AFormItem>
|
||||
<AFormItem>
|
||||
<!-- eslint-disable sonarjs/no-vue-bypass-sanitization -->
|
||||
<p v-if="current?.links?.api">
|
||||
{{ $gettext('API Document') }}: <a
|
||||
:href="current.links.api"
|
||||
|
@ -92,6 +93,7 @@ const filterOption = (input: string, option: { label: string }) => {
|
|||
rel="noopener noreferrer"
|
||||
>{{ current.links.go_client }}</a>
|
||||
</p>
|
||||
<!-- eslint-enable -->
|
||||
</AFormItem>
|
||||
<template v-if="current?.configuration?.credentials">
|
||||
<h4>{{ $gettext('Credentials') }}</h4>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="tsx">
|
||||
import DNSChallenge from './DNSChallenge.vue'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import dns_credential from '@/api/dns_credential'
|
||||
import StdCurd from '@/components/StdDesign/StdDataDisplay/StdCurd.vue'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { input } from '@/components/StdDesign/StdDataEntry'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import DNSChallenge from './DNSChallenge.vue'
|
||||
|
||||
const columns: Column[] = [{
|
||||
title: () => $gettext('Name'),
|
||||
|
@ -18,7 +18,7 @@ const columns: Column[] = [{
|
|||
}, {
|
||||
title: () => $gettext('Provider'),
|
||||
dataIndex: ['config', 'name'],
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
return args.record.provider
|
||||
},
|
||||
sorter: true,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import ObtainCertLive from '@/views/site/cert/components/ObtainCertLive.vue'
|
||||
import type { AutoCertOptions } from '@/api/auto_cert'
|
||||
import ObtainCertLive from '@/views/site/cert/components/ObtainCertLive.vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const props = defineProps<{
|
||||
options: AutoCertOptions
|
||||
|
@ -16,7 +16,7 @@ const modalClosable = ref(true)
|
|||
|
||||
const refObtainCertLive = ref()
|
||||
|
||||
const issueCert = () => {
|
||||
function issueCert() {
|
||||
modalVisible.value = true
|
||||
|
||||
const { name, domains, key_type } = props.options
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import type { Ref } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import ObtainCertLive from '@/views/site/cert/components/ObtainCertLive.vue'
|
||||
import type { AutoCertOptions } from '@/api/auto_cert'
|
||||
import type { Ref } from 'vue'
|
||||
import AutoCertStepOne from '@/views/site/cert/components/AutoCertStepOne.vue'
|
||||
import ObtainCertLive from '@/views/site/cert/components/ObtainCertLive.vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
issued: [void]
|
||||
|
@ -39,12 +39,11 @@ const computedDomain = computed(() => {
|
|||
return `*.${domain.value}`
|
||||
})
|
||||
|
||||
const issueCert = () => {
|
||||
function issueCert() {
|
||||
step.value++
|
||||
modalVisible.value = true
|
||||
|
||||
refObtainCertLive.value.issue_cert(computedDomain.value,
|
||||
[computedDomain.value, domain.value], data.value.key_type)
|
||||
refObtainCertLive.value.issue_cert(computedDomain.value, [computedDomain.value, domain.value], data.value.key_type)
|
||||
.then(() => {
|
||||
message.success($gettext('Renew successfully'))
|
||||
emit('issued')
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { InfoCircleOutlined } from '@ant-design/icons-vue'
|
||||
import _ from 'lodash'
|
||||
import { formatDateTime } from '@/lib/helper'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import type { Config } from '@/api/config'
|
||||
import config from '@/api/config'
|
||||
import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
|
||||
import ngx from '@/api/ngx'
|
||||
import InspectConfig from '@/views/config/InspectConfig.vue'
|
||||
import ChatGPT from '@/components/ChatGPT/ChatGPT.vue'
|
||||
import type { ChatComplicationMessage } from '@/api/openai'
|
||||
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
|
||||
import type { Ref } from 'vue'
|
||||
import config from '@/api/config'
|
||||
import ngx from '@/api/ngx'
|
||||
import ChatGPT from '@/components/ChatGPT/ChatGPT.vue'
|
||||
import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import NodeSelector from '@/components/NodeSelector/NodeSelector.vue'
|
||||
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
|
||||
import { formatDateTime } from '@/lib/helper'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import InspectConfig from '@/views/config/InspectConfig.vue'
|
||||
import { InfoCircleOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import _ from 'lodash'
|
||||
|
||||
const settings = useSettingsStore()
|
||||
const route = useRoute()
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import { $gettext } from '../../gettext'
|
||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import config from '@/api/config'
|
||||
import configColumns from '@/views/config/configColumns'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import InspectConfig from '@/views/config/InspectConfig.vue'
|
||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import { useBreadcrumbs } from '@/composables/useBreadcrumbs'
|
||||
import Mkdir from '@/views/config/components/Mkdir.vue'
|
||||
import Rename from '@/views/config/components/Rename.vue'
|
||||
import configColumns from '@/views/config/configColumns'
|
||||
import InspectConfig from '@/views/config/InspectConfig.vue'
|
||||
import { $gettext } from '../../gettext'
|
||||
|
||||
const table = ref()
|
||||
const route = useRoute()
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
import { message } from 'ant-design-vue'
|
||||
import config from '@/api/config'
|
||||
import use2FAModal from '@/components/TwoFA/use2FAModal'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const emit = defineEmits(['created'])
|
||||
const visible = ref(false)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import config from '@/api/config'
|
||||
import use2FAModal from '@/components/TwoFA/use2FAModal'
|
||||
import NodeSelector from '@/components/NodeSelector/NodeSelector.vue'
|
||||
import use2FAModal from '@/components/TwoFA/use2FAModal'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const emit = defineEmits(['renamed'])
|
||||
const visible = ref(false)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { h } from 'vue'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { JSXElements } from '@/components/StdDesign/types'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { input } from '@/components/StdDesign/StdDataEntry'
|
||||
import { h } from 'vue'
|
||||
|
||||
const configColumns = [{
|
||||
title: () => $gettext('Name'),
|
||||
|
@ -15,7 +15,7 @@ const configColumns = [{
|
|||
}, {
|
||||
title: () => $gettext('Type'),
|
||||
dataIndex: 'is_dir',
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
const template: JSXElements = []
|
||||
const { text } = args
|
||||
if (text === true || text > 0)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import ServerAnalytic from '@/views/dashboard/ServerAnalytic.vue'
|
||||
import Environments from '@/views/dashboard/Environments.vue'
|
||||
import ServerAnalytic from '@/views/dashboard/ServerAnalytic.vue'
|
||||
|
||||
const key = ref(0)
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import Icon, { LinkOutlined, SendOutlined, ThunderboltOutlined } from '@ant-design/icons-vue'
|
||||
import type { Node } from '@/api/environment'
|
||||
import type ReconnectingWebSocket from 'reconnecting-websocket'
|
||||
import type { Ref } from 'vue'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import type { Node } from '@/api/environment'
|
||||
import analytic from '@/api/analytic'
|
||||
import environment from '@/api/environment'
|
||||
import logo from '@/assets/img/logo.png'
|
||||
import pulse from '@/assets/svg/pulse.svg?component'
|
||||
import { formatDateTime } from '@/lib/helper'
|
||||
import NodeAnalyticItem from '@/views/dashboard/components/NodeAnalyticItem.vue'
|
||||
import analytic from '@/api/analytic'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import { version } from '@/version.json'
|
||||
import NodeAnalyticItem from '@/views/dashboard/components/NodeAnalyticItem.vue'
|
||||
import Icon, { LinkOutlined, SendOutlined, ThunderboltOutlined } from '@ant-design/icons-vue'
|
||||
|
||||
const data = ref([]) as Ref<Node[]>
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import type { CPUInfoStat, DiskStat, HostInfoStat, LoadStat, MemStat } from '@/api/analytic'
|
||||
import type { Series } from '@/components/Chart/types'
|
||||
import type ReconnectingWebSocket from 'reconnecting-websocket'
|
||||
import analytic from '@/api/analytic'
|
||||
import AreaChart from '@/components/Chart/AreaChart.vue'
|
||||
import RadialBarChart from '@/components/Chart/RadialBarChart.vue'
|
||||
import type { CPUInfoStat, DiskStat, HostInfoStat, LoadStat, MemStat } from '@/api/analytic'
|
||||
import analytic from '@/api/analytic'
|
||||
import { bytesToSize } from '@/lib/helper'
|
||||
import type { Series } from '@/components/Chart/types'
|
||||
|
||||
let websocket: ReconnectingWebSocket | WebSocket
|
||||
|
||||
|
@ -21,11 +21,9 @@ const cpu = ref('0.0')
|
|||
const cpu_info = reactive([]) as CPUInfoStat[]
|
||||
const cpu_analytic_series = reactive([{ name: 'User', data: [] }, { name: 'Total', data: [] }]) as Series[]
|
||||
|
||||
const net_analytic = reactive([{ name: $gettext('Receive'), data: [] },
|
||||
{ name: $gettext('Send'), data: [] }]) as Series[]
|
||||
const net_analytic = reactive([{ name: $gettext('Receive'), data: [] }, { name: $gettext('Send'), data: [] }]) as Series[]
|
||||
|
||||
const disk_io_analytic = reactive([{ name: $gettext('Writes'), data: [] },
|
||||
{ name: $gettext('Reads'), data: [] }]) as Series[]
|
||||
const disk_io_analytic = reactive([{ name: $gettext('Writes'), data: [] }, { name: $gettext('Reads'), data: [] }]) as Series[]
|
||||
|
||||
const memory = reactive({
|
||||
total: '',
|
||||
|
@ -45,11 +43,11 @@ const uptime = ref('')
|
|||
const loadavg = reactive({ load1: 0, load5: 0, load15: 0 }) as LoadStat
|
||||
const net = reactive({ recv: 0, sent: 0, last_recv: 0, last_sent: 0 })
|
||||
|
||||
const net_formatter = (bytes: number) => {
|
||||
function net_formatter(bytes: number) {
|
||||
return `${bytesToSize(bytes)}/s`
|
||||
}
|
||||
|
||||
const cpu_formatter = (usage: number) => {
|
||||
function cpu_formatter(usage: number) {
|
||||
return usage.toFixed(2)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import Icon, { ArrowDownOutlined, ArrowUpOutlined, DatabaseOutlined, LineChartOutlined } from '@ant-design/icons-vue'
|
||||
import cpu from '@/assets/svg/cpu.svg?component'
|
||||
import memory from '@/assets/svg/memory.svg?component'
|
||||
import { bytesToSize } from '@/lib/helper'
|
||||
import UsageProgressLine from '@/components/Chart/UsageProgressLine.vue'
|
||||
import { bytesToSize } from '@/lib/helper'
|
||||
import Icon, { ArrowDownOutlined, ArrowUpOutlined, DatabaseOutlined, LineChartOutlined } from '@ant-design/icons-vue'
|
||||
|
||||
defineProps<{
|
||||
item: {
|
||||
|
@ -157,5 +157,4 @@ defineProps<{
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import _ from 'lodash'
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { marked } from 'marked'
|
||||
import { useRoute } from 'vue-router'
|
||||
import type { Environment } from '@/api/environment'
|
||||
import type { Ref } from 'vue'
|
||||
import upgrade, { type RuntimeInfo } from '@/api/upgrade'
|
||||
import websocket from '@/lib/websocket'
|
||||
import { message } from 'ant-design-vue'
|
||||
import _ from 'lodash'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const visible = ref(false)
|
||||
|
@ -80,7 +79,6 @@ const dryRun = computed(() => {
|
|||
return !!route.query.dry_run
|
||||
})
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
async function performUpgrade() {
|
||||
showLogContainer.value = true
|
||||
progressStatus.value = 'active'
|
||||
|
@ -224,7 +222,7 @@ async function performUpgrade() {
|
|||
{{ $gettext('Pre-release') }}
|
||||
</ATag>
|
||||
</h1>
|
||||
<div v-html="marked.parse(data.body)" />
|
||||
<div vue-dompurify-html="marked.parse(data.body)" />
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end">
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script setup lang="tsx">
|
||||
import { message } from 'ant-design-vue'
|
||||
import environment from '@/api/environment'
|
||||
import StdCurd from '@/components/StdDesign/StdDataDisplay/StdCurd.vue'
|
||||
import envColumns from '@/views/environment/envColumns'
|
||||
import FooterToolBar from '@/components/FooterToolbar'
|
||||
import StdCurd from '@/components/StdDesign/StdDataDisplay/StdCurd.vue'
|
||||
import BatchUpgrader from '@/views/environment/BatchUpgrader.vue'
|
||||
import envColumns from '@/views/environment/envColumns'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const curd = ref()
|
||||
function loadFromSettings() {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { h } from 'vue'
|
||||
import { Badge, Tag } from 'ant-design-vue'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Column, JSXElements } from '@/components/StdDesign/types'
|
||||
import { input, switcher } from '@/components/StdDesign/StdDataEntry'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { input, switcher } from '@/components/StdDesign/StdDataEntry'
|
||||
import { Badge, Tag } from 'ant-design-vue'
|
||||
import { h } from 'vue'
|
||||
|
||||
const columns: Column[] = [{
|
||||
title: () => $gettext('Name'),
|
||||
|
@ -14,8 +14,7 @@ const columns: Column[] = [{
|
|||
type: input,
|
||||
},
|
||||
search: true,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
title: () => $gettext('URL'),
|
||||
dataIndex: 'url',
|
||||
sorter: true,
|
||||
|
@ -26,13 +25,11 @@ const columns: Column[] = [{
|
|||
placeholder: () => 'https://10.0.0.1:9000',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
}, {
|
||||
title: () => $gettext('Version'),
|
||||
dataIndex: 'version',
|
||||
pithy: true,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
title: () => 'NodeSecret',
|
||||
dataIndex: 'token',
|
||||
sorter: true,
|
||||
|
@ -77,21 +74,21 @@ const columns: Column[] = [{
|
|||
{
|
||||
title: () => $gettext('Status'),
|
||||
dataIndex: 'status',
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
const template: JSXElements = []
|
||||
const { text } = args
|
||||
if (args.record.enabled) {
|
||||
if (text === true || text > 0) {
|
||||
template.push(<Badge status="success"/>)
|
||||
template.push(<Badge status="success" />)
|
||||
template.push($gettext('Online'))
|
||||
}
|
||||
else {
|
||||
template.push(<Badge status="error"/>)
|
||||
template.push(<Badge status="error" />)
|
||||
template.push($gettext('Offline'))
|
||||
}
|
||||
}
|
||||
else {
|
||||
template.push(<Badge status="default"/>)
|
||||
template.push(<Badge status="default" />)
|
||||
template.push($gettext('Disabled'))
|
||||
}
|
||||
|
||||
|
@ -99,11 +96,10 @@ const columns: Column[] = [{
|
|||
},
|
||||
sorter: true,
|
||||
pithy: true,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
title: () => $gettext('Enabled'),
|
||||
dataIndex: 'enabled',
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
const template: JSXElements = []
|
||||
const { text } = args
|
||||
if (text === true || text > 0)
|
||||
|
@ -119,15 +115,13 @@ const columns: Column[] = [{
|
|||
},
|
||||
sorter: true,
|
||||
pithy: true,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
title: () => $gettext('Updated at'),
|
||||
dataIndex: 'updated_at',
|
||||
customRender: datetime,
|
||||
sorter: true,
|
||||
pithy: true,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
title: () => $gettext('Action'),
|
||||
dataIndex: 'action',
|
||||
}]
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import type ReconnectingWebSocket from 'reconnecting-websocket'
|
||||
import { debounce } from 'lodash'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import type { INginxLogData } from '@/api/nginx_log'
|
||||
import type ReconnectingWebSocket from 'reconnecting-websocket'
|
||||
import nginx_log from '@/api/nginx_log'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import ws from '@/lib/websocket'
|
||||
import { debounce } from 'lodash'
|
||||
|
||||
const logContainer = ref()
|
||||
let websocket: ReconnectingWebSocket | WebSocket
|
||||
|
@ -24,7 +24,9 @@ const control: INginxLogData = reactive({
|
|||
})
|
||||
|
||||
function logType() {
|
||||
return route.path.indexOf('access') > 0 ? 'access' : route.path.indexOf('error') > 0 ? 'error' : 'site'
|
||||
if (route.path.indexOf('access') > 0)
|
||||
return 'access'
|
||||
return route.path.indexOf('error') > 0 ? 'error' : 'site'
|
||||
}
|
||||
|
||||
function openWs() {
|
||||
|
@ -162,8 +164,9 @@ const computedBuffer = computed(() => {
|
|||
ref="logContainer"
|
||||
class="nginx-log-container"
|
||||
@scroll="debounce_scroll_log"
|
||||
v-html="computedBuffer"
|
||||
/>
|
||||
>
|
||||
{{ computedBuffer }}
|
||||
</pre>
|
||||
</ACard>
|
||||
<FooterToolBar v-if="control.type === 'site'">
|
||||
<AButton @click="router.go(-1)">
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import StdCurd from '@/components/StdDesign/StdDataDisplay/StdCurd.vue'
|
||||
import notification from '@/api/notification'
|
||||
import StdCurd from '@/components/StdDesign/StdDataDisplay/StdCurd.vue'
|
||||
import { useUserStore } from '@/pinia'
|
||||
import notificationColumns from '@/views/notification/notificationColumns'
|
||||
import { message } from 'ant-design-vue'
|
||||
|
||||
const { unreadCount } = storeToRefs(useUserStore())
|
||||
|
||||
|
|
|
@ -1,33 +1,41 @@
|
|||
import { Tag } from 'ant-design-vue'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { detailRender } from '@/components/Notification/detailRender'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { NotificationTypeT } from '@/constants'
|
||||
import { detailRender } from '@/components/Notification/detailRender'
|
||||
import { Tag } from 'ant-design-vue'
|
||||
|
||||
const columns: Column[] = [{
|
||||
title: () => $gettext('Type'),
|
||||
dataIndex: 'type',
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
if (args.text === NotificationTypeT.Error) {
|
||||
return <Tag color="error">
|
||||
{ $gettext('Error') }
|
||||
</Tag>
|
||||
return (
|
||||
<Tag color="error">
|
||||
{ $gettext('Error') }
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
else if (args.text === NotificationTypeT.Warning) {
|
||||
return <Tag color="warning">
|
||||
{ $gettext('Warning') }
|
||||
</Tag>
|
||||
return (
|
||||
<Tag color="warning">
|
||||
{ $gettext('Warning') }
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
else if (args.text === NotificationTypeT.Info) {
|
||||
return <Tag color="info">
|
||||
{ $gettext('Info')}
|
||||
</Tag>
|
||||
return (
|
||||
<Tag color="info">
|
||||
{ $gettext('Info')}
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
else if (args.text === NotificationTypeT.Success) {
|
||||
return <Tag color="success">
|
||||
{ $gettext('Success') }
|
||||
</Tag>
|
||||
return (
|
||||
<Tag color="success">
|
||||
{ $gettext('Success') }
|
||||
</Tag>
|
||||
)
|
||||
}
|
||||
},
|
||||
sorter: true,
|
||||
|
@ -35,7 +43,7 @@ const columns: Column[] = [{
|
|||
}, {
|
||||
title: () => $gettext('Title'),
|
||||
dataIndex: 'title',
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
return h('span', $gettext(args.text))
|
||||
},
|
||||
pithy: true,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const info = computed(() => {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import install from '@/api/install'
|
||||
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
|
||||
import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
|
||||
import { DatabaseOutlined, LockOutlined, MailOutlined, UserOutlined } from '@ant-design/icons-vue'
|
||||
|
||||
import { Form, message } from 'ant-design-vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { DatabaseOutlined, LockOutlined, MailOutlined, UserOutlined } from '@ant-design/icons-vue'
|
||||
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
|
||||
|
||||
import install from '@/api/install'
|
||||
import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
|
||||
|
||||
const thisYear = new Date().getFullYear()
|
||||
const loading = ref(false)
|
||||
|
@ -47,16 +47,14 @@ const rulesRef = reactive({
|
|||
database: [
|
||||
{
|
||||
message: () =>
|
||||
$gettext('The filename cannot contain the following characters: %{c}',
|
||||
{ c: '& " ? < > # {} % ~ / \\' },
|
||||
),
|
||||
$gettext('The filename cannot contain the following characters: %{c}', { c: '& " ? < > # {} % ~ / \\' }),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const { validate, validateInfos } = Form.useForm(modelRef, rulesRef)
|
||||
|
||||
const onSubmit = () => {
|
||||
function onSubmit() {
|
||||
validate().then(() => {
|
||||
// modelRef
|
||||
loading.value = true
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<script setup lang="ts">
|
||||
import { KeyOutlined, LockOutlined, UserOutlined } from '@ant-design/icons-vue'
|
||||
import { Form, message } from 'ant-design-vue'
|
||||
import { startAuthentication } from '@simplewebauthn/browser'
|
||||
import { useUserStore } from '@/pinia'
|
||||
import auth from '@/api/auth'
|
||||
import install from '@/api/install'
|
||||
import passkey from '@/api/passkey'
|
||||
import SetLanguage from '@/components/SetLanguage/SetLanguage.vue'
|
||||
import SwitchAppearance from '@/components/SwitchAppearance/SwitchAppearance.vue'
|
||||
import Authorization from '@/components/TwoFA/Authorization.vue'
|
||||
import gettext from '@/gettext'
|
||||
import passkey from '@/api/passkey'
|
||||
import { useUserStore } from '@/pinia'
|
||||
import { KeyOutlined, LockOutlined, UserOutlined } from '@ant-design/icons-vue'
|
||||
import { startAuthentication } from '@simplewebauthn/browser'
|
||||
import { Form, message } from 'ant-design-vue'
|
||||
|
||||
const thisYear = new Date().getFullYear()
|
||||
|
||||
|
@ -53,7 +53,7 @@ const userStore = useUserStore()
|
|||
const { login, passkeyLogin } = userStore
|
||||
const { secureSessionId } = storeToRefs(userStore)
|
||||
|
||||
const onSubmit = () => {
|
||||
function onSubmit() {
|
||||
validate().then(async () => {
|
||||
loading.value = true
|
||||
|
||||
|
@ -121,7 +121,7 @@ auth.get_casdoor_uri()
|
|||
message.error($gettext(e.message ?? 'Server error'))
|
||||
})
|
||||
|
||||
const loginWithCasdoor = () => {
|
||||
function loginWithCasdoor() {
|
||||
window.location.href = casdoor_uri.value
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,7 @@ async function handlePasskeyLogin() {
|
|||
await router.push(next)
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line ts/no-explicit-any
|
||||
catch (e: any) {
|
||||
message.error($gettext(e.message ?? 'Server error'))
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<script setup lang="tsx">
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { BannedIP, Settings } from '@/api/settings'
|
||||
import type { CustomRenderProps } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Ref } from 'vue'
|
||||
import setting from '@/api/settings'
|
||||
import TOTP from '@/views/preference/components/TOTP.vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import dayjs from 'dayjs'
|
||||
import PasskeyRegistration from './components/Passkey.vue'
|
||||
import type { BannedIP, Settings } from '@/api/settings'
|
||||
import setting from '@/api/settings'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import TOTP from '@/views/preference/components/TOTP.vue'
|
||||
|
||||
const data: Settings = inject('data') as Settings
|
||||
|
||||
|
@ -19,7 +19,7 @@ const bannedIPColumns = [{
|
|||
}, {
|
||||
title: $gettext('Banned Until'),
|
||||
dataIndex: 'expired_at',
|
||||
customRender: (args: customRender) => {
|
||||
customRender: (args: CustomRenderProps) => {
|
||||
return dayjs.unix(args.text).format('YYYY-MM-DD HH:mm:ss')
|
||||
},
|
||||
}, {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import Draggable from 'vuedraggable'
|
||||
import { DeleteOutlined, HolderOutlined } from '@ant-design/icons-vue'
|
||||
import type { Settings } from '@/api/settings'
|
||||
import { DeleteOutlined, HolderOutlined } from '@ant-design/icons-vue'
|
||||
import Draggable from 'vuedraggable'
|
||||
|
||||
const data: Settings = inject('data') as Settings
|
||||
const errors: Record<string, Record<string, string>> = inject('errors') as Record<string, Record<string, string>>
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<script setup lang="ts">
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import settings from '@/api/settings'
|
||||
import BasicSettings from '@/views/preference/BasicSettings.vue'
|
||||
import OpenAISettings from '@/views/preference/OpenAISettings.vue'
|
||||
import NginxSettings from '@/views/preference/NginxSettings.vue'
|
||||
import type { Settings } from '@/api/settings'
|
||||
import LogrotateSettings from '@/views/preference/LogrotateSettings.vue'
|
||||
import type { Ref } from 'vue'
|
||||
import settings from '@/api/settings'
|
||||
import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
|
||||
import use2FAModal from '@/components/TwoFA/use2FAModal'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import AuthSettings from '@/views/preference/AuthSettings.vue'
|
||||
import use2FAModal from '@/components/TwoFA/use2FAModal'
|
||||
import BasicSettings from '@/views/preference/BasicSettings.vue'
|
||||
import CertSettings from '@/views/preference/CertSettings.vue'
|
||||
import LogrotateSettings from '@/views/preference/LogrotateSettings.vue'
|
||||
import NginxSettings from '@/views/preference/NginxSettings.vue'
|
||||
import OpenAISettings from '@/views/preference/OpenAISettings.vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const data = ref<Settings>({
|
||||
app: {
|
||||
|
@ -135,7 +135,6 @@ onMounted(() => {
|
|||
if (route.query?.tab)
|
||||
activeKey.value = route.query.tab.toString()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue