listTables with preview in two layouts

This commit is contained in:
ma0068
2025-02-11 09:02:56 +01:00
parent 018220594a
commit ae3072be92
9 changed files with 508 additions and 47 deletions
@@ -36,7 +36,7 @@ class Messages extends FHCAPI_Controller
$this->terminateWithError("logic for type_id " . $type_id . " not defined yet", self::ERROR_TYPE_GENERAL);
}
$result = $this->MessageModel->getMessagesOfPerson($id);
$result = $this->MessageModel->getMessagesForTable($id);
$data = $this->getDataOrTerminateWithError($result);
+53 -4
View File
@@ -109,10 +109,7 @@ class Message_model extends DB_Model
re.vornamen AS revornamen,
s.status,
s.statusinfo,
s.insertamum AS statusamum,
CONCAT(se.titelpre, ' ', se.vorname, ' ', se.nachname, ' ', se.titelpost) as sender,
CONCAT(re.titelpre, ' ', re.vorname, ' ', re.nachname, ' ', re.titelpost ) as recipient,
TO_CHAR(s.insertamum::timestamp, 'DD.MM.YYYY HH24:MI') AS format_insertamum
s.insertamum AS statusamum
FROM public.tbl_msg_message m
JOIN public.tbl_msg_recipient r ON m.message_id = r.message_id
JOIN public.tbl_person se ON (m.person_id = se.person_id)
@@ -233,4 +230,56 @@ class Message_model extends DB_Model
return $this->execQuery($query, $params);
}
/**
* Gets messages for a person for tableMessages.
* @param $person_id
* @param null $status message status. by default, latest status is returned
* @return array|null
*/
public function getMessagesForTable($person_id, $status = null)
{
$sql = "
SELECT
m.message_id AS message_id,
m.subject AS subject,
m.body AS body,
m.insertamum AS insertamum,
m.relationmessage_id AS relationmessage_id,
(SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = m.person_id) as sender,
(SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = r.person_id) as recipient,
m.person_id as sender_id,
r.person_id as recipient_id,
MAX(ss.status) as status,
MAX(ss.insertamum) as statusdatum
FROM public.tbl_msg_message m
JOIN public.tbl_msg_recipient r USING(message_id)
JOIN public.tbl_msg_status ss ON(r.message_id = ss.message_id AND ss.person_id = r.person_id)
WHERE m.person_id = ?
GROUP BY m.message_id, m.subject, m.body, m.insertamum, m.relationmessage_id, sender, recipient, sender_id, recipient_id
UNION ALL
SELECT
m.message_id AS message_id,
m.subject AS subject,
m.body AS body,
m.insertamum AS insertamum,
m.relationmessage_id AS relationmessage_id,
(SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = m.person_id) as sender,
(SELECT COALESCE(titelpre,'') || ' ' || COALESCE(vorname,'') || ' ' || COALESCE(nachname,'') || ' ' || COALESCE(titelpost,'') FROM public.tbl_person WHERE person_id = r.person_id) as recipient,
m.person_id as sender_id,
r.person_id as recipient_id,
MAX(ss.status) as status,
MAX(ss.insertamum) as statusdatum
FROM public.tbl_msg_recipient r
JOIN public.tbl_msg_status ss USING(message_id, person_id)
JOIN public.tbl_msg_message m USING(message_id)
WHERE r.person_id = ?
GROUP BY m.message_id, m.subject, m.body, m.insertamum, m.relationmessage_id, sender, recipient, sender_id, recipient_id
ORDER BY insertamum
";
$parametersArray = array($person_id, $person_id);
return $this->execQuery($sql, $parametersArray);
}
}
+1
View File
@@ -4,6 +4,7 @@
@import './components/FilterComponent.css';
@import './components/Tabs.css';
@import './components/Notiz.css';
@import './components/Messages.css';
html {
font-size: .875em;
+4
View File
@@ -0,0 +1,4 @@
.twoColumns {
height: 400px;
overflow-y: auto;
}
-1
View File
@@ -1,6 +1,5 @@
export default {
getMessages(url, config, params){
console.log("in api", params);
return this.$fhcApi.get('api/frontend/v1/messages/messages/getMessages/' + params.id + '/' + params.type);
},
}
@@ -1,8 +1,12 @@
import {CoreFilterCmpt} from "../../filter/Filter.js";
import FormForm from '../../Form/Form.js';
//import FormInput from '../../Form/Input.js';
export default {
components: {
CoreFilterCmpt,
FormForm,
// FormInput
},
props: {
endpoint: {
@@ -14,6 +18,7 @@ export default {
type: [Number, String],
required: true
},
messageLayout: String,
},
//TODO(Manu) endpoint macht Probleme
data(){
@@ -32,12 +37,65 @@ export default {
{title: "subject", field: "subject"},
{title: "body", field: "body", visible: false},
{title: "message_id", field: "message_id", visible: false},
{title: "datum", field: "format_insertamum"},
{
title: "Datum",
field: "insertamum",
formatter: function (cell) {
const dateStr = cell.getValue();
const date = new Date(dateStr); // Convert to Date object
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
hour12: false
});
}
},
{title: "sender", field: "sender"},
{title: "recipient", field: "recipient"},
{title: "sepersonid", field: "sepersonid"},
{title: "repersonid", field: "repersonid"},
{title: "status", field: "status"},
{title: "senderId", field: "sender_id"},
{title: "recipientId", field: "recipient_id"},
{
title: "status",
field: "status",
formatter: function (cell) {
//TODO(Manu) get phrases in this context to work?
/* const statusMap = {
0: this.$p.t('messsages', 'unread'),
1: this.$p.t('messsages', 'read'),
2: this.$p.t('messsages', 'archived'),
3: this.$p.t('messsages', 'deleted')
};*/
const statusMap = {
0: 'unread',
1: 'read',
2: 'archived',
3: 'deleted'
};
return statusMap[cell.getValue()];
// return this.$p.t('messsages', 'deleted');
}
},
{
title: "letzte Änderung",
field: "statusdatum",
formatter: function (cell) {
const dateStr = cell.getValue();
const date = new Date(dateStr); // Convert to Date object
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
hour12: false
});
}
},
{
title: 'Aktionen', field: 'actions',
width: 100,
@@ -47,23 +105,23 @@ export default {
let button = document.createElement('button');
button.className = 'btn btn-outline-secondary btn-action';
button.title = this.$p.t('ui', 'notiz_edit');
button.innerHTML = '<i class="fa fa-edit"></i>';
button.title = this.$p.t('global', 'reply');
button.innerHTML = '<i class="fa fa-reply"></i>';
button.addEventListener(
'click',
(event) =>
this.actionEditNotiz(cell.getData().notiz_id)
this.reply(cell.getData().message_id)
);
container.append(button);
button = document.createElement('button');
button.className = 'btn btn-outline-secondary btn-action';
button.title = this.$p.t('notiz', 'notiz_delete');
button.title = this.$p.t('ui', 'loeschen');
button.innerHTML = '<i class="fa fa-xmark"></i>';
button.addEventListener(
'click',
() =>
this.actionDeleteNotiz(cell.getData().notiz_id)
this.deleteMessage(cell.getData().message_id)
);
container.append(button);
@@ -71,46 +129,186 @@ export default {
},
frozen: true
}],
layout: 'fitColumns',
layoutColumnsOnNewData: false,
height: '250',
layout: 'fitDataFill',
layoutColumnsOnNewData: false,
// height: 'auto',
height: '400',
selectable: true,
selectableRangeMode: 'click',
/* layoutColumnsOnNewData: false,
selectableRangeMode: 'click',
selectable: true,
index: 'message_id',
persistenceID: 'core-message'
persistenceID: 'core-message'*/
},
tabulatorEvents: [
{
event: 'dataLoaded',
handler: data => this.tabulatorData = data.map(item => {
return item;
}),
},
{
event: 'tableBuilt',
handler: async() => {
await this.$p.loadCategory(['global', 'person', 'stv', 'messages', 'ui', 'notiz']);
let cm = this.$refs.table.tabulator.columnManager;
cm.getColumnByField('subject').component.updateDefinition({
title: this.$p.t('global', 'betreff')
});
cm.getColumnByField('body').component.updateDefinition({
title: this.$p.t('messages', 'body')
});
cm.getColumnByField('message_id').component.updateDefinition({
title: this.$p.t('messages', 'message_id')
});
cm.getColumnByField('insertamum').component.updateDefinition({
title: this.$p.t('global', 'datum')
});
cm.getColumnByField('sender').component.updateDefinition({
title: this.$p.t('messages', 'sender')
});
cm.getColumnByField('recipient').component.updateDefinition({
title: this.$p.t('messages', 'recipient')
});
cm.getColumnByField('sender_id').component.updateDefinition({
title: this.$p.t('messages', 'senderId')
});
cm.getColumnByField('recipient_id').component.updateDefinition({
title: this.$p.t('messages', 'recipientId')
});
cm.getColumnByField('statusdatum').component.updateDefinition({
title: this.$p.t('notiz', 'letzte_aenderung')
});
/*
cm.getColumnByField('actions').component.updateDefinition({
title: this.$p.t('global', 'aktionen')
});
*/
}
},
{
event: 'rowClick',
handler: (e, row) => {
const selectedMessage = row.getData().message_id;
const body = row.getData().body;
this.previewBody = body;
console.log(selectedMessage);
}
},
],
tabulatorData: [],
previewBody: ""
}
},
/* computed: {
methods: {
reply(message_id){
console.log("in reply " + message_id);
},
deleteMessage(message_id){
console.log("deleteMessage " + message_id);
},
actionNewMessage(){
console.log("action new message");
},
},
computed: {
statusText(){
0: this.$p.t('messsages', 'unread'),
1: this.$p.t('messsages', 'read'),
2: this.$p.t('messsages', 'archived'),
0: this.$p.t('messsages', 'unread'),
3: this.$p.t('person', 'deleted'),
return {
0: this.$p.t('messsages', 'unread'),
1: this.$p.t('messsages', 'read'),
2: this.$p.t('messsages', 'archived'),
3: this.$p.t('messsages', 'deleted')
}
}
},*/
},
mounted() {
// change to target="_blank"
/* this.$nextTick(() => {
const links = document.querySelectorAll('.preview a');
links.forEach(link => {
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer'); // Sicherheitsmaßnahme
});
});*/
},
template: `
<div class="messages-detail-table">
<h4>Table Messages</h4>
<p>type_id: {{typeId}}</p>
<p>id: {{id}}</p>
<p>endpoint: {{endpoint}}</p>
<p>{{messageLayout}}</p>
<!-- {{statusText[0] }}
<hr>
{{$p.t('messages', 'unread')}} -->
<!-- {{statusText.0}} -->
<!-- <p v-for="(bezeichnung, key) in statusText" :key="key" :value="key">{{bezeichnung}}</p> -->
<!--View Studierendenverwaltung-->
<div v-if="messageLayout=='twoColumnsTableLeft'">
<!-- {{statusText}}-->
<core-filter-cmpt
ref="table"
:tabulator-options="tabulatorOptions"
table-only
:side-menu="false"
reload
new-btn-show
:new-btn-label="this.$p.t('global', 'nachricht')"
@click:new="actionNewNotiz"
>
</core-filter-cmpt>
<div class="row">
<!--table-->
<div class="col-sm-6 pt-6">
<core-filter-cmpt
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
:side-menu="false"
reload
new-btn-show
:new-btn-label="this.$p.t('global', 'nachricht')"
@click:new="actionNewMessage"
>
</core-filter-cmpt>
</div>
<!--preview wysiwyg-window-->
<div class="col-sm-6 pt-6">
<br><br><br><br>
<div ref="preview">
<div v-html="previewBody" class="p-3 border rounded overflow-scroll twoColumns"></div>
</div>
</div>
</div>
</div>
<!--View Infocenter-->
<div v-if="messageLayout=='listTableTop'">
<!--table-->
<div class="col-sm-12 pt-6">
<core-filter-cmpt
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
:side-menu="false"
reload
new-btn-show
:new-btn-label="this.$p.t('global', 'nachricht')"
@click:new="actionNewMessage"
>
</core-filter-cmpt>
</div>
<!--preview wysiwyg-window-->
<div class="col-sm-12">
<div ref="preview">
<div v-html="previewBody" class="p-3 border rounded overflow-scroll twoColumns"></div>
</div>
</div>
</div>
</div>
`
+13 -2
View File
@@ -17,14 +17,24 @@ export default {
required: true
},
showNew: Boolean,
showTable: Boolean
showTable: Boolean,
messageLayout: {
type: String,
default: 'twoColumnsTableLeft',
validator(value) {
return [
'twoColumnsTableLeft',
'listTableTop'
].includes(value)
}
},
},
data() {
return {}
},
template: `
<div class="core-messages h-100 pb-3">
<p>endpoint: {{endpoint}}</p>
<p>endpoint Messages.js: {{endpoint}}</p>
<div v-if="showNew">
<NewMessage
@@ -37,6 +47,7 @@ export default {
:type-id="typeId"
:id="id"
:endpoint="endpoint"
:messageLayout="messageLayout"
>
</TableMessages>
@@ -14,12 +14,11 @@ export default {
endpoint="$fhcApi.factory.messages.person"
type-id="person_id"
:id="modelValue.person_id"
messageLayout="listTableTop"
show-table
>
</core-messages>
</div>
`
};
+200
View File
@@ -37319,6 +37319,206 @@ array(
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'unread',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'ungelesen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'unread',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'read',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'gelesen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'read',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'archived',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'archiviert',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'archived',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'deleted',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'gelöscht',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'deleted',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'body',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Nachrichtentext',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Body',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'message_id',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Message ID',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Message ID',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'sender',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'SenderIn',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Sender',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'recipient',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'EmpfängerIn',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Recipient',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'senderId',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'SenderIn ID',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Sender ID',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'messages',
'phrase' => 'recipientId',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'EmpfängerIn ID',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Recipient ID',
'description' => '',
'insertvon' => 'system'
)
)
),
/////////// FHC4 Phrases Messages END ///////////
);