diff --git a/dolphinscheduler-ui-next/package.json b/dolphinscheduler-ui-next/package.json
index 65e89f5c18..54de5e4c6e 100644
--- a/dolphinscheduler-ui-next/package.json
+++ b/dolphinscheduler-ui-next/package.json
@@ -15,6 +15,7 @@
"date-fns": "^2.28.0",
"echarts": "^5.2.2",
"lodash": "^4.17.21",
+ "monaco-editor": "^0.31.1",
"naive-ui": "2.23.2",
"nprogress": "^0.2.0",
"pinia": "^2.0.9",
diff --git a/dolphinscheduler-ui-next/src/App.tsx b/dolphinscheduler-ui-next/src/App.tsx
index df3a27621e..33476945ce 100644
--- a/dolphinscheduler-ui-next/src/App.tsx
+++ b/dolphinscheduler-ui-next/src/App.tsx
@@ -15,20 +15,43 @@
* limitations under the License.
*/
-import { defineComponent, computed } from 'vue'
-import { NConfigProvider, darkTheme, GlobalThemeOverrides } from 'naive-ui'
+import { defineComponent, computed, ref, nextTick, provide } from 'vue'
+import {
+ zhCN,
+ enUS,
+ NConfigProvider,
+ darkTheme,
+ GlobalThemeOverrides,
+ NMessageProvider,
+} from 'naive-ui'
import { useThemeStore } from '@/store/theme/theme'
+import { useLocalesStore } from '@/store/locales/locales'
import themeList from '@/themes'
const App = defineComponent({
name: 'App',
setup() {
+ const isRouterAlive = ref(true)
const themeStore = useThemeStore()
const currentTheme = computed(() =>
- themeStore.darkTheme ? darkTheme : undefined
+ themeStore.darkTheme ? darkTheme : undefined,
)
+ const localesStore = useLocalesStore()
+ /*refresh page when router params change*/
+ const reload = () => {
+ isRouterAlive.value = false
+ nextTick(() => {
+ isRouterAlive.value = true
+ })
+ }
+
+ provide('reload', reload)
+
return {
+ reload,
+ isRouterAlive,
currentTheme,
+ localesStore,
}
},
render() {
@@ -40,8 +63,11 @@ const App = defineComponent({
theme={this.currentTheme}
themeOverrides={themeOverrides}
style={{ width: '100%', height: '100vh' }}
+ locale={String(this.localesStore.getLocales) === 'zh_CN' ? zhCN : enUS}
>
-
+
+ {this.isRouterAlive ? : ''}
+
)
},
diff --git a/dolphinscheduler-ui-next/src/components/card/index.tsx b/dolphinscheduler-ui-next/src/components/card/index.tsx
index 9ad5602ab9..25be283ffe 100644
--- a/dolphinscheduler-ui-next/src/components/card/index.tsx
+++ b/dolphinscheduler-ui-next/src/components/card/index.tsx
@@ -29,7 +29,6 @@ const contentStyle = {
const props = {
title: {
type: String as PropType,
- required: true,
},
}
diff --git a/dolphinscheduler-ui-next/src/components/conditions/index.module.scss b/dolphinscheduler-ui-next/src/components/conditions/index.module.scss
new file mode 100644
index 0000000000..2e59ac9260
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/conditions/index.module.scss
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ .conditions-model {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin: 10px 0;
+ .right {
+ > .form-box {
+ .list {
+ float: right;
+ margin: 3px 0 3px 4px;
+ }
+ }
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/components/conditions/index.tsx b/dolphinscheduler-ui-next/src/components/conditions/index.tsx
new file mode 100644
index 0000000000..d193f74bdc
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/conditions/index.tsx
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import _ from 'lodash'
+import { useI18n } from 'vue-i18n'
+import { defineComponent, ref } from 'vue'
+import { SearchOutlined } from '@vicons/antd'
+import { NButton, NIcon, NInput, NSpace } from 'naive-ui'
+import Card from '@/components/card'
+import styles from './index.module.scss'
+
+const Conditions = defineComponent({
+ name: 'Conditions',
+ emits: ['conditions'],
+ setup(props, ctx) {
+ const searchVal = ref()
+ const handleConditions = () => {
+ ctx.emit('conditions', _.trim(searchVal.value))
+ }
+
+ return { searchVal, handleConditions }
+ },
+ render() {
+ const { t } = useI18n()
+ const { $slots, handleConditions } = this
+ return (
+
+
+ {$slots}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ },
+})
+
+export default Conditions
diff --git a/dolphinscheduler-ui-next/src/components/monaco-editor/index.tsx b/dolphinscheduler-ui-next/src/components/monaco-editor/index.tsx
new file mode 100644
index 0000000000..fb7100aa05
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/components/monaco-editor/index.tsx
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ defineComponent,
+ onMounted,
+ onUnmounted,
+ PropType,
+ nextTick,
+ ref,
+ watch,
+} from 'vue'
+import * as monaco from 'monaco-editor'
+import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
+import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
+import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
+import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
+import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
+
+const props = {
+ modelValue: {
+ type: String as PropType,
+ default: '',
+ },
+ language: {
+ type: String as PropType,
+ default: 'shell',
+ },
+ readOnly: {
+ type: Boolean as PropType,
+ default: false,
+ },
+ options: {
+ type: Object,
+ default: () => {},
+ },
+}
+
+// @ts-ignore
+window.MonacoEnvironment = {
+ getWorker(_: any, label: string) {
+ if (label === 'json') {
+ return new jsonWorker()
+ }
+ if (['css', 'scss', 'less'].includes(label)) {
+ return new cssWorker()
+ }
+ if (['html', 'handlebars', 'razor'].includes(label)) {
+ return new htmlWorker()
+ }
+ if (['typescript', 'javascript'].includes(label)) {
+ return new tsWorker()
+ }
+ return new editorWorker()
+ },
+}
+
+export default defineComponent({
+ name: 'MonacoEditor',
+ props,
+ setup(props) {
+ let editor = null as monaco.editor.IStandaloneCodeEditor | null
+ const content = ref()
+ const getValue = () => editor?.getValue()
+
+ watch(
+ () => props.modelValue,
+ (val) => {
+ if (val !== getValue()) {
+ editor?.setValue(val)
+ }
+ },
+ )
+
+ onMounted(async () => {
+ content.value = props.modelValue
+
+ await nextTick()
+ const dom = document.getElementById('monaco-container')
+ if (dom) {
+ editor = monaco.editor.create(dom, props.options, {
+ value: props.modelValue,
+ language: props.language,
+ readOnly: props.readOnly,
+ automaticLayout: true,
+ })
+ }
+ })
+
+ onUnmounted(() => {
+ editor?.dispose()
+ })
+
+ return { getValue }
+ },
+ render() {
+ return (
+
+ )
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/env.d.ts b/dolphinscheduler-ui-next/src/env.d.ts
index 776e88b786..db96b93c11 100644
--- a/dolphinscheduler-ui-next/src/env.d.ts
+++ b/dolphinscheduler-ui-next/src/env.d.ts
@@ -15,13 +15,23 @@
* limitations under the License.
*/
+import { DefineComponent } from 'vue'
+// import * as $ from 'jquery'
+
declare module '*.vue' {
- import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}
+declare global {
+ interface Window {
+ $message: any
+ }
+}
+
+declare namespace jquery {}
+
declare module '*.png'
declare module '*.jpg'
declare module '*.jpeg'
diff --git a/dolphinscheduler-ui-next/src/layouts/content/index.tsx b/dolphinscheduler-ui-next/src/layouts/content/index.tsx
index 3eb9a61eab..82da2a9ae2 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/index.tsx
+++ b/dolphinscheduler-ui-next/src/layouts/content/index.tsx
@@ -16,7 +16,7 @@
*/
import { defineComponent, onMounted, watch, toRefs, ref } from 'vue'
-import { NLayout, NLayoutContent, NLayoutHeader } from 'naive-ui'
+import { NLayout, NLayoutContent, NLayoutHeader, useMessage } from 'naive-ui'
import NavBar from './components/navbar'
import SideBar from './components/sidebar'
import { useDataList } from './use-dataList'
@@ -27,6 +27,8 @@ import { useI18n } from 'vue-i18n'
const Content = defineComponent({
name: 'Content',
setup() {
+ window.$message = useMessage()
+
const menuStore = useMenuStore()
const { locale } = useI18n()
const localesStore = useLocalesStore()
diff --git a/dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts b/dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts
index 7b0a725b34..3a37e6dbcf 100644
--- a/dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts
+++ b/dolphinscheduler-ui-next/src/layouts/content/use-dataList.ts
@@ -122,7 +122,7 @@ export function useDataList() {
},
{
label: t('menu.resources'),
- key: 'resources',
+ key: 'resource',
icon: renderIcon(FolderOutlined),
isShowSide: true,
children: [
@@ -153,6 +153,7 @@ export function useDataList() {
key: 'datasource',
icon: renderIcon(DatabaseOutlined),
isShowSide: false,
+ children: [],
},
{
label: t('menu.monitor'),
diff --git a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
index be1fb01de6..a05a074408 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/en_US.ts
@@ -151,6 +151,44 @@ const monitor = {
},
}
+const resource = {
+ file: {
+ file_manage: 'File Manage',
+ create_folder: 'Create Folder',
+ create_file: 'Create File',
+ upload_files: 'Upload Files',
+ enter_keyword_tips: 'Please enter keyword',
+ id: '#',
+ name: 'Name',
+ user_name: 'Resource userName',
+ whether_directory: 'Whether directory',
+ file_name: 'File Name',
+ description: 'Description',
+ size: 'Size',
+ update_time: 'Update Time',
+ operation: 'Operation',
+ edit: 'Edit',
+ rename: 'Rename',
+ download: 'Download',
+ delete: 'Delete',
+ yes: 'Yes',
+ no: 'No',
+ folder_name: 'Folder Name',
+ enter_name_tips: 'Please enter name',
+ enter_description_tips: 'Please enter description',
+ enter_content_tips: 'Please enter the resource content',
+ file_format: 'File Format',
+ file_content: 'File Content',
+ delete_confirm: 'Delete?',
+ confirm: 'Confirm',
+ cancel: 'Cancel',
+ success: 'Success',
+ file_details: 'File Details',
+ return: 'Return',
+ save: 'Save',
+ }
+}
+
const project = {
list: {
create_project: 'Create Project',
@@ -185,5 +223,6 @@ export default {
password,
profile,
monitor,
+ resource,
project,
}
diff --git a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
index 41d83cca76..3372ccbdda 100644
--- a/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
+++ b/dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts
@@ -149,6 +149,45 @@ const monitor = {
},
}
+const resource = {
+ file: {
+ file_manage: '文件管理',
+ create_folder: '创建文件夹',
+ create_file: '创建文件',
+ upload_files: '上传文件',
+ enter_keyword_tips: '请输入关键词',
+ id: '编号',
+ name: '名称',
+ user_name: '所属用户',
+ whether_directory: '是否文件夹',
+ file_name: '文件名称',
+ description: '描述',
+ size: '大小',
+ update_time: '更新时间',
+ operation: '操作',
+ edit: '编辑',
+ rename: '重命名',
+ download: '下载',
+ delete: '删除',
+ yes: '是',
+ no: '否',
+ folder_name: '文件夹名称',
+ enter_name_tips: '请输入名称',
+ enter_description_tips: '请输入描述',
+ enter_content_tips: '请输入资源内容',
+ enter_suffix_tips: '请输入文件后缀',
+ file_format: '文件格式',
+ file_content: '文件内容',
+ delete_confirm: '确定删除吗?',
+ confirm: '确定',
+ cancel: '取消',
+ success: '成功',
+ file_details: '文件详情',
+ return: '返回',
+ save: '保存',
+ }
+}
+
const project = {
list: {
create_project: '创建项目',
@@ -183,5 +222,6 @@ export default {
password,
profile,
monitor,
+ resource,
project,
}
diff --git a/dolphinscheduler-ui-next/src/router/modules/resources.ts b/dolphinscheduler-ui-next/src/router/modules/resources.ts
index 6ea940a746..24fc461b75 100644
--- a/dolphinscheduler-ui-next/src/router/modules/resources.ts
+++ b/dolphinscheduler-ui-next/src/router/modules/resources.ts
@@ -32,7 +32,7 @@ export default {
{
path: '/resource/file',
name: 'file',
- component: components['home'],
+ component: components['file'],
meta: {
title: '文件管理',
},
@@ -40,9 +40,41 @@ export default {
{
path: '/resource/file/create',
name: 'resource-file-create',
- component: components['home'],
+ component: components['resource-file-create'],
meta: {
- title: '创建资源',
+ title: '文件创建',
+ },
+ },
+ {
+ path: '/resource/file/edit/:id',
+ name: 'resource-file-edit',
+ component: components['resource-file-edit'],
+ meta: {
+ title: '文件编辑',
+ },
+ },
+ {
+ path: '/resource/file/subdirectory/:id',
+ name: 'resource-file-subdirectory',
+ component: components['file'],
+ meta: {
+ title: '文件管理',
+ },
+ },
+ {
+ path: '/resource/file/list/:id',
+ name: 'resource-file-list',
+ component: components['resource-file-edit'],
+ meta: {
+ title: '文件详情',
+ },
+ },
+ {
+ path: '/resource/file/create/:id',
+ name: 'resource-subfile-create',
+ component: components['resource-file-create'],
+ meta: {
+ title: '文件创建',
},
},
],
diff --git a/dolphinscheduler-ui-next/src/service/modules/resources/index.ts b/dolphinscheduler-ui-next/src/service/modules/resources/index.ts
index 9fce316fdb..b1e1ce3910 100644
--- a/dolphinscheduler-ui-next/src/service/modules/resources/index.ts
+++ b/dolphinscheduler-ui-next/src/service/modules/resources/index.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { axios } from '@/service/service'
+import { axios, downloadFile } from '@/service/service'
import {
FileReq,
ResourceTypeReq,
@@ -37,7 +37,7 @@ import {
} from './types'
export function queryResourceListPaging(
- params: ListReq & IdReq & ResourceTypeReq
+ params: ListReq & IdReq & ResourceTypeReq,
): any {
return axios({
url: '/resources',
@@ -47,7 +47,7 @@ export function queryResourceListPaging(
}
export function createResource(
- data: CreateReq & FileNameReq & NameReq & ResourceTypeReq
+ data: CreateReq & FileNameReq & NameReq & ResourceTypeReq,
): any {
return axios({
url: '/resources',
@@ -81,7 +81,7 @@ export function authUDFFunc(params: UserIdReq): any {
}
export function createDirectory(
- data: CreateReq & NameReq & ResourceTypeReq
+ data: CreateReq & NameReq & ResourceTypeReq,
): any {
return axios({
url: '/resources/directory',
@@ -99,7 +99,7 @@ export function queryResourceList(params: ResourceTypeReq): any {
}
export function onlineCreateResource(
- data: OnlineCreateReq & FileNameReq & ResourceTypeReq
+ data: OnlineCreateReq & FileNameReq & ResourceTypeReq,
): any {
return axios({
url: '/resources/online-create',
@@ -109,7 +109,7 @@ export function onlineCreateResource(
}
export function queryResourceByProgramType(
- params: ResourceTypeReq & ProgramTypeReq
+ params: ResourceTypeReq & ProgramTypeReq,
): any {
return axios({
url: '/resources/query-by-type',
@@ -151,7 +151,7 @@ export function deleteUdfFunc(id: IdReq): any {
export function unAuthUDFFunc(params: UserIdReq): any {
return axios({
- url: `/resources/unauth-udf-func`,
+ url: '/resources/unauth-udf-func',
method: 'get',
params,
})
@@ -167,7 +167,7 @@ export function verifyResourceName(params: FullNameReq & ResourceTypeReq): any {
export function queryResource(
params: FullNameReq & ResourceTypeReq,
- id: IdReq
+ id: IdReq,
): any {
return axios({
url: `/resources/verify-name/${id}`,
@@ -177,8 +177,8 @@ export function queryResource(
}
export function updateResource(
- data: NameReq & ResourceTypeReq,
- id: IdReq
+ data: NameReq & ResourceTypeReq & IdReq & DescriptionReq,
+ id: number,
): any {
return axios({
url: `/resources/${id}`,
@@ -187,18 +187,15 @@ export function updateResource(
})
}
-export function deleteResource(id: IdReq): any {
+export function deleteResource(id: number): any {
return axios({
url: `/resources/${id}`,
method: 'delete',
})
}
-export function downloadResource(id: IdReq): any {
- return axios({
- url: `/resources/${id}/download`,
- method: 'get',
- })
+export function downloadResource(id: number): void {
+ downloadFile(`resources/${id}/download`)
}
export function viewUIUdfFunction(id: IdReq): any {
@@ -208,7 +205,7 @@ export function viewUIUdfFunction(id: IdReq): any {
})
}
-export function updateResourceContent(data: ContentReq, id: IdReq): any {
+export function updateResourceContent(data: ContentReq, id: number): any {
return axios({
url: `/resources/${id}/update-content`,
method: 'put',
@@ -216,7 +213,7 @@ export function updateResourceContent(data: ContentReq, id: IdReq): any {
})
}
-export function viewResource(params: ViewResourceReq, id: IdReq): any {
+export function viewResource(params: ViewResourceReq, id: number): any {
return axios({
url: `/resources/${id}/view`,
method: 'get',
@@ -226,7 +223,7 @@ export function viewResource(params: ViewResourceReq, id: IdReq): any {
export function createUdfFunc(
data: UdfFuncReq,
- resourceId: ResourceIdReq
+ resourceId: ResourceIdReq,
): any {
return axios({
url: `/resources/${resourceId}/udf-func`,
@@ -238,7 +235,7 @@ export function createUdfFunc(
export function updateUdfFunc(
data: UdfFuncReq,
resourceId: ResourceIdReq,
- id: IdReq
+ id: IdReq,
): any {
return axios({
url: `/resources/${resourceId}/udf-func/${id}`,
diff --git a/dolphinscheduler-ui-next/src/service/modules/resources/types.ts b/dolphinscheduler-ui-next/src/service/modules/resources/types.ts
index 79ec58bdf2..2102ba6516 100644
--- a/dolphinscheduler-ui-next/src/service/modules/resources/types.ts
+++ b/dolphinscheduler-ui-next/src/service/modules/resources/types.ts
@@ -90,6 +90,28 @@ interface UdfFuncReq extends UdfTypeReq, DescriptionReq {
database?: string
}
+interface ResourceFile {
+ id: number
+ pid: number
+ alias: string
+ userId: number
+ type: string
+ directory: boolean
+ fileName: string
+ fullName: string
+ description: string
+ size: number
+ updateTime: string
+}
+
+interface ResourceListRes {
+ currentPage: number
+ pageSize: number
+ start: number
+ total: number
+ totalList: ResourceFile[]
+}
+
export {
FileReq,
ResourceTypeReq,
@@ -108,4 +130,5 @@ export {
ViewResourceReq,
ResourceIdReq,
UdfFuncReq,
+ ResourceListRes,
}
diff --git a/dolphinscheduler-ui-next/src/service/service.ts b/dolphinscheduler-ui-next/src/service/service.ts
index 6c3bfc198d..d357d9df43 100644
--- a/dolphinscheduler-ui-next/src/service/service.ts
+++ b/dolphinscheduler-ui-next/src/service/service.ts
@@ -22,6 +22,7 @@ import axios, {
AxiosRequestHeaders,
} from 'axios'
import qs from 'qs'
+import _ from 'lodash'
import { useUserStore } from '@/store/user/user'
const userStore = useUserStore()
@@ -30,7 +31,12 @@ const baseRequestConfig: AxiosRequestConfig = {
baseURL: import.meta.env.VITE_APP_WEB_URL + '/dolphinscheduler',
timeout: 10000,
transformRequest: (params) => {
- return qs.stringify(params, { arrayFormat: 'repeat' })
+ if (_.isPlainObject(params)) {
+ console.log(params)
+ return qs.stringify(params, { arrayFormat: 'repeat' })
+ } else {
+ return params
+ }
},
paramsSerializer: (params) => {
return qs.stringify(params, { arrayFormat: 'repeat' })
@@ -66,4 +72,46 @@ service.interceptors.response.use((res: AxiosResponse) => {
}
}, err)
-export { service as axios }
+const apiPrefix = '/dolphinscheduler'
+const reSlashPrefix = /^\/+/
+
+const resolveURL = (url: string) => {
+ if (url.indexOf('http') === 0) {
+ return url
+ }
+ if (url.charAt(0) !== '/') {
+ return `${apiPrefix}/${url.replace(reSlashPrefix, '')}`
+ }
+
+ return url
+}
+
+/**
+ * download file
+ */
+const downloadFile = (url: string, obj?: any) => {
+ const param: any = {
+ url: resolveURL(url),
+ obj: obj || {},
+ }
+
+ const form = document.createElement('form')
+ form.action = param.url
+ form.method = 'get'
+ form.style.display = 'none'
+ Object.keys(param.obj).forEach((key) => {
+ const input = document.createElement('input')
+ input.type = 'hidden'
+ input.name = key
+ input.value = param.obj[key]
+ form.appendChild(input)
+ })
+ const button = document.createElement('input')
+ button.type = 'submit'
+ form.appendChild(button)
+ document.body.appendChild(form)
+ form.submit()
+ document.body.removeChild(form)
+}
+
+export { service as axios, downloadFile }
diff --git a/dolphinscheduler-ui-next/src/store/file/file.ts b/dolphinscheduler-ui-next/src/store/file/file.ts
new file mode 100644
index 0000000000..96fb868b3d
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/store/file/file.ts
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineStore } from 'pinia'
+import type { FileState } from '@/store/file/types'
+
+export const useFileStore = defineStore({
+ id: 'file',
+ state: (): FileState => ({
+ file: '',
+ currentDir: '/',
+ }),
+ persist: true,
+ getters: {
+ getFileInfo(): string {
+ return this.file
+ },
+ getCurrentDir(): string {
+ return this.currentDir
+ },
+ },
+ actions: {
+ setFileInfo(file: string): void {
+ this.file = file
+ },
+ setCurrentDir(currentDir: string): void {
+ this.currentDir = currentDir
+ },
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/store/file/types.ts b/dolphinscheduler-ui-next/src/store/file/types.ts
new file mode 100644
index 0000000000..57ef1220c5
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/store/file/types.ts
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+interface FileState {
+ file: string
+ currentDir: string
+}
+
+export { FileState }
diff --git a/dolphinscheduler-ui-next/src/store/menu/menu.ts b/dolphinscheduler-ui-next/src/store/menu/menu.ts
index b86cdc7057..b4c5c09aec 100644
--- a/dolphinscheduler-ui-next/src/store/menu/menu.ts
+++ b/dolphinscheduler-ui-next/src/store/menu/menu.ts
@@ -26,7 +26,7 @@ export const useMenuStore = defineStore({
persist: true,
getters: {
getMenuKey(): string {
- return this.menuKey
+ return this.menuKey || 'home'
},
},
actions: {
diff --git a/dolphinscheduler-ui-next/src/utils/common.ts b/dolphinscheduler-ui-next/src/utils/common.ts
new file mode 100644
index 0000000000..15e7ca0b8e
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/utils/common.ts
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Intelligent display kb m
+ */
+export const bytesToSize = (bytes: number) => {
+ if (bytes === 0) return '0 B'
+ const k = 1024 // or 1024
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+ const i = Math.floor(Math.log(bytes) / Math.log(k))
+
+ return parseInt((bytes / Math.pow(k, i)).toPrecision(3)) + ' ' + sizes[i]
+}
+
+export const fileTypeArr = [
+ 'txt',
+ 'log',
+ 'sh',
+ 'bat',
+ 'conf',
+ 'cfg',
+ 'py',
+ 'java',
+ 'sql',
+ 'xml',
+ 'hql',
+ 'properties',
+ 'json',
+ 'yml',
+ 'yaml',
+ 'ini',
+ 'js',
+]
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/create/resource-file-create.tsx b/dolphinscheduler-ui-next/src/views/resource/file/create/resource-file-create.tsx
new file mode 100644
index 0000000000..ccebfdc614
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/create/resource-file-create.tsx
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineComponent, ref, toRefs } from 'vue'
+import { useRouter } from 'vue-router'
+import { NForm, NFormItem, NInput, NSelect, NButton } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+
+import Card from '@/components/card'
+import MonacoEditor from '@/components/monaco-editor'
+import { useCreate } from './use-create'
+import { useForm } from './use-form'
+import { fileTypeArr } from '@/utils/common'
+
+import styles from '../index.module.scss'
+
+import type { Router } from 'vue-router'
+
+export default defineComponent({
+ name: 'ResourceFileCreate',
+ setup() {
+ const router: Router = useRouter()
+
+ const codeEditorRef = ref()
+ const { state } = useForm()
+ const { handleCreateFile } = useCreate(state)
+
+ const fileSuffixOptions = fileTypeArr.map((suffix) => ({
+ key: suffix,
+ label: suffix,
+ value: suffix,
+ }))
+
+ const handleFile = () => {
+ state.fileForm.content = codeEditorRef.value?.getValue()
+ handleCreateFile()
+ }
+
+ const handleReturn = () => {
+ const { id } = router.currentRoute.value.params
+ const name = id ? 'resource-file-subdirectory' : 'file'
+ router.push({ name, params: { id } })
+ }
+
+ return {
+ codeEditorRef,
+ fileSuffixOptions,
+ handleFile,
+ handleReturn,
+ ...toRefs(state),
+ }
+ },
+ render() {
+ const { t } = useI18n()
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/create/use-create.ts b/dolphinscheduler-ui-next/src/views/resource/file/create/use-create.ts
new file mode 100644
index 0000000000..dc03a3d362
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/create/use-create.ts
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useI18n } from 'vue-i18n'
+import { useRouter } from 'vue-router'
+import type { Router } from 'vue-router'
+import { useFileStore } from '@/store/file/file'
+import { onlineCreateResource } from '@/service/modules/resources'
+
+export function useCreate(state: any) {
+ const { t } = useI18n()
+ const router: Router = useRouter()
+ const fileStore = useFileStore()
+
+ const handleCreateFile = () => {
+ const pid = router.currentRoute.value.params.id || -1
+ const currentDir = fileStore.getCurrentDir || '/'
+ state.fileFormRef.validate(async (valid: any) => {
+ if (!valid) {
+ try {
+ await onlineCreateResource({
+ ...state.fileForm,
+ ...{ pid, currentDir },
+ })
+
+ window.$message.success(t('resource.file.success'))
+ const name = pid ? 'resource-file-subdirectory' : 'file'
+ router.push({ name, params: { id: pid } })
+ } catch (error: any) {
+ window.$message.error(error.message)
+ }
+ }
+ })
+ }
+
+ return {
+ handleCreateFile,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/create/use-form.ts b/dolphinscheduler-ui-next/src/views/resource/file/create/use-form.ts
new file mode 100644
index 0000000000..b0e7573d79
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/create/use-form.ts
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useI18n } from 'vue-i18n'
+import { reactive, ref, unref } from 'vue'
+import type { FormRules } from 'naive-ui'
+
+const defaultValue = () => ({
+ pid: -1,
+ type: 'FILE',
+ suffix: 'sh',
+ fileName: '',
+ description: '',
+ content: '',
+ currentDir: '/',
+})
+
+export function useForm() {
+ const { t } = useI18n()
+
+ const resetForm = () => {
+ state.fileForm = Object.assign(unref(state.fileForm), defaultValue())
+ }
+
+ const state = reactive({
+ fileFormRef: ref(),
+ fileForm: defaultValue(),
+ rules: {
+ fileName: {
+ required: true,
+ trigger: ['input', 'blur'],
+ validator() {
+ if (state.fileForm.fileName === '') {
+ return new Error(t('resource.file.enter_name_tips'))
+ }
+ },
+ },
+ suffix: {
+ required: true,
+ trigger: ['input', 'blur'],
+ validator() {
+ if (state.fileForm.suffix === '') {
+ return new Error(t('resource.file.enter_suffix_tips'))
+ }
+ },
+ },
+ content: {
+ required: true,
+ trigger: ['input', 'blur'],
+ validator() {
+ if (state.fileForm.content === '') {
+ return new Error(t('resource.file.enter_content_tips'))
+ }
+ },
+ },
+ } as FormRules,
+ })
+
+ return {
+ state,
+ resetForm,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/edit/resource-file-edit.tsx b/dolphinscheduler-ui-next/src/views/resource/file/edit/resource-file-edit.tsx
new file mode 100644
index 0000000000..2cadb9302e
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/edit/resource-file-edit.tsx
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useRouter } from 'vue-router'
+import { defineComponent, onMounted, ref, toRefs } from 'vue'
+import { NButton, NForm, NFormItem, NSpace } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import Card from '@/components/card'
+import MonacoEditor from '@/components/monaco-editor'
+import { useForm } from './use-form'
+import { useEdit } from './use-edit'
+
+import styles from '../index.module.scss'
+import type { Router } from 'vue-router'
+
+export default defineComponent({
+ name: 'ResourceFileEdit',
+ setup() {
+ const router: Router = useRouter()
+
+ const resourceViewRef = ref()
+ const codeEditorRef = ref()
+ const routeNameRef = ref(router.currentRoute.value.name)
+ const idRef = ref(Number(router.currentRoute.value.params.id))
+
+ const { state } = useForm()
+ const { getResourceView, handleUpdateContent } = useEdit(state)
+
+ const handleFileContent = () => {
+ state.fileForm.content = codeEditorRef.value?.getValue()
+ handleUpdateContent(idRef.value)
+ }
+
+ const handleReturn = () => {
+ router.go(-1)
+ }
+
+ onMounted(() => {
+ resourceViewRef.value = getResourceView(idRef.value)
+ })
+
+ return {
+ idRef,
+ routeNameRef,
+ codeEditorRef,
+ resourceViewRef,
+ handleReturn,
+ handleFileContent,
+ ...toRefs(state),
+ }
+ },
+ render() {
+ const { t } = useI18n()
+ return (
+
+
+
+ )
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/edit/use-edit.ts b/dolphinscheduler-ui-next/src/views/resource/file/edit/use-edit.ts
new file mode 100644
index 0000000000..f4cea46dad
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/edit/use-edit.ts
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useI18n } from 'vue-i18n'
+import { useRouter } from 'vue-router'
+import type { Router } from 'vue-router'
+import { useAsyncState } from '@vueuse/core'
+import {
+ viewResource,
+ updateResourceContent,
+} from '@/service/modules/resources'
+
+export function useEdit(state: any) {
+ const { t } = useI18n()
+ const router: Router = useRouter()
+
+ const getResourceView = (id: number) => {
+ const params = {
+ skipLineNum: 0,
+ limit: 3000,
+ }
+ const { state } = useAsyncState(viewResource(params, id), {})
+ return state
+ }
+
+ const handleUpdateContent = (id: number) => {
+ state.fileFormRef.validate(async (valid: any) => {
+ if (!valid) {
+ try {
+ await updateResourceContent(
+ {
+ ...state.fileForm,
+ },
+ id,
+ )
+
+ window.$message.success(t('resource.file.success'))
+ router.go(-1)
+ } catch (error: any) {
+ window.$message.error(error.message)
+ }
+ }
+ })
+ }
+
+ return {
+ getResourceView,
+ handleUpdateContent,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/edit/use-form.ts b/dolphinscheduler-ui-next/src/views/resource/file/edit/use-form.ts
new file mode 100644
index 0000000000..68dbf653dd
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/edit/use-form.ts
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { reactive, ref, unref } from 'vue'
+import { useI18n } from 'vue-i18n'
+import type { FormRules } from 'naive-ui'
+
+const defaultValue = () => ({
+ content: '',
+})
+
+export function useForm() {
+ const { t } = useI18n()
+
+ const resetForm = () => {
+ state.fileForm = Object.assign(unref(state.fileForm), defaultValue())
+ }
+
+ const state = reactive({
+ fileFormRef: ref(),
+ fileForm: defaultValue(),
+ rules: {
+ content: {
+ required: true,
+ trigger: ['input', 'blur'],
+ validator() {
+ if (state.fileForm.content === '') {
+ return new Error(t('resource.file.enter_content_tips'))
+ }
+ },
+ },
+ } as FormRules,
+ })
+
+ return {
+ state,
+ resetForm,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/folder/index.tsx b/dolphinscheduler-ui-next/src/views/resource/file/folder/index.tsx
new file mode 100644
index 0000000000..bc2618a0be
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/folder/index.tsx
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineComponent, toRefs, PropType } from 'vue'
+import { NForm, NFormItem, NInput } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import Modal from '@/components/modal'
+import { useForm } from './use-form'
+import { useFolder } from './use-folder'
+
+const props = {
+ show: {
+ type: Boolean as PropType,
+ default: false,
+ },
+}
+
+export default defineComponent({
+ name: 'ResourceFileFolder',
+ props,
+ emits: ['updateList', 'update:show'],
+ setup(props, ctx) {
+ const { state, resetForm } = useForm()
+ const { handleCreateFolder } = useFolder(state)
+
+ const hideModal = () => {
+ ctx.emit('update:show')
+ }
+
+ const handleFolder = () => {
+ handleCreateFolder(ctx.emit, hideModal, resetForm)
+ }
+
+ return {
+ hideModal,
+ handleFolder,
+ ...toRefs(state),
+ }
+ },
+ render() {
+ const { t } = useI18n()
+ return (
+
+
+
+
+
+
+
+
+
+
+ )
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/folder/use-folder.ts b/dolphinscheduler-ui-next/src/views/resource/file/folder/use-folder.ts
new file mode 100644
index 0000000000..0b4599c049
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/folder/use-folder.ts
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useI18n } from 'vue-i18n'
+import { IEmit } from '../types'
+import { useRouter } from 'vue-router'
+import type { Router } from 'vue-router'
+import { useFileStore } from '@/store/file/file'
+import { createDirectory } from '@/service/modules/resources'
+
+export function useFolder(state: any) {
+ const { t } = useI18n()
+ const router: Router = useRouter()
+ const fileStore = useFileStore()
+
+ const handleCreateFolder = (
+ emit: IEmit,
+ hideModal: () => void,
+ resetForm: () => void,
+ ) => {
+ const pid = router.currentRoute.value.params.id || -1
+ const currentDir = fileStore.getCurrentDir || '/'
+ state.folderFormRef.validate(async (valid: any) => {
+ if (!valid) {
+ try {
+ await createDirectory({
+ ...state.folderForm,
+ ...{ pid, currentDir },
+ })
+
+ window.$message.success(t('resource.file.success'))
+ emit('updateList')
+ } catch (error: any) {
+ window.$message.error(error.message)
+ }
+ hideModal()
+ resetForm()
+ }
+ })
+ }
+
+ return {
+ handleCreateFolder,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/folder/use-form.ts b/dolphinscheduler-ui-next/src/views/resource/file/folder/use-form.ts
new file mode 100644
index 0000000000..be8e279a50
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/folder/use-form.ts
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { reactive, ref, unref } from 'vue'
+import { useI18n } from 'vue-i18n'
+import type { FormRules } from 'naive-ui'
+
+const defaultValue = () => ({
+ pid: -1,
+ type: 'FILE',
+ name: '',
+ description: '',
+ currentDir: '/',
+})
+
+export function useForm() {
+ const { t } = useI18n()
+
+ const resetForm = () => {
+ state.folderForm = Object.assign(unref(state.folderForm), defaultValue())
+ }
+
+ const state = reactive({
+ folderFormRef: ref(),
+ folderForm: defaultValue(),
+ rules: {
+ name: {
+ required: true,
+ trigger: ['input', 'blur'],
+ validator() {
+ if (state.folderForm.name === '') {
+ return new Error(t('resource.file.enter_name_tips'))
+ }
+ },
+ },
+ } as FormRules,
+ })
+
+ return {
+ state,
+ resetForm,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/index.module.scss b/dolphinscheduler-ui-next/src/views/resource/file/index.module.scss
new file mode 100644
index 0000000000..a6c089e897
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/index.module.scss
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.file-edit-content {
+ width: 100%;
+ background: #fff;
+ padding-bottom: 20px;
+ >h2 {
+ line-height: 60px;
+ text-align: center;
+ padding-right: 170px;
+ position: relative;
+ }
+}
+
+.form-content {
+ padding: 0 50px 0 50px;
+}
+
+.submit {
+ text-align: left;
+ padding-top: 12px;
+ margin-left: 160px;
+}
+
+.pagination {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-top: 20px;
+}
+
+.table-box {
+ table {
+ width: 100%;
+ tr {
+ height: 40px;
+ font-size: 12px;
+ th,td{
+ &:nth-child(1) {
+ width: 50px;
+ text-align: center;
+ }
+ }
+ th {
+ &:nth-child(1) {
+ width: 60px;
+ text-align: center;
+ }
+ >span {
+ font-size: 12px;
+ color: #555;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/index.tsx b/dolphinscheduler-ui-next/src/views/resource/file/index.tsx
new file mode 100644
index 0000000000..f61aac2184
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/index.tsx
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useRouter } from 'vue-router'
+import {
+ defineComponent,
+ onMounted,
+ ref,
+ reactive,
+ Ref,
+ watch,
+ inject,
+} from 'vue'
+import { NDataTable, NButtonGroup, NButton, NPagination } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import Card from '@/components/card'
+import Conditions from '@/components/conditions'
+import { useTable } from './table/use-table'
+import { useFileState } from './use-file'
+import ResourceFolderModal from './folder'
+import ResourceUploadModal from './upload'
+import ResourceRenameModal from './rename'
+import { IRenameFile } from './types'
+import type { Router } from 'vue-router'
+import styles from './index.module.scss'
+
+export default defineComponent({
+ name: 'File',
+ inject: ['reload'],
+ setup() {
+ const router: Router = useRouter()
+ const fileId = ref(Number(router.currentRoute.value.params.id) || -1)
+
+ const reload = inject('reload')
+ const resourceListRef = ref()
+ const folderShowRef = ref(false)
+ const uploadShowRef = ref(false)
+ const renameShowRef = ref(false)
+ const serachRef = ref()
+
+ const renameInfo = reactive({
+ id: -1,
+ name: '',
+ description: '',
+ })
+
+ const paginationReactive = reactive({
+ page: 1,
+ pageSize: 10,
+ itemCount: 0,
+ pageSizes: [10, 30, 50],
+ })
+
+ const handleUpdatePage = (page: number) => {
+ paginationReactive.page = page
+ resourceListRef.value = getResourceListState(
+ fileId.value,
+ serachRef.value,
+ paginationReactive.page,
+ paginationReactive.pageSize,
+ )
+ }
+
+ const handleUpdatePageSize = (pageSize: number) => {
+ paginationReactive.page = 1
+ paginationReactive.pageSize = pageSize
+ resourceListRef.value = getResourceListState(
+ fileId.value,
+ serachRef.value,
+ paginationReactive.page,
+ paginationReactive.pageSize,
+ )
+ }
+
+ const handleShowModal = (showRef: Ref) => {
+ showRef.value = true
+ }
+
+ const setPagination = (count: number) => {
+ paginationReactive.itemCount = count
+ }
+
+ const { getResourceListState } = useFileState(setPagination)
+
+ const handleConditions = (val: string) => {
+ serachRef.value = val
+ resourceListRef.value = getResourceListState(fileId.value, val)
+ }
+
+ const handleCreateFolder = () => {
+ handleShowModal(folderShowRef)
+ }
+
+ const handleCreateFile = () => {
+ const name = fileId.value
+ ? 'resource-subfile-create'
+ : 'resource-file-create'
+ router.push({
+ name,
+ params: { id: fileId.value },
+ })
+ }
+
+ const handleUploadFile = () => {
+ handleShowModal(uploadShowRef)
+ }
+
+ const handleRenameFile: IRenameFile = (id, name, description) => {
+ renameInfo.id = id
+ renameInfo.name = name
+ renameInfo.description = description
+ handleShowModal(renameShowRef)
+ }
+
+ const updateList = () => {
+ resourceListRef.value = getResourceListState(
+ fileId.value,
+ serachRef.value,
+ )
+ }
+
+ onMounted(() => {
+ resourceListRef.value = getResourceListState(fileId.value)
+ })
+
+ watch(
+ () => router.currentRoute.value.params.id,
+ () => reload(),
+ )
+
+ return {
+ fileId,
+ folderShowRef,
+ uploadShowRef,
+ renameShowRef,
+ handleShowModal,
+ resourceListRef,
+ updateList,
+ handleConditions,
+ handleCreateFolder,
+ handleCreateFile,
+ handleUploadFile,
+ handleRenameFile,
+ handleUpdatePage,
+ handleUpdatePageSize,
+ pagination: paginationReactive,
+ renameInfo,
+ }
+ },
+ render() {
+ const { t } = useI18n()
+ const { columnsRef } = useTable(this.handleRenameFile, this.updateList)
+ const {
+ handleConditions,
+ handleCreateFolder,
+ handleCreateFile,
+ handleUploadFile,
+ } = this
+ return (
+
+ )
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/rename/index.tsx b/dolphinscheduler-ui-next/src/views/resource/file/rename/index.tsx
new file mode 100644
index 0000000000..aaf04433cb
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/rename/index.tsx
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { defineComponent, toRefs, PropType, watch } from 'vue'
+import { NForm, NFormItem, NInput } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import Modal from '@/components/modal'
+import { useForm } from './use-form'
+import { useRename } from './use-rename'
+
+const props = {
+ show: {
+ type: Boolean as PropType,
+ default: false,
+ },
+ id: {
+ type: Number as PropType,
+ default: -1,
+ },
+ name: {
+ type: String as PropType,
+ default: '',
+ },
+ description: {
+ type: String as PropType,
+ default: '',
+ },
+}
+
+export default defineComponent({
+ name: 'ResourceFileRename',
+ props,
+ emits: ['updateList', 'update:show'],
+ setup(props, ctx) {
+ const { state, resetForm } = useForm(props.name, props.description)
+ const { handleRenameFile } = useRename(state)
+
+ const hideModal = () => {
+ ctx.emit('update:show', false)
+ }
+
+ const handleFile = () => {
+ handleRenameFile(ctx.emit, hideModal, resetForm)
+ }
+
+ watch(
+ () => props.name,
+ () => {
+ state.renameForm.id = props.id
+ state.renameForm.name = props.name
+ state.renameForm.description = props.description
+ },
+ )
+
+ return { hideModal, handleFile, ...toRefs(state) }
+ },
+ render() {
+ const { t } = useI18n()
+ return (
+
+
+
+
+
+
+
+
+
+
+ )
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/rename/use-form.ts b/dolphinscheduler-ui-next/src/views/resource/file/rename/use-form.ts
new file mode 100644
index 0000000000..0ff73809e6
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/rename/use-form.ts
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { reactive, ref, unref } from 'vue'
+import { useI18n } from 'vue-i18n'
+import type { FormRules } from 'naive-ui'
+
+const defaultValue = (name = '', description = '') => ({
+ id: -1,
+ name,
+ type: 'FILE',
+ description,
+})
+
+export function useForm(name: string, description: string) {
+ const { t } = useI18n()
+
+ const resetForm = () => {
+ state.renameForm = Object.assign(unref(state.renameForm), defaultValue())
+ }
+
+ const state = reactive({
+ renameFormRef: ref(),
+ renameForm: defaultValue(name, description),
+ rules: {
+ name: {
+ required: true,
+ trigger: ['input', 'blur'],
+ validator() {
+ if (state.renameForm.name === '') {
+ return new Error(t('resource.file.enter_name_tips'))
+ }
+ },
+ },
+ } as FormRules,
+ })
+
+ return {
+ state,
+ resetForm,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/rename/use-rename.ts b/dolphinscheduler-ui-next/src/views/resource/file/rename/use-rename.ts
new file mode 100644
index 0000000000..7006178f3e
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/rename/use-rename.ts
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useI18n } from 'vue-i18n'
+import { IEmit } from '../types'
+import { updateResource } from '@/service/modules/resources'
+
+export function useRename(state: any) {
+ const { t } = useI18n()
+
+ const handleRenameFile = (
+ emit: IEmit,
+ hideModal: () => void,
+ resetForm: () => void,
+ ) => {
+ state.renameFormRef.validate(async (valid: any) => {
+ if (!valid) {
+ try {
+ await updateResource(
+ {
+ ...state.renameForm,
+ },
+ state.renameForm.id,
+ )
+ window.$message.success(t('resource.file.success'))
+ emit('updateList')
+ } catch (error: any) {
+ window.$message.error(error.message)
+ }
+ }
+
+ hideModal()
+ resetForm()
+ })
+ }
+
+ return {
+ handleRenameFile,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/table/index.module.scss b/dolphinscheduler-ui-next/src/views/resource/file/table/index.module.scss
new file mode 100644
index 0000000000..4ec0732516
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/table/index.module.scss
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+.links {
+ color: #2080f0;
+ text-decoration: none;
+ &:hover {
+ text-decoration: underline;
+ }
+}
\ No newline at end of file
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/table/table-action.tsx b/dolphinscheduler-ui-next/src/views/resource/file/table/table-action.tsx
new file mode 100644
index 0000000000..164c35b532
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/table/table-action.tsx
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useRouter } from 'vue-router'
+import { defineComponent, PropType } from 'vue'
+import { NSpace, NTooltip, NButton, NIcon, NPopconfirm } from 'naive-ui'
+import {
+ DeleteOutlined,
+ DownloadOutlined,
+ FormOutlined,
+ EditOutlined,
+ InfoCircleFilled,
+} from '@vicons/antd'
+import _ from 'lodash'
+import { useI18n } from 'vue-i18n'
+import { ResourceFileTableData } from '../types'
+import { fileTypeArr } from '@/utils/common'
+import { downloadResource, deleteResource } from '@/service/modules/resources'
+import { IRenameFile, IRtDisb } from '../types'
+import type { Router } from 'vue-router'
+
+const props = {
+ show: {
+ type: Boolean as PropType,
+ default: false,
+ },
+ row: {
+ type: Object as PropType,
+ default: {
+ id: -1,
+ name: '',
+ description: '',
+ },
+ },
+}
+
+export default defineComponent({
+ name: 'TableAction',
+ props,
+ emits: ['updateList', 'renameResource'],
+ setup(props, { emit }) {
+ const { t } = useI18n()
+ const router: Router = useRouter()
+
+ const rtDisb: IRtDisb = (name, size) => {
+ const i = name.lastIndexOf('.')
+ const a = name.substring(i, name.length)
+ const flag = _.includes(fileTypeArr, _.trimStart(a, '.'))
+ return !(flag && size < 1000000)
+ }
+
+ const handleEditFile = (item: { id: number }) => {
+ router.push({ name: 'resource-file-edit', params: { id: item.id } })
+ }
+
+ const handleDeleteFile = (id: number) => {
+ deleteResource(id).then(() => emit('updateList'))
+ }
+
+ const handleRenameFile: IRenameFile = (id, name, description) => {
+ emit('renameResource', id, name, description)
+ }
+
+ return {
+ t,
+ rtDisb,
+ handleEditFile,
+ handleDeleteFile,
+ handleRenameFile,
+ ...props,
+ }
+ },
+ render() {
+ const { t } = useI18n()
+ return (
+
+
+ {{
+ default: () => t('resource.file.edit'),
+ trigger: () => (
+ {
+ this.handleEditFile(this.row)
+ }}
+ style={{ marginRight: '-5px' }}
+ circle
+ >
+
+
+
+
+ ),
+ }}
+
+
+ {{
+ default: () => t('resource.file.rename'),
+ trigger: () => (
+
+ this.handleRenameFile(
+ this.row.id,
+ this.row.name,
+ this.row.description,
+ )
+ }
+ style={{ marginRight: '-5px' }}
+ circle
+ >
+
+
+
+
+ ),
+ }}
+
+
+ {{
+ default: () => t('resource.file.download'),
+ trigger: () => (
+ downloadResource(this.row.id)}
+ >
+
+
+
+
+ ),
+ }}
+
+
+ {{
+ default: () => t('resource.file.delete'),
+ trigger: () => (
+
+ {
+ this.handleDeleteFile(this.row.id)
+ }}
+ >
+ {{
+ default: () => t('resource.file.delete_confirm'),
+ icon: () => (
+
+
+
+ ),
+ trigger: () => (
+
+
+
+ ),
+ }}
+
+
+ ),
+ }}
+
+
+ )
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/table/use-table.ts b/dolphinscheduler-ui-next/src/views/resource/file/table/use-table.ts
new file mode 100644
index 0000000000..4df55f3348
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/table/use-table.ts
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { h } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { useRouter } from 'vue-router'
+import { bytesToSize } from '@/utils/common'
+import { useFileStore } from '@/store/file/file'
+import TableAction from './table-action'
+import { IRenameFile } from '../types'
+import type { Router } from 'vue-router'
+import type { TableColumns } from 'naive-ui/es/data-table/src/interface'
+import styles from './index.module.scss'
+
+const goSubFolder = (router: Router, item: any) => {
+ const fileStore = useFileStore()
+ fileStore.setFileInfo(`${item.alias}|${item.size}`)
+
+ if (item.directory) {
+ fileStore.setCurrentDir(`${item.fullName}`)
+ router.push({ name: 'resource-file-subdirectory', params: { id: item.id } })
+ } else {
+ router.push({ name: 'resource-file-list', params: { id: item.id } })
+ }
+}
+
+export function useTable(renameResource: IRenameFile, updateList: () => void) {
+ const { t } = useI18n()
+ const router: Router = useRouter()
+
+ const columnsRef: TableColumns = [
+ {
+ title: t('resource.file.id'),
+ key: 'id',
+ width: 50,
+ render: (_row, index) => index + 1,
+ },
+ {
+ title: t('resource.file.name'),
+ key: 'name',
+ width: 120,
+ render: (row) =>
+ h(
+ 'a',
+ {
+ href: 'javascript:',
+ class: styles.links,
+ onClick: () => goSubFolder(router, row),
+ },
+ {
+ default: () => {
+ return row.name
+ },
+ },
+ ),
+ },
+ { title: t('resource.file.user_name'), width: 100, key: 'user_name' },
+ {
+ title: t('resource.file.whether_directory'),
+ key: 'whether_directory',
+ width: 100,
+ render: (row) =>
+ row.directory ? t('resource.file.yes') : t('resource.file.no'),
+ },
+ { title: t('resource.file.file_name'), key: 'file_name' },
+ { title: t('resource.file.description'), width: 150, key: 'description' },
+ {
+ title: t('resource.file.size'),
+ key: 'size',
+ render: (row) => bytesToSize(row.size),
+ },
+ { title: t('resource.file.update_time'), width: 150, key: 'update_time' },
+ {
+ title: t('resource.file.operation'),
+ key: 'operation',
+ width: 150,
+ render: (row) =>
+ h(TableAction, {
+ row,
+ onRenameResource: (id, name, description) =>
+ renameResource(id, name, description),
+ onUpdateList: () => updateList(),
+ }),
+ },
+ ]
+
+ return {
+ columnsRef,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/types.ts b/dolphinscheduler-ui-next/src/views/resource/file/types.ts
new file mode 100644
index 0000000000..8bd5e52a14
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/types.ts
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export interface ResourceFileTableData {
+ id: number
+ name: string
+ user_name: string
+ directory: string
+ file_name: string
+ description: string
+ size: number
+ update_time: string
+}
+
+export interface IEmit {
+ (event: any, ...args: any[]): void
+}
+
+export interface IRenameFile {
+ (id: number, name: string, description: string): void
+}
+export interface IRtDisb {
+ (name: string, size: number): boolean
+}
+
+export interface IResourceListState {
+ (id?: number, searchVal?: string, pageNo?: number, pageSize?: number): any
+}
+
+export interface BasicTableProps {
+ title?: string
+ dataSource: Function
+ columns: any[]
+ pagination: object
+ showPagination: boolean
+ actionColumn: any[]
+ canResize: boolean
+ resizeHeightOffset: number
+}
+
+export interface PaginationProps {
+ page?: number
+ pageCount?: number
+ pageSize?: number
+ pageSizes?: number[]
+ showSizePicker?: boolean
+ showQuickJumper?: boolean
+}
+
+export interface ISetPagination {
+ (itemCount: number): void
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/upload/index.tsx b/dolphinscheduler-ui-next/src/views/resource/file/upload/index.tsx
new file mode 100644
index 0000000000..b7f69eb588
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/upload/index.tsx
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { defineComponent, toRefs, PropType } from 'vue'
+import { NButton, NForm, NFormItem, NInput, NUpload } from 'naive-ui'
+
+import { useI18n } from 'vue-i18n'
+import Modal from '@/components/modal'
+import { useForm } from './use-form'
+import { useUpload } from './use-upload'
+
+const props = {
+ show: {
+ type: Boolean as PropType,
+ default: false,
+ },
+}
+
+export default defineComponent({
+ name: 'ResourceFileUpload',
+ props,
+ emits: ['updateList', 'update:show'],
+ setup(props, ctx) {
+ const { state, resetForm } = useForm()
+ const { handleUploadFile } = useUpload(state)
+
+ const hideModal = () => {
+ ctx.emit('update:show')
+ }
+
+ const customRequest = ({ file }: any) => {
+ state.uploadForm.name = file.name
+ state.uploadForm.file = file.file
+ }
+
+ const handleFile = () => {
+ handleUploadFile(ctx.emit, hideModal, resetForm)
+ }
+
+ return {
+ hideModal,
+ customRequest,
+ handleFile,
+ ...toRefs(state),
+ }
+ },
+ render() {
+ const { t } = useI18n()
+ return (
+
+
+
+
+
+
+
+
+
+
+ {t('resource.file.upload_files')}
+
+
+
+
+ )
+ },
+})
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/upload/use-form.ts b/dolphinscheduler-ui-next/src/views/resource/file/upload/use-form.ts
new file mode 100644
index 0000000000..08de62d72e
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/upload/use-form.ts
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { reactive, ref, unref } from 'vue'
+import { useI18n } from 'vue-i18n'
+import type { FormRules } from 'naive-ui'
+
+const defaultValue = () => ({
+ name: '',
+ file: '',
+ description: '',
+ pid: -1,
+ currentDir: '/',
+})
+
+export function useForm() {
+ const { t } = useI18n()
+
+ const resetForm = () => {
+ state.uploadForm = Object.assign(unref(state.uploadForm), defaultValue())
+ }
+
+ const state = reactive({
+ uploadFormRef: ref(),
+ uploadForm: defaultValue(),
+ rules: {
+ name: {
+ required: true,
+ trigger: ['input', 'blur'],
+ validator() {
+ if (state.uploadForm.name === '') {
+ return new Error(t('resource.file.enter_name_tips'))
+ }
+ },
+ },
+ file: {
+ required: true,
+ trigger: ['input', 'blur'],
+ validator() {
+ if (state.uploadForm.file === '') {
+ return new Error(t('resource.file.enter_content_tips'))
+ }
+ },
+ },
+ } as FormRules,
+ })
+
+ return {
+ state,
+ resetForm,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/upload/use-upload.ts b/dolphinscheduler-ui-next/src/views/resource/file/upload/use-upload.ts
new file mode 100644
index 0000000000..a5d7aab13a
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/upload/use-upload.ts
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useI18n } from 'vue-i18n'
+import { IEmit } from '../types'
+import { useRouter } from 'vue-router'
+import type { Router } from 'vue-router'
+import { useFileStore } from '@/store/file/file'
+import { createResource } from '@/service/modules/resources'
+
+export function useUpload(state: any) {
+ const { t } = useI18n()
+ const router: Router = useRouter()
+ const fileStore = useFileStore()
+
+ const handleUploadFile = (
+ emit: IEmit,
+ hideModal: () => void,
+ resetForm: () => void,
+ ) => {
+ state.uploadFormRef.validate(async (valid: any) => {
+ const pid = router.currentRoute.value.params.id || -1
+ const currentDir = fileStore.getCurrentDir || '/'
+ if (!valid) {
+ const formData = new FormData()
+ formData.append('file', state.uploadForm.file)
+ formData.append('type', 'FILE')
+ formData.append('name', state.uploadForm.name)
+ formData.append('pid', String(pid))
+ formData.append('currentDir', currentDir)
+ formData.append('description', state.uploadForm.description)
+
+ try {
+ await createResource(formData as any)
+ window.$message.success(t('resource.file.success'))
+ emit('updateList')
+ } catch (error: any) {
+ window.$message.error(error.message)
+ }
+
+ hideModal()
+ resetForm()
+ }
+ })
+ }
+
+ return {
+ handleUploadFile,
+ }
+}
diff --git a/dolphinscheduler-ui-next/src/views/resource/file/use-file.ts b/dolphinscheduler-ui-next/src/views/resource/file/use-file.ts
new file mode 100644
index 0000000000..3e7c7a0209
--- /dev/null
+++ b/dolphinscheduler-ui-next/src/views/resource/file/use-file.ts
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useAsyncState } from '@vueuse/core'
+import {
+ queryResourceListPaging,
+ viewResource,
+} from '@/service/modules/resources'
+import type { ResourceListRes } from '@/service/modules/resources/types'
+import { IResourceListState, ISetPagination } from './types'
+
+export function useFileState(
+ setPagination: ISetPagination = {} as ISetPagination,
+) {
+ const getResourceListState: IResourceListState = (
+ id = -1,
+ searchVal = '',
+ pageNo = 1,
+ pageSize = 10,
+ ) => {
+ const { state } = useAsyncState(
+ queryResourceListPaging({
+ id,
+ type: 'FILE',
+ searchVal,
+ pageNo,
+ pageSize,
+ }).then((res: ResourceListRes): any => {
+ const { total } = res
+ setPagination(total)
+ const table = res.totalList.map((item) => {
+ return {
+ id: item.id,
+ name: item.alias,
+ alias: item.alias,
+ fullName: item.fullName,
+ type: item.type,
+ directory: item.directory,
+ file_name: item.fileName,
+ description: item.description,
+ size: item.size,
+ update_time: item.updateTime,
+ }
+ })
+
+ return { total, table }
+ }),
+ { total: 0, table: [] },
+ )
+
+ return state
+ }
+
+ const getResourceView = (id: number) => {
+ const params = {
+ skipLineNum: 0,
+ limit: 3000,
+ }
+ const { state } = useAsyncState(viewResource(params, id), {})
+ return state
+ }
+
+ return { getResourceListState, getResourceView }
+}