mirror of
https://gitee.com/dolphinscheduler/DolphinScheduler.git
synced 2024-11-29 10:47:42 +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.setFullName(resource.getFullName());
|
||||
tempResourceComponent.setType(resource.getType());
|
||||
tempResourceComponent.setCurrentDir(resource.getRelativePath());
|
||||
return tempResourceComponent;
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,6 @@ public final class Constants {
|
||||
public static final String FORMAT_S_S_COLON = "%s:%s";
|
||||
public static final String FOLDER_SEPARATOR = "/";
|
||||
|
||||
public static final String RESOURCE_TYPE_FILE = "resources";
|
||||
|
||||
public static final String EMPTY_STRING = "";
|
||||
|
||||
/**
|
||||
|
@ -85,7 +85,7 @@ public abstract class AbstractStorageOperator implements StorageOperator {
|
||||
String resourceBaseDirectory;
|
||||
switch (resourceType) {
|
||||
case FILE:
|
||||
resourceBaseDirectory = FileUtils.concatFilePath(tenantBaseDirectory, FILE_FOLDER_NAME);
|
||||
resourceBaseDirectory = FileUtils.concatFilePath(tenantBaseDirectory, StorageOperator.FILE_FOLDER_NAME);
|
||||
break;
|
||||
case ALL:
|
||||
resourceBaseDirectory = tenantBaseDirectory;
|
||||
|
@ -46,4 +46,5 @@ public class StorageEntity {
|
||||
private long size;
|
||||
private Date createTime;
|
||||
private Date updateTime;
|
||||
private String relativePath;
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import java.util.List;
|
||||
public interface StorageOperator {
|
||||
|
||||
String FILE_FOLDER_NAME = "resources";
|
||||
String UDF_FOLDER_NAME = "udfs";
|
||||
|
||||
ResourceMetadata getResourceMetaData(String resourceAbsolutePath);
|
||||
|
||||
|
@ -306,6 +306,7 @@ public class CosStorageOperator extends AbstractStorageOperator implements Close
|
||||
.type(resourceMetaData.getResourceType())
|
||||
.isDirectory(StringUtils.isEmpty(fileExtension))
|
||||
.size(metadata.getContentLength())
|
||||
.relativePath(resourceMetaData.getResourceRelativePath())
|
||||
.createTime(metadata.getLastModified())
|
||||
.updateTime(metadata.getLastModified())
|
||||
.build();
|
||||
|
@ -273,6 +273,7 @@ public class GcsStorageOperator extends AbstractStorageOperator implements Close
|
||||
entity.setDirectory(resourceMetaData.isDirectory());
|
||||
entity.setType(resourceMetaData.getResourceType());
|
||||
entity.setSize(blob.getSize());
|
||||
entity.setRelativePath(resourceMetaData.getResourceRelativePath());
|
||||
entity.setCreateTime(Date.from(blob.getCreateTimeOffsetDateTime().toInstant()));
|
||||
entity.setUpdateTime(Date.from(blob.getUpdateTimeOffsetDateTime().toInstant()));
|
||||
return entity;
|
||||
|
@ -268,7 +268,6 @@ public class HdfsStorageOperator extends AbstractStorageOperator implements Clos
|
||||
Path fileStatusPath = fileStatus.getPath();
|
||||
String fileAbsolutePath = fileStatusPath.toString();
|
||||
ResourceMetadata resourceMetaData = getResourceMetaData(fileAbsolutePath);
|
||||
|
||||
return StorageEntity.builder()
|
||||
.fileName(fileStatusPath.getName())
|
||||
.fullName(fileAbsolutePath)
|
||||
@ -276,6 +275,7 @@ public class HdfsStorageOperator extends AbstractStorageOperator implements Clos
|
||||
.type(resourceMetaData.getResourceType())
|
||||
.isDirectory(fileStatus.isDirectory())
|
||||
.size(fileStatus.getLen())
|
||||
.relativePath(resourceMetaData.getResourceRelativePath())
|
||||
.createTime(new Date(fileStatus.getModificationTime()))
|
||||
.updateTime(new Date(fileStatus.getModificationTime()))
|
||||
.build();
|
||||
|
@ -20,7 +20,6 @@ package org.apache.dolphinscheduler.plugin.storage.hdfs;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
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.plugin.storage.api.ResourceMetadata;
|
||||
import org.apache.dolphinscheduler.plugin.storage.api.StorageEntity;
|
||||
@ -47,7 +46,7 @@ class LocalStorageOperatorTest {
|
||||
Paths.get(LocalStorageOperatorTest.class.getResource("/").getFile(), "localStorage").toString();
|
||||
private static final String tenantCode = "default";
|
||||
private static final String baseDir =
|
||||
Paths.get(resourceBaseDir, tenantCode, StorageConstants.RESOURCE_TYPE_FILE).toString();
|
||||
Paths.get(resourceBaseDir, tenantCode, StorageOperator.FILE_FOLDER_NAME).toString();
|
||||
|
||||
@SneakyThrows
|
||||
@BeforeEach
|
||||
@ -116,7 +115,7 @@ class LocalStorageOperatorTest {
|
||||
public void testGetStorageBaseDirectory_withTenant_withResourceTypeFile() {
|
||||
String storageBaseDirectory = storageOperator.getStorageBaseDirectory("default", ResourceType.FILE);
|
||||
assertThat(storageBaseDirectory)
|
||||
.isEqualTo("file:" + Paths.get(resourceBaseDir, tenantCode, Constants.RESOURCE_TYPE_FILE));
|
||||
.isEqualTo("file:" + Paths.get(resourceBaseDir, tenantCode, StorageOperator.FILE_FOLDER_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -143,21 +142,21 @@ class LocalStorageOperatorTest {
|
||||
public void testGetStorageFileAbsolutePath() {
|
||||
String fileAbsolutePath = storageOperator.getStorageFileAbsolutePath("default", "test.sh");
|
||||
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
|
||||
@Test
|
||||
public void testCreateStorageDir_notExists() {
|
||||
String testDirFileAbsolutePath =
|
||||
"file:" + Paths.get(resourceBaseDir, "root", Constants.RESOURCE_TYPE_FILE, "testDir");
|
||||
"file:" + Paths.get(resourceBaseDir, "root", StorageOperator.FILE_FOLDER_NAME, "testDir");
|
||||
try {
|
||||
storageOperator.createStorageDir(testDirFileAbsolutePath);
|
||||
StorageEntity storageEntity = storageOperator.getStorageEntity(testDirFileAbsolutePath);
|
||||
assertThat(storageEntity.getFullName()).isEqualTo(testDirFileAbsolutePath);
|
||||
assertThat(storageEntity.getFileName()).isEqualTo("testDir");
|
||||
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.getType()).isEqualTo(ResourceType.FILE);
|
||||
} finally {
|
||||
@ -169,7 +168,7 @@ class LocalStorageOperatorTest {
|
||||
@Test
|
||||
public void testCreateStorageDir_exists() {
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -260,6 +260,7 @@ public class ObsStorageOperator extends AbstractStorageOperator implements Close
|
||||
.type(resourceMetaData.getResourceType())
|
||||
.isDirectory(StringUtils.isEmpty(fileExtension))
|
||||
.size(metadata.getContentLength())
|
||||
.relativePath(resourceMetaData.getResourceRelativePath())
|
||||
.createTime(metadata.getLastModified())
|
||||
.updateTime(metadata.getLastModified())
|
||||
.build();
|
||||
|
@ -331,6 +331,7 @@ public class OssStorageOperator extends AbstractStorageOperator implements Close
|
||||
storageEntity.setType(resourceMetaData.getResourceType());
|
||||
storageEntity.setDirectory(resourceMetaData.isDirectory());
|
||||
storageEntity.setSize(ossObject.getObjectMetadata().getContentLength());
|
||||
storageEntity.setRelativePath(resourceMetaData.getResourceRelativePath());
|
||||
storageEntity.setCreateTime(ossObject.getObjectMetadata().getLastModified());
|
||||
storageEntity.setUpdateTime(ossObject.getObjectMetadata().getLastModified());
|
||||
return storageEntity;
|
||||
|
@ -294,6 +294,7 @@ public class S3StorageOperator extends AbstractStorageOperator implements Closea
|
||||
entity.setDirectory(resourceMetaData.isDirectory());
|
||||
entity.setType(resourceMetaData.getResourceType());
|
||||
entity.setSize(object.getObjectMetadata().getContentLength());
|
||||
entity.setRelativePath(resourceMetaData.getResourceRelativePath());
|
||||
entity.setCreateTime(object.getObjectMetadata().getLastModified());
|
||||
entity.setUpdateTime(object.getObjectMetadata().getLastModified());
|
||||
return entity;
|
||||
|
@ -15,12 +15,15 @@
|
||||
* 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 { queryResourceList } from '@/service/modules/resources'
|
||||
import { useTaskNodeStore } from '@/store/project/task-node'
|
||||
import utils from '@/utils'
|
||||
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(
|
||||
span: number | Ref<number> = 24,
|
||||
@ -42,6 +45,9 @@ export function useResources(
|
||||
|
||||
const taskStore = useTaskNodeStore()
|
||||
|
||||
const source = ref('Hello')
|
||||
const { copy, isSupported } = useClipboard({ source })
|
||||
|
||||
const getResources = async () => {
|
||||
if (taskStore.resources.length) {
|
||||
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(() => {
|
||||
getResources()
|
||||
})
|
||||
@ -139,7 +155,44 @@ export function useResources(
|
||||
keyField: 'fullName',
|
||||
labelField: 'name',
|
||||
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: {
|
||||
trigger: ['blur'],
|
||||
|
Loading…
Reference in New Issue
Block a user