aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/BaseBackButton.vue25
-rw-r--r--src/components/CommitPatch.vue149
-rw-r--r--src/components/HomeHeader.vue39
-rw-r--r--src/components/RepositoryHeader.vue50
-rw-r--r--src/components/RepositoryNavbar.vue32
5 files changed, 295 insertions, 0 deletions
diff --git a/src/components/BaseBackButton.vue b/src/components/BaseBackButton.vue
new file mode 100644
index 0000000..64b1286
--- /dev/null
+++ b/src/components/BaseBackButton.vue
@@ -0,0 +1,25 @@
+<template>
+ <div class="d-inline">
+ <router-link :to="to">
+ <svg
+ xmlns="http://www.w3.org/2000/svg" id="back"
+ height="24px" width="24px"
+ viewBox="0 0 24 24" fill="#ffffff">
+ <path d="M0 0h24v24H0z" fill="none" />
+ <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
+ </svg>
+ </router-link>
+ </div>
+</template>
+
+<script>
+export default {
+ name: "BaseBackButton",
+ props: {
+ to: {
+ type: String,
+ required: true
+ }
+ }
+}
+</script> \ No newline at end of file
diff --git a/src/components/CommitPatch.vue b/src/components/CommitPatch.vue
new file mode 100644
index 0000000..53edeb9
--- /dev/null
+++ b/src/components/CommitPatch.vue
@@ -0,0 +1,149 @@
+<script>
+import { h } from "vue";
+import hljs from "highlight.js";
+import hljs_languages from "../util/hljs-languages";
+
+export default {
+ name: "CommitPatch",
+ props: {
+ patch: {
+ type: Object,
+ required: true
+ }
+ },
+ setup(props)
+ {
+ const commit_patch = [
+ h("div", { "class": "commit-file-header" }, [
+ h("span", { "class": "fw-bold"}, (props.patch["to"] === "/dev/null") ? props.patch["from"] : props.patch["to"]),
+ h("span", (props.patch["to"] === "/dev/null") ? "Deleted" : "" ),
+ h("div", { class: "commit-file-add-del" }, [
+ h("span", `+${ props.patch["additions"] }`),
+ h("span", `-${ props.patch["deletions"] }`)
+ ])
+ ])
+ ];
+
+ if(props.patch["too_large"] === false) {
+ let all_hunks = props.patch["hunks"].map((hunk) => hunk["hunk"]);
+
+ const language = hljs_languages.find((lang) => lang["extensions"].some((extension) => props.patch["to"].endsWith(extension)));
+ let highlighted = language ? hljs.highlight(language["name"], all_hunks.join("\n")) : hljs.highlightAuto(all_hunks.join("\n"));
+ console.log(highlighted);
+ highlighted = highlighted["value"].split("\n");
+
+ const highlighted_hunks = [];
+ let hunk_start = 0;
+ all_hunks.forEach((hunk) =>
+ {
+ const hunk_row_cnt = hunk.split("\n").length;
+ highlighted_hunks.push(highlighted.slice(hunk_start, hunk_start + hunk_row_cnt));
+ hunk_start = hunk_start + hunk_row_cnt;
+ });
+
+ all_hunks = all_hunks.map((hunk) => hunk.split("\n"));
+
+ commit_patch.push(h("table", { cellspacing: "0px" }, [
+ h("tbody", [
+ props.patch["hunks"].map((hunk, hunk_index) =>
+ {
+ let new_offset = 0;
+ let deleted_offset = 0;
+ const multiline_comments = [];
+
+ return highlighted_hunks[hunk_index].map((line, line_index) =>
+ {
+ if(/^@@ -[0-9,]+ \+[0-9,]+ @@/.test(all_hunks[hunk_index][line_index])) {
+ new_offset++;
+ deleted_offset++;
+ return h("tr", { class: "commit-file-pos-change" }, [
+ h("td", "..."),
+ h("td", "..."),
+ h("td", "..."),
+ h("td", [
+ h("code", all_hunks[hunk_index][line_index])
+ ])
+ ]);
+ }
+ else if(/^\\ No newline at end of file$/.test(all_hunks[hunk_index][line_index])) {
+ new_offset++;
+ deleted_offset++;
+ return h("tr", { class: "commit-file-no-newline" }, [
+ h("td", ""),
+ h("td", ""),
+ h("td", ""),
+ h("td", [
+ h("code", all_hunks[hunk_index][line_index])
+ ])
+ ]);
+ }
+ else {
+ let first_td;
+ let second_td;
+ let third_td;
+
+ if(hunk['new'].includes(line_index)) {
+ first_td = h("td", "");
+ second_td = h("td", { class: "line-highlight-new" }, Number(hunk["new_start"]) + line_index - new_offset);
+ third_td = h("td", { class: "line-new" }, "+")
+ deleted_offset++;
+ }
+ else if(hunk['deleted'].includes(line_index)) {
+ first_td = h("td", Number(hunk["old_start"]) + line_index - deleted_offset);
+ second_td = h("td", { class: "line-highlight-deleted" });
+ third_td = h("td", { class: "line-deleted" }, "-")
+ new_offset++;
+ }
+ else {
+ first_td = h("td", { class: "line-unchanged" }, Number(hunk["old_start"]) + line_index - deleted_offset);
+ second_td = h("td", { class: "line-unchanged" }, Number(hunk["new_start"]) + line_index - new_offset);
+ third_td = h("td", "");
+ }
+
+ let comment_open = line.match(/<span class="hljs-comment">/g);
+ const comment_open_cnt = (comment_open !== null) ? comment_open.length : 0;
+ comment_open = (comment_open !== null) ? comment_open[0] : "";
+
+ let comment_close = line.match(/<\/span>/g);
+ const comment_close_cnt = (comment_close !== null) ? comment_close.length : 0;
+ comment_close = (comment_close !== null) ? comment_close[0] : "";
+
+ if(comment_open_cnt > comment_close_cnt) {
+ line = line + "</span>";
+ console.log("Öppning " + line);
+ multiline_comments.push(comment_open);
+ }
+ else if(comment_open_cnt < comment_close_cnt && multiline_comments.length !== 0) {
+ line = multiline_comments[multiline_comments.length - 1] + line;
+ console.log("Stängning " + line + " " + multiline_comments[multiline_comments.length - 1]);
+ multiline_comments.pop();
+ }
+ else if(multiline_comments.length !== 0) {
+ line = multiline_comments[multiline_comments.length - 1] + line + "</span>";
+ console.log("Mitt i " + line);
+ }
+
+ return h("tr", [
+ first_td,
+ second_td,
+ third_td,
+ h("td", [
+ h("code", { innerHTML: line })
+ ])
+ ]);
+ }
+ });
+ })
+ ])
+ ]));
+ }
+ else {
+ commit_patch.push(h("div", { class: "ps-3 pt-3 patch-too-large" }, [
+ h("span", "Patch is too large to display.")
+ ]));
+ }
+
+ return () => h("div", { class: "commit-file" }, commit_patch);
+ }
+}
+</script> \ No newline at end of file
diff --git a/src/components/HomeHeader.vue b/src/components/HomeHeader.vue
new file mode 100644
index 0000000..f0366a3
--- /dev/null
+++ b/src/components/HomeHeader.vue
@@ -0,0 +1,39 @@
+<template>
+ <div class="row mx-0">
+ <div id="header" class="col d-flex mt-3 ms-2">
+ <div class="d-inline ms-3">
+ <span id="title" class="fs-1">{{ title }}</span>
+ <p id="about" class="mb-3 fs-4">
+ {{ about }}
+ </p>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import { watch, reactive, toRefs } from "vue";
+
+export default {
+ name: "HomeHeader",
+ setup()
+ {
+ const state = reactive({ title: String, about: String });
+
+ watch(() =>
+ {
+ fetch(`http://localhost:1337/api/v1/info`)
+ .then((res) => res.json())
+ .then((data) =>
+ {
+ state.title = data["data"]["title"],
+ state.about = data["data"]["about"]
+ });
+ });
+
+ return {
+ ... toRefs(state)
+ };
+ }
+}
+</script> \ No newline at end of file
diff --git a/src/components/RepositoryHeader.vue b/src/components/RepositoryHeader.vue
new file mode 100644
index 0000000..db1ab1e
--- /dev/null
+++ b/src/components/RepositoryHeader.vue
@@ -0,0 +1,50 @@
+<template>
+ <div class="row mx-0">
+ <div id="header" class="col d-flex mt-3 ms-2">
+ <BaseBackButton to="/" />
+ <div class="d-inline ms-3">
+ <span id="title" class="fs-1">{{ title }}</span>
+ <p id="about" class="mb-3 fs-4">
+ {{ about }}
+ </p>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import BaseBackButton from "./BaseBackButton";
+import { watch, reactive, toRefs } from "vue";
+
+export default {
+ name: "RepositoryHeader",
+ components: {
+ BaseBackButton
+ },
+ props: {
+ repository: {
+ type: String,
+ required: true
+ }
+ },
+ setup(props)
+ {
+ const state = reactive({ title: String, about: String });
+
+ watch(() =>
+ {
+ fetch(`http://localhost:1337/api/v1/repos/${props.repository}`)
+ .then((res) => res.json())
+ .then((data) =>
+ {
+ state.title = data["data"]["name"];
+ state.about = data["data"]["description"];
+ });
+ });
+
+ return {
+ ... toRefs(state)
+ };
+ }
+}
+</script> \ No newline at end of file
diff --git a/src/components/RepositoryNavbar.vue b/src/components/RepositoryNavbar.vue
new file mode 100644
index 0000000..a1e1002
--- /dev/null
+++ b/src/components/RepositoryNavbar.vue
@@ -0,0 +1,32 @@
+<template>
+ <div id="navbar" class="row mx-0">
+ <div id="repo-navbar" class="col ms-4 ps-4">
+ <nav class="navbar navbar-expand navbar-dark">
+ <div class="container-fluid px-0">
+ <div class="collapse navbar-collapse">
+ <ul class="navbar-nav">
+ <li v-for="(item, index) in nav_items" v-bind:key="index" class="nav-item">
+ <a class="nav-link fs-4" :class="{ active: activePage === item }" :aria-current="(activePage === item) ? 'page' : ''" :href="item">{{ item }}</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </nav>
+ </div>
+ </div>
+</template>
+
+<script>
+export default {
+ name: "RepositoryNavbar",
+ props: {
+ activePage: String
+ },
+ data()
+ {
+ return {
+ nav_items: ["log", "refs", "tree"]
+ };
+ }
+}
+</script> \ No newline at end of file