First stuff works

Show a list of active GitLab projects.
This commit is contained in:
Marcel Kapfer 2021-10-13 22:48:59 +02:00
parent cc0337cec2
commit 47f3db0834
Signed by: mmk2410
GPG key ID: CADE6F0C09F21B09
10 changed files with 270 additions and 80 deletions

View file

@ -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

View file

@ -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"
}, },

View file

@ -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>

View file

@ -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

View 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>

View 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>

View 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>

View file

@ -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>

View file

@ -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"