while upgrading to symfony 6.1

This commit is contained in:
tracer 2022-10-28 18:48:25 +02:00
parent 433603fad2
commit e97f8e43bf
58 changed files with 1743 additions and 4656 deletions

8
.env
View File

@ -24,7 +24,6 @@ APP_SECRET=06f6b2aee3d5d74c8ce1db7d26a1dd5e
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7"
DATABASE_URL="mysql://24unix:24.unix@127.0.0.1:3306/24unix"
###< doctrine/doctrine-bundle ###
###> symfony/mailer ###
@ -36,3 +35,10 @@ MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=false
###> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
###< nelmio/cors-bundle ###
###> symfony/messenger ###
# Choose one of the transports below
# MESSENGER_TRANSPORT_DSN=doctrine://default
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
###< symfony/messenger ###

13
TODO
View File

@ -1,11 +1,10 @@
entity types
accent color #d43934
remove vue
use bootsrap
use turbo
make unit tests
- use quill vue
- add linenumbering
- add yntax highlighning
- pinia
- harden Api-Platform
- learn tailwind

12
assets/app.js Normal file
View File

@ -0,0 +1,12 @@
/*
* Welcome to your app's main JavaScript file!
*
* We recommend including the built version of this JavaScript file
* (and its CSS file) in your base layout (base.html.twig).
*/
// any CSS you import will output into a single css file (app.css in this case)
import './styles/app.css';
// start the Stimulus application
import './bootstrap';

11
assets/bootstrap.js vendored Normal file
View File

@ -0,0 +1,11 @@
import { startStimulusApp } from '@symfony/stimulus-bridge';
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
export const app = startStimulusApp(require.context(
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
true,
/\.[jt]sx?$/
));
// register any custom, 3rd party controllers here
// app.register('some_controller_name', SomeImportedController);

4
assets/controllers.json Normal file
View File

@ -0,0 +1,4 @@
{
"controllers": [],
"entrypoints": []
}

View File

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
}
}

View File

@ -1,70 +0,0 @@
<template>
<v-app>
<v-app-bar color="grey-lighten-2"/>
<!--
<the-navbar
@invalidate-user="onUserInvalidate"
/>
-->
<v-navigation-drawer></v-navigation-drawer>
<v-main class="container-fluid text-center">
<div class="col-xl-3">
<the-sidebar/>
</div>
<div class="col-xl-9">
<suspense>
<template #default>
<router-view
@user-authenticated="onUserAuthenticated"
/>
</template>
<template #fallback>
<div class="loading">
loading
</div>
</template>
</suspense>
</div>
<div class="col mt-2"/>
</v-main>
<div class="row">
<div class="col">
<the-footer/>
</div>
</div>
</v-app>
</template>
<script setup>
import axios from 'axios'
import { useRoute } from 'vue-router'
//import RouterView from 'vue-router'
import TheNavbar from '@/components/TheNavbar'
import TheSidebar from '@/components/TheSidebar'
import TheFooter from '@/components/TheFooter'
if (window.user) {
const { user } = window
}
if (window.quote) {
const { quote } = window
}
const onUserAuthenticated = (userUri) => {
//console.log('authenticated')
axios
.get(userUri)
.then((response) => {
this.user = response.data
})
this.$router.push('/')
}
const onUserInvalidate = () => {
//console.log('invalidated')
this.user = null
window.user = null
}
</script>

View File

@ -1,48 +0,0 @@
<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
:to="{ name: props.to }"
>
<span
:class="`fa fa-lg fa-fw ${fa}`"
aria-hidden="true"
/>
&nbsp;
<slot/>
</router-link>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { RouterLink } from 'vue-router'
const props = defineProps({
to: {
type: String,
required: true
},
fa: {
type: String,
default: ''
}
})
const isExternal = computed(() => props.to.startsWith('http'))
</script>

View File

@ -1,10 +0,0 @@
<template>
<div></div>
</template>
<script>
export default {
name: 'HandleLogout'
}
</script>

View File

@ -1,97 +0,0 @@
<template>
<div class="container box">
<form @submit.prevent="handleSubmit">
<div
v-if="errorMessage"
class="alert alert-danger mt-2"
>
{{ errorMessage }}
</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 setup>
import { ref } from 'vue'
import axios from 'axios'
const username = ref('')
const password = ref('')
const errorMessage = ref('')
const isLoading = ref(false)
const emit = defineEmits(['user-authenticated'])
const handleSubmit = () => {
//console.log('handle submit')
isLoading.value = true
axios
.post('/login', {
username: username.value,
password: password.value
})
.then((response) => {
//console.log(response.headers)
emit('user-authenticated', response.headers.location)
username.value = ''
password.value = ''
})
.catch((error) => {
console.log(error)
console.log(error.response.data)
if (error.response.data.error) {
errorMessage.value = error.response.data.error
} else {
errorMessage.value = 'Unknown error'
}
})
.finally(() => {
isLoading.value = false
})
}
</script>
<style scoped lang="scss">
</style>

View File

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

View File

@ -1,14 +0,0 @@
<template>
<div>
Bio:
Symfonycast
</div>
</template>
<script>
export default {
name: 'TheAbout'
}
</script>

View File

@ -1,63 +0,0 @@
<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>
<router-link
:to="{ name: 'About'}"
class="d-inline-block mx-auto"
>
About Me
</router-link>
</div>
</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>

View File

@ -1,73 +0,0 @@
<template>
<nav
class="
grid fixed inset-x-0 top-0 flex-wrap justify-between items-center py-0 leading-6 border-b
@border-orange-400 opacity-90 md:flex-nowrap md:justify-start md:px-24 box-border
bg-neutral-800 text-stone-300 grid-cols-2 place-content-around"
style="z-index: 1030;"
>
<div>
<router-link
class="py-1 mr-4 text-xl leading-7 text-white whitespace-nowrap cursor-pointer box-border
hover:text-white focus:text-white"
:to="{ name: 'Home' }"
>
<img
src="/build/images/24unix/24_logo_bg_96x96.png"
class="align-middle box-border"
alt="24unix.net"
>
</router-link>
</div>
<div class="text-end">
<router-link
id="buttonLogin"
class="inline-block py-1 px-3 mt-6 text-base font-normal leading-normal text-center
text-black align-middle bg-orange-400 rounded border border-orange-400 border-solid
cursor-pointer select-none box-border hover:border-orange-400 hover:bg-orange-400 hover:text-black
focus:border-orange-400 focus:bg-orange-400 focus:text-black"
:to="{ name: 'LoginForm' }"
role="button"
style="text-decoration: none; transition: none 0s ease 0s; list-style: outside none none;"
>
<span class="fa fa-sign-in fa-lg fa-fw"></span>&nbsp;Log In
</router-link>
</div>
</nav>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios'
import 'vue-navigation-bar/dist/vue-navigation-bar.css'
const props = defineProps({
user: {
type: Object,
default() {
return {
username: 'tracer'
}
}
}
})
const isLoggedIn = () => (!!this.user)
let showDropdown = ref(false)
const toggleDropDown = () => {
console.log('toggle', showDropdown)
showDropdown.value = !showDropdown.value
}
/*
const logout = () => ({
axios
.get('/logout')
.then(this.$emit('invalidate-user'))
})
*/
</script>

View File

@ -1,62 +0,0 @@
<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: 'Blog',
url: 'Blog',
fa: 'fa-file-text-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>

View File

@ -1,55 +0,0 @@
<template>
<div>
<!-- media -->
<div class="h-64 w-auto md:w-1/2">
<img
class="inset-0 h-full w-full object-cover object-center"
src="/build/images/tracer_schmolle150x150.png"
alt=""
>
</div>
<!-- content -->
<div class="w-full py-4 px-6 text-gray-800 flex flex-col justify-between">
<h3 class="font-semibold text-lg leading-tight truncate">
{{ post.title }}
</h3>
<p class="mt-2">
{{ post.body.split('.')[0] }}
</p>
<p class="text-sm text-gray-700 uppercase tracking-wide font-semibold mt-2">
{{ post.createdAt.toLocaleString('de-DE') }}
</p>
<p v-if="blogUser">
{{ blogUser }}
</p>
<p class="font-normal text-gray-700 mb-3">
dddd
</p>
<router-link
:to="{ name: 'BlogPost', params: { id: post.id } }"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300
font-medium rounded-lg text-sm px-3 py-2 text-center inline-flex items-center"
>
Read more
</router-link>
</div>
</div>
</template>
<script setup>
import useResource from '@/composables/useResource'
const props = defineProps({
post: {
type: Object,
required: true
}
})
const post = { ...props.post }
const { items: blogUser, fetchOne } = useResource('users')
fetchOne(post.user)
console.log("blug user", post.user)
console.log(blogUser.value)
</script>

View File

@ -1,37 +0,0 @@
<template>
<div class="pt-6 pb-12 bg-gray-300">
<div
id="card"
class=""
>
<h2 class="text-center font-serif uppercase text-4xl xl:text-5xl">
Recent Articles
</h2>
<!-- container for all cards -->
<div class="container w-100 lg:w-4/5 mx-auto flex flex-col">
<BlogCard
v-for="post in blogPosts"
:key="post.id"
:post="post"
class="
flex flex-col md:flex-row overflow-hidden bg-white rounded-lg
shadow-xl mt-4 w-100 mx-2"
/>
</div>
</div>
</div>
</template>
<script setup async>
import useResource from '@/composables/useResource'
//import useUser from '@/composables/useUser'
import BlogCard from '@/components/blog/BlogCard'
const {
items: blogPosts,
fetchAll
} = useResource('users/1/blogPosts')
fetchAll()
</script>

View File

@ -1,47 +0,0 @@
<template>
<div
v-if="blogPost"
class="
flex
m-2
gap-2
items-center
shadow-md
w-1/4
flex-grow
rounded
overflow-hidden
"
style="border: 1px solid #eee"
>
BlogIPost
<img
src="https://via.placeholder.com/150"
style="background: #cccccc"
width="150"
height="150"
alt="placeholder"
>
user {{ blogPost.userId }}:
<div v-if="user">
"{{ user.name }}
</div>
<br>
{{ blogPost.title }}<br>
{{ blogPost.body }}
</div>
</template>
<script setup async>
import { useRoute } from 'vue-router'
import useResource from '@/composables/useResource'
const route = useRoute()
const { item: blogPost, fetchOne: fetchOneBlog } = useResource('https://jsonplaceholder.typicode.com/posts')
await fetchOneBlog(route.params.id)
const { item: user, fetchOne: fetchOneUser } = useResource('https://jsonplaceholder.typicode.com/users')
fetchOneUser(blogPost.value.userId)
</script>

View File

@ -1,3 +0,0 @@
<template>
</template>

View File

@ -1,60 +0,0 @@
<template>
<div class="box ma7 p-5">
<h2
v-if="page"
v-html="page.name"
/>
<div
v-if="page"
v-html="page.content"
/>
<router-link
:to="editTarget"
variant="outline"
>
<button>
<i class="fa fa-2x fa-fw fa-edit"/>
</button>
</router-link>
<hr>
</div>
</template>
<script setup>
import { reactive, watchEffect, computed } from 'vue'
import axios from 'axios'
//import h from 'highlightjs'
//import hi from 'highlightjs-line-numbers.js'
//hi.highlightAll()
//hi.initLineNumbersOnLoad()
const props = defineProps({
slug: {
type: String,
required: true
}
})
let page = reactive({ name: '', slug: '' })
const editTarget = computed(() => {
if (page) {
return `/pages/edit/${page.slug}`
}
return ''
})
const getPagesDetails = async (slug) => {
console.log('get page details')
await axios.get(`/api/pages?slug=${slug}`)
.then((response) => {
page = response.data['hydra:member']
console.log(page)
})
}
// watch fpr slug
watchEffect(() => getPagesDetails(props.slug))
</script>

View File

@ -1,152 +0,0 @@
<template>
<div
v-if="!isLoading"
class="box p-3"
>
<tabs-group @tabActivated="tabActivated">
<tab-content title="Visual Editor">
<div class="editor mt-2">
<QuillEditor
ref="editor"
theme="snow"
:content="JSON.parse(page.content)"
:options="editorOptions"
:disabled="isVueEditorDisabled"
/>
<button
class="btn btn-primary mt-3 mb-2"
@click="saveContent"
>
Save
</button>
</div>
</tab-content>
<tab-content title="Preview">
<div class="preview mt-2 no-overflow">
<QuillEditor
ref="preview"
theme="bubble"
class="no-overflow"
:content="JSON.parse(page.content)"
:options="editorOptions"
:disabled="true"
/>
</div>
<!--
<div>
<textarea
v-model="page.content"
class="p-fluid pages-editor-raw"
/>
</div>
-->
</tab-content>
<tab-content title="Delta">
<div class="editor mt-2">
<textarea
ref="delta"
v-model="page.content"
class="p-fluid pages-editor-raw"
/>
</div>
<button
class="btn btn-primary mt-3 mb-2"
@click="saveDelta"
>
Save
</button>
</tab-content>
</tabs-group>
</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 'highlight.js/styles/tomorrow-night-blue.css'
import hljs from 'highlight.js'
//import Quill from 'quill'
import { Quill, QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import '@vueup/vue-quill/dist/vue-quill.bubble.css'
import htmlEditButton from 'quill-html-edit-button'
import TabsGroup from '@/components/tabs/TabsGroup'
import TabContent from '@/components/tabs/TabContent'
Quill
// .register('modules/syntax', syntax, false)
.register('modules/htmlEditButton', htmlEditButton)
hljs.configure({
languages: ['javascript', 'php', 'swift']
})
export default {
name: 'PagesEdit',
components: {
QuillEditor,
TabsGroup,
TabContent
},
data: () => ({
page: null,
isLoading: true,
isVueEditorDisabled: false,
editorOptions: {
modules: {
htmlEditButton: {
debug: true
},
syntax: {
highlight: (text) => hljs.highlightAuto(text).value
}
}
},
theme: 'snow'
}),
beforeMount() {
const { slug } = this.$route.params
axios
.get(`/api/pages?slug=${slug}`)
.then((response) => {
[this.page] = response.data['hydra:member']
this.isLoading = false
})
},
methods: {
saveContent() {
this.page.content = JSON.stringify(this.$refs.editor.getContents())
axios
.put(`/api/pages/${this.page.id}`, this.page)
.then(() => {
//this.$router.push({
// name: 'Pages',
// params: { slug: this.page.slug }
//})
})
},
saveDelta() {
axios
.put(`/api/pages/${this.page.id}`, this.page)
.then(() => {
//this.$router.push({
// name: 'Pages',
// params: { slug: this.page.slug }
//})
})
},
tabActivated(name) {
this.isVueEditorDisabled = name === 'Raw Content'
}
}
}
</script>

View File

@ -1,107 +0,0 @@
<template>
<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="row"
>
<div class="col-sm-12">
<!-- {% if is_granted('ROLE_ADMIN') %}
<div class="d-flex justify-content-end">
<a :to="id"><i class="fa fa-3x fa-fw fa-edit"></i></a>
<a :to="project.id"><i class="fa fa-3x fa-fw fa-trash"></i></a>
</div>
{% endif %}-->
<div class="show-article-container p-3 mt-4">
<div class="show-article-title-container d-inline-block pl-3 align-middle">
<h2>{{ project.name }}</h2>
</div>
<div>
Source:
<a
:href="project.url"
target="_blank"
>
{{ project.url }}
</a>
&nbsp;
<i
class="fa fa-external-link"
aria-hidden="true"
/>
</div>
<div class="row mt-5">
<div class="col-sm-12">
<!-- eslint-disable vue/no-v-html -->
<div
class="article-text"
v-html="readmeToHtml"
/>
<!-- eslint-enable -->
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios'
import { marked } from 'marked'
import Author from '@/components/users/UserCard'
export default {
Name: 'ProjectDetails',
components: {
Author,
marked
},
data: () => ({
project: null,
readme: null,
isLoading: true
}),
computed: {
readmeToHtml() {
if (!this.isLoading) {
return marked(this.readme)
}
return ''
}
},
mounted() {
const { id } = this.$route.params
console.log(id)
axios
.get(`/api/projects/${id}`)
.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
console.log(response)
})
.catch((error) => {
console.log(error)
})
})
.catch((error) => {
console.log(error)
})
},
methods: {
getProjects() {
}
}
}
</script>

View File

@ -1,113 +0,0 @@
<template>
<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="container-fluid"
>
<div class="row">
<h2 class="mt-2">
This is an overview of my current public (and open source) projects.
</h2>
<!-- projects List -->
<div class="col-sm-12">
<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">
<router-link :to="'/projects/' + project.id">
<img
v-if="project.teaserImage"
class="blog-img"
:src="'/uploads/projects/' + project.teaserImage"
alt="Teaser"
>
<img
v-else
class="blog-img"
src="/build/images/24unix/24_logo_bg_96x96.png"
alt="Teaser"
>
</router-link>
<br>
<div>
<div
v-for="developer in project.developer"
:key="developer"
class="col"
>
<user-card :author-iri="developer"/>
</div>
</div>
</div>
<div class="col-sm-8 mt-2">
<router-link :to="'/projects/' + project.id">
<div class="article-title d-inline-block pl-3 align-middle">
<h2 v-html="project.name"/>
</div>
</router-link>
<br>
<div class="blog-teaser mb-2 pb-2 text-xl-start">
<span v-html="project.description"/>
<br>
<br>
started: <span v-html="formatDate(project.createdAt)"/>
</div>
</div>
</div>
</div>
</div>
</div>
<!--
<div class="text-xl-start">
<router-link to="/add">
<i class="fa fa-plus-circle"/>
</router-link>
</div>
-->
</div>
</div>
</template>
<script>
import axios from 'axios'
import UserCard from '@/components/users/UserCard'
export default {
name: 'ProjectsList',
components: {
UserCard,
},
data: () => ({
projects: null,
isLoading: true
}),
mounted() {
this.getProjects()
},
methods: {
getProjects() {
axios
.get('/api/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>

View File

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

View File

@ -1,34 +0,0 @@
<template lang="html">
<div
v-show="title === selectedTitle"
class="tab-content"
>
<slot/>
</div>
</template>
<script>
import { inject } from 'vue'
export default {
props: {
title: {
type: String,
required: true
}
},
setup() {
const selectedTitle = inject('selectedTitle')
return {
selectedTitle
}
}
}
</script>
<style>
.tab-content {
padding: 20px;
border-radius: 5px;
}
</style>

View File

@ -1,78 +0,0 @@
<template lang="html">
<div class="tabs">
<ul class="tabs-header">
<li
v-for="title in tabTitles"
:key="title"
:class="{ selected: title === selectedTitle }"
class="btn"
@click="handleClick(title)"
>
{{ title }}
</li>
</ul>
<slot/>
</div>
</template>
<script>
import { ref, provide } from 'vue'
export default {
name: 'TabsGroup',
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
}
},
methods: {
handleClick(title) {
this.selectedTitle = title
this.$emit('tabActivated', title)
}
},
}
</script>
<style lang="scss">
@import "~styles/app.scss";
.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: #2e2e2e;
border-radius: 5px;
color: #999999;
cursor: pointer;
transition: 0.4s all ease-out;
}
.tabs-header li.selected {
background-color: $primary;
color: $jet-black;
}
.tabs-header li.selected:hover {
/*border-color: $body-color; */
}
</style>

View File

@ -1,87 +0,0 @@
<template>
<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="container box rounded bg-dark mt-5 mb-5"
>
<div class="row">
<div class="col-md-3">
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
Profile of {{ user.username }}
<img
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="text-white-50">
<i class="fa fa-lg fa-envelope me-1"/>{{ user.email }}
</span>
</div>
</div>
<div class="col-md-5">
<div class="p-3 py-5">
<div class="d-flex justify-content-between align-items-center mb-3">
<h4 class="text-right">
User Projects
</h4>
</div>
<div class="row mt-2"/>
<!--
<div class="mt-5 text-center">
<button class="btn btn-primary profile-button" type="button">Save Profile</button>
</div>
-->
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import axios from 'axios'
const user = reactive(null)
const isLoading = ref(true)
const router = useRouter()
const route = useRoute()
// if there is no param, we go to our own profile, elso to the login
if (route.params.username) {
console.log('we have the username')
} else if (window.user) {
console.log(window.user)
} else {
router.push({ name: 'LoginForm' })
}
const userEndpoint = '/api/users?username=tracer'
axios
.get(userEndpoint)
.then((response) => {
//console.log(response);
[user.value] = response.data['hydra:member']
//console.log(this.user)
isLoading.value = false
})
.catch(() => {
//console.log(error)
})
</script>

View File

@ -1,67 +0,0 @@
<template>
<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'
export default {
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>

View File

@ -1,34 +0,0 @@
import { ref } from 'vue'
import axios from 'axios'
export default function useResource(resource) {
console.log('useBlog')
axios.defaults.headers.common['app-id'] = '628cbf673800f869ed218152' // for all requests
const apiBaseUrl = 'https://628cc5c6a3fd714fd03914c2.mockapi.io/api/'
const items = ref([])
const item = ref(null)
const fetchAll = async () => {
await axios
.get(apiBaseUrl + resource)
.then((response) => {
console.log(response.data)
items.value = response.data
})
}
const fetchOne = async (id) => {
console.log('fetchOne', id)
await axios
.get(`${resource}/${id}`)
.then((response) => {
item.value = response.data
})
}
return {
items,
fetchAll,
item,
fetchOne
}
}

View File

@ -1,53 +1,17 @@
// assets/js/index.js
import '../styles/app.scss'
// CKEditor
import '../styles/ckeditor.css'
import 'fork-awesome/scss/fork-awesome.scss'
import { createApp } from 'vue'
require('bootstrap')
import 'bootswatch/dist/slate/bootstrap.min.css'
import { createPinia } from 'pinia'
$(document).ready(function () {
console.log('ready')
$('#toggleSidebar').on('click', function () {
$('#toggleIcon').toggleClass('fa fa-lg fa-fw fa-caret-square-o-left')
$('#toggleIcon').toggleClass('fa fa-lg fa-fw fa-caret-square-o-right')
$('#sidebar').toggleClass('active')
})
})
//import { QuillEditor } from '@vueup/vue-quill'
//import '@vueup/vue-quill/dist/vue-quill.snow.css'
//import '@vueup/vue-quill/dist/vue-quill.bubble.css'
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;
createApp(App)
.component('AppLink', AppLink)
// .component('QuillEditor', QuillEditor)
.use(createPinia())
.use(router)
.mount('#app')

View File

@ -1,86 +0,0 @@
import { createRouter, createWebHistory } from 'vue-router'
import LoginForm from '@/components/LoginForm'
import Quotes from '@/components/quotes'
import Pages from '@/components/pages/PagesIndex'
import PagesEdit from '@/components/pages/edit'
import ProjectsList from '@/components/projects'
import ProjectsDetails from '@/components/projects/ProjectDetails'
import BlogIndex from '@/components/blog/BlogIndex'
import BlogPost from '@/components/blog/BlogPost'
import ProfileView from '@/components/users/ProfileView'
import TheAbout from '@/components/TheAbout'
import NotFound from '@/components/NotFound'
const routes = [
{
path: '/',
name: 'Home',
component: Quotes
},
{
path: '/about',
name: 'About',
component: TheAbout
},
{
path: '/form_login',
name: 'LoginForm',
component: LoginForm
},
{
path: '/projects',
name: 'Projects',
component: ProjectsList
},
{
path: '/projects/:id',
name: 'ProjectDetails',
component: ProjectsDetails
},
{
path: '/blog',
name: 'Blog',
component: BlogIndex
},
{
path: '/blog/post/:id',
name: 'BlogPost',
component: BlogPost
},
{
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
})
/*
router.beforeEach((to) => {
if (to.meta.requiredAuth && !window.user) {
return { name: 'LoginForm' }
}
})
*/
export default router

View File

@ -1,13 +0,0 @@
import { defineStore } from 'pinia';
import axios from 'axios';
export const useQuotesStore = defineStore('QuotesStore', {
state: () => ({
quotes: []
}),
actions: {
async fill() {
this.quotes = (await axios.get('api/quotes')).data;
}
}
});

View File

@ -1,8 +0,0 @@
import { defineStore } from 'pinia';
export const useUserStore = defineStore('UsersStore', {
state: () => {
},
});

View File

@ -1,442 +0,0 @@
/*
jet black (tiefschwarz) - RAL 9005: #0e0e10, rgba(14, 14, 16, 1.0);
mango: #FF8040, rgba(255, 130, 67, 1.0);
gray: #a1a1a1, rgba(161, 161, 161, 1.0)
*/
/*
@media (prefers-color-scheme: light) {}
@media (prefers-color-scheme: dark) {}
*/
/* debug */
* {
//border: 1px solid gray;
}
html, body{
margin: 0;
padding: 0;
background: black;
background: linear-gradient(90deg, rgba(14,14,16,1) 0%, rgba(255,128,64,1) 35%, rgba(14,14,16,1) 100%);
}
// the ~ allows you to reference things in node_modules
@import 'quill/dist/quill.core.css';
// customize some Bootstrap variables
$bs-primary: #FF8040;
$primary: #FF8040;
$body-bg: #0E0E10;
$body-color: darken(white, 20);
$border-primary: #FF8040;
$dropdown-dark-bg: black;
$dropdown-dark-link-color: $primary;
$dropdown-dark-border-color: $primary;
$jet-black: #0e0e10;
$mango: #FF8040;
.btn-primary {
border-color: $primary;
}
.btn-outline-primary {
color: $primary;
border-color: $primary;
}
.pages-editor-raw {
width: 100%;
height: 650px !important;
background-color: black;
color: white;
}
.ql-container {
overflow-y: scroll;
height: 650px !important;
}
.no-overflow {
overflow-y: visible !important;
height: auto !important;
}
.ql-syntax {
background-color: #222222;
border: 1px solid #888;
border-left: 3px solid $primary;
color: #666;
page-break-inside: avoid;
font-family: monospace;
font-size: 15px;
line-height: 1.6;
margin-bottom: 1.6em;
max-width: 100%;
overflow: auto;
padding: 1em 1.5em;
display: block;
word-wrap: break-word;
}
.ql-editor {
counter-reset: line;
padding-left: 0;
}
.ql-editor div:before {
counter-increment: line;
content: counter(line);
display: inline-block;
border-right: 1px solid red;
padding: 0 .5em;
margin-right: .5em;
color: #888
}
.ql-syntax pre:before {
counter-increment: line;
content: counter(line);
display: inline-block;
border-right: 1px solid #ddd;
padding: 2px .5em;
margin-right: .5em;
color: #888
}
/*
pre span.hljs-tag::before, span.hljs-attr::before {
content: "xxx";
display: inline-block;
}
*/
.wrapper {
clear: both;
position: sticky;
top: 0;
}
a:link {
text-decoration: none;
color: $mango;
}
a:visited {
text-decoration: none;
color: $mango;
}
a:hover {
text-decoration: none;
color: $mango;
}
a:active {
text-decoration: none;
color: $mango;
}
body {
padding-top: 95px;
padding-bottom: 155px;
}
.row.content {
height: 350px;
}
.col-center {
margin: 0 auto;
}
.sidenav-left {
padding-top: 20px;
padding-left: 0;
padding-right: 0;
background-color: #f1f1f1;
height: 100%;
width: auto;
margin-left: 3em !important;
}
.sidenav-left ul {
list-style-type: none;
line-height: 2.1;
}
.sidenav-right {
padding-top: 20px;
background-color: #f1f1f1;
height: 100%;
}
@media screen and (max-width: 767px) {
.sidenav {
height: auto;
padding: 15px;
}
.row.content {
height: auto;
}
}
.navbar {
opacity: 0.9;
}
footer {
opacity: 0.9;
}
.navbar-top {
border-bottom-width: 1px;
border-bottom-color: $primary;
padding-top: 0;
padding-bottom: 0;
opacity: 0.9;
}
.navbar-bottom {
border-top-width: 1px;
border-top-color: $primary;
padding-top: 0;
padding-bottom: 0;
height: 125px;
opacity: 0.9;
}
.navbar-nav > li > .dropdown-menu {
background-color: black;
opacity: 0.8;
}
.display-wrapper {
text-align: left;
width: 90%;
margin: 0 auto 150px;
}
.button-login {
margin-top: 25px;
}
.main-content {
}
.box {
border-width: 1px;
border-style: solid;
border-color: $primary;
border-radius: 10px;
color: lightgray;
background: black;
align-content: center;
margin: 15px 15px 20px;
height: auto;
}
/* BlogPosts */
.main-article {
border: 2px solid #efefee;
Background: #fff;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
.main-article img {
width: 100%;
height: 250px;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
border-top: 5px solid lightblue;
}
.blog-container {
border: 1px solid $primary;
border-radius: 5px;
margin-bottom: 25px;
background: #0E0E10 url('../images/bg.jpeg') center;
}
.main-article-link, .article-container a {
text-decoration: none;
color: #000;
}
.main-article-link:hover {
text-decoration: none;
color: #000;
}
.article-title {
min-width: 300px;
}
.article-text {
text-align: justify;
hyphens: auto;
}
@media (max-width: 440px) {
.article-title {
min-width: 100px;
max-width: 245px;
}
}
.circle {
position:fixed;
width:500px;
height:600px;
margin:-300px auto auto -250px;
top:50%;
left:50%;
text-align:center;
}
.teaser-image {
object-fit: contain;
width: 800px;
border-radius: 5px;
margin: 7px;
}
.project-container {
border-radius: 5px;
}
.blog-img {
height: 100px;
width: 100px;
border-radius: 5px;
border-width: 1px;
border-color: $primary;
margin: 7px;
}
.article-author-img {
height: 50px;
border: 1px solid $primary;
margin-left: 25px;
}
.blog-details {
font-size: .8em;
margin-right: 15px;
}
.blog-teaser {
margin-left: 15px;
}
/* registration form */
.social_icon span {
font-size: 60px;
margin-left: 10px;
color: $primary;
}
.social_icon span:hover{
color: white;
cursor: pointer;
}
.card{
height: 370px;
margin-top: 45px;
margin-bottom: auto;
width: 500px;
background-color: #383c4a;
border-color: $primary;
padding: 15px;
background-image: url('../images/bg.jpeg');
border-bottom-left-radius: 10px !important;
border-bottom-right-radius: 10px !important;
}
.card-header {
position: absolute;
color: black;
background-color: $primary;
width: 500px;
height: 55px;
border-top-left-radius: 15px !important;
border-top-right-radius: 15px !important;
}
.card-body {
}
.social_icon{
/* position: absolute;
right: 20px;
top: 45px;
*/
}
.input-group-prepend span{
width: 50px;
background-color: $primary;
color: black;
border:0 !important;
height: 40px;
margin-bottom: 15px;
border-radius: 10px 0 0 10px;
}
.form-control {
height: 40px;
background-image: url('../images/bg.jpeg') !important;
color: white;
border-color: $primary;
}
input:focus{
/* TODO */
}
.submit-button {
color: $primary;
background-color: black;
width: 100px;
border-radius: 10px;
}
.submit-button:hover{
color: black;
background-color: $primary;
}
.links{
color: white;
}
.teaser-text {
height: 180px;
}
.content-text {
height: 400px;
}
.file-input {
color: $primary;
}

View File

@ -18,74 +18,39 @@
html, body{
margin: 0;
padding: 0;
background: black;
background: linear-gradient(90deg, rgba(14,14,16,1) 0%, rgba(255,128,64,1) 35%, rgba(14,14,16,1) 100%);
//background: linear-gradient(90deg, rgba(14,14,16,1) 0%, rgba(255,128,64,1) 35%, rgba(14,14,16,1) 100%);
background: #0e0e10;
}
// customize some Bootstrap variables
$primary: #FF8040;
$jet-black: #0e0e10;
//@import "bootstrap/scss/bootstrap";
///
@import 'quill/dist/quill.core.css';
// customize some Bootstrap variables
// sidebar
.pages-editor-raw {
width: 100%;
height: 650px !important;
background-color: black;
color: white;
#sidebar {
min-width: 180px;
max-width: 180px;
display: inline;
white-space: nowrap;
overflow: hidden;
float: left;
transition: min-width 0.5s, max-width 0.5s;
}
.ql-container {
overflow-y: scroll;
height: 650px !important;
#sidebar.active {
min-width: 60px;
max-width: 60px;
}
.no-overflow {
overflow-y: visible !important;
height: auto !important;
#content {
}
.ql-syntax {
background-color: #222222;
border: 1px solid #888;
border-left: 3px solid $primary;
color: #666;
page-break-inside: avoid;
font-family: monospace;
font-size: 15px;
line-height: 1.6;
margin-bottom: 1.6em;
max-width: 100%;
overflow: auto;
padding: 1em 1.5em;
display: block;
word-wrap: break-word;
#sidebar.active .menuText {
display: none;
}
.ql-editor {
counter-reset: line;
padding-left: 0;
}
.ql-editor div:before {
counter-increment: line;
content: counter(line);
display: inline-block;
border-right: 1px solid red;
padding: 0 .5em;
margin-right: .5em;
color: #888
}
.ql-syntax pre:before {
counter-increment: line;
content: counter(line);
display: inline-block;
border-right: 1px solid #ddd;
padding: 2px .5em;
margin-right: .5em;
color: #888
}

View File

@ -9,51 +9,50 @@
"ext-iconv": "*",
"api-platform/core": "^2.6",
"doctrine/annotations": "^1.0",
"doctrine/doctrine-bundle": "^2.6",
"doctrine/doctrine-bundle": "^2.7",
"doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/orm": "^2.11",
"easycorp/easyadmin-bundle": "^4.0",
"friendsofsymfony/ckeditor-bundle": "^2.4",
"knplabs/knp-time-bundle": "^1.18",
"league/commonmark": "^2.3",
"nelmio/cors-bundle": "^2.2",
"phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.4",
"rector/rector": "^0.12.21",
"sensio/framework-extra-bundle": "^6.1",
"sensio/framework-extra-bundle": "^v6.2.8",
"sunrise/slugger": "^2.1",
"symfony/asset": "6.0.*",
"symfony/console": "6.0.*",
"symfony/doctrine-messenger": "6.0.*",
"symfony/dotenv": "6.0.*",
"symfony/expression-language": "6.0.*",
"symfony/apache-pack": "^1.0",
"symfony/asset": "6.1.*",
"symfony/console": "6.1.*",
"symfony/doctrine-messenger": "6.1.*",
"symfony/dotenv": "6.1.*",
"symfony/expression-language": "6.1.*",
"symfony/flex": "^2",
"symfony/form": "6.0.*",
"symfony/framework-bundle": "6.0.*",
"symfony/http-client": "6.0.*",
"symfony/intl": "6.0.*",
"symfony/mailer": "6.0.*",
"symfony/mime": "6.0.*",
"symfony/form": "6.1.*",
"symfony/framework-bundle": "6.1.*",
"symfony/http-client": "6.1.*",
"symfony/intl": "6.1.*",
"symfony/mailer": "6.1.*",
"symfony/mime": "6.1.*",
"symfony/monolog-bundle": "^3.0",
"symfony/notifier": "6.0.*",
"symfony/process": "6.0.*",
"symfony/property-access": "6.0.*",
"symfony/property-info": "6.0.*",
"symfony/proxy-manager-bridge": "6.0.*",
"symfony/runtime": "6.0.*",
"symfony/security-bundle": "6.0.*",
"symfony/serializer": "6.0.*",
"symfony/string": "6.0.*",
"symfony/translation": "6.0.*",
"symfony/twig-bundle": "6.0.*",
"symfony/validator": "6.0.*",
"symfony/web-link": "6.0.*",
"symfony/notifier": "6.1.*",
"symfony/process": "6.1.*",
"symfony/property-access": "6.1.*",
"symfony/property-info": "6.1.*",
"symfony/proxy-manager-bridge": "6.1.*",
"symfony/runtime": "6.1.*",
"symfony/security-bundle": "6.1.*",
"symfony/serializer": "6.1.*",
"symfony/string": "6.1.*",
"symfony/translation": "6.1.*",
"symfony/twig-bundle": "6.1.*",
"symfony/validator": "6.1.*",
"symfony/web-link": "6.1.*",
"symfony/webapp-meta": "^1.0",
"symfony/webpack-encore-bundle": "^1.14",
"symfony/yaml": "6.0.*",
"twig/extra-bundle": "^3.3",
"twig/markdown-extra": "^3.3",
"twig/twig": "^2.12|^3.0"
"symfony/yaml": "6.1.*",
"twig/markdown-extra": "^3.4",
"twig/twig": "3.3.10"
},
"config": {
"allow-plugins": {
@ -88,8 +87,7 @@
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd",
"ckeditor:install": "symfony-cmd"
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
@ -103,14 +101,14 @@
},
"extra": {
"symfony": {
"allow-contrib": false,
"require": "6.0.*"
"allow-contrib": true,
"require": "6.1.*"
}
},
"require-dev": {
"symfony/debug-bundle": "6.0.*",
"symfony/debug-bundle": "6.1.*.*",
"symfony/maker-bundle": "^1.0",
"symfony/stopwatch": "6.0.*",
"symfony/web-profiler-bundle": "6.0.*"
"symfony/stopwatch": "6.1.*",
"symfony/web-profiler-bundle": "6.1.*"
}
}

1976
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
{
"devDependencies": {
"@hotwired/stimulus": "^3.0.0",
"@popperjs/core": "^2.11.6",
"@symfony/stimulus-bridge": "^3.0.0",
"@symfony/webpack-encore": "^2.0.0",
"autoprefixer": "^10.4.7",
@ -12,14 +13,12 @@
"regenerator-runtime": "^0.13.2",
"sass": "^1.50.0",
"sass-loader": "^12.0.0",
"tailwindcss": "^3.0.24",
"ts-loader": "^9.0.0",
"typescript": "^4.6.4",
"vue-loader": "^17.0.0",
"webpack-manifest-plugin": "^5.0.0",
"webpack-notifier": "^1.6.0"
},
"license": "UNLICENSED",
"license": "MIT",
"private": true,
"scripts": {
"dev-server": "encore dev-server",
@ -30,28 +29,21 @@
"dependencies": {
"@fortawesome/fontawesome-free": "^6.1.1",
"@typescript-eslint/eslint-plugin-tslint": "^5.26.0",
"@vueup/vue-quill": "^1.0.0-beta.8",
"axios": "^0.27.1",
"bootsdark": "^1.0.16",
"bootstrap": "^5.2.2",
"bootswatch": "^5.2.2",
"eslint": "^8.15.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-tailwindcss": "^3.5.0",
"eslint-plugin-vue": "^9.0.1",
"fork-awesome": "^1.2.0",
"highlight.js": "^11.5.1",
"husky": "^7.0.4",
"less": "^4.1.2",
"marked": "^4.0.15",
"pinia": "^2.0.14",
"popper.js": "^1.16.1",
"postcss-import": "^14.1.0",
"postcss-loader": "^7.0.0",
"quill": "^1.3.7",
"quill-html-edit-button": "^2.2.12",
"tailwind": "^4.0.0",
"vue": "3",
"vue-navigation-bar": "^5.0.0",
"vue-router": "4"
"quill-html-edit-button": "^2.2.12"
}
}

View File

@ -1,7 +0,0 @@
module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
require('postcss-import')
]
}

66
public/.htaccess Normal file
View File

@ -0,0 +1,66 @@
# Use the front controller as index file. It serves as a fallback solution when
# every other rewrite/redirect fails (e.g. in an aliased environment without
# mod_rewrite). Additionally, this reduces the matching process for the
# start page (path "/") because otherwise Apache will apply the rewriting rules
# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl).
DirectoryIndex index.php
# By default, Apache does not evaluate symbolic links if you did not enable this
# feature in your server configuration. Uncomment the following line if you
# install assets as symlinks or if you experience problems related to symlinks
# when compiling LESS/Sass/CoffeScript assets.
# Options +FollowSymlinks
# Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve
# to the front controller "/index.php" but be rewritten to "/index.php/index".
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the index.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
RewriteRule .* - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .+
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]
# Redirect to URI without front controller to prevent duplicate content
# (with and without `/index.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
# following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
# Rewrite all other queries to the front controller.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect of
# the start page to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 307 ^/$ /index.php/
# RedirectTemp cannot be used instead
</IfModule>
</IfModule>

View File

@ -6,6 +6,7 @@ declare(strict_types=1);
namespace App\Controller;
use App\Repository\QuotesRepository;
use Exception;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
@ -16,17 +17,18 @@ use Symfony\Component\Serializer\SerializerInterface;
*/
class FrontendController extends AbstractController
{
const TEMPLATE_DIR = 'themes/default/';
/**
* @throws \Exception
* @throws Exception
*/
#[Route(path: '/', name: 'app_main')]
#[Route(path: '/{route}', name: 'vue_pages', requirements: ['route' => '^(?!.*_wdt|_profiler|login|logout).+'] )]
public function quote(SerializerInterface $serializer, QuotesRepository $quotesRepository): Response
{
$quote = $quotesRepository->findOneRandom();
return $this->render(view: 'base.html.twig', parameters: [
return $this->render(view: self::TEMPLATE_DIR . 'base.html.twig', parameters: [
'template_dir' => self::TEMPLATE_DIR,
'user' => $serializer->serialize(data: $this->getUser(), format: 'jsonld'),
'quote' => json_encode(value: $quote->getQuote())
]);

View File

@ -10,6 +10,8 @@ use Symfony\Component\Routing\Annotation\Route;
class PagesController extends AbstractController
{
const TEMPLATE_DIR = 'themes/default/';
#[Route(path: '/pages/{name}', name: 'pages_display')]
public function display(PagesRepository $pagesRepository, string $name): Response
{
@ -27,4 +29,22 @@ class PagesController extends AbstractController
'page' => $page,
]);
}
#[Route(path: '/imprint', name: 'app_imprint')]
public function imprint(): Response
{
return $this->render(view: self::TEMPLATE_DIR . 'pages/imprint.html.twig', parameters: [
'template_dir' => self::TEMPLATE_DIR,
'controller_name' => 'PagesController',
]);
}
#[Route(path: '/privacy', name: 'app_privacy')]
public function privacy(): Response
{
return $this->render(view: self::TEMPLATE_DIR . 'pages/privacy.html.twig', parameters: [
'template_dir' => self::TEMPLATE_DIR,
'controller_name' => 'PagesController',
]);
}
}

View File

@ -18,13 +18,7 @@ class SecurityController extends AbstractController
#[Route(path: '/login', name: 'app_login')] // *** method post
public function login(AuthenticationUtils $authenticationUtils, IriConverterInterface $iriConverter): Response
{
if (!$this->isGranted(attribute: 'IS_AUTHENTICATED_FULLY')) {
return $this->json(data: [
'error' => 'Invalid login request'
], status: 400);
}
/** @var User $user */
$user = $this->getUser() ?? null;

View File

@ -15,10 +15,7 @@ use Symfony\Component\Security\Core\Exception\UserNotFoundException;
*/
class UserController extends AbstractController
{
/**
* @param string $userName
*
*/
#[Route(path: '/profile/edit/{username}', name: 'app_profile_edit')]
public function editProfile(UserRepository $userRepository, string $username = ''): Response
{

View File

@ -27,8 +27,9 @@ class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
use TargetPathTrait;
public function __construct(private readonly UserRepository $userRepository, private readonly RouterInterface $router)
{
}
{
// empty body
}
public function authenticate(Request $request): Passport
{
@ -38,7 +39,8 @@ class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
$request->getSession()->set(name: Security::LAST_USERNAME, value: $username);
dd("here");
return new Passport(
userBadge: new UserBadge(userIdentifier: $username, userLoader: function ($userIdentifier) {
$user = $this->userRepository->findOneBy(['username' => $userIdentifier]);

View File

@ -1,9 +1,9 @@
{
"api-platform/core": {
"version": "2.6",
"version": "2.7",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "2.5",
"ref": "05b57782a78c21a664a42055dc11cf1954ca36bb"
},
@ -13,40 +13,22 @@
"src/Entity/.gitignore"
]
},
"dflydev/dot-access-data": {
"version": "v3.0.1"
},
"doctrine/annotations": {
"version": "1.13",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "1.10",
"ref": "64d8583af5ea57b7afa4aba4b159907f3a148b05"
}
},
"doctrine/cache": {
"version": "2.1.1"
},
"doctrine/collections": {
"version": "1.6.8"
},
"doctrine/common": {
"version": "3.2.2"
},
"doctrine/dbal": {
"version": "3.3.5"
},
"doctrine/deprecations": {
"version": "v0.5.3"
},
"doctrine/doctrine-bundle": {
"version": "2.6",
"version": "2.7",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "2.4",
"ref": "ddddd8249dd55bbda16fa7a45bb7499ef6f8e90e"
"ref": "da713d006953b90d1c085c1be480ecdd6c4a95e0"
},
"files": [
"config/packages/doctrine.yaml",
@ -58,89 +40,32 @@
"version": "3.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "3.1",
"ref": "ee609429c9ee23e22d6fa5728211768f51ed2818"
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"doctrine/event-manager": {
"version": "1.1.1"
},
"doctrine/inflector": {
"version": "2.0.4"
},
"doctrine/instantiator": {
"version": "1.4.1"
},
"doctrine/lexer": {
"version": "1.2.3"
},
"doctrine/migrations": {
"version": "3.5.0"
},
"doctrine/orm": {
"version": "2.11.2"
},
"doctrine/persistence": {
"version": "2.4.1"
},
"doctrine/sql-formatter": {
"version": "1.1.2"
},
"easycorp/easyadmin-bundle": {
"version": "4.0",
"version": "4.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "3.0",
"ref": "b131e6cbfe1b898a508987851963fff485986285"
}
},
"egulias/email-validator": {
"version": "3.1.2"
},
"fig/link-util": {
"version": "1.2.0"
},
"friendsofphp/proxy-manager-lts": {
"version": "v1.0.7"
},
"friendsofsymfony/ckeditor-bundle": {
"version": "2.4",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "2.0",
"ref": "f5ad42002183a6881962683e6d84bbb25cdfce5d"
},
"files": [
"config/packages/fos_ckeditor.yaml"
]
},
"knplabs/knp-time-bundle": {
"version": "v1.18.0"
},
"laminas/laminas-code": {
"version": "4.5.1"
},
"league/commonmark": {
"version": "2.3.0"
},
"league/config": {
"version": "v1.1.1"
},
"monolog/monolog": {
"version": "2.4.0"
"version": "v1.20.0"
},
"nelmio/cors-bundle": {
"version": "2.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "1.5",
"ref": "6bea22e6c564fba3a1391615cada1437d0bde39c"
},
@ -148,53 +73,11 @@
"config/packages/nelmio_cors.yaml"
]
},
"nette/schema": {
"version": "v1.2.2"
},
"nette/utils": {
"version": "v3.2.7"
},
"nikic/php-parser": {
"version": "v4.13.2"
},
"phpdocumentor/reflection-common": {
"version": "2.2.0"
},
"phpdocumentor/reflection-docblock": {
"version": "5.3.0"
},
"phpdocumentor/type-resolver": {
"version": "1.6.1"
},
"phpstan/phpdoc-parser": {
"version": "1.4.2"
},
"phpstan/phpstan": {
"version": "1.6.0"
},
"psr/cache": {
"version": "3.0.0"
},
"psr/container": {
"version": "2.0.2"
},
"psr/event-dispatcher": {
"version": "1.0.0"
},
"psr/link": {
"version": "2.0.1"
},
"psr/log": {
"version": "3.0.0"
},
"rector/rector": {
"version": "0.12.21"
},
"sensio/framework-extra-bundle": {
"version": "6.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "5.2",
"ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
},
@ -202,26 +85,23 @@
"config/packages/sensio_framework_extra.yaml"
]
},
"sunrise/slugger": {
"version": "v2.1.3"
},
"symfony/asset": {
"version": "v6.0.7"
},
"symfony/cache": {
"version": "v6.0.6"
},
"symfony/cache-contracts": {
"version": "v3.0.1"
},
"symfony/config": {
"version": "v6.0.7"
"symfony/apache-pack": {
"version": "1.0",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "1.0",
"ref": "9d254a22efca7264203eea98b866f16f944b2f09"
},
"files": [
"public/.htaccess"
]
},
"symfony/console": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "5.3",
"ref": "da0c8be8157600ad34f10ff0c9cc91232522e047"
},
@ -230,10 +110,10 @@
]
},
"symfony/debug-bundle": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "5.3",
"ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b"
},
@ -241,59 +121,23 @@
"config/packages/debug.yaml"
]
},
"symfony/dependency-injection": {
"version": "v6.0.7"
},
"symfony/deprecation-contracts": {
"version": "v3.0.1"
},
"symfony/doctrine-bridge": {
"version": "v6.0.7"
},
"symfony/doctrine-messenger": {
"version": "v6.0.7"
},
"symfony/dotenv": {
"version": "v6.0.5"
},
"symfony/error-handler": {
"version": "v6.0.7"
},
"symfony/event-dispatcher": {
"version": "v6.0.3"
},
"symfony/event-dispatcher-contracts": {
"version": "v3.0.1"
},
"symfony/expression-language": {
"version": "v6.0.7"
},
"symfony/filesystem": {
"version": "v6.0.7"
},
"symfony/finder": {
"version": "v6.0.3"
},
"symfony/flex": {
"version": "2.1",
"version": "2.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "1.0",
"ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e"
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172"
},
"files": [
".env"
]
},
"symfony/form": {
"version": "v6.0.7"
},
"symfony/framework-bundle": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "5.4",
"ref": "3cd216a4d007b78d8554d44a5b1c0a446dab24fb"
},
@ -308,26 +152,11 @@
"src/Kernel.php"
]
},
"symfony/http-client": {
"version": "v6.0.7"
},
"symfony/http-client-contracts": {
"version": "v3.0.1"
},
"symfony/http-foundation": {
"version": "v6.0.7"
},
"symfony/http-kernel": {
"version": "v6.0.7"
},
"symfony/intl": {
"version": "v6.0.5"
},
"symfony/mailer": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "4.3",
"ref": "97a61eabb351d7f6cb7702039bcfe07fe9d7e03c"
},
@ -336,16 +165,16 @@
]
},
"symfony/maker-bundle": {
"version": "1.38",
"version": "1.47",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "1.0",
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
"symfony/messenger": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
@ -356,17 +185,11 @@
"config/packages/messenger.yaml"
]
},
"symfony/mime": {
"version": "v6.0.7"
},
"symfony/monolog-bridge": {
"version": "v6.0.3"
},
"symfony/monolog-bundle": {
"version": "3.7",
"version": "3.8",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "3.7",
"ref": "213676c4ec929f046dfde5ea8e97625b81bc0578"
},
@ -375,10 +198,10 @@
]
},
"symfony/notifier": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "5.0",
"ref": "c31585e252b32fe0e1f30b1f256af553f4a06eb9"
},
@ -386,99 +209,36 @@
"config/packages/notifier.yaml"
]
},
"symfony/options-resolver": {
"version": "v6.0.3"
},
"symfony/password-hasher": {
"version": "v6.0.3"
},
"symfony/polyfill-intl-grapheme": {
"version": "v1.25.0"
},
"symfony/polyfill-intl-icu": {
"version": "v1.25.0"
},
"symfony/polyfill-intl-idn": {
"version": "v1.25.0"
},
"symfony/polyfill-intl-normalizer": {
"version": "v1.25.0"
},
"symfony/polyfill-mbstring": {
"version": "v1.25.0"
},
"symfony/polyfill-php81": {
"version": "v1.25.0"
},
"symfony/polyfill-uuid": {
"version": "v1.25.0"
},
"symfony/process": {
"version": "v6.0.7"
},
"symfony/property-access": {
"version": "v6.0.7"
},
"symfony/property-info": {
"version": "v6.0.7"
},
"symfony/proxy-manager-bridge": {
"version": "v6.0.6"
},
"symfony/routing": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "6.0",
"ref": "eb3b377a4dc07006c4bdb2c773652cc9434f5246"
"branch": "main",
"version": "6.1",
"ref": "a44010c0d06989bd4f154aa07d2542d47caf5b83"
},
"files": [
"config/packages/routing.yaml",
"config/routes.yaml"
]
},
"symfony/runtime": {
"version": "v6.0.7"
},
"symfony/security-bundle": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "5.3",
"ref": "98f1f2b0d635908c2b40f3675da2d23b1a069d30"
"branch": "main",
"version": "6.0",
"ref": "8a5b112826f7d3d5b07027f93786ae11a1c7de48"
},
"files": [
"config/packages/security.yaml"
]
},
"symfony/security-core": {
"version": "v6.0.7"
},
"symfony/security-csrf": {
"version": "v6.0.3"
},
"symfony/security-http": {
"version": "v6.0.7"
},
"symfony/serializer": {
"version": "v6.0.7"
},
"symfony/service-contracts": {
"version": "v3.0.1"
},
"symfony/stopwatch": {
"version": "v6.0.5"
},
"symfony/string": {
"version": "v6.0.3"
},
"symfony/translation": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "5.3",
"ref": "da64f5a2b6d96f5dc24914517c0350a5f91dee43"
},
@ -487,17 +247,11 @@
"translations/.gitignore"
]
},
"symfony/translation-contracts": {
"version": "v3.0.1"
},
"symfony/twig-bridge": {
"version": "v6.0.7"
},
"symfony/twig-bundle": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "5.4",
"ref": "bb2178c57eee79e6be0b297aa96fc0c0def81387"
},
@ -506,14 +260,11 @@
"templates/base.html.twig"
]
},
"symfony/uid": {
"version": "v6.0.3"
},
"symfony/validator": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"branch": "main",
"version": "5.3",
"ref": "c32cfd98f714894c4f128bb99aa2530c1227603c"
},
@ -521,47 +272,26 @@
"config/packages/validator.yaml"
]
},
"symfony/var-dumper": {
"version": "v6.0.6"
},
"symfony/var-exporter": {
"version": "v6.0.7"
},
"symfony/web-link": {
"version": "v6.0.3"
},
"symfony/web-profiler-bundle": {
"version": "6.0",
"version": "6.1",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "5.3",
"ref": "24bbc3d84ef2f427f82104f766014e799eefcc3e"
"branch": "main",
"version": "6.1",
"ref": "e42b3f0177df239add25373083a564e5ead4e13a"
},
"files": [
"config/packages/web_profiler.yaml",
"config/routes/web_profiler.yaml"
]
},
"symfony/webapp-meta": {
"version": "1.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.0",
"ref": "67cae591d131c133d63b893c5324796b88c59b34"
},
"files": [
"config/packages/messenger.yaml"
]
},
"symfony/webpack-encore-bundle": {
"version": "1.14",
"version": "1.16",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.10",
"ref": "91f4d29f5ebbd2fcccc71ca55a17d14a17b308e8"
"ref": "5878c7c28468ca0fdce2497a04cfc66bab0dc3ef"
},
"files": [
"assets/app.js",
@ -573,23 +303,5 @@
"package.json",
"webpack.config.js"
]
},
"symfony/yaml": {
"version": "v6.0.3"
},
"twig/extra-bundle": {
"version": "v3.3.8"
},
"twig/markdown-extra": {
"version": "v3.3.8"
},
"twig/twig": {
"version": "v3.3.10"
},
"webmozart/assert": {
"version": "1.10.0"
},
"willdurand/negotiation": {
"version": "3.1.0"
}
}

View File

@ -1,26 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Spookie{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
{# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{{ encore_entry_link_tags('tailwind') }}
{% endblock %}
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</head>
<body>
<script>
window.user = {{ user|raw }}
window.quote = {{ quote|raw }}
</script>
<div id="app"></div>
</body>
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>

View File

@ -1,4 +1,4 @@
{% extends 'base.html.twig' %}
{% extends '../themes/default/base.html.twig' %}
{% block title %}Log In!{% endblock %}

View File

@ -0,0 +1,13 @@
<footer class="footer">
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-bottom navbar-bottom">
<div class="d-flex justify-content-xl-around">
<div>powered by
<a href="#"><img src="{{ asset('build/images/Spookie/spookie_64x64.png') }}" alt="Spookie"></a>
</div>
<div id="legal">
<a href="{{ path('app_imprint') }}">Imprint</a>
<a href="{{ path('app_privacy') }}">Privacy Policy</a>
</div>
</div>
</nav>
</footer>

View File

@ -0,0 +1,61 @@
<nav class="navbar navbar-expand-md navbar-dark bg-dark sticky-top px-sm-5 border-0">
<a class="navbar-brand border-0" href="{{ path('app_main') }}">
<img src="{{ asset('build/images/24unix/24_logo_bg_64x64.png') }}" alt="24unix.net" id="site-logo">
</a>
<button class="navbar-toggler border-0" type="button" data-toggle="collapse" data-target="#CollapsingNavbar">
&#9776;
</button>
<div class="collapse navbar-collapse" id="CollapsingNavbar">
<ul class="navbar-nav ms-auto">
<!--
<li>
<form class="d-flex">
<input class="form-control me-2 my-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn" type="submit">Search</button>
</form>
</li>
-->
{% if is_granted('ROLE_USER') %}
<li class="nav-item dropdown me-auto">
<button type="button" id="navbar-dropdown" data-bs-target="#dropdown-menu" data-bs-toggle="dropdown"
class="btn btn-primary dropdown-toggle ml-auto mb-2 button-login">
{{ app.user.username }}
</button>
<div class="dropdown-menu dropdown-menu-dark dropdown-menu-end" id="dropdown-menu"
aria-labelledby="navbar-dropdown">
<a class="dropdown-item" href="{{ path('app_profile_edit') }}">
<span class="fa fa-lg fa-fw fa-user" aria-hidden="true"></span>
Profile</a>
<a class="dropdown-item" href="#">
<span class="fa fa-lg fa-fw fa-wrench" aria-hidden="true"></span>
Settings</a>
<div class="dropdown-divider"></div>
{% if is_granted('ROLE_ADMIN') %}
<a class="dropdown-item" href="{{ path('admin') }}">
<span class="fa fa-lg fa-fw fa-cog" aria-hidden="true"></span>
Administration
</a>
<div class="dropdown-divider"></div>
{% endif %}
<a class="dropdown-item" href="{{ path('app_logout') }}">
<span class="fa fa-lg fa-fw fa-sign-out" aria-hidden="true"></span>&nbsp;
Logout
</a>
</div>
</li>
{% else %}
<li class="nav-item">
<a class="btn btn-primary button-login" href="{{ path('app_login') }}" role="button"
id="buttonLogin">
<span class="fa fa-sign-in fa-lg fa-fw" aria-hidden="true"></span>Log In
</a>
</li>
{% endif %}
</ul>
</div>
</nav>

View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Spookie{% endblock %}</title>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
<!-- Matomo -->
<script>
let _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, g = d.createElement("script"), s = d.getElementsByTagName("script")[0]
g.async = true
g.src = u + "matomo.js"
s.parentNode.insertBefore(g, s)
})()
</script>
<!-- End Matomo Code -->
{% endblock %}
</head>
<body>
{% include template_dir ~ '_header.html.twig' %}
<div class="container-fluid mt-3">
<nav id="sidebar" class="vh-100 me-3">
<ul class="list-group ml1" id="main-menu">
<li class="list-group-item list-group-item-action">
<a href="{{ path('app_projects') }}" class="text-decoration-none">
<i class="fa fa-lg fa-fw fa-file-code-o" aria-hidden="true" title="Projects"></i>
<span class="menuText">&nbsp;Projects</span>
</a>
</li>
<li class="list-group-item list-group-item-action">
<a href="//git.24unix.net" class="text-decoration-none" target="_blank">
<i class="fa fa-lg fa-fw fa-gitea" aria-hidden="true" title="Gitea"></i>
<span class="menuText">&nbsp;Gitea</span>
</a>
<span class="menuText"><i class="fa fa-external-link" aria-hidden="true"></i></span>
</li>
<li class="list-group-item list-group-item-action">
<a href="//cloud.24unix.net" class="text-decoration-none" target="_blank">
<i class="fa fa-lg fa-fw fa-nextcloud" aria-hidden="true" title="NextCloud"></i>
<span class="menuText">&nbsp;NextCloud</span>
</a>
<span class="menuText"><i class="fa fa-external-link" aria-hidden="true"></i></span>
</li>
<li class="list-group-item list-group-item-action">
<a href="#" id="toggleSidebar">
<i id="toggleIcon" class="fa fa-lg fa-caret-square-o-left"></i>
</a>
</li>
<!-- <a href="//pastebin.24unix.net">pastebin.24unix.net</a>-->
</ul>
</nav>
</div>
<div class="container-fluid" id="content">
{% for message in app.flashes('success') %}
<div class="alert alert-success">
{{ message }}
</div>
{% endfor %}
{% for message in app.flashes('error') %}
<div class="alert alert-danger">
{{ message }}
</div>
{% endfor %}
{% block body %}
<div class="col">
<h1 class="q-title-show">Quote of the Moment</h1>
<div class="q-display p-3">
{# <i class="fa fa-quote-left"></i> #}
<p class="d-inline">
{{ quote | markdown_to_html }}
</p>
</div>
</div>
{% endblock %}
</div>
{% include template_dir ~ '_footer.html.twig' %}
</body>
</html>

View File

@ -0,0 +1,20 @@
{% extends template_dir ~ 'base.html.twig' %}
{% block title %}Imprint{% endblock %}
{% block body %}
<div class="imprint-wrapper">
<p>This page is only available in German, as the server is located in Germany.</p>
<p>Inhaltlich Verantwortlicher gemäß § 55 Abs. 2RStV: Michael Espey, Große Kirchreihe 27, 25377 Kollmar</p>
<p>eMail: webmaster (AT) 24unix.net</p>
<p>Für den Inhalt des Internetauftritts ist allein der Inhaber zuständig. Der Inhaber bemüht sich, sein Internetangebot aktuell, korrekt und vollständig zu halten. Dessen ungeachtet kann eine Garantie für die Vollständigkeit, Richtigkeit und letzte Aktualität der Angaben nicht übernommen werden. Daher kann der Inhaber keinerlei Verantwortung oder Haftung weder auf den redaktionellen Inhalt noch für die angebotenen Leistungen auf dieser Website übernehmen. Bei den bereitgestellten Informationen handelt es sich um solche allgemeiner Art, die nicht auf die Bedürfnisse bestimmter Personen oder Unternehmen zugeschnitten sind. Insbesondere soll durch sie keine rechtliche Beratung erfolgen. Trotz sorgfältiger inhaltlicher Kontrolle übernehme ich keine Haftung für die Inhalte externer Links. Für den Inhalt der verlinkten Seiten sind ausschließlich deren Betreiber verantwortlich.</p>
<p>Umsatzsteuer-Identifikationsnummer gemäß § 27a Umsatzsteuergesetz: DE245057708</p>
</div>
{% endblock %}

View File

@ -0,0 +1,289 @@
{% extends template_dir ~'base.html.twig' %}
{% block title %}Privacy{% endblock %}
{% block body %}
<p class="privacy-wrapper">
<h2>This page is only available in German, as the server is located in Germany.</h2>
<p style="text-align:left;">Der Betreiber der Internetseite 24unix.net nimmt den Schutz Deiner persönlichen Daten
sehr ernst.
Er behandelt Deine Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser
Datenschutzerklärung.
Die Kontaktdaten des Ansprechpartners kannst Du dem Impressum entnehmen.
Zusätzlich stehen Dir die Administratoren gerne unter webmaster@24unix.net zur Verfügung.<p>
<b>Behandlung personenbezogener Daten</b>
<p style="text-align:left;">Die Nutzung von 24unix.net zum Lesen und Suchen ist ohne Angabe von personenbezogenen
Daten möglich.
Die Nutzung der Angebote zur Diskussion (z.B. Schreiben von Beiträgen, private Nachrichten empfangen und
verfassen) benötigt eine vorherige Registrierung.
Die im Zuge dieser Registrierung eingegebenen Daten, die aus der Eingabemaske des Registrierungsformulars
ersichtlich sind, umfassen u.a. E-Mailadresse, Benutzername (Nutzung eines Pseudonyms möglich) und Passwort.
Diese Daten werden ausschließlich für die Verwendung des Angebots seitens 24unix.net erhoben und gespeichert.
Mit der Registrierung werden zudem das Datum sowie die Uhrzeit der Registrierung gespeichert.
Dies dient dem Fall, dass ein Dritter deine Daten missbraucht und sich mit diesen Daten ohne dein Wissen auf
24unix.net registriert sowie zur Absicherung des Betreibers.
Zugriff auf deine Registrierungsdaten haben ausschließlich der Betreiber (siehe Impressum) sowie die berufenen
Forenadministratoren (siehe Admin-Team).
Alle diese Parteien sind dieser Datenschutzrichtlinie verpflichtet. Eine Weitergabe deiner Daten an Dritte
erfolgt nicht.
Ein Abgleich der so erhobenen Daten mit Daten, die möglicherweise durch andere Komponenten (z.B. in
Server-Log-Dateien) erhoben werden, erfolgt ebenfalls nicht.
24unix.net anonymisiert sämtliche IP-Adressen seiner Nutzer automatisch nach drei Wochen.
Der Betreiber weist darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail)
Sicherheitslücken aufweist.
Einen lückenlosen Schutz deiner Daten vor dem Zugriff durch Dritte kann der Betreiber daher nicht
gewährleisten.</p>
<b>Speicherung des Passworts</b>
<p style="text-align:left">Dein Passwort wird mit einer Einwegeverschlüsselung (Hash) gespeichert, sodass der
originale Inhalt nicht rekonstruiert werden kann.
Jedoch ist zu empfehlen, dieses Passwort nicht auf einer Vielzahl von Webseiten zu verwenden.
Insbesondere wird dich kein Vertreter seitens 24unix.net (Betreiber oder Administratoren) nach deinem Passwort
fragen.
Solltest du dein Passwort vergessen haben, so nutze die Funktion „Ich habe mein Passwort vergessen“.
Die Forensoftware fragt dich daraufhin nach deinem Benutzernamen sowie eMailadresse und sendet anschließend ein
neu generiertes Passwort an deine hinterlegte Adresse.</p>
<b>Hinweis zur TLS-Verschlüsselung</b>
<p style="text-align:left">24unix.net wird über das Secure-http-Protokoll ausgeliefert. Diese TLS (früher:
SSL)-Verschlüsselung stellt nach derzeitigem technischen Stand sicher,
dass kein Dritter übertragene Daten mitlesen bzw. verändern kann. Dies gilt sowohl für die Inhalte der Seite als
auch für Daten,
die Ihr durch die Nutzung von Formularen an uns sendet.</p>
<b>Kommentarmöglichkeit</b>
<p style="text-align:left">24unix.net bietet Dir die Möglichkeit, Kommentare zu den einzelnen Beiträgen zu
hinterlassen.
Hierbei wird die IP-Adresse des Verfassers/Anschlussinhabers für drei Wochen gespeichert, um sie ggf. an
Strafermittlungsbehörden weiterleiten zu können wenn wir dazu verpflichtet werden sollten.
Eine Weitergabe von Daten an Dritte erfolgt nicht. Ein Abgleich der so erhobenen Daten mit Daten, die
möglicherweise durch andere Komponenten seitens 24unix.net erhoben werden,
erfolgt ebenfalls nicht.</p>
<b>Nutzung von Cookies</b>
<p style="text-align:left">24unix.net verwendet sogenannte Cookies. Dies sind kleine Textdateien, die auf Deinem
Rechner lokal abgelegt werden und die Dein Browser speichert.
Cookies dienen dazu, das Forum nutzerfreundlicher, effektiver und sicherer zu machen.
<!-- Alle Cookies werden standardmäßig für ein Jahr angelegt, können jedoch jederzeit über einen am Ende der Seite
[url="https://rc-heli-fan.org/ucp.php?mode=delete_cookies"]auffindbaren Link[/url] gelöscht werden.-->
Cookies werden im 24unix.net für folgende Funktionen genutzt:</p>
<ul style="text-align:left">
<li>Speichern der persönlichen Einstellung der User, über ein- oder ausgeklappte Kategorien
<li>Den automatischen Login-Dienst zu nutzen
<li>Die Sitzungs-ID. Mit diesem Cookie wird in Verbindung mit der Benutzer-ID der Nutzer identifiziert.
<li>Die User ID des Benutzers
<li>Speichern, ob der User den Hinweis des Forums, dass Cookies genutzt werden, bestätigt hat.
<li>Markieren von gelesenen/ungelesenen Beiträgen für Gäste
</ul>
<p style="text-align:left">Du kannst den Umgang mit Cookies in Deinem Browser konfigurieren, z.B. das du über das
Speichern neuer Cookies
informiert wirst.
Bei der Deaktivierung von Cookies im Browser kann die Funktionalität des 24unix.nets eingeschränkt sein.</p>
<b>Zugriffsdaten in Server-Log-Dateien</b>
<p style="text-align:left">24unix.net erhebt und speichert Informationen in sogenannten Server-Log-Dateien, die Dein
Browser automatisch übermittelt.
Diese Daten werden bis zu zehn Wochen gespeichert. Sie umfassen:</p>
<ul style="text-align:left">
<li>Browsertyp und -version</li>
<li>verwendetes Betriebssystem</li>
<li>Webseite, von der aus du uns besuchst (Referrer URL)</li>
<li>die aufgerufene Seite</li>
<li>Datum und Uhrzeit des Zugriffs</li>
<li>die Internet Protokoll (IP)-Adresse</li>
</ul>
<p style="text-align:left">Die Verarbeitung erfolgt gemäß Art. 6 Abs. 1 lit. f DSGVO auf Basis unseres berechtigten Interesses an
der Verbesserung der Stabilität
und Funktionalität unserer Website. Eine Weitergabe oder anderweitige Verwendung der Daten findet nicht statt.
Wir behalten uns allerdings vor, die Server-Logfiles nachträglich zu überprüfen, sollten konkrete Anhaltspunkte
auf eine rechtswidrige Nutzung hinweisen.</p>
<b>Gestattung der Kontaktaufnahme</b>
<p style="text-align:left">Du gestattest dem Betreiber und den Administratoren, dich unter den von dir angegebenen
Kontaktdaten zu kontaktieren,
sofern dies zur Übermittlung zentraler Informationen über das Forum erforderlich ist. Darüber hinaus dürfen der
Betreiber,
Administratoren und andere registrierte Benutzer des Forums dich kontaktieren, sofern du dies an entsprechender
Stelle erlaubt hast.
Im Rahmen der Kontaktaufnahme mit uns (z.B. per eMail) werden personenbezogene Daten (IP Adressen) erhoben.
Diese Daten werden ausschließlich zum Zweck der Beantwortung deines Anliegens bzw. für die Kontaktaufnahme und
die damit verbundene technische Administration gespeichert und verwendet. Rechtsgrundlage für die Verarbeitung
der Daten ist unser berechtigtes Interesse an der Beantwortung deines Anliegens gemäß Art. 6 Abs. 1 lit. f
DSGVO.
Zielt Deine Kontaktierung auf den Abschluss eines Vertrages ab, so ist zusätzliche Rechtsgrundlage für die
Verarbeitung Art. 6 Abs. 1 lit. b DSGVO.
Deine Daten werden nach abschließender Bearbeitung der Anfrage gelöscht, dies ist der Fall, wenn sich aus den
Umständen entnehmen lässt,
dass der betroffene Sachverhalt abschließend geklärt ist und sofern keine gesetzlichen Aufbewahrungspflichten
entgegenstehen.</p>
<b>Rechte des Betroffenen</b>
<p style="text-align:left">Das geltende Datenschutzrecht gewährt dir gegenüber dem Verantwortlichen hinsichtlich der
Verarbeitung deiner personenbezogenen Daten
umfassende Betroffenenrechte (Auskunfts- und Interventionsrechte), über die wir dich nachstehend
informieren:</p>
<ul style="text-align:left">
<li>Auskunftsrecht gemäß Art. 15 DSGVO: Du hast insbesondere ein Recht auf Auskunft über Deine von uns
verarbeiteten personenbezogenen Daten,
die Verarbeitungszwecke, die Kategorien der verarbeiteten personenbezogenen Daten, die Empfänger oder
Kategorien
von Empfängern,
gegenüber denen Deine Daten offengelegt wurden oder werden, die geplante Speicherdauer bzw. die Kriterien
für
die Festlegung der Speicherdauer,
das Bestehen eines Rechts auf Berichtigung, Löschung, Einschränkung der Verarbeitung, Widerspruch gegen die
Verarbeitung,
Beschwerde bei einer Aufsichtsbehörde, die Herkunft Deiner Daten, wenn diese nicht durch uns bei dir erhoben
wurden,
das Bestehen einer automatisierten Entscheidungsfindung einschließlich Profiling und ggf. aussagekräftige
Informationen
über die involvierte Logik und die Dich betreffende Tragweite und die angestrebten Auswirkungen einer
solchen
Verarbeitung,
sowie dein Recht auf Unterrichtung, welche Garantien gemäß Art. 46 DSGVO bei Weiterleitung deiner Daten in
Drittländer bestehen.
</li>
<li>Recht auf Berichtigung gemäß Art. 16 DSGVO: Du hast ein Recht auf unverzügliche Berichtigung dich
betreffender unrichtiger Daten
und/oder Vervollständigung deiner bei uns gespeicherten unvollständigen Daten.
</li>
<li>Recht auf Löschung gemäß Art. 17 DSGVO: Du hast das Recht, die Löschung Deiner personenbezogenen Daten bei
Vorliegen
der Voraussetzungen des Art. 17 Abs. 1 DSGVO zu verlangen. Dieses Recht besteht jedoch insbesondere dann
nicht,
wenn die Verarbeitung zur Ausübung des Rechts auf freie Meinungsäußerung und Information, zur Erfüllung
einer
rechtlichen
Verpflichtung, aus Gründen des öffentlichen Interesses oder zur Geltendmachung, Ausübung oder Verteidigung
von
Rechtsansprüchen erforderlich ist.
</li>
<li>Recht auf Einschränkung der Verarbeitung gemäß Art. 18 DSGVO: Du hast das Recht, die Einschränkung der
Verarbeitung Deiner personenbezogenen
Daten zu verlangen, solange die von dir bestrittene Richtigkeit Deiner Daten überprüft wird, wenn du eine
Löschung Deiner Daten wegen unzulässiger
Datenverarbeitung ablehnst und stattdessen die Einschränkung der Verarbeitung Deiner Daten verlangen, wenn
du
Deine Daten zur Geltendmachung,
Ausübung oder Verteidigung von Rechtsansprüchen benötigst, nachdem wir diese Daten nach Zweckerreichung
nicht
mehr benötigen oder wenn du Widerspruch
aus Gründen deiner besonderen Situation eingelegt hast, solange noch nicht feststeht, ob unsere berechtigten
Gründe überwiegen.
</li>
<li>Recht auf Unterrichtung gemäß Art. 19 DSGVO: Hast Du das Recht auf Berichtigung, Löschung oder Einschränkung
der Verarbeitung gegenüber
dem Verantwortlichen geltend gemacht, ist dieser verpflichtet, allen Empfängern, denen die dich betreffenden
personenbezogenen Daten
offengelegt wurden, diese Berichtigung oder Löschung der Daten oder Einschränkung der Verarbeitung
mitzuteilen,
es sei denn, dies erweist
sich als unmöglich oder ist mit einem unverhältnismäßigen Aufwand verbunden. Dir steht das Recht zu, über
diese
Empfänger unterrichtet zu werden.
</li>
<li>Recht auf Datenübertragbarkeit gemäß Art. 20 DSGVO: Du hast das Recht, Deine personenbezogenen Daten, die du
uns bereitgestellt hast,
in einem strukturierten, gängigen und maschinenlesebaren Format zu erhalten oder die Übermittlung an einen
anderen Verantwortlichen
zu verlangen, soweit dies technisch machbar ist.
</li>
<li>Recht auf Widerruf erteilter Einwilligungen gemäß Art. 7 Abs. 3 DSGVO: Du hast das Recht, eine einmal
erteilte Einwilligung
in die Verarbeitung von Daten jederzeit mit Wirkung für die Zukunft zu widerrufen. Im Falle des Widerrufs
werden
wir die betroffenen
Daten unverzüglich löschen, sofern eine weitere Verarbeitung nicht auf eine Rechtsgrundlage zur
einwilligungslosen Verarbeitung gestützt
werden kann. Durch den Widerruf der Einwilligung wird die Rechtmäßigkeit der aufgrund der Einwilligung bis
zum
Widerruf erfolgten Verarbeitung nicht berührt.
</li>
<li>Recht auf Beschwerde gemäß Art. 77 DSGVO: Wenn du der Ansicht bist, dass die Verarbeitung der Dich
betreffenden personenbezogenen Daten gegen die DSGVO
verstößt, hast du - unbeschadet eines anderweitigen verwaltungsrechtlichen oder gerichtlichen Rechtsbehelfs
-
das Recht auf Beschwerde
bei einer Aufsichtsbehörde, insbesondere in dem Mitgliedstaat deines Aufenthaltsortes, deines Arbeitsplatzes
oder des Ortes des mutmaßlichen Verstoßes.
</li>
</ul>
<b>Widerspruchsrecht</b>
<p style="text-align:left">Du hast das Recht, aus Gründen, die sich aus Deiner besonderen Situation ergibt,
jederzeit gegen die Verarbeitung der Dich betreffenden
personenbezogenen Daten, die aufgrund von Art. 6 Abs. 1 lit. e oder f DSGVO erfolgt, Widerspruch einzulegen;
dies gilt auch für ein auf diese Bestimmungen gestütztes Profiling.
Der Verantwortliche verarbeitet die Dich betreffenden personenbezogenen Daten nicht mehr, es sei denn, er kann
zwingende schutzwürdige Gründe
für die Verarbeitung nachweisen, die deine Interessen, Rechte und Freiheiten überwiegen, oder die Verarbeitung
dient der Geltendmachung,
Ausübung oder Verteidigung von Rechtsansprüchen.
Werden die Dich betreffenden personenbezogenen Daten verarbeitet, um Direktwerbung zu betreiben, hast du das
Recht,
jederzeit Widerspruch gegen die Verarbeitung der Dich betreffenden personenbezogenen Daten zum Zwecke derartiger
Werbung einzulegen;
dies gilt auch für das Profiling, soweit es mit solcher Direktwerbung in Verbindung steht.
Widersprichst du der Verarbeitung für Zwecke der Direktwerbung, so werden die dich betreffenden
personenbezogenen Daten nicht mehr für diese Zwecke verarbeitet.
Du hast die Möglichkeit, im Zusammenhang mit der Nutzung von Diensten der Informationsgesellschaft ungeachtet
der Richtlinie 2002/58/EG Dein
Widerspruchsrecht mittels automatisierter Verfahren auszuüben, bei denen technische Spezifikationen verwendet
werden.
Du hast auch das Recht, aus Gründen, die sich aus Deiner besonderen Situation ergeben, bei der Verarbeitung Dich
betreffender personenbezogener Daten,
die zu wissenschaftlichen oder historischen Forschungszwecken oder zu statistischen Zwecken gem. Art. 89 Abs. 1
DSGVO erfolgt, dieser zu widersprechen.
Dein Widerspruchsrecht kann insoweit beschränkt werden, als es voraussichtlich die Verwirklichung der
Forschungs- oder Statistikzwecke unmöglich
macht oder ernsthaft beeinträchtigt und die Beschränkung für die Erfüllung der Forschungs- oder Statistikzwecke
notwendig ist.</p>
<b>Geltungsbereich dieser Richtlinie</b>
<p>Diese Richtlinie umfasst alle Seiten, die unter 24unix.net gespeichert sind.
Ergeben sich Änderungen an dieser Richtlinie, werden die Benutzer des Forums hierüber informiert und es besteht
ein Widerspruchsrecht.
Explizit keinen Einfluss hat der Betreiber auf externe, verlinkte Webseiten, auf denen diese Richtlinie nicht
gilt.</p>
Quellen:
<ul style="text-align:left;padding-bottom: 200px">
<li><a href="https://www.ratgeberrecht.eu">Muster-Datenschutzerklärung der Anwaltskanzlei Weiß & Partner</a>
</li>
<li><a href="https://www.e-recht24.de">e-recht24.de</a></li>
<li><a href="https://dsaforum.de/app.php/datenschutz">Datenschutzerklärung des DSA-Forums</a></li>
<li>eigene Ergänzungen</li>
</ul>
{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends 'base.html.twig' %}
{% extends '../themes/default/base.html.twig' %}
{% block title %}
Profile of {{ user.username }}

View File

@ -1,4 +1,4 @@
{% extends 'base.html.twig' %}
{% extends '../themes/default/base.html.twig' %}
{% block title %}
Userlist

View File

@ -1,4 +1,4 @@
{% extends 'base.html.twig' %}
{% extends '../themes/default/base.html.twig' %}
{% block title %}
Profile of {{ user.username }}

View File

@ -14,7 +14,6 @@ Encore
to: 'images/[path][name].[ext]'
})
.addEntry('app', './assets/js/index.js')
.addEntry('tailwind', './assets/styles/tailwind.css')
.splitEntryChunks()
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
@ -36,7 +35,6 @@ Encore
styles: path.resolve(__dirname, 'assets', 'styles')
})
.enableSassLoader()
.enableVueLoader(() => {}, { runtimeCompilerBuild: false })
.enableTypeScriptLoader()
.enablePostCssLoader((options) => {
options.postcssOptions = {

1178
yarn.lock

File diff suppressed because it is too large Load Diff