createproject: improve remote repos selection

Use a select to choose the remote source and fetch remote repos only for that
remote source
This commit is contained in:
Simone Gotti 2019-05-21 17:43:15 +02:00
parent 5b13083861
commit 26d5247846
2 changed files with 80 additions and 49 deletions

View File

@ -15,27 +15,49 @@
</label> </label>
</div> </div>
<h4 class="text-xl">Available remote repositories</h4> <div class="mb-3 flex items-center">
<div v-for="remoteSource in remoteSources" v-bind:key="remoteSource.id"> <div class="flex relative w-64">
<remoterepos <select
class="remoterepos" class="block appearance-none w-full bg-white border border-gray-400 hover:border-gray-500 px-4 py-2 pr-8 rounded shadow leading-tight focus:outline-none focus:shadow-outline"
:remotesource="remoteSource" v-model="selectedRemoteSourceIndex"
:selected="selectedRemoteSource && selectedRemoteSource.id == remoteSource.id" >
v-on:reposelected="repoSelected(remoteSource, $event)" <option :value="null" disabled>Select the remote source</option>
/> <option
v-for="(rs, index) in remoteSources"
v-bind:key="rs.id"
:value="index"
>{{ rs.name }}</option>
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"></path>
</svg>
</div>
</div>
<button
class="ml-3 btn btn-blue"
v-bind:class="{ 'spinner': fetchRemoteReposLoading }"
:disabled="selectedRemoteSourceIndex == null"
@click="fetchRemoteRepos()"
>Fetch remote repositories</button>
</div> </div>
<button
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" <div v-if="remoteRepos.length">
v-bind:class="{ 'spinner': createProjectLoading }" <h4 class="text-xl">Available remote repositories</h4>
:disabled="!createProjectButtonEnabled" <remoterepos :remoterepos="remoteRepos" v-on:reposelected="repoSelected($event)"/>
@click="createProject()" <button
>Create Project</button> class="btn btn-blue"
<div v-bind:class="{ 'spinner': createProjectLoading }"
v-if="createProjectError" :disabled="!createProjectButtonEnabled"
class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" @click="createProject()"
role="alert" >Create Project</button>
> <div
<span class="block sm:inline">{{ createProjectError }}</span> v-if="createProjectError"
class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<span class="block sm:inline">{{ createProjectError }}</span>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -44,7 +66,8 @@
import { import {
fetchCurrentUser, fetchCurrentUser,
fetchRemoteSources, fetchRemoteSources,
createProject createProject,
userRemoteRepos
} from "@/util/data.js"; } from "@/util/data.js";
import { projectLink } from "@/util/link.js"; import { projectLink } from "@/util/link.js";
@ -62,26 +85,38 @@ export default {
data() { data() {
return { return {
createProjectError: null, createProjectError: null,
fetchRemoteReposLoading: false,
fetchRemoteReposLoadingTimeout: false,
createProjectLoading: false, createProjectLoading: false,
createProjectLoadingTimeout: null, createProjectLoadingTimeout: null,
user: null, user: null,
remoteSources: null, remoteSources: null,
remoteRepos: [], remoteRepos: [],
selectedRemoteSourceIndex: null,
projectName: "", projectName: "",
projectIsPrivate: false, projectIsPrivate: false,
remoteRepoPath: null, remoteRepoPath: null
selectedRemoteSource: null
}; };
}, },
computed: { computed: {
createProjectButtonEnabled: function() { createProjectButtonEnabled: function() {
return this.projectName.length && this.selectedRemoteSource; return this.projectName.length && this.remoteRepoPath;
} }
}, },
watch: {},
methods: { methods: {
resetErrors() { resetErrors() {
this.createProjectError = null; this.createProjectError = null;
}, },
startFetchRemoteReposLoading() {
this.fetchRemoteReposLoadingTimeout = setTimeout(() => {
this.fetchRemoteReposLoading = true;
}, 300);
},
stopFetchRemoteReposLoading() {
clearTimeout(this.fetchRemoteReposLoadingTimeout);
this.fetchRemoteReposLoading = false;
},
startProjectLoading() { startProjectLoading() {
this.createProjectLoadingTimeout = setTimeout(() => { this.createProjectLoadingTimeout = setTimeout(() => {
this.createProjectLoading = true; this.createProjectLoading = true;
@ -91,10 +126,23 @@ export default {
clearTimeout(this.createProjectLoadingTimeout); clearTimeout(this.createProjectLoadingTimeout);
this.createProjectLoading = false; this.createProjectLoading = false;
}, },
repoSelected(remoteSource, repoPath) { repoSelected(repoPath) {
this.selectedRemoteSource = remoteSource;
this.remoteRepoPath = repoPath; this.remoteRepoPath = repoPath;
}, },
async fetchRemoteRepos() {
this.remoteRepos = [];
this.remoteRepoPath = null;
this.startFetchRemoteReposLoading();
let remoteSource = this.remoteSources[this.selectedRemoteSourceIndex];
let { data, error } = await userRemoteRepos(remoteSource.id);
this.stopFetchRemoteReposLoading();
if (error) {
this.$store.dispatch("setError", error);
return;
}
this.remoteRepos = data;
},
async createProject() { async createProject() {
this.resetErrors(); this.resetErrors();
@ -109,12 +157,14 @@ export default {
visibility = "private"; visibility = "private";
} }
let remoteSource = this.remoteSources[this.selectedRemoteSourceIndex];
this.startProjectLoading(); this.startProjectLoading();
let { error } = await createProject( let { error } = await createProject(
parentref, parentref,
this.projectName, this.projectName,
visibility, visibility,
this.selectedRemoteSource.name, remoteSource.name,
this.remoteRepoPath this.remoteRepoPath
); );
this.stopProjectLoading(); this.stopProjectLoading();

View File

@ -1,9 +1,5 @@
<template> <template>
<div class="mb-2 border-solid border-gray-300 rounded border shadow-sm"> <div class="mb-2 border-solid border-gray-300 rounded border shadow-sm">
<p class="bg-gray-200 px-4 py-3 border-solid border-gray-300 border-b">
repositories from
<strong>{{ remotesource.name }}</strong>
</p>
<div v-if="remoterepos.length > 0"> <div v-if="remoterepos.length > 0">
<label <label
class="block px-4 py-2 border-b" class="block px-4 py-2 border-b"
@ -11,7 +7,7 @@
v-bind:key="repo.id" v-bind:key="repo.id"
@click="select(index)" @click="select(index)"
> >
<input type="radio" :checked="selectedrepo == index && selected"> <input type="radio" :checked="selectedrepo == index">
{{repo.path}} {{repo.path}}
</label> </label>
</div> </div>
@ -20,37 +16,22 @@
</template> </template>
<script> <script>
import { userRemoteRepos } from "@/util/data.js";
export default { export default {
components: {}, components: {},
name: "remoterepos", name: "remoterepos",
props: { props: {
remotesource: Object, remoterepos: Array
selected: Boolean
}, },
data() { data() {
return { return {
selectedrepo: null, selectedrepo: null
remoterepos: []
}; };
}, },
methods: { methods: {
select(index) { select(index) {
this.selectedrepo = index; this.selectedrepo = index;
this.$emit("reposelected", this.remoterepos[index].path); this.$emit("reposelected", this.remoterepos[index].path);
},
async fetchRemoteRepos(remotesourceid) {
let { data, error } = await userRemoteRepos(remotesourceid);
if (error) {
this.$store.dispatch("setError", error);
return;
}
this.remoterepos = data;
} }
},
created: function() {
this.fetchRemoteRepos(this.remotesource.id);
} }
}; };
</script> </script>