alarm history

This commit is contained in:
Alessandro Francia
2019-01-09 08:33:29 +01:00
parent 2b0f3a2e5d
commit 3734d2a2be
7 changed files with 410 additions and 58 deletions
@@ -704,6 +704,21 @@
}
}
}
.alarm-disable-box-right{
width: 496px;
height: 760px;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
z-index: 200;
background-color: #ffffffcc;
font-size: 24px;
font-weight: bold;
color: #4b4b4b;
}
.alarm-history-body-right{
width: 496px;
height: 760px;
@@ -875,6 +890,10 @@
border: 2px solid @color-darkish-blue;
color: @color-darkish-blue;
}
.message-box{
width: 370px;
}
}
}
}
+16
View File
@@ -4207,6 +4207,19 @@ footer .container button.big:before {
.alarm-history-container .alarm-history-body .alarm-history-body-left .alarm-history-table tr:nth-child(odd) {
background-color: rgba(23, 145, 255, 0.3);
}
.alarm-history-container .alarm-history-body .alarm-disable-box-right {
width: 496px;
height: 760px;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
z-index: 200;
background-color: #ffffffcc;
font-size: 24px;
font-weight: bold;
color: #4b4b4b;
}
.alarm-history-container .alarm-history-body .alarm-history-body-right {
width: 496px;
height: 760px;
@@ -4393,6 +4406,9 @@ footer .container button.big:before {
border: 2px solid #002680;
color: #002680;
}
.alarm-history-container .alarm-history-body .alarm-history-body-right .box-right .box-right-action .note .message-box {
width: 370px;
}
.hmi-container {
position: absolute;
left: 0;
@@ -63,7 +63,7 @@ export default class AlarmDetail extends Vue {
updateLimitation() {
if (this.limitationList > 3)
this.limitationList == 3;
this.limitationList = 3;
else
this.limitationList = Math.max(this.attaches.length, this.notes.length, 3);
}
@@ -139,6 +139,7 @@ export default class AlarmDetail extends Vue {
}
}
async saveNote(note) {
debugger
if (!note) return;
let result = await alarmsService.postNote(this.alarm.id, note.message);
@@ -6,6 +6,10 @@ import DatePicker from 'vue2-datepicker'
import { Watch } from "vue-property-decorator";
import { alarmsService } from "src/services/alarmsService";
import { AlarmModel } from "@/src/store";
import { ModalHelper } from "../../../components/modals";
import { getColorFromName, isDarkColor } from "src/_base/utils";
import moment from "moment";
@Component({
components: {
@@ -32,17 +36,46 @@ export default class AlarmHistory extends Vue {
interval?: Date[]
} = {
type: 0,
user: null,
title: null,
user: 1,
title: "",
};
users: any = [];
types: Array<string> = [
"NC","PLC"
];
users: Array<any> = [];
data: AlarmModel[] = []
paginationData: { firstDate: any, pages: number } = null;
selectedAlarm: AlarmModel = null;
selectedAttach: any = null;
selectedNote: any = null;
attaches = [];
notes = [];
limitationList: number = 3;
newAttach: any = null;
newNote: any = {};
enableModifyNote = true;
// get filteredAttaches() {
// return this.attaches.filter((v, idx) => idx < this.limitationList);
// }
get currentUser() {
return this.$store.state.currentUser;
}
get filteredAttaches() {
return this.attaches.filter((v, idx) => idx < this.limitationList);
}
get filteredNotes() {
return this.notes.filter((v, idx) => idx < this.limitationList);
}
@Watch("filter", { deep: true })
async filterChanged(n, o) {
debugger
let from = this.filter.interval && this.filter.interval.length ? this.filter.interval[0] : null;
let to = this.filter.interval && this.filter.interval.length ? this.filter.interval[1] : null;
@@ -50,7 +83,161 @@ export default class AlarmHistory extends Vue {
}
async mounted() {
var $this = this;
this.users = await loginService.getAllUsers();
this.paginationData = await alarmsService.getAlarmsData();
}
async onChange(e) {
this.newAttach = e.target.files[0];
let result = await alarmsService.postAttachment(this.selectedAlarm.alarmId, this.newAttach);
this.attaches.push(result.data);
// new MaintenanceService().uploadFile(this.selectedMaintenance, this.state.file);
}
user(id: number)
{
return this.users.find(x => x.id == id) || {};
}
async selectAlarm(alarm){
debugger
this.selectedAlarm = alarm;
this.attaches = await alarmsService.getAttachments(this.selectedAlarm.alarmId);
this.notes = await alarmsService.getNote(this.selectedAlarm.alarmId);
}
updateLimitation() {
debugger
if (this.limitationList > 3)
this.limitationList = 3;
else
this.limitationList = Math.max(this.attaches.length, this.notes.length, 3);
}
isimage(name) {
if (name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".pjpeg") || name.endsWith(".jfif") || name.endsWith(".pjp"))
return true
return false
}
ispdf(name) {
if (name.endsWith(".pdf") || name.endsWith(".pdfa"))
return true
return false
}
onClickSelectAttach(attach) {
this.selectedAttach = attach;
}
onClickSelectNote(note) {
this.selectedNote = note;
}
deselectNote() {
if (!this.enableModifyNote) return;
this.selectedNote = {};
}
onClickModifyNote(note) {
if (this.selectedNote == note) {
this.enableModifyNote = false;
this.isDisabled(note);
}
this.enableModifyNote = false;
this.selectedNote = note;
}
async openAttach(attach) {
if (attach) {
await alarmsService.OpenModal(attach, this.isimage(attach.fileName));
}
}
onClickCancelModifyNote() {
this.enableModifyNote = true;
}
async onClickDeleteNote(note){
debugger
let $this = this;
if(note){
ModalHelper.AskConfirm(this.$options.filters.localize("modal_confirm_delete", "Richiesta di conferma"),
this.$options.filters.localize("modal_confirm_delete_note", "Confermi la cancellazione della nota?"),
() => {
alarmsService.deleteNote(this.selectedAlarm.alarmId,note.id).then(response => {
let idx = $this.notes.indexOf(note);
$this.notes.splice(idx, 1);
});
}, null);
}
}
deleteAttach(attach) {
let $this = this;
if (attach) {
ModalHelper.AskConfirm(this.$options.filters.localize("modal_confirm_delete", "Richiesta di conferma"),
this.$options.filters.localize("modal_confirm_delete_attachment", "Confermi la cancellazione dell'allegato?"),
() => {
alarmsService.deleteAttachments(attach.attachmentId).then(response => {
let idx = $this.attaches.indexOf(attach);
$this.attaches.splice(idx, 1);
});
}, null);
}
}
async saveModifyNoteMaintenance(note){
debugger
if(!note){
this.enableModifyNote = true;
return;
}
let result = await alarmsService.putNote(this.selectedAlarm.alarmId, note.id, note.message);
for(let index in this.notes){
let obj = this.notes[index];
if(obj.id == note.id){
this.notes.splice(parseInt(index),1);
this.notes.push(result);
this.enableModifyNote = true;
}
}
}
async saveNote(note) {
debugger
if (!note) return;
let result = await alarmsService.postNote(this.selectedAlarm.alarmId, note.message);
this.notes.push(result);
this.newNote = {};
}
isDisabled(note) {
if (this.selectedNote && this.selectedNote.id == note.id && !this.enableModifyNote) {
return false;
}
else {
return true;
}
}
getColor(nome, cognome) {
return getColorFromName(nome, cognome);
}
isDarkColor(color) {
return isDarkColor(color);
}
convertDate(date) {
return moment(date).format('L');
}
convertDateToTime(date) {
return moment(date).format('LT');
}
}
@@ -48,56 +48,60 @@
<tr>
<th>{{'alarms_history.ID' | localize("ID")}}</th>
<th>{{'alarms_history.Tipo' | localize("Tipo") }}</th>
<th>{{'alarms_history.Titolo' | localize("Titolo Allarme") }}</th>
<th>{{'alarms_history.Descrizione'| localize("Descrizione")}}</th>
<th>{{'alarms_history.Start'| localize("Start")}}</th>
<th>{{'alarms_history.Stop'| localize("Stop")}}</th>
<th>{{'alarms_history.TTotale'| localize("T.Totale")}}</th>
<th>{{'alarms_history.Data'| localize("Data")}}</th>
<th>{{'alarms_history.Utente'| localize("Utente")}}</th>
</tr>
</thead>
<tbody class="scrollable">
<tr v-for="(row,index) in data" :key="index">
{{row}}
<td colspan="1">001</td>
<td colspan="1">Allarme</td>
<td colspan="1">Mandrino 1 non bloccato</td>
<td colspan="1">15:24:53</td>
<td colspan="1">15:24:53</td>
<td colspan="1">15:24:53</td>
<td colspan="1">User01</td>
<tr v-for="(row,index) in data" :key="index" @click="selectAlarm(row)">
<td colspan="1">{{row.id}}</td>
<td colspan="1">{{types[row.type]}}</td>
<td colspan="1">{{row.title}}</td>
<td colspan="1">{{row.description}}</td>
<td colspan="1">{{row.timeStamp | date('DD-MM-YYYY HH:mm:ss')}}</td>
<td colspan="1">
<span v-for="(iduser, index) in row.users" :key="iduser">
{{user(iduser).username}}
<text v-if="index < row.users.length -1">, </text>
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="alarm-history-body-right">
<!-- <div class="box-right scrollable">
<div class="box-right scrollable" v-if="selectedAlarm">
<div class="box-right-info">
<div class="box-right-info-header">
<div class="title">
<span>#### {{'alarm_history_box_right_info_description_machine_not_calibrated' | localize("La macchina non è tarata")}}La macchina non è tarata</span>
<span>{{selectedAlarm.title}}</span>
</div>
<div class="subtitle">
<label>3 AUX</label>
<label>{{types[selectedAlarm.type]}}</label>
</div>
<div class="date">
<label>01/01/2017 - 12:03</label>
<label>{{selectedAlarm.timeStamp | date('DD-MM-YYYY HH:mm:ss')}}</label>
</div>
</div>
<div class="box-right-info-body">
<span>
{{'alarm_history_box_right_info_first_description' | localize("Lorem ipsum dolor sit amet, consectetur")}}
{{'alarm_history_box_right_info_second_description' | localize("adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna.")}}
<span v-if="selectedAlarm.description">
{{selectedAlarm.description}}
</span>
<span v-if="!selectedAlarm.description">
{{'alarm_history_description_null' | localize("La descrizione non è stata inserita.")}}
</span>
</div>
<div class="box-right-info-footer">
<!-- <div class="box-right-info-footer">
<span>
<label>{{'alarm_history_box_right_info_footer_state' | localize("Stato:")}}</label> attivo
</span>
</div>
</div> -->
</div>
<div class="box-right-action">
<div class="wizard">
<!-- <div class="wizard">
<div class="user-help">
<i class="group"></i>
<div class="detail">
@@ -117,38 +121,137 @@
<button
class="btn btn-success"
>{{'alarm_history_manual_btn_refresh' | localize("Refresh")}}</button>
</div>
</div> -->
<!-- <accordion :title="'Allegati'" :counter="attaches.length">
<div class="dropdown">
<div class="filename" v-for="a in filteredAttaches" :key="a.id" :class="{selected: selectedAttach == a}" @click="onClickSelectAttach(a)">
<i class="fa fa-file-text-o" v-if="!isimage(a.fileName) && !ispdf(a.fileName)"></i>
<i class="fa fa-file-image-o" v-if="isimage(a.fileName)"></i>
<i class="fa fa-file-pdf-o" v-if="ispdf(a.fileName)"></i>
<span>{{a.fileName}}</span>
<div class="right">
<button class="btn-hidden" v-if="selectedAttach == a" @click="openAttach(a)"><i class="fa fa-file-o"></i></button>
<button class="btn-hidden" v-if="selectedAttach == a && a.userId == currentUser.id" @click="deleteAttach(a)"><i class="fa fa-trash" ></i></button>
</div>
</div>
<div class="allattach" v-if="attaches.length>3">
<button class="btn-hidden" @click="updateLimitation(limitationList)">
<span v-if="limitationList > 3">{{'maintenance_card_btn_hide_all_attach' | localize("Nascondi tutti gli allegati")}}</span>
<span v-if="limitationList < attaches.length">{{'maintenance_card_btn_view_all_attach' | localize("Mostra tutti gli allegati")}}</span>
</button>
</div>
<div class="addattach">
<div class="group-button-add-attach"><label for="input">{{'alarm_btn_add_attach' | localize("Aggiungi un allegato")}}<label for="input" class="btn"><i class="fa fa-plus"><input id="input" type="file" accept="application/pdf,image/jpeg,image/png" @change="onChange" style="display: none"/></i></label></label></div>
</div>
</div>
</accordion>
<accordion :title="'Note'" :counter="notes.length">
<div class="dropdown">
<div class="all-message-box scrollable_auto">
<div class="message-box" v-for="(n, index) in filteredNotes" :key="index" @click="onClickSelectNote(n)">
<div class="message-box-header">
<div v-if="currentUser && n.user.username != currentUser.username" :class="{'colorWhite':isDarkColor(getColor(n.user.lastName,n.user.firstName))}" :style="{'background-color':getColor(n.user.lastName,n.user.firstName) }" class="avatar">{{n.user.firstName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}{{n.user.lastName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}</div>
<textarea :disabled="isDisabled(n)" class="text-message" v-model="n.message"></textarea>
<div v-if="currentUser && n.user.username == currentUser.username" :class="{'colorWhite':isDarkColor(getColor(n.user.lastName,n.user.firstName))}" :style="{'background-color':getColor(n.user.lastName,n.user.firstName) }" class="avatar"> {{n.user.firstName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}{{n.user.lastName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}</div>
</div>
<div class="message-box-body" :class="{'my':(currentUser && n.user.username == currentUser.username)}">
<label class="text-date">{{'maintenance_card_label_date_timestamp' | localize("Aggiunta il %s alle %s",convertDate(n.dateTime),convertDateToTime(n.dateTime))}}</label>
</div>
<div class="groupbutton" :class="{'enablemodify':!enableModifyNote}">
<button class="btn-hidden" v-if="selectedNote == n && enableModifyNote && currentUser && n.user.username == currentUser.username" @click="onClickModifyNote(n)"><i class="fa fa-pencil-square-o"></i></button>
<button class="btn-hidden" v-if="selectedNote == n && enableModifyNote && currentUser && n.user.username == currentUser.username" @click="onClickDeleteNote(n)"><i class="fa fa-trash" ></i></button>
<div class="modify-padding">
<button class="btn" v-if="selectedNote == n && !enableModifyNote" @click="onClickCancelModifyNote">{{'maintenance_card_btn_cancel_modify_note' | localize("Cancel")}}</button>
<button class="btn" v-if="selectedNote == n && !enableModifyNote" @click="saveModifyNoteMaintenance(n)">{{'maintenance_card_btn_save_modify_note' | localize("Save")}}</button>
</div>
</div>
</div>
</div>
<div class="allnotes">
<button class="btn-hidden" @click="updateLimitation(limitationList)">
<span v-if="limitationList > 3">{{'maintenance_card_btn_hide_all_note' | localize("Nascondi tutte le note")}}</span>
<span v-if="limitationList < notes.length">{{'maintenance_card_btn_view_all_note' | localize("Mostra tutte le note")}}</span>
</button>
</div>
<div class="addnote" @click="deselectNote()">
<div class="addnote-header">
<textarea @focus="deselectNote()" v-validate.initial="{required: true}" class="text-add-note" v-model="newNote.message" :disabled="!enableModifyNote"></textarea>
<div class="avatar" v-if="currentUser" :class="{'colorWhite':isDarkColor(getColor(currentUser.lastName,currentUser.firstName))}" :style="{'background-color':getColor(currentUser.lastName,currentUser.firstName) }" >{{currentUser.firstName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}{{currentUser.lastName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}</div>
</div>
<div class="addnote-buttons">
<button class="btn" :disabled="!enableModifyNote" @click="saveNote(newNote)">{{'maintenance_card_btn_save_note' | localize("Save")}}</button>
</div>
</div>
</div>
</accordion> -->
<div class="attach">
<accordion :title="'Allegati'" :counter="5">
<div class="filename">
<i class="fa fa-file-text-o" v-if="false"></i>
<i class="fa fa-file-image-o" v-if="false"></i>
<i class="fa fa-file-pdf-o" v-if="true"></i>
<span>NomeFile.pdf</span>
<div class="right">
<button class="btn-hidden">
<i class="fa fa-file-o"></i>
</button>
<button class="btn-hidden">
<i class="fa fa-trash"></i>
</button>
<accordion :title="'Allegati'" :counter="attaches.length">
<div class="dropdown">
<div class="filename" v-for="a in filteredAttaches" :key="a.id" :class="{selected: selectedAttach == a}" @click="onClickSelectAttach(a)">
<i class="fa fa-file-text-o" v-if="!isimage(a.fileName) && !ispdf(a.fileName)"></i>
<i class="fa fa-file-image-o" v-if="isimage(a.fileName)"></i>
<i class="fa fa-file-pdf-o" v-if="ispdf(a.fileName)"></i>
<span>{{a.fileName}}</span>
<div class="right">
<button class="btn-hidden" v-if="selectedAttach == a" @click="openAttach(a)"><i class="fa fa-file-o"></i></button>
<button class="btn-hidden" v-if="selectedAttach == a && a.userId == currentUser.id" @click="deleteAttach(a)"><i class="fa fa-trash" ></i></button>
</div>
</div>
<div class="allattach" v-if="attaches.length>3">
<button class="btn-hidden" @click="updateLimitation(limitationList)">
<span v-if="limitationList > 3">{{'maintenance_card_btn_hide_all_attach' | localize("Nascondi tutti gli allegati")}}</span>
<span v-if="limitationList < attaches.length">{{'maintenance_card_btn_view_all_attach' | localize("Mostra tutti gli allegati")}}</span>
</button>
</div>
<div class="addattach">
<div class="group-button-add-attach"><label for="input">{{'alarm_btn_add_attach' | localize("Aggiungi un allegato")}}<label for="input" class="btn"><i class="fa fa-plus"><input id="input" type="file" accept="application/pdf,image/jpeg,image/png" @change="onChange" style="display: none"/></i></label></label></div>
</div>
</div>
<div class="allattach">
<button class="btn-hidden">
<span>{{'alarm_history_allattach_btn' | localize("Mostra tutti gli allegati")}}</span>
</button>
</div>
<div class="item text-success">
<strong>{{'alarm_history_allattach_strong_label_add_attach' | localize("Aggiungi un allegato")}}</strong>
<button class="btn text-22">
<i class="fa fa-plus"></i>
</button>
</div>
</accordion>
</div>
<div class="note">
<accordion :title="'Note'" :counter="4">
<accordion :title="'Note'" :counter="notes.length">
<div class="dropdown">
<div class="all-message-box scrollable_auto">
<div class="message-box" v-for="(n, index) in filteredNotes" :key="index" @click="onClickSelectNote(n)">
<div class="message-box-header">
<div v-if="currentUser && n.user.username != currentUser.username" :class="{'colorWhite':isDarkColor(getColor(n.user.lastName,n.user.firstName))}" :style="{'background-color':getColor(n.user.lastName,n.user.firstName) }" class="avatar">{{n.user.firstName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}{{n.user.lastName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}</div>
<textarea :disabled="isDisabled(n)" class="text-message" v-model="n.message"></textarea>
<div v-if="currentUser && n.user.username == currentUser.username" :class="{'colorWhite':isDarkColor(getColor(n.user.lastName,n.user.firstName))}" :style="{'background-color':getColor(n.user.lastName,n.user.firstName) }" class="avatar"> {{n.user.firstName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}{{n.user.lastName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}</div>
</div>
<div class="message-box-body" :class="{'my':(currentUser && n.user.username == currentUser.username)}">
<label class="text-date">{{'alarm_history_label_date_timestamp' | localize("Aggiunta il %s alle %s",convertDate(n.dateTime),convertDateToTime(n.dateTime))}}</label>
</div>
<div class="groupbutton" :class="{'enablemodify':!enableModifyNote}">
<button class="btn-hidden" v-if="selectedNote == n && enableModifyNote && currentUser && n.user.username == currentUser.username" @click="onClickModifyNote(n)"><i class="fa fa-pencil-square-o"></i></button>
<button class="btn-hidden" v-if="selectedNote == n && enableModifyNote && currentUser && n.user.username == currentUser.username" @click="onClickDeleteNote(n)"><i class="fa fa-trash" ></i></button>
<div class="modify-padding">
<button class="btn" v-if="selectedNote == n && !enableModifyNote" @click="onClickCancelModifyNote">{{'alarm_history_btn_cancel_modify_note' | localize("Cancel")}}</button>
<button class="btn" v-if="selectedNote == n && !enableModifyNote" @click="saveModifyNoteMaintenance(n)">{{'alarm_history_btn_save_modify_note' | localize("Save")}}</button>
</div>
</div>
</div>
</div>
<div class="allnotes">
<button class="btn-hidden" @click="updateLimitation(limitationList)">
<span v-if="limitationList > 3">{{'alarm_history_hide_allnote_btn' | localize("Nascondi tutte le note")}}</span>
<span v-if="limitationList < notes.length">{{'alarm_history_allnote_btn' | localize("Mostra tutte le note")}}</span>
</button>
</div>
<div class="addnote" @click="deselectNote()">
<div class="addnote-header">
<textarea @focus="deselectNote()" v-validate.initial="{required: true}" class="text-add-note" v-model="newNote.message" :disabled="!enableModifyNote"></textarea>
<div class="avatar" v-if="currentUser" :class="{'colorWhite':isDarkColor(getColor(currentUser.lastName,currentUser.firstName))}" :style="{'background-color':getColor(currentUser.lastName,currentUser.firstName) }" >{{currentUser.firstName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}{{currentUser.lastName.split(' ').map(function (s) { return s.charAt(0); }).join('')}}</div>
</div>
<div class="addnote-buttons">
<button class="btn" :disabled="!enableModifyNote" @click="saveNote(newNote)">{{'alarm_history__btn_save_note' | localize("Save")}}</button>
</div>
</div>
</div>
</accordion>
<!-- <accordion :title="'Note'" :counter="4">
<div class="filename">
<i class="fa fa-file-text-o" v-if="false"></i>
<i class="fa fa-file-image-o" v-if="false"></i>
@@ -174,10 +277,13 @@
<i class="fa fa-plus"></i>
</button>
</div>
</accordion>
</accordion> -->
</div>
</div>
</div>-->
</div>
<div class="alarm-disable-box-right" v-if="!selectedAlarm">
<label>{{'alarm_history_label_disable-alarms' | localize("Seleziona un'allarme...")}}</label>
</div>
</div>
</div>
</div>
+23 -3
View File
@@ -15,10 +15,13 @@ export class AlarmsService extends baseRestService {
let types = [];
if (user) users.push(user);
if (type) types.push(type);
// if (type) types.push(type);
if(type != null || type != undefined){
types.push(type);
}
let result = await this.Post<AlarmModel[]>(this.BASE_URL + "paginated",
{
"page": page +1,
"page": page,
"pageSize": pagesize,
"title": title,
"type": types,
@@ -26,7 +29,24 @@ export class AlarmsService extends baseRestService {
"endDate": toDate,
"userIds": users,
language: "en"
}, true);
}
// {
// "page": 0,
// "pageSize": 100,
// "title": "",
// "type": [
// 0,
// 1
// ],
// "startDate": "2019-01-03T23:00:00.000Z",
// "endDate": "2019-01-14T10:01:01.686Z",
// "userIds": [
// 1,
// -1
// ],
// "language": "en"
// }
, true);
debugger
return result;
}
+3
View File
@@ -15,9 +15,12 @@ export interface AlarmModel {
uid?: string;
title: string;
description: string;
alarmId?: number;
date: Date;
restorationIsActive: boolean;
timeStamp?: Date;
source?: string;
process?: number;