Hangar/frontend/components/modals/versions/DependencyTable.vue

205 lines
8.0 KiB
Vue
Raw Normal View History

2021-03-12 15:59:36 +08:00
<template>
<div>
<v-simple-table :key="`${platform}-deps-table`" class="ma-2">
<thead>
<tr>
<th>{{ $t('general.name') }}</th>
<th>{{ $t('general.required') }}</th>
<th>{{ $t('general.link') }}</th>
<th>{{ $t('general.delete') }}</th>
</tr>
</thead>
<tbody>
<tr v-for="dep in version.pluginDependencies[platform]" :key="`${platform}-${dep.name}`">
<td>{{ dep.name }}</td>
<!--TODO having ripple here produces console errors?-->
<td><v-simple-checkbox v-model="dep.required" :ripple="false" /></td>
<td>
<v-text-field
v-model.trim="dep.externalUrl"
dense
hide-details
:placeholder="$t('version.new.form.externalUrl')"
:disabled="dep.namespace !== null && Object.keys(dep.namespace).length !== 0"
:rules="
dep.namespace !== null && Object.keys(dep.namespace).length !== 0 ? [] : [$util.$vc.require('version.new.form.externalUrl')]
"
clearable
/>
<v-autocomplete
v-model="dep.namespace"
dense
hide-details
hide-no-data
:placeholder="$t('version.new.form.hangarProject')"
class="mb-2"
:items="results[dep.name]"
:item-text="getNamespace"
:item-value="getNamespace"
return-object
clearable
auto-select-first
:disabled="!!dep.externalUrl"
:rules="!!dep.externalUrl ? [] : [$util.$vc.require('version.new.form.hangarProject')]"
@update:search-input="onSearch($event, dep.name)"
/>
</td>
<td>
<v-btn icon color="error" @click="deleteDep(dep.name)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</td>
</tr>
<tr v-for="(newDep, index) in newDeps" :key="`newDep-${index}`">
<td>
<v-text-field
v-model.trim="newDep.name"
dense
hide-details
flat
:label="$t('general.name')"
:rules="[$util.$vc.require($t('general.name'))]"
/>
</td>
<td><v-simple-checkbox v-model="newDep.required" :ripple="false" /></td>
<td>
<v-text-field
v-model.trim="newDep.externalUrl"
dense
hide-details
:placeholder="$t('version.new.form.externalUrl')"
:disabled="newDep.namespace !== null && Object.keys(newDep.namespace).length !== 0"
:rules="
newDep.namespace !== null && Object.keys(newDep.namespace).length !== 0
? []
: [$util.$vc.require('version.new.form.externalUrl')]
"
clearable
/>
<v-autocomplete
v-model="newDep.namespace"
dense
hide-details
hide-no-data
:placeholder="$t('version.new.form.hangarProject')"
class="mb-2"
:items="newDepResults[index]"
:item-text="getNamespace"
:item-value="getNamespace"
return-object
clearable
auto-select-first
:disabled="!!newDep.externalUrl"
:rules="!!newDep.externalUrl ? [] : [$util.$vc.require('version.new.form.hangarProject')]"
@update:search-input="onNewDepSearch($event, index)"
/>
</td>
<td>
<v-btn icon color="error" @click="deleteNewDep(index)">
<v-icon>mdi-delete</v-icon>
</v-btn>
</td>
</tr>
</tbody>
</v-simple-table>
<v-btn block color="primary" @click="addNewDep">
<v-icon left>mdi-plus</v-icon>
{{ $t('general.add') }}
</v-btn>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'nuxt-property-decorator';
import { PropType } from 'vue';
import { DependencyVersion, PaginatedResult, PluginDependency, Project, ProjectNamespace } from 'hangar-api';
import { Platform } from '~/types/enums';
@Component
export default class DependencyTable extends Vue {
results: Record<string, ProjectNamespace[]> = {};
newDepResults: ProjectNamespace[][] = [];
newDeps: Partial<PluginDependency>[] = [];
@Prop({ type: Object as PropType<DependencyVersion>, required: true })
version!: DependencyVersion;
@Prop({ type: String as PropType<Platform>, required: true })
platform!: Platform;
addNewDep() {
this.newDeps.push({
name: undefined,
required: false,
namespace: null,
externalUrl: null,
});
this.newDepResults.push([]);
}
getNamespace(namespace: ProjectNamespace) {
return `${namespace.owner}/${namespace.slug}`;
}
onSearch(val: string, name: string) {
if (val) {
this.$api
.request<PaginatedResult<Project>>(`projects?relevance=true&limit=25&offset=0&q=${val}`)
.then((projects) => {
this.results[name].push(...projects.result.map((p) => p.namespace));
})
.catch(console.error);
}
}
deleteDep(name: string) {
this.$delete(
this.version.pluginDependencies[this.platform],
this.version.pluginDependencies[this.platform].findIndex((pd) => pd.name === name)
);
}
deleteNewDep(index: number) {
this.$delete(this.newDeps, index);
}
onNewDepSearch(val: string, index: number) {
if (val) {
this.$api
.request<PaginatedResult<Project>>(`projects?relevance=true&limit=25&offset=0&q=${val}`)
.then((projects) => {
this.newDepResults[index].push(...projects.result.map((p) => p.namespace));
})
.catch(console.error);
}
}
@Watch('newDepResults', { deep: true })
onFormChange() {
this.$emit('change');
}
@Watch('version', { deep: true })
onOtherFormChange() {
this.$emit('change');
}
reset() {
this.newDeps = [];
this.newDepResults = [];
this.results = {};
if (this.version.pluginDependencies[this.platform]) {
for (const dep of this.version.pluginDependencies[this.platform]) {
if (dep.namespace) {
this.results[dep.name] = [dep.namespace];
} else {
this.results[dep.name] = [];
}
}
}
}
}
</script>
<style lang="scss" scoped></style>