before recipes:update

This commit is contained in:
2022-05-11 14:48:04 +02:00
parent 1b4ca82754
commit c84ec14cb5
46 changed files with 1363 additions and 1235 deletions

@ -1,42 +1,47 @@
<template>
<div>
<nav-bar
:user="user"
@invalidate-user="onInvalidateUser"
/>
<div class="container-fluid">
<div class="row">
<div class="col">
<nav-bar
:user="user"
@invalidate-user="onInvalidateUser"
/>
</div>
</div>
<b-container
fluid
class="mt-5 main-content"
>
<b-row>
<div class="col-2">
<sidebar/>
</div>
<div class="col-9 box">
<router-view
:quote="quote"
@user-authenticated="onUserAuthenticated"
/>
</div>
<div class="col mt-2"/>
</b-row>
</b-container>
<div class="row mt-5 main-content">
<div class="col-xl-3">
<sidebar/>
</div>
<div class="col-xl-9">
<router-view
:quote="quote"
@user-authenticated="onUserAuthenticated"
/>
</div>
<div class="col mt-2"/>
</div>
<footer-component/>
<div class="row">
<div class="col">
<footer-component/>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
import axios from 'axios'
import NavBar from '@/components/TheNavbar';
import Sidebar from '@/components/sidebar';
import FooterComponent from '@/components/footer';
import routerView from 'vue-router'
import NavBar from '@/components/TheNavbar'
import Sidebar from '@/components/TheSidebar'
import FooterComponent from '@/components/TheFooter'
export default {
name: 'App',
components: {
routerView,
Sidebar,
NavBar,
FooterComponent
@ -45,31 +50,32 @@ export default {
return {
user: null,
quote: null
};
}
},
mounted() {
if (window.user) {
this.user = window.user;
console.log(this.user);
this.user = window.user
console.log(this.user)
}
if (window.quote) {
this.quote = window.quote;
this.quote = window.quote
}
},
methods: {
onUserAuthenticated(userUri) {
console.log('authenticated');
console.log('authenticated')
axios
.get(userUri)
.then((response) => {
this.user = response.data;
});
this.$router.push('/');
this.user = response.data
})
this.$router.push('/')
},
onInvalidateUser() {
console.log('invalidated');
this.user = null;
console.log('invalidated')
this.user = null
window.user = null
}
}
};
}
</script>

@ -0,0 +1,49 @@
<template>
<div>
<div v-if="isExternal">
<a :href="to">
<span
:class="`fa fa-lg fa-fw ${fa}`"
aria-hidden="true"
/>
&nbsp;
<slot/>
</a>
&nbsp;
<span
class="fa fa-lg fa-fw fa-external-link"
aria-hidden="true"
/>
</div>
<router-link
v-else
v-bind="$props"
>
<span
:class="`fa fa-lg fa-fw ${fa}`"
aria-hidden="true"
/>
&nbsp;
<slot/>
</router-link>
</div>
</template>
<script>
import { RouterLink } from 'vue-router'
export default {
props: {
...RouterLink.props,
fa: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return typeof this.to === 'string' && this.to.startsWith('http')
}
}
}
</script>

@ -0,0 +1,110 @@
<template>
<div class="container box">
<form @submit.prevent="handleSubmit">
<div
v-if="error"
class="alert alert-danger"
>
{{ error }}
</div>
<div class="form-group mt-2">
<label for="exampleInputEmail1">Username</label>
<input
id="username"
v-model="username"
type="text"
class="form-control"
aria-describedby="emailHelp"
placeholder="Enter email"
>
</div>
<div class="form-group mt-2">
<label for="password">Password</label>
<input
id="password"
v-model="password"
type="password"
class="form-control"
placeholder="Password"
>
</div>
<div class="form-check mt-2">
<input
id="remember-me"
type="checkbox"
class="form-check-input"
>
<label
class="form-check-label"
for="remember-me"
>
Remember Me
</label>
</div>
<button
type="submit"
class="btn btn-primary mt-2 mb-2"
:class="{ disabled: isLoading }"
>
Log in
</button>
</form>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'LoginForm',
/*
props: {
user: {
Type: Object
}
},
*/
data() {
return {
username: '',
password: '',
error: '',
isLoading: false
}
},
methods: {
handleSubmit() {
console.log('handle submit')
this.isLoading = true
this.error = ''
axios
.post('/login', {
username: this.username,
password: this.password
})
.then((response) => {
console.log(response.headers)
this.$emit('user-authenticated', response.headers.location)
this.username = ''
this.password = ''
})
.catch((error) => {
console.log(error.response.data)
if (error.response.data.error) {
this.error = error.response.data.error
} else {
this.error = 'Unknown error'
}
})
.finally(() => {
this.isLoading = false
})
}
}
}
</script>
<style scoped lang="scss">
</style>

@ -0,0 +1,11 @@
<template>
<div>
404 Not Found
</div>
</template>
<script>
export default {
name: 'NotFound'
}
</script>

@ -0,0 +1,55 @@
<template>
<footer class="dark fixed-bottom">
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col text-center">
<div>
powered by
<router-link
to="/"
class="d-inline-block mx-auto"
>
<img
src="/build/images/Spookie/spookie_64x64.png"
alt="Spookie"
>
</router-link>
</div>
</div>
<div class="col md-4 text-left">
<div id="legal">
<h5 class="bd-text-purple-bright mb-1 mt-3">
Legal
</h5>
<ul class="list-unstyled ml-3">
<li>
<router-link :to="{ name: 'Pages', params: {slug: 'imprint'}}">
Imprint
</router-link>
</li>
<li>
<router-link to="/pages/privacy-policy">
Privacy Policy
</router-link>
</li>
</ul>
</div>
</div>
</div>
</div>
</footer>
</template>
<script>
export default {
name: 'TheFooter'
}
</script>
<style type="scss">
footer {
color: lightgray;
background: #0e0e10;
}
</style>

@ -1,99 +1,151 @@
<template>
<b-navbar
toggleable="lg"
type="dark"
variant="dark"
fixed="top"
>
<b-navbar-brand to="/">
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top navbar-top">
<router-link
class="navbar-brand"
:to="{ name: 'Home' }"
>
<img
id="site-logo"
src="/build/images/24unix/24_logo_bg_96x96.png"
class="img-fluid"
alt="24unix.net"
>
</b-navbar-brand>
<b-navbar-toggle target="nav-collapse" />
<b-collapse
id="nav-collapse"
is-nav
</router-link>
<button
class="navbar-toggler border-0"
type="button"
data-toggle="collapse"
data-target="#CollapsingNavbar"
>
<!--
<b-nav-form>
<b-form-input size="sm" class="mr-sm-2" placeholder="Search"></b-form-input>
<b-button size="sm" class="my-2 my-sm-0" type="submit">Search</b-button>
</b-nav-form>
-->
<!--
<b-nav-item-dropdown text="Lang" right>
<b-dropdown-item href="#">EN</b-dropdown-item>
<b-dropdown-item href="#">ES</b-dropdown-item>
<b-dropdown-item href="#">RU</b-dropdown-item>
<b-dropdown-item href="#">FA</b-dropdown-item>
</b-nav-item-dropdown>
-->
<b-navbar-nav class="ml-auto mr-5">
<b-button
v-if="!isLoggedIn"
to="/form_login"
>
Login
</b-button>
<b-dropdown
v-else
id="dropdown"
:text="user.username"
class="m-md-2"
type="dark"
>
<b-dropdown-item>
<b-link
:to="{ name: 'Profile' }"
class="fa fa-lg fa-fw fa-user"
aria-hidden="true"
/>&nbsp;Profile
</b-dropdown-item>
<b-dropdown-item>
<span
class="fa fa-lg fa-fw fa-wrench"
aria-hidden="true"
/>&nbsp;Settings
</b-dropdown-item>
<b-dropdown-divider />
<b-dropdown-item @click="logout">
<span
class="fa fa-lg fa-fw fa-sign-out"
aria-hidden="true"
/>&nbsp;Logout
</b-dropdown-item>
</b-dropdown>
</b-navbar-nav>
</b-collapse>
</b-navbar>
</button>
<div
id="CollapsingNavbar"
class="collapse navbar-collapse"
>
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<div v-if="isLoggedIn">
<button
v-if="isLoggedIn"
data-bs-target="#dropdown-menu"
data-bs-toggle="dropdown"
class="btn btn-primary button-login dropdown-toggle ml-auto mb-2 mr-5"
:to="{ name: 'Home'}"
>
{{ user.username }}
</button>
<div
id="dropdown-menu"
class="dropdown-menu dropdown-menu-dark dropdown-menu-end"
aria-labelledby="navbar-dropdown"
>
<router-link
:to="{name: 'Profile'}"
class="dropdown-item"
href="/profile"
>
<span
class="fa fa-lg fa-fw fa-user"
aria-hidden="true"
/>
Profile
</router-link>
<a
class="dropdown-item"
href="#"
>
<span
class="fa fa-lg fa-fw fa-wrench"
aria-hidden="true"
/>
Settings</a>
<div class="dropdown-divider"/>
<a
class="dropdown-item"
href="/admin"
>
<span
class="fa fa-lg fa-fw fa-cog"
aria-hidden="true"
/>
Administration
</a>
<div class="dropdown-divider"/>
<a
class="dropdown-item"
href="/logout"
>
<span
class="fa fa-lg fa-fw fa-sign-out"
aria-hidden="true"
/>
&nbsp;Logout
</a>
</div>
</div>
<button
v-else
class="btn btn-outline-primary"
>
<router-link :to="{ name: 'LoginForm'}">
<span
class="fa fa-sign-in fa-lg fa-fw"
aria-hidden="true"
/>
Login
</router-link>
</button>
</li>
</ul>
</div>
<!--
<span
class="fa fa-lg fa-fw fa-wrench"
aria-hidden="true"
/>&nbsp;Settings
</b-dropdown-item>
<b-dropdown-divider/>
<b-dropdown-item @click="logout">
<span
class="fa fa-lg fa-fw fa-sign-out"
aria-hidden="true"
/>&nbsp;Logout
</b-dropdown-item>
-->
</nav>
</template>
<script>
import axios from 'axios';
import axios from 'axios'
import 'vue-navigation-bar/dist/vue-navigation-bar.css'
export default {
name: 'TheNavbar',
props: ['user'],
components: {},
props: {
user: {
type: Object,
default: null
}
},
data: () => ({}),
computed: {
isLoggedIn() {
return !!this.user;
return !!this.user
}
},
methods: {
logout() {
console.log('logout');
console.log('logout')
axios
.get('/logout')
.then(this.$emit('invalidate-user'));
.then(this.$emit('invalidate-user'))
}
}
};
}
</script>
<style>

@ -0,0 +1,57 @@
<template>
<div
id="main-menu"
class="container-fluid col sidenav-left box text-start"
>
<ul>
<li
v-for="link in links"
:key="link.url"
>
<AppLink
:to="link.url"
:fa="link.fa"
>
{{ link.name }}
</AppLink>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'TheSidebar',
data: () => ({
links: [
{
name: 'Projects',
url: 'Projects',
fa: 'fa-file-code-o',
},
{
name: 'Gitea',
url: 'https://git.24unix.net',
fa: 'fa-gitea',
},
{
name: 'NextCloud',
url: 'https://cloud.24unix.net',
fa: 'fa-nextcloud',
},
{
name: 'Pastebin',
url: 'https://pastebin.24unix.net',
fa: 'fa-paste',
},
{
name: 'YOURLS',
url: 'https://y.24unix.net',
fa: 'fa-link',
external: true
}
]
})
}
</script>

@ -1,37 +0,0 @@
<template>
<footer class="dark fixed-bottom"> <!-- :class="['bd-footer', 'text-muted']"> -->
<b-container class="mt-5">
<b-row class="justify-content-center">
<b-col class="text-center">
<div>powered by
<b-link to="/" class="d-inline-block mx-auto"><img src="/build/images/Spookie/spookie_64x64.png" alt="Spookie"></b-link>
</div>
</b-col>
<b-col cols="auto" md="4" class="text-left">
<div id="legal">
<h5 class="bd-text-purple-bright mb-1 mt-3">Legal</h5>
<ul class="list-unstyled ml-3">
<li><b-link to="/pages/imprint">Imprint</b-link></li>
<li><b-link to="/pages/privacy-policy">Privacy Policy</b-link></li>
</ul>
</div>
</b-col>
</b-row>
</b-container>
</footer>
</template>
<script>
export default {
name: "Footer"
}
</script>
<style type="scss">
footer {
color: lightgray;
background: #0e0e10;
}
</style>

@ -1,71 +0,0 @@
<template>
<form v-on:submit.prevent="handleSubmit">
<div v-if="error" class="alert alert-danger">
{{ error }}
</div>
<div class="form-group">
<label for="exampleInputEmail1">Username</label>
<input type="text" v-model="username" class="form-control" id="username"
aria-describedby="emailHelp" placeholder="Enter email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" v-model="password" class="form-control"
id="exampleInputPassword1" placeholder="Password">
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck1">
<label class="form-check-label" for="exampleCheck1">I like cheese</label>
</div>
<button type="submit" class="btn btn-primary" v-bind:class="{ disabled: isLoading }">Log in</button>
</form>
</template>
<script>
import axios from 'axios';
export default {
name: 'Login',
data() {
return {
username: '',
password: '',
error: '',
isLoading: false
}
},
props: ['user'],
methods: {
handleSubmit() {
console.log("handle submit");
this.isLoading = true
this.error = ''
axios
.post('/login', {
username: this.username,
password: this.password
})
.then(response => {
console.log(response.headers);
this.$emit('user-authenticated', response.headers.location);
this.username = '';
this.password = '';
}).catch(error => {
console.log(error.response.data);
if (error.response.data.error) {
this.error = error.response.data.error
} else {
this.error = 'Unknown error'
}
}).finally(() => {
this.isLoading = false;
})
},
},
}
</script>
<style scoped lang="scss">
</style>

@ -1,11 +0,0 @@
<template>
<div>
404 Not Found
</div>
</template>
<script>
export default {
name: "NotFound"
}
</script>

@ -1,62 +1,77 @@
<template>
<div v-if="!isLoading">
<div id="edit-wrapper">
<div class="editor mt-2">
<VueEditor v-model="page.content"></VueEditor>
</div>
<b-button @click="saveContent" class="mt-3 mb-2">Save</b-button>
</div>
</div>
<div v-else>
<i class="fa fa-spinner fa-spin fa-3x fa-fw"></i>
<span class="sr-only">Loading </span></div>
<div
v-if="!isLoading"
class="box p-3"
>
<tab-wrapper>
<tab-content title="Visual Editor">
<div class="editor mt-2">
<!-- *** disbaled = true? -->
<VueEditor v-model="page.content"/>
</div>
</tab-content>
<tab-content title="Raw Content">
<div>
<textarea
v-model="page.content"
class="p-fluid"
/>
</div>
</tab-content>
</tab-wrapper>
<button
class="btn btn-primary mt-3 mb-2"
@click="saveContent"
>
Save
</button>
</div>
<div v-else>
<i class="fa fa-spinner fa-spin fa-3x fa-fw"/>
<span class="sr-only">Loading </span>
</div>
</template>
<script>
import axios from "axios";
import axios from 'axios'
// Basic Use - Covers most scenarios
import { VueEditor } from "vue2-editor";
import { VueEditor } from 'vue3-editor'
import TabWrapper from '@/components/tabs/TabWrapper'
import TabContent from '@/components/tabs/TabContent'
export default {
name: 'PagesEdit',
components: {
VueEditor
},
data: () => ({
page: null,
isLoading: true
}),
methods: {
saveContent() {
console.log(this.page)
axios
.put('/api/pages/' + this.page.id, this.page)
.then(response => {
console.log("resp:" + response)
})
}
},
beforeMount() {
const slug = this.$route.params.slug
console.log("slug: " + slug)
name: 'PagesEdit',
components: {
VueEditor,
TabWrapper,
TabContent
},
data: () => ({
page: null,
isLoading: true
}),
beforeMount() {
const { slug } = this.$route.params
console.log(`slug: ${slug}`)
axios
.get('/api/pages?slug=' + slug)
.then(response => {
this.page = response.data['hydra:member'][0]
this.isLoading = false
})
},
axios
.get(`/api/pages?slug=${slug}`)
.then((response) => {
[this.page] = response.data['hydra:member']
this.isLoading = false
})
},
methods: {
saveContent() {
console.log(this.page)
axios
.put(`/api/pages/${this.page.id}`, this.page)
.then((response) => {
console.log(`resp:${response}`)
})
}
}
}
</script>
<style>
.ql-container {
height: 800px !important;
overflow-y: scroll;
}
</style>

@ -1,48 +1,64 @@
<template>
<div>
<div class="box ma7 p-5">
<h2
v-if="page"
v-html="page.name"
/>
<div
v-if="page"
v-html="page.content"
/>
<h2 v-if="page" v-html="page.name"></h2>
<div v-if="page" v-html="page.content"></div>
<b-button :to="editTarget" variant="outline"><i class="fa fa-2x fa-fw fa-edit"></i></b-button>
<hr>
</div>
<router-link
:to="editTarget"
variant="outline"
>
<button>
<i class="fa fa-2x fa-fw fa-edit"/>
</button>
</router-link>
<hr>
</div>
</template>
<script>
import axios from 'axios';
import axios from 'axios'
export default {
name: "Pages",
data: () => ({
page: null
}),
watch: {
$route() {
console.log("watch called")
this.getPagesDetails()
}
},
beforeMount() {
this.getPagesDetails()
},
methods: {
getPagesDetails() {
const slug = this.$route.params.slug
console.log("slug: " + slug)
axios
.get('/api/pages?slug=' + slug)
.then(response => (this.page = response.data['hydra:member'][0]))
}
},
computed: {
editTarget() {
if (this.page) {
return "/pages/edit/" + this.page.slug
}
}
}
name: 'PagesDisplay',
props: {
slug: {
type: String,
required: true
}
},
data: () => ({
page: null
}),
computed: {
editTarget() {
if (this.page) {
return `/pages/edit/${this.page.slug}`
}
return ''
}
},
beforeMount() {
this.getPagesDetails()
this.$watch(
() => this.slug,
() => {
this.getPagesDetails()
}
)
},
methods: {
async getPagesDetails() {
await axios.get(`/api/pages?slug=${this.slug}`)
.then((response) => {
[this.page] = response.data['hydra:member']
})
}
}
}
</script>
</script>

@ -3,7 +3,7 @@
v-if="isLoading"
class="circle"
>
<i class="fa fa-spinner fa-spin fa-3x fa-fw" />
<i class="fa fa-spinner fa-spin fa-3x fa-fw"/>
<span class="sr-only">Loading </span>
</div>
<div
@ -23,12 +23,14 @@
<h2>{{ project.name }}</h2>
</div>
<div>
Source: <b-link
:to="project.url"
Source:
<a
:href="project.url"
target="_blank"
>
{{ project.url }}
</b-link>&nbsp
</a>
&nbsp;
<i
class="fa fa-external-link"
aria-hidden="true"
@ -36,12 +38,12 @@
</div>
<div class="row mt-5">
<div class="col-sm-12">
<!-- eslint-disable vue/no-v-html -->
<div
class="article-text"
v-html="readmeToHtml"
>
{{ }}
</div>
/>
<!-- eslint-enable -->
</div>
</div>
</div>
@ -52,7 +54,7 @@
<script>
import axios from 'axios'
import { marked } from 'marked';
import { marked } from 'marked'
import Author from '@/components/users/UserCard'
export default {
@ -71,6 +73,7 @@ export default {
if (!this.isLoading) {
return marked(this.readme)
}
return ''
}
},
mounted() {
@ -78,15 +81,14 @@ export default {
console.log(id)
axios
.get(`/api/projects/${id}`)
.then((response) => {
console.log(response)
this.project = response.data
console.log(this.project);
.then((projectResponse) => {
this.project = projectResponse.data
console.log(this.project)
axios
.get(`${this.project.url}/raw/branch/master/README.md`)
.then((response) => {
this.readme = response.data
this.isLoading = false;
this.isLoading = false
console.log(response)
})
.catch((error) => {
@ -101,5 +103,5 @@ export default {
getProjects() {
}
}
};
}
</script>

@ -3,7 +3,7 @@
v-if="isLoading"
class="circle"
>
<i class="fa fa-spinner fa-spin fa-3x fa-fw" />
<i class="fa fa-spinner fa-spin fa-3x fa-fw"/>
<span class="sr-only">Loading </span>
</div>
<div
@ -16,14 +16,14 @@
</h2>
<!-- projects List -->
<div class="col-sm-12">
<b-col
<div
v-for="project in projects"
:key="project.id"
>
<div class="project-container bg-dark my-4">
<div class="row">
<div class="col-sm-3">
<b-link :to="'/projects/' + project.id">
<router-link :to="'/projects/' + project.id">
<img
v-if="project.teaserImage"
class="blog-img"
@ -36,70 +36,78 @@
src="/build/images/24unix/24_logo_bg_96x96.png"
alt="Teaser"
>
</b-link>
</router-link>
<br>
<div>
<b-col
<div
v-for="developer in project.developer"
:key="developer"
class="col"
>
<author :author-iri="developer" />
</b-col>
<user-card :author-iri="developer"/>
</div>
</div>
</div>
<div class="col-sm-8 mt-2">
<b-link :to="'/projects/' + project.id">
<router-link :to="'/projects/' + project.id">
<div class="article-title d-inline-block pl-3 align-middle">
<h2 v-html="project.name" />
<h2 v-html="project.name"/>
</div>
</b-link>
</router-link>
<br>
<div class="blog-teaser mb-2 pb-2 text-xl-start">
<span v-html="project.description" />
<span v-html="project.description"/>
<br>
<br>
started: <span v-html="project.createdAt" />
started: <span v-html="formatDate(project.createdAt)"/>
</div>
</div>
</div>
</div>
</b-col>
</div>
</div>
<!--
<div class="text-xl-start">
<b-link to="/add">
<i class="fa fa-plus-circle" />
</b-link>
<router-link to="/add">
<i class="fa fa-plus-circle"/>
</router-link>
</div>
-->
</div>
</div>
</template>
<script>
import axios from 'axios';
import axios from 'axios'
import Author from '@/components/users/UserCard';
import UserCard from '@/components/users/UserCard'
export default {
name: 'ProjectsList',
components: {
Author
UserCard,
},
data: () => ({
projects: null,
isLoading: true
}),
mounted() {
this.getProjects();
this.getProjects()
},
methods: {
getProjects() {
axios
.get('/api/projects')
.then((response) => (this.projects = response.data['hydra:member']));
this.isLoading = false;
console.log(this.projects);
.then((response) => {
this.projects = response.data['hydra:member']
})
this.isLoading = false
console.log(this.projects)
},
formatDate(date) {
return new Date(date).toLocaleDateString('de-DE')
}
}
};
}
</script>

@ -1,5 +1,5 @@
<template>
<div class="d-flex flex-column justify-content-between mt-2 mb-2">
<div class="d-flex flex-column justify-content-between box mt-2 p-3 mb-2">
<div></div>
<div>
<span v-html="quote"></span>
@ -13,4 +13,4 @@ export default {
name: 'Quote',
props: ['quote']
}
</script>
</script>

@ -1,34 +0,0 @@
<template>
<b-container fluid class="col sidenav-left box text-start" id="main-menu">
<ul>
<li>
<i class="fa fa-lg fa-fw fa-file-code-o" aria-hidden="true"></i>&nbsp
<b-link to="/projects">Projects</b-link>
</li>
<li>
<i class="fa fa-lg fa-fw fa-gitea" aria-hidden="true"></i>&nbsp;
<b-link href="https://git.24unix.net" target="_blank">Gitea</b-link>&nbsp<i class="fa fa-external-link" aria-hidden="true"></i>
</li>
<li>
<i class="fa fa-lg fa-fw fa-nextcloud" aria-hidden="true"></i>&nbsp;
<b-link href="//cloud.24unix.net" target="_blank">NextCloud</b-link>&nbsp;<i class="fa fa-external-link" aria-hidden="true"></i>
</li>
<li>
<i class="fa fa-lg fa-fw fa-paste" aria-hidden="true"></i>&nbsp;
<b-link href="//pastebin.24unix.net" target="_blank">Pastebin</b-link>&nbsp;<i class="fa fa-external-link" aria-hidden="true"></i>
</li>
<li>
<i class="fa fa-lg fa-fw fa-link" aria-hidden="true"></i>&nbsp;
<b-link href="//y.24unix.net" target="_blank">YOURLS</b-link>&nbsp;<i class="fa fa-external-link" aria-hidden="true"></i>
</li>
</ul>
</b-container>
</template>
<script>
export default {
name: "Sidebar"
}
</script>

@ -0,0 +1,25 @@
<template lang="html">
<div v-show="title == selectedTitle">
<slot/>
</div>
</template>
<script>
import { inject } from 'vue'
export default {
props: {
title: {
type: String,
required: true
}
},
setup() {
const selectedTitle = inject('selectedTitle')
return {
selectedTitle
}
}
}
</script>

@ -0,0 +1,70 @@
<template lang="html">
<div class="tabs">
<ul class="tabs-header">
<li
v-for="title in tabTitles"
:key="title"
:class="{ selected: title === selectedTitle }"
@click="selectedTitle = title"
>
{{ title }}
</li>
</ul>
<slot/>
</div>
</template>
<script>
import { ref, provide } from 'vue'
export default {
name: 'TabWrapper',
setup(props, { slots }) {
const tabTitles = ref(slots.default()
.map((tab) => tab.props.title))
const selectedTitle = ref(tabTitles.value[0])
provide('selectedTitle', selectedTitle)
return {
selectedTitle,
tabTitles
}
},
data: () => ({
selectedIndex: 0,
tabs: []
}),
created() {
},
}
</script>
<style>
.tabs {
width: auto;
margin: 0 auto;
}
.tabs-header {
margin-bottom: 10px;
list-style: none;
display: flex;
}
.tabs-header li {
width: 140px;
text-align: center;
padding: 10px 20px;
margin-right: 10px;
background-color: #ddd;
border-radius: 5px;
color: black;
cursor: pointer;
transition: 0.4s all ease-out;
}
.tabs-header li.selected {
background-color: #0984e3;
color: white;
}
</style>

@ -15,17 +15,16 @@
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
Profile of {{ user.username }}
<img
class="rounded-circle mt-5"
width="150px"
src="/build/images/tracer_schmolle.png"
class="rounded-circle border-1 mt-5"
src="/build/images/tracer_schmolle150x150.png"
alt="profile image"
>
<span class="font-weight-bold">{{ user.username }}</span>
<!--<span class="font-weight-bold"><a
href="{{ path('app_main', { '_switch_user': app.user.username }) }}">switch user {{
user.username
}}</span>
-->
<!--
<span class="font-weight-bold">
<a href="{{ path('app_main', { '_switch_user': app.user.username }) }}">
switch user {{ user.username }}</span>
-->
<span class="text-white-50">
<i class="fa fa-lg fa-envelope me-1"/>{{ user.email }}
</span>
@ -52,7 +51,7 @@
</template>
<script>
import axios from 'axios';
import axios from 'axios'
export default {
name: 'ProfileView',
@ -63,9 +62,9 @@ export default {
computed: {
getUserEndpoint() {
if (this.$route.params.username) {
return `/api/users?username=${this.$route.params.username}`;
return `/api/users?username=${this.$route.params.username}`
}
return '/api/users?username=tracer';
return '/api/users?username=tracer'
}
},
mounted() {
@ -73,14 +72,14 @@ export default {
.get(this.getUserEndpoint)
.then((response) => {
console.log(response);
[this.user] = response.data['hydra:member'];
[this.user] = response.data['hydra:member']
console.log(this.user);
this.isLoading = false;
console.log(this.user)
this.isLoading = false
})
.catch((error) => {
console.log(error);
});
console.log(error)
})
}
};
}
</script>

@ -1,53 +1,67 @@
<template>
<div v-if="isLoading" class="circle">
<i class="fa fa-spinner fa-spin fa-3x fa-fw"></i>
<span class="sr-only">Loading </span>
</div>
<div v-else class="mt-1 mb-1">
<b-link class="align-left blog-details" :to="'/profile/' + author.username">
<img class="article-author-img rounded-circle"
:src="'build/images/' + author.avatar"
alt="profile"></b-link>
<b-link :to="'/profile/' + author.username">
{{ author.username }}
</b-link>
</div>
<div
v-if="isLoading"
class="circle"
>
<i class="fa fa-spinner fa-spin fa-3x fa-fw"/>
<span class="sr-only">Loading </span>
</div>
<div
v-else
class="mt-1 mb-1"
>
<router-link
class="align-left blog-details"
:to="'/profile/' + author.username"
>
<img
class="article-author-img rounded-circle"
:src="'build/images/' + author.avatar"
alt="profile"
>
</router-link>
<router-link :to="'/profile/' + author.username">
{{ author.username }}
</router-link>
</div>
</template>
<script>
import axios from "axios";
import axios from 'axios'
export default {
name: "Author",
data: () => ({
author: null,
isLoading: true
}),
props: ["authorIri"],
mounted() {
this.getAuthor();
},
methods: {
getAuthor() {
console.log("here" + this.authorIri);
axios
.get(this.authorIri)
.then(response => {
console.log("response");
console.log(response);
this.author = response.data;
console.log(this.author);
this.isLoading = false;
})
.catch(error => {
console.log(error);
});
console.log(this.author);
}
}
};
</script>
name: 'UserCard',
props: {
authorIri: {
type: String,
required: true
}
},
data: () => ({
author: null,
isLoading: true
}),
mounted() {
this.getAuthor()
},
methods: {
getAuthor() {
console.log(`here${this.authorIri}`)
axios
.get(this.authorIri)
.then((response) => {
console.log('response')
console.log(response)
this.author = response.data
console.log(this.author)
this.isLoading = false
})
.catch((error) => {
console.log(error)
})
console.log(this.author)
}
}
}
</script>

@ -1,63 +1,54 @@
// assets/js/index.js
// End Matomo Code
import '../styles/app.scss';
/*
require('@fortawesome/fontawesome-free/css/all.min.css');
require('@fortawesome/fontawesome-free/js/all.js');
*/
import '../styles/app.scss'
// CKEditor
//require '@'
import '../styles/ckeditor.css';
import '../styles/ckeditor.css'
import 'fork-awesome/scss/fork-awesome.scss'
import Vue from 'vue';
import { BootstrapVue, IconsPlugin, NavbarPlugin } from 'bootstrap-vue';
import VueRouter from 'vue-router';
import { createApp } from 'vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap/dist/js/bootstrap'
import { createPinia, PiniaVuePlugin } from 'pinia';
import router from '@/router';
import App from '@/App';
import PrimeVue from 'primevue/config'
import 'primevue/resources/primevue.min.css'
//import 'primeicons/primeicons.css'
import 'primevue/resources/themes/lara-dark-blue/theme.css'
import { createPinia } from 'pinia'
import Router from '@/router'
import AppLink from '@/components/AppLink'
import App from '@/App'
/* eslint-disable */
globalThis.__VUE_OPTIONS_API__ = true
globalThis.__VUE_PROD_DEVTOOLS__ = true
// Matomo
const _paq = window._paq = window._paq || []
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView'])
_paq.push(['enableLinkTracking']);
(function () {
const u = 'https://analytics.24unix.net/'
_paq.push(['setTrackerUrl', `${u}matomo.php`])
_paq.push(['setSiteId', '1'])
const d = document
const g = d.createElement('script')
const
s = d.getElementsByTagName('script')[0]
g.async = true
g.src = `${u}matomo.js`
s.parentNode.insertBefore(g, s)
}())
// End Matomo Code
/* eslint-enable */
//globalThis.__VUE_OPTIONS_API__ = true;
//globalThis.__VUE_PROD_DEVTOOLS__ = true;
/* eslint-disable */
// Matomo
const _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function () {
const u = 'https://analytics.24unix.net/';
_paq.push(['setTrackerUrl', `${u}matomo.php`]);
_paq.push(['setSiteId', '1']);
const d = document; const g = d.createElement('script'); const
s = d.getElementsByTagName('script')[0];
g.async = true;
g.src = `${u}matomo.js`;
s.parentNode.insertBefore(g, s);
}());
/* eslint-enable */
require('fork-awesome/scss/fork-awesome.scss');
Vue.use(BootstrapVue);
Vue.use(VueRouter);
Vue.use(IconsPlugin);
Vue.use(NavbarPlugin);
Vue.config.productionTip = false;
Vue.use(PiniaVuePlugin);
const pinia = createPinia();
new Vue({
router,
pinia,
render: (h) => h(App)
})
.$mount('#app');
createApp(App)
.component('AppLink', AppLink)
.use(createPinia())
.use(Router)
.use(PrimeVue)
.mount('#app')

@ -1,55 +1,66 @@
import Router from 'vue-router';
import LoginForm from '@/components/login';
import Quotes from '@/components/quotes';
import Pages from '@/components/pages';
import PagesEdit from '@/components/pages/edit';
import ProjectsList from '@/components/projects';
import ProjectsDetails from '@/components/projects/details';
import ProfileView from '@/components/users/ProfileView';
import NotFound from '@/components/not-found';
import { createRouter, createWebHistory } from 'vue-router'
import LoginForm from '@/components/LoginForm'
import Quotes from '@/components/quotes'
import Pages from '@/components/pages'
import PagesEdit from '@/components/pages/edit'
import ProjectsList from '@/components/projects'
import ProjectsDetails from '@/components/projects/ProjectDetails'
import ProfileView from '@/components/users/ProfileView'
import NotFound from '@/components/NotFound'
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Home',
component: Quotes
},
{
path: '/form_login',
name: 'LoginForm',
component: LoginForm
},
{
path: '/projects',
name: 'Projects',
component: ProjectsList
},
{
path: '/projects/:id',
name: 'ProjectDetails',
component: ProjectsDetails
},
{
path: '/pages/:slug',
name: 'Pages',
component: Pages
},
{
path: '/pages/edit/:slug',
component: PagesEdit,
meta: { requiredAuth: true }
},
{
path: '/profile/:username?',
name: 'Profile',
component: ProfileView
},
{
path: '*',
name: 'NotFound',
component: NotFound
}
]
});
const routes = [
{
path: '/',
name: 'Home',
component: Quotes
},
{
path: '/form_login',
name: 'LoginForm',
component: LoginForm
},
{
path: '/projects',
name: 'Projects',
component: ProjectsList
},
{
path: '/projects/:id',
name: 'ProjectDetails',
component: ProjectsDetails
},
{
path: '/pages/:slug',
name: 'Pages',
component: Pages,
props: true
},
{
path: '/pages/edit/:slug',
component: PagesEdit,
meta: { requiredAuth: true }
},
{
path: '/profile/:username?',
name: 'Profile',
component: ProfileView
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
/* eslint-disable */
router.beforeEach((to) => {
if (to.meta.requiredAuth && !window.user) {
return { name: 'LoginForm' }
}
})
export default router