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

111 lines
2.8 KiB
Vue

<template>
<div class="space-y-3 max-h-96 overflow-auto px-4">
<button
class="block w-full cursor-pointer rounded-md border px-4 py-3 text-left shadow ring-inset focus:outline-none"
:class="
isAppSelected(app)
? 'bg-gray-50 ring-2 ring-gray-600'
: 'cursor-pointer hover:border-gray-300'
"
v-for="app in apps"
:key="app.name"
@click="toggleApp(app.name)"
>
<div class="ml-1 flex items-center justify-between text-left text-base">
<div>
<div class="font-semibold">
{{ app.title }}
</div>
<div class="text-gray-700">
{{ app.source.repository_owner }}/{{ app.source.repository }}
</div>
</div>
<Dropdown :options="dropdownItems(app)" right>
<template v-slot="{ open }">
<Button type="white" icon-right="chevron-down">
<span>{{ app.source.branch }}</span>
</Button>
</template>
</Dropdown>
</div>
</button>
</div>
</template>
<script>
export default {
name: 'AppSourceSelector',
props: ['apps', 'modelValue', 'multiple'],
emits: ['update:modelValue'],
methods: {
toggleApp(appName) {
let mapApp = app => ({ app: app.name, source: app.source });
if (!this.multiple) {
let selectedApp = this.apps.find(app => app.name === appName);
this.$emit('update:modelValue', mapApp(selectedApp));
return;
}
// multiple
let selectedAppsMap = Object.assign({}, this.selectedAppsMap);
if (selectedAppsMap[appName]) {
// exists already, remove
selectedAppsMap[appName] = false;
} else {
// add
selectedAppsMap[appName] = true;
}
let selectedApps = this.apps
.filter(app => selectedAppsMap[app.name])
.map(mapApp);
this.$emit('update:modelValue', selectedApps);
},
isAppSelected(app) {
if (this.multiple) {
return this.selectedAppsMap[app.name];
}
return this.modelValue && this.modelValue.app === app.name;
},
dropdownItems(app) {
return app.sources.map(source => ({
label: `${source.repository_owner}/${source.repository}:${source.branch}`,
onClick: () => this.selectSource(app, source)
}));
},
selectSource(app, source) {
app.source = source;
if (this.multiple) {
let selectedApps = this.modelValue.map(_app => {
if (app.name === _app.app) {
return {
app: app.name,
source
};
}
return _app;
});
this.$emit('update:modelValue', selectedApps);
} else {
this.$emit('update:modelValue', {
app: app.name,
source
});
}
}
},
computed: {
selectedAppsMap() {
if (!this.multiple) return {};
let out = {};
let selectedAppNames = this.modelValue.map(app => app.app);
for (let app of this.apps) {
out[app.name] = selectedAppNames.includes(app.name);
}
return out;
}
}
};
</script>