*: handle api errors
* Use a global error when fetching data * Use a local error message when calling a mutating api
This commit is contained in:
parent
98073502e2
commit
789d0f5fcd
42
src/App.vue
42
src/App.vue
|
@ -43,8 +43,27 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="main-container container">
|
|
||||||
<router-view></router-view>
|
<div v-if="error" class="container">
|
||||||
|
<div class="message is-danger global-error-message">
|
||||||
|
<div class="message-body">
|
||||||
|
<nav class="level">
|
||||||
|
<div class="level-left">
|
||||||
|
<div class="level-item">
|
||||||
|
<p>Failed to fetch data: {{ error }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-right">
|
||||||
|
<div class="level-item">
|
||||||
|
<button class="button is-danger" @click="reload()">Retry</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="main-container container">
|
||||||
|
<router-view v-if="routerActive"></router-view>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -57,7 +76,12 @@ export default {
|
||||||
name: "App",
|
name: "App",
|
||||||
components: {},
|
components: {},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["user"])
|
...mapGetters(["error", "user"])
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
routerActive: true
|
||||||
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
user: function(user) {
|
user: function(user) {
|
||||||
|
@ -68,6 +92,14 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// method to reload current view from https://github.com/vuejs/vue-router/issues/296#issuecomment-356530037
|
||||||
|
methods: {
|
||||||
|
reload() {
|
||||||
|
this.$store.dispatch("setError", null);
|
||||||
|
this.routerActive = false;
|
||||||
|
this.$nextTick(() => (this.routerActive = true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -78,4 +110,8 @@ export default {
|
||||||
.main-container {
|
.main-container {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.global-error-message {
|
||||||
|
margin-top: 10rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -19,9 +19,9 @@
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button class="button is-primary" @click="createProject()">Create Project</button>
|
<button class="button is-primary" @click="createProject()">Create Project</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
</div>
|
||||||
<button class="button is-text">Cancel</button>
|
<div v-if="createProjectError" class="message is-danger">
|
||||||
</div>
|
<div class="message-body">{{ createProjectError }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -47,6 +47,7 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
createProjectError: null,
|
||||||
user: null,
|
user: null,
|
||||||
remoteSources: null,
|
remoteSources: null,
|
||||||
remoteRepos: [],
|
remoteRepos: [],
|
||||||
|
@ -56,23 +57,32 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
resetErrors() {
|
||||||
|
this.createProjectError = null;
|
||||||
|
},
|
||||||
repoSelected(remoteSource, repoPath) {
|
repoSelected(remoteSource, repoPath) {
|
||||||
this.selectedRemoteSource = remoteSource;
|
this.selectedRemoteSource = remoteSource;
|
||||||
this.remoteRepoPath = repoPath;
|
this.remoteRepoPath = repoPath;
|
||||||
},
|
},
|
||||||
async createProject() {
|
async createProject() {
|
||||||
|
this.resetErrors();
|
||||||
|
|
||||||
let refArray = [this.ownertype, this.ownername];
|
let refArray = [this.ownertype, this.ownername];
|
||||||
if (this.projectgroupref) {
|
if (this.projectgroupref) {
|
||||||
refArray = [...refArray, ...this.projectgroupref];
|
refArray = [...refArray, ...this.projectgroupref];
|
||||||
}
|
}
|
||||||
let parentref = refArray.join("/");
|
let parentref = refArray.join("/");
|
||||||
|
|
||||||
await createProject(
|
let { error } = await createProject(
|
||||||
parentref,
|
parentref,
|
||||||
this.projectName,
|
this.projectName,
|
||||||
this.selectedRemoteSource.name,
|
this.selectedRemoteSource.name,
|
||||||
this.remoteRepoPath
|
this.remoteRepoPath
|
||||||
);
|
);
|
||||||
|
if (error) {
|
||||||
|
this.createProjectError = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let projectref = [this.projectName];
|
let projectref = [this.projectName];
|
||||||
if (this.projectgroupref) {
|
if (this.projectgroupref) {
|
||||||
|
@ -84,9 +94,20 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: async function() {
|
created: async function() {
|
||||||
this.user = await fetchCurrentUser();
|
let { data, error } = await fetchCurrentUser();
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.user = data;
|
||||||
|
|
||||||
// TODO(sgotti) filter only remote source where the user has a linked account
|
// TODO(sgotti) filter only remote source where the user has a linked account
|
||||||
this.remoteSources = await fetchRemoteSources();
|
({ data, error } = await fetchRemoteSources());
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.remoteSources = data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button class="button is-primary" @click="createProjectGroup()">Create Project Group</button>
|
<button class="button is-primary" @click="createProjectGroup()">Create Project Group</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
</div>
|
||||||
<button class="button is-text">Cancel</button>
|
<div v-if="createProjectGroupError" class="message is-danger">
|
||||||
</div>
|
<div class="message-body">{{ createProjectGroupError }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -27,8 +27,6 @@ import { createProjectGroup } from "@/util/data.js";
|
||||||
|
|
||||||
import { projectGroupLink } from "@/util/link.js";
|
import { projectGroupLink } from "@/util/link.js";
|
||||||
|
|
||||||
import remoterepos from "@/components/remoterepos.vue";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
components: {},
|
||||||
name: "createprojectgroup",
|
name: "createprojectgroup",
|
||||||
|
@ -39,18 +37,31 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
createProjectGroupError: null,
|
||||||
projectGroupName: null
|
projectGroupName: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
resetErrors() {
|
||||||
|
this.createProjectGroupError = null;
|
||||||
|
},
|
||||||
async createProjectGroup() {
|
async createProjectGroup() {
|
||||||
|
this.resetErrors();
|
||||||
|
|
||||||
let refArray = [this.ownertype, this.ownername];
|
let refArray = [this.ownertype, this.ownername];
|
||||||
if (this.projectgroupref) {
|
if (this.projectgroupref) {
|
||||||
refArray = [...refArray, ...this.projectgroupref];
|
refArray = [...refArray, ...this.projectgroupref];
|
||||||
}
|
}
|
||||||
let parentref = refArray.join("/");
|
let parentref = refArray.join("/");
|
||||||
|
|
||||||
await createProjectGroup(parentref, this.projectGroupName);
|
let { error } = await createProjectGroup(
|
||||||
|
parentref,
|
||||||
|
this.projectGroupName
|
||||||
|
);
|
||||||
|
if (error) {
|
||||||
|
this.createProjectGroupError = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let projectgroupref = [this.projectGroupName];
|
let projectgroupref = [this.projectGroupName];
|
||||||
if (this.projectgroupref) {
|
if (this.projectgroupref) {
|
||||||
|
|
|
@ -42,6 +42,9 @@
|
||||||
>Delete Project Group</button>
|
>Delete Project Group</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="deleteProjectGroupError" class="message is-danger">
|
||||||
|
<div class="message-body">{{ deleteProjectGroupError }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,6 +67,7 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
deleteProjectGroupError: null,
|
||||||
variables: [],
|
variables: [],
|
||||||
allvariables: [],
|
allvariables: [],
|
||||||
projectGroupNameToDelete: ""
|
projectGroupNameToDelete: ""
|
||||||
|
@ -83,6 +87,9 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
resetErrors() {
|
||||||
|
this.deleteProjectGroupError = null;
|
||||||
|
},
|
||||||
async deleteProjectGroup() {
|
async deleteProjectGroup() {
|
||||||
let projectgroupref = [
|
let projectgroupref = [
|
||||||
this.ownertype,
|
this.ownertype,
|
||||||
|
@ -91,7 +98,11 @@ export default {
|
||||||
].join("/");
|
].join("/");
|
||||||
|
|
||||||
if (this.projectGroupNameToDelete == this.projectGroupName) {
|
if (this.projectGroupNameToDelete == this.projectGroupName) {
|
||||||
let res = await deleteProjectGroup(projectgroupref);
|
let { error } = await deleteProjectGroup(projectgroupref);
|
||||||
|
if (error) {
|
||||||
|
this.deleteProjectGroupError = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$router.push(
|
this.$router.push(
|
||||||
projectGroupLink(
|
projectGroupLink(
|
||||||
this.ownertype,
|
this.ownertype,
|
||||||
|
@ -103,16 +114,33 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: async function() {
|
created: async function() {
|
||||||
this.variables = await fetchVariables(
|
let projectgroupref = [
|
||||||
|
this.ownertype,
|
||||||
|
this.ownername,
|
||||||
|
...this.projectgroupref
|
||||||
|
].join("/");
|
||||||
|
|
||||||
|
let { data, error } = await fetchVariables(
|
||||||
"projectgroup",
|
"projectgroup",
|
||||||
[this.ownertype, this.ownername, ...this.projectgroupref].join("/"),
|
projectgroupref,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
this.allvariables = await fetchVariables(
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.variables = data;
|
||||||
|
|
||||||
|
({ data, error } = await fetchVariables(
|
||||||
"projectgroup",
|
"projectgroup",
|
||||||
[this.ownertype, this.ownername, ...this.projectgroupref].join("/"),
|
projectgroupref,
|
||||||
true
|
true
|
||||||
);
|
));
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.allvariables = data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -32,7 +32,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { apiurl, fetch } from "@/util/auth";
|
import {
|
||||||
|
fetchProjectGroupProjects,
|
||||||
|
fetchProjectGroupSubgroups
|
||||||
|
} from "@/util/data.js";
|
||||||
|
|
||||||
import { projectLink, projectGroupLink } from "@/util/link.js";
|
import { projectLink, projectGroupLink } from "@/util/link.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -66,24 +70,33 @@ export default {
|
||||||
return ref;
|
return ref;
|
||||||
},
|
},
|
||||||
async fetchProjects(ownertype, ownername) {
|
async fetchProjects(ownertype, ownername) {
|
||||||
let ref = [ownertype, ownername];
|
let projectgroupref = [ownertype, ownername];
|
||||||
if (this.projectgroupref) {
|
if (this.projectgroupref) {
|
||||||
ref.push(...this.projectgroupref);
|
projectgroupref.push(...this.projectgroupref);
|
||||||
}
|
}
|
||||||
let path = "/projectgroups/" + encodeURIComponent(ref.join("/"));
|
|
||||||
path += "/projects";
|
let { data, error } = await fetchProjectGroupProjects(
|
||||||
let res = await (await fetch(apiurl(path))).json();
|
projectgroupref.join("/")
|
||||||
this.projects = res;
|
);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.projects = data;
|
||||||
},
|
},
|
||||||
async fetchProjectGroups(ownertype, ownername) {
|
async fetchProjectGroups(ownertype, ownername) {
|
||||||
let ref = [ownertype, ownername];
|
let projectgroupref = [ownertype, ownername];
|
||||||
if (this.projectgroupref) {
|
if (this.projectgroupref) {
|
||||||
ref.push(...this.projectgroupref);
|
projectgroupref.push(...this.projectgroupref);
|
||||||
}
|
}
|
||||||
let path = "/projectgroups/" + encodeURIComponent(ref.join("/"));
|
let { data, error } = await fetchProjectGroupSubgroups(
|
||||||
path += "/subgroups";
|
projectgroupref.join("/")
|
||||||
let res = await (await fetch(apiurl(path))).json();
|
);
|
||||||
this.projectgroups = res;
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.projectgroups = data;
|
||||||
},
|
},
|
||||||
projectLink: projectLink,
|
projectLink: projectLink,
|
||||||
projectGroupLink: projectGroupLink
|
projectGroupLink: projectGroupLink
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
<button class="button is-primary" @click="updateProject()">Update</button>
|
<button class="button is-primary" @click="updateProject()">Update</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="updateProjectError" class="message is-danger">
|
||||||
|
<div class="message-body">{{ updateProjectError }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<nav class="panel">
|
<nav class="panel">
|
||||||
|
@ -64,6 +68,10 @@
|
||||||
@click="deleteProject()"
|
@click="deleteProject()"
|
||||||
:disabled="!deleteButtonEnabled"
|
:disabled="!deleteButtonEnabled"
|
||||||
>Delete Project</button>
|
>Delete Project</button>
|
||||||
|
|
||||||
|
<div v-if="deleteProjectError" class="message is-danger">
|
||||||
|
<div class="message-body">{{ deleteProjectError }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -92,6 +100,8 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
updateProjectError: null,
|
||||||
|
deleteProjectError: null,
|
||||||
project: null,
|
project: null,
|
||||||
projectIsPrivate: false,
|
projectIsPrivate: false,
|
||||||
variables: [],
|
variables: [],
|
||||||
|
@ -111,7 +121,13 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
resetErrors() {
|
||||||
|
this.updateProjectError = null;
|
||||||
|
this.deleteProjectError = null;
|
||||||
|
},
|
||||||
async updateProject() {
|
async updateProject() {
|
||||||
|
this.resetErrors();
|
||||||
|
|
||||||
let projectref = [
|
let projectref = [
|
||||||
this.ownertype,
|
this.ownertype,
|
||||||
this.ownername,
|
this.ownername,
|
||||||
|
@ -122,9 +138,19 @@ export default {
|
||||||
if (this.projectIsPrivate) {
|
if (this.projectIsPrivate) {
|
||||||
visibility = "private";
|
visibility = "private";
|
||||||
}
|
}
|
||||||
let res = await updateProject(projectref, this.project.name, visibility);
|
let { error } = await updateProject(
|
||||||
|
projectref,
|
||||||
|
this.project.name,
|
||||||
|
visibility
|
||||||
|
);
|
||||||
|
if (error) {
|
||||||
|
this.updateProjectError = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async deleteProject() {
|
async deleteProject() {
|
||||||
|
this.resetErrors();
|
||||||
|
|
||||||
let projectref = [
|
let projectref = [
|
||||||
this.ownertype,
|
this.ownertype,
|
||||||
this.ownername,
|
this.ownername,
|
||||||
|
@ -132,7 +158,11 @@ export default {
|
||||||
].join("/");
|
].join("/");
|
||||||
|
|
||||||
if (this.projectNameToDelete == this.projectName) {
|
if (this.projectNameToDelete == this.projectName) {
|
||||||
let res = await deleteProject(projectref);
|
let { error } = await deleteProject(projectref);
|
||||||
|
if (error) {
|
||||||
|
this.deleteProjectError = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.$router.push(
|
this.$router.push(
|
||||||
projectGroupLink(
|
projectGroupLink(
|
||||||
this.ownertype,
|
this.ownertype,
|
||||||
|
@ -148,19 +178,27 @@ export default {
|
||||||
"/"
|
"/"
|
||||||
);
|
);
|
||||||
|
|
||||||
this.project = await fetchProject(projectref);
|
let { data, error } = await fetchProject(projectref);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.project = data;
|
||||||
this.projectIsPrivate = this.project.visibility == "private";
|
this.projectIsPrivate = this.project.visibility == "private";
|
||||||
|
|
||||||
this.variables = await fetchVariables(
|
({ data, error } = await fetchVariables("project", projectref, false));
|
||||||
"project",
|
if (error) {
|
||||||
[this.ownertype, this.ownername, ...this.projectref].join("/"),
|
this.$store.dispatch("setError", error);
|
||||||
false
|
return;
|
||||||
);
|
}
|
||||||
this.allvariables = await fetchVariables(
|
this.variables = data;
|
||||||
"project",
|
|
||||||
[this.ownertype, this.ownername, ...this.projectref].join("/"),
|
({ data, error } = await fetchVariables("project", projectref, true));
|
||||||
true
|
if (error) {
|
||||||
);
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.allvariables = data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -43,7 +43,12 @@ export default {
|
||||||
this.$emit("reposelected", this.remoterepos[index].path);
|
this.$emit("reposelected", this.remoterepos[index].path);
|
||||||
},
|
},
|
||||||
async fetchRemoteRepos(remotesourceid) {
|
async fetchRemoteRepos(remotesourceid) {
|
||||||
this.remoterepos = await userRemoteRepos(remotesourceid);
|
let { data, error } = await userRemoteRepos(remotesourceid);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.remoterepos = data;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: function() {
|
created: function() {
|
||||||
|
|
|
@ -101,7 +101,13 @@ export default {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
},
|
},
|
||||||
async fetchRun() {
|
async fetchRun() {
|
||||||
this.run = await fetchRun(this.runid);
|
let { data, error } = await fetchRun(this.runid);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.run = data;
|
||||||
|
|
||||||
// sort tasks by level
|
// sort tasks by level
|
||||||
let tasks = this.run.tasks;
|
let tasks = this.run.tasks;
|
||||||
let sortedTasks = Object.keys(this.run.tasks)
|
let sortedTasks = Object.keys(this.run.tasks)
|
||||||
|
|
|
@ -67,8 +67,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { apiurl, fetch } from "@/util/auth";
|
import { fetchUser, fetchProject, fetchRuns } from "@/util/data.js";
|
||||||
import { fetchProject, fetchRuns } from "@/util/data.js";
|
|
||||||
import { userLocalRunLink, projectRunLink } from "@/util/link.js";
|
import { userLocalRunLink, projectRunLink } from "@/util/link.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -127,15 +126,28 @@ export default {
|
||||||
this.pollData();
|
this.pollData();
|
||||||
},
|
},
|
||||||
async fetchProject() {
|
async fetchProject() {
|
||||||
this.project = await fetchProject(
|
let projectref = [
|
||||||
[this.ownertype, this.ownername, ...this.projectref].join("/")
|
this.ownertype,
|
||||||
);
|
this.ownername,
|
||||||
|
...this.projectref
|
||||||
|
].join("/");
|
||||||
|
|
||||||
|
let { data, error } = await fetchProject(projectref);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.project = data;
|
||||||
|
|
||||||
this.fetchRuns();
|
this.fetchRuns();
|
||||||
},
|
},
|
||||||
async fetchUser() {
|
async fetchUser() {
|
||||||
let res = await (await fetch(apiurl("/users/" + this.username))).json();
|
let { data, error } = await fetchUser(this.username);
|
||||||
this.user = res;
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.user = data;
|
||||||
|
|
||||||
this.fetchRuns();
|
this.fetchRuns();
|
||||||
},
|
},
|
||||||
|
@ -159,7 +171,12 @@ export default {
|
||||||
group = "/user/" + this.user.id;
|
group = "/user/" + this.user.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.runs = await fetchRuns(group, lastrun);
|
let { data, error } = await fetchRuns(group, lastrun);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.runs = data;
|
||||||
},
|
},
|
||||||
pollData() {
|
pollData() {
|
||||||
clearInterval(this.polling);
|
clearInterval(this.polling);
|
||||||
|
|
|
@ -63,10 +63,20 @@ export default {
|
||||||
return "unknown";
|
return "unknown";
|
||||||
},
|
},
|
||||||
async fetchRun() {
|
async fetchRun() {
|
||||||
this.run = await fetchRun(this.runid);
|
let { data, error } = await fetchRun(this.runid);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.run = data;
|
||||||
},
|
},
|
||||||
async fetchTask() {
|
async fetchTask() {
|
||||||
this.task = await fetchTask(this.runid, this.taskid);
|
let { data, error } = await fetchTask(this.runid, this.taskid);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.task = data;
|
||||||
},
|
},
|
||||||
pollData() {
|
pollData() {
|
||||||
this.polling = setInterval(() => {
|
this.polling = setInterval(() => {
|
||||||
|
|
|
@ -10,26 +10,33 @@
|
||||||
<button class="button is-primary" @click="deleteUserToken(token)">Delete</button>
|
<button class="button is-primary" @click="deleteUserToken(token)">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="deleteUserTokenError" class="message is-danger">
|
||||||
|
<div class="message-body">{{ deleteUserTokenError }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="item-list">No user tokens</div>
|
<div v-else>No user tokens</div>
|
||||||
<hr>
|
<hr>
|
||||||
<div v-if="token" class="notification is-success">
|
<div v-if="token" class="notification is-success">
|
||||||
<button class="delete" @click="closeNewTokenNotification()"></button>
|
<button class="delete" @click="closeNewTokenNotification()"></button>
|
||||||
User token created: {{token}}
|
User token created: {{token}}
|
||||||
</div>
|
</div>
|
||||||
<h4 class="title is-4">Create new User Token</h4>
|
<h5 class="title is-5">Create new User Token</h5>
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input class="input is-primary" type="text" placeholder="Token name" v-model="newtokenname">
|
<input class="input is-primary" type="text" placeholder="Token name" v-model="newtokenname">
|
||||||
</div>
|
</div>
|
||||||
<button class="button is-primary" @click="createUserToken()">Create Token</button>
|
<button class="button is-primary" @click="createUserToken()">Create Token</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="createUserTokenError" class="message is-danger">
|
||||||
|
<div class="message-body">{{ createUserTokenError }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
fetchCurrentUser,
|
fetchCurrentUser,
|
||||||
|
fetchRemoteSources,
|
||||||
createUserToken,
|
createUserToken,
|
||||||
deleteUserToken
|
deleteUserToken
|
||||||
} from "@/util/data.js";
|
} from "@/util/data.js";
|
||||||
|
@ -40,33 +47,85 @@ export default {
|
||||||
props: {},
|
props: {},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
createUserTokenError: null,
|
||||||
|
deleteUserTokenError: null,
|
||||||
user: [],
|
user: [],
|
||||||
|
remotesources: [],
|
||||||
token: null,
|
token: null,
|
||||||
newtokenname: null
|
newtokenname: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
resetErrors() {
|
||||||
|
this.createUserTokenError = null;
|
||||||
|
this.deleteUserTokenError = null;
|
||||||
|
},
|
||||||
|
async fetchCurrentUser() {
|
||||||
|
let { data, error } = await fetchCurrentUser();
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.user = data;
|
||||||
|
},
|
||||||
|
async fetchRemoteSources() {
|
||||||
|
let { data, error } = await fetchRemoteSources();
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.remotesources = data;
|
||||||
|
},
|
||||||
async createUserToken() {
|
async createUserToken() {
|
||||||
let res = await createUserToken(this.user.username, this.newtokenname);
|
this.resetErrors();
|
||||||
this.token = res.token;
|
|
||||||
|
let { data, error } = await createUserToken(
|
||||||
|
this.user.username,
|
||||||
|
this.newtokenname
|
||||||
|
);
|
||||||
|
if (error) {
|
||||||
|
this.createUserTokenError = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.token = data.token;
|
||||||
this.newtokenname = null;
|
this.newtokenname = null;
|
||||||
this.user = await fetchCurrentUser();
|
this.fetchCurrentUser();
|
||||||
},
|
},
|
||||||
async deleteUserToken(tokenname) {
|
async deleteUserToken(tokenname) {
|
||||||
await deleteUserToken(this.user.username, tokenname);
|
this.resetErrors();
|
||||||
this.user = await fetchCurrentUser();
|
|
||||||
|
let { error } = await deleteUserToken(this.user.username, tokenname);
|
||||||
|
if (error) {
|
||||||
|
this.deleteUserTokenError = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.fetchCurrentUser();
|
||||||
},
|
},
|
||||||
closeNewTokenNotification() {
|
closeNewTokenNotification() {
|
||||||
this.token = null;
|
this.token = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: async function() {
|
created: function() {
|
||||||
this.user = await fetchCurrentUser();
|
this.fetchCurrentUser();
|
||||||
|
this.fetchRemoteSources();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import "@/css/_variables.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>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,11 @@ import Logout from "./views/Logout.vue";
|
||||||
|
|
||||||
import { parseRef } from "@/util/link.js";
|
import { parseRef } from "@/util/link.js";
|
||||||
|
|
||||||
|
import store from "./store";
|
||||||
|
|
||||||
Vue.use(VueRouter);
|
Vue.use(VueRouter);
|
||||||
|
|
||||||
export default new VueRouter({
|
const router = new VueRouter({
|
||||||
mode: "history",
|
mode: "history",
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
|
@ -327,3 +329,10 @@ export default new VueRouter({
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.beforeEach((to, from, next) => {
|
||||||
|
store.dispatch("setError", null);
|
||||||
|
next()
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router
|
13
src/store.js
13
src/store.js
|
@ -4,11 +4,16 @@ import Vuex from 'vuex'
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
|
error: null,
|
||||||
user: null,
|
user: null,
|
||||||
registeruser: null
|
registeruser: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
const getters = {
|
const getters = {
|
||||||
|
// global error
|
||||||
|
error: state => {
|
||||||
|
return state.error
|
||||||
|
},
|
||||||
user: state => {
|
user: state => {
|
||||||
return state.user
|
return state.user
|
||||||
},
|
},
|
||||||
|
@ -18,6 +23,9 @@ const getters = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
|
setError(state, error) {
|
||||||
|
state.error = error
|
||||||
|
},
|
||||||
setUser(state, user) {
|
setUser(state, user) {
|
||||||
state.user = user
|
state.user = user
|
||||||
},
|
},
|
||||||
|
@ -27,6 +35,9 @@ const mutations = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
setError({ commit }, error) {
|
||||||
|
commit('setError', error)
|
||||||
|
},
|
||||||
setUser({ commit }, user) {
|
setUser({ commit }, user) {
|
||||||
commit('setUser', user)
|
commit('setUser', user)
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,13 +7,13 @@ const USER_KEY = 'user';
|
||||||
let API_URL = window.CONFIG.API_URL;
|
let API_URL = window.CONFIG.API_URL;
|
||||||
let API_BASE_PATH = window.CONFIG.API_BASE_PATH;
|
let API_BASE_PATH = window.CONFIG.API_BASE_PATH;
|
||||||
|
|
||||||
export function login(token, user) {
|
export function setLoggedUser(token, user) {
|
||||||
setIdToken(token);
|
setIdToken(token);
|
||||||
setUser(user);
|
setUser(user);
|
||||||
store.dispatch('setUser', user)
|
store.dispatch('setUser', user)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logout() {
|
export function doLogout() {
|
||||||
unsetIdToken();
|
unsetIdToken();
|
||||||
unsetUser()
|
unsetUser()
|
||||||
store.dispatch('setUser', null)
|
store.dispatch('setUser', null)
|
||||||
|
@ -48,6 +48,19 @@ export function oauth2callbackurl() {
|
||||||
return new URL(API_URL + "/oauth2/callback");
|
return new URL(API_URL + "/oauth2/callback");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function loginapi(init) {
|
||||||
|
if (init === undefined) {
|
||||||
|
init = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let res = await window.fetch(loginurl(), init)
|
||||||
|
return res
|
||||||
|
} catch (e) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetch(url, init) {
|
export async function fetch(url, init) {
|
||||||
if (init === undefined) {
|
if (init === undefined) {
|
||||||
init = {}
|
init = {}
|
||||||
|
@ -60,10 +73,14 @@ export async function fetch(url, init) {
|
||||||
init.headers["Authorization"] = "bearer " + idToken
|
init.headers["Authorization"] = "bearer " + idToken
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = await window.fetch(url, init)
|
try {
|
||||||
if (res.status === 401) {
|
let res = await window.fetch(url, init)
|
||||||
router.push({ name: "login" })
|
if (res.status === 401) {
|
||||||
} else { return res }
|
router.push({ name: "login" })
|
||||||
|
} else { return res }
|
||||||
|
} catch (e) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setIdToken(idToken) {
|
export function setIdToken(idToken) {
|
||||||
|
|
116
src/util/data.js
116
src/util/data.js
|
@ -1,9 +1,49 @@
|
||||||
import { apiurl, fetch } from "@/util/auth";
|
import { apiurl, loginapi } from "@/util/auth";
|
||||||
|
import { fetch as authfetch } from "@/util/auth";
|
||||||
|
|
||||||
|
export async function fetch(url, init) {
|
||||||
|
try {
|
||||||
|
let res = await authfetch(url, init)
|
||||||
|
if (!res.ok) {
|
||||||
|
let data = await res.json()
|
||||||
|
return { data: null, error: data.message }
|
||||||
|
} else {
|
||||||
|
if (res.status == 204) {
|
||||||
|
return { data: null, error: null }
|
||||||
|
}
|
||||||
|
return { data: await res.json(), error: null }
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return { data: null, error: "api call failed: " + e }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function login(username, password, remotesourcename) {
|
||||||
|
let init = {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify({
|
||||||
|
remote_source_name: remotesourcename,
|
||||||
|
login_name: username,
|
||||||
|
password: password
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let res = await loginapi(init)
|
||||||
|
if (!res.ok) {
|
||||||
|
let data = await res.json()
|
||||||
|
return { data: null, error: data.message }
|
||||||
|
} else {
|
||||||
|
return { data: await res.json(), error: null }
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return { data: null, error: "api call failed: " + e }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchCurrentUser() {
|
export async function fetchCurrentUser() {
|
||||||
let path = "/user"
|
let path = "/user"
|
||||||
let res = await fetch(apiurl(path));
|
return await fetch(apiurl(path));
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchRuns(group, lastrun) {
|
export async function fetchRuns(group, lastrun) {
|
||||||
|
@ -14,25 +54,40 @@ export async function fetchRuns(group, lastrun) {
|
||||||
if (lastrun) {
|
if (lastrun) {
|
||||||
u.searchParams.append("lastrun", true)
|
u.searchParams.append("lastrun", true)
|
||||||
}
|
}
|
||||||
let res = await fetch(u)
|
return await fetch(u)
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchRun(runid) {
|
export async function fetchRun(runid) {
|
||||||
let res = await fetch(apiurl("/runs/" + runid));
|
return await fetch(apiurl("/runs/" + runid));
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchTask(runid, taskid) {
|
export async function fetchTask(runid, taskid) {
|
||||||
let res = await fetch(apiurl("/runs/" + runid + "/tasks/" + taskid))
|
return await fetch(apiurl("/runs/" + runid + "/tasks/" + taskid))
|
||||||
return res.json();
|
}
|
||||||
|
|
||||||
|
export async function fetchUser(username) {
|
||||||
|
let path = "/users/" + username
|
||||||
|
return await fetch(apiurl(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchProjectGroupSubgroups(projectgroupref) {
|
||||||
|
let path = "/projectgroups/" + encodeURIComponent(projectgroupref)
|
||||||
|
path += "/subgroups";
|
||||||
|
|
||||||
|
return await fetch(apiurl(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchProjectGroupProjects(projectgroupref) {
|
||||||
|
let path = "/projectgroups/" + encodeURIComponent(projectgroupref)
|
||||||
|
path += "/projects";
|
||||||
|
|
||||||
|
return await fetch(apiurl(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchProject(ref) {
|
export async function fetchProject(ref) {
|
||||||
let path = "/projects/" + encodeURIComponent(ref)
|
let path = "/projects/" + encodeURIComponent(ref)
|
||||||
|
|
||||||
let res = await fetch(apiurl(path));
|
return await fetch(apiurl(path));
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchVariables(ownertype, ref, all) {
|
export async function fetchVariables(ownertype, ref, all) {
|
||||||
|
@ -47,8 +102,7 @@ export async function fetchVariables(ownertype, ref, all) {
|
||||||
if (all) {
|
if (all) {
|
||||||
path += "?tree&removeoverridden";
|
path += "?tree&removeoverridden";
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path));
|
return await fetch(apiurl(path));
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createUserToken(username, tokenname) {
|
export async function createUserToken(username, tokenname) {
|
||||||
|
@ -59,8 +113,7 @@ export async function createUserToken(username, tokenname) {
|
||||||
token_name: tokenname,
|
token_name: tokenname,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteUserToken(username, tokenname) {
|
export async function deleteUserToken(username, tokenname) {
|
||||||
|
@ -68,8 +121,7 @@ export async function deleteUserToken(username, tokenname) {
|
||||||
let init = {
|
let init = {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.text();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function restartRun(runid, fromStart) {
|
export async function restartRun(runid, fromStart) {
|
||||||
|
@ -81,8 +133,7 @@ export async function restartRun(runid, fromStart) {
|
||||||
from_start: fromStart
|
from_start: fromStart
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function stopRun(runid) {
|
export async function stopRun(runid) {
|
||||||
|
@ -93,8 +144,7 @@ export async function stopRun(runid) {
|
||||||
action_type: "stop"
|
action_type: "stop"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function approveTask(runid, taskid) {
|
export async function approveTask(runid, taskid) {
|
||||||
|
@ -105,20 +155,17 @@ export async function approveTask(runid, taskid) {
|
||||||
action_type: "approve"
|
action_type: "approve"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchRemoteSources() {
|
export async function fetchRemoteSources() {
|
||||||
let path = "/remotesources"
|
let path = "/remotesources"
|
||||||
let res = await fetch(apiurl(path));
|
return await fetch(apiurl(path));
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function userRemoteRepos(remotesourceid) {
|
export async function userRemoteRepos(remotesourceid) {
|
||||||
let path = "/user/remoterepos/" + remotesourceid
|
let path = "/user/remoterepos/" + remotesourceid
|
||||||
let res = await fetch(apiurl(path));
|
return await fetch(apiurl(path));
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createProjectGroup(parentref, name) {
|
export async function createProjectGroup(parentref, name) {
|
||||||
|
@ -131,8 +178,7 @@ export async function createProjectGroup(parentref, name) {
|
||||||
visibility: "public",
|
visibility: "public",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createProject(parentref, name, remotesourcename, remoterepopath) {
|
export async function createProject(parentref, name, remotesourcename, remoterepopath) {
|
||||||
|
@ -147,8 +193,7 @@ export async function createProject(parentref, name, remotesourcename, remoterep
|
||||||
repo_path: remoterepopath,
|
repo_path: remoterepopath,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.json();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateProject(projectref, name, visibility) {
|
export async function updateProject(projectref, name, visibility) {
|
||||||
|
@ -160,8 +205,7 @@ export async function updateProject(projectref, name, visibility) {
|
||||||
visibility: visibility,
|
visibility: visibility,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.json()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteProject(projectref) {
|
export async function deleteProject(projectref) {
|
||||||
|
@ -169,8 +213,7 @@ export async function deleteProject(projectref) {
|
||||||
let init = {
|
let init = {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.text();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteProjectGroup(projectgroupref) {
|
export async function deleteProjectGroup(projectgroupref) {
|
||||||
|
@ -178,6 +221,5 @@ export async function deleteProjectGroup(projectgroupref) {
|
||||||
let init = {
|
let init = {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
}
|
}
|
||||||
let res = await fetch(apiurl(path), init)
|
return await fetch(apiurl(path), init)
|
||||||
return res.text();
|
|
||||||
}
|
}
|
|
@ -1,17 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
<div v-if="error" class="message is-danger">
|
||||||
|
<div class="message-header">
|
||||||
|
<p>Login error</p>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">{{ error }}</div>
|
||||||
|
</div>
|
||||||
<div class="column is-4 is-offset-4">
|
<div class="column is-4 is-offset-4">
|
||||||
<div class="box" v-for="rs in remotesources" v-bind:key="rs.id">
|
<div class="box" v-for="rs in remotesources" v-bind:key="rs.id">
|
||||||
<LoginForm
|
<LoginForm
|
||||||
action="Login"
|
action="Login"
|
||||||
:name="rs.name"
|
:name="rs.name"
|
||||||
v-if="rs.auth_type == 'password'"
|
v-if="rs.auth_type == 'password'"
|
||||||
v-on:login="doLogin(rs.name, $event.username, $event.password)"
|
v-on:login="doLogin($event.username, $event.password, rs.name)"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-else
|
v-else
|
||||||
class="button is-info is-fullwidth"
|
class="button is-info is-fullwidth"
|
||||||
@click="doLogin(rs.name)"
|
@click="doLogin(null, null, rs.name)"
|
||||||
>Login with {{rs.name}}</button>
|
>Login with {{rs.name}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,8 +25,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fetchRemoteSources } from "@/util/data";
|
import { fetchRemoteSources, login } from "@/util/data";
|
||||||
import { loginurl, fetch, login, logout } from "@/util/auth";
|
import { setLoggedUser, doLogout } from "@/util/auth";
|
||||||
|
|
||||||
import LoginForm from "@/components/loginform";
|
import LoginForm from "@/components/loginform";
|
||||||
|
|
||||||
|
@ -31,34 +37,39 @@ export default {
|
||||||
},
|
},
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
|
error: null,
|
||||||
remotesources: null
|
remotesources: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getRemoteSources() {
|
async fetchRemoteSources() {
|
||||||
this.remotesources = await fetchRemoteSources();
|
let { data, error } = await fetchRemoteSources();
|
||||||
},
|
if (error) {
|
||||||
async doLogin(rsName, username, password) {
|
this.$store.dispatch("setError", error);
|
||||||
let u = loginurl();
|
|
||||||
let res = await (await fetch(u, {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
remote_source_name: rsName,
|
|
||||||
login_name: username,
|
|
||||||
password: password
|
|
||||||
})
|
|
||||||
})).json();
|
|
||||||
if (res.oauth2_redirect) {
|
|
||||||
window.location = res.oauth2_redirect;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
login(res.token, res.user);
|
this.remotesources = data;
|
||||||
|
},
|
||||||
|
async doLogin(username, password, remotesourcename) {
|
||||||
|
this.error = null;
|
||||||
|
|
||||||
|
let { data, error } = await login(username, password, remotesourcename);
|
||||||
|
if (error) {
|
||||||
|
// set local login error on failed login.
|
||||||
|
this.error = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.oauth2_redirect) {
|
||||||
|
window.location = data.oauth2_redirect;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoggedUser(data.token, data.user);
|
||||||
this.$router.push({ name: "home" });
|
this.$router.push({ name: "home" });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: function() {
|
created: function() {
|
||||||
logout();
|
doLogout();
|
||||||
this.getRemoteSources();
|
this.fetchRemoteSources();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { logout } from "@/util/auth";
|
import { doLogout } from "@/util/auth";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Logout",
|
name: "Logout",
|
||||||
created: function() {
|
created: function() {
|
||||||
logout();
|
doLogout();
|
||||||
this.$router.push("/");
|
this.$router.push("/");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div>{{code}}</div>
|
<div v-if="error" class="message is-danger">
|
||||||
<div>{{username}}</div>
|
<div class="message-header">
|
||||||
|
<p>Error</p>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">{{ error }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { oauth2callbackurl, login, fetch } from "@/util/auth";
|
import { fetch } from "@/util/data";
|
||||||
|
|
||||||
|
import { oauth2callbackurl, setLoggedUser } from "@/util/auth";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {},
|
components: {},
|
||||||
|
@ -14,6 +20,7 @@ export default {
|
||||||
props: {},
|
props: {},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
error: null,
|
||||||
run: null,
|
run: null,
|
||||||
code: this.$route.query.code,
|
code: this.$route.query.code,
|
||||||
polling: null,
|
polling: null,
|
||||||
|
@ -25,12 +32,18 @@ export default {
|
||||||
let u = oauth2callbackurl();
|
let u = oauth2callbackurl();
|
||||||
u.searchParams.append("code", this.$route.query.code);
|
u.searchParams.append("code", this.$route.query.code);
|
||||||
u.searchParams.append("state", this.$route.query.state);
|
u.searchParams.append("state", this.$route.query.state);
|
||||||
let res = await (await fetch(u)).json();
|
let { data, error } = await fetch(u);
|
||||||
if (res.request_type === "loginuser") {
|
if (error) {
|
||||||
login(res.response.token, res.response.user);
|
// set local login error on failed oauth2.
|
||||||
|
this.error = error;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.request_type === "loginuser") {
|
||||||
|
setLoggedUser(data.response.token, data.response.user);
|
||||||
this.$router.push("/");
|
this.$router.push("/");
|
||||||
} else if (res.request_type === "authorize") {
|
} else if (data.request_type === "authorize") {
|
||||||
this.$store.dispatch("setRegisterUser", res.response);
|
this.$store.dispatch("setRegisterUser", data.response);
|
||||||
this.$router.push("/register");
|
this.$router.push("/register");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,12 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
$route: async function(route) {
|
$route: async function(route) {
|
||||||
if (route.params.runid) {
|
if (route.params.runid) {
|
||||||
this.run = await fetchRun(route.params.runid);
|
let { data, error } = await fetchRun(route.params.runid);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.run = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -153,7 +158,12 @@ export default {
|
||||||
},
|
},
|
||||||
created: async function() {
|
created: async function() {
|
||||||
if (this.$route.params.runid) {
|
if (this.$route.params.runid) {
|
||||||
this.run = await fetchRun(this.$route.params.runid);
|
let { data, error } = await fetchRun(this.$route.params.runid);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.run = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -51,8 +51,6 @@ import {
|
||||||
projectGroupCreateProjectLink
|
projectGroupCreateProjectLink
|
||||||
} from "@/util/link.js";
|
} from "@/util/link.js";
|
||||||
|
|
||||||
import { fetchRun } from "@/util/data.js";
|
|
||||||
|
|
||||||
import projbreadcrumbs from "@/components/projbreadcrumbs.vue";
|
import projbreadcrumbs from "@/components/projbreadcrumbs.vue";
|
||||||
import createprojectbutton from "@/components/createprojectbutton.vue";
|
import createprojectbutton from "@/components/createprojectbutton.vue";
|
||||||
|
|
||||||
|
@ -64,18 +62,6 @@ export default {
|
||||||
ownername: String,
|
ownername: String,
|
||||||
projectgroupref: Array
|
projectgroupref: Array
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
run: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
$route: async function(route) {
|
|
||||||
if (route.params.runid) {
|
|
||||||
this.run = await fetchRun(route.params.runid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
projectGroupProjectsLink: projectGroupProjectsLink,
|
projectGroupProjectsLink: projectGroupProjectsLink,
|
||||||
projectGroupSettingsLink: projectGroupSettingsLink,
|
projectGroupSettingsLink: projectGroupSettingsLink,
|
||||||
|
@ -103,11 +89,6 @@ export default {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
created: async function() {
|
|
||||||
if (this.$route.params.runid) {
|
|
||||||
this.run = await fetchRun(this.$route.params.runid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -31,7 +31,9 @@ import { mapGetters } from "vuex";
|
||||||
import LoginForm from "@/components/loginform";
|
import LoginForm from "@/components/loginform";
|
||||||
import RegisterForm from "@/components/registerform";
|
import RegisterForm from "@/components/registerform";
|
||||||
|
|
||||||
import { apiurl, authorizeurl, registerurl, fetch, logout } from "@/util/auth";
|
import { fetchRemoteSources } from "@/util/data";
|
||||||
|
|
||||||
|
import { authorizeurl, registerurl, fetch, doLogout } from "@/util/auth";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Register",
|
name: "Register",
|
||||||
|
@ -48,9 +50,13 @@ export default {
|
||||||
...mapGetters(["registeruser"])
|
...mapGetters(["registeruser"])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getRemoteSources() {
|
async fetchRemoteSources() {
|
||||||
let res = await (await fetch(apiurl("/remotesources"))).json();
|
let { data, error } = await fetchRemoteSources();
|
||||||
this.remotesources = res;
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.remotesources = data;
|
||||||
},
|
},
|
||||||
async doAuthorize(rsName, username, password) {
|
async doAuthorize(rsName, username, password) {
|
||||||
let u = authorizeurl();
|
let u = authorizeurl();
|
||||||
|
@ -99,8 +105,8 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: function() {
|
created: function() {
|
||||||
logout();
|
doLogout();
|
||||||
this.getRemoteSources();
|
this.fetchRemoteSources();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -117,7 +117,12 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
$route: async function(route) {
|
$route: async function(route) {
|
||||||
if (route.params.runid) {
|
if (route.params.runid) {
|
||||||
this.run = await fetchRun(route.params.runid);
|
let { data, error } = await fetchRun(route.params.runid);
|
||||||
|
if (error) {
|
||||||
|
this.$store.dispatch("setError", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.run = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue