Compare commits
3 Commits
a0ebf89ef8
...
5a583a94ff
Author | SHA1 | Date | |
---|---|---|---|
5a583a94ff | |||
8383080395 | |||
2e8ee7ca5c |
31
README.MD
31
README.MD
@ -16,3 +16,34 @@ Funktionen:
|
|||||||
- Erklärung MP3
|
- Erklärung MP3
|
||||||
- Quittierung MP3
|
- Quittierung MP3
|
||||||
- Verabschiedung MP3
|
- Verabschiedung MP3
|
||||||
|
|
||||||
|
|
||||||
|
## API Endpoint planning
|
||||||
|
|
||||||
|
alertContacts (CRUD Fully implemented)
|
||||||
|
alerts -> Only get
|
||||||
|
|
||||||
|
|
||||||
|
actionPlan (CRUD)
|
||||||
|
- select all prios
|
||||||
|
|
||||||
|
priorities (CRUD)
|
||||||
|
- select actionPlan
|
||||||
|
- Only allow changes to priority
|
||||||
|
|
||||||
|
content (CRUD)
|
||||||
|
- Howto handle upload?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
POST /alert/[:alert_hook]
|
||||||
|
-> Check actionplan if hook exists and select current prios -> Write call request to XYXYX
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1. create one or more alertContacts
|
||||||
|
2. create 4x content (all phases)
|
||||||
|
3. create actionplan with contents
|
||||||
|
4. create one or more priorities
|
||||||
|
|
||||||
|
2278
docs/index.html
2278
docs/index.html
File diff suppressed because one or more lines are too long
@ -2,7 +2,7 @@
|
|||||||
//// THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
|
//// THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
|
||||||
//// ------------------------------------------------------
|
//// ------------------------------------------------------
|
||||||
|
|
||||||
Project "AssetFlow" {
|
Project "ATAS" {
|
||||||
database_type: ''
|
database_type: ''
|
||||||
Note: ''
|
Note: ''
|
||||||
}
|
}
|
||||||
@ -10,11 +10,11 @@ Project "AssetFlow" {
|
|||||||
Table alerts {
|
Table alerts {
|
||||||
id Int [pk, increment]
|
id Int [pk, increment]
|
||||||
type alertType [not null]
|
type alertType [not null]
|
||||||
message String
|
state alertState [not null]
|
||||||
|
description String
|
||||||
|
date DateTime [not null]
|
||||||
actionplan actionPlan
|
actionplan actionPlan
|
||||||
actionplanId Int
|
actionplanId Int
|
||||||
date DateTime [not null]
|
|
||||||
state alertState [not null]
|
|
||||||
acknowledged_by alertContacts [not null]
|
acknowledged_by alertContacts [not null]
|
||||||
acknowledged_at DateTime
|
acknowledged_at DateTime
|
||||||
}
|
}
|
||||||
@ -30,9 +30,9 @@ Table alertContacts {
|
|||||||
|
|
||||||
Table actionPlan {
|
Table actionPlan {
|
||||||
id Int [pk, increment]
|
id Int [pk, increment]
|
||||||
name String [not null]
|
name String [unique, not null]
|
||||||
comment String
|
comment String
|
||||||
alert_hook String [unique, not null]
|
alerthook String [unique, not null]
|
||||||
prio priorities [not null]
|
prio priorities [not null]
|
||||||
content content [not null]
|
content content [not null]
|
||||||
alerts alerts [not null]
|
alerts alerts [not null]
|
||||||
@ -85,7 +85,7 @@ Enum alertType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Enum alertState {
|
Enum alertState {
|
||||||
incomming
|
incoming
|
||||||
running
|
running
|
||||||
failed
|
failed
|
||||||
acknowledged
|
acknowledged
|
||||||
|
@ -26,7 +26,7 @@ generator dbml {
|
|||||||
provider = "prisma-dbml-generator"
|
provider = "prisma-dbml-generator"
|
||||||
output = "../docs"
|
output = "../docs"
|
||||||
outputName = "schema.dbml"
|
outputName = "schema.dbml"
|
||||||
projectName = "AssetFlow"
|
projectName = "ATAS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ enum alertType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum alertState {
|
enum alertState {
|
||||||
incomming // Incomming alerts
|
incoming // Incoming alerts
|
||||||
running // Started calling
|
running // Started calling
|
||||||
failed // Failed to get acknowledgement of any alertContacts
|
failed // Failed to get acknowledgement of any alertContacts
|
||||||
acknowledged // Some user acknowledged alert
|
acknowledged // Some user acknowledged alert
|
||||||
@ -55,16 +55,19 @@ enum alertState {
|
|||||||
model alerts {
|
model alerts {
|
||||||
id Int @id @unique @default(autoincrement())
|
id Int @id @unique @default(autoincrement())
|
||||||
type alertType
|
type alertType
|
||||||
message String?
|
state alertState
|
||||||
|
|
||||||
|
description String?
|
||||||
|
date DateTime
|
||||||
|
|
||||||
actionplan actionPlan? @relation(fields: [actionplanId], references: [id])
|
actionplan actionPlan? @relation(fields: [actionplanId], references: [id])
|
||||||
actionplanId Int?
|
actionplanId Int?
|
||||||
date DateTime
|
|
||||||
state alertState
|
|
||||||
acknowledged_by alertContacts[]
|
acknowledged_by alertContacts[]
|
||||||
acknowledged_at DateTime?
|
acknowledged_at DateTime?
|
||||||
@@fulltext([message])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@@fulltext([description])
|
||||||
|
}
|
||||||
|
|
||||||
model alertContacts {
|
model alertContacts {
|
||||||
id Int @id @unique @default(autoincrement())
|
id Int @id @unique @default(autoincrement())
|
||||||
@ -73,17 +76,20 @@ model alertContacts {
|
|||||||
comment String?
|
comment String?
|
||||||
prios priorities[]
|
prios priorities[]
|
||||||
alerts alerts[]
|
alerts alerts[]
|
||||||
|
|
||||||
@@fulltext([name, phone, comment])
|
@@fulltext([name, phone, comment])
|
||||||
}
|
}
|
||||||
|
|
||||||
model actionPlan {
|
model actionPlan {
|
||||||
id Int @id @unique @default(autoincrement())
|
id Int @id @unique @default(autoincrement())
|
||||||
name String
|
name String @unique
|
||||||
comment String?
|
comment String?
|
||||||
alert_hook String @unique
|
alerthook String @unique
|
||||||
prio priorities[]
|
prio priorities[]
|
||||||
content content[] // aka. all voice files
|
content content[] // aka. all voice files
|
||||||
|
|
||||||
alerts alerts[]
|
alerts alerts[]
|
||||||
|
|
||||||
@@fulltext([name, comment])
|
@@fulltext([name, comment])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,12 +110,10 @@ model content {
|
|||||||
name String
|
name String
|
||||||
filename String
|
filename String
|
||||||
actionplan actionPlan[]
|
actionplan actionPlan[]
|
||||||
|
|
||||||
@@fulltext([name, filename])
|
@@fulltext([name, filename])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// https://spacecdn.de/file/bma_stoe_v1.mp3
|
// https://spacecdn.de/file/bma_stoe_v1.mp3
|
||||||
// https://spacecdn.de/file/quittiert_v1.mp3
|
// https://spacecdn.de/file/quittiert_v1.mp3
|
||||||
// https://spacecdn.de/file/angenehmen_tag_v1.mp3
|
// https://spacecdn.de/file/angenehmen_tag_v1.mp3
|
||||||
|
@ -59,9 +59,62 @@ let _api = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
},
|
||||||
|
delete: async function (path, data) {
|
||||||
|
const options = {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: new Headers({ 'content-type': 'application/json' }),
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
};
|
||||||
|
const response = await fetch(_apiConfig.basePath + path, options);
|
||||||
|
// Handle the response
|
||||||
|
if (!response.ok) {
|
||||||
|
_testPageFail(response.statusText);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
const result = await response.json();
|
||||||
|
// Handle the result, was json valid?
|
||||||
|
if (!result) {
|
||||||
|
_testPageFail('Invalid JSON response');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
patch: async function (path, data) {
|
||||||
|
const options = {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: new Headers({ 'content-type': 'application/json' }),
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
};
|
||||||
|
const response = await fetch(_apiConfig.basePath + path, options);
|
||||||
|
// Handle the response
|
||||||
|
if (!response.ok) {
|
||||||
|
_testPageFail(response.statusText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const result = await response.json();
|
||||||
|
// Handle the result, was json valid?
|
||||||
|
if (!result) {
|
||||||
|
_testPageFail('Invalid JSON response');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function updateRow(tableName, id, data) {
|
||||||
|
invalidateCache(tableName);
|
||||||
|
return _api.patch(`${tableName}`, { id: id, ...data });
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteRow(tableName, id) {
|
||||||
|
invalidateCache(tableName);
|
||||||
|
return _api.delete(`${tableName}`, { id: id });
|
||||||
|
}
|
||||||
|
|
||||||
function getApiDescriptionByTable(tableName) {
|
function getApiDescriptionByTable(tableName) {
|
||||||
const keyDesc = `desc:${tableName}`;
|
const keyDesc = `desc:${tableName}`;
|
||||||
const keyTime = `${keyDesc}:time`;
|
const keyTime = `${keyDesc}:time`;
|
||||||
|
@ -39,6 +39,9 @@ tables.forEach(async (table) => {
|
|||||||
// Get THs and attach onClick event to sort
|
// Get THs and attach onClick event to sort
|
||||||
const ths = table.querySelectorAll('th');
|
const ths = table.querySelectorAll('th');
|
||||||
ths.forEach((th) => {
|
ths.forEach((th) => {
|
||||||
|
if(th.getAttribute('fnc') == "actions") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
th.style.cursor = 'pointer';
|
th.style.cursor = 'pointer';
|
||||||
th.style.userSelect = 'none';
|
th.style.userSelect = 'none';
|
||||||
th.addEventListener('click', async function () {
|
th.addEventListener('click', async function () {
|
||||||
@ -216,9 +219,17 @@ modalForms.forEach((modalForm) => {
|
|||||||
jsonData[key] = value;
|
jsonData[key] = value;
|
||||||
});
|
});
|
||||||
console.log('JSON Data: ', jsonData);
|
console.log('JSON Data: ', jsonData);
|
||||||
let resp = await createEntry(table, jsonData);
|
let resp = {};
|
||||||
|
if(modalForm.getAttribute('data-action') == 'edit') {
|
||||||
|
Rid = modalForm.getAttribute('data-rid');
|
||||||
|
resp = await updateRow(table, Rid,jsonData);
|
||||||
|
modalForm.setAttribute('data-action', 'create');
|
||||||
|
} else {
|
||||||
|
resp = await createEntry(table, jsonData);
|
||||||
|
}
|
||||||
|
|
||||||
console.log('Response: ', resp);
|
console.log('Response: ', resp);
|
||||||
if (resp['status'] == 'CREATED') {
|
if (resp['status'] == 'CREATED' || resp['status'] == 'UPDATED') {
|
||||||
console.log('Entry created successfully');
|
console.log('Entry created successfully');
|
||||||
modalForm.closest('.modal').classList.remove('is-active');
|
modalForm.closest('.modal').classList.remove('is-active');
|
||||||
modalForm.reset();
|
modalForm.reset();
|
||||||
@ -358,10 +369,18 @@ function writeDataToTable(table, data, paginationPassOn) {
|
|||||||
|
|
||||||
// All required cols
|
// All required cols
|
||||||
let requiredCols = [];
|
let requiredCols = [];
|
||||||
|
let actionFields = [];
|
||||||
columns.forEach((column) => {
|
columns.forEach((column) => {
|
||||||
|
// console.log('Column: ', column, ' FNC: ', column.getAttribute('data-fnc'), column.attributes);
|
||||||
|
if(column.getAttribute('data-fnc') == "actions") {
|
||||||
|
console.log('!!! Found actions column !!!');
|
||||||
|
actionFields.push(column);
|
||||||
|
return;
|
||||||
|
}
|
||||||
requiredCols.push(column.getAttribute('data-dataCol'));
|
requiredCols.push(column.getAttribute('data-dataCol'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Get paginationPassOn
|
// Get paginationPassOn
|
||||||
const start = paginationPassOn['start'];
|
const start = paginationPassOn['start'];
|
||||||
const end = paginationPassOn['end'];
|
const end = paginationPassOn['end'];
|
||||||
@ -457,6 +476,100 @@ function writeDataToTable(table, data, paginationPassOn) {
|
|||||||
td.innerText = row[column];
|
td.innerText = row[column];
|
||||||
tr.appendChild(td);
|
tr.appendChild(td);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add action fields
|
||||||
|
actionFields.forEach((actionField) => {
|
||||||
|
const td = document.createElement('td');
|
||||||
|
const actions = actionField.getAttribute('data-actions').split(',');
|
||||||
|
actions.forEach((action) => {
|
||||||
|
const button = document.createElement('button');
|
||||||
|
let icon = '';
|
||||||
|
let color = 'is-primary';
|
||||||
|
switch(action) {
|
||||||
|
case 'edit': {
|
||||||
|
icon = '<i class="bi bi-pencil"></i>';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'delete': {
|
||||||
|
icon = '<i class="bi bi-trash"></i>';
|
||||||
|
color = 'is-danger';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add classes
|
||||||
|
button.classList.add('button');
|
||||||
|
button.classList.add('is-small');
|
||||||
|
button.classList.add(color);
|
||||||
|
button.classList.add('is-outlined');
|
||||||
|
button.innerHTML = ` <span class="icon is-small">${icon}</span> `;
|
||||||
|
button.style.marginRight = '5px';
|
||||||
|
|
||||||
|
// Add data-action and data-id
|
||||||
|
button.setAttribute('data-action', action);
|
||||||
|
button.setAttribute("data-id", row["id"]);
|
||||||
|
|
||||||
|
// Add event listener
|
||||||
|
button.addEventListener('click', async function() {
|
||||||
|
const table = actionField.closest('table');
|
||||||
|
const row = button.closest('tr');
|
||||||
|
const columns = table.querySelectorAll('th');
|
||||||
|
const columnIndices = [];
|
||||||
|
columns.forEach((column, index) => {
|
||||||
|
columnIndices[column.getAttribute('data-dataCol')] = index;
|
||||||
|
});
|
||||||
|
const data = [];
|
||||||
|
columns.forEach((column) => {
|
||||||
|
data[column.getAttribute('data-dataCol')] = row.children[columnIndices[column.getAttribute('data-dataCol')]].innerText;
|
||||||
|
});
|
||||||
|
console.log('Data: ', data);
|
||||||
|
switch(action) {
|
||||||
|
case 'edit': {
|
||||||
|
// Open modal with form
|
||||||
|
const form = document.querySelector("form[data-targetTable='" + table.getAttribute('data-dataSource') + "']");
|
||||||
|
const formTitle = form.querySelector('.title');
|
||||||
|
const entryPhase = form.querySelector('.entryPhase');
|
||||||
|
const loadPhase = form.querySelector('.loadPhase');
|
||||||
|
const fields = form.querySelectorAll('input');
|
||||||
|
// Set modal to edit mode
|
||||||
|
form.setAttribute('data-action', 'edit');
|
||||||
|
form.setAttribute('data-rid', button.getAttribute('data-id'));
|
||||||
|
formTitle.innerText = 'Edit entry';
|
||||||
|
fields.forEach((field) => {
|
||||||
|
// Skip for submit button
|
||||||
|
if(field.getAttribute('type') == 'submit') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
field.value = data[field.getAttribute('name')];
|
||||||
|
});
|
||||||
|
form.closest('.modal').classList.add('is-active');
|
||||||
|
// TBD
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'delete': {
|
||||||
|
// confirm
|
||||||
|
const confirm = window.confirm('Do you really want to delete this entry?');
|
||||||
|
// Delete entry
|
||||||
|
if(confirm) {
|
||||||
|
const table = actionField.closest('table');
|
||||||
|
const id = button.getAttribute('data-id');
|
||||||
|
const resp = await deleteRow(table.getAttribute('data-dataSource'), id);
|
||||||
|
if(resp['status'] == 'DELETED') {
|
||||||
|
refreshTable(table);
|
||||||
|
updateSingeltonsByTableName(table.getAttribute('data-dataSource'));
|
||||||
|
} else {
|
||||||
|
// Show error message
|
||||||
|
// TODO: Show error message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
td.appendChild(button);
|
||||||
|
});
|
||||||
|
tr.appendChild(td);
|
||||||
|
});
|
||||||
tbody.appendChild(tr);
|
tbody.appendChild(tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,9 @@
|
|||||||
<i class="bi bi-arrow-clockwise title"></i>
|
<i class="bi bi-arrow-clockwise title"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="box entryPhase">
|
<div class="box entryPhase">
|
||||||
<h2 class="title">New Contact</h1>
|
|
||||||
<form data-targetTable="AlertContacts">
|
<form data-targetTable="AlertContacts">
|
||||||
|
<h2 class="title">New Contact</h1>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Name</label>
|
<label class="label">Name</label>
|
||||||
<div class="control has-icons-left">
|
<div class="control has-icons-left">
|
||||||
@ -108,6 +109,7 @@
|
|||||||
<th data-dataCol = "name">Name</th>
|
<th data-dataCol = "name">Name</th>
|
||||||
<th data-dataCol = "phone">Telefon Nummer</th>
|
<th data-dataCol = "phone">Telefon Nummer</th>
|
||||||
<th data-dataCol = "comment">Kommentar</th>
|
<th data-dataCol = "comment">Kommentar</th>
|
||||||
|
<th data-fnc="actions" data-actions="edit,delete">Aktionen</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user