Compare commits

...

22 Commits

Author SHA1 Message Date
164aee574e Update dependency katex to ^0.17.0
Some checks failed
renovate/artifacts Artifact file update failure
2026-06-06 15:11:47 +00:00
e592334fb2 Merge pull request 'Update Rust crate serde_json to v1.0.150' (#7) from renovate/serde_json-1.x-lockfile into nuxt
Reviewed-on: #7
2026-05-30 08:50:54 +00:00
a832d5cf8f Merge pull request 'Update Rust crate tauri to v2.11.2' (#8) from renovate/tauri-2.x-lockfile into nuxt
Reviewed-on: #8
2026-05-30 08:50:45 +00:00
9c88cfa860 Update Rust crate tauri to v2.11.2 2026-05-30 08:39:34 +00:00
6ed630b37f Update Rust crate serde_json to v1.0.150 2026-05-30 08:39:11 +00:00
8ecb64b80a Update node Docker tag to v26 (#6) 2026-05-09 10:17:26 +00:00
2efef8c4aa Update node Docker tag to v26 2026-05-08 11:08:52 +00:00
a42226dc13 Update package-lock.json 2026-05-08 12:17:25 +02:00
9f51261e58 Merge pull request 'Update node Docker tag to v25' (#5) from renovate/node-25.x into nuxt
Reviewed-on: #5
2026-05-06 13:02:04 +00:00
28cf26c953 Update node Docker tag to v25 2026-05-06 13:01:49 +00:00
31ef7c245f Merge pull request 'Update Rust crate tauri to v2.11.1' (#3) from renovate/tauri-2.x-lockfile into nuxt
Reviewed-on: #3
2026-05-06 12:58:54 +00:00
1ed2efb52a Update Rust crate tauri to v2.11.1 2026-05-06 12:56:38 +00:00
8d7c0fbcc5 Merge pull request 'Update Rust crate serde_json to v1.0.149' (#2) from renovate/serde_json-1.x-lockfile into nuxt
Reviewed-on: #2
2026-05-06 12:55:04 +00:00
5dd1d0f88d Merge pull request 'Update Rust crate tauri-plugin-opener to v2.5.4' (#4) from renovate/tauri-plugin-opener-2.x-lockfile into nuxt
Reviewed-on: #4
2026-05-06 12:53:30 +00:00
358461c50a Merge pull request 'Update Rust crate serde to v1.0.228' (#1) from renovate/serde-1.x-lockfile into nuxt
Reviewed-on: #1
2026-05-06 12:52:58 +00:00
aa43d12787 Update Rust crate tauri-plugin-opener to v2.5.4 2026-05-06 12:48:27 +00:00
f9fe6e9639 Add bildschau and bildvorschau 2026-05-06 14:48:27 +02:00
48595fb8b2 Update Rust crate serde_json to v1.0.149 2026-05-06 11:58:21 +00:00
b4e7bbfa83 Update Rust crate serde to v1.0.228 2026-05-06 11:57:58 +00:00
8f8decf263 Fix Galerie 2026-05-05 12:29:21 +02:00
75b50fb9ef Add Form Support 2026-05-02 19:11:09 +02:00
d388d7048a Fix tauri, add DTO Submodule 2026-04-26 22:29:51 +02:00
26 changed files with 1810 additions and 1314 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "app/dto"]
path = app/dto
url = https://git.ritzenbergen.de/R40fendt/ritzenbergen-dto.git

View File

@@ -1,4 +1,4 @@
FROM node:20-alpine
FROM node:26-alpine
WORKDIR /app

View File

@@ -1,6 +0,0 @@
<template>
<div>
<NuxtRouteAnnouncer />
<NuxtWelcome />
</div>
</template>

View File

@@ -1,6 +1,5 @@
<script setup>
<script setup lang="ts">
import emblaCarouselVue from "embla-carousel-vue";
import RitzenbergenLib from "../ritzenbergenlib.ts";
import { onMounted, ref } from "vue";
import EmblaItem from "./EmblaItem.vue";
@@ -42,13 +41,22 @@ defineProps({
type: Array,
required: true,
},
jahre: {
type: Array,
required: false,
},
fontSize:{
type: Number,
required: false,
default: 100
}
});
</script>
<template>
<div class="embla" ref="emblaRef">
<div class="embla__container">
<EmblaItem v-for="el, i in src" :src="el" :link="links[i]" />
<EmblaItem v-for="el, i in src" :src="el" :jahr="jahre?jahre[i]:null" :link="links[i]" :font-size="fontSize"/>
</div>
<button class="embla__button embla__button--prev" @click="prev">
<span class="mobi-mbri mobi-mbri-arrow-prev" aria-hidden="true"></span>

View File

@@ -1,7 +1,5 @@
<script lang="ts">
export default {
props: ["src", "link"],
};
<script lang="ts" setup>
const {src, link, jahr, fontSize}=defineProps(["src", "link","jahr","fontSize"]);
</script>
<template>
<div
@@ -11,16 +9,31 @@ export default {
<div class="slide-content">
<div class="item-img">
<div class="item-wrapper">
<RouterLink :to="link">
<NuxtLink :to="link">
<img
:src="
src
"
/>
</RouterLink>
<span class="jahr-overlay" v-if="jahr" :style="{'font-size': fontSize+'px'}">
{{ jahr }}
</span>
</NuxtLink>
</div>
</div>
</div>
</div>
</template>
<style></style>
<style scoped>
.item-wrapper {
position: relative;
}
.jahr-overlay {
color: white;
mix-blend-mode: difference;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
</style>

View File

@@ -17,7 +17,7 @@ export default {
<section
class="footer3 cid-u6k7q0Blvk"
once="footers"
id="footer-6-u6k7q0Blvk"
id="footer"
>
<div class="container">
<div class="row">
@@ -41,7 +41,7 @@ export default {
<br />
</p>
<RouterLink to="/adminpanel/login">Admin Login</RouterLink>
<NuxtLink to="/adminpanel/login">Admin Login</NuxtLink>
</Modal>
<button @click="aboutVisible=true" class="text-white btn-ueber openBtn">Über</button>

View File

@@ -15,8 +15,8 @@ export default {
return {
datalinks: [
{ link: "/galerie", title: "Galerie" },
{ link: "/umgebung", title: "Umgebung" },
{ link: "/footer", title: "Kontakt" },
{ link: "/#umgebung", title: "Umgebung" },
{ link: "/#footer", title: "Kontakt" },
{ link: "/bulitipp", title: "BuLi-Tipp" },
],
buttontextdata: "Über Ritzenbergen",
@@ -58,18 +58,18 @@ export default {
<div class="container">
<div class="navbar-brand">
<span class="navbar-logo">
<span href="/">
<NuxtLink to="/">
<img
class="navbar-logo-img"
src="../assets/RitzenbergenOrtsschild.png"
style="height: 60px; padding-left: 5px"
/>
</span>
</NuxtLink>
</span>
<span class="navbar-caption-wrap">
<span class="navbar-caption text-black display-4" href="/"
>Amedorf & Ritzenbergen</span
>
<NuxtLink to="/" class="navbar-caption text-black display-4">
Amedorf & Ritzenbergen
</NuxtLink>
</span>
</div>
<button
@@ -95,13 +95,13 @@ export default {
<div class="navbar-collapse opacityScroll" :class="{show: !isNavCollapsed, collapsing: isCollapsing, collapse: !isCollapsing}" id="navbarSupportedContent">
<ul class="navbar-nav nav-dropdown" data-app-modern-menu="true">
<li class="nav-item" v-for="link in datalinks">
<span
<NuxtLink
class="nav-link link text-black display-4"
:href="link.link"
:to="link.link"
aria-expanded="false"
>
{{ link.title }}
</span>
</NuxtLink>
</li>
</ul>
<div class="navbar-buttons mbr-section-btn">

View File

@@ -1,38 +1,37 @@
<script lang="ts" setup>
import RitzenbergenLib from "../../ritzenbergenlib.ts";
import {ref} from "vue";
async function loadImage(path: string) {
try{
const response = await fetch(RitzenbergenLib.RitzenbergenLib.api(path), {
headers: {
"Accept":"image/png"
}
});
if(!response.ok) return false;
const blob = await response.blob();
return URL.createObjectURL(blob);
// async function loadImage(path: string) {
// try{
// const response = await fetch(RitzenbergenLib.RitzenbergenLib.api(path), {
// headers: {
// "Accept":"image/png"
// }
// });
// if(!response.ok) return false;
// const blob = await response.blob();
// return URL.createObjectURL(blob);
}
catch(e){
console.warn(e);
}
}
// }
// catch(e){
// console.warn(e);
// }
// }
loadImage("randomimage.php?path=/doppelkopf&recursive=1&tn=1&color=white&text=Doppelkopf&size=3").then((url)=>{
images.value[0]=url;
});
loadImage("randomimage.php?path=/erntefest&recursive=1&tn=1&color=white&text=Erntefest&size=3").then((url)=>{
images.value[1]=url;
});
loadImage("randomimage.php?path=/fussball&recursive=1&tn=1&color=white&text=Fußballturnier&size=3").then((url)=>{
images.value[2]=url;
});
loadImage("randomimage.php?path=/osterfeuer&recursive=1&tn=1&color=white&text=Osterfeuer&size=3").then((url)=>{
images.value[3]=url;
});
// loadImage("randomimage.php?path=/doppelkopf&recursive=1&tn=1&color=white&text=Doppelkopf&size=3").then((url)=>{
// images.value[0]=url;
// });
// loadImage("randomimage.php?path=/erntefest&recursive=1&tn=1&color=white&text=Erntefest&size=3").then((url)=>{
// images.value[1]=url;
// });
// loadImage("randomimage.php?path=/fussball&recursive=1&tn=1&color=white&text=Fußballturnier&size=3").then((url)=>{
// images.value[2]=url;
// });
// loadImage("randomimage.php?path=/osterfeuer&recursive=1&tn=1&color=white&text=Osterfeuer&size=3").then((url)=>{
// images.value[3]=url;
// });
const images=ref([]);
const images=ref(["bild1","bild2","bild3","bild4"]);
</script>
<template>
<section
@@ -64,9 +63,9 @@ const images=ref([]);
>
<div class="item-wrapper">
<div class="item-img">
<RouterLink to="/galerie/doppelkopf"
<NuxtLink to="/galerie/#doppelkopf"
><img :src="images[0]"
/></RouterLink>
/></NuxtLink>
</div>
</div>
</div>
@@ -75,9 +74,9 @@ const images=ref([]);
>
<div class="item-wrapper">
<div class="item-img">
<RouterLink to="/galerie/erntefest"
<NuxtLink to="/galerie/#erntefest"
><img :src="images[1]"
/></RouterLink>
/></NuxtLink>
</div>
</div>
</div>
@@ -86,9 +85,9 @@ const images=ref([]);
>
<div class="item-wrapper">
<div class="item-img">
<RouterLink to="/galerie/fussball"
<NuxtLink to="/galerie/#fussball"
><img :src="images[2]"
/></RouterLink>
/></NuxtLink>
</div>
</div>
</div>
@@ -97,9 +96,9 @@ const images=ref([]);
>
<div class="item-wrapper">
<div class="item-img">
<RouterLink to="/galerie/osterfeuer"
<NuxtLink to="/galerie/#osterfeuer"
><img :src="images[3]"
/></RouterLink>
/></NuxtLink>
</div>
</div>
</div>

View File

@@ -5,8 +5,9 @@ import { ref } from "vue";
import Modal from "../Modal.vue";
import { Formular } from "../../dto/formular.dto";
async function init() {
forms.value=await RitzenbergenLib.graphqlClient.request<{formulare: Formular[] }>(`
const { $gql, $myfetch } = useNuxtApp();
const forms = await $gql.request<{formulare: Formular[] }>(`
{
formulare {
id
@@ -33,31 +34,16 @@ async function init() {
`
).then(data=>data.formulare);
console.log(forms.value);
}
const forms = ref([] as Formular[]);
const props=defineProps({
formid: {
type: [Number, null],
required: false,
default: null
}
});
init();
function submit($event: Event) {
const url = new URL(
RitzenbergenLib.RitzenbergenLib.api("/formulare/submit.php")
);
console.log($event);
if($event.target==null) return;
const formData = new FormData(<HTMLFormElement>$event.target);
fetch(url.toString(), {
const body = Object.fromEntries(formData);
$myfetch("/formulare/submit/"+(<HTMLFormElement>$event.target).dataset.formid,{
method: "POST",
body: formData
body
}).then(() => {
init();
values.value={};
});
}
@@ -109,6 +95,7 @@ const values=ref({});
:data-i="i"
@submit.prevent="submit"
>
<div v-for="(field, j) in form.fields" :key="j">
<label
v-if="field.placeholder == null"
@@ -160,7 +147,6 @@ const values=ref({});
Absenden
</button>
</div>
<input type="hidden" :value="form.id" name="internalformid" />
</form>
</div>
</div>

1
app/dto Submodule

Submodule app/dto added at 78d9d15d64

View File

@@ -1,3 +0,0 @@
# Ritzenbergen DTO
- Test

View File

@@ -1,23 +0,0 @@
export class MyEvent {
id: number;
eventname: string;
datum: Date;
type: EventType;
content: string;
minitext: string;
link: string|null;
foto: string;
formular: number|null;
}
export enum EventType {
html = "html",
markdown = "markdown",
fotos = "fotos",
link = "link",
dlink = "dlink"
}

View File

@@ -1,55 +0,0 @@
export class Formular {
public id: number;
public name: string;
public minitext: string;
public ispublic: boolean;
public multiple: boolean;
public fields: MyField[];
public results: FormularResults[];
}
export enum FieldType {
TEXT = "text",
PASSWORD = "password",
NUMBER = "number",
RANGE = "range",
DATE = "date",
TIME = "time",
CHECKBOX = "checkbox",
RADIO = "radio",
COLOR = "color",
SUBMIT = "submit",
TEXTAREA = "textarea"
}
export class MyField {
id?: number;
formular: number;
name: string;
displayname?: string | null;
value: string;
displayvalue?: string | null;
placeholder?: string | null;
type: FieldType;
title?: string | null;
required: boolean;
maxlength?: number | null;
min?: number | null;
max?: number | null;
checked?: boolean | null;
}
export class FormularResult {
id: number;
parentid: number;
parentobj: FormularResults;
name: string;
value: string;
}
export class FormularResults {
id:number;
formular: Formular;
formularid: number;
results: FormularResult[];
}

View File

@@ -1,164 +0,0 @@
<script lang="js">
import Navbar from "../components/Navbar.vue";
import Embla from "../components/Embla.vue";
import RitzenbergenLib from "../ritzenbergenlib.ts";
import MyFooter from "../components/MyFooter.vue"; // Geändert von Footer auf MyFooter
import $ from "jquery";
export default {
components: {
Navbar,
Embla,
MyFooter, // Geändert von Footer auf MyFooter
},
computed: {
events() {
let erntefeste = this.get_jahre("erntefest");
let osterfeuer = this.get_jahre("osterfeuer");
let doppelkopf = this.get_jahre("doppelkopf");
let fussball = this.get_jahre("fussball");
if(erntefeste==undefined) return [];
let result = [
{
src: erntefeste.map((erntefest) =>
RitzenbergenLib.RitzenbergenLib.api(
"randomimage.php?path=/erntefest/" +
erntefest +
"&recursive=1&tn=1&text=" +
erntefest +
"&color=white"
)
),
title: "Erntefeste",
ev: "erntefest",
},
{
src: osterfeuer.map((osterfeuer) =>
RitzenbergenLib.RitzenbergenLib.api(
"randomimage.php?path=/osterfeuer/" +
osterfeuer +
"&recursive=1&tn=1&text=" +
osterfeuer +
"&color=white"
)
),
title: "Osterfeuer",
ev: "osterfeuer",
},
{
src: doppelkopf.map((doppelkopf) =>
RitzenbergenLib.RitzenbergenLib.api(
"randomimage.php?path=/doppelkopf/" +
doppelkopf +
"&recursive=1&tn=1&text=" +
doppelkopf +
"&color=white"
)
),
title: "Doppelkopf",
ev: "doppelkopf",
},
{
src: fussball.map((fussball) =>
RitzenbergenLib.RitzenbergenLib.api(
"randomimage.php?path=/fussball/" +
fussball +
"&recursive=1&tn=1&text=" +
fussball +
"&color=white"
)
),
title: "Fußballturniere",
ev: "fussball",
},
];
return result.map((ev) => {
let jahre = this.get_jahre(ev.ev);
ev.links = jahre.map((jahr) => {
return "/bild/" + ev.ev + "/" + jahr;
});
return ev;
});
},
},
methods: {
get_jahre(event) {
let result;
$.ajax(RitzenbergenLib.RitzenbergenLib.api("/galerie/get_jahre.php"), {
success(data) {
result = JSON.parse(data);
},
async: false,
data: { event },
});
return result;
},
},
mounted(){
if(this.$route.params.ev){
let ev = this.$route.params.ev;
if(this.$refs[ev]) this.$refs[ev][0].scrollIntoView();
this.$router.push("/galerie");
}
}
};
</script>
<template>
<Navbar :links="[
{ title: 'Erntefest', link: '/galerie/erntefest' },
{ title: 'Osterfeuer', link: '/galerie/osterfeuer' },
{ title: 'Doppelkopf', link: '/galerie/doppelkopf' },
{ title: 'Fußballturniere', link: '/galerie/fussball' },
]" />
<br />
<br />
<br />
<br />
<br />
<br />
<section class="article12 cid-u6k7q0yKNv" id="about-us-12-u6k7q0yKNv">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12 col-lg-10">
<h3 class="mbr-section-title mbr-fonts-style mb-4 mt-0 display-2">
<strong>Willkommen in der Galerie</strong>
</h3>
<p class="mbr-text mbr-fonts-style display-7">
In unserem Fotoalbum findest du chronisch geordnete Bilder
verschiedener Veranstaltungen aus den letzten Jahrzehnten. Einfach
auf ein Bild mit einer Jahreszahl raufklicken.
</p>
</div>
</div>
</div>
</section>
<br /><br />
<section
class="slider4 mbr-embla cid-u6k7q0yLdW"
:ref="event.ev"
v-for="event in events"
>
<div class="container-fluid">
<div class="row">
<h4
class="mbr-section-title mbr-fonts-style align-center mb-0 display-2"
>
<strong>{{ event.title }}</strong>
</h4>
<div class="col-12">
<br />
<Embla :src="event.src" :links="event.links" />
</div>
</div>
</div>
<br /><br /><br />
</section>
<h1 v-if="events.length==0">Keine Internetverbindung!</h1>
<br /><br /><br />
<MyFooter />
</template>
<style scoped></style>

View File

@@ -2,7 +2,7 @@
import Navbar from "../../components/Navbar.vue";
import { ref } from "vue";
import { useRouter } from 'vue-router'
import RitzenbergenLib from "../../ritzenbergenlib.ts";
import RitzenbergenLib from "../../ritzenbergenlib";

View File

@@ -1,28 +1,71 @@
<script lang="ts">
import MyFooter from "../components/MyFooter.vue"; // Geändert von Footer auf MyFooter
import Navbar from "../components/Navbar.vue";
import RitzenbergenLib from "../ritzenbergenlib";
import $ from "jquery";
import type { JahrMitBild } from "~/dto/galerie.dto";
import MyFooter from "../../../../components/MyFooter.vue"; // Geändert von Footer auf MyFooter
import Navbar from "../../../../components/Navbar.vue";
import RitzenbergenLib from "../../../../ritzenbergenlib";
const route=useRoute();
const {$gql} = useNuxtApp();
export default {
components: {
Navbar,
MyFooter, // Geändert von Footer auf MyFooter
},
onMounted(){
console.log($gql.request<{bilder:JahrMitBild[]}>(`
{
bilder(event: "${route.params.ev}", jahr: ${route.params.jahr}) {
jahr
bild
}
}
`));
},
data() {
return {
bild: parseInt(<string>this.$route.params.bild),
ev: this.$route.params.ev,
jahr: this.$route.params.jahr,
bild: parseInt(<string>route.params.i),
ev: route.params.ev,
jahr: route.params.jahr,
RitzenbergenLib: RitzenbergenLib.RitzenbergenLib,
username: "",
kommentar: "",
reloader: false
reloader: false,
bilder: [],
};
},
asyncComputed: {
kommentare: {
get() {
},
default: null,
watch: ["bild", "ev", "jahr","reloader"],
},
bilder: {
get(){
// erwartete Rückgabe: ["/erntefest/2011/pi01.jpg"]
return $gql.request(`
{
bilder(event: "${route.params.event}", jahr: ${route.params.year})
}
`).then(()=>{
});
},
default: [],
watch: []
}
},
methods: {
getKommentare(){
const url = new URL(
RitzenbergenLib.RitzenbergenLib.api(
"/galerie/get_kommentare.php"
@@ -34,34 +77,8 @@ export default {
return fetch(url, {
method: "GET",
}).then((response) => response.json());
},
default: null,
watch: ["bild", "ev", "jahr","reloader"],
},
},
computed: {
bilder() {
let result: any[] = [];
$.ajax(
RitzenbergenLib.RitzenbergenLib.api("/galerie/get_bilder.php"),
{
async: false,
success(data: string) {
result = JSON.parse(data);
},
method: "GET",
data: {
ev: this.ev,
jahr: this.jahr,
},
}
);
return result;
},
},
methods: {
kommentarsubmit() {
const url = new URL(
RitzenbergenLib.RitzenbergenLib.api(
@@ -153,7 +170,7 @@ export default {
<MyFooter></MyFooter>
</template>
<style scoped lang="scss">
@import "../assets/bildschau/style.sass";
@import "../../../../assets/bildschau/style.sass";
.roboto-thin {
font-family: "Roboto", sans-serif;

View File

@@ -1,83 +1,76 @@
<script lang="ts">
import { RouterLink } from "vue-router";
import Navbar from "../components/Navbar.vue";
import RitzenbergenLib from "../ritzenbergenlib";
import Footer from "../components/MyFooter.vue";
import $ from "jquery";
<script lang="ts" setup>
import Navbar from "../../../components/Navbar.vue";
import Footer from "../../../components/MyFooter.vue";
import type { JahrMitBild } from "~/dto/galerie.dto";
export default {
data() {
return {
ev: this.$route.params.ev,
jahr: this.$route.params.jahr,
RitzenbergenLib: RitzenbergenLib.RitzenbergenLib,
};
},
computed: {
bilder() {
let result: any[] = [];
const route=useRoute();
const {event, year} = route.params;
function capitalizeFirstLetter(str: string){
if (str.length === 0) return str;
return str[0].toUpperCase() + str.slice(1);
$.ajax(RitzenbergenLib.RitzenbergenLib.api("/galerie/get_bilder.php"),{
async: false,
success(data: string) {
result=JSON.parse(data);
},
method: "GET",
data: {
ev: this.ev,
jahr: this.jahr
}
});
const {$gql} = useNuxtApp();
const bilder: string[]=(await $gql.request<{bilder:JahrMitBild[]}>(`
{
bilder(event: "${event}", jahr: ${year}) {
jahr
bild
}
}
`)).bilder[0].bild;
function toTable<T>(input: T[], columns: number = 5): T[][] {
if (columns <= 0) {
throw new Error("columns must be > 0");
}
const result: T[][] = [];
for (let i = 0; i < input.length; i += columns) {
const row = input.slice(i, i + columns);
result.push(row);
}
return result;
},
bildersplitted() {
let result: any[] = [];
this.bilder.forEach((element, i) => {
if (i % 5 == 0) {
result.push([]);
}
result[result.length - 1].push(element);
});
return result;
},
einereihe() {
return this.bilder.length <= 5;
},
},
components: {
RouterLink,
Navbar,
Footer,
},
methods: {
capitalizeFirstLetter(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
},
},
};
function getImg(filename){
return 'http://localhost:3000/api/galerie/bild/'+event+'/'+year+'/'+filename;
}
const bildersplitted=toTable<string>(bilder);
console.log(bildersplitted);;
</script>
<template>
<Navbar />
<section class="galerie-section">
<div class="galerie-container">
<h2>{{ capitalizeFirstLetter(ev) }} {{ jahr }}</h2>
<h2>{{ capitalizeFirstLetter(<string>event) }} {{ year }}</h2>
Vorschaubilder <br />
{{ bilder.length }} Bilder
<table>
<tbody>
<tr v-for="row, i in bildersplitted">
<td v-for="column, j in row">
<RouterLink :to="jahr+'/'+(i*5+j).toString()"
><img :src="RitzenbergenLib.get_img(column)" alt="Vorschaubild"
/></RouterLink>
<NuxtLink :to="'/bildschau/'+event+'/'+year+'/'+(i*5+j)"
><img :src="getImg(column)" alt="Vorschaubild"
/></NuxtLink>
</td>
</tr>
</tbody>
</table>
</div>
</section>
<div class="platzhalter" v-if="einereihe"></div>
<div class="platzhalter" v-if="bilder.length<=5"></div> <!-- Eine Reihe -->
<Footer></Footer>
</template>
<style scoped>

View File

@@ -6,10 +6,9 @@ import Uebersicht from "../components/bulitipp/Uebersicht.vue";
import Rangliste from "../components/bulitipp/Rangliste.vue";
import Paarungsergebnisse from "../components/bulitipp/Paarungsergebnisse.vue";
import Tabelle from "../components/bulitipp/Tabelle.vue";
import RitzenbergenLib from "../ritzenbergenlib.ts";
import SpieltagSumme from "../ritzenbergenlib.ts";
import RitzenbergenLib from "../ritzenbergenlib";
import SpieltagSumme from "../ritzenbergenlib";
import Loading from "../components/bulitipp/Loading.vue";
import $ from "jquery";
import Tippen from "../components/bulitipp/Tippen.vue";
import TippenEinloggen from "../components/bulitipp/TippenEinloggen.vue";

131
app/pages/galerie.vue Normal file
View File

@@ -0,0 +1,131 @@
<script lang="ts" setup>
import Navbar from "../components/Navbar.vue";
import Embla from "../components/Embla.vue";
import MyFooter from "../components/MyFooter.vue";
const { $gql } = useNuxtApp();
function mapperSrc(event:string, jahr:number){
return "http://localhost:3000/api/galerie/randomimage/"+event+"/"+jahr;
}
function mapperLink(event:string, jahr:number){
return "/bildvorschau/"+event+"/"+jahr;
}
const events = await $gql.request<{
erntefest: Array<{jahr:number}>,
osterfeuer: Array<{jahr:number}>,
fussball: Array<{jahr:number}>,
doppelkopf: Array<{jahr:number}>
}>(`
{
erntefest: bilder(event: "erntefest") {
jahr
}
osterfeuer: bilder(event: "osterfeuer") {
jahr
}
doppelkopf: bilder(event: "doppelkopf") {
jahr
}
fussball: bilder(event: "fussball") {
jahr
}
}
`);
const mappedEvents=[
{
"title":"Erntefest",
"src": events.erntefest.map((event)=>mapperSrc("erntefest",event.jahr)),
"links": events.erntefest.map((event)=>mapperLink("erntefest",event.jahr)),
"id":"erntefest",
"jahre": events.erntefest.map((event)=>event.jahr)
},
{
"title":"Osterfeuer",
"src": events.osterfeuer.map((event)=>mapperSrc("osterfeuer",event.jahr)),
"links": events.osterfeuer.map((event)=>mapperLink("osterfeuer",event.jahr)),
"id":"osterfeuer",
"jahre": events.osterfeuer.map((ev)=>ev.jahr),
},
{
"title":"Preisdoppelkopf",
"src": events.doppelkopf.map((event)=>mapperSrc("doppelkopf",event.jahr)),
"links": events.doppelkopf.map((event)=>mapperLink("doppelkopf",event.jahr)),
"id":"doppelkopf",
"jahre": events.doppelkopf.map((ev)=>ev.jahr),
},
{
"title":"Fußballturniere",
"src": events.fussball.map((event)=>mapperSrc("fussball",event.jahr)),
"links": events.fussball.map((event)=>mapperLink("fussball",event.jahr)),
"id":"fussball",
"jahre": events.fussball.map((ev)=>ev.jahr),
},
]
</script>
<template>
<Navbar :links="[
{ title: 'Erntefest', link: '/galerie/#erntefest' },
{ title: 'Osterfeuer', link: '/galerie/#osterfeuer' },
{ title: 'Doppelkopf', link: '/galerie/#doppelkopf' },
{ title: 'Fußballturniere', link: '/galerie/#fussball' },
]" />
<br />
<br />
<br />
<br />
<br />
<br />
<section class="article12 cid-u6k7q0yKNv" id="about-us-12-u6k7q0yKNv">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-12 col-lg-10">
<h3 class="mbr-section-title mbr-fonts-style mb-4 mt-0 display-2">
<strong>Willkommen in der Galerie</strong>
</h3>
<p class="mbr-text mbr-fonts-style display-7">
In unserem Fotoalbum findest du chronisch geordnete Bilder
verschiedener Veranstaltungen aus den letzten Jahrzehnten. Einfach
auf ein Bild mit einer Jahreszahl raufklicken.
</p>
</div>
</div>
</div>
</section>
<br /><br />
<section
class="slider4 mbr-embla cid-u6k7q0yLdW"
v-for="event in mappedEvents"
:id="event.id"
>
<div class="container-fluid">
<div class="row">
<h4
class="mbr-section-title mbr-fonts-style align-center mb-0 display-2"
>
<strong>{{ event.title }}</strong>
</h4>
<div class="col-12">
<br />
<!-- src: Link zum Randomimage, links: Link zur Bildschau -->
<Embla :src="event.src" :links="event.links" :jahre="event.jahre" />
</div>
</div>
</div>
<br /><br /><br />
</section>
<h1 v-if="mappedEvents.length==0">Keine Internetverbindung!</h1>
<br /><br /><br />
<MyFooter />
</template>
<style scoped></style>

View File

@@ -1,10 +1,8 @@
<script lang="ts" setup>
import Navbar from "../components/Navbar.vue";
import Modal from "../components/Modal.vue";
import Embla from "../components/Embla.vue";
import Umgebung from "../components/startseite/Umgebung.vue";
import MyFooter from "../components/MyFooter.vue"; // Geändert von Footer auf MyFooter
import RitzenbergenLib from "../ritzenbergenlib";
import MyFooter from "../components/MyFooter.vue";
import WillkommenText from "../components/startseite/WillkommenText.vue";
import Bilderbuch from "../components/startseite/Bilderbuch.vue";
import Forms from "../components/startseite/Forms.vue";
@@ -13,35 +11,7 @@ import Willkommen from "../components/startseite/Willkommen.vue";
import { ref } from "vue";
const images=ref([]);
async function loadImage(path: string) {
try{
const response = await fetch(RitzenbergenLib.RitzenbergenLib.api(path), {
headers: {
"Accept":"image/png"
}
});
if(!response.ok) return false;
const blob = await response.blob();
return URL.createObjectURL(blob);
}catch(e){
console.warn(e);
}
}
// loadImage("randomimage.php?path=/doppelkopf&recursive=1&tn=1&color=white&text=Doppelkopf&size=3").then((url)=>{
// images.value[0]=url;
// });
// loadImage("randomimage.php?path=/erntefest&recursive=1&tn=1&color=white&text=Erntefest&size=3").then((url)=>{
// images.value[1]=url;
// });
// loadImage("randomimage.php?path=/fussball&recursive=1&tn=1&color=white&text=Fußballturnier&size=3").then((url)=>{
// images.value[2]=url;
// });
// loadImage("randomimage.php?path=/osterfeuer&recursive=1&tn=1&color=white&text=Osterfeuer&size=3").then((url)=>{
// images.value[3]=url;
// });
const images=ref(["http://localhost:3000/api/galerie/randomimage/erntefest","http://localhost:3000/api/galerie/randomimage/osterfeuer","http://localhost:3000/api/galerie/randomimage/doppelkopf","http://localhost:3000/api/galerie/randomimage/fussball","http://localhost:3000/api/galerie/bild/andere/0/hauptfoto.jpg"]);
</script>
<template>
@@ -55,24 +25,26 @@ async function loadImage(path: string) {
<Forms/>
<!-- <Bilderbuch/> -->
<Bilderbuch/>
<!-- <section class="slider4 mbr-embla cid-u6k7q0yLdW" id="gallery-13-u6k7q0yLdW" v-if="images[0]">
<section class="slider4 mbr-embla cid-u6k7q0yLdW" id="gallery-13-u6k7q0yLdW" v-if="images[0]">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<Embla :src="images"
:font-size="49"
:links='[
"/galerie/erntefest",
"/galerie/osterfeuer",
"/galerie/doppelkopf",
"/galerie/fussball",
"/galerie/#erntefest",
"/galerie/#osterfeuer",
"/galerie/#doppelkopf",
"/galerie/#fussball",
""
]'
:jahre="['Erntefest','Osterfeuer','Doppelkopf', 'Fußball','']"
/>
</div>
</div>
@@ -86,10 +58,10 @@ async function loadImage(path: string) {
<br>
<br> -->
<br>
<Umgebung ref="umgebung" />
<Umgebung ref="umgebung" id="umgebung" />
<MyFooter ref="footer" />
</template>

16
app/plugins/graphql.ts Normal file
View File

@@ -0,0 +1,16 @@
import { GraphQLClient } from "graphql-request";
export default defineNuxtPlugin(() => {
const config=useRuntimeConfig();
const endpoint = import.meta.server
? config.graphqlEndpoint
: config.public.graphqlEndpoint
const client = new GraphQLClient(endpoint);
return {
provide: {
gql: client
}
}
});

15
app/plugins/my-fetch.ts Normal file
View File

@@ -0,0 +1,15 @@
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
const myfetch = $fetch.create({
baseURL: import.meta.server ? config.apiBase : config.public.apiBase,
onRequest({ options }) {
},
})
return {
provide: {
myfetch: myfetch,
},
}
})

View File

@@ -1,8 +1,22 @@
import { GraphQLClient } from "graphql-request";
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: '2025-07-15',
devtools: { enabled: true },
modules: [],
ssr: false,
modules: ["@formkit/nuxt"],
devServer: {
port: 1420
},
runtimeConfig: {
graphqlEndpoint: process.env.GRAPHQL_ENDPOINT_INTERNAL || "http://localhost:3000/graphql",
apiBase: process.env.API_BASE_INTERNAL || "http://localhost:3000/api",
public: {
graphqlEndpoint: process.env.GRAPHQL_ENDPOINT_PUBLIC || "http://backend:3000/graphql",
apiBase: process.env.API_BASE_PUBLIC || "http://backend:3000/api"
}
},
css: [
'~/assets/mobirise/css/additional.scss',

898
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,16 +10,31 @@
"postinstall": "nuxt prepare"
},
"dependencies": {
"@formkit/nuxt": "^2.0.0",
"@formkit/themes": "^2.0.0",
"@formkit/vue": "^2.0.0",
"@nuxtjs/tailwindcss": "^6.14.0",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2",
"bcryptjs": "^3.0.3",
"crypto-js": "^4.2.0",
"embla-carousel-vue": "^8.6.0",
"graphql-request": "^7.4.0",
"jarallax": "^3.0.0",
"katex": "^0.16.45",
"katex": "^0.17.0",
"moment": "^2.30.1",
"nuxt": "^4.4.2",
"process": "^0.11.10",
"sloc": "^0.3.2",
"striptags": "^3.2.0",
"vscode-langservers-extracted": "^4.10.0",
"vue": "^3.5.32",
"vue-renderer-markdown": "^0.0.62",
"vue-router": "^5.0.4"
},
"devDependencies": {
"@tauri-apps/cli": "^2.10.1",
"@types/markdown-it": "^14.1.2",
"sass-embedded": "^1.99.0"
}
}

1343
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load Diff