Conflicts resolved

This commit is contained in:
Ivymaster
2026-10-22 11:45:54 +02:00
16 changed files with 194 additions and 59 deletions
+8 -6
View File
@@ -237,7 +237,7 @@ class KalenderLib
WHERE tbl_betriebsmittel_kalender.eindeutige_kalender_gruppen_id = tbl_kalender.eindeutige_kalender_gruppen_id
) AS has_assigned_resources"
]);
$data = $this->_loadFilteredBasePlan($start_date, $end_date);
return $this->_mapEvents($data, $collisionCheck, $maxDailyEventLimit);
@@ -415,7 +415,7 @@ class KalenderLib
if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
'message' => $this->_ci->phraseslib->t('ui', 'entry_marked_for_deletion_not_editable'),
'errorCode' => 'entry_not_editable'
]);
}
@@ -466,7 +466,7 @@ class KalenderLib
if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
'message' => $this->_ci->phraseslib->t('ui', 'entry_marked_for_deletion_not_editable'),
'errorCode' => 'entry_not_editable'
]);
}
@@ -1077,7 +1077,7 @@ class KalenderLib
if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
'message' => $this->_ci->phraseslib->t('ui', 'entry_marked_for_deletion_not_editable'),
'errorCode' => 'entry_not_editable'
]);
}
@@ -1153,7 +1153,7 @@ class KalenderLib
if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
'message' => $this->_ci->phraseslib->t('ui', 'entry_marked_for_deletion_not_editable'),
'errorCode' => 'entry_not_editable'
]);
}
@@ -1497,6 +1497,7 @@ class KalenderLib
tbl_organisationseinheit.bezeichnung as organisationseinheit,
lehrfach.kurzbz AS lehrfach_kurzbz,
lehrfach.bezeichnung AS lehrfach_bezeichnung,
lehrfach.kurzbz AS lehrfach_kurz_bezeichnung,
lehrfach.farbe,
COALESCE(orginasator.uid, tbl_lehreinheitmitarbeiter.mitarbeiter_uid) as mitarbeiter_uid,
COALESCE(reservierung_person.vorname, tbl_person.vorname) as vorname,
@@ -1704,7 +1705,6 @@ class KalenderLib
'datum' => $von->format('Y-m-d'),
'isostart' => $von->format('c'),
'isoend' => $bis->format('c'),
'tooltip' => 'tip',
'status_kurzbz' => $row->status_kurzbz,
'ort_kurzbz' => [],
'ort_infos' => [],
@@ -1740,6 +1740,7 @@ class KalenderLib
$events[$id]->lehreinheit_infos[] = ['lehreinheit_id' => $row->lehreinheit_id,
'anmerkung' => (isset($row->le_anmerkung) ? $row->le_anmerkung : ''),
'lehrfach_bezeichnung' => (isset($row->lehrfach_bezeichnung) ? $row->lehrfach_bezeichnung : ''),
'lehrfach_kurz_bezeichnung' => (isset($row->lehrfach_kurz_bezeichnung) ? $row->lehrfach_kurz_bezeichnung : ''),
'studiensemester_kurzbz' => (isset($row->le_studiensemester_kurzbz) ? $row->le_studiensemester_kurzbz : ''),
];
}
@@ -1750,6 +1751,7 @@ class KalenderLib
$events[$id]->lehrveranstaltung_infos[] = ['lehrveranstaltung_id' => $row->lehrveranstaltung_id,
'lehrform_kurzbz' => (isset($row->lehrform_kurzbz) ? $row->lehrform_kurzbz : ''),
'lehrfach_bezeichnung' => (isset($row->lehrfach_bezeichnung) ? $row->lehrfach_bezeichnung : ''),
'lehrfach_kurz_bezeichnung' => (isset($row->lehrfach_kurz_bezeichnung) ? $row->lehrfach_kurz_bezeichnung : ''),
'oe_bezeichnung' => (isset($row->organisationseinheit) ? $row->organisationseinheit : ''),
'studiensemester_kurzbz' => (isset($row->le_studiensemester_kurzbz) ? $row->le_studiensemester_kurzbz : ''),
];
@@ -53,12 +53,14 @@ class LectureCollisionCheck implements ICollisionCheck
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
$grouped = [];
$this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id, current_lehreinheit_ma.mitarbeiter_uid, other_kalender.von, other_kalender.kalender_id as other_kalender_id');
$this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id, current_lehreinheit_ma.mitarbeiter_uid, current_mitarbeiter.kurzbz, other_kalender.von, other_kalender.kalender_id as other_kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit current_kalender_le', 'current_kalender_le.kalender_id = tbl_kalender.kalender_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter current_lehreinheit_ma', 'current_lehreinheit_ma.lehreinheit_id = current_kalender_le.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter other_lehreinheithreinheit_ma', 'other_lehreinheithreinheit_ma.mitarbeiter_uid = current_lehreinheit_ma.mitarbeiter_uid');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit other_kalender_le', 'other_kalender_le.lehreinheit_id = other_lehreinheithreinheit_ma.lehreinheit_id');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender other_kalender', 'other_kalender.kalender_id = other_kalender_le.kalender_id');
$this->_ci->KalenderModel->addJoin('public.tbl_mitarbeiter current_mitarbeiter', 'current_mitarbeiter.mitarbeiter_uid = current_lehreinheit_ma.mitarbeiter_uid');
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
@@ -84,7 +86,7 @@ class LectureCollisionCheck implements ICollisionCheck
foreach (getData($result) as $row)
{
$grouped[$row->kalender_id][] = [
'message' => $this->_ci->phraseslib->t('ui', 'ma_le_kollision') . ': ' . $row->mitarbeiter_uid,
'message' => $this->_ci->phraseslib->t('ui', 'ma_le_kollision') . ': ' . ($row->kurzbz ? $row->kurzbz . ' [' . $row->mitarbeiter_uid . ']' : $row->mitarbeiter_uid),
'kalender_id' => $row->other_kalender_id,
'datum' => $row->von,
];
@@ -43,6 +43,7 @@ class VerbandCollisionCheck implements ICollisionCheck
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
AND (
current_lehreinheitguppe.verband IS NULL
OR other_lehreinheitguppe.verband IS NULL
OR (
current_lehreinheitguppe.verband = other_lehreinheitguppe.verband
AND (current_lehreinheitguppe.gruppe IS NULL OR other_lehreinheitguppe.gruppe IS NULL OR current_lehreinheitguppe.gruppe = other_lehreinheitguppe.gruppe)
@@ -99,6 +100,7 @@ class VerbandCollisionCheck implements ICollisionCheck
{
$sql_gruppen = "
SELECT
DISTINCT (current_kalender.kalender_id),
other_kalender.von,
other_kalender.bis,
COALESCE(
@@ -246,6 +248,7 @@ class VerbandCollisionCheck implements ICollisionCheck
AND other_event_teilnehmer.gruppe_kurzbz IS NULL
AND (
current_event_teilnehmer.verband IS NULL
OR other_event_teilnehmer.verband IS NULL
OR (
current_event_teilnehmer.verband = other_event_teilnehmer.verband
AND (current_event_teilnehmer.gruppe IS NULL OR other_event_teilnehmer.gruppe IS NULL OR current_event_teilnehmer.gruppe = other_event_teilnehmer.gruppe)
@@ -312,7 +315,7 @@ class VerbandCollisionCheck implements ICollisionCheck
$placeholders = implode(',', array_fill(0, count($kalender_ids), '?'));
$sql = "
SELECT DISTINCT ON (current_kalender.kalender_id) current_kalender.kalender_id,
SELECT DISTINCT current_kalender.kalender_id,
COALESCE(
other_lehreinheitguppe.gruppe_kurzbz,
UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
@@ -367,6 +370,7 @@ class VerbandCollisionCheck implements ICollisionCheck
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
AND (
current_lehreinheitguppe.verband IS NULL
OR other_lehreinheitguppe.verband IS NULL
OR (
current_lehreinheitguppe.verband = other_lehreinheitguppe.verband
AND (current_lehreinheitguppe.gruppe IS NULL OR other_lehreinheitguppe.gruppe IS NULL OR current_lehreinheitguppe.gruppe = other_lehreinheitguppe.gruppe)
+6 -1
View File
@@ -286,4 +286,9 @@ body {
.timepicker-row {
display: flex;
align-items: center;
}
}
.event-dialog-location {
overflow-wrap: anywhere;
}
@@ -1,7 +1,7 @@
import {CoreFilterCmpt} from "../../../../components/filter/Filter.js";
import {CoreFilterCmpt} from "../../../filter/Filter.js";
import BsModal from '../../../Bootstrap/Modal.js';
import FormInput from "../../../Form/Input.js";
import CoreTag from '../../../../components/Tag/Tag.js';
import CoreTag from '../../../Tag/Tag.js';
import {
buildTagHeaderFilterExpression,
@@ -59,7 +59,8 @@ export default {
},
},
tagEndpoint: ApiTempusTag,
selectedColumnValues: []
selectedColumnValues: [],
pendingSelection: null
}
},
computed: {
@@ -170,13 +171,41 @@ export default {
tableBuilt() {
this.$refs.tableViewTable.tabulator.updateColumnDefinition('tags', {
headerFilterParams: this.tagHeaderFilterParams(),
});;
});
},
rememberSelection() {
const tab = this.$refs.tableViewTable?.tabulator;
this.pendingSelection = (tab?.getSelectedData() ?? [])
.map(r => r.eindeutige_kalender_gruppen_id);
},
clearPendingSelection() {
this.pendingSelection = null;
},
restoreSelection() {
const ids = this.pendingSelection;
if (!ids?.length) return;
const tab = this.$refs.tableViewTable?.tabulator;
if (!tab) return;
const rows = tab.getRows().filter(row =>
ids.includes(row.getData().eindeutige_kalender_gruppen_id)
);
if (!rows.length) return;
this.clearPendingSelection();
tab.selectRow(rows);
tab.scrollToRow(rows[0], "center", false).catch(() => {});
},
openModal() {
let selected = this.$refs.tableViewTable?.tabulator?.getSelectedData() ?? [];
if (!selected.length)
return;
this.rememberSelection();
this.tableActions?.openRaumauswahl(selected)
},
async deleteSelected() {
@@ -203,14 +232,20 @@ export default {
let isConfirmed = await this.$fhcAlert.confirmDelete();
if (!isConfirmed) return;
await this.tableActions?.deleteEntries(selected)
return;
}
else if (this.actionSelect === 'toLecturer')
{
await this.tableActions?.syncToLecturer(selected)
}
else if (this.actionSelect === 'toStudent')
{
await this.tableActions?.syncToStudent(selected)
try {
if (this.actionSelect === 'toLecturer')
{
await this.tableActions?.syncToLecturer(selected)
}
else if (this.actionSelect === 'toStudent')
{
await this.tableActions?.syncToStudent(selected)
}
} catch (e) {
this.clearPendingSelection();
throw e;
}
},
async fetchAssignedTagsByCalender(calendarGroupId) {
@@ -362,6 +397,7 @@ export default {
:tabulator-events="[{ event: 'tableBuilt', handler: tableBuilt },
{ event: 'rowSelectionChanged', handler: updateSelectedRows },
{ event: 'dataLoaded', handler: dataLoadedHandler },
{ event: 'dataProcessed', handler: restoreSelection },
{ event: 'dataFiltered', handler: dataFilteredHandler },
{ event: 'columnWidth', handler: columnWidthHandler },
{ event: 'rowClick', handler: onRowClick }
+20 -3
View File
@@ -127,6 +127,10 @@ export default {
type: Boolean,
default: true,
},
canAccessSettingsView: {
type: Boolean,
default: true,
},
canToggleCollisionCheck: {
type: Boolean,
default: true,
@@ -492,17 +496,30 @@ export default {
</div>
<div
v-if="isEventDraggingEnabled"
class="d-flex align-items-center gap-2 "
class="d-flex align-items-center gap-2"
style="cursor:grab"
v-draggable:move.noimage="{ type: 'reservierung', id: null, orig: {} }"
data-cy="reservationDragHandle"
@click.stop="$emit('open-reservierung')"
>
<i
class="fa-solid fa-calendar-plus text-primary"
style="cursor:pointer"
@click.stop="$emit('open-reservierung')"
></i>
<span>Reservierung</span>
</div>
<div
v-if="canAccessSettingsView"
class="d-flex align-items-center gap-2"
style="cursor:pointer"
data-bs-toggle="modal"
data-bs-target="#configModal"
>
<i
class="fa-solid fa-gear text-primary"
style="cursor:pointer"
></i>
<span class="form-check-label">{{ $p.t('ui/settings') }}</span>
</div>
<div
v-if="canToggleCollisionCheck"
class="d-flex align-items-center gap-2"
+1
View File
@@ -69,6 +69,7 @@ export function idTagFormatter (id, tagData, tagComponent, typeId, semesterStart
tagsToShow.forEach(tag => {
let tagElement = document.createElement('span');
tagElement.style.cursor = 'pointer';
if(tag.automatisiert)
tagElement.innerHTML = "<i class='fa-solid fa-lock'></i> " + tag.beschreibung;
else
@@ -38,22 +38,24 @@ export default {
template: /*html*/`
<tr v-if="collisions.length">
<th>
<i class="fa-solid fa-triangle-exclamation text-danger"></i>
<i class="fa-solid fa-xl fa-triangle-exclamation text-danger"></i>
{{ $p.t('ui','collision') }}:
</th>
<td>
<div v-for="(collision, index) in collisions" :key="collision.kalender_id ?? index" class="d-block">
<a
v-if="isJumpable(collision)"
href="#"
@click.prevent="jumpTo(collision)"
>
{{ collision.message }}
</a>
<template v-else>
{{ collision.message }}
</template>
</div>
<div class="overflow-auto" style="max-height: 15vh;">
<div v-for="(collision, index) in collisions" :key="collision.kalender_id ?? index" class="d-block">
<a
v-if="isJumpable(collision)"
href="#"
@click.prevent="jumpTo(collision)"
>
{{ collision.message }}
</a>
<template v-else>
{{ collision.message }}
</template>
</div>
</div>
</td>
</tr>`
};
+20 -4
View File
@@ -45,8 +45,24 @@ export default {
openRaumvorschlag() {
this.$refs.raumModal.show(this.event);
},
addToRoomFilter(ort) {
this.modalActions?.addToFilter({ ort_kurzbz: ort }, 'ort');
addToRoomFilter(ort, addOnlyIfExists = false) {
this.modalActions?.addToFilter({ ort_kurzbz: ort }, 'ort', addOnlyIfExists);
},
updateRooms(orte)
{
if (Array.isArray(orte))
{
if (orte.length < 1)
{
this.modalActions?.addToFilter([], 'ort', true);
}
else
{
orte.forEach((ort) => this.addToRoomFilter(ort, true));
}
}
this.reload();
}
},
template: /*html*/`
@@ -70,10 +86,10 @@ export default {
></i>
{{ ort }}
</div>
<div>
<div class="event-dialog-location">
{{event.location}}
</div>
<raumauswahl-modal ref="raumModal" @saved="reload()" />
<raumauswahl-modal ref="raumModal" @saved="updateRooms" />
</td>
</tr>`
};
+5 -4
View File
@@ -59,10 +59,11 @@ export default {
let el = this.$refs.tagWrapper;
if (!el) return;
const tagData = this.tags.map(t => ({
...t,
notiz_id: t.id,
bezeichnung: t.beschreibung,
const tagData = this.tags.map(tag => ({
...tag,
notiz_id: tag.id,
text: tag.notiz,
bezeichnung: tag.beschreibung,
}));
el.replaceChildren(
@@ -97,8 +97,8 @@ export default {
return;
}
this.$emit('saved', this.selectedRooms.map((room) => room.ort_kurzbz));
this.hide();
this.$emit('saved');
return;
}
let orte = {};
@@ -119,8 +119,8 @@ export default {
);
}
this.$emit("saved", this.selectedRooms.map((room) => room.ort_kurzbz));
this.hide();
this.$emit("saved");
},
},
watch: {
@@ -170,7 +170,7 @@ export default {
<div class="event-text" v-tooltip="tooltipString">
<span class="event-topic">{{ topicString }}</span>
<span
class="event-place"
class="event-place text-break"
data-cy="calendar-event-room"
>{{ ortString }}</span>
<span v-if="gruppeString" class="event-gruppe">{{ gruppeString }}</span>
@@ -112,7 +112,6 @@ export default {
<tbody>
<kollision-row :event="event" />
<zeit-row ref="zeit" :event="event" />
<raum-row :event="event" />
<tr>
<th>{{$p.t('global','anzahl')}} {{$p.t('global','students')}}:
</th>
@@ -120,6 +119,8 @@ export default {
{{anzahlSchwund}} ({{anzahl}})
</td>
</tr>
<raum-row :event="event" />
<tr>
<th>{{
$p.t('lehre','lehrveranstaltung')?
@@ -130,7 +131,7 @@ export default {
<div v-for="lehrveranstaltung in event.lehrveranstaltung_infos" class="d-block">
<a v-if="lvLinks.lvverwaltung[lehrveranstaltung.lehrveranstaltung_id]" target='_blank' :aria-label="$p.t('lehre','lehrveranstaltung')" :title="$p.t('lehre','lehrveranstaltung')" :href="lvLinks.lvverwaltung[lehrveranstaltung.lehrveranstaltung_id]"><i class="fa fa-arrow-up-right-from-square me-1" aria-hidden="true"></i></a>
<a v-if="lvLinks.vilesci[lehrveranstaltung.lehrveranstaltung_id]" target='_blank' :aria-label="$p.t('lehre','lvInfoBearbeiten')" :title="$p.t('lehre','lehrveranstaltung')" :href="lvLinks.vilesci[lehrveranstaltung.lehrveranstaltung_id]"><i class="fa fa-pen-to-square me-1" aria-hidden="true"></i></a>
<span v-tooltip="lehrveranstaltung.oe_bezeichnung">{{'('+ lehrveranstaltung.lehrform_kurzbz + ') ' + lehrveranstaltung.lehrfach_bezeichnung }} </span>
<span v-tooltip="lehrveranstaltung.oe_bezeichnung">{{'('+ lehrveranstaltung.lehrform_kurzbz + ') ' + '[' + lehrveranstaltung.lehrfach_kurz_bezeichnung + '] ' + lehrveranstaltung.lehrfach_bezeichnung }} </span>
</div>
</td>
</tr>
@@ -143,7 +144,7 @@ export default {
<td>
<div v-for="lehreinheit in event.lehreinheit_infos" class="d-block">
<a v-if="leLinks[lehreinheit.lehreinheit_id]" target='_blank' :aria-label="$p.t('lehre','lehreinheit')" :title="$p.t('lehre','lehreinheit')" :href="leLinks[lehreinheit.lehreinheit_id]"><i class="fa fa-arrow-up-right-from-square me-1" aria-hidden="true"></i></a>
<span v-tooltip="lehreinheit.anmerkung">{{lehreinheit.lehrfach_bezeichnung}}</span>
<span v-tooltip="lehreinheit.anmerkung">[{{lehreinheit.lehrfach_kurz_bezeichnung}}] {{lehreinheit.lehrfach_bezeichnung}}</span>
</div>
</td>
</tr>
@@ -159,7 +160,7 @@ export default {
<a v-if="lektorenLinks[lektor.kurzbz]" target='_blank' :aria-label="$p.t('lehre','lektor')" :title="$p.t('lehre','lektor')" :href="lektorenLinks[lektor.kurzbz]"><i class="fa fa-arrow-up-right-from-square me-1" aria-hidden="true"></i></a>
<i class="fa fa-filter" @click="addLecturerFilter(lektor)"></i>
{{lektor.vorname}} {{lektor.nachname}} ({{lektor.kurzbz}})
<small v-if="zeitwunschMap[lektor.mitarbeiter_uid]" class="text-muted">
<small v-if="zeitwunschMap[lektor.mitarbeiter_uid]" class="text-muted" :title="$p.t('lehre', 'zeitwuensche_last_update', [formatDate(zeitwunschMap[lektor.mitarbeiter_uid])])">
<i class="fa-regular fa-clock"></i> {{ formatDate(zeitwunschMap[lektor.mitarbeiter_uid]) }}
</small>
</div>
+13 -6
View File
@@ -97,7 +97,7 @@ export default {
},
modalActions: {
saveEventTime: (payload) => this.handleSaveEventTime(payload),
addToFilter: (filter, type) => this.addToFilter(filter, type),
addToFilter: (filter, type, addOnlyIfExists) => this.addToFilter(filter, type, addOnlyIfExists),
goToEvent: ({datum}) => {
this.jumpToDate(datum);
}
@@ -401,9 +401,19 @@ export default {
}
},
addToFilter(filter, type) {
if (type === 'ort') {
addToFilter(filter, type, addOnlyIfExists = false) {
if (type === 'ort')
{
const ort_kurzbz = filter.ort_kurzbz;
if (addOnlyIfExists)
{
if (Array.isArray(this.rooms) && this.rooms.length < 1)
return;
if (!ort_kurzbz)
return this.rooms = [];
}
if (!this.rooms.some((room) => room.ort_kurzbz === ort_kurzbz)) {
this.rooms.push({ ort_kurzbz });
}
@@ -619,9 +629,6 @@ export default {
.catch((error) => {
this.currentlyUpdatedEvent = null;
this.removeVisualForUpdatingCalendarEvent(obj.orig.eindeutige_kalender_gruppen_id);
this.$nextTick(() => {
this.$refs.calendar.resetEventLoader(false, false);
});
throw error;
});
},
@@ -223,6 +223,7 @@ export default {
:is-event-dragging-enabled="false"
:is-event-resizing-enabled="false"
:isRangeVirtualScrollEnabled="false"
:can-access-settings-view="false"
:can-toggle-collision-check="false"
@update:date="handleChangeDate"
class="responsive-calendar"
+40
View File
@@ -3443,6 +3443,26 @@ $phrases = array(
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
'phrase' => 'zeitwuensche_last_update',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Zeitwünsche zuletzt bearbeitet am {0}',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Time preferences last updated on {0}',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
@@ -51040,6 +51060,26 @@ In the list:
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'entry_marked_for_deletion_not_editable',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Eintrag ist zum Löschen markiert und kann daher nicht bearbeitet werden',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Entry is marked for deletion and can therefore no longer be edited',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',