mirror of
https://github.com/Luzifer/go-latestver.git
synced 2024-12-20 10:31:16 +00:00
Start implementing frontend
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
ca0e05c97e
commit
fe63b10e21
7 changed files with 356 additions and 2 deletions
106
package-lock.json
generated
106
package-lock.json
generated
|
@ -5,12 +5,17 @@
|
|||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "^2.0.6",
|
||||
"axios": "^0.24.0",
|
||||
"bootstrap": "^4.6.0",
|
||||
"bootstrap-vue": "^2.21.2",
|
||||
"bootswatch": "^4.6.0",
|
||||
"moment": "^2.29.1",
|
||||
"vue": "^2.6.14"
|
||||
"vue": "^2.6.14",
|
||||
"vue-router": "^3.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.1.0",
|
||||
|
@ -220,6 +225,60 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "0.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
|
||||
"integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-svg-core": {
|
||||
"version": "1.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz",
|
||||
"integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-brands-svg-icons": {
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-solid-svg-icons": {
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/vue-fontawesome": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-2.0.6.tgz",
|
||||
"integrity": "sha512-V3vT3flY15AKbUS31aZOP12awQI3aAzkr2B1KnqcHLmwrmy51DW3pwyBczKdypV8QxBZ8U68Hl2XxK2nudTxpg==",
|
||||
"peerDependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "~1 || >=1.3.0-beta1",
|
||||
"vue": "~2"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
|
||||
|
@ -3301,6 +3360,11 @@
|
|||
"resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz",
|
||||
"integrity": "sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA=="
|
||||
},
|
||||
"node_modules/vue-router": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz",
|
||||
"integrity": "sha512-FUlILrW3DGitS2h+Xaw8aRNvGTwtuaxrRkNSHWTizOfLUie7wuYwezeZ50iflRn8YPV5kxmU2LQuu3nM/b3Zsg=="
|
||||
},
|
||||
"node_modules/vue-template-compiler": {
|
||||
"version": "2.6.14",
|
||||
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz",
|
||||
|
@ -3538,6 +3602,41 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "0.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz",
|
||||
"integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg=="
|
||||
},
|
||||
"@fortawesome/fontawesome-svg-core": {
|
||||
"version": "1.2.36",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz",
|
||||
"integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
}
|
||||
},
|
||||
"@fortawesome/free-brands-svg-icons": {
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-f1witbwycL9cTENJegcmcZRYyawAFbm8+c6IirLmwbbpqz46wyjbQYLuxOc7weXFXfB7QR8/Vd2u5R3q6JYD9g==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
}
|
||||
},
|
||||
"@fortawesome/free-solid-svg-icons": {
|
||||
"version": "5.15.4",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz",
|
||||
"integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.36"
|
||||
}
|
||||
},
|
||||
"@fortawesome/vue-fontawesome": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-2.0.6.tgz",
|
||||
"integrity": "sha512-V3vT3flY15AKbUS31aZOP12awQI3aAzkr2B1KnqcHLmwrmy51DW3pwyBczKdypV8QxBZ8U68Hl2XxK2nudTxpg==",
|
||||
"requires": {}
|
||||
},
|
||||
"@humanwhocodes/config-array": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
|
||||
|
@ -5958,6 +6057,11 @@
|
|||
"resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz",
|
||||
"integrity": "sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA=="
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz",
|
||||
"integrity": "sha512-FUlILrW3DGitS2h+Xaw8aRNvGTwtuaxrRkNSHWTizOfLUie7wuYwezeZ50iflRn8YPV5kxmU2LQuu3nM/b3Zsg=="
|
||||
},
|
||||
"vue-template-compiler": {
|
||||
"version": "2.6.14",
|
||||
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz",
|
||||
|
|
|
@ -8,11 +8,16 @@
|
|||
"vue-template-compiler": "^2.6.14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.36",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.4",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.4",
|
||||
"@fortawesome/vue-fontawesome": "^2.0.6",
|
||||
"axios": "^0.24.0",
|
||||
"bootstrap": "^4.6.0",
|
||||
"bootstrap-vue": "^2.21.2",
|
||||
"bootswatch": "^4.6.0",
|
||||
"moment": "^2.29.1",
|
||||
"vue": "^2.6.14"
|
||||
"vue": "^2.6.14",
|
||||
"vue-router": "^3.5.3"
|
||||
}
|
||||
}
|
||||
|
|
52
src/app.vue
Normal file
52
src/app.vue
Normal file
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<div>
|
||||
<b-navbar
|
||||
class="mb-2"
|
||||
toggleable="lg"
|
||||
type="dark"
|
||||
variant="primary"
|
||||
>
|
||||
<b-navbar-brand :to="{name: 'index'}">
|
||||
<font-awesome-icon
|
||||
fixed-width
|
||||
:icon="['fas', 'cloud-download-alt']"
|
||||
/>
|
||||
Go-LatestVer
|
||||
</b-navbar-brand>
|
||||
|
||||
<b-navbar-toggle target="nav-collapse" />
|
||||
|
||||
<b-collapse
|
||||
id="nav-collapse"
|
||||
is-nav
|
||||
>
|
||||
<b-navbar-nav>
|
||||
<b-nav-item :to="{name: 'log'}">
|
||||
Log
|
||||
</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
|
||||
<!-- Right aligned nav items -->
|
||||
<b-navbar-nav class="ml-auto">
|
||||
<b-nav-item href="/log.rss">
|
||||
<font-awesome-icon
|
||||
fixed-width
|
||||
:icon="['fas', 'rss']"
|
||||
/>
|
||||
All Updates
|
||||
</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
</b-collapse>
|
||||
</b-navbar>
|
||||
|
||||
<b-container>
|
||||
<router-view />
|
||||
</b-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'GoLatestVerApp',
|
||||
}
|
||||
</script>
|
95
src/catalog_index.vue
Normal file
95
src/catalog_index.vue
Normal file
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-table
|
||||
:fields="fields"
|
||||
:items="catalog"
|
||||
small
|
||||
striped
|
||||
>
|
||||
<template #cell(_key)="data">
|
||||
<router-link :to="{name: 'entry', params: { name:data.item.name, tag: data.item.tag }}">
|
||||
{{ data.item.name }}:{{ data.item.tag }}
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<template #cell(version_time)="data">
|
||||
{{ moment(data.item.version_time).format('lll') }}
|
||||
</template>
|
||||
|
||||
<template #cell(_links)="data">
|
||||
<a
|
||||
v-for="link in data.item.links"
|
||||
:key="link.name"
|
||||
:href="link.url"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<font-awesome-icon
|
||||
fixed-width
|
||||
:icon="iconClassesToIcon(link.icon_class)"
|
||||
/>
|
||||
{{ link.name }}
|
||||
</a>
|
||||
</template>
|
||||
</b-table>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
catalog: [],
|
||||
fields: [
|
||||
{ key: '_key', label: 'Catalog Entry', sortable: true },
|
||||
{ key: 'current_version', label: 'Version' },
|
||||
{ key: 'version_time', label: 'Updated At', sortable: true },
|
||||
{ key: '_links', label: 'External Links' },
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchCatalogIndex() {
|
||||
axios.get('/v1/catalog')
|
||||
.then(resp => {
|
||||
this.catalog = resp.data
|
||||
})
|
||||
},
|
||||
|
||||
iconClassesToIcon(ic) {
|
||||
let namespace = 'fas'
|
||||
let icon = ''
|
||||
|
||||
for (const c of ic.split(' ')) {
|
||||
if (c === 'fa-fw') {
|
||||
continue
|
||||
}
|
||||
|
||||
if (['fab', 'fas'].includes(c)) {
|
||||
namespace = c
|
||||
}
|
||||
|
||||
if (c.startsWith('fa-')) {
|
||||
icon = c.replace('fa-', '')
|
||||
}
|
||||
}
|
||||
|
||||
return [namespace, icon]
|
||||
},
|
||||
|
||||
moment,
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.fetchCatalogIndex()
|
||||
},
|
||||
|
||||
name: 'GoLatestVerCatalogIndex',
|
||||
}
|
||||
</script>
|
59
src/log.vue
Normal file
59
src/log.vue
Normal file
|
@ -0,0 +1,59 @@
|
|||
<template>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-table
|
||||
:fields="fields"
|
||||
:items="logs"
|
||||
small
|
||||
striped
|
||||
>
|
||||
<template #cell(_key)="data">
|
||||
<router-link :to="{name: 'entry', params: { name:data.item.catalog_name, tag: data.item.catalog_tag }}">
|
||||
{{ data.item.catalog_name }}:{{ data.item.catalog_tag }}
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<template #cell(timestamp)="data">
|
||||
{{ moment(data.item.timestamp).format('lll') }}
|
||||
</template>
|
||||
</b-table>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
fields: [
|
||||
{ key: '_key', label: 'Catalog Entry' },
|
||||
{ key: 'version_from', label: 'Version From' },
|
||||
{ key: 'version_to', label: 'Version To' },
|
||||
{ key: 'timestamp', label: 'Updated At' },
|
||||
],
|
||||
|
||||
logs: [],
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchLog() {
|
||||
axios.get('/v1/log')
|
||||
.then(resp => {
|
||||
this.logs = resp.data
|
||||
})
|
||||
},
|
||||
|
||||
moment,
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.fetchLog()
|
||||
},
|
||||
|
||||
name: 'GoLatestVerLog',
|
||||
}
|
||||
</script>
|
12
src/main.js
12
src/main.js
|
@ -4,17 +4,29 @@ import 'bootstrap/dist/css/bootstrap.css'
|
|||
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||
import 'bootswatch/dist/darkly/bootstrap.css'
|
||||
|
||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||
import { fab } from '@fortawesome/free-brands-svg-icons'
|
||||
import { fas } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
|
||||
library.add(fab, fas)
|
||||
|
||||
import Vue from 'vue'
|
||||
import { BootstrapVue } from 'bootstrap-vue'
|
||||
import VueRouter from 'vue-router'
|
||||
|
||||
import App from './app.vue'
|
||||
import router from './router.js'
|
||||
|
||||
Vue.config.devtools = process.env.NODE_ENV === 'dev'
|
||||
Vue.component('FontAwesomeIcon', FontAwesomeIcon)
|
||||
Vue.use(BootstrapVue)
|
||||
Vue.use(VueRouter)
|
||||
|
||||
new Vue({
|
||||
components: { App },
|
||||
el: '#app',
|
||||
name: 'GoLatestVer',
|
||||
render: h => h(App),
|
||||
router,
|
||||
})
|
||||
|
|
27
src/router.js
Normal file
27
src/router.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
import CatalogEntry from './catalog_entry.vue'
|
||||
import CatalogIndex from './catalog_index.vue'
|
||||
import Log from './log.vue'
|
||||
import VueRouter from 'vue-router'
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
routes: [
|
||||
{
|
||||
component: CatalogIndex,
|
||||
name: 'index',
|
||||
path: '/',
|
||||
},
|
||||
{
|
||||
component: CatalogEntry,
|
||||
name: 'entry',
|
||||
path: '/:name/:tag',
|
||||
},
|
||||
{
|
||||
component: Log,
|
||||
name: 'log',
|
||||
path: '/log',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
export default router
|
Loading…
Reference in a new issue