Added Automatic HistoryItems to Events,Customers,Vendors

This commit is contained in:
2024-04-08 15:41:28 +02:00
parent 3a0f3f75b4
commit 44a0e10a94
5 changed files with 282 additions and 15 deletions

View File

@@ -50,6 +50,8 @@ const historyItems = computed(() => {
items = dataStore.historyItems.filter(i => i.profile === elementId)
} else if(type === "absencerequest") {
items = dataStore.historyItems.filter(i => i.absenceRequest === elementId)
} else if(type === "event") {
items = dataStore.historyItems.filter(i => i.event === elementId)
}
return items
@@ -87,6 +89,8 @@ const addHistoryItem = async () => {
addHistoryItemData.value.profile = elementId
} else if(type === "absencerequest") {
addHistoryItemData.value.absenceRequest = elementId
} else if(type === "event") {
addHistoryItemData.value.event = elementId
}
@@ -176,15 +180,15 @@ const renderText = (text) => {
/>
<div class="flex items-center gap-3">
<UAvatar
v-if="!item.user"
v-if="!item.createdBy"
:src="colorMode.value === 'light' ? '/Logo.png' : '/Logo_Dark.png' "
/>
<UAvatar
:alt="dataStore.profiles.find(profile => profile.id === item.user).fullName"
:alt="dataStore.getProfileById(item.createdBy).fullName"
v-else
/>
<div>
<h3 v-if="item.user">{{dataStore.getProfileById(item.user) ? dataStore.getProfileById(item.user).fullName : ""}}</h3>
<h3 v-if="item.createdBy">{{dataStore.getProfileById(item.createdBy) ? dataStore.getProfileById(item.createdBy).fullName : ""}}</h3>
<h3 v-else>Spaces Bot</h3>
<span v-html="renderText(item.text)"/><br>
<span class="text-gray-500">{{dayjs(item.created_at).format("DD.MM.YY HH:mm")}}</span>

View File

@@ -23,6 +23,7 @@ const itemInfo = ref({
active: true,
isCompany: true
})
const oldItemInfo = ref({})
//Functions
const setupPage = async () => {
@@ -31,6 +32,7 @@ const setupPage = async () => {
}
if(mode.value === "edit") itemInfo.value = currentItem.value
if(currentItem.value.id) oldItemInfo.value = JSON.parse(JSON.stringify(currentItem.value))
}
const editItem = async () => {
@@ -54,7 +56,7 @@ setupPage()
<template #right>
<UButton
v-if="mode === 'edit'"
@click="dataStore.updateItem('customers',itemInfo)"
@click="dataStore.updateItem('customers',itemInfo,oldItemInfo)"
>
Speichern
</UButton>

View File

@@ -11,9 +11,10 @@ const mode = ref(route.params.mode || "show")
const itemInfo = ref({
resources: []
})
const oldItemInfo = ref({})
const resourceToAdd = ref(dataStore.activeProfile.id)
const mapResources = () => {
/*const mapResources = () => {
console.log(itemInfo.value.resources)
itemInfo.value.resources.map(resource => {
console.log(resource)
@@ -22,7 +23,7 @@ const mapResources = () => {
type: resource.type
}
})
}
}*/
const setupPage = () => {
@@ -39,6 +40,7 @@ const setupPage = () => {
})
}
if(route.query.project) itemInfo.value.project = route.query.project
if(itemInfo.value.id) oldItemInfo.value = JSON.parse(JSON.stringify(itemInfo.value))
@@ -65,7 +67,7 @@ setupPage()
Erstellen
</UButton>
<UButton
@click="dataStore.updateItem('events',itemInfo)"
@click="dataStore.updateItem('events',itemInfo,oldItemInfo)"
v-else-if="mode === 'edit' && route.params.id"
>
Speichern
@@ -92,7 +94,11 @@ setupPage()
{{itemInfo}}
</div>
<div v-if="item.label === 'Logbuch'">
<HistoryDisplay
type="event"
v-if="itemInfo"
:element-id="itemInfo.id"
/>
</div>
</UCard>
</template>

View File

@@ -19,6 +19,7 @@ const mode = ref(route.params.mode || "show")
const itemInfo = ref({
infoData: {}
})
const oldItemInfo = ref({})
//Functions
const setupPage = () => {
@@ -27,6 +28,8 @@ const setupPage = () => {
}
if (mode.value === "edit") itemInfo.value = currentItem.value
if(currentItem.value.id) oldItemInfo.value = JSON.parse(JSON.stringify(currentItem.value))
}
const editItem = async () => {
@@ -49,7 +52,7 @@ setupPage()
<template #right>
<UButton
v-if="mode === 'edit'"
@click="dataStore.updateItem('vendors',itemInfo)"
@click="dataStore.updateItem('vendors',itemInfo,oldItemInfo)"
>
Speichern
</UButton>

View File

@@ -17,13 +17,15 @@ export const useDataStore = defineStore('data', () => {
tasks: {
label: "Aufgaben",
labelSingle: "Aufgabe",
redirect: true
redirect: true,
historyItemHolder: "task"
},
customers: {
label: "Kunden",
labelSingle: "Kunde",
redirect:true,
numberRangeHolder: "customerNumber"
numberRangeHolder: "customerNumber",
historyItemHolder: "customer"
},
contacts: {
label: "Kontakte",
@@ -100,7 +102,9 @@ export const useDataStore = defineStore('data', () => {
},
events: {
label: "Termine",
labelSingle: "Termin"
labelSingle: "Termin",
historyItemHolder: "event",
redirect: true
},
profiles: {
label: "Mitarbeiter",
@@ -400,6 +404,250 @@ export const useDataStore = defineStore('data', () => {
}
var deepDiffMapper = function () {
return {
VALUE_CREATED: 'created',
VALUE_UPDATED: 'updated',
VALUE_DELETED: 'deleted',
VALUE_UNCHANGED: 'unchanged',
map: function(obj1, obj2) {
if (this.isFunction(obj1) || this.isFunction(obj2)) {
throw 'Invalid argument. Function given, object expected.';
}
if (this.isValue(obj1) || this.isValue(obj2)) {
return {
type: this.compareValues(obj1, obj2),
data: {o: obj1, n: obj2}//obj1 === undefined ? obj2 : obj1
};
}
var diff = {};
for (var key in obj1) {
if (this.isFunction(obj1[key])) {
continue;
}
var value2 = undefined;
if (obj2[key] !== undefined) {
value2 = obj2[key];
}
diff[key] = this.map(obj1[key], value2);
}
for (var key in obj2) {
if (this.isFunction(obj2[key]) || diff[key] !== undefined) {
continue;
}
diff[key] = this.map(undefined, obj2[key]);
}
return diff;
},
compareValues: function (value1, value2) {
if (value1 === value2) {
return this.VALUE_UNCHANGED;
}
if (this.isDate(value1) && this.isDate(value2) && value1.getTime() === value2.getTime()) {
return this.VALUE_UNCHANGED;
}
if (value1 === undefined) {
return this.VALUE_CREATED;
}
if (value2 === undefined) {
return this.VALUE_DELETED;
}
return this.VALUE_UPDATED;
},
isFunction: function (x) {
return Object.prototype.toString.call(x) === '[object Function]';
},
isArray: function (x) {
return Object.prototype.toString.call(x) === '[object Array]';
},
isDate: function (x) {
return Object.prototype.toString.call(x) === '[object Date]';
},
isObject: function (x) {
return Object.prototype.toString.call(x) === '[object Object]';
},
isValue: function (x) {
return !this.isObject(x) && !this.isArray(x);
}
}
}();
const generateHistoryItems = async (dataType,newData, oldData=null) => {
//console.log(oldData)
//console.log(newData)
let itemsToCreate = []
const checkPropState = (key,propContent) => {
//console.log(propContent)
if(propContent.type && propContent.data){
if(propContent.type === "updated" ||propContent.type === "created"){
createHistoryItem(key,propContent)
}
} else {
for (let prop in propContent) {
checkPropState(prop,propContent[prop])
}
}
}
const createHistoryItem = (key,prop) => {
console.log("OLD: " + prop.data.o)
console.log("NEW: " + prop.data.n)
let name = "" || key
let oldVal = prop.data.o || "-"
let newVal = prop.data.n || "-"
if(key === "project") {
name = "Projekt"
oldVal = projects.value.find(i => i.id === prop.data.o).name
newVal = projects.value.find(i => i.id === prop.data.n).name
} else if (key === "title") {
name = "Titel"
} else if(key === "type") {
name = "Typ"
} else if(key === "notes") {
name = "Notizen"
} else if(key === "link") {
name = "Link"
} else if(key === "start") {
name = "Start"
oldVal = dayjs(prop.data.o).format("DD.MM.YY HH:mm")
newVal = dayjs(prop.data.n).format("DD.MM.YY HH:mm")
} else if(key === "end") {
name = "Ende"
oldVal = dayjs(prop.data.o).format("DD.MM.YY HH:mm")
newVal = dayjs(prop.data.n).format("DD.MM.YY HH:mm")
} else if(key === "resources") {
name = "Resourcen"
oldVal = prop.data.o.map(i => i.title).join(", ")
newVal = prop.data.n.map(i => i.title).join(", ")
} else if(key === "customerNumber") {
name = "Kundennummer"
} else if(key === "active") {
name = "Aktiv"
if(oldVal === true){
oldVal = "Aktiv"
newVal = "Gesperrt"
} else if(oldVal === "-") {
oldVal = "Gesperrt"
newVal = "Aktiv"
}
} else if(key === "isCompany") {
name = "Firmenkunde"
if(oldVal === true){
oldVal = "Firma"
newVal = "Privatkunde"
} else if(oldVal === "-") {
oldVal = "Privatkunde"
newVal = "Firma"
}
} else if(key === "special") {
name = "Adresszusatz"
} else if(key === "street") {
name = "Straße & Hausnummer"
} else if(key === "city") {
name = "Ort"
} else if(key === "zip") {
name = "Postleitzahl"
} else if(key === "country") {
name = "Land"
} else if(key === "web") {
name = "Webseite"
} else if(key === "email") {
name = "E-Mail"
} else if(key === "tel") {
name = "Telefon"
} else if(key === "ustid") {
name = "USt-ID"
}
let text = ""
if(prop.type === "updated" && newVal !== "-" && oldVal !== "-") {
text = `Verändert: ${name} von "${oldVal}" zu "${newVal}"`
} else if(prop.type === "updated" && newVal !== "-" && oldVal === "-") {
text = `Hinzugefügt: ${name} "${newVal}"`
} else if(prop.type === "created") {
text = `Hinzugefügt: ${name} "${newVal}"`
} else if(prop.type === "updated" && newVal === "-" && oldVal !== "-") {
text = `Entfernt: ${name} "${oldVal}"`
}
let historyItem = {
text: text,
createdBy: activeProfile.value.id,
oldVal: prop.data.o,
newVal: prop.data.n,
tenant: currentTenant.value
}
historyItem[dataTypes[dataType].historyItemHolder] = newData.id
console.log(historyItem)
itemsToCreate.push(historyItem)
}
if(oldData) {
let result = deepDiffMapper.map(oldData,newData)
console.log(result)
for (let prop in result) {
//console.log(prop)
checkPropState(prop,result[prop])
//console.log(prop)
//console.log(result[prop])
}
} else {
let historyItem = {
text: `${dataTypes[dataType].labelSingle} erstellt`,
createdBy: activeProfile.value.id,
tenant: currentTenant.value
}
historyItem[dataTypes[dataType].historyItemHolder] = newData.id
console.log(historyItem)
itemsToCreate.push(historyItem)
}
/*const {data,error} = await supabase.from("historyitems").insert(itemsToCreate)
if(error) {
console.log(error)
} else {
fetchHistoryItems()
}*/
}
//Realtime Update
const channelA = supabase
@@ -454,6 +702,8 @@ export const useDataStore = defineStore('data', () => {
}
const {data:supabaseData,error:supabaseError} = await supabase
.from(dataType)
.insert(data)
@@ -463,6 +713,8 @@ export const useDataStore = defineStore('data', () => {
console.log(supabaseError)
toast.add({title: "Es ist ein Fehler bei der Erstellung aufgetreten", color: "rose"})
} else if (supabaseData) {
console.log(supabaseData)
await generateHistoryItems(dataType, supabaseData[0])
await eval( dataType + '.value.push(' + JSON.stringify(...supabaseData) + ')')
toast.add({title: `${dataTypes[dataType].labelSingle} hinzugefügt`})
if(dataTypes[dataType].redirect) await router.push(`/${dataType}/show/${supabaseData[0].id}`)
@@ -470,12 +722,11 @@ export const useDataStore = defineStore('data', () => {
}
}
async function updateItem (dataType, data) {
async function updateItem (dataType, data, oldData = null) {
const {tenants, ...newData} = data
await generateHistoryItems(dataType,data,oldData)
const {data:supabaseData,error: supabaseError} = await supabase
.from(dataType)
@@ -1164,6 +1415,7 @@ export const useDataStore = defineStore('data', () => {
changeProfile,
uploadFiles,
hasRight,
generateHistoryItems,
//Data
profiles,