Compare commits

...

6 Commits

Author SHA1 Message Date
8e8f6eb976 mail
All checks were successful
deploy to production / deploy (push) Successful in 30s
2023-11-20 15:05:22 +00:00
b107392907 backups
All checks were successful
deploy to production / deploy (push) Successful in 34s
2023-11-05 09:32:22 +00:00
819452e15e test
All checks were successful
deploy to production / deploy (push) Successful in 29s
2023-10-18 15:16:54 +00:00
7d2e708e65 test
All checks were successful
deploy to production / deploy (push) Successful in 29s
2023-10-18 15:13:46 +00:00
75d4c88d47 test
All checks were successful
deploy to production / deploy (push) Successful in 30s
2023-10-18 15:00:30 +00:00
850fb6ad1e test
All checks were successful
deploy to production / deploy (push) Successful in 31s
2023-10-18 14:55:24 +00:00
7 changed files with 227 additions and 5 deletions

View File

@@ -0,0 +1,95 @@
name: backups
meta:
isBackupcollection: true
permissions:
public:
methods:
get: false
post: false
put: false
delete: false
user:
methods:
get: true
post: false
put: false
delete: false
# token als Zusatzsicherung gegen Spam, mehr siehe Hook
"token:${PUBLIC_TOKEN}":
methods:
get: false
post: true
put: false
delete: false
hooks:
post:
create:
type: javascript
file: hooks/backups/post_create.js
fields:
- name: collectionName
type: string
meta:
label: Collection Name
- name: entryId
type: string
meta:
label: Entry ID
- name: versionNr
type: number
meta:
label: Version Nr
- name: manipulatedBy
type: string
meta:
label: Manipulated By
- name: eventDescription
type: string
meta:
label: Event Description
widget: select
choices:
- id: create
name: Create
- id: update
name: Update
- id: delete
name: Delete
- id: recreate
name: Recreate
- id: activate
name: Activate
- name: updateLogs
type: object[]
meta:
label: Veränderungen
subFields:
- name: field
type: string
meta:
label: Feldname
- name: previous
type: string
meta:
label: Vorheriger Wert
- name: current
type: string
meta:
label: Aktueller Wert
- name: entry
type: object
meta:
label: Entry

View File

@@ -4,6 +4,9 @@ uploadPath: ../media/page
meta: meta:
label: Inhalt label: Inhalt
muiIcon: web muiIcon: web
backup:
active: true
collectionName: backups
views: views:
- type: table - type: table
columns: columns:
@@ -90,6 +93,7 @@ fields:
type: object[] type: object[]
meta: meta:
label: Zeilen label: Zeilen
widget: containerLessObjectArray
folding: folding:
force: true force: true
subFields: subFields:

View File

@@ -8,9 +8,26 @@ meta:
- url: https://tibi-admin-server.code.testversion.online/api/v1/_/demo - url: https://tibi-admin-server.code.testversion.online/api/v1/_/demo
description: code-server description: code-server
dashboard:
majorItems:
- collection: navigation
type: reference
style:
upper: rgba(3, 50, 59, 0.7)
lower: rgba(3, 50, 59)
- collection: page
type: reference
style:
upper: rgba(3, 50, 59, 0.7)
lower: rgba(3, 50, 59)
minorItems: []
collections: collections:
- !include collections/navigation.yml - !include collections/navigation.yml
- !include collections/content.yml - !include collections/content.yml
- !include collections/backups.yml
assets: assets:
- name: img - name: img

View File

@@ -0,0 +1,92 @@
;(function () {
let backup = context.data
const updateLogs = compareAndUpdateEntry(backup?.entry, backup?.collectionName, backup?.versionNr - 1)
backup.updateLogs = updateLogs
return { data: backup }
function compareAndUpdateEntry(entry, collectionName, versionNr) {
let updateLogs
if (versionNr == 0) {
updateLogs = getUpdateLogs({}, entry)
}
delete entry.updateTime
let previousEntry = context.db.find("backups", {
filter: { entryId: context.data.entryId, versionNr, collectionName },
})[0]
if (!previousEntry) {
console.error("No previous entry found")
updateLogs = getUpdateLogs({}, entry)
} else {
delete previousEntry.updateTime
updateLogs = getUpdateLogs(previousEntry.entry, entry)
}
console.log(context.json.stringify(previousEntry?.entry), context.json.stringify(entry))
return updateLogs
}
function filterValidObjects(array) {
return array.filter((object) => {
for (let key in object) {
if (typeof object[key] !== "string" && object[key] !== null) {
return false
}
}
return true
})
}
function getUpdateLogs(oldObj = {}, newObj = {}, path = "") {
let updateLogs = []
const ignoredKeys = ["id", "insertTime", "updateTime"]
const allKeys = new Set([...Object.keys(oldObj), ...Object.keys(newObj)])
allKeys.forEach((key) => {
if (ignoredKeys.includes(key)) return
const newPath = path ? `${path}.${key}` : key
const oldVal = oldObj.hasOwnProperty(key) ? oldObj[key] : ""
const newVal = newObj.hasOwnProperty(key) ? newObj[key] : ""
// Handle Arrays
if (Array.isArray(oldVal) || Array.isArray(newVal)) {
const oldArr = oldVal || []
const newArr = newVal || []
for (let i = 0; i < Math.max(oldArr.length, newArr.length); i++) {
const itemPath = `${newPath}[${i}]`
if (oldArr[i] !== newArr[i]) {
if (typeof oldArr[i] === "object" || typeof newArr[i] === "object") {
const arrUpdates = getUpdateLogs(oldArr[i], newArr[i], itemPath)
updateLogs = updateLogs.concat(arrUpdates)
} else {
updateLogs.push({
field: itemPath,
previous: oldArr[i] === undefined ? "" : oldArr[i].toString(),
current: newArr[i] === undefined ? "" : newArr[i].toString(),
})
}
}
}
}
// Handle nested objects but not arrays
else if (
(typeof oldVal === "object" && oldVal !== null) ||
(typeof newVal === "object" && newVal !== null)
) {
const nestedUpdates = getUpdateLogs(oldVal || {}, newVal || {}, newPath)
updateLogs = updateLogs.concat(nestedUpdates)
}
// Handle primitive types
else if (oldVal !== newVal) {
updateLogs.push({
field: newPath,
previous: oldVal.toString(),
current: newVal.toString(),
})
}
})
return filterValidObjects(updateLogs)
}
})()

View File

@@ -33,8 +33,10 @@
return "" return ""
} }
$: console.log($pages)
let nestedPath = checkNestedPath() let nestedPath = checkNestedPath()
window.addEventListener("popstate", function (event) {
$rerender = $rerender + 1
})
</script> </script>
{#if Object.keys(row).length} {#if Object.keys(row).length}
@@ -44,7 +46,7 @@
</h3> </h3>
{/if} {/if}
{#if nestedPath} {#if nestedPath}
<div style="display: flex; width: 100%; justify-content: space-between;"> <div class="top-header" style="display: flex; width: 100%; justify-content: space-between;">
<h3 <h3
style="cursor: pointer; display: flex; align-items: center; gap: 10px; line-height: 1.4;" style="cursor: pointer; display: flex; align-items: center; gap: 10px; line-height: 1.4;"
on:keydown on:keydown
@@ -59,10 +61,11 @@
style="cursor: pointer; display: flex; align-items: center; gap: 10px; line-height: 1.4;" style="cursor: pointer; display: flex; align-items: center; gap: 10px; line-height: 1.4;"
on:keydown on:keydown
on:click="{() => { on:click="{() => {
$rerender = $rerender + 1
navigate(row?.nextPage || nestedPath) navigate(row?.nextPage || nestedPath)
}}" }}"
> >
zum nächsten Profil <img src="/media/arrowr.svg" alt="arrow" /> Zum nächsten Profil <img src="/media/arrowr.svg" alt="arrow" />
</h3> </h3>
</div> </div>
{/if} {/if}
@@ -146,6 +149,18 @@
font-weight: 500; font-weight: 500;
font-size: 2rem; font-size: 2rem;
} }
.top-header {
img {
width: 20px;
}
font-size: 0.7rem;
@media @tablet {
font-size: 1.2rem;
img {
width: 48px;
}
}
}
@media @tablet { @media @tablet {
h3 { h3 {
font-size: 1.3rem; font-size: 1.3rem;

View File

@@ -39,7 +39,6 @@
initPage() initPage()
} }
} }
$: console.log(page?.rows, "==rows")
</script> </script>
<div class="rows" class:HP="{path == '/'}"> <div class="rows" class:HP="{path == '/'}">

View File

@@ -38,7 +38,7 @@
{@html box.text} {@html box.text}
{#if box.emailButton} {#if box.emailButton}
<a <a
href="mailto:info@fontis.de?subject={box.emailSubject || 'Bewerbung'}" href="mailto:bewerbung@fontis.de?subject={box.emailSubject || 'Bewerbung'}"
style="text-decoration: none;" style="text-decoration: none;"
class="button" class="button"
> >