blob: a8a918be0fe902e7228bfdcb161b950ec28a66a8 [file] [log] [blame]
<!--
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
https://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.
-->
<script lang="ts">
import { computed, defineComponent, onMounted, reactive, ref } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n';
import { toPomString } from '/@/views/flink/app/utils/Pom';
export default defineComponent({
name: 'Resource',
});
</script>
<script setup lang="ts" name="Resource">
import { getMonacoOptions } from '/@/views/flink/app/data';
import { Icon } from '/@/components/Icon';
import { useMonaco } from '/@/hooks/web/useMonaco';
import { Select, Tabs, Alert, Tag, Space, Form } from 'ant-design-vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { fetchUpload } from '/@/api/flink/app/app';
import UploadJobJar from '/@/views/flink/app/components/UploadJobJar.vue';
import {onMounted, unref} from "vue";
interface DependencyType {
artifactId: string;
exclusions: string[];
groupId: string;
version: string;
classifier: string;
}
const TabPane = Tabs.TabPane;
const activeTab = ref('pom');
const pomBox = ref();
const dependency = reactive({
jar: {},
pom: {},
});
const dependencyRecords = ref<DependencyType[]>([]);
const uploadJars = ref<string[]>([]);
const loading = ref(false);
const emit = defineEmits(['update:value']);
const props = defineProps({
value: {
type: String,
default: '',
},
formModel: {
type: Object as PropType<Recordable>,
required: true,
},
});
const { t } = useI18n();
const defaultValue = '';
const { Swal } = useMessage();
const { onChange, setContent } = useMonaco(pomBox, {
language: 'xml',
code: props.value || defaultValue,
options: {
minimap: { enabled: false },
...(getMonacoOptions(false) as any),
},
});
async function handleApplyPom() {
dependency.pom = {};
dependencyRecords.value = [];
if (props.value == null || props.value.trim() === '') {
return;
}
const groupExp = /<groupId>([\s\S]*?)<\/groupId>/;
const artifactExp = /<artifactId>([\s\S]*?)<\/artifactId>/;
const versionExp = /<version>([\s\S]*?)<\/version>/;
const classifierExp = /<classifier>([\s\S]*?)<\/classifier>/;
const exclusionsExp = /<exclusions>([\s\S]*?)<\/exclusions>/;
const poms = props.value
.split('</dependency>')
.filter((x) => x.trim().replace(/\\s+/, '') !== '');
poms.forEach((dep) => {
const groupId = dep.match(groupExp) ? groupExp.exec(dep)![1].trim() : null;
const artifactId = dep.match(artifactExp) ? artifactExp.exec(dep)![1].trim() : null;
const version = dep.match(versionExp) ? versionExp.exec(dep)![1].trim() : null;
const classifier = dep.match(classifierExp) ? classifierExp.exec(dep)![1].trim() : null;
const exclusion = dep.match(exclusionsExp) ? exclusionsExp.exec(dep)![1].trim() : null;
if (groupId != null && artifactId != null && version != null) {
const mvnPom: Recordable = {
groupId: groupId,
artifactId: artifactId,
version: version,
};
if (classifier != null) {
mvnPom.classifier = classifier;
}
const id = getId(mvnPom);
const pomExclusion = {};
if (exclusion != null) {
const exclusions = exclusion.split('<exclusion>');
exclusions.forEach((e) => {
if (e != null && e.length > 0) {
const e_group = e.match(groupExp) ? groupExp.exec(e)![1].trim() : null;
const e_artifact = e.match(artifactExp) ? artifactExp.exec(e)![1].trim() : null;
const id = e_group + '_' + e_artifact;
pomExclusion[id] = {
groupId: e_group,
artifactId: e_artifact,
};
}
});
}
mvnPom.exclusions = pomExclusion;
dependency.pom[id] = mvnPom;
} else {
console.error('dependency error...');
}
});
handleUpdateDependency();
}
/* custom http */
async function handleCustomDepsRequest(data) {
try {
loading.value = true;
const formData = new FormData();
formData.append('file', data.file);
await fetchUpload(formData);
dependency.jar = {}
dependency.jar[data.file.name] = data.file.name;
handleUpdateDependency();
} catch (error) {
console.error(error);
} finally {
loading.value = false;
}
}
// update the dependency list
function handleUpdateDependency() {
const deps: DependencyType[] = [];
const jars: string[] = [];
Object.keys(dependency.pom).forEach((v: string) => {
deps.push(dependency.pom[v]);
});
Object.keys(dependency.jar).forEach((v: string) => {
jars.push(v);
});
dependencyRecords.value = deps;
uploadJars.value = jars;
}
function handleRemoveJar(jar: string) {
delete dependency.jar[jar];
handleUpdateDependency();
}
// set default value
function setDefaultValue(dataSource: { pom?: DependencyType[]; jar?: string[] }) {
dependencyRecords.value = dataSource.pom || [];
uploadJars.value = dataSource.jar || [];
dependency.pom = {};
dependency.jar = {};
if (dataSource.pom === undefined) {
setContent(defaultValue)
}
dataSource.pom?.map((pomRecord: DependencyType) => {
const id = getId(pomRecord);
dependency.pom[id] = pomRecord;
setContent(toPomString(pomRecord))
});
dataSource.jar?.map((fileName: string) => {
dependency.jar[fileName] = fileName;
});
}
function getId(pom) {
if (pom.classifier != null) {
return pom.groupId + '_' + pom.artifactId + '_' + pom.classifier;
}
return pom.groupId + '_' + pom.artifactId;
}
onChange((data) => {
emit('update:value', data);
});
onMounted(async () => {
setDefaultValue(JSON.parse(props?.formModel?.dependency || '{}'));
});
defineExpose({
setDefaultValue,
dependency,
handleApplyPom,
dependencyRecords,
uploadJars,
});
</script>
<style lang="less">
@import url('/@/views/flink/app/styles/Add.less');
.apply-pom {
z-index: 99;
position: absolute;
bottom: 20px;
float: right;
right: 20px;
cursor: pointer;
height: 26px;
padding: 0 12px;
font-size: 12px;
}
</style>
<template>
<Tabs type="card" v-model:activeKey="activeTab" class="pom-card">
<TabPane key="pom" tab="Maven pom">
<div class="relative">
<div ref="pomBox" class="pom-box syntax-true" style="height: 300px"></div>
</div>
</TabPane>
<TabPane key="jar" tab="Upload Jar">
<UploadJobJar :custom-request="handleCustomDepsRequest" v-model:loading="loading" />
</TabPane>
</Tabs>
<div class="dependency-box" v-if="uploadJars.length > 0">
<Alert
class="dependency-item"
v-for="jar in uploadJars"
:key="`upload_jars_${jar}`"
type="info"
>
<template #message>
<Space>
<Tag class="tag-dependency" color="#108ee9">JAR</Tag>
{{ jar }}
<Icon
icon="ant-design:close-outlined"
class="icon-close cursor-pointer"
:size="12"
@click="handleRemoveJar(jar)"
/>
</Space>
</template>
</Alert>
</div>
</template>