Formulare im Admin Panel, Event Formular-Fremdschlüssel-Spalte hinzugefügt
This commit is contained in:
@@ -10,3 +10,5 @@ Bei der Migration beachten:
|
|||||||
- Neue Formulartabelle
|
- Neue Formulartabelle
|
||||||
- .env.production anpassen
|
- .env.production anpassen
|
||||||
- Salt ändern (secret.php in der API)
|
- Salt ändern (secret.php in der API)
|
||||||
|
- Event-Tabelle updaten (neue Formular-Spalte)
|
||||||
|
- Admin-Tabellen hinzufügen
|
||||||
|
|||||||
@@ -1,31 +1,54 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import RitzenbergenLib from "../ritzenbergenlib.ts";
|
import RitzenbergenLib from "../ritzenbergenlib.ts";
|
||||||
import { defineProps, ref } from "vue";
|
import { defineProps, ref, watchEffect } from "vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
form: {
|
form: {
|
||||||
type: RitzenbergenLib.Formular,
|
type: RitzenbergenLib.Formular,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
token: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ""
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = props.form;
|
const form = ref(props.form);
|
||||||
|
|
||||||
let results = ref([]);
|
|
||||||
fetch(
|
const results = ref([]);
|
||||||
RitzenbergenLib.RitzenbergenLib.api(
|
const myfields = ref([]);
|
||||||
"/formulare/get_results.php?id=" + form.id
|
watchEffect(() => {
|
||||||
|
fetch(
|
||||||
|
RitzenbergenLib.RitzenbergenLib.api(
|
||||||
|
"/formulare/get_results.php?id=" + form.value.id
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
.then((res) => res.json())
|
||||||
.then((res) => res.json())
|
.then((data) => {
|
||||||
.then((data) => {
|
if(data.error){
|
||||||
results.value = data;
|
// Admin Rechte nötig
|
||||||
|
fetch(RitzenbergenLib.RitzenbergenLib.api("/admin/formulare/ergebnisse.php?formular="+form.value.id),{
|
||||||
|
headers: {
|
||||||
|
"Authorization":props.token
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((res)=>res.json())
|
||||||
|
.then((data)=>{
|
||||||
|
results.value=data;
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
results.value = data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
myfields.value = [];
|
||||||
|
form.value.fields.forEach((field: RitzenbergenLib.Field) => {
|
||||||
|
if (myfields.value.find((el) => el.name == field.name) == undefined) {
|
||||||
|
myfields.value.push(field);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const myfields = [];
|
|
||||||
form.fields.forEach((field: RitzenbergenLib.Field) => {
|
|
||||||
if (myfields.find((el) => el.name == field.name) == undefined) {
|
|
||||||
myfields.push(field);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function prettyResult(result: any) {
|
function prettyResult(result: any) {
|
||||||
@@ -36,7 +59,7 @@ function prettyResult(result: any) {
|
|||||||
let tempresult = result.value;
|
let tempresult = result.value;
|
||||||
let cancel = false;
|
let cancel = false;
|
||||||
tempresult = tempresult.map((el) => {
|
tempresult = tempresult.map((el) => {
|
||||||
let field = form.fields.find((f) => f.value == el);
|
let field = form.value.fields.find((f) => f.value == el);
|
||||||
if (field == undefined) {
|
if (field == undefined) {
|
||||||
cancel = true;
|
cancel = true;
|
||||||
return el;
|
return el;
|
||||||
@@ -48,7 +71,7 @@ function prettyResult(result: any) {
|
|||||||
return result.value.join(", ");
|
return result.value.join(", ");
|
||||||
}
|
}
|
||||||
if (result.type == "radio") {
|
if (result.type == "radio") {
|
||||||
let field = form.fields.find((f) => f.value == result.value);
|
let field = form.value.fields.find((f) => f.value == result.value);
|
||||||
if (field != undefined) {
|
if (field != undefined) {
|
||||||
return field.displayvalue ?? result.value;
|
return field.displayvalue ?? result.value;
|
||||||
}
|
}
|
||||||
@@ -58,7 +81,9 @@ function prettyResult(result: any) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<h1>Ergebnisse {{ form.name }}</h1>
|
<h1>Ergebnisse {{ form.name }}</h1>
|
||||||
|
<div class="main">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -70,8 +95,23 @@ function prettyResult(result: any) {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="(result, ri) in results" :key="ri">
|
<tr v-for="(result, ri) in results" :key="ri">
|
||||||
<td v-for="(field, fi) in myfields" :key="fi" :style="field.type=='color'?{ 'backgroundColor': result.data.find((el) => el.name == field.name).value, width: '10px', height: '10px' }:{}">
|
<td
|
||||||
<span v-if="field.type!='color'">{{
|
v-if="result.data != undefined"
|
||||||
|
v-for="(field, fi) in myfields"
|
||||||
|
:key="fi"
|
||||||
|
:style="
|
||||||
|
field.type == 'color'
|
||||||
|
? {
|
||||||
|
backgroundColor: result.data.find(
|
||||||
|
(el) => el.name == field.name
|
||||||
|
).value,
|
||||||
|
width: '10px',
|
||||||
|
height: '10px',
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span v-if="field.type != 'color'">{{
|
||||||
prettyResult(
|
prettyResult(
|
||||||
result.data.find(
|
result.data.find(
|
||||||
(el) =>
|
(el) =>
|
||||||
@@ -80,17 +120,28 @@ function prettyResult(result: any) {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}}</span>
|
}}</span>
|
||||||
<span v-else ></span>
|
<span v-else></span>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ result.timestamp }}</td>
|
<td>{{ result.timestamp }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@import "../assets/css/bulitipp2.css";
|
@import "../assets/css/bulitipp2.css";
|
||||||
td {
|
td {
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
tbody, table, .main{
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
thead tr td {
|
||||||
|
background-color: #efefef;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default {
|
|||||||
<br />
|
<br />
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
<br /><br />
|
<RouterLink to="/adminpanel/login">Admin Login</RouterLink>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<button @click="aboutVisible=true" class="text-white btn-ueber openBtn">Über</button>
|
<button @click="aboutVisible=true" class="text-white btn-ueber openBtn">Über</button>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Modal from "../Modal.vue";
|
|||||||
import $ from "jquery";
|
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";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
@@ -27,7 +28,6 @@ export default {
|
|||||||
result = JSON.parse(data);
|
result = JSON.parse(data);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log(result);
|
|
||||||
return result;
|
return result;
|
||||||
/*
|
/*
|
||||||
Beispiel-Event-Array:
|
Beispiel-Event-Array:
|
||||||
@@ -40,7 +40,8 @@ export default {
|
|||||||
content: "# Test",
|
content: "# Test",
|
||||||
link: undefined,
|
link: undefined,
|
||||||
foto: "erntefest/2011/pic08.jpg",
|
foto: "erntefest/2011/pic08.jpg",
|
||||||
minitext: ""
|
minitext: "",
|
||||||
|
formular: 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -111,6 +112,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
MarkdownRender,
|
MarkdownRender,
|
||||||
|
Forms
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -158,6 +160,7 @@ export default {
|
|||||||
:content="event.content"
|
:content="event.content"
|
||||||
/>
|
/>
|
||||||
<div v-else v-html="event.content"></div>
|
<div v-else v-html="event.content"></div>
|
||||||
|
<Forms v-if="event.formular" :formid="event.formular"/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<div class="item-wrapper">
|
<div class="item-wrapper">
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import RitzenbergenLib from "../../ritzenbergenlib.ts";
|
import RitzenbergenLib from "../../ritzenbergenlib.ts";
|
||||||
import FormResults from "../FormResults.vue";
|
import FormResults from "../FormResults.vue";
|
||||||
import { ref } from "vue";
|
import { ref, defineProps } from "vue";
|
||||||
import Modal from "../Modal.vue";
|
import Modal from "../Modal.vue";
|
||||||
|
|
||||||
const Formular = RitzenbergenLib.Formular;
|
const Formular = RitzenbergenLib.Formular;
|
||||||
const Field = RitzenbergenLib.Field;
|
const Field = RitzenbergenLib.Field;
|
||||||
const forms = ref([] as Formular[]);
|
const forms = ref([] as Formular[]);
|
||||||
|
|
||||||
|
const props=defineProps({
|
||||||
|
formid: {
|
||||||
|
type: [Number, null],
|
||||||
|
required: false,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Formular.getForms().then((f) => {
|
Formular.getForms().then((f) => {
|
||||||
forms.value = f;
|
forms.value = f;
|
||||||
});
|
});
|
||||||
@@ -23,6 +34,8 @@ function submit($event: Event) {
|
|||||||
forms.value = Formular.getForms().then((f) => {
|
forms.value = Formular.getForms().then((f) => {
|
||||||
forms.value = f;
|
forms.value = f;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
values.value={};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,12 +51,12 @@ function openModal(form: Formular){
|
|||||||
const values=ref({});
|
const values=ref({});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<Modal v-show="modalOpened" @closemodal="modalOpened=false">
|
<Modal v-if="openedForm && openedForm.ispublic" v-show="modalOpened" @closemodal="modalOpened=false">
|
||||||
<FormResults v-if="openedForm" :form="openedForm"/>
|
<FormResults v-if="modalOpened" :form="openedForm"/>
|
||||||
</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" :key="i">
|
<div class="container" v-for="(form, i) in forms.filter((form)=>form.id==props.formid||props.id==null)" :key="form">
|
||||||
<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">
|
||||||
@@ -54,8 +67,8 @@ const values=ref({});
|
|||||||
</h3>
|
</h3>
|
||||||
<br />
|
<br />
|
||||||
<h5 style="text-align: center">
|
<h5 style="text-align: center">
|
||||||
<b @click="openModal(form)" class="fakelink">{{ form.minitext }}
|
<b @click="openModal(form)" class="fakelink" v-if="form.ispublic">{{ form.minitext }}
|
||||||
</b> <br />
|
</b> <b v-else>{{ form.minitext }}</b> <br />
|
||||||
</h5>
|
</h5>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +86,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="j">
|
<div v-for="(field, j) in form.fields" :key="field">
|
||||||
<label
|
<label
|
||||||
v-if="field.placeholder == null"
|
v-if="field.placeholder == null"
|
||||||
:for="'field-' + field.id"
|
:for="'field-' + field.id"
|
||||||
@@ -82,7 +95,7 @@ const values=ref({});
|
|||||||
field.displayvalue ?? field.displayname ?? field.name
|
field.displayvalue ?? field.displayname ?? field.name
|
||||||
}}:
|
}}:
|
||||||
<span v-if="field.type == 'range'"
|
<span v-if="field.type == 'range'"
|
||||||
><br />{{ values[field.name] }}</span
|
><br />{{ values[field.id] }}</span
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
<FormKit
|
<FormKit
|
||||||
@@ -98,7 +111,7 @@ const values=ref({});
|
|||||||
:checked="field.checked"
|
:checked="field.checked"
|
||||||
:title="field.title"
|
:title="field.title"
|
||||||
:value="field.value"
|
:value="field.value"
|
||||||
v-model="values[field.name]"
|
v-model="values[field.id]"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<textarea
|
<textarea
|
||||||
@@ -128,6 +141,10 @@ const values=ref({});
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -1,12 +1,26 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import AdminNavbar from "../../components/admin/AdminNavbar.vue";
|
import AdminNavbar from "../../components/admin/AdminNavbar.vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
const token = ref(route.params.token);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<AdminNavbar/>
|
<AdminNavbar />
|
||||||
<h1>Events</h1>
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<h1>Events</h1>
|
||||||
</template>
|
</template>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
h1{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ref } from "vue";
|
|||||||
import AdminNavbar from "../../components/admin/AdminNavbar.vue";
|
import AdminNavbar from "../../components/admin/AdminNavbar.vue";
|
||||||
import RitzenbergenLib from "../../ritzenbergenlib.ts";
|
import RitzenbergenLib from "../../ritzenbergenlib.ts";
|
||||||
import InputP from "../../components/admin/InputP.vue";
|
import InputP from "../../components/admin/InputP.vue";
|
||||||
|
import FormResults from "../../components/FormResults.vue";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
@@ -24,6 +25,23 @@ async function saveForm(form) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
async function deleteForm(form){
|
||||||
|
const url=new URL(RitzenbergenLib.RitzenbergenLib.api("/admin/formulare/deleteForm.php"));
|
||||||
|
url.searchParams.set("id",form.id);
|
||||||
|
return fetch(url,{
|
||||||
|
headers: {
|
||||||
|
"Authorization":"Bearer "+token.value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.ok)
|
||||||
|
RitzenbergenLib.Formular.getForms().then(
|
||||||
|
(result) => (formulare.value = result)
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
function filterType(type: string) {
|
function filterType(type: string) {
|
||||||
if (type in ["radio", "checkbox"]) return "text";
|
if (type in ["radio", "checkbox"]) return "text";
|
||||||
return type;
|
return type;
|
||||||
@@ -49,8 +67,10 @@ async function newForm() {
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
<h1>Formulare</h1>
|
<h1>Formulare</h1>
|
||||||
<div>
|
<div class="formeditor">
|
||||||
<form
|
<form
|
||||||
@submit.prevent="saveForm(form)"
|
@submit.prevent="saveForm(form)"
|
||||||
v-for="(form, i) in formulare"
|
v-for="(form, i) in formulare"
|
||||||
@@ -195,9 +215,14 @@ async function newForm() {
|
|||||||
<br />
|
<br />
|
||||||
<input class="saveBtn" type="submit" value="Speichern" />
|
<input class="saveBtn" type="submit" value="Speichern" />
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<input class="deleteBtn" type="button" value="Löschen (Doppelklick)" @dblclick="deleteForm(form)" />
|
||||||
</form>
|
</form>
|
||||||
<button class="saveBtn" @click="newForm">Neues Formular</button>
|
<button class="newFormBtn deleteBtn" @click="newForm">Neues Formular</button>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</div>
|
||||||
|
<div class="formresults">
|
||||||
|
<FormResults v-for="form in formulare.filter((el)=>el!=undefined)" :key="form" :form="form" :token="token"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -209,7 +234,47 @@ thead tr td {
|
|||||||
margin-left: 20%;
|
margin-left: 20%;
|
||||||
margin-right: 20%;
|
margin-right: 20%;
|
||||||
}
|
}
|
||||||
label, p, i {
|
label, p, i, h1, h2 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
.formresults{
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
input{
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 3px solid black;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 20px;
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.deleteBtn {
|
||||||
|
padding: 12px 20px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #cc0000;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.deleteBtn:hover{
|
||||||
|
background-color: #aa0000;
|
||||||
|
}
|
||||||
|
.newFormBtn{
|
||||||
|
background-color: #0000ff;
|
||||||
|
}
|
||||||
|
.newFormBtn:hover{
|
||||||
|
background-color: #0000aa;
|
||||||
|
}
|
||||||
|
.formeditor {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user