generated from cms/tibi-docs
This commit is contained in:
parent
819452e15e
commit
b107392907
95
api/collections/backups.yml
Normal file
95
api/collections/backups.yml
Normal 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
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
92
api/hooks/backups/post_create.js
Normal file
92
api/hooks/backups/post_create.js
Normal 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)
|
||||||
|
}
|
||||||
|
})()
|
@ -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 == '/'}">
|
||||||
|
Loading…
Reference in New Issue
Block a user