Compare commits

...

10 Commits

Author SHA1 Message Date
a3fff5e4a1 Update submodules 2026-03-20 14:10:37 +01:00
d069dbb2d2 Fix Form Display 2026-03-20 12:11:45 +01:00
5d4f459d09 Updated DTO 2026-03-20 11:56:24 +01:00
R40fendt
8c29559fc9 Started migrating Forms 2026-02-02 12:18:27 +01:00
9e34a12e23 Updated Events to GraphQL 2026-01-30 14:34:44 +01:00
6beffcb734 Added dto submodule (again...) 2026-01-30 11:46:35 +01:00
R40fendt
269bf54c9d Added dto submodule 2026-01-29 19:40:47 +01:00
R40fendt
c1d8638e5f Removed dto submodule 2026-01-29 19:39:37 +01:00
R40fendt
cbfd572141 Added DTO Submodule 2026-01-28 19:24:26 +01:00
R40fendt
2b23d501b9 Added Dev Dockerfile 2026-01-28 19:15:35 +01:00
9 changed files with 136 additions and 297 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "src/dto"]
path = src/dto
url = git@github.com:R40fendt/ritzenbergen-dto.git

17
Dockerfile.dev Normal file
View File

@@ -0,0 +1,17 @@
FROM node:20-alpine
WORKDIR /app
# nur package-Dateien zuerst, damit Docker-Cache greift
COPY package*.json ./
RUN npm install
# Rest des Codes
COPY . .
# Vite Dev-Server
EXPOSE 1420
CMD ["npm", "run", "dev", "--", "--host"]

View File

@@ -2,7 +2,6 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/png" href="RitzenbergenOrtsschild.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Willkommen auf ritzenbergen.de</title> <title>Willkommen auf ritzenbergen.de</title>
@@ -18,8 +17,7 @@
</noscript> </noscript>
<link rel="stylesheet" <link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" /> href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
<script src="http://192.168.188.38/Jonas/ritzenbergenapi/addhit.php"> <!-- <script src="http://192.168.188.38/Jonas/ritzenbergenapi/addhit.php"></script> -->
</script>
</head> </head>

View File

@@ -19,6 +19,7 @@
"bcryptjs": "^3.0.3", "bcryptjs": "^3.0.3",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"embla-carousel-vue": "^8.6.0", "embla-carousel-vue": "^8.6.0",
"graphql-request": "^7.4.0",
"jarallax": "^2.2.1", "jarallax": "^2.2.1",
"jquery": "^3.7.1", "jquery": "^3.7.1",
"katex": "^0.16.27", "katex": "^0.16.27",

View File

@@ -1,126 +1,58 @@
<script lang="ts"> <script lang="ts" setup>
import RitzenbergenLib from "../../ritzenbergenlib.ts"; import RitzenbergenLib from "../../ritzenbergenlib";
import striptags from "striptags";
import moment, { Moment } from "moment";
import Modal from "../Modal.vue"; import Modal from "../Modal.vue";
import $ from "jquery";
import MarkdownRender from "vue-renderer-markdown"; import MarkdownRender from "vue-renderer-markdown";
import "katex/dist/katex.min.css"; import "katex/dist/katex.min.css";
import Forms from "./Forms.vue"; import Forms from "./Forms.vue";
import { ref } from "vue";
import { EventType, MyEvent } from "../../dto/event.dto.js";
export default { const initdone=ref(false);
data() {
const openedModals: number[] = [];
return {
openedModals,
modaltypes: ["markdown", "html"],
RitzenbergenLib: RitzenbergenLib.RitzenbergenLib,
};
},
computed: {
events() {
let result: Array<any> = [];
$.ajax(RitzenbergenLib.RitzenbergenLib.api("get_events.php"), { const events = ref<MyEvent[]>([]);
crossDomain: true,
async: false, const openedModals=ref<number[]>([]);
success: function (data: string) {
result = JSON.parse(data); const modaltypes=[EventType.html,EventType.markdown];
},
error: function () { async function init() {
result=false;
} events.value=(await RitzenbergenLib.graphqlClient.request<{events: MyEvent[]}>
}); (`{
return result; events {
/* id
Beispiel-Event-Array: eventname
[ type
{ minitext
id: 0, datum
eventname: "Eventname", content
datum: "2009-04-06", link
type: "markdown", foto
content: "# Test", formular
link: undefined, }
foto: "erntefest/2011/pic08.jpg", }`)).events;
minitext: "", console.log(events.value);
formular: 1
},
{ }
id: 1,
eventname: "Link", init().then(()=>{
datum: "2009-04-06",
type: "link", initdone.value=true;
content: "<h1>Testlink</h1>",
link: "#/test", });
foto: "erntefest/2011/pic08.jpg",
minitext: "" function format_date(date: string){
}, return new Date(date).toDateString();
}, }
{
id: 2, function vorschautext(str: string){
eventname: "Download-Link", return str;
datum: "2009-04-06", }
type: "dlink",
content: "<h1>Testlink2</h1>",
link: "/",
foto: "erntefest/2011/pic08.jpg",
minitext: ""
},
},
{
id: 3,
eventname: "Fotos endlich online!",
datum: "2009-04-06",
type: "fotos",
content: "Fotos vom Erntefest 2011",
link: "erntefest/2011",
foto: "erntefest/2011/pic08.jpg",
minitext: ""
},
},
{
id: 4,
eventname: "Eventname",
datum: "2009-04-06",
type: "html",
content: "<h1>Test2</h1>",
link: undefined,
foto: "erntefest/2011/pic08.jpg",
minitext: ""
},
},
];*/
},
},
methods: {
vorschautext(content: string) {
const stripped = striptags(content);
const vorschaulen = 30;
if (stripped.length > vorschaulen) {
return stripped.substring(0, vorschaulen) + "...";
} else {
return stripped;
}
},
format_date(date: string) {
const mymoment: Moment = moment(date);
return mymoment.format("DD.MM.YYYY");
},
galerie(content: string) {
this.$router.push({ path: "/bild/" + content });
},
},
components: {
Modal,
MarkdownRender,
Forms
},
};
</script> </script>
<template> <template>
<section class="features03 cid-u6k7q0xyDG" id="news-1-u6k7q0xyDG"> <section class="features03 cid-u6k7q0xyDG" id="news-1-u6k7q0xyDG" v-if="initdone">
<div class="container-fluid"> <div class="container-fluid">
<div class="row justify-content-center mb-5"> <div class="row justify-content-center mb-5">
<div class="col-12 content-head"> <div class="col-12 content-head">
@@ -159,7 +91,7 @@ export default {
" "
> >
<MarkdownRender <MarkdownRender
v-if="event.type == 'markdown'" v-if="event.type == EventType.markdown"
:content="event.content" :content="event.content"
/> />
<div v-else v-html="event.content"></div> <div v-else v-html="event.content"></div>
@@ -168,7 +100,7 @@ export default {
<div class="item-wrapper"> <div class="item-wrapper">
<div class="item-img mb-3"> <div class="item-img mb-3">
<img :src="RitzenbergenLib.get_img(event.foto)" /> <img :src="RitzenbergenLib.RitzenbergenLib.get_img(event.foto)" />
</div> </div>
<div class="item-content align-left"> <div class="item-content align-left">
<h6 <h6

View File

@@ -1,11 +1,41 @@
<script lang="ts" setup> <script lang="ts" setup>
import RitzenbergenLib from "../../ritzenbergenlib.ts"; import RitzenbergenLib from "../../ritzenbergenlib";
import FormResults from "../FormResults.vue"; import FormResults from "../FormResults.vue";
import { ref, defineProps } from "vue"; import { ref } from "vue";
import Modal from "../Modal.vue"; import Modal from "../Modal.vue";
import { Formular } from "../../dto/formular.dto";
async function init() {
forms.value=await RitzenbergenLib.graphqlClient.request<{formulare: Formular[] }>(`
{
formulare {
id
name
minitext
ispublic
fields {
id
name
displayname
displayvalue
placeholder
type
title
required
maxlength
min
max
checked
value
}
}
}
`
).then(data=>data.formulare);
console.log(forms.value);
}
const Formular = RitzenbergenLib.Formular;
const Field = RitzenbergenLib.Field;
const forms = ref([] as Formular[]); const forms = ref([] as Formular[]);
const props=defineProps({ const props=defineProps({
@@ -16,26 +46,19 @@ const props=defineProps({
} }
}); });
init();
Formular.getForms().then((f) => {
forms.value = f;
});
function submit($event: Event) { function submit($event: Event) {
const url = new URL( const url = new URL(
RitzenbergenLib.RitzenbergenLib.api("/formulare/submit.php") RitzenbergenLib.RitzenbergenLib.api("/formulare/submit.php")
); );
const formData = new FormData($event.target); const formData = new FormData(<HTMLFormElement>$event.target);
fetch(url.toString(), { fetch(url.toString(), {
method: "POST", method: "POST",
body: formData body: formData
}).then(() => { }).then(() => {
forms.value = Formular.getForms().then((f) => { init();
forms.value = f; values.value={};
});
values.value={};
}); });
} }
@@ -56,7 +79,7 @@ const values=ref({});
</Modal> </Modal>
<section ref="anmeldeformular" id="anmeldeformular"> <section ref="anmeldeformular" id="anmeldeformular">
<section class="form5 cid-u6k7q0BfGa"> <section class="form5 cid-u6k7q0BfGa">
<div class="container" v-for="(form, i) in forms.filter((form)=>form.id==props.formid||props.id==null)" :key="form"> <div class="container" v-for="(form, i) in forms" :key="i">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-12 content-head"> <div class="col-12 content-head">
<div class="mbr-section-head mb-5"> <div class="mbr-section-head mb-5">
@@ -86,7 +109,7 @@ const values=ref({});
:data-i="i" :data-i="i"
@submit.prevent="submit" @submit.prevent="submit"
> >
<div v-for="(field, j) in form.fields" :key="field"> <div v-for="(field, j) in form.fields" :key="j">
<label <label
v-if="field.placeholder == null" v-if="field.placeholder == null"
:for="'field-' + field.id" :for="'field-' + field.id"

1
src/dto Submodule

Submodule src/dto added at 12938c8125

View File

@@ -1,5 +1,11 @@
import $ from "jquery"; import $ from "jquery";
import { ref } from "vue"; import { GraphQLClient } from 'graphql-request';
const graphqlClient = new GraphQLClient('http://localhost:3000/graphql', {
headers: {
// optional: Authorization: 'Bearer TOKEN'
},
});
const apiBaseUrl = import.meta.env.VITE_BACKEND_URL; const apiBaseUrl = import.meta.env.VITE_BACKEND_URL;
@@ -155,148 +161,7 @@ class Spiel {
}); });
} }
} }
class Formular {
public id: number;
public name: string;
public minitext: string;
public ispublic: boolean;
public multiple: boolean;
public fields=ref<Field[]>([]);
constructor(
id: number,
name: string,
minitext: string,
ispublic: boolean,
multiple: boolean
) {
this.id = id;
this.name = name;
this.minitext = minitext;
this.ispublic = ispublic;
this.multiple = multiple;
this.getFields().then((fields)=>this.fields.value=fields);
}
public static async getForms(): Promise<Formular[]> {
let forms: Formular[] = [];
try{
forms = await fetch(
RitzenbergenLib.api("/formulare/get_formulare.php"),
{
method: "GET",
}
)
.then((response) => response.json())
.then((result) =>
result.map(
(el: any) =>
new Formular(
el.id,
el.name,
el.minitext,
el.public==null?null:(el.public==1?true:false),
el.multiple==null?null:(el.multiple==1?true:false)
)
)
);
} catch(e){
console.warn(e);
}
return forms;
}
private async getFields(): Promise<Field[]> {
return fetch(
RitzenbergenLib.api(
"/formulare/get_fields.php?formular=" + this.id
),
{
method: "GET",
}
)
.then((response) => response.json())
.then((result) =>
result.map(
(el: any) =>
new Field(el.formular, el.name, el.value, el.type, {
id: el.id,
displayname: el.displayname,
displayvalue: el.displayvalue,
placeholder: el.placeholder,
title: el.title,
required: el.required==null?null:(el.required==1?true:false),
maxlength: el.maxlength,
min: el.min,
max: el.max,
multiple: el.multiple==null?null:(el.multiple==1?true:false),
checked: el.checked==null?null:(el.checked==1?true:false),
})
)
);
}
}
type FieldType =
| "text"
| "password"
| "number"
| "range"
| "date"
| "time"
| "checkbox"
| "radio"
| "color"
| "submit"
| "textarea";
class Field {
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;
constructor(
formular: number,
name: string,
value: string,
type: FieldType,
options?: {
id?: number;
displayname?: string | null;
displayvalue?: string | null;
placeholder?: string | null;
title?: string | null;
required?: boolean;
maxlength?: number | null;
min?: number | null;
max?: number | null;
multiple?: boolean | null;
checked?: boolean | null;
}
) {
this.id = options?.id;
this.formular = formular;
this.name = name;
this.displayname = options?.displayname ?? null;
this.value = value;
this.displayvalue = options?.displayvalue ?? null;
this.placeholder = options?.placeholder ?? null;
this.type = type;
this.title = options?.title ?? null;
this.required = options?.required ?? false;
this.maxlength = options?.maxlength ?? null;
this.min = options?.min ?? null;
this.max = options?.max ?? null;
this.checked = options?.checked ?? null;
}
}
export default { export default {
RitzenbergenLib, RitzenbergenLib,
@@ -306,6 +171,5 @@ export default {
Ergebnis, Ergebnis,
Tipp, Tipp,
Spiel, Spiel,
Formular, graphqlClient
Field,
}; };

View File

@@ -4,7 +4,7 @@ import Modal from "../components/Modal.vue";
import Embla from "../components/Embla.vue"; import Embla from "../components/Embla.vue";
import Umgebung from "../components/startseite/Umgebung.vue"; import Umgebung from "../components/startseite/Umgebung.vue";
import MyFooter from "../components/MyFooter.vue"; // Geändert von Footer auf MyFooter import MyFooter from "../components/MyFooter.vue"; // Geändert von Footer auf MyFooter
import RitzenbergenLib from "../ritzenbergenlib.ts"; import RitzenbergenLib from "../ritzenbergenlib";
import WillkommenText from "../components/startseite/WillkommenText.vue"; import WillkommenText from "../components/startseite/WillkommenText.vue";
import Bilderbuch from "../components/startseite/Bilderbuch.vue"; import Bilderbuch from "../components/startseite/Bilderbuch.vue";
import Forms from "../components/startseite/Forms.vue"; import Forms from "../components/startseite/Forms.vue";
@@ -29,18 +29,18 @@ async function loadImage(path: string) {
} }
} }
loadImage("randomimage.php?path=/doppelkopf&recursive=1&tn=1&color=white&text=Doppelkopf&size=3").then((url)=>{ // loadImage("randomimage.php?path=/doppelkopf&recursive=1&tn=1&color=white&text=Doppelkopf&size=3").then((url)=>{
images.value[0]=url; // images.value[0]=url;
}); // });
loadImage("randomimage.php?path=/erntefest&recursive=1&tn=1&color=white&text=Erntefest&size=3").then((url)=>{ // loadImage("randomimage.php?path=/erntefest&recursive=1&tn=1&color=white&text=Erntefest&size=3").then((url)=>{
images.value[1]=url; // images.value[1]=url;
}); // });
loadImage("randomimage.php?path=/fussball&recursive=1&tn=1&color=white&text=Fußballturnier&size=3").then((url)=>{ // loadImage("randomimage.php?path=/fussball&recursive=1&tn=1&color=white&text=Fußballturnier&size=3").then((url)=>{
images.value[2]=url; // images.value[2]=url;
}); // });
loadImage("randomimage.php?path=/osterfeuer&recursive=1&tn=1&color=white&text=Osterfeuer&size=3").then((url)=>{ // loadImage("randomimage.php?path=/osterfeuer&recursive=1&tn=1&color=white&text=Osterfeuer&size=3").then((url)=>{
images.value[3]=url; // images.value[3]=url;
}); // });
</script> </script>
@@ -55,11 +55,11 @@ loadImage("randomimage.php?path=/osterfeuer&recursive=1&tn=1&color=white&text=Os
<Forms/> <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="container-fluid">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
@@ -86,7 +86,7 @@ loadImage("randomimage.php?path=/osterfeuer&recursive=1&tn=1&color=white&text=Os
<br> <br>
<br> <br> -->
<Umgebung ref="umgebung" /> <Umgebung ref="umgebung" />