mirror of
https://gitee.com/dolphinscheduler/DolphinScheduler.git
synced 2024-12-01 19:58:29 +08:00
[Feature-16801][UI] Add copy path of resource file in task definition (#16803)
This commit is contained in:
parent
15adf21e45
commit
f3b5d1f57d
@ -126,6 +126,7 @@ public class ResourceTreeVisitor implements Visitor {
|
|||||||
tempResourceComponent.setName(resource.getFileName());
|
tempResourceComponent.setName(resource.getFileName());
|
||||||
tempResourceComponent.setFullName(resource.getFullName());
|
tempResourceComponent.setFullName(resource.getFullName());
|
||||||
tempResourceComponent.setType(resource.getType());
|
tempResourceComponent.setType(resource.getType());
|
||||||
|
tempResourceComponent.setCurrentDir(resource.getRelativePath());
|
||||||
return tempResourceComponent;
|
return tempResourceComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,8 +43,6 @@ public final class Constants {
|
|||||||
public static final String FORMAT_S_S_COLON = "%s:%s";
|
public static final String FORMAT_S_S_COLON = "%s:%s";
|
||||||
public static final String FOLDER_SEPARATOR = "/";
|
public static final String FOLDER_SEPARATOR = "/";
|
||||||
|
|
||||||
public static final String RESOURCE_TYPE_FILE = "resources";
|
|
||||||
|
|
||||||
public static final String EMPTY_STRING = "";
|
public static final String EMPTY_STRING = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,7 +85,7 @@ public abstract class AbstractStorageOperator implements StorageOperator {
|
|||||||
String resourceBaseDirectory;
|
String resourceBaseDirectory;
|
||||||
switch (resourceType) {
|
switch (resourceType) {
|
||||||
case FILE:
|
case FILE:
|
||||||
resourceBaseDirectory = FileUtils.concatFilePath(tenantBaseDirectory, FILE_FOLDER_NAME);
|
resourceBaseDirectory = FileUtils.concatFilePath(tenantBaseDirectory, StorageOperator.FILE_FOLDER_NAME);
|
||||||
break;
|
break;
|
||||||
case ALL:
|
case ALL:
|
||||||
resourceBaseDirectory = tenantBaseDirectory;
|
resourceBaseDirectory = tenantBaseDirectory;
|
||||||
|
@ -46,4 +46,5 @@ public class StorageEntity {
|
|||||||
private long size;
|
private long size;
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
private String relativePath;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import java.util.List;
|
|||||||
public interface StorageOperator {
|
public interface StorageOperator {
|
||||||
|
|
||||||
String FILE_FOLDER_NAME = "resources";
|
String FILE_FOLDER_NAME = "resources";
|
||||||
String UDF_FOLDER_NAME = "udfs";
|
|
||||||
|
|
||||||
ResourceMetadata getResourceMetaData(String resourceAbsolutePath);
|
ResourceMetadata getResourceMetaData(String resourceAbsolutePath);
|
||||||
|
|
||||||
|
@ -306,6 +306,7 @@ public class CosStorageOperator extends AbstractStorageOperator implements Close
|
|||||||
.type(resourceMetaData.getResourceType())
|
.type(resourceMetaData.getResourceType())
|
||||||
.isDirectory(StringUtils.isEmpty(fileExtension))
|
.isDirectory(StringUtils.isEmpty(fileExtension))
|
||||||
.size(metadata.getContentLength())
|
.size(metadata.getContentLength())
|
||||||
|
.relativePath(resourceMetaData.getResourceRelativePath())
|
||||||
.createTime(metadata.getLastModified())
|
.createTime(metadata.getLastModified())
|
||||||
.updateTime(metadata.getLastModified())
|
.updateTime(metadata.getLastModified())
|
||||||
.build();
|
.build();
|
||||||
|
@ -273,6 +273,7 @@ public class GcsStorageOperator extends AbstractStorageOperator implements Close
|
|||||||
entity.setDirectory(resourceMetaData.isDirectory());
|
entity.setDirectory(resourceMetaData.isDirectory());
|
||||||
entity.setType(resourceMetaData.getResourceType());
|
entity.setType(resourceMetaData.getResourceType());
|
||||||
entity.setSize(blob.getSize());
|
entity.setSize(blob.getSize());
|
||||||
|
entity.setRelativePath(resourceMetaData.getResourceRelativePath());
|
||||||
entity.setCreateTime(Date.from(blob.getCreateTimeOffsetDateTime().toInstant()));
|
entity.setCreateTime(Date.from(blob.getCreateTimeOffsetDateTime().toInstant()));
|
||||||
entity.setUpdateTime(Date.from(blob.getUpdateTimeOffsetDateTime().toInstant()));
|
entity.setUpdateTime(Date.from(blob.getUpdateTimeOffsetDateTime().toInstant()));
|
||||||
return entity;
|
return entity;
|
||||||
|
@ -268,7 +268,6 @@ public class HdfsStorageOperator extends AbstractStorageOperator implements Clos
|
|||||||
Path fileStatusPath = fileStatus.getPath();
|
Path fileStatusPath = fileStatus.getPath();
|
||||||
String fileAbsolutePath = fileStatusPath.toString();
|
String fileAbsolutePath = fileStatusPath.toString();
|
||||||
ResourceMetadata resourceMetaData = getResourceMetaData(fileAbsolutePath);
|
ResourceMetadata resourceMetaData = getResourceMetaData(fileAbsolutePath);
|
||||||
|
|
||||||
return StorageEntity.builder()
|
return StorageEntity.builder()
|
||||||
.fileName(fileStatusPath.getName())
|
.fileName(fileStatusPath.getName())
|
||||||
.fullName(fileAbsolutePath)
|
.fullName(fileAbsolutePath)
|
||||||
@ -276,6 +275,7 @@ public class HdfsStorageOperator extends AbstractStorageOperator implements Clos
|
|||||||
.type(resourceMetaData.getResourceType())
|
.type(resourceMetaData.getResourceType())
|
||||||
.isDirectory(fileStatus.isDirectory())
|
.isDirectory(fileStatus.isDirectory())
|
||||||
.size(fileStatus.getLen())
|
.size(fileStatus.getLen())
|
||||||
|
.relativePath(resourceMetaData.getResourceRelativePath())
|
||||||
.createTime(new Date(fileStatus.getModificationTime()))
|
.createTime(new Date(fileStatus.getModificationTime()))
|
||||||
.updateTime(new Date(fileStatus.getModificationTime()))
|
.updateTime(new Date(fileStatus.getModificationTime()))
|
||||||
.build();
|
.build();
|
||||||
|
@ -20,7 +20,6 @@ package org.apache.dolphinscheduler.plugin.storage.hdfs;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import org.apache.dolphinscheduler.common.constants.Constants;
|
|
||||||
import org.apache.dolphinscheduler.common.utils.FileUtils;
|
import org.apache.dolphinscheduler.common.utils.FileUtils;
|
||||||
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata;
|
import org.apache.dolphinscheduler.plugin.storage.api.ResourceMetadata;
|
||||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity;
|
import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity;
|
||||||
@ -47,7 +46,7 @@ class LocalStorageOperatorTest {
|
|||||||
Paths.get(LocalStorageOperatorTest.class.getResource("/").getFile(), "localStorage").toString();
|
Paths.get(LocalStorageOperatorTest.class.getResource("/").getFile(), "localStorage").toString();
|
||||||
private static final String tenantCode = "default";
|
private static final String tenantCode = "default";
|
||||||
private static final String baseDir =
|
private static final String baseDir =
|
||||||
Paths.get(resourceBaseDir, tenantCode, StorageConstants.RESOURCE_TYPE_FILE).toString();
|
Paths.get(resourceBaseDir, tenantCode, StorageOperator.FILE_FOLDER_NAME).toString();
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@ -116,7 +115,7 @@ class LocalStorageOperatorTest {
|
|||||||
public void testGetStorageBaseDirectory_withTenant_withResourceTypeFile() {
|
public void testGetStorageBaseDirectory_withTenant_withResourceTypeFile() {
|
||||||
String storageBaseDirectory = storageOperator.getStorageBaseDirectory("default", ResourceType.FILE);
|
String storageBaseDirectory = storageOperator.getStorageBaseDirectory("default", ResourceType.FILE);
|
||||||
assertThat(storageBaseDirectory)
|
assertThat(storageBaseDirectory)
|
||||||
.isEqualTo("file:" + Paths.get(resourceBaseDir, tenantCode, Constants.RESOURCE_TYPE_FILE));
|
.isEqualTo("file:" + Paths.get(resourceBaseDir, tenantCode, StorageOperator.FILE_FOLDER_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -143,21 +142,21 @@ class LocalStorageOperatorTest {
|
|||||||
public void testGetStorageFileAbsolutePath() {
|
public void testGetStorageFileAbsolutePath() {
|
||||||
String fileAbsolutePath = storageOperator.getStorageFileAbsolutePath("default", "test.sh");
|
String fileAbsolutePath = storageOperator.getStorageFileAbsolutePath("default", "test.sh");
|
||||||
assertThat(fileAbsolutePath).isEqualTo(
|
assertThat(fileAbsolutePath).isEqualTo(
|
||||||
"file:" + Paths.get(resourceBaseDir, tenantCode, Constants.RESOURCE_TYPE_FILE, "test.sh"));
|
"file:" + Paths.get(resourceBaseDir, tenantCode, StorageOperator.FILE_FOLDER_NAME, "test.sh"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Test
|
@Test
|
||||||
public void testCreateStorageDir_notExists() {
|
public void testCreateStorageDir_notExists() {
|
||||||
String testDirFileAbsolutePath =
|
String testDirFileAbsolutePath =
|
||||||
"file:" + Paths.get(resourceBaseDir, "root", Constants.RESOURCE_TYPE_FILE, "testDir");
|
"file:" + Paths.get(resourceBaseDir, "root", StorageOperator.FILE_FOLDER_NAME, "testDir");
|
||||||
try {
|
try {
|
||||||
storageOperator.createStorageDir(testDirFileAbsolutePath);
|
storageOperator.createStorageDir(testDirFileAbsolutePath);
|
||||||
StorageEntity storageEntity = storageOperator.getStorageEntity(testDirFileAbsolutePath);
|
StorageEntity storageEntity = storageOperator.getStorageEntity(testDirFileAbsolutePath);
|
||||||
assertThat(storageEntity.getFullName()).isEqualTo(testDirFileAbsolutePath);
|
assertThat(storageEntity.getFullName()).isEqualTo(testDirFileAbsolutePath);
|
||||||
assertThat(storageEntity.getFileName()).isEqualTo("testDir");
|
assertThat(storageEntity.getFileName()).isEqualTo("testDir");
|
||||||
assertThat(storageEntity.getPfullName())
|
assertThat(storageEntity.getPfullName())
|
||||||
.isEqualTo("file:" + Paths.get(resourceBaseDir, "root", Constants.RESOURCE_TYPE_FILE));
|
.isEqualTo("file:" + Paths.get(resourceBaseDir, "root", StorageOperator.FILE_FOLDER_NAME));
|
||||||
assertThat(storageEntity.isDirectory()).isTrue();
|
assertThat(storageEntity.isDirectory()).isTrue();
|
||||||
assertThat(storageEntity.getType()).isEqualTo(ResourceType.FILE);
|
assertThat(storageEntity.getType()).isEqualTo(ResourceType.FILE);
|
||||||
} finally {
|
} finally {
|
||||||
@ -169,7 +168,7 @@ class LocalStorageOperatorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testCreateStorageDir_exists() {
|
public void testCreateStorageDir_exists() {
|
||||||
String testDirFileAbsolutePath =
|
String testDirFileAbsolutePath =
|
||||||
"file:" + Paths.get(resourceBaseDir, "default", Constants.RESOURCE_TYPE_FILE, "sqlDirectory");
|
"file:" + Paths.get(resourceBaseDir, "default", StorageOperator.FILE_FOLDER_NAME, "sqlDirectory");
|
||||||
assertThrows(FileAlreadyExistsException.class, () -> storageOperator.createStorageDir(testDirFileAbsolutePath));
|
assertThrows(FileAlreadyExistsException.class, () -> storageOperator.createStorageDir(testDirFileAbsolutePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +260,7 @@ public class ObsStorageOperator extends AbstractStorageOperator implements Close
|
|||||||
.type(resourceMetaData.getResourceType())
|
.type(resourceMetaData.getResourceType())
|
||||||
.isDirectory(StringUtils.isEmpty(fileExtension))
|
.isDirectory(StringUtils.isEmpty(fileExtension))
|
||||||
.size(metadata.getContentLength())
|
.size(metadata.getContentLength())
|
||||||
|
.relativePath(resourceMetaData.getResourceRelativePath())
|
||||||
.createTime(metadata.getLastModified())
|
.createTime(metadata.getLastModified())
|
||||||
.updateTime(metadata.getLastModified())
|
.updateTime(metadata.getLastModified())
|
||||||
.build();
|
.build();
|
||||||
|
@ -331,6 +331,7 @@ public class OssStorageOperator extends AbstractStorageOperator implements Close
|
|||||||
storageEntity.setType(resourceMetaData.getResourceType());
|
storageEntity.setType(resourceMetaData.getResourceType());
|
||||||
storageEntity.setDirectory(resourceMetaData.isDirectory());
|
storageEntity.setDirectory(resourceMetaData.isDirectory());
|
||||||
storageEntity.setSize(ossObject.getObjectMetadata().getContentLength());
|
storageEntity.setSize(ossObject.getObjectMetadata().getContentLength());
|
||||||
|
storageEntity.setRelativePath(resourceMetaData.getResourceRelativePath());
|
||||||
storageEntity.setCreateTime(ossObject.getObjectMetadata().getLastModified());
|
storageEntity.setCreateTime(ossObject.getObjectMetadata().getLastModified());
|
||||||
storageEntity.setUpdateTime(ossObject.getObjectMetadata().getLastModified());
|
storageEntity.setUpdateTime(ossObject.getObjectMetadata().getLastModified());
|
||||||
return storageEntity;
|
return storageEntity;
|
||||||
|
@ -294,6 +294,7 @@ public class S3StorageOperator extends AbstractStorageOperator implements Closea
|
|||||||
entity.setDirectory(resourceMetaData.isDirectory());
|
entity.setDirectory(resourceMetaData.isDirectory());
|
||||||
entity.setType(resourceMetaData.getResourceType());
|
entity.setType(resourceMetaData.getResourceType());
|
||||||
entity.setSize(object.getObjectMetadata().getContentLength());
|
entity.setSize(object.getObjectMetadata().getContentLength());
|
||||||
|
entity.setRelativePath(resourceMetaData.getResourceRelativePath());
|
||||||
entity.setCreateTime(object.getObjectMetadata().getLastModified());
|
entity.setCreateTime(object.getObjectMetadata().getLastModified());
|
||||||
entity.setUpdateTime(object.getObjectMetadata().getLastModified());
|
entity.setUpdateTime(object.getObjectMetadata().getLastModified());
|
||||||
return entity;
|
return entity;
|
||||||
|
@ -15,12 +15,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ref, onMounted, Ref, isRef } from 'vue'
|
import { ref, onMounted, Ref, isRef, h } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { queryResourceList } from '@/service/modules/resources'
|
import { queryResourceList } from '@/service/modules/resources'
|
||||||
import { useTaskNodeStore } from '@/store/project/task-node'
|
import { useTaskNodeStore } from '@/store/project/task-node'
|
||||||
import utils from '@/utils'
|
import utils from '@/utils'
|
||||||
import type { IJsonItem, IResource } from '../types'
|
import type { IJsonItem, IResource } from '../types'
|
||||||
|
import { NButton, NIcon, NTag } from 'naive-ui'
|
||||||
|
import { CopyOutlined } from '@vicons/antd'
|
||||||
|
import { useClipboard } from '@vueuse/core'
|
||||||
|
|
||||||
export function useResources(
|
export function useResources(
|
||||||
span: number | Ref<number> = 24,
|
span: number | Ref<number> = 24,
|
||||||
@ -42,6 +45,9 @@ export function useResources(
|
|||||||
|
|
||||||
const taskStore = useTaskNodeStore()
|
const taskStore = useTaskNodeStore()
|
||||||
|
|
||||||
|
const source = ref('Hello')
|
||||||
|
const { copy, isSupported } = useClipboard({ source })
|
||||||
|
|
||||||
const getResources = async () => {
|
const getResources = async () => {
|
||||||
if (taskStore.resources.length) {
|
if (taskStore.resources.length) {
|
||||||
resourcesOptions.value = taskStore.resources
|
resourcesOptions.value = taskStore.resources
|
||||||
@ -116,6 +122,16 @@ export function useResources(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const copyResourceName = async (name: string) => {
|
||||||
|
if (isSupported.value) {
|
||||||
|
event?.stopPropagation()
|
||||||
|
await copy(name)
|
||||||
|
window.$message.success(t('project.node.copy_success'))
|
||||||
|
} else {
|
||||||
|
window.$message.error(t('project.node.copy_failed'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getResources()
|
getResources()
|
||||||
})
|
})
|
||||||
@ -139,7 +155,44 @@ export function useResources(
|
|||||||
keyField: 'fullName',
|
keyField: 'fullName',
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
disabledField: 'disable',
|
disabledField: 'disable',
|
||||||
loading: resourcesLoading
|
loading: resourcesLoading,
|
||||||
|
'render-tag': ({
|
||||||
|
option,
|
||||||
|
handleClose
|
||||||
|
}: {
|
||||||
|
option: any
|
||||||
|
handleClose: any
|
||||||
|
}) => {
|
||||||
|
return h(
|
||||||
|
NTag,
|
||||||
|
{
|
||||||
|
type: 'success',
|
||||||
|
closable: true,
|
||||||
|
onClose: () => {
|
||||||
|
handleClose()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => option.currentDir,
|
||||||
|
avatar: () =>
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
tag: 'div',
|
||||||
|
type: 'info',
|
||||||
|
size: 'tiny',
|
||||||
|
onClick: () => copyResourceName(option.currentDir)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: () =>
|
||||||
|
h(NIcon, null, {
|
||||||
|
default: () => h(CopyOutlined)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
trigger: ['blur'],
|
trigger: ['blur'],
|
||||||
|
Loading…
Reference in New Issue
Block a user