*: implement create project and project group

This commit is contained in:
Simone Gotti 2019-05-06 17:58:18 +02:00
parent e1ccccac71
commit 85406fad77
10 changed files with 521 additions and 20 deletions

View File

@ -0,0 +1,109 @@
<template>
<div>
<h4 class="title is-4">Create Project</h4>
<div class="field">
<div class="control">
<input class="input" type="text" placeholder="Project name" v-model="projectName">
</div>
</div>
<h4 class="title is-4">Available remote repositories</h4>
<div v-for="remoteSource in remoteSources" v-bind:key="remoteSource.id">
<h5 class="title is-5">Remote source: {{remoteSource.name}}</h5>
<remoterepos
:remotesource="remoteSource.id"
v-on:reposelected="repoSelected(remoteSource, $event)"
/>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" @click="createProject()">Create Project</button>
</div>
<div class="control">
<button class="button is-text">Cancel</button>
</div>
</div>
</div>
</template>
<script>
import {
fetchCurrentUser,
fetchRemoteSources,
createProject
} from "@/util/data.js";
import { projectLink } from "@/util/link.js";
import remoterepos from "@/components/remoterepos.vue";
export default {
components: { remoterepos },
name: "createproject",
props: {
ownertype: String,
ownername: String,
projectgroupref: Array
},
data() {
return {
user: null,
remoteSources: null,
remoteRepos: [],
projectName: null,
remoteRepoPath: null,
selectedRemoteSource: null
};
},
methods: {
repoSelected(remoteSource, repoPath) {
this.selectedRemoteSource = remoteSource;
this.remoteRepoPath = repoPath;
},
async createProject() {
let refArray = [this.ownertype, this.ownername];
if (this.projectgroupref) {
refArray = [...refArray, ...this.projectgroupref];
}
let parentref = refArray.join("/");
await createProject(
parentref,
this.projectName,
this.selectedRemoteSource.name,
this.remoteRepoPath
);
let projectref = [this.projectName];
if (this.projectgroupref) {
projectref = this.projectgroupref.concat(this.projectName);
}
this.$router.push(
projectLink(this.ownertype, this.ownername, projectref)
);
}
},
created: async function() {
this.user = await fetchCurrentUser();
// TODO(sgotti) filter only remote source where the user has a linked account
this.remoteSources = await fetchRemoteSources();
}
};
</script>
<style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
cursor: pointer;
display: flex;
padding: 10px;
}
.name {
font-weight: bold;
}
}
</style>

View File

@ -0,0 +1,64 @@
<template>
<div>
<div class="field has-addons is-pulled-rigth">
<p class="control">
<button class="button" @click="clicked">{{ buttonValue }}</button>
</p>
<div class="control">
<div class="dropdown is-right" v-bind:class="{ 'is-active': dropdownActive }">
<div class="dropdown-trigger">
<button class="button" @click="toggleDropdown()">
<span class="icon is-small">
<i class="mdi mdi-chevron-down"></i>
</span>
</button>
</div>
<div class="dropdown-menu" role="menu">
<div class="dropdown-content">
<a href="#" class="dropdown-item" @click="setButton('project')">New Project</a>
<a href="#" class="dropdown-item" @click="setButton('projectgroup')">New Project Group</a>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
components: {},
name: "createprojectbutton",
props: {},
data() {
return {
dropdownActive: false,
type: "project"
};
},
computed: {
buttonValue: function() {
if (this.type == "project") {
return "New Project";
}
return "New Project Group";
}
},
methods: {
toggleDropdown() {
this.dropdownActive = !this.dropdownActive;
},
setButton(type) {
this.type = type;
this.dropdownActive = false;
},
clicked() {
this.$emit("click", this.type);
}
}
};
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,84 @@
<template>
<div>
<h4 class="title is-4">Create Project Group</h4>
<div class="field">
<div class="control">
<input
class="input"
type="text"
placeholder="Project Group Name"
v-model="projectGroupName"
>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" @click="createProjectGroup()">Create Project Group</button>
</div>
<div class="control">
<button class="button is-text">Cancel</button>
</div>
</div>
</div>
</template>
<script>
import { createProjectGroup } from "@/util/data.js";
import { projectGroupLink } from "@/util/link.js";
import remoterepos from "@/components/remoterepos.vue";
export default {
components: {},
name: "createprojectgroup",
props: {
ownertype: String,
ownername: String,
projectgroupref: Array
},
data() {
return {
projectGroupName: null
};
},
methods: {
async createProjectGroup() {
let refArray = [this.ownertype, this.ownername];
if (this.projectgroupref) {
refArray = [...refArray, ...this.projectgroupref];
}
let parentref = refArray.join("/");
await createProjectGroup(parentref, this.projectGroupName);
let projectgroupref = [this.projectGroupName];
if (this.projectgroupref) {
projectgroupref = this.projectgroupref.concat(this.projectGroupName);
}
this.$router.push(
projectGroupLink(this.ownertype, this.ownername, projectgroupref)
);
}
}
};
</script>
<style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
cursor: pointer;
display: flex;
padding: 10px;
}
.name {
font-weight: bold;
}
}
</style>

View File

@ -0,0 +1,66 @@
<template>
<div>
<div v-if="remoterepos.length > 0">
<div
class="item-list"
v-for="(repo, index) in remoterepos"
v-bind:key="repo.id"
@click="select(index)"
>
<span class="icon has-text-success">
<i v-if="selectedrepo == index" class="mdi mdi-radiobox-marked"></i>
<i v-else class="mdi mdi-radiobox-blank"></i>
</span>
<span class="name">{{repo.path}}</span>
</div>
</div>
<div v-else class="item-list">No remote repositories</div>
</div>
</template>
<script>
import { userRemoteRepos } from "@/util/data.js";
export default {
components: {},
name: "remoterepos",
props: {
remotesource: String
},
data() {
return {
selectedrepo: null,
remoterepos: []
};
},
methods: {
select(index) {
this.selectedrepo = index;
this.$emit("reposelected", this.remoterepos[index].path);
},
async fetchRemoteRepos(remotesource) {
this.remoterepos = await userRemoteRepos(remotesource);
}
},
created: function() {
this.fetchRemoteRepos(this.remotesource);
}
};
</script>
<style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
cursor: pointer;
display: flex;
padding: 10px;
}
.name {
font-weight: bold;
}
}
</style>

View File

@ -9,6 +9,8 @@ import usersettings from "./components/usersettings.vue";
import projects from "./components/projects.vue";
import projectsettings from "./components/projectsettings.vue";
import projectgroupsettings from "./components/projectgroupsettings.vue";
import createproject from "./components/createproject.vue";
import createprojectgroup from "./components/createprojectgroup.vue";
import runs from "./components/runs.vue";
import run from "./components/run.vue";
import task from "./components/task.vue";
@ -90,6 +92,18 @@ export default new VueRouter({
component: usersettings,
props: (route) => ({ username: route.params.username }),
},
{
path: "createprojectgroup",
name: "user create project group",
component: createprojectgroup,
props: (route) => ({ ownertype: "user", ownername: route.params.username })
},
{
path: "createproject",
name: "user create project",
component: createproject,
props: (route) => ({ ownertype: "user", ownername: route.params.username })
},
]
},
{
@ -171,6 +185,18 @@ export default new VueRouter({
component: projectgroupsettings,
props: (route) => ({ ownertype: "user", ownername: route.params.username, projectgroupref: parseRef(route.params.projectgroupref) })
},
{
path: "createprojectgroup",
name: "user project group create project group",
component: createprojectgroup,
props: (route) => ({ ownertype: "user", ownername: route.params.username, projectgroupref: parseRef(route.params.projectgroupref) })
},
{
path: "createproject",
name: "user project group create project",
component: createproject,
props: (route) => ({ ownertype: "user", ownername: route.params.username, projectgroupref: parseRef(route.params.projectgroupref) })
},
]
},
@ -191,6 +217,18 @@ export default new VueRouter({
component: projects,
props: (route) => ({ ownertype: "org", ownername: route.params.orgname })
},
{
path: "createprojectgroup",
name: "org create project group",
component: createprojectgroup,
props: (route) => ({ ownertype: "org", ownername: route.params.orgname })
},
{
path: "createproject",
name: "org create project",
component: createproject,
props: (route) => ({ ownertype: "org", ownername: route.params.orgname })
},
]
},
@ -273,6 +311,18 @@ export default new VueRouter({
component: projectgroupsettings,
props: (route) => ({ ownertype: "org", ownername: route.params.orgname, projectgroupref: parseRef(route.params.projectgroupref) })
},
{
path: "createprojectgroup",
name: "org project group create project group",
component: createprojectgroup,
props: (route) => ({ ownertype: "org", ownername: route.params.orgname, projectgroupref: parseRef(route.params.projectgroupref) })
},
{
path: "createproject",
name: "org project group create project",
component: createproject,
props: (route) => ({ ownertype: "org", ownername: route.params.orgname, projectgroupref: parseRef(route.params.projectgroupref) })
},
]
},
]

View File

@ -113,4 +113,40 @@ export async function fetchRemoteSources() {
let path = "/remotesources"
let res = await fetch(apiurl(path));
return res.json();
}
export async function userRemoteRepos(remotesourceid) {
let path = "/user/remoterepos/" + remotesourceid
let res = await fetch(apiurl(path));
return res.json();
}
export async function createProjectGroup(parentref, name) {
let path = "/projectgroups"
let init = {
method: "POST",
body: JSON.stringify({
name: name,
parent_ref: parentref,
visibility: "public",
})
}
let res = await fetch(apiurl(path), init)
return res.json();
}
export async function createProject(parentref, name, remotesourcename, remoterepopath) {
let path = "/projects"
let init = {
method: "POST",
body: JSON.stringify({
name: name,
parent_ref: parentref,
visibility: "public",
remote_source_name: remotesourcename,
repo_path: remoterepopath,
})
}
let res = await fetch(apiurl(path), init)
return res.json();
}

View File

@ -39,14 +39,31 @@ export function userLocalRunTaskLink(username, runid, taskid) {
// Note, when creating a router link containing a project/projectgroup ref (a
// path), unfortunately, we cannot use route name and params since it will path
// escape it
export function projectGroupPath(ownertype, ownername, projectgroupref) {
let path = `/${ownertype}/${ownername}`
if (Array.isArray(projectgroupref) && projectgroupref.length) {
let projectgrouppath = (projectgroupref.join("/") + ".proj")
path = `${path}/projectgroups/${projectgrouppath}`
}
return path
}
export function projectPath(ownertype, ownername, projectref) {
let path = `/${ownertype}/${ownername}`
if (Array.isArray(projectref) && projectref.length) {
let projectpath = (projectref.join("/") + ".proj")
path = `${path}/projects/${projectpath}`
}
return path
}
export function projectGroupLink(ownertype, ownername, projectgroupref) {
let projectgrouppath = (projectgroupref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projectgroups/${projectgrouppath}`, }
return { path: projectGroupPath(ownertype, ownername, projectgroupref) }
}
export function projectGroupProjectsLink(ownertype, ownername, projectgroupref) {
let projectgrouppath = (projectgroupref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projectgroups/${projectgrouppath}/projects`, }
return { path: `/${ownertype}/${ownername}/projectgroups/${projectgrouppath}/projects` }
}
export function projectLink(ownertype, ownername, projectref) {
@ -61,35 +78,45 @@ export function projectRunsLink(ownertype, ownername, projectref) {
export function projectBranchesRunsLink(ownertype, ownername, projectref) {
let projectpath = (projectref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/branches`, }
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/branches` }
}
export function projectTagsRunsLink(ownertype, ownername, projectref) {
let projectpath = (projectref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/tags`, }
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/tags` }
}
export function projectPRsRunsLink(ownertype, ownername, projectref) {
let projectpath = (projectref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/pullrequests`, }
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/pullrequests` }
}
export function projectRunLink(ownertype, ownername, projectref, runid) {
let projectpath = (projectref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/runs/${runid}`, }
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/runs/${runid}` }
}
export function projectRunTaskLink(ownertype, ownername, projectref, runid, taskid) {
let projectpath = (projectref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/runs/${runid}/tasks/${taskid}`, }
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/runs/${runid}/tasks/${taskid}` }
}
export function projectGroupSettingsLink(ownertype, ownername, projectgroupref) {
let projectgrouppath = (projectgroupref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projectgroups/${projectgrouppath}/settings`, }
return { path: `/${ownertype}/${ownername}/projectgroups/${projectgrouppath}/settings` }
}
export function projectSettingsLink(ownertype, ownername, projectref) {
let projectpath = (projectref.join("/") + ".proj")
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/settings`, }
return { path: `/${ownertype}/${ownername}/projects/${projectpath}/settings` }
}
export function projectGroupCreateProjectGroupLink(ownertype, ownername, projectgroupref) {
let path = projectGroupPath(ownertype, ownername, projectgroupref)
return { path: `${path}/createprojectgroup` }
}
export function projectGroupCreateProjectLink(ownertype, ownername, projectgroupref) {
let path = projectGroupPath(ownertype, ownername, projectgroupref)
return { path: `${path}/createproject` }
}

View File

@ -13,6 +13,9 @@
<div class="name">
<span class="is-size-3">{{orgname}}</span>
<div class="is-pulled-right">
<createprojectbutton v-on:click="goToCreate($event)"/>
</div>
</div>
<div class="tabs">
@ -46,19 +49,34 @@
import {
ownerLink,
ownerProjectsLink,
ownerSettingsLink
ownerSettingsLink,
projectGroupCreateProjectGroupLink,
projectGroupCreateProjectLink
} from "@/util/link.js";
import createprojectbutton from "@/components/createprojectbutton.vue";
export default {
name: "Org",
components: {},
components: { createprojectbutton },
props: {
orgname: String
},
methods: {
ownerLink: ownerLink,
ownerProjectsLink: ownerProjectsLink,
ownerSettingsLink: ownerSettingsLink
ownerSettingsLink: ownerSettingsLink,
projectGroupCreateProjectGroupLink: projectGroupCreateProjectGroupLink,
projectGroupCreateProjectLink: projectGroupCreateProjectLink,
goToCreate(type) {
if (type == "project") {
this.$router.push(projectGroupCreateProjectLink("org", this.orgname));
return;
}
this.$router.push(
projectGroupCreateProjectGroupLink("org", this.orgname)
);
}
}
};
</script>

View File

@ -8,7 +8,10 @@
/>
<div class="name">
<span class="is-size-3">{{projectgroupref[projectgroupref.length-1]}}</span>
<span class="is-size-3">{{projectGroupName()}}</span>
<div class="is-pulled-right">
<createprojectbutton v-on:click="goToCreate($event)"/>
</div>
</div>
<div class="tabs">
@ -43,16 +46,19 @@
<script>
import {
projectGroupProjectsLink,
projectGroupSettingsLink
projectGroupSettingsLink,
projectGroupCreateProjectGroupLink,
projectGroupCreateProjectLink
} from "@/util/link.js";
import { fetchRun } from "@/util/data.js";
import projbreadcrumbs from "@/components/projbreadcrumbs.vue";
import createprojectbutton from "@/components/createprojectbutton.vue";
export default {
name: "ProjectGroup",
components: { projbreadcrumbs },
components: { projbreadcrumbs, createprojectbutton },
props: {
ownertype: String,
ownername: String,
@ -72,7 +78,31 @@ export default {
},
methods: {
projectGroupProjectsLink: projectGroupProjectsLink,
projectGroupSettingsLink: projectGroupSettingsLink
projectGroupSettingsLink: projectGroupSettingsLink,
projectGroupCreateProjectGroupLink: projectGroupCreateProjectGroupLink,
projectGroupCreateProjectLink: projectGroupCreateProjectLink,
projectGroupName() {
return this.projectgroupref[this.projectgroupref.length - 1];
},
goToCreate(type) {
if (type == "project") {
this.$router.push(
projectGroupCreateProjectLink(
this.ownertype,
this.ownername,
this.projectgroupref
)
);
return;
}
this.$router.push(
projectGroupCreateProjectGroupLink(
this.ownertype,
this.ownername,
this.projectgroupref
)
);
}
},
created: async function() {
if (this.$route.params.runid) {

View File

@ -13,6 +13,9 @@
<div class="name">
<span class="is-size-3">{{username}}</span>
<div class="is-pulled-right">
<createprojectbutton v-on:click="goToCreate($event)"/>
</div>
</div>
<div class="tabs">
@ -90,16 +93,19 @@ import {
userLocalRunsLink,
userLocalRunLink,
userLocalRunTaskLink,
ownerSettingsLink
ownerSettingsLink,
projectGroupCreateProjectGroupLink,
projectGroupCreateProjectLink
} from "@/util/link.js";
import { fetchRun } from "@/util/data.js";
import createprojectbutton from "@/components/createprojectbutton.vue";
import tabarrow from "@/components/tabarrow.vue";
export default {
name: "User",
components: { tabarrow },
components: { createprojectbutton, tabarrow },
props: {
username: String
},
@ -121,7 +127,18 @@ export default {
userLocalRunsLink: userLocalRunsLink,
userLocalRunLink: userLocalRunLink,
userLocalRunTaskLink: userLocalRunTaskLink,
ownerSettingsLink: ownerSettingsLink
ownerSettingsLink: ownerSettingsLink,
projectGroupCreateProjectGroupLink: projectGroupCreateProjectGroupLink,
projectGroupCreateProjectLink: projectGroupCreateProjectLink,
goToCreate(type) {
if (type == "project") {
this.$router.push(projectGroupCreateProjectLink("user", this.username));
return;
}
this.$router.push(
projectGroupCreateProjectGroupLink("user", this.username)
);
}
}
};
</script>