diff options
author | HampusM <hampus@hampusmat.com> | 2021-06-05 19:37:52 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2021-06-05 19:37:52 +0200 |
commit | 4da3272bf7893760f6710c9a1ec7de02358136e6 (patch) | |
tree | 92eb961bf20a7ef9f7c0650ba288baf512986fca /packages/client/src/views | |
parent | 4e3074dfd752dd52951d300090c642aee76cfaac (diff) |
Reorganized into a monorepo, refactored the frontend again, goodbye Parcel
Diffstat (limited to 'packages/client/src/views')
-rw-r--r-- | packages/client/src/views/Home.vue | 79 | ||||
-rw-r--r-- | packages/client/src/views/Repository.vue | 27 | ||||
-rw-r--r-- | packages/client/src/views/RepositoryCommit.vue | 202 | ||||
-rw-r--r-- | packages/client/src/views/RepositoryLog.vue | 111 | ||||
-rw-r--r-- | packages/client/src/views/RepositoryTree.vue | 106 |
5 files changed, 525 insertions, 0 deletions
diff --git a/packages/client/src/views/Home.vue b/packages/client/src/views/Home.vue new file mode 100644 index 0000000..80f2e9a --- /dev/null +++ b/packages/client/src/views/Home.vue @@ -0,0 +1,79 @@ +<template> + <div class="container-fluid px-0"> + <HomeHeader /> + <HomeProjectsHeader /> + <div class="row mx-0"> + <div class="col ms-4"> + <ul id="repos"> + <li v-for="(project, project_name, index) in projects" :key="index"> + <div v-if="(search !== null && project_name.includes(search)) || search == null"> + <span class="fs-3"> + <router-link :to="project_name"> + {{ project_name }} + </router-link> + </span> + <span class="repo-last-updated fs-5">Last updated about {{ project["last_updated"] }} ago</span> + <span class="fs-5">{{ project["description"] }}</span> + </div> + </li> + </ul> + </div> + </div> + </div> +</template> + +<script> +import HomeHeader from "@/components/HomeHeader"; +import HomeProjectsHeader from "@/components/HomeProjectsHeader"; +import { ref } from "vue"; + +export default { + name: "Home", + components: { + HomeHeader, + HomeProjectsHeader + }, + setup() { + const projects = ref({}); + const search = ref(""); + + const fetchProjects = async() => { + const projects_data = await (await fetch(`${window.location.protocol}//${window.location.host}/api/v1/repos`)).json(); + projects.value = projects_data.data; + }; + + search.value = (new URLSearchParams(window.location.search)).get("q"); + + return { projects, search, fetchProjects }; + }, + mount() { + this.fetchProjects(); + }, + created() { + this.fetchProjects(); + } +}; +</script> + +<style lang="scss" scoped> +@use "../scss/colors"; +@import "../scss/bootstrap"; + +#repos { + margin-top: 25px; + li { + margin-bottom: 25px; + } +} + +.repo-last-updated { + display: block; + font-weight: 300; + font-style: italic; +} + +ul { + list-style-type: none; + padding: 0; +} +</style> diff --git a/packages/client/src/views/Repository.vue b/packages/client/src/views/Repository.vue new file mode 100644 index 0000000..93c3f82 --- /dev/null +++ b/packages/client/src/views/Repository.vue @@ -0,0 +1,27 @@ +<template> + <div class="container-fluid px-0 d-flex"> + <RepositoryHeader :repository="$router.currentRoute._rawValue.params.repo" /> + <RepositoryNavbar :repository="$router.currentRoute._rawValue.params.repo" :active-page="$router.currentRoute._rawValue.path.split('/')[2]" /> + <router-view /> + </div> +</template> + +<script> +import RepositoryHeader from "@/components/RepositoryHeader"; +import RepositoryNavbar from "@/components/RepositoryNavbar"; + +export default { + name: "Repository", + components: { + RepositoryHeader, + RepositoryNavbar + } +}; +</script> + +<style lang="scss" scoped> +.container-fluid { + flex-flow: column; + height: 100vh; +} +</style> diff --git a/packages/client/src/views/RepositoryCommit.vue b/packages/client/src/views/RepositoryCommit.vue new file mode 100644 index 0000000..6bbbcaa --- /dev/null +++ b/packages/client/src/views/RepositoryCommit.vue @@ -0,0 +1,202 @@ +<template> + <div class="row mx-0"> + <div class="col ms-2 ps-4 ps-sm-5 fs-5 vld-parent"> + <BaseBreadcrumb :items="[{ name: 'Log', path: '/' + $router.currentRoute._rawValue.params.repo + '/log' }]" :active-item="$router.currentRoute._rawValue.params.commit" /> + <table id="commit-info" class="table table-dark"> + <tbody> + <tr> + <td class="commit-info-title"> + Author + </td> + <td>{{ commit_data["author"] }}</td> + </tr> + <tr> + <td class="commit-info-title"> + Date + </td> + <td>{{ commit_data["date"] }}</td> + </tr> + <tr> + <td class="commit-info-title"> + Message + </td> + <td>{{ commit_data["message"] }}</td> + </tr> + </tbody> + </table> + <Loading + :active="is_loading" :height="24" + :width="24" color="#ffffff" + :opacity="0" :is-full-page="false" /> + <div + v-for="(patch, index) in commit_data['patches']" :key="index" + class="commit-patch"> + <div class="commit-patch-header"> + <span class="fw-bold">{{ (patch.to === "/dev/null") ? patch.from : patch.to }} </span> + <span v-if="patch.to === '/dev/null'">Deleted</span> + <div class="commit-patch-add-del"> + <span>+{{ patch.additions }}</span> + <span>-{{ patch.deletions }}</span> + </div> + </div> + <CommitPatch :patch="patch" /> + </div> + </div> + </div> +</template> + +<script> +import BaseBreadcrumb from "@/components/BaseBreadcrumb"; +import CommitPatch from "@/components/CommitPatch"; +import Loading from "vue-loading-overlay"; +import { ref } from "vue"; +import { format } from "date-fns"; + +export default { + name: "RepositoryCommit", + components: { + BaseBreadcrumb, + Loading, + CommitPatch + }, + setup() { + const commit_data = ref({}); + const is_loading = ref(true); + + const fetchCommit = async(repository, commit) => { + const data = await (await fetch(`${window.location.protocol}//${window.location.host}/api/v1/repos/${repository}/log/${commit}`)).json(); + data.data.date = format(new Date(data.data.date), "yyyy-MM-dd hh:mm"); + commit_data.value = data.data; + is_loading.value = false; + }; + + return { commit_data, is_loading, fetchCommit }; + }, + created() { + this.fetchCommit(this.$router.currentRoute._rawValue.params.repo, this.$router.currentRoute._rawValue.params.commit); + } +}; +</script> + +<style lang="scss"> +@use "../scss/colors"; +@import "../scss/bootstrap"; + +@import "~bootstrap/scss/tables"; + +@import "~vue-loading-overlay/dist/vue-loading.css"; +@import "~highlight.js/scss/srcery.scss"; + +#commit-info { + margin-bottom: 2rem; + tbody tr { + td { + padding: 0px; + padding-right: 10px; + } + } +} + +.commit-patch { + margin-bottom: 50px; + table { + padding-top: 15px; + tbody tr td { + padding: 0px; + padding-left: 8px; + vertical-align: top; + &:nth-child(2) { + padding-right: 7px; + } + &:nth-child(3) { + padding-right: 15px; + } + } + } +} + +.commit-patch-add-del { + margin-left: auto; + margin-right: 23px; + span { + margin-right: 10px !important; + font-weight: 700; + &:nth-child(1) { + color: colors.$new; + } + } +} + +.commit-patch-header { + display: flex; + background-color: lighten(#000000, 14%); + padding: 10px; + span { + margin-right: 30px; + &:nth-child(2) { + color: colors.$danger; + } + } +} + +.commit-info-title { + color: colors.$secondary; + padding-right: 30px; + width: 20px; +} + +.patch-too-large { + font-weight: 600; +} + +.commit-file-pos-change { + color: colors.$text-gray; +} + +.commit-file-no-newline { + color: colors.$text-gray; +} + +.line-new { + color: colors.$new; +} +.line-deleted { + color: colors.$danger; +} + +.line-unchanged { + color: colors.$text-gray; +} + +[patch-line-col-unsel]::before { + content: attr(patch-line-col-unsel); +} + +.line-highlight-new { + border-right: 1px solid colors.$new; +} +.line-highlight-deleted { + border-right: 1px solid colors.$danger; +} + +code { + white-space: pre-wrap; + word-wrap: anywhere; +} + +.row { + height: 100%; +} + +@include media-breakpoint-down(sm) { + .commit-patch table tbody tr td { + padding-left: 4px; + &:nth-child(2) { + padding-right: 4px; + } + &:nth-child(3) { + padding-right: 5px; + } + } +} +</style> diff --git a/packages/client/src/views/RepositoryLog.vue b/packages/client/src/views/RepositoryLog.vue new file mode 100644 index 0000000..542831f --- /dev/null +++ b/packages/client/src/views/RepositoryLog.vue @@ -0,0 +1,111 @@ +<template> + <div class="row mx-0 vld-parent"> + <Loading + :active="is_loading" :height="24" + :width="24" color="#ffffff" + :opacity="0" /> + <div class="col ms-4 ps-4 ps-sm-5 mt-3"> + <table id="log" class="table table-dark fs-5"> + <thead> + <tr> + <th class="text-secondary"> + Subject + </th> + <th class="text-secondary"> + Author + </th> + <th class="text-secondary"> + Date + </th> + <th class="text-secondary"> + Files + </th> + <th class="text-secondary"> + Del/Add + </th> + </tr> + </thead> + <tbody> + <tr v-for="(commit, index) in commits" :key="index"> + <td> + <router-link :to="'log/' + commit['commit']"> + {{ commit["message"] }} + </router-link> + </td> + <td>{{ commit["author_name"] }}</td> + <td>{{ format(new Date(commit["date"]), "yyyy-MM-dd hh:mm") }}</td> + <td>{{ commit["files_changed"] }}</td> + <td><span class="text-danger">-{{ commit["deletions"] }}</span> / <span class="text-success">+{{ commit["insertions"] }}</span></td> + </tr> + </tbody> + </table> + </div> + </div> +</template> + +<script> +import Loading from "vue-loading-overlay"; +import { ref } from "vue"; +import { format } from "date-fns"; + +export default { + name: "RepositoryLog", + components: { + Loading + }, + data() { + return { + format + }; + }, + setup() { + const commits = ref({}); + const is_loading = ref(true); + + const fetchLog = async(repository) => { + const log_data = await (await fetch(`${window.location.protocol}//${window.location.host}/api/v1/repos/${repository}/log`)).json(); + commits.value = log_data.data; + is_loading.value = false; + }; + + return { commits, is_loading, fetchLog }; + }, + created() { + this.fetchLog(this.$router.currentRoute._rawValue.params.repo); + } +}; +</script> + +<style lang="scss" scoped> +@use "../scss/colors"; + +@import "~vue-loading-overlay/dist/vue-loading.css"; +@import "../scss/bootstrap"; +@import "../scss/fonts"; + +@import "~bootstrap/scss/tables"; + +#log { + border-spacing: 0; + tbody tr { + &:hover { + --bs-table-bg: 0; + background-color: lighten(colors.$background, 5%); + } + td { + padding-bottom: 1em; + } + } + th { + text-align: start; + padding-bottom: 1em; + } +} + +@include media-breakpoint-down(sm) { + .table > :not(caption) > * > * { + padding: 0.1rem; + } +} + +</style> diff --git a/packages/client/src/views/RepositoryTree.vue b/packages/client/src/views/RepositoryTree.vue new file mode 100644 index 0000000..1b61c42 --- /dev/null +++ b/packages/client/src/views/RepositoryTree.vue @@ -0,0 +1,106 @@ +<template> + <div class="row mx-0"> + <div class="col ms-4 ps-4 ps-sm-5 mt-3 fs-5 vld-parent"> + <BaseBreadcrumb + :items="(pathArr.length === 0) ? [] : [{ name: $router.currentRoute._rawValue.params.repo, path: '/' + $router.currentRoute._rawValue.params.repo + '/tree' }].concat(pathArr.slice(0, -1).map((path_part, index) => + { + return { + name: path_part, + path: '/' + $router.currentRoute._rawValue.params.repo + '/tree/' + pathArr.slice(0, index + 1).join('/') + } + }))" :active-item="(pathArr.length === 0) ? $router.currentRoute._rawValue.params.repo : pathArr[pathArr.length - 1]" /> + <RepositoryTreeTree + :repository="$router.currentRoute._rawValue.params.repo" :path="path" + :tree="tree" v-if="type === 'tree'" + :is-loading="is_loading" /> + <RepositoryTreeBlob + :repository="$router.currentRoute._rawValue.params.repo" :path="path" + :content="blob_content" v-else /> + <Loading + :active="is_loading" :height="24" + :width="24" color="#ffffff" + :opacity="0" :is-full-page="false" /> + </div> + </div> +</template> + +<script> +import BaseBreadcrumb from "@/components/BaseBreadcrumb"; +import RepositoryTreeBlob from "@/components/RepositoryTreeBlob"; +import RepositoryTreeTree from "@/components/RepositoryTreeTree"; +import Loading from "vue-loading-overlay"; +import { ref } from "vue"; + +export default { + name: "RepositoryTree", + components: { + BaseBreadcrumb, + RepositoryTreeBlob, + RepositoryTreeTree, + Loading + }, + props: { + pathArr: { + type: Array, + required: true + } + }, + watch: { + pathArr() { + this.is_loading = true; + this.tree = {}; + this.fetchTree(this.$router.currentRoute._rawValue.params.repo); + } + }, + setup(props) { + const type = ref(""); + const tree = ref({}); + const blob_content = ref(""); + const is_loading = ref(true); + const path = ref(""); + + const fetchTree = async(repository) => { + path.value = props.pathArr ? props.pathArr.join("/") : undefined; + const data = await (await fetch(`${window.location.protocol}//${window.location.host}/api/v1/repos/${repository}/tree${path.value ? "?path=" + path.value : ""}`)).json(); + console.log(path.value); + type.value = data.data.type; + + if(data.data.type === "tree") { + const tree_data = data.data.tree; + + let tree_trees = Object.entries(tree_data).filter((entry) => entry[1].type === "tree"); + tree_trees = tree_trees.sort((a, b) => a[0].localeCompare(b[0])); + + let tree_blobs = Object.entries(tree_data).filter((entry) => entry[1].type === "blob"); + tree_blobs = tree_blobs.sort((a, b) => a[0].localeCompare(b[0])); + + tree.value = Object.fromEntries(tree_trees.concat(tree_blobs)); + } else { + blob_content.value = data.data.content; + } + + is_loading.value = false; + }; + + return { + type, + tree, + blob_content, + is_loading, + path, + fetchTree + }; + }, + created() { + this.fetchTree(this.$router.currentRoute._rawValue.params.repo); + } +}; +</script> + +<style lang="scss" scoped> +@import "~vue-loading-overlay/dist/vue-loading.css"; + +.row { + height: 100%; +} +</style> |