First stuff works
Show a list of active GitLab projects.
This commit is contained in:
parent
cc0337cec2
commit
47f3db0834
10 changed files with 270 additions and 80 deletions
|
@ -1,5 +1,7 @@
|
||||||
# git-dashboard
|
# git-dashboard
|
||||||
|
|
||||||
|
**WARNING: THIS IS ALPHA SOFTWARE! DO NOT USE IT! IF YOU DO, IT IS ON YOUR OWN RISK! IT MAY DESTROY YOUR COMPUTER, BURN YOUR HOUSE AND KILL YOUR KITTEN**
|
||||||
|
|
||||||
## Project setup
|
## Project setup
|
||||||
```
|
```
|
||||||
yarn install
|
yarn install
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bulma": "^0.9.3",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"vue": "^3.0.0"
|
"vue": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,12 +6,17 @@
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
</noscript>
|
</noscript>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
75
src/App.vue
75
src/App.vue
|
@ -1,27 +1,68 @@
|
||||||
<template>
|
<template>
|
||||||
<img alt="Vue logo" src="./assets/logo.png">
|
<h1 class="title">My GitLab Dashboard</h1>
|
||||||
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
|
<gitlab-auth
|
||||||
|
v-if="!authorized"
|
||||||
|
@authTokenSubmit="authTokenSubmit"
|
||||||
|
:auth-error="authError"
|
||||||
|
></gitlab-auth>
|
||||||
|
<div v-if="authorized" class="columns">
|
||||||
|
<div class="column is-one-quarter">
|
||||||
|
<gitlab-user :gitlabToken="gitlabToken"></gitlab-user>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<gitlab-projects
|
||||||
|
:gitlabToken="gitlabToken"
|
||||||
|
:gitlabId="gitlabId"
|
||||||
|
></gitlab-projects>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from "vue";
|
||||||
import HelloWorld from './components/HelloWorld.vue';
|
import GitlabAuth from "./components/GitlabAuth.vue";
|
||||||
|
import GitlabUser from "./components/GitlabUser.vue";
|
||||||
|
import GitlabProjects from "./components/GitlabProjects.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'App',
|
name: "App",
|
||||||
components: {
|
components: {
|
||||||
HelloWorld
|
GitlabAuth,
|
||||||
|
GitlabUser,
|
||||||
|
GitlabProjects,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
gitlabToken: "",
|
||||||
|
gitlabId: 0,
|
||||||
|
authorized: false, // temp property, should be replaced by an empty gitlabToken
|
||||||
|
authError: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
authTokenSubmit(authToken: string) {
|
||||||
|
if (!authToken) return;
|
||||||
|
|
||||||
|
fetch("https://gitlab.com/api/v4/user", {
|
||||||
|
headers: {
|
||||||
|
"PRIVATE-TOKEN": authToken,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
if (data.id) {
|
||||||
|
this.gitlabId = data.id;
|
||||||
|
} else {
|
||||||
|
throw new Error("Auth token not valid");
|
||||||
}
|
}
|
||||||
|
this.gitlabToken = authToken;
|
||||||
|
this.authorized = true;
|
||||||
|
})
|
||||||
|
.catch((Error) => {
|
||||||
|
console.log(Error);
|
||||||
|
this.authError = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
#app {
|
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
text-align: center;
|
|
||||||
color: #2c3e50;
|
|
||||||
margin-top: 60px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 6.7 KiB |
48
src/components/GitlabAuth.vue
Normal file
48
src/components/GitlabAuth.vue
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<template>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="title is-4">GitLab Authentication required</p>
|
||||||
|
<p class="mb-5">
|
||||||
|
Please create a GitLab authentication token over at
|
||||||
|
<a
|
||||||
|
href="https://gitlab.com/-/profile/personal_access_tokens"
|
||||||
|
taget="blank"
|
||||||
|
>GitLab.com</a
|
||||||
|
>
|
||||||
|
(API scope is enought) and enter it here. Attention: Currently the token
|
||||||
|
is not stored in any way by this app so it is recommended to save in a
|
||||||
|
safe place e.g. a password store for the next use.
|
||||||
|
</p>
|
||||||
|
<div class="field has-addons has-addons-centered">
|
||||||
|
<p class="control">
|
||||||
|
<input
|
||||||
|
@keyup.enter="$emit('authTokenSubmit', authToken)"
|
||||||
|
v-model="authToken"
|
||||||
|
class="input"
|
||||||
|
type="text"
|
||||||
|
placeholder="GitLab Access Token"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<p class="control">
|
||||||
|
<a @click="$emit('authTokenSubmit', authToken)" class="button is-primary">Submit</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div v-if="authError" class="notification is-danger">
|
||||||
|
<strong>Authentication failed!</strong> Please double check your authentication token.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "GitlabAuth",
|
||||||
|
props: ['authError'],
|
||||||
|
emits: ['authTokenSubmit'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
authToken: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
93
src/components/GitlabProjects.vue
Normal file
93
src/components/GitlabProjects.vue
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
<template>
|
||||||
|
<div class="box">
|
||||||
|
<h3 class="title is-3">Active Projects</h3>
|
||||||
|
<article
|
||||||
|
v-for="project in projects"
|
||||||
|
class="media"
|
||||||
|
:href="project.web_url"
|
||||||
|
:key="project"
|
||||||
|
>
|
||||||
|
<div class="media-left" v-if="project.avatar_url">
|
||||||
|
<figure class="image is-64x64">
|
||||||
|
<img :src="project.avatar_url" />
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
<div class="media-content">
|
||||||
|
<div class="content">
|
||||||
|
<h5 class="subtitle is-5 is-spaced">{{ project.name }}</h5>
|
||||||
|
<div class="tags" v-if="project.topics">
|
||||||
|
<span
|
||||||
|
v-for="topic in project.topics"
|
||||||
|
:key="topic"
|
||||||
|
class="tag is-link"
|
||||||
|
>{{ topic }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<small>Last activity: {{ project.last_activity_at }}</small>
|
||||||
|
<p v-if="project.description">{{ project.description }}</p>
|
||||||
|
<p v-if="project.issues_enabled && project.open_issues_count">
|
||||||
|
{{ project.open_issues_count }} open issues
|
||||||
|
</p>
|
||||||
|
<div class="buttons">
|
||||||
|
<a
|
||||||
|
target="blank"
|
||||||
|
:href="project.web_url"
|
||||||
|
class="button is-primary is-rounded"
|
||||||
|
>Visit</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
target="blank"
|
||||||
|
:href="`${project.web_url}/-/issues`"
|
||||||
|
class="button is-rounded"
|
||||||
|
>Issues</a
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
target="blank"
|
||||||
|
:href="`${project.web_url}/-/merge_requests`"
|
||||||
|
class="button is-rounded"
|
||||||
|
>Merge Requests</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "GitlabProjects",
|
||||||
|
props: {
|
||||||
|
gitlabToken: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
gitlabId: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
projects: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
fetch(
|
||||||
|
`https://gitlab.com/api/v4/users/${this.gitlabId}/projects?archived=false&order_by=last_activity_at`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"PRIVATE-TOKEN": this.gitlabToken,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
this.projects = data;
|
||||||
|
})
|
||||||
|
.catch((Error) => {
|
||||||
|
console.log(Error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
56
src/components/GitlabUser.vue
Normal file
56
src/components/GitlabUser.vue
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<template>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-image">
|
||||||
|
<figure class="image is-4by4">
|
||||||
|
<img :src="user.avatar_url" alt="Profile Picture" />
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<p class="title is-4"><a :href="user.web_url">{{ user.name }}</a></p>
|
||||||
|
<p class="subtitle is-6">{{ user.username }}</p>
|
||||||
|
<div class="content">
|
||||||
|
{{ user.bio }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer class="card-footer">
|
||||||
|
<p class="card-footer-item">
|
||||||
|
<span>{{ user.location }}</span>
|
||||||
|
</p>
|
||||||
|
<p class="card-footer-item">
|
||||||
|
<span><a :href="user.website_url">{{ user.website_url_nice }}</a></span>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "GitlabUser",
|
||||||
|
props: {
|
||||||
|
gitlabToken: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
user: {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
fetch("https://gitlab.com/api/v4/user", {
|
||||||
|
headers: {
|
||||||
|
"PRIVATE-TOKEN": this.gitlabToken
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
this.user = data;
|
||||||
|
this.user.website_url_nice = this.user.website_url.substring(8);
|
||||||
|
})
|
||||||
|
.catch((Error) => {
|
||||||
|
console.log(Error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -1,61 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="hello">
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
<p>
|
|
||||||
For a guide and recipes on how to configure / customize this project,<br>
|
|
||||||
check out the
|
|
||||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
|
||||||
</p>
|
|
||||||
<h3>Installed CLI Plugins</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Essential Links</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
|
||||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
|
||||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
|
||||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
|
||||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Ecosystem</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
|
||||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
|
||||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: 'HelloWorld',
|
|
||||||
props: {
|
|
||||||
msg: String,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped lang="scss">
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #42b983;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -2419,6 +2419,11 @@ builtin-status-codes@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||||
integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
|
integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
|
||||||
|
|
||||||
|
bulma@^0.9.3:
|
||||||
|
version "0.9.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.9.3.tgz#ddccb7436ebe3e21bf47afe01d3c43a296b70243"
|
||||||
|
integrity sha512-0d7GNW1PY4ud8TWxdNcP6Cc8Bu7MxcntD/RRLGWuiw/s0a9P+XlH/6QoOIrmbj6o8WWJzJYhytiu9nFjTszk1g==
|
||||||
|
|
||||||
bytes@3.0.0:
|
bytes@3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||||
|
|
Reference in a new issue