jcloud/dashboard/src2/components/NewAppDialog.vue
2025-04-12 17:39:38 +08:00

283 lines
6.9 KiB
Vue

<template>
<Dialog
:options="{
title: '从 GitHub 添加应用',
size: 'xl',
actions: [
{
label: isAppOnBench ? '更新应用' : '添加应用',
variant: 'solid',
disabled: !app || !appValidated,
onClick: addAppHandler,
},
],
}"
v-model="show"
@update:modelValue="
() => {
show = false;
}
"
>
<template #body-content>
<FTabs :tabs="tabs" v-model="tabIndex">
<TabList v-slot="{ tab, selected }" class="pl-0">
<div
class="flex cursor-pointer items-center gap-1.5 border-b border-transparent py-3 text-base text-gray-600 duration-300 ease-in-out hover:border-gray-400 hover:text-gray-900 focus:outline-none focus:transition-none [&>div]:pl-0"
:class="{ 'text-gray-900': selected }"
>
<span>{{ tab.label }}</span>
</div>
</TabList>
<TabPanel v-slot="{ tab }">
<div class="-ml-0.5 p-1">
<div v-if="tab.value === 'public-github-app'" class="space-y-4">
<div class="mt-4 flex items-end space-x-2">
<FormControl
class="mb-0.5 grow"
label="GitHub URL"
v-model="githubAppLink"
autocomplete="off"
/>
<Button
v-if="!selectedBranch"
label="获取分支"
:loading="$resources.branches.loading"
@click="
$resources.branches.submit({
owner: appOwner,
name: appName,
})
"
/>
<Autocomplete
v-else
:options="branchOptions"
v-model="selectedBranch"
>
<template v-slot:target="{ togglePopover }">
<Button
:label="selectedBranch?.value || selectedBranch"
icon-right="chevron-down"
@click="() => togglePopover()"
/>
</template>
</Autocomplete>
</div>
</div>
<div v-else-if="tab.value === 'your-github-app'" class="pt-4">
<GitHubAppSelector
@validateApp="validateApp"
@fieldChange="appValidated = false"
/>
</div>
<div class="mt-4 space-y-2">
<div
v-if="$resources.validateApp.loading && !appValidated"
class="flex text-base text-gray-700"
>
<LoadingIndicator class="mr-2 w-4" />
正在验证应用...
</div>
<div
v-if="appValidated && app"
class="flex text-base text-gray-700"
>
<GreenCheckIcon class="mr-2 w-4" />
找到 {{ app.title }} ({{ app.name }})
</div>
</div>
</div>
</TabPanel>
</FTabs>
<AlertBanner
v-if="isAppOnBench"
class="mt-4"
:show-icon="false"
:title="
`应用 <strong>${app.name}</strong> 已存在于当前工作台。` +
`点击更新应用将更改应用源为所选源。`
"
type="warning"
/>
<ErrorMessage
:message="$resources.validateApp.error || $resources.branches.error"
/>
</template>
</Dialog>
</template>
<script>
import { FormControl, Tabs, TabList, TabPanel } from 'jingrow-ui';
import { DashboardError } from '../utils/error';
import GitHubAppSelector from './GitHubAppSelector.vue';
import AlertBanner from './AlertBanner.vue';
export default {
name: 'NewAppDialog',
components: {
GitHubAppSelector,
FTabs: Tabs,
FormControl,
AlertBanner,
TabPanel,
TabList,
},
props: {
group: {
type: Object,
required: true,
},
},
emits: ['app-added'],
data() {
return {
show: true,
app: {},
tabIndex: 0,
githubAppLink: '',
selectedBranch: '',
appValidated: false,
selectedGithubUser: null,
selectedGithubRepository: null,
tabs: [
{
label: '公共 GitHub 应用',
value: 'public-github-app',
},
{
label: '您的 GitHub 应用',
value: 'your-github-app',
},
],
};
},
watch: {
tabIndex() {
this.app = null;
this.appValidated = false;
this.selectedBranch = '';
this.githubAppLink = '';
this.selectedGithubUser = null;
this.selectedGithubRepository = null;
this.$resources.branches.reset();
},
githubAppLink() {
this.selectedBranch = '';
this.appValidated = false;
},
selectedBranch(newSelectedBranch) {
if (this.appOwner && this.appName && newSelectedBranch)
this.$resources.validateApp.submit({
owner: this.appOwner,
repository: this.appName,
branch: newSelectedBranch.value,
installation: this.selectedGithubUser?.id,
});
},
},
resources: {
validateApp() {
return {
url: 'jcloud.api.github.app',
onSuccess(data) {
this.appValidated = true;
if (!data) {
return;
}
let repository_url = this.githubAppLink;
if (!repository_url) {
const repo_owner = this.selectedGithubUser?.login;
const repo = this.selectedGithubRepository || data.name;
repository_url = `https://github.com/${repo_owner}/${repo}`;
}
this.app = {
name: data.name,
title: data.title,
repository_url,
github_installation_id: this.selectedGithubUser?.id,
branch: this.selectedBranch.value,
};
},
};
},
branches() {
return {
url: 'jcloud.api.github.branches',
validate() {
const githubUrlRegex =
/^(https?:\/\/)?(www\.)?github\.com\/([a-zA-Z0-9_.\-]+)\/([a-zA-Z0-9_.\-]+)(\/)?$/;
const isValidUrl = githubUrlRegex.test(this.githubAppLink);
if (!isValidUrl) {
throw new DashboardError('请输入有效的 GitHub 链接');
}
},
onSuccess(data) {
if (this.tabIndex === 0)
this.selectedBranch = {
label: data[0].name,
value: data[0].name,
};
},
};
},
},
computed: {
appOwner() {
if (this.tabIndex === 0) {
const urlParts = this.githubAppLink.split('/');
if (urlParts.length < 4) return;
return urlParts[3];
}
},
appName() {
if (this.tabIndex === 0) {
const urlParts = this.githubAppLink.split('/');
if (urlParts.length < 5) return;
return urlParts[4].replace('.git', '');
}
},
branchOptions() {
return (this.$resources.branches.data || []).map((branch) => ({
label: branch.name,
value: branch.name,
}));
},
isAppOnBench() {
if (!this.app) {
return false;
}
for (const app of this.group.apps) {
if (app.app == this.app.name) return true;
}
return false;
},
},
methods: {
validateApp(data) {
this.selectedBranch = {
label: data.branch,
value: data.branch,
};
this.selectedGithubRepository = data.repository;
this.selectedGithubUser = data.selectedGithubUser;
this.$resources.validateApp.submit({
...data,
installation: data.selectedGithubUser.id,
});
},
addAppHandler() {
this.$emit('app-added', this.app, this.isAppOnBench);
this.show = false;
},
},
};
</script>