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

212 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div v-if="$resources.options.loading" class="mt-2 flex justify-center">
<LoadingText />
</div>
<div class="flex justify-center pt-2" v-else-if="!options?.authorized">
<Button
v-if="requiresReAuth"
variant="solid"
icon-left="github"
label="重新授权 GitHub"
@click="$resources.clearAccessToken.submit()"
:loading="$resources.clearAccessToken.loading"
/>
<Button
v-if="needsAuthorization"
variant="solid"
icon-left="github"
label="连接到 GitHub"
:link="options.installation_url + '?state=' + state"
/>
</div>
<div v-else class="space-y-4">
<FormControl
type="autocomplete"
label="选择 GitHub 用户/组织"
:options="
options.installations.map((i) => ({
label: i.login,
value: String(i.id), // type cast to string for search to work
image: i.image,
}))
"
v-model="selectedGithubUser"
>
<template #prefix>
<img
v-if="selectedGithubUserData"
:src="selectedGithubUserData?.image"
class="mr-2 h-4 w-4 rounded-full"
/>
<FeatherIcon v-else name="users" class="mr-2 h-4 w-4" />
</template>
<template #item-prefix="{ active, selected, option }">
<img
v-if="option?.image"
:src="option.image"
class="mr-2 h-4 w-4 rounded-full"
/>
<FeatherIcon v-else name="user" class="mr-2 h-4 w-4" />
</template>
</FormControl>
<span class="text-sm text-gray-600">
没有看到您的组织
<Link
:href="options.installation_url + '?state=' + state"
class="font-medium"
>
GitHub 添加
</Link>
</span>
<FormControl
type="autocomplete"
v-if="selectedGithubUserData"
label="选择 GitHub 仓库"
:options="
(selectedGithubUserData.repos || []).map((r) => ({
label: r.name,
value: r.name,
}))
"
v-model="selectedGithubRepository"
>
<template #prefix>
<FeatherIcon name="book" class="mr-2 h-4 w-4" />
</template>
<template #item-prefix="{ active, selected, option }">
<FeatherIcon
:name="option.value.private ? 'lock' : 'book'"
class="mr-2 h-4 w-4"
/>
</template>
</FormControl>
<p v-if="selectedGithubUserData" class="!mt-2 text-sm text-gray-600">
没有看到您的仓库
<Link :href="selectedGithubUserData.url" class="font-medium">
GitHub 添加
</Link>
</p>
<FormControl
v-if="selectedGithubRepository"
type="autocomplete"
label="选择分支"
:options="branchOptions"
v-model="selectedBranch"
>
<template #prefix>
<FeatherIcon name="git-branch" class="mr-2 h-4 w-4" />
</template>
</FormControl>
</div>
</template>
<script>
export default {
emits: ['validateApp', 'fieldChange'],
data() {
return {
app: {},
selectedBranch: '',
selectedGithubUser: null,
selectedGithubRepository: null,
};
},
watch: {
selectedGithubUser() {
this.selectedBranch = '';
this.$emit('fieldChange');
},
selectedGithubRepository(val) {
if (!val) {
this.selectedBranch = '';
return;
}
this.$emit('fieldChange');
this.$resources.branches.submit({
owner: this.selectedGithubUser?.label,
name: val?.label,
installation: this.selectedGithubUser?.value,
});
if (this.selectedGithubUserData) {
let defaultBranch = this.selectedGithubUserData.repos.find(
(r) => r.name === val.label
).default_branch;
this.selectedBranch = { label: defaultBranch, value: defaultBranch };
} else this.selectedBranch = '';
},
selectedBranch(newSelectedBranch) {
if (this.appOwner && this.appName && newSelectedBranch)
this.$emit('validateApp', {
owner: this.appOwner,
repository: this.appName,
branch: newSelectedBranch.value,
selectedGithubUser: this.selectedGithubUserData,
});
},
},
resources: {
options() {
return {
url: 'jcloud.api.github.options',
auto: true,
};
},
branches() {
return {
url: 'jcloud.api.github.branches',
};
},
clearAccessToken() {
return {
url: 'jcloud.api.github.clear_token_and_get_installation_url',
onSuccess(installation_url) {
window.location.href = installation_url + '?state=' + this.state;
},
};
},
},
computed: {
options() {
return this.$resources.options.data;
},
appOwner() {
return this.selectedGithubUser?.label;
},
appName() {
return this.selectedGithubRepository?.label;
},
branchOptions() {
return (this.$resources.branches.data || []).map((branch) => ({
label: branch.name,
value: branch.name,
}));
},
selectedGithubUserData() {
if (!this.selectedGithubUser) return null;
return this.options.installations.find(
(i) => i.id === Number(this.selectedGithubUser.value)
);
},
needsAuthorization() {
if (this.$resources.options.loading) return false;
return (
this.$resources.options.data &&
(!this.$resources.options.data.authorized ||
this.$resources.options.data.installations.length === 0)
);
},
requiresReAuth() {
return this.$resources.options?.error?.messages.includes(
'Bad credentials'
);
},
state() {
let location = window.location.href;
let state = { team: this.$team.name, url: location };
return btoa(JSON.stringify(state));
},
},
};
</script>