mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-23 09:52:22 +00:00
Merge branch 'feature-40128/Mehrere_Suchergebnisse_für_selbe_Person' into rc1_FHC4_C4
This commit is contained in:
@@ -0,0 +1,874 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
|
||||
$config['person'] = [
|
||||
'primarykey' => 'person_id',
|
||||
'table' => 'public.tbl_person',
|
||||
'searchfields' => [
|
||||
'uid' => [
|
||||
'comparison' => 'equals',
|
||||
'field' => 'uid',
|
||||
'join' => [
|
||||
'table' => "public.tbl_benutzer",
|
||||
'using' => "person_id"
|
||||
],
|
||||
'1-n' => true
|
||||
],
|
||||
'vorname' => [
|
||||
'alias' => ['firstname'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'vorname'
|
||||
],
|
||||
'nachname' => [
|
||||
'alias' => ['lastname', 'surename'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'nachname'
|
||||
],
|
||||
'name' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => "(vorname || ' ' || nachname)"
|
||||
],
|
||||
'email' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => 'kontakt',
|
||||
'join' => [
|
||||
'table' => "public.tbl_kontakt",
|
||||
'on' => "kontakttyp = 'email' AND tbl_kontakt.person_id = tbl_person.person_id"
|
||||
],
|
||||
"1-n" => true
|
||||
],
|
||||
'tel' => [
|
||||
'alias' => ['phone', 'telefon'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'kontakt',
|
||||
'join' => [
|
||||
'table' => "public.tbl_kontakt",
|
||||
'on' => "kontakttyp IN ('telefon', 'so.tel', 'mobil') AND tbl_kontakt.person_id = tbl_person.person_id"
|
||||
],
|
||||
"1-n" => true
|
||||
],
|
||||
'preid' => [
|
||||
'alias' => ['prestudent_id'],
|
||||
'comparison' => 'equal-int',
|
||||
'field' => 'prestudent_id',
|
||||
'join' => [
|
||||
'table' => "public.tbl_prestudent",
|
||||
'using' => "person_id"
|
||||
],
|
||||
'1-n' => true
|
||||
],
|
||||
'pid' => [
|
||||
'alias' => ['person_id'],
|
||||
'comparison' => 'equal-int',
|
||||
'field' => 'person_id'
|
||||
]
|
||||
],
|
||||
'resultfields' => [
|
||||
"ARRAY( SELECT uid FROM public.tbl_benutzer WHERE person_id = p.person_id ) AS uids",
|
||||
"p.person_id",
|
||||
"(p.vorname || ' ' || p.nachname) AS name",
|
||||
"ARRAY( SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp = 'email' AND person_id=p.person_id ) AS email",
|
||||
"CASE
|
||||
WHEN p.foto IS NOT NULL THEN 'data:image/jpeg' || CONVERT_FROM(DECODE('3b','hex'), 'UTF8') || 'base64,' || p.foto
|
||||
ELSE NULL END
|
||||
AS photo_url"
|
||||
],
|
||||
'resultjoin' => "
|
||||
JOIN public.tbl_person p USING (person_id)"
|
||||
];
|
||||
|
||||
$config['student'] = [
|
||||
'primarykey' => 'student_uid',
|
||||
'table' => 'public.tbl_student',
|
||||
'searchfields' => [
|
||||
'uid' => [
|
||||
'comparison' => 'equals',
|
||||
'field' => 'student_uid'
|
||||
],
|
||||
'vorname' => [
|
||||
'alias' => ['firstname'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'vorname',
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_prestudent",
|
||||
'using' => "prestudent_id"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
]
|
||||
],
|
||||
'nachname' => [
|
||||
'alias' => ['lastname', 'surename'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'nachname',
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_prestudent",
|
||||
'using' => "prestudent_id"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
]
|
||||
],
|
||||
'name' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => "(vorname || ' ' || nachname)",
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_prestudent",
|
||||
'using' => "prestudent_id"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
]
|
||||
],
|
||||
'email' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => 'kontakt',
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_prestudent",
|
||||
'using' => "prestudent_id"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_kontakt",
|
||||
'on' => "kontakttyp = 'email' AND tbl_kontakt.person_id = tbl_prestudent.person_id"
|
||||
]
|
||||
],
|
||||
"1-n" => true
|
||||
],
|
||||
'tel' => [
|
||||
'alias' => ['phone', 'telefon'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'kontakt',
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_prestudent",
|
||||
'using' => "prestudent_id"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_kontakt",
|
||||
'on' => "kontakttyp IN ('telefon', 'so.tel', 'mobil') AND tbl_kontakt.person_id = tbl_prestudent.person_id"
|
||||
]
|
||||
],
|
||||
"1-n" => true
|
||||
],
|
||||
'stg' => [
|
||||
'alias' => ['studiengang'],
|
||||
'comparison' => 'equals',
|
||||
'field' => "typ || kurzbz",
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_prestudent",
|
||||
'using' => "prestudent_id"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_studiengang",
|
||||
'on' => "tbl_studiengang.studiengang_kz = tbl_prestudent.studiengang_kz"
|
||||
]
|
||||
]
|
||||
],
|
||||
'preid' => [
|
||||
'alias' => ['prestudent_id'],
|
||||
'comparison' => 'equal-int',
|
||||
'field' => 'prestudent_id'
|
||||
],
|
||||
'pid' => [
|
||||
'alias' => ['person_id'],
|
||||
'comparison' => 'equal-int',
|
||||
'field' => 'person_id',
|
||||
'join' => [
|
||||
'table' => "public.tbl_prestudent",
|
||||
'using' => "prestudent_id"
|
||||
]
|
||||
]
|
||||
],
|
||||
'resultfields' => [
|
||||
"s.student_uid AS uid",
|
||||
"s.matrikelnr",
|
||||
"p.person_id",
|
||||
"(p.vorname || ' ' || p.nachname) AS name",
|
||||
"(s.student_uid || '@" . DOMAIN . "') || ARRAY( SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp = 'email' AND person_id=p.person_id ) AS email",
|
||||
"CASE
|
||||
WHEN p.foto IS NOT NULL THEN 'data:image/jpeg' || CONVERT_FROM(DECODE('3b','hex'), 'UTF8') || 'base64,' || p.foto
|
||||
ELSE NULL END
|
||||
AS photo_url",
|
||||
"b.aktiv"
|
||||
],
|
||||
'resultjoin' => "
|
||||
JOIN public.tbl_student s USING (student_uid)
|
||||
JOIN public.tbl_benutzer b ON(b.uid = s.student_uid)
|
||||
JOIN public.tbl_person p USING(person_id)"
|
||||
];
|
||||
|
||||
$prestudent_sort = [
|
||||
"Student",
|
||||
"Incoming",
|
||||
"Outgoing",
|
||||
"Diplomand",
|
||||
"Unterbrecher",
|
||||
"Aufgenommener",
|
||||
"Wartender",
|
||||
"Bewerber",
|
||||
"Interessent",
|
||||
"Abgewiesener",
|
||||
"Absolvent",
|
||||
"Abbrecher",
|
||||
"Ausserordentlicher",
|
||||
"Praktikant"
|
||||
];
|
||||
$prestudent_sort_array = "array['" . implode("','", $prestudent_sort) . "']";
|
||||
$config['prestudent'] = [
|
||||
'primarykey' => 'prestudent_id',
|
||||
'table' => 'public.tbl_prestudent',
|
||||
'searchfields' => [
|
||||
'uid' => [
|
||||
'comparison' => 'equals',
|
||||
'field' => 'student_uid',
|
||||
'join' => [
|
||||
'table' => "public.tbl_student",
|
||||
'using' => "prestudent_id"
|
||||
]
|
||||
],
|
||||
'vorname' => [
|
||||
'alias' => ['firstname'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'vorname',
|
||||
'join' => [
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
],
|
||||
'nachname' => [
|
||||
'alias' => ['lastname', 'surename'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'nachname',
|
||||
'join' => [
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
],
|
||||
'name' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => "(vorname || ' ' || nachname)",
|
||||
'join' => [
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
],
|
||||
'email' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => 'kontakt',
|
||||
'join' => [
|
||||
'table' => "public.tbl_kontakt",
|
||||
'on' => "kontakttyp = 'email' AND tbl_kontakt.person_id = tbl_prestudent.person_id"
|
||||
],
|
||||
"1-n" => true
|
||||
],
|
||||
'tel' => [
|
||||
'alias' => ['phone', 'telefon'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'kontakt',
|
||||
'join' => [
|
||||
'table' => "public.tbl_kontakt",
|
||||
'on' => "kontakttyp IN ('telefon', 'so.tel', 'mobil') AND tbl_kontakt.person_id = tbl_prestudent.person_id"
|
||||
],
|
||||
"1-n" => true
|
||||
],
|
||||
'stg' => [
|
||||
'alias' => ['studiengang'],
|
||||
'comparison' => 'equals',
|
||||
'field' => "typ || kurzbz",
|
||||
'join' => [
|
||||
'table' => "public.tbl_studiengang",
|
||||
'using' => "studiengang_kz"
|
||||
]
|
||||
],
|
||||
'preid' => [
|
||||
'alias' => ['prestudent_id'],
|
||||
'comparison' => 'equal-int',
|
||||
'field' => 'prestudent_id'
|
||||
],
|
||||
'pid' => [
|
||||
'alias' => ['person_id'],
|
||||
'comparison' => 'equal-int',
|
||||
'field' => 'person_id',
|
||||
'join' => [
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
]
|
||||
],
|
||||
'resultfields' => [
|
||||
"ps.prestudent_id",
|
||||
"ps.studiengang_kz",
|
||||
"s.matrikelnr",
|
||||
"p.person_id",
|
||||
"b.uid",
|
||||
"(p.vorname || ' ' || p.nachname) AS name",
|
||||
"(b.uid || '@" . DOMAIN . "') || ARRAY( SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp = 'email' AND person_id=p.person_id ) AS email",
|
||||
"CASE
|
||||
WHEN p.foto IS NOT NULL THEN 'data:image/jpeg' || CONVERT_FROM(DECODE('3b','hex'), 'UTF8') || 'base64,' || p.foto
|
||||
ELSE NULL END
|
||||
AS photo_url",
|
||||
"UPPER(sg.typ || sg.kurzbz) AS stg_kuerzel",
|
||||
"sg.bezeichnung",
|
||||
"(
|
||||
SELECT bezeichnung_mehrsprachig[(TABLE lang)]
|
||||
FROM public.tbl_status
|
||||
WHERE status_kurzbz = public.get_rolle_prestudent(ps.prestudent_id, NULL)
|
||||
LIMIT 1
|
||||
) AS status",
|
||||
"COALESCE(
|
||||
(
|
||||
SELECT COALESCE(plan.orgform_kurzbz, pss.orgform_kurzbz)
|
||||
FROM public.tbl_prestudentstatus pss
|
||||
LEFT JOIN lehre.tbl_studienplan plan USING (studienplan_id)
|
||||
WHERE pss.prestudent_id=ps.prestudent_id
|
||||
ORDER BY pss.datum DESC, pss.insertamum DESC, pss.ext_id DESC
|
||||
LIMIT 1
|
||||
),
|
||||
sg.orgform_kurzbz
|
||||
) AS orgform",
|
||||
"b.aktiv",
|
||||
"array_position(" . $prestudent_sort_array . ", public.get_rolle_prestudent(ps.prestudent_id, NULL)) AS sort"
|
||||
],
|
||||
'resultjoin' => "
|
||||
LEFT JOIN public.tbl_prestudent ps USING (prestudent_id)
|
||||
LEFT JOIN public.tbl_student s ON (ps.prestudent_id = s.prestudent_id)
|
||||
LEFT JOIN public.tbl_benutzer b ON (b.uid = s.student_uid)
|
||||
JOIN public.tbl_person p ON (p.person_id = ps.person_id)
|
||||
LEFT JOIN public.tbl_studiengang sg ON (sg.studiengang_kz = ps.studiengang_kz)"
|
||||
];
|
||||
|
||||
$config['employee'] = [
|
||||
'alias' => ['ma', 'mitarbeiter'],
|
||||
'primarykey' => 'mitarbeiter_uid',
|
||||
'table' => 'public.tbl_mitarbeiter',
|
||||
'searchfields' => [
|
||||
'uid' => [
|
||||
'alias' => ['mitarbeiter_uid'],
|
||||
'comparison' => 'equals',
|
||||
'field' => "mitarbeiter_uid"
|
||||
],
|
||||
'vorname' => [
|
||||
'alias' => ['firstname'],
|
||||
'comparison' => 'similar',
|
||||
'field' => "vorname",
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_benutzer",
|
||||
'on' => "uid = mitarbeiter_uid"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
]
|
||||
],
|
||||
'nachname' => [
|
||||
'alias' => ['lastname', 'surename'],
|
||||
'comparison' => 'similar',
|
||||
'field' => "nachname",
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_benutzer",
|
||||
'on' => "uid = mitarbeiter_uid"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
]
|
||||
],
|
||||
'name' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => "(vorname || ' ' || nachname)",
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_benutzer",
|
||||
'on' => "uid = mitarbeiter_uid"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_person",
|
||||
'using' => "person_id"
|
||||
]
|
||||
]
|
||||
],
|
||||
'email' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => "COALESCE(alias, uid) || '" . '@' . DOMAIN . "'",
|
||||
'join' => [
|
||||
'table' => "public.tbl_benutzer",
|
||||
'on' => "uid = mitarbeiter_uid"
|
||||
]
|
||||
],
|
||||
'tel' => [
|
||||
'alias' => ['phone', 'telefon'],
|
||||
'comparison' => 'similar',
|
||||
'field' => "TRIM(COALESCE(kontakt, '') || ' ' || COALESCE(telefonklappe, ''))",
|
||||
'join' => [
|
||||
'table' => "public.tbl_kontakt",
|
||||
'on' => "kontakttyp = 'telefon' AND tbl_kontakt.standort_id = tbl_mitarbeiter.standort_id"
|
||||
],
|
||||
"1-n" => true
|
||||
],
|
||||
'pid' => [
|
||||
'alias' => ['person_id'],
|
||||
'comparison' => 'equal-int',
|
||||
'field' => "person_id",
|
||||
'join' => [
|
||||
'table' => "public.tbl_benutzer",
|
||||
'on' => "uid = mitarbeiter_uid"
|
||||
]
|
||||
],
|
||||
'oe' => [
|
||||
'alias' => ['ou', 'organisationseinheit', 'organisationunit'],
|
||||
'comparison' => 'vector',
|
||||
'field' => "fts_bezeichnung",
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_benutzerfunktion",
|
||||
'on' => "mitarbeiter_uid = uid
|
||||
AND funktion_kurzbz = 'oezuordnung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_organisationseinheit",
|
||||
'using' => "oe_kurzbz"
|
||||
]
|
||||
],
|
||||
'1-n' => true
|
||||
],
|
||||
'kst' => [
|
||||
'comparison' => 'vector',
|
||||
'field' => "fts_bezeichnung",
|
||||
'join' => [
|
||||
[
|
||||
'table' => "public.tbl_benutzerfunktion",
|
||||
'on' => "mitarbeiter_uid = uid
|
||||
AND funktion_kurzbz = 'kstzuordnung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())"
|
||||
],
|
||||
[
|
||||
'table' => "public.tbl_organisationseinheit",
|
||||
'using' => "oe_kurzbz"
|
||||
]
|
||||
],
|
||||
'1-n' => true
|
||||
]
|
||||
],
|
||||
'resultfields' => [
|
||||
"b.uid",
|
||||
"p.person_id",
|
||||
"(p.vorname || ' ' || p.nachname) AS name",
|
||||
"ARRAY(
|
||||
SELECT
|
||||
'[' || ot.bezeichnung || '] ' || o.bezeichnung AS bezeichnung
|
||||
FROM public.tbl_benutzerfunktion bf
|
||||
JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
|
||||
JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
|
||||
WHERE bf.funktion_kurzbz = 'oezuordnung'
|
||||
AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
|
||||
AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
|
||||
AND bf.uid = b.uid
|
||||
GROUP BY o.bezeichnung, ot.bezeichnung
|
||||
) AS organisationunit_name",
|
||||
"COALESCE(b.alias, b.uid) || '" . '@' . DOMAIN . "' AS email",
|
||||
"TRIM(COALESCE(k.kontakt, '') || ' ' || COALESCE(m.telefonklappe, '')) AS phone",
|
||||
"'" . base_url("/cis/public/bild.php?src=person&person_id=") . "' || p.person_id AS photo_url",
|
||||
"ARRAY(
|
||||
SELECT
|
||||
'[' || ot.bezeichnung || '] ' || o.bezeichnung AS bezeichnung
|
||||
FROM public.tbl_benutzerfunktion bf
|
||||
JOIN public.tbl_organisationseinheit o USING(oe_kurzbz)
|
||||
JOIN public.tbl_organisationseinheittyp ot USING(organisationseinheittyp_kurzbz)
|
||||
WHERE bf.funktion_kurzbz = 'kstzuordnung'
|
||||
AND (bf.datum_von IS NULL OR bf.datum_von <= NOW())
|
||||
AND (bf.datum_bis IS NULL OR bf.datum_bis >= NOW())
|
||||
AND bf.uid = b.uid
|
||||
GROUP BY o.bezeichnung, ot.bezeichnung
|
||||
) AS standardkostenstelle"
|
||||
],
|
||||
'resultjoin' => "
|
||||
JOIN public.tbl_mitarbeiter m USING (mitarbeiter_uid)
|
||||
JOIN public.tbl_benutzer b ON (b.uid = m.mitarbeiter_uid)
|
||||
JOIN public.tbl_person p USING(person_id)
|
||||
LEFT JOIN (
|
||||
SELECT kontakt, standort_id
|
||||
FROM public.tbl_kontakt
|
||||
WHERE kontakttyp = 'telefon'
|
||||
) k ON (k.standort_id = m.standort_id)"
|
||||
];
|
||||
|
||||
// TODO(chris): move to searchpv21.php
|
||||
$config['unassigned_employee'] = $config['employee'];
|
||||
$config['unassigned_employee']['alias'] = ['mitarbeiter_ohne_zuordnung'];
|
||||
$config['unassigned_employee']['prepare'] = "unassigned_employee AS (
|
||||
SELECT tbl_mitarbeiter.*
|
||||
FROM public.tbl_mitarbeiter
|
||||
LEFT JOIN public.tbl_benutzerfunktion ON (
|
||||
uid = mitarbeiter_uid
|
||||
AND funktion_kurzbz = 'kstzuordnung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())
|
||||
)
|
||||
WHERE tbl_benutzerfunktion.bezeichnung IS NULL
|
||||
UNION
|
||||
SELECT tbl_mitarbeiter.*
|
||||
FROM public.tbl_mitarbeiter
|
||||
LEFT JOIN public.tbl_benutzerfunktion ON (
|
||||
uid = mitarbeiter_uid
|
||||
AND funktion_kurzbz = 'oezuordnung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())
|
||||
)
|
||||
WHERE tbl_benutzerfunktion.bezeichnung IS NULL
|
||||
)";
|
||||
$config['unassigned_employee']['table'] = "unassigned_employee";
|
||||
$config['unassigned_employee']['searchfields']['tel']['join']['on'] = "
|
||||
kontakttyp = 'telefon'
|
||||
AND tbl_kontakt.standort_id = unassigned_employee.standort_id
|
||||
";
|
||||
$config['unassigned_employee']['renderer'] = 'employee';
|
||||
|
||||
$config['organisationunit'] = [
|
||||
'alias' => ['ou', 'organisationseinheit', 'oe'],
|
||||
'primarykey' => 'oe_kurzbz',
|
||||
'table' => 'public.tbl_organisationseinheit',
|
||||
'searchfields' => [
|
||||
'uid' => [
|
||||
'comparison' => 'equals',
|
||||
'field' => 'uid',
|
||||
'prepare' => "organisationunit_leader(oe_kurzbz, uid, vorname, nachname) AS (
|
||||
SELECT oe_kurzbz, vorname, nachname, uid
|
||||
FROM public.tbl_benutzerfunktion
|
||||
JOIN public.tbl_benutzer USING (uid)
|
||||
JOIN public.tbl_person USING (person_id)
|
||||
WHERE funktion_kurzbz = 'Leitung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())
|
||||
AND tbl_benutzer.aktiv = TRUE
|
||||
)",
|
||||
'join' => [
|
||||
'table' => "organisationunit_leader",
|
||||
'using' => "oe_kurzbz"
|
||||
],
|
||||
'1-n' => true
|
||||
],
|
||||
'vorname' => [
|
||||
'alias' => ['firstname'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'vorname',
|
||||
'prepare' => "organisationunit_leader(oe_kurzbz, uid, vorname, nachname) AS (
|
||||
SELECT oe_kurzbz, vorname, nachname, uid
|
||||
FROM public.tbl_benutzerfunktion
|
||||
JOIN public.tbl_benutzer USING (uid)
|
||||
JOIN public.tbl_person USING (person_id)
|
||||
WHERE funktion_kurzbz = 'Leitung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())
|
||||
AND tbl_benutzer.aktiv = TRUE
|
||||
)",
|
||||
'join' => [
|
||||
'table' => "organisationunit_leader",
|
||||
'using' => "oe_kurzbz"
|
||||
],
|
||||
'1-n' => true
|
||||
],
|
||||
'nachname' => [
|
||||
'alias' => ['lastname', 'surename'],
|
||||
'comparison' => 'similar',
|
||||
'field' => 'nachname',
|
||||
'prepare' => "organisationunit_leader(oe_kurzbz, uid, vorname, nachname) AS (
|
||||
SELECT oe_kurzbz, vorname, nachname, uid
|
||||
FROM public.tbl_benutzerfunktion
|
||||
JOIN public.tbl_benutzer USING (uid)
|
||||
JOIN public.tbl_person USING (person_id)
|
||||
WHERE funktion_kurzbz = 'Leitung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())
|
||||
AND tbl_benutzer.aktiv = TRUE
|
||||
)",
|
||||
'join' => [
|
||||
'table' => "organisationunit_leader",
|
||||
'using' => "oe_kurzbz"
|
||||
],
|
||||
'1-n' => true
|
||||
],
|
||||
'name' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => "(vorname || ' ' || nachname)",
|
||||
'prepare' => "organisationunit_leader(oe_kurzbz, uid, vorname, nachname) AS (
|
||||
SELECT oe_kurzbz, vorname, nachname, uid
|
||||
FROM public.tbl_benutzerfunktion
|
||||
JOIN public.tbl_benutzer USING (uid)
|
||||
JOIN public.tbl_person USING (person_id)
|
||||
WHERE funktion_kurzbz = 'Leitung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())
|
||||
AND tbl_benutzer.aktiv = TRUE
|
||||
)",
|
||||
'join' => [
|
||||
'table' => "organisationunit_leader",
|
||||
'using' => "oe_kurzbz"
|
||||
],
|
||||
'1-n' => true
|
||||
],
|
||||
'oe' => [
|
||||
'alias' => ['ou', 'organisationseinheit', 'organisationunit'],
|
||||
'comparison' => 'vector',
|
||||
'field' => "fts_bezeichnung"
|
||||
],
|
||||
'kurzbz' => [
|
||||
'alias' => ['oe_kurzbz'],
|
||||
'comparison' => 'equals',
|
||||
'field' => "oe_kurzbz"
|
||||
]
|
||||
],
|
||||
'resultfields' => [
|
||||
"oe.oe_kurzbz",
|
||||
"('[' || type.bezeichnung || '] ' || oe.bezeichnung) AS name",
|
||||
"oe_parent.oe_kurzbz AS parentoe_kurzbz",
|
||||
"(CASE WHEN oe_parent.bezeichnung IS NOT NULL THEN '[' || type_parent.bezeichnung || '] ' || oe_parent.bezeichnung END) AS parentoe_name",
|
||||
"ARRAY(
|
||||
SELECT JSON_BUILD_OBJECT('uid', b.uid, 'vorname', p.vorname, 'nachname', p.nachname, 'name', (p.vorname || ' ' || p.nachname))
|
||||
FROM public.tbl_benutzerfunktion bf
|
||||
JOIN public.tbl_benutzer b USING (uid)
|
||||
JOIN public.tbl_person p USING (person_id)
|
||||
WHERE funktion_kurzbz = 'Leitung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())
|
||||
AND b.aktiv = TRUE
|
||||
AND oe_kurzbz = oe.oe_kurzbz
|
||||
) AS leaders",
|
||||
"(
|
||||
SELECT COUNT(*)
|
||||
FROM public.tbl_benutzerfunktion
|
||||
WHERE funktion_kurzbz = 'oezuordnung'
|
||||
AND (datum_von IS NULL OR datum_von <= NOW())
|
||||
AND (datum_bis IS NULL OR datum_bis >= NOW())
|
||||
AND oe_kurzbz = oe.oe_kurzbz
|
||||
) AS number_of_people",
|
||||
"(CASE WHEN oe.mailverteiler THEN oe.oe_kurzbz || '" . '@' . DOMAIN . "' END) AS mailgroup"
|
||||
],
|
||||
'resultjoin' => "
|
||||
JOIN public.tbl_organisationseinheit oe
|
||||
USING (oe_kurzbz)
|
||||
JOIN public.tbl_organisationseinheittyp type
|
||||
USING (organisationseinheittyp_kurzbz)
|
||||
LEFT JOIN public.tbl_organisationseinheit oe_parent
|
||||
ON (oe_parent.oe_kurzbz = oe.oe_parent_kurzbz)
|
||||
LEFT JOIN public.tbl_organisationseinheittyp type_parent
|
||||
ON (oe_parent.organisationseinheittyp_kurzbz = type_parent.organisationseinheittyp_kurzbz)"
|
||||
];
|
||||
|
||||
$config['room'] = [
|
||||
'alias' => ['raum'],
|
||||
'primarykey' => 'ort_kurzbz',
|
||||
'table' => 'public.tbl_ort',
|
||||
'searchfields' => [
|
||||
'name' => [
|
||||
'comparison' => 'similar',
|
||||
'field' => 'ort_kurzbz'
|
||||
]
|
||||
],
|
||||
'resultfields' => [
|
||||
"ort.ort_kurzbz",
|
||||
"ort.gebteil AS building",
|
||||
"ort.ausstattung AS equipment",
|
||||
"ort.stockwerk AS floor",
|
||||
"ort.dislozierung AS room_number",
|
||||
"ort.content_id",
|
||||
"address.ort AS city",
|
||||
"address.plz AS zip",
|
||||
"address.strasse AS street",
|
||||
"ort.max_person",
|
||||
"ort.arbeitsplaetze AS workplaces"
|
||||
],
|
||||
'resultjoin' => "
|
||||
JOIN public.tbl_ort ort
|
||||
USING (ort_kurzbz)
|
||||
LEFT JOIN public.tbl_standort
|
||||
USING (standort_id)
|
||||
LEFT JOIN public.tbl_adresse address
|
||||
USING (adresse_id)"
|
||||
];
|
||||
$sprache = getUserLanguage();
|
||||
$config['cms'] = [
|
||||
'primarykey' => 'contentsprache_id',
|
||||
'table' => 'campus.tbl_contentsprache',
|
||||
'prepare' => "
|
||||
cms_auth (content_id) AS (
|
||||
SELECT content_id
|
||||
FROM campus.tbl_content c
|
||||
WHERE NOT EXISTS (SELECT 1 FROM campus.tbl_contentgruppe g WHERE g.content_id=c.content_id)
|
||||
UNION
|
||||
SELECT content_id
|
||||
FROM public.vw_gruppen g
|
||||
JOIN campus.tbl_contentgruppe c USING (gruppe_kurzbz)
|
||||
WHERE uid = (TABLE auth)
|
||||
),
|
||||
cms_active (content_id, template_kurzbz) AS (
|
||||
SELECT content_id, template_kurzbz
|
||||
FROM cms_auth
|
||||
JOIN campus.tbl_content USING (content_id)
|
||||
WHERE aktiv = TRUE
|
||||
),
|
||||
cms_active_redirect (content_id) AS (
|
||||
SELECT content_id
|
||||
FROM cms_active
|
||||
WHERE template_kurzbz = 'redirect'
|
||||
),
|
||||
cms_active_redirect_linked (content_id) AS (
|
||||
SELECT content_id
|
||||
FROM cms_active_redirect
|
||||
JOIN campus.tbl_contentsprache USING (content_id)
|
||||
WHERE LEFT((xpath('string(/content/url)', content))[1]::text, 1) <> '#'
|
||||
),
|
||||
cms_active_others (content_id) AS (
|
||||
SELECT content_id
|
||||
FROM cms_active
|
||||
WHERE template_kurzbz IN ('contentmittitel', 'contentohnetitel', 'contentmittitel_filterwidget')
|
||||
)
|
||||
",
|
||||
'searchfields' => [
|
||||
'content' => [
|
||||
'alias' => ['inhalt'],
|
||||
'comparison' => "vector",
|
||||
'field' => "(
|
||||
setweight(to_tsvector('simple', COALESCE(titel, '')), 'A')
|
||||
||
|
||||
setweight(to_tsvector('simple', COALESCE(content, '')::text), 'B')
|
||||
)"
|
||||
],
|
||||
'content_id' => [
|
||||
'alias' => ['id'],
|
||||
'comparison' => "equal-int",
|
||||
'field' => "content_id"
|
||||
],
|
||||
'lang' => [
|
||||
'alias' => ['language', 'sprache'],
|
||||
'comparison' => "equals",
|
||||
'field' => "sprache"
|
||||
]
|
||||
],
|
||||
'resultfields' => [
|
||||
"contentsprache.content_id",
|
||||
"content.template_kurzbz",
|
||||
"contentsprache.version",
|
||||
"contentsprache.sprache AS language",
|
||||
"contentsprache.titel AS title",
|
||||
"contentsprache.content",
|
||||
"(xpath('string(/content/url)', contentsprache.content))[1] AS content_url"
|
||||
],
|
||||
'resultjoin' => "
|
||||
JOIN campus.tbl_contentsprache contentsprache
|
||||
USING (contentsprache_id)
|
||||
JOIN campus.tbl_content content
|
||||
USING (content_id)
|
||||
WHERE content_id IN (
|
||||
SELECT content_id
|
||||
FROM cms_active_redirect_linked
|
||||
UNION
|
||||
SELECT content_id
|
||||
FROM cms_active_others
|
||||
)
|
||||
AND version = campus.get_highest_content_version(content_id)
|
||||
AND contentsprache.sprache = '{$sprache}'"
|
||||
];
|
||||
|
||||
$config['dms'] = [
|
||||
'primarykey' => 'dms_id, version',
|
||||
'table' => 'campus.tbl_dms_version',
|
||||
'searchfields' => [
|
||||
'keywords' => [
|
||||
'alias' => ['keyword', 'keywords', 'schlagwort', 'schlagworte'],
|
||||
'comparison' => "vector",
|
||||
'field' => "(to_tsvector('simple', COALESCE(schlagworte, '')))"
|
||||
]
|
||||
],
|
||||
'resultfields' => [
|
||||
"v.dms_id",
|
||||
"v.version",
|
||||
"v.filename",
|
||||
"v.mimetype",
|
||||
"v.name",
|
||||
"v.beschreibung AS description",
|
||||
"v.schlagworte AS keywords"
|
||||
],
|
||||
'resultjoin' => "
|
||||
JOIN campus.tbl_dms_version v
|
||||
USING (dms_id, version)
|
||||
WHERE cis_suche = TRUE
|
||||
AND version=(SELECT MAX(version) FROM campus.tbl_dms_version WHERE dms_id=v.dms_id)
|
||||
AND NOT EXISTS (
|
||||
SELECT
|
||||
1
|
||||
FROM
|
||||
fue.tbl_projekt_dokument p
|
||||
WHERE p.dms_id = v.dms_id
|
||||
) AND (
|
||||
NOT EXISTS (
|
||||
WITH RECURSIVE categories (kategorie_kurzbz) AS (
|
||||
SELECT
|
||||
kategorie_kurzbz
|
||||
FROM
|
||||
campus.tbl_dms c
|
||||
WHERE c.dms_id = v.dms_id
|
||||
UNION ALL
|
||||
SELECT
|
||||
cat.parent_kategorie_kurzbz AS kategorie_kurzbz
|
||||
FROM
|
||||
categories
|
||||
JOIN campus.tbl_dms_kategorie cat USING (kategorie_kurzbz)
|
||||
)
|
||||
SELECT
|
||||
1
|
||||
FROM
|
||||
categories
|
||||
JOIN campus.tbl_dms_kategorie_gruppe USING (kategorie_kurzbz)
|
||||
UNION
|
||||
SELECT
|
||||
1
|
||||
FROM
|
||||
categories
|
||||
JOIN campus.tbl_dms_kategorie USING (kategorie_kurzbz)
|
||||
WHERE
|
||||
berechtigung_kurzbz IS NOT NULL
|
||||
) OR EXISTS (
|
||||
WITH RECURSIVE categories (kategorie_kurzbz) AS (
|
||||
SELECT
|
||||
kategorie_kurzbz
|
||||
FROM
|
||||
campus.tbl_dms c
|
||||
WHERE c.dms_id = v.dms_id
|
||||
UNION ALL
|
||||
SELECT
|
||||
cat.parent_kategorie_kurzbz AS kategorie_kurzbz
|
||||
FROM
|
||||
categories
|
||||
JOIN campus.tbl_dms_kategorie cat USING (kategorie_kurzbz)
|
||||
)
|
||||
SELECT
|
||||
1
|
||||
FROM
|
||||
categories
|
||||
JOIN campus.tbl_dms_kategorie_gruppe USING (kategorie_kurzbz)
|
||||
JOIN public.tbl_benutzergruppe USING(gruppe_kurzbz)
|
||||
WHERE
|
||||
uid = (TABLE auth)
|
||||
)
|
||||
)"
|
||||
];
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
|
||||
$CI =& get_instance();
|
||||
|
||||
|
||||
$config['employee'] = $CI->config->item('employee', 'search');
|
||||
|
||||
$config['student'] = $CI->config->item('student', 'search');
|
||||
unset($config['student']['searchfields']['email']);
|
||||
unset($config['student']['searchfields']['tel']);
|
||||
$config['student']['resultfields'] = [
|
||||
"s.student_uid AS uid",
|
||||
"s.matrikelnr",
|
||||
"p.person_id",
|
||||
"(p.vorname || ' ' || p.nachname) AS name",
|
||||
"ARRAY[s.student_uid || '@' || '" . DOMAIN . "'] AS email",
|
||||
"CASE
|
||||
WHEN p.foto IS NOT NULL THEN 'data:image/jpeg' || CONVERT_FROM(DECODE('3b','hex'), 'UTF8') || 'base64,' || p.foto
|
||||
ELSE NULL END
|
||||
AS photo_url",
|
||||
"b.aktiv"
|
||||
];
|
||||
|
||||
$config['organisationunit'] = $CI->config->item('organisationunit', 'search');
|
||||
$config['organisationunit']['prepare'] = 'active_organisationseinheit AS (SELECT * FROM public.tbl_organisationseinheit WHERE aktiv = true)';
|
||||
$config['organisationunit']['table'] = 'active_organisationseinheit';
|
||||
|
||||
$config['room'] = $CI->config->item('room', 'search');
|
||||
|
||||
$config['cms'] = $CI->config->item('cms', 'search');
|
||||
|
||||
$config['dms'] = $CI->config->item('dms', 'search');
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
/*
|
||||
* TODO: 2025-07-21 ma0080 bare integer comparision results in db error
|
||||
* if searchstring is numeric but out of range of int, think about
|
||||
* more sophisticated solution using column data type - quick fix
|
||||
* convert field and search string to text
|
||||
*/
|
||||
$config['equal-int'] = [
|
||||
'priority' => 4,
|
||||
'rank' => "0",
|
||||
'compare' => "{field}::text = {word}::text",
|
||||
'force_integer' => true
|
||||
];
|
||||
|
||||
$config['equals'] = [
|
||||
'priority' => 3,
|
||||
'rank' => "0",
|
||||
'compare' => "LOWER({field}) = {word}"
|
||||
];
|
||||
|
||||
$config['similar'] = [
|
||||
'priority' => 2,
|
||||
'rank' => "(COALESCE({field}, '') <->> {word})",
|
||||
'compare' => "COALESCE({field}, '') %> {word}",
|
||||
'compare_boolean' => "COALESCE({field}, '') ILIKE {like:word}"
|
||||
];
|
||||
|
||||
$config['vector'] = [
|
||||
'priority' => 1,
|
||||
'rank' => "ts_rank({field}, to_tsquery('simple', {word}))",
|
||||
'compare' => "to_tsquery('simple', {word}) @@ {field}"
|
||||
];
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
|
||||
$CI =& get_instance();
|
||||
|
||||
|
||||
$config['student'] = $CI->config->item('student', 'search');
|
||||
|
||||
$config['prestudent'] = $CI->config->item('prestudent', 'search');
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* This controller operates between (interface) the JS (GUI) and the back-end
|
||||
* Provides data to the ajax get calls about languages
|
||||
* This controller works with JSON calls on the HTTP GET and the output is always JSON
|
||||
*/
|
||||
class Language extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'get' => self::PERM_LOGGED
|
||||
]);
|
||||
|
||||
// Load models
|
||||
$this->load->model('system/Sprache_model', 'SpracheModel');
|
||||
}
|
||||
|
||||
public function get()
|
||||
{
|
||||
$this->SpracheModel->addOrder('sprache');
|
||||
|
||||
$result = $this->SpracheModel->load();
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
}
|
||||
@@ -35,11 +35,10 @@ class Searchbar extends FHCAPI_Controller
|
||||
{
|
||||
// NOTE(chris): additional permission checks will be done in SearchBarLib
|
||||
parent::__construct([
|
||||
'search' => self::PERM_LOGGED
|
||||
'search' => self::PERM_LOGGED,
|
||||
'searchCis' => self::PERM_LOGGED,
|
||||
'searchStv' => self::PERM_LOGGED
|
||||
]);
|
||||
|
||||
// Load the library SearchBarLib
|
||||
$this->load->library('SearchBarLib');
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
@@ -50,6 +49,7 @@ class Searchbar extends FHCAPI_Controller
|
||||
*/
|
||||
public function search()
|
||||
{
|
||||
$this->load->library('SearchBarLib');
|
||||
$this->load->library('form_validation');
|
||||
|
||||
// Checks if the searchstr and the types parameters are in the POSTed JSON
|
||||
@@ -63,7 +63,53 @@ class Searchbar extends FHCAPI_Controller
|
||||
$result = $this->searchbarlib->search($this->input->post(self::SEARCHSTR_PARAM), $this->input->post(self::TYPES_PARAM));
|
||||
if (property_exists($result, 'error'))
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
$this->terminateWithSuccess($result);
|
||||
|
||||
$this->addMeta('mode', 'simple');
|
||||
|
||||
$this->terminateWithSuccess($result->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a JSON body via HTTP POST and provides the parameters
|
||||
*/
|
||||
public function searchCis()
|
||||
{
|
||||
return $this->searchAdvanced([ 'config' => 'searchcis' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a JSON body via HTTP POST and provides the parameters
|
||||
*/
|
||||
public function searchStv()
|
||||
{
|
||||
return $this->searchAdvanced([ 'config' => 'searchstv' ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a JSON body via HTTP POST and provides the parameters
|
||||
*/
|
||||
private function searchAdvanced($config)
|
||||
{
|
||||
$this->load->library('SearchLib', $config);
|
||||
$this->load->library('form_validation');
|
||||
|
||||
// Checks if the searchstr and the types parameters are in the POSTed JSON
|
||||
$this->form_validation->set_rules(self::SEARCHSTR_PARAM, null, 'required');
|
||||
$this->form_validation->set_rules(self::TYPES_PARAM . '[]', null, 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
// Convert to json the result from searchlib->search
|
||||
$result = $this->searchlib->search($this->input->post(self::SEARCHSTR_PARAM), $this->input->post(self::TYPES_PARAM));
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->addMeta('time', $result->meta['time']);
|
||||
$this->addMeta('searchstring', $result->meta['searchstring']);
|
||||
$this->addMeta('mode', 'advanced');
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,10 +109,15 @@ class FHCAPI_Controller extends Auth_Controller
|
||||
$error = [];
|
||||
|
||||
if (is_array($data)) {
|
||||
if ($type == self::ERROR_TYPE_VALIDATION)
|
||||
if ($type == self::ERROR_TYPE_VALIDATION) {
|
||||
$error['messages'] = $data;
|
||||
else
|
||||
} elseif (array_is_list($data)) {
|
||||
foreach ($data as $d)
|
||||
$this->addError($d, $type);
|
||||
return;
|
||||
} else {
|
||||
$error = $data;
|
||||
}
|
||||
} elseif (is_object($data)) {
|
||||
$error = (array)$data;
|
||||
} else {
|
||||
|
||||
@@ -424,6 +424,23 @@ function isValidDate($dateString)
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// PHP functions that don't exist in older versions
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns true if the given array is sequential
|
||||
*/
|
||||
if (!function_exists('array_is_list')) {
|
||||
function array_is_list(array $arr)
|
||||
{
|
||||
if ($arr === []) {
|
||||
return true;
|
||||
}
|
||||
return array_keys($arr) === range(0, count($arr) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Collection of utility functions for form validation purposes
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,35 @@
|
||||
--fhc-searchbar-results-btn-color: var(--bs-btn-color, white);
|
||||
}
|
||||
|
||||
.searchbar_input_clear {
|
||||
/* 1rem * 5 / 8 = width of icon */
|
||||
margin-inline-start: calc(-1rem * 5 / 8 - var(--bs-btn-padding-x) * 2 - var(--bs-border-width)) !important;
|
||||
border: 0;
|
||||
margin-inline-end: 1px;
|
||||
z-index: 1;
|
||||
}
|
||||
.searchbar_input_clear:hover,
|
||||
.searchbar_input_clear:focus {
|
||||
color: var(--bs-body-color);
|
||||
background-color: transparent;
|
||||
}
|
||||
.searchbar_input:focus,
|
||||
.searchbar_input:focus ~ .searchbar_input_clear {
|
||||
z-index: 5; /* same as bootstrap .input-group > .form-control:focus */
|
||||
}
|
||||
|
||||
.searchbar_setting_btn {
|
||||
--bs-btn-color: var(--bs-body-color);
|
||||
--bs-btn-bg: var(--bs-tertiary-bg);
|
||||
--bs-btn-border-color: var(--bs-border-color);
|
||||
}
|
||||
|
||||
|
||||
.searchbar_searchbox.open {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
|
||||
.searchbar_settings {
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
@@ -120,6 +149,76 @@
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/* new variant with template/frame */
|
||||
|
||||
.searchbar-result-template-frame {
|
||||
border-bottom: 1px solid lightgrey;
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.searchbar-result-template-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .5rem;
|
||||
padding: 0;
|
||||
margin: 1rem 0 0;
|
||||
}
|
||||
|
||||
.searchbar-square-image {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
}
|
||||
.searchbar-square-image > * {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.searchbar-square-image > img {
|
||||
object-fit: cover;
|
||||
}
|
||||
.searchbar-square-image > div {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
color: rgba(var(--bs-white-rgb),1);
|
||||
background-color: rgba(var(--bs-primary-rgb), 1);
|
||||
}
|
||||
.searchbar-square-image.rounded-circle > img,
|
||||
.searchbar-square-image.rounded-circle > div {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.searchbar-rounded-image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
.searchbar-rounded-image > img {
|
||||
width: 100%;
|
||||
}
|
||||
.searchbar-rounded-image > div {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
color: rgba(var(--bs-white-rgb),1);
|
||||
background-color: rgba(var(--bs-primary-rgb), 1);
|
||||
height: calc((100px - .75em) * 1.3);
|
||||
}
|
||||
.searchbar-rounded-image > img,
|
||||
.searchbar-rounded-image > div {
|
||||
border-radius: .25rem;
|
||||
}
|
||||
|
||||
.no-margin-paragraphs p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.non-selectable {
|
||||
user-select: none;
|
||||
-webkit-user-select: none; /* Safari */
|
||||
@@ -129,4 +228,4 @@
|
||||
|
||||
.searchbar_inaktiv {
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (C) 2025 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getAll() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/language/get'
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -22,5 +22,19 @@ export default {
|
||||
url: '/api/frontend/v1/searchbar/search',
|
||||
params
|
||||
};
|
||||
},
|
||||
searchCis(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/searchbar/searchCis',
|
||||
params
|
||||
};
|
||||
},
|
||||
searchStv(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/searchbar/searchStv',
|
||||
params
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -40,6 +40,7 @@ import menu from "./menu.js";
|
||||
import dashboard from "./dashboard.js";
|
||||
import authinfo from "./authinfo.js";
|
||||
import studium from "./studium.js";
|
||||
import language from "./language.js";
|
||||
|
||||
export default {
|
||||
search,
|
||||
@@ -68,4 +69,5 @@ export default {
|
||||
menu,
|
||||
authinfo,
|
||||
studium,
|
||||
language
|
||||
};
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getAll() {
|
||||
return this.$fhcApi.get('/api/frontend/v1/language/get');
|
||||
}
|
||||
};
|
||||
@@ -16,8 +16,16 @@
|
||||
*/
|
||||
|
||||
export default {
|
||||
search(searchsettings) {
|
||||
search(searchsettings, config) {
|
||||
const url = '/api/frontend/v1/searchbar/search';
|
||||
return this.$fhcApi.post(url, searchsettings, config);
|
||||
},
|
||||
searchAdvanced(searchsettings, config) {
|
||||
const url = '/api/frontend/v1/searchbar/searchAdvanced';
|
||||
return this.$fhcApi.post(url, searchsettings, config);
|
||||
},
|
||||
searchdummy(searchsettings) {
|
||||
const url = 'public/js/apps/api/dummyapi.php/Search';
|
||||
return this.$fhcApi.post(url, searchsettings);
|
||||
}
|
||||
};
|
||||
|
||||
+34
-9
@@ -16,12 +16,14 @@ const app = Vue.createApp({
|
||||
origin: "cis",
|
||||
cssclass: "",
|
||||
calcheightonly: true,
|
||||
types: [
|
||||
"mitarbeiter",
|
||||
"student",
|
||||
"raum",
|
||||
"organisationunit"
|
||||
],
|
||||
types: {
|
||||
employee: Vue.computed(() => this.$p.t("search/type_employee")),
|
||||
student: Vue.computed(() => this.$p.t("search/type_student")),
|
||||
room: Vue.computed(() => this.$p.t("search/type_room")),
|
||||
organisationunit: Vue.computed(() => this.$p.t("search/type_organisationunit")),
|
||||
cms: Vue.computed(() => this.$p.t("search/type_cms")),
|
||||
dms: Vue.computed(() => this.$p.t("search/type_dms"))
|
||||
},
|
||||
actions: {
|
||||
employee: {
|
||||
defaultaction: {
|
||||
@@ -44,7 +46,7 @@ const app = Vue.createApp({
|
||||
},
|
||||
childactions: []
|
||||
},
|
||||
raum: {
|
||||
room: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
renderif: function(data) {
|
||||
@@ -106,14 +108,37 @@ const app = Vue.createApp({
|
||||
}
|
||||
},
|
||||
childactions: []
|
||||
}
|
||||
},
|
||||
cms: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
action: function (data) {
|
||||
const link = FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
'/CisVue/Cms/content/' + data.content_id;
|
||||
return link;
|
||||
}
|
||||
},
|
||||
childactions: []
|
||||
},
|
||||
dms: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
action: function (data) {
|
||||
const link = FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
'cms/dms.php?id=' + data.dms_id;
|
||||
return link;
|
||||
}
|
||||
},
|
||||
childactions: []
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
searchfunction: function(searchsettings) {
|
||||
return this.$api.call(ApiSearchbar.search(searchsettings));
|
||||
return this.$api.call(ApiSearchbar.searchCis(searchsettings));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -75,12 +75,12 @@ export default {
|
||||
return {
|
||||
selected: [],
|
||||
searchbaroptions: {
|
||||
cssclass: "position-relative",
|
||||
origin: 'stv',
|
||||
calcheightonly: true,
|
||||
types: [
|
||||
"studentStv",
|
||||
"prestudent"
|
||||
],
|
||||
types: {
|
||||
student: Vue.computed(() => this.$p.t('search/type_student')),
|
||||
prestudent: Vue.computed(() => this.$p.t('search/type_prestudent'))
|
||||
},
|
||||
actions: {
|
||||
student: {
|
||||
defaultaction: {
|
||||
@@ -101,8 +101,28 @@ export default {
|
||||
},
|
||||
childactions: [
|
||||
]
|
||||
},
|
||||
mergedPerson: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
action: data => this.$fhcApi.getUri('/studentenverwaltung/person/' + data.person_id)
|
||||
},
|
||||
defaultactionstudent: {
|
||||
type: "link",
|
||||
action: data => {
|
||||
if (data.prestudent_id) {
|
||||
return this.$fhcApi.getUri('/studentenverwaltung/prestudent/' + data.prestudent_id);
|
||||
} else if (data.uid) {
|
||||
return this.$fhcApi.getUri('/studentenverwaltung/student/' + data.uid);
|
||||
} else {
|
||||
return this.$fhcApi.getUri('/studentenverwaltung/person/' + data.person_id);
|
||||
}
|
||||
}
|
||||
},
|
||||
childactions: []
|
||||
}
|
||||
}
|
||||
},
|
||||
mergeResults: 'person'
|
||||
},
|
||||
studiengangKz: undefined,
|
||||
studiensemesterKurzbz: this.defaultSemester,
|
||||
@@ -128,8 +148,8 @@ export default {
|
||||
reloadList() {
|
||||
this.$refs.stvList.reload();
|
||||
},
|
||||
searchfunction(params) {
|
||||
return this.$api.call(ApiSearchbar.search(params));
|
||||
searchfunction(params, config) {
|
||||
return this.$api.call(ApiSearchbar.searchStv(params), config);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -217,7 +237,11 @@ export default {
|
||||
<header class="navbar navbar-expand-lg navbar-dark bg-dark flex-md-nowrap p-0 shadow">
|
||||
<a class="navbar-brand col-md-4 col-lg-3 col-xl-2 me-0 px-3" :href="stvRoot">FHC 4.0</a>
|
||||
<button class="navbar-toggler d-md-none m-1 collapsed" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" :aria-label="$p.t('ui/toggle_nav')"><span class="navbar-toggler-icon"></span></button>
|
||||
<core-searchbar :searchoptions="searchbaroptions" :searchfunction="searchfunction" class="searchbar w-100"></core-searchbar>
|
||||
<core-searchbar
|
||||
:searchoptions="searchbaroptions"
|
||||
:searchfunction="searchfunction"
|
||||
class="searchbar position-relative w-100"
|
||||
></core-searchbar>
|
||||
</header>
|
||||
<div class="container-fluid overflow-hidden">
|
||||
<div class="row h-100">
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
res: {
|
||||
type: Object
|
||||
},
|
||||
action: {
|
||||
type: Object
|
||||
},
|
||||
cssclass: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
template: `
|
||||
<template v-if="this.renderif()">
|
||||
<a :class="this.cssclass" :href="this.getactionhref()"
|
||||
:alt="$p.t('ui','aktion')"
|
||||
@click="this.execaction()">
|
||||
<slot>Action</slot>
|
||||
</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
<slot>Action</slot>
|
||||
</template>
|
||||
`,
|
||||
methods: {
|
||||
getactionhref: function() {
|
||||
return (this.action.type === 'link') ? this.action.action(this.res)
|
||||
: 'javascript:void(0);';
|
||||
},
|
||||
execaction: function() {
|
||||
this.action.action(this.res);
|
||||
this.$emit('actionexecuted');
|
||||
},
|
||||
renderif: function() {
|
||||
if(this.action?.renderif === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return this.action.renderif(this.res);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
import action from "./action.js";
|
||||
|
||||
export default {
|
||||
props: [ "res", "actions" ],
|
||||
components: {
|
||||
action: action
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
template: `
|
||||
<ul class="searchbar_actions" v-if="this.actions.length > 0">
|
||||
<template v-for="(action, index) in this.actions" :key="action.label">
|
||||
<li v-if="this.renderif(action)">
|
||||
<action :res="this.res" :action="action" :cssclass="'btn btn-primary btn-sm'" @actionexecuted="$emit('actionexecuted')">
|
||||
<i v-if="this.hasicon(index)" :class="this.geticonclass(index)"></i>
|
||||
<span class="p-2">{{ action.label }}</span>
|
||||
</action>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<div class="mb-3" v-else=""></div>
|
||||
`,
|
||||
methods: {
|
||||
hasicon: function(index) {
|
||||
return (typeof this.actions[index].icon !== "undefined");
|
||||
},
|
||||
geticonclass: function(index) {
|
||||
return this.actions[index].icon;
|
||||
},
|
||||
renderif: function(action) {
|
||||
if(action?.renderif === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return action.renderif(this.res);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
import action from "./action.js";
|
||||
import actions from "./actions.js";
|
||||
|
||||
export default {
|
||||
props: [ "res", "actions" ],
|
||||
components: {
|
||||
action: action,
|
||||
actions: actions
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
template: `
|
||||
<div class="searchbar_result searchbar_employee">
|
||||
|
||||
<div class="searchbar_grid">
|
||||
<div class="searchbar_icon">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<img v-if="(typeof res.photo_url !== 'undefined') && (res.photo_url !== null)" :alt="$p.t('profilUpdate','profilBild')" :src="res.photo_url"
|
||||
class="rounded" style="max-height: 120px; max-width: 90px;" />
|
||||
<i v-else class="fas fa-user-circle fa-5x"></i>
|
||||
</action>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_data">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<span class="fw-bold">{{ res.name }}</span>
|
||||
</action>
|
||||
|
||||
<div class="mb-3"></div>
|
||||
|
||||
<div class="searchbar_table">
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Standard-Kostenstelle</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<ul class="searchbar_inline_ul" v-if="res.standardkostenstelle.length > 0">
|
||||
<li v-for="(stdkst, idx) in res.standardkostenstelle" :key="idx">{{ stdkst }}</li>
|
||||
</ul>
|
||||
<span v-else="">keine</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Organisations-Einheit</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<ul class="searchbar_inline_ul" v-if="res.organisationunit_name.length > 0">
|
||||
<li v-for="(oe, idx) in res.organisationunit_name" :key="idx">{{ oe }}</li>
|
||||
</ul>
|
||||
<span v-else="">keine</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">EMail</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="this.mailtourl">
|
||||
{{ res.email }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Telefon</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="this.telurl">
|
||||
{{ res.phone }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<actions :res="this.res" :actions="this.actions.childactions" @actionexecuted="$emit('actionexecuted')"></actions>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
},
|
||||
computed: {
|
||||
mailtourl: function() {
|
||||
return 'mailto:' + this.res.email;
|
||||
},
|
||||
telurl: function() {
|
||||
return 'tel:' + this.res.phone;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,83 +0,0 @@
|
||||
import action from "./action.js";
|
||||
import actions from "./actions.js";
|
||||
|
||||
export default {
|
||||
props: [ "res", "actions" ],
|
||||
components: {
|
||||
action: action,
|
||||
actions: actions
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
template: `
|
||||
<div class="searchbar_result searchbar_organisationunit">
|
||||
|
||||
<div class="searchbar_grid">
|
||||
<div class="searchbar_icon">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<i class="fas fa-sitemap fa-4x" aria-hidden="true"></i>
|
||||
</action>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_data">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<span class="fw-bold">{{ res.name }}</span>
|
||||
</action>
|
||||
|
||||
<div class="mb-3"></div>
|
||||
|
||||
<div class="searchbar_table">
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">übergeordnete OrgEinheit</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.parentoe_name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Gruppen-EMail</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="this.mailtourl" v-if="res.mailgroup">
|
||||
{{ res.mailgroup }}
|
||||
</a>
|
||||
<span v-else>-</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Leiter</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<ul class="searchbar_inline_ul" v-if="res.leaders.length > 0">
|
||||
<li v-for="(leader, idx) in res.leaders" :key="idx">{{ leader.name }}</li>
|
||||
</ul>
|
||||
<span v-else="">N.N.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Mitarbeiter-Anzahl</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.number_of_people }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<actions :res="this.res" :actions="this.actions.childactions" @actionexecuted="$emit('actionexecuted')"></actions>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
},
|
||||
computed: {
|
||||
mailtourl: function() {
|
||||
return 'mailto:' + this.res.mailgroup;
|
||||
},
|
||||
telurl: function() {
|
||||
return 'tel:' + this.res.phone;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,56 +0,0 @@
|
||||
import action from "./action.js";
|
||||
import actions from "./actions.js";
|
||||
|
||||
export default {
|
||||
props: [ "res", "actions" ],
|
||||
components: {
|
||||
action: action,
|
||||
actions: actions
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
template: `
|
||||
<div class="searchbar_result searchbar_person">
|
||||
|
||||
<div class="searchbar_grid">
|
||||
<div class="searchbar_icon">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<img v-if="(typeof res.foto !== 'undefined') && (res.foto !== null)"
|
||||
:alt="$p.t('profilUpdate','profilBild')" :src="res.foto"
|
||||
class="rounded" style="max-height: 120px; max-width: 90px;" />
|
||||
<i v-else class="fas fa-user-circle fa-5x"></i>
|
||||
</action>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_data">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<span class="fw-bold">{{ res.gn }} {{ res.sn }}</span>
|
||||
</action>
|
||||
|
||||
<div class="mb-3"></div>
|
||||
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">EMail</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="this.mailtourl">
|
||||
{{ res.mail }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<actions :res="this.res" :actions="this.actions.childactions" @actionexecuted="$emit('actionexecuted')"></actions>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
},
|
||||
computed: {
|
||||
mailtourl: function() {
|
||||
return 'mailto:' + this.res.mail;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
import action from "./action.js";
|
||||
import actions from "./actions.js";
|
||||
|
||||
export default {
|
||||
props: [ "res", "actions" ],
|
||||
components: {
|
||||
action: action,
|
||||
actions: actions
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
template: `
|
||||
<div class="searchbar_result searchbar_prestudent">
|
||||
|
||||
<div class="searchbar_grid">
|
||||
<div class="searchbar_icon">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<img v-if="(typeof res.foto !== 'undefined') && (res.foto !== null)"
|
||||
:alt="$p.t('profilUpdate','profilBild')"
|
||||
:src="'data:image/jpeg;base64,' + res.foto"
|
||||
class="rounded-circle" height="100"/>
|
||||
<i v-else class="fas fa-user-circle fa-5x"></i>
|
||||
</action>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_data">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<span class="fw-bold">{{ res.name }}</span>
|
||||
</action>
|
||||
|
||||
<div class="mb-3"></div>
|
||||
|
||||
<div class="searchbar_table">
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Prestudent_id</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.prestudent_id }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Student_uid</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.uid }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Person_id</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.person_id }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Studiengang</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.bezeichnung }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">EMail</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="this.mailtourl">
|
||||
{{ res.email }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<actions :res="this.res" :actions="this.actions.childactions"
|
||||
@actionexecuted="$emit('actionexecuted')"></actions>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
},
|
||||
computed: {
|
||||
mailtourl: function() {
|
||||
return 'mailto:' + this.res.email;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
import action from "./action.js";
|
||||
import actions from "./actions.js";
|
||||
|
||||
export default {
|
||||
props: [ "res", "actions" ],
|
||||
components: {
|
||||
action: action,
|
||||
actions: actions
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
template: /*html*/`
|
||||
<div class="searchbar_result searchbar_raum">
|
||||
<div class="searchbar_grid">
|
||||
<div class="searchbar_icon">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<i class="fas fa-door-open fa-4x" aria-hidden="true"></i>
|
||||
</action>
|
||||
</div>
|
||||
<div class="searchbar_data">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<span class="fw-bold">{{ res.ort_kurzbz }}</span>
|
||||
</action>
|
||||
|
||||
<div class="mb-3"></div>
|
||||
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Standort</div>
|
||||
<div class="searchbar_tablecell searchbar_value">{{ res.standort }}</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Sitzplätze</div>
|
||||
<div class="searchbar_tablecell searchbar_value">{{ res.sitzplaetze }}</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Gebäude</div>
|
||||
<div class="searchbar_tablecell searchbar_value">{{ res.building }}</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Zusatz Informationen</div>
|
||||
<div class="searchbar_tablecell searchbar_value"><div v-html="res.austattung.replace('<br />','')"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<actions :res="this.res" :actions="this.actions.childactions" @actionexecuted="$emit('actionexecuted')"></actions>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultCms',
|
||||
components: {
|
||||
TemplateFrame
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
inject: [
|
||||
'query'
|
||||
],
|
||||
computed: {
|
||||
preview() {
|
||||
if (this.res.template_kurzbz != 'redirect') {
|
||||
let text = this.res.content.replace(/<!\[CDATA\[|\]\]>/ig, '').replace(/<[^>]+>/ig, '').replace(/^\s+|\s+$/g, '');
|
||||
|
||||
if (text.length > 1000) {
|
||||
// NOTE(chris): focus on searched text!
|
||||
let lower = text.toLowerCase();
|
||||
let firstOccurence = Math.min(this.query.split(' ').reduce((a, c) => {
|
||||
// NOTE(chris): filter query for words that affects the content field and get the lowest index of them
|
||||
if (c == 'or')
|
||||
return a;
|
||||
let i = c.indexOf(':');
|
||||
if (i < 0 || (i > 0 && ['content', 'inhalt'].includes(c.split(':')[0]))) {
|
||||
let posInText = lower.indexOf(c);
|
||||
if (posInText >= 0)
|
||||
a.push(posInText);
|
||||
}
|
||||
return a;
|
||||
}, []));
|
||||
|
||||
if (firstOccurence) {
|
||||
if (firstOccurence + 997 >= text.length) {
|
||||
firstOccurence = text.length - 997;
|
||||
if (firstOccurence > 0)
|
||||
return '...' + text.substr(firstOccurence, 997);
|
||||
} else {
|
||||
return '...' + text.substr(firstOccurence, 994) + '...';
|
||||
}
|
||||
}
|
||||
|
||||
text = text.substr(0, 997) + '...';
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
let url = this.res.content_url;
|
||||
if (url.substr(0, 16) == '../index.ci.php/')
|
||||
url = this.$fhcApi.getUri(url.substr(16));
|
||||
else if (url.substr(0, 3) == '../')
|
||||
url = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/\/+$/, '') + url.substr(2);
|
||||
return '<a href="' + url + '">' + url + '</a>';
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-cms"
|
||||
:res="res"
|
||||
:actions="actions"
|
||||
:title="res.title"
|
||||
image-fallback="fas fa-newspaper fa-4x"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div v-if="preview" class="searchbar_table" v-html="preview"></div>
|
||||
<div v-else class="searchbar_table text-muted">
|
||||
{{ $p.t('search/result_content_none') }}
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultDms',
|
||||
components: {
|
||||
TemplateFrame
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
computed: {
|
||||
icon() {
|
||||
switch (this.res.mimetype) {
|
||||
case 'application/pdf':
|
||||
return 'file-pdf';
|
||||
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
|
||||
case 'application/msword':
|
||||
return 'file-word';
|
||||
case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
|
||||
case 'application/mspowerpoint':
|
||||
return 'file-powerpoint';
|
||||
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
|
||||
case 'application/vnd.ms-excel':
|
||||
return 'file-excel';
|
||||
case 'application/x-zip':
|
||||
case 'application/zip':
|
||||
return 'file-zipper';
|
||||
case 'image/jpeg':
|
||||
case 'image/gif':
|
||||
case 'image/png':
|
||||
return 'file-image';
|
||||
default:
|
||||
return 'file';
|
||||
}
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-dms"
|
||||
:res="res"
|
||||
:actions="actions"
|
||||
:title="res.name"
|
||||
:image-fallback="'fas fa-' + icon + ' fa-4x'"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_dms_id') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.dms_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_version') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.version }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_keywords') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.keywords }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('global/beschreibung') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultEmployee',
|
||||
components: {
|
||||
TemplateFrame
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-student"
|
||||
:res="res"
|
||||
:actions="actions"
|
||||
:title="res.name"
|
||||
:image="res.photo_url"
|
||||
image-fallback="fas fa-user fa-4x"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_stdkst') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<ul class="searchbar_inline_ul" v-if="res.standardkostenstelle.length > 0">
|
||||
<li v-for="(stdkst, idx) in res.standardkostenstelle" :key="idx">{{ stdkst }}</li>
|
||||
</ul>
|
||||
<span v-else="">{{ $p.t('search/result_stdkst_none') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('lehre/organisationseinheit') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<ul class="searchbar_inline_ul" v-if="res.organisationunit_name.length > 0">
|
||||
<li v-for="(oe, idx) in res.organisationunit_name" :key="idx">{{ oe }}</li>
|
||||
</ul>
|
||||
<span v-else="">{{ $p.t('search/result_oe_none') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_emails') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="'mailto:' + res.email" class="d-block">
|
||||
{{ res.email }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('person/telefon') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="'tel:' + res.phone" class="d-block">
|
||||
{{ res.phone }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,209 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
import TemplateAction from "./template/action.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultMergedperson',
|
||||
components: {
|
||||
TemplateFrame,
|
||||
TemplateAction
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
mode: String,
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
computed: {
|
||||
person() {
|
||||
// Cummulate all emails
|
||||
const email = this.res.list.reduce((a, c) => [...a, ...(Array.isArray(c.email) ? c.email : [c.email])], []);
|
||||
|
||||
// Use person entry if available (with cummulated emails)
|
||||
const person = this.res.list.find(item => item.type == 'person');
|
||||
if (person)
|
||||
return {...person, email};
|
||||
|
||||
// Those properties should be the same in all entries
|
||||
const { person_id, name } = this.res.list[0];
|
||||
// Get first photo (prefer student photo if available)
|
||||
let photo_url;
|
||||
if (this.mode == 'simple') {
|
||||
let foto = (this.students ? this.students.find(el => el.foto) : null)?.foto;
|
||||
if (foto)
|
||||
foto = 'data:image/jpeg;base64,' + foto;
|
||||
photo_url = foto || this.employee?.photo_url;
|
||||
} else
|
||||
photo_url = ((this.students ? this.students.find(el => el.photo_url) : null) || this.employee)?.photo_url;
|
||||
|
||||
return { person_id, name, photo_url, email };
|
||||
},
|
||||
employee() {
|
||||
return this.res.list.find(item => [
|
||||
'employee',
|
||||
'unassigned_employee',
|
||||
'mitarbeiter',
|
||||
'mitarbeiter_ohne_zuordnung'
|
||||
].includes(item.type)) || null;
|
||||
},
|
||||
students() {
|
||||
const students = this.res.list.filter(item => [
|
||||
'student',
|
||||
'prestudent',
|
||||
'studentcis',
|
||||
'studentStv'
|
||||
].includes(item.type))
|
||||
.filter((item, idx, arr) => {
|
||||
if (item.type === 'prestudent') {
|
||||
return true;
|
||||
}
|
||||
|
||||
let prestudentwithsameuidexists = arr.some(tmpitem => {
|
||||
return tmpitem.uid === item.uid && tmpitem.type === 'prestudent';
|
||||
});
|
||||
|
||||
if (prestudentwithsameuidexists) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}).sort((a, b) => (a.sort || 0) - (b.sort || 0));
|
||||
return students.length ? students : null;
|
||||
},
|
||||
emails() {
|
||||
// Remove duplicates
|
||||
return new Set(this.person.email);
|
||||
},
|
||||
telurl() {
|
||||
return 'tel:' + this.employee?.phone;
|
||||
},
|
||||
inaktiv() {
|
||||
return this.res.list.some(item => item?.aktiv === false);
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-mergedperson"
|
||||
:class="(inaktiv) ? 'searchbar_inaktiv' : ''"
|
||||
:res="person"
|
||||
:actions="actions"
|
||||
:title="person.name"
|
||||
:image="person.photo_url"
|
||||
image-fallback="fas fa-user fa-4x"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('person/person_id') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ person.person_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_emails') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a v-for="email in emails" :key="email" :href="'mailto:' + email" class="d-block">
|
||||
{{ email }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="employee">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell">
|
||||
<template-action
|
||||
:res="employee"
|
||||
:action="actions.defaultactionemployee || actions.defaultaction"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
{{ $p.t('search/result_employee') }}
|
||||
</template-action>
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label ps-3">{{ $p.t('search/result_stdkst') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<ul class="searchbar_inline_ul" v-if="employee.standardkostenstelle.length > 0">
|
||||
<li
|
||||
v-for="(stdkst, idx) in employee.standardkostenstelle"
|
||||
:key="idx"
|
||||
>
|
||||
{{ stdkst }}
|
||||
</li>
|
||||
</ul>
|
||||
<span v-else="">{{ $p.t('search/result_stdkst_none') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label ps-3">{{ $p.t('lehre/organisationseinheit') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<ul class="searchbar_inline_ul" v-if="employee.organisationunit_name.length > 0">
|
||||
<li
|
||||
v-for="(oe, idx) in employee.organisationunit_name"
|
||||
:key="idx"
|
||||
>
|
||||
{{ oe }}
|
||||
</li>
|
||||
</ul>
|
||||
<span v-else="">{{ $p.t('search/result_oe_none') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label ps-3">{{ $p.t('person/telefon') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="telurl">
|
||||
{{ employee.phone }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="students">
|
||||
<template v-for="student in students">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell">
|
||||
<template-action
|
||||
v-if="actions.defaultaction"
|
||||
:res="student"
|
||||
:action="actions.defaultactionstudent || actions.defaultaction"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<template v-if="mode == 'simple'">
|
||||
{{ student.studiengang_kz }}
|
||||
</template>
|
||||
<template v-else-if="student.status && student.stg_kuerzel">
|
||||
{{ student.status }} ({{ student.stg_kuerzel }})
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $p.t('person/student') }}
|
||||
</template>
|
||||
</template-action>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="student.bezeichnung" class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label ps-3">{{ $p.t('lehre/studiengang') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ student.bezeichnung }} {{ student.orgform ? '(' + student.orgform + ')' : '' }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="student.prestudent_id" class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label ps-3">{{ $p.t('search/result_prestudent_id') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ student.prestudent_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="student.uid" class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label ps-3">{{ $p.t('search/result_student_uid') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ student.uid }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="student.matrikelnr" class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label ps-3">{{ $p.t('person/matrikelnummer') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ student.matrikelnr }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
import ResultPrestudent from "./prestudent.js";
|
||||
import ResultStudent from "./student.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultMergedstudent',
|
||||
components: {
|
||||
ResultPrestudent,
|
||||
ResultStudent
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
mode: String,
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
computed: {
|
||||
prestudent() {
|
||||
const prestudent = this.res.list.filter(item => item.type == 'prestudent');
|
||||
return prestudent.pop();
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<result-prestudent
|
||||
v-if="prestudent"
|
||||
:mode="mode"
|
||||
:res="prestudent"
|
||||
:actions="actions"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
class="searchbar-result-mergedstudent"
|
||||
></result-prestudent>
|
||||
<result-student
|
||||
v-else
|
||||
:mode="mode"
|
||||
:res="res.list[0]"
|
||||
:actions="actions"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
class="searchbar-result-mergedstudent"
|
||||
></result-student>`
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultOrganistationunit',
|
||||
components: {
|
||||
TemplateFrame
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-organisationunit"
|
||||
:res="res"
|
||||
:actions="actions"
|
||||
:title="res.name"
|
||||
image-fallback="fas fa-sitemap fa-4x"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_parent_oe') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.parentoe_name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_group_emails') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a v-if="res.mailgroup" :href="'mailto:' + res.mailgroup">
|
||||
{{ res.mailgroup }}
|
||||
</a>
|
||||
<template v-else>-</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_leader') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<ul class="searchbar_inline_ul" v-if="res.leaders.length > 0">
|
||||
<li v-for="(leader, idx) in res.leaders" :key="idx">{{ leader.name }}</li>
|
||||
</ul>
|
||||
<span v-else="">{{ $p.t('search/result_leader_none') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_number_of_employees') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.number_of_people }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultPerson',
|
||||
components: {
|
||||
TemplateFrame
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
computed: {
|
||||
emails() {
|
||||
return new Set(this.res.email);
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-student"
|
||||
:res="res"
|
||||
:actions="actions"
|
||||
:title="res.name"
|
||||
:image="res.photo_url"
|
||||
image-fallback="fas fa-user fa-4x"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('person/person_id') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.person_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_emails') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a v-for="email in emails" :key="email" :href="'mailto:' + email" class="d-block">
|
||||
{{ email }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultPrestudent',
|
||||
components: {
|
||||
TemplateFrame
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
mode: String,
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
if (this.mode == 'simple')
|
||||
return this.res.name;
|
||||
return this.res.name + ' (' + this.res.status + ' ' + this.res.stg_kuerzel + ')';
|
||||
},
|
||||
photo_url() {
|
||||
if (this.mode != 'simple')
|
||||
return this.res.photo_url;
|
||||
if (this.res.foto)
|
||||
return 'data:image/jpeg;base64,' + this.res.foto;
|
||||
return null;
|
||||
},
|
||||
emails() {
|
||||
if (this.mode == 'simple')
|
||||
return new Set([this.res.email]);
|
||||
return new Set(this.res.email);
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-prestudent"
|
||||
:res="res"
|
||||
:actions="actions"
|
||||
:title="title"
|
||||
:image="photo_url"
|
||||
image-fallback="fas fa-user fa-4x"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('person/person_id') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.person_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_emails') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a v-for="email in emails" :key="email" :href="'mailto:' + email" class="d-block">
|
||||
{{ email }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="res.uid" class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_student_uid') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.uid }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="res.matrikelnr" class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('person/matrikelnummer') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.matrikelnr }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_prestudent_id') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.prestudent_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('lehre/studiengang') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.bezeichnung }} {{ res.orgform ? '(' + res.orgform + ')' : '' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultRoom',
|
||||
components: {
|
||||
TemplateFrame
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
mode: String,
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
computed: {
|
||||
equipment() {
|
||||
if (!this.res.equipment)
|
||||
return "";
|
||||
return this.res.equipment.replace(new RegExp('<br />', 'ig'), '');
|
||||
},
|
||||
address() {
|
||||
let address = this.res.zip || '';
|
||||
if (this.res.city)
|
||||
address += (address ? ' ' : '') + this.res.city;
|
||||
if (this.res.street)
|
||||
address += (address ? ', ' : '') + this.res.street;
|
||||
if (this.res.floor)
|
||||
address += (address ? ' / ' : '') + this.$p.t('search/result_address_floor', this.res);
|
||||
|
||||
return address || this.$p.t('search/result_address_none');
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-room"
|
||||
:res="res"
|
||||
:actions="actions"
|
||||
:title="res.ort_kurzbz"
|
||||
image-fallback="fas fa-door-open fa-4x"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_room_address') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ address }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_workplaces') }}</div>
|
||||
<div v-if="mode == 'simple'" class="searchbar_tablecell searchbar_value">
|
||||
{{ res.sitzplaetze }}
|
||||
</div>
|
||||
<div v-else class="searchbar_tablecell searchbar_value">
|
||||
<template v-if="res.max_person !== null && res.workplaces !== null">
|
||||
{{ $p.t('search/result_workplaces_pc', res) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ $p.t('search/result_workplaces_none') }}
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_building') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.building }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_equipment') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<div v-if="mode == 'simple'" class="no-margin-paragraphs" v-html="res.austattung.replace('<br />','')"></div>
|
||||
<div v-else class="no-margin-paragraphs" v-html="equipment"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
import TemplateFrame from "./template/frame.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultStudent',
|
||||
components: {
|
||||
TemplateFrame
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
mode: String,
|
||||
res: Object,
|
||||
actions: Object
|
||||
},
|
||||
computed: {
|
||||
photo_url() {
|
||||
if (this.mode != 'simple')
|
||||
return this.res.photo_url;
|
||||
if (this.res.foto)
|
||||
return 'data:image/jpeg;base64,' + this.res.foto;
|
||||
return null;
|
||||
},
|
||||
emails() {
|
||||
if (this.mode == 'simple')
|
||||
return new Set([this.res.email]);
|
||||
return new Set(this.res.email);
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<template-frame
|
||||
class="searchbar-result-student"
|
||||
:res="res"
|
||||
:actions="actions"
|
||||
:title="res.name"
|
||||
:image="photo_url"
|
||||
image-fallback="fas fa-user fa-4x"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<div class="searchbar_table">
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_student_uid') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.uid }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('person/person_id') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.person_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('person/matrikelnummer') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.matrikelnr }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{ $p.t('search/result_emails') }}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a v-for="email in emails" :key="email" :href="'mailto:' + email" class="d-block">
|
||||
{{ email }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template-frame>`
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
export default {
|
||||
name: 'SearchbarResultTemplateAction',
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
res: Object,
|
||||
action: Object
|
||||
},
|
||||
computed: {
|
||||
actionHref() {
|
||||
if (this.action.type !== 'link')
|
||||
return 'javascript:void(0);';
|
||||
return typeof this.action.action === 'function'
|
||||
? this.action.action(this.res)
|
||||
: this.action.action;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
actionFunc() {
|
||||
if (this.action.type !== 'function')
|
||||
return;
|
||||
this.action.action(this.res);
|
||||
this.$emit('actionexecuted');
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<a class="searchbar-result-template-action" :href="actionHref" @click="actionFunc">
|
||||
<slot>{{ $p.t('search/action_default_label') }}</slot>
|
||||
</a>`
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
import ResultAction from "./action.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultTemplateActions',
|
||||
components: {
|
||||
ResultAction
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
res: Object,
|
||||
actions: Array
|
||||
},
|
||||
template: `
|
||||
<div v-if="actions.length" class="searchbar-result-template-actions">
|
||||
<result-action
|
||||
v-for="(action, index) in actions"
|
||||
:key="action.label"
|
||||
:res="res"
|
||||
:action="action"
|
||||
class="btn btn-primary btn-sm"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
<i v-if="action.icon" :class="action.icon"></i>
|
||||
<span class="p-2">{{ action.label }}</span>
|
||||
</result-action>
|
||||
</div>`
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
import ResultAction from "./action.js";
|
||||
import ResultActions from "./actions.js";
|
||||
|
||||
export default {
|
||||
name: 'SearchbarResultTemplateFrame',
|
||||
components: {
|
||||
ResultAction,
|
||||
ResultActions
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
props: {
|
||||
res: Object,
|
||||
actions: Object,
|
||||
title: String,
|
||||
image: String,
|
||||
imageFallback: String
|
||||
},
|
||||
template: `
|
||||
<div class="searchbar-result-template-frame">
|
||||
<div class="searchbar_grid">
|
||||
<div class="searchbar_icon">
|
||||
<result-action
|
||||
:res="res"
|
||||
:action="actions.defaultaction"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
class="searchbar-rounded-image"
|
||||
>
|
||||
<img
|
||||
v-if="image"
|
||||
:src="image"
|
||||
/>
|
||||
<div v-else>
|
||||
<i :class="imageFallback"></i>
|
||||
</div>
|
||||
</result-action>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_data">
|
||||
<result-action
|
||||
:res="res"
|
||||
:action="actions.defaultaction"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
class="mb-3"
|
||||
>
|
||||
<span class="fw-bold">{{ title }}</span>
|
||||
</result-action>
|
||||
|
||||
<slot></slot>
|
||||
|
||||
<result-actions
|
||||
:res="res"
|
||||
:actions="actions.childactions"
|
||||
@actionexecuted="$emit('actionexecuted')"
|
||||
>
|
||||
</result-actions>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
};
|
||||
@@ -1,137 +1,206 @@
|
||||
import person from "./person.js";
|
||||
import raum from "./raum.js";
|
||||
import employee from "./employee.js";
|
||||
import organisationunit from "./organisationunit.js";
|
||||
import student from "./student.js";
|
||||
import prestudent from "./prestudent.js";
|
||||
import person from "./result/person.js";
|
||||
import room from "./result/room.js";
|
||||
import employee from "./result/employee.js";
|
||||
import organisationunit from "./result/organisationunit.js";
|
||||
import student from "./result/student.js";
|
||||
import prestudent from "./result/prestudent.js";
|
||||
import dms from "./result/dms.js";
|
||||
import cms from "./result/cms.js";
|
||||
import mergedStudent from "./result/mergedstudent.js";
|
||||
import mergedPerson from "./result/mergedperson.js";
|
||||
|
||||
export default {
|
||||
name: "FhcSearchbar",
|
||||
components: {
|
||||
person,
|
||||
room,
|
||||
employee,
|
||||
organisationunit,
|
||||
student,
|
||||
prestudent,
|
||||
dms,
|
||||
cms,
|
||||
mergedStudent,
|
||||
mergedPerson
|
||||
},
|
||||
props: [ "searchoptions", "searchfunction" ],
|
||||
provide() {
|
||||
return {
|
||||
query: Vue.computed(() => this.lastQuery)
|
||||
};
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
searchtimer: null,
|
||||
hidetimer: null,
|
||||
searchsettings: {
|
||||
searchstr: this.getSearchStr(),
|
||||
types: this.getSearchTypes(),
|
||||
types: this.getInitiallySelectedTypes(),
|
||||
},
|
||||
searchresult: [],
|
||||
searchmode: '',
|
||||
showresult: false,
|
||||
searching: false,
|
||||
error: null,
|
||||
settingsDropdown:null,
|
||||
abortController: null,
|
||||
settingsDropdown: null,
|
||||
lastQuery: ''
|
||||
};
|
||||
},
|
||||
components: {
|
||||
person: person,
|
||||
raum: raum,
|
||||
employee: employee,
|
||||
organisationunit: organisationunit,
|
||||
student: student,
|
||||
prestudent: prestudent
|
||||
},
|
||||
template: /*html*/`
|
||||
<form
|
||||
ref="searchform"
|
||||
class="d-flex me-3"
|
||||
:class="searchoptions.cssclass"
|
||||
action="javascript:void(0);"
|
||||
@focusin="searchfocusin"
|
||||
@focusout="searchfocusout"
|
||||
>
|
||||
<div ref="searchbox" class="h-100 input-group me-2">
|
||||
computed:{
|
||||
searchTypesPlaceholder() {
|
||||
if (!this.searchsettings.types.length) {
|
||||
return Object.values(this.typeLabels).join(' / ');
|
||||
}
|
||||
return this.searchsettings.types.map(type => this.typeLabels[type]).join(' / ');
|
||||
},
|
||||
types() {
|
||||
if (!this.searchoptions.types)
|
||||
return [];
|
||||
if (Array.isArray(this.searchoptions.types))
|
||||
return this.searchoptions.types;
|
||||
return Object.keys(this.searchoptions.types);
|
||||
},
|
||||
typeLabels() {
|
||||
if (!this.searchoptions.types)
|
||||
return {};
|
||||
if (Array.isArray(this.searchoptions.types)) {
|
||||
return this.searchoptions.types.reduce((res, type) => {
|
||||
res[type] = type;
|
||||
return res
|
||||
}, {});
|
||||
}
|
||||
return this.searchoptions.types;
|
||||
}
|
||||
},
|
||||
template: /*html*/`
|
||||
<form
|
||||
ref="searchform"
|
||||
class="d-flex me-3"
|
||||
action="javascript:void(0);"
|
||||
@focusin="searchfocusin"
|
||||
@focusout="searchfocusout"
|
||||
>
|
||||
<div
|
||||
ref="searchbox"
|
||||
class="h-100 input-group me-2 searchbar_searchbox"
|
||||
:class="showresult ? 'open' : 'closed'"
|
||||
>
|
||||
<span class="input-group-text">
|
||||
<i class="fa-solid fa-magnifying-glass"></i>
|
||||
</span>
|
||||
<input
|
||||
ref="input"
|
||||
@keyup="search"
|
||||
@focus="showsearchresult"
|
||||
v-model="searchsettings.searchstr"
|
||||
class="form-control"
|
||||
class="form-control searchbar_input"
|
||||
type="search"
|
||||
:placeholder="'Search: '+ search_types_string"
|
||||
aria-label="Search"
|
||||
:placeholder="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
:aria-label="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
>
|
||||
<span
|
||||
<button
|
||||
v-if="searchsettings.searchstr"
|
||||
class="searchbar_input_clear btn btn-outline-secondary"
|
||||
@click="clearInput"
|
||||
>
|
||||
<i class="fas fa-close"></i>
|
||||
</button>
|
||||
<button
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#searchSettings"
|
||||
aria-expanded="false"
|
||||
aria-controls="searchSettings"
|
||||
ref="settingsbutton"
|
||||
class="input-group-text"
|
||||
class="searchbar_setting_btn btn btn-secondary"
|
||||
type="button"
|
||||
:title="$p.t('search/button_filter_label')"
|
||||
:aria-label="$p.t('search/button_filter_label')"
|
||||
>
|
||||
<i class="fas fa-cog"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-show="this.showresult"
|
||||
<div v-show="showresult"
|
||||
class="searchbar_results" tabindex="-1">
|
||||
<div class="searchbar_results_scroller" ref="result">
|
||||
<div class="searchbar_results_wrapper" ref="results">
|
||||
<div v-if="this.searching">
|
||||
<div v-if="searching">
|
||||
<i class="fas fa-spinner fa-spin fa-2x"></i>
|
||||
</div>
|
||||
<div v-else-if="this.error !== null">{{ this.error }}</div>
|
||||
<div v-else-if="searchresult.length < 1">Es wurden keine Ergebnisse gefunden.</div>
|
||||
<template v-else="" v-for="res in searchresult">
|
||||
<person v-if="res.type === 'person'" :res="res" :actions="this.searchoptions.actions.person" @actionexecuted="this.hideresult"></person>
|
||||
<student v-else-if="res.type === 'student' || res.type === 'studentStv'" :res="res" :actions="this.searchoptions.actions.student" @actionexecuted="this.hideresult"></student>
|
||||
<prestudent v-else-if="res.type === 'prestudent'" :res="res" :actions="this.searchoptions.actions.prestudent" @actionexecuted="this.hideresult"></prestudent>
|
||||
<employee v-else-if="res.type === 'mitarbeiter' || res.type === 'mitarbeiter_ohne_zuordnung'" :res="res" :actions="this.searchoptions.actions.employee" @actionexecuted="this.hideresult"></employee>
|
||||
<organisationunit v-else-if="res.type === 'organisationunit'" :res="res" :actions="this.searchoptions.actions.organisationunit" @actionexecuted="this.hideresult"></organisationunit>
|
||||
<raum v-else-if="res.type === 'raum'" :res="res" :actions="this.searchoptions.actions.raum" @actionexecuted="this.hideresult"></raum>
|
||||
<div v-else="">Unbekannter Ergebnistyp: '{{ res.type }}'.</div>
|
||||
<div v-else-if="this.error !== null">{{ error }}</div>
|
||||
<div v-else-if="searchresult.length < 1">{{ $p.t('search/error_no_results') }}</div>
|
||||
<template v-else v-for="res in searchresult">
|
||||
<component
|
||||
v-if="isValidRenderer(res.renderer)"
|
||||
:is="res.renderer"
|
||||
:mode="searchmode"
|
||||
:res="res"
|
||||
:actions="searchoptions.actions[dash2camelCase(res.renderer)]"
|
||||
@actionexecuted="hideresult"
|
||||
></component>
|
||||
<div v-else class="searchbar-result text-danger fw-bold">{{ $p.t('search/error_unknown_type', res) }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="searchSettings" ref="settings"
|
||||
<div
|
||||
id="searchSettings"
|
||||
ref="settings"
|
||||
@[\`shown.bs.collapse\`]="handleShowSettings"
|
||||
@[\`hide.bs.collapse\`]="handleHideSettings"
|
||||
class="top-100 end-0 searchbar_settings text-white collapse" tabindex="-1">
|
||||
<div class="d-flex flex-column m-3" v-if="this.searchoptions.types.length > 0">
|
||||
<span class="fw-light mb-2">Suche filtern nach:</span>
|
||||
<template v-for="(type, index) in this.searchoptions.types" :key="type">
|
||||
<div class="form-check form-switch">
|
||||
<input class="fhc-switches form-check-input" type="checkbox" role="switch" :id="this.$.uid + 'search_type_' + index" :value="type" v-model="searchsettings.types" />
|
||||
<label class="ps-2 form-check-label non-selectable" :for="this.$.uid + 'search_type_' + index">{{ type }}</label>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
class="top-100 end-0 searchbar_settings text-white collapse"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div
|
||||
v-if="types.length > 0"
|
||||
class="d-flex flex-column m-3"
|
||||
>
|
||||
<span class="fw-light mb-2">
|
||||
{{ $p.t('search/applyfilter_label') }}
|
||||
</span>
|
||||
<template
|
||||
v-for="(label, value) in typeLabels"
|
||||
:key="value"
|
||||
>
|
||||
<div class="form-check form-switch">
|
||||
<input
|
||||
class="fhc-switches form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
:id="$.uid + 'search_type_' + value"
|
||||
:value="value"
|
||||
v-model="searchsettings.types"
|
||||
>
|
||||
<label
|
||||
class="ps-2 form-check-label non-selectable"
|
||||
:for="$.uid + 'search_type_' + value"
|
||||
>
|
||||
{{ label }}
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</form>
|
||||
`,
|
||||
watch:{
|
||||
'searchsettings.searchstr': function (newSearchValue, oldSearchValue) {
|
||||
'searchsettings.searchstr': function (newSearchValue) {
|
||||
if(this.searchoptions.origin){
|
||||
sessionStorage.setItem(`${this.searchoptions.origin}_searchstr`,newSearchValue);
|
||||
}
|
||||
},
|
||||
},
|
||||
computed:{
|
||||
search_types_string(){
|
||||
if (Array.isArray(this.searchsettings.types) && this.searchsettings.types.length > 0){
|
||||
return this.searchsettings.types.join(' / ');
|
||||
}else{
|
||||
return JSON.stringify(this.searchsettings.types);
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
beforeMount: function() {
|
||||
this.$watch('searchsettings.types', (newValue, oldValue) => {
|
||||
if (Array.isArray(newValue) && newValue.length === 0){
|
||||
this.searchsettings.types = this.allSearchTypes();
|
||||
'searchsettings.types'(newValue) {
|
||||
if (Array.isArray(newValue) && newValue.length === 0) {
|
||||
this.searchsettings.types = [...this.types];
|
||||
}
|
||||
// stores the search types in the localstorage, only if the newValue is also an array
|
||||
if(Array.isArray(newValue) && this.searchoptions.origin){
|
||||
if (Array.isArray(newValue) && this.searchoptions.origin) {
|
||||
localStorage.setItem(`${this.searchoptions.origin}_searchtypes`, JSON.stringify(newValue));
|
||||
}
|
||||
this.search();
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
this.settingsDropdown = new bootstrap.Collapse(this.$refs.settings, {
|
||||
@@ -150,22 +219,26 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getSearchTypes: function () {
|
||||
let result = this.allSearchTypes();
|
||||
clearInput() {
|
||||
this.searchsettings.searchstr = "";
|
||||
this.hideresult();
|
||||
this.$refs.input.focus()
|
||||
},
|
||||
getInitiallySelectedTypes() {
|
||||
let result = false;
|
||||
if (this.searchoptions.origin) {
|
||||
let localStorageValue = localStorage.getItem(`${this.searchoptions.origin}_searchtypes`);
|
||||
if (localStorageValue) {
|
||||
result = JSON.parse(localStorageValue);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
allSearchTypes() {
|
||||
let allTypes = [];
|
||||
for (const idx in this.searchoptions.types) {
|
||||
allTypes.push(this.searchoptions.types[idx]);
|
||||
};
|
||||
return allTypes;
|
||||
if (result)
|
||||
return result;
|
||||
if (!this.searchoptions.types)
|
||||
return [];
|
||||
if (Array.isArray(this.searchoptions.types))
|
||||
return [...this.searchoptions.types];
|
||||
return Object.keys(this.searchoptions.types);
|
||||
},
|
||||
getSearchStr: function(){
|
||||
if (!this.searchoptions.origin)
|
||||
@@ -187,12 +260,6 @@ export default {
|
||||
// removes the event listener checkSettingsVisibility when the collapsible is hidden
|
||||
document.removeEventListener("click", this.checkSettingsVisibility);
|
||||
},
|
||||
allSearchOptions: function() {
|
||||
this.searchsettings.types = [];
|
||||
for( const idx in this.searchoptions.types ) {
|
||||
this.searchsettings.types.push(this.searchoptions.types[idx]);
|
||||
}
|
||||
},
|
||||
calcSearchResultHeight: function() {
|
||||
const rect = this.$refs.results.getBoundingClientRect();
|
||||
if( rect.height > 0 && rect.height < (window.innerHeight * 0.8) ) {
|
||||
@@ -218,6 +285,10 @@ export default {
|
||||
if( this.searchtimer !== null ) {
|
||||
clearTimeout(this.searchtimer);
|
||||
}
|
||||
if (this.abortController) {
|
||||
this.abortController.abort();
|
||||
this.abortController = null;
|
||||
}
|
||||
if( this.searchsettings.searchstr.length >= 2 ) {
|
||||
this.calcSearchResultExtent();
|
||||
this.searchtimer = setTimeout(
|
||||
@@ -233,27 +304,82 @@ export default {
|
||||
this.searchresult.splice(0, this.searchresult.length);
|
||||
this.searching = true;
|
||||
this.showsearchresult();
|
||||
if(this.searchsettings.types.length === 0) {
|
||||
this.error = 'Kein Ergebnistyp ausgewählt. Bitte mindestens einen Ergebnistyp auswählen.';
|
||||
this.searching = false;
|
||||
return;
|
||||
}
|
||||
this.searchfunction(this.searchsettings)
|
||||
if(this.searchsettings.types.length === 0) {
|
||||
this.error = this.$p.t('search/error_missing_type');
|
||||
this.searching = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.abortController)
|
||||
this.abortController.abort();
|
||||
this.abortController = new AbortController();
|
||||
|
||||
this.searchfunction(this.searchsettings, { timeout: 50000, signal: this.abortController.signal })
|
||||
.then(response=>{
|
||||
if( response.data?.error === 1 ) {
|
||||
this.error = 'Bei der Suche ist ein Fehler aufgetreten.';
|
||||
if (!response.data) {
|
||||
this.error = this.$p.t('search/error_general');
|
||||
} else {
|
||||
for(let element of response.data.data){
|
||||
this.searchresult.push(element);
|
||||
let res = response.data.map(el => el.data ? {...el, ...JSON.parse(el.data)} : el);
|
||||
this.lastQuery = response.meta.searchstring;
|
||||
if (this.searchoptions.mergeResults) {
|
||||
let counter = 0;
|
||||
let mergeTypes = [];
|
||||
let mergedType = 'merged-';
|
||||
let mergeKey = '';
|
||||
|
||||
switch (this.searchoptions.mergeResults) {
|
||||
case 'student':
|
||||
mergeTypes = ['student', 'prestudent'];
|
||||
mergedType += this.searchoptions.mergeResults;
|
||||
mergeKey = 'uid';
|
||||
break;
|
||||
case 'person':
|
||||
mergeTypes = ['person', 'employee', 'student', 'prestudent'];
|
||||
mergedType += this.searchoptions.mergeResults;
|
||||
mergeKey = 'person_id';
|
||||
break;
|
||||
}
|
||||
|
||||
if (mergeTypes.length) {
|
||||
res = Object.values(res.reduce((a, c) => {
|
||||
if (!mergeTypes.includes(c.renderer)) {
|
||||
a['nomerge' + counter++] = c;
|
||||
} else if (c[mergeKey] === null) {
|
||||
a['nomerge' + counter++] = c;
|
||||
} else if (a[c[mergeKey]] === undefined) {
|
||||
a[c[mergeKey]] = {
|
||||
rank: c.rank,
|
||||
renderer: mergedType,
|
||||
type: mergedType,
|
||||
list: [c]
|
||||
};
|
||||
} else {
|
||||
a[c[mergeKey]].list.push(c);
|
||||
if (c.rank > a[c[mergeKey]].rank)
|
||||
a[c[mergeKey]].rank = c.rank;
|
||||
}
|
||||
return a;
|
||||
}, {})).sort((a, b) => b.rank - a.rank);
|
||||
}
|
||||
}
|
||||
this.searchresult = res;
|
||||
this.searchmode = response.meta.mode;
|
||||
}
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
})
|
||||
.catch(error=> {
|
||||
this.error = 'Bei der Suche ist ein Fehler aufgetreten.'
|
||||
+ ' ' + error.message;
|
||||
})
|
||||
.finally(()=> {
|
||||
if (error.code == "ERR_CANCELED") {
|
||||
return this.retry = 0;
|
||||
}
|
||||
if (error.code == "ECONNABORTED" && this.retry) {
|
||||
this.retry--;
|
||||
return this.callsearchapi();
|
||||
}
|
||||
|
||||
this.error = this.$p.t('search/error_general', error);
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
});
|
||||
},
|
||||
refreshsearch: function() {
|
||||
@@ -285,6 +411,13 @@ export default {
|
||||
this.hideresult,
|
||||
100
|
||||
);
|
||||
},
|
||||
dash2camelCase(string) {
|
||||
return string.replace(/-([a-z])/g, g => g[1].toUpperCase());
|
||||
},
|
||||
isValidRenderer(renderer) {
|
||||
const camelCaseRenderer = this.dash2camelCase(renderer);
|
||||
return Object.keys(this.$.components).includes(camelCaseRenderer);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
import action from "./action.js";
|
||||
import actions from "./actions.js";
|
||||
|
||||
export default {
|
||||
props: [ "res", "actions" ],
|
||||
components: {
|
||||
action: action,
|
||||
actions: actions
|
||||
},
|
||||
emits: [ 'actionexecuted' ],
|
||||
template: `
|
||||
<div class="searchbar_result searchbar_student" :class="(!res?.aktiv) ? 'searchbar_inaktiv' : ''">
|
||||
|
||||
<div class="searchbar_grid">
|
||||
<div class="searchbar_icon">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<img v-if="(typeof res.foto !== 'undefined') && (res.foto !== null)"
|
||||
:src="studentImage"
|
||||
:alt="$p.t('personUpdate','profilBild')"
|
||||
class="rounded" style="max-height: 120px; max-width: 90px;" />
|
||||
<i v-else class="fas fa-user-circle fa-5x"></i>
|
||||
</action>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_data">
|
||||
<action :res="this.res" :action="this.actions.defaultaction" @actionexecuted="$emit('actionexecuted')">
|
||||
<span class="fw-bold">{{ res.name }}</span>
|
||||
</action>
|
||||
|
||||
<div class="mb-3"></div>
|
||||
|
||||
<div class="searchbar_table">
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Student UID</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.uid }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{$p.t('lehre','studiengang')}}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.studiengang }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">Verband</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.verband }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{$p.t('person','personenkennzeichen')}}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
{{ res.matrikelnr }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchbar_tablerow">
|
||||
<div class="searchbar_tablecell searchbar_label">{{$p.t('person','email')}}</div>
|
||||
<div class="searchbar_tablecell searchbar_value">
|
||||
<a :href="this.mailtourl">
|
||||
{{ res.email }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<actions :res="this.res" :actions="this.actions.childactions"
|
||||
@actionexecuted="$emit('actionexecuted')"></actions>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
},
|
||||
computed: {
|
||||
mailtourl: function() {
|
||||
return 'mailto:' + this.res.email;
|
||||
},
|
||||
studentImage: function () {
|
||||
if (!this.res.foto) return;
|
||||
return 'data:image/jpeg;base64,'.concat(this.res.foto);
|
||||
},
|
||||
}
|
||||
};
|
||||
@@ -50,6 +50,8 @@ export default {
|
||||
function _clean_return_value(response) {
|
||||
const result = response.data;
|
||||
delete response.data;
|
||||
if (!result)
|
||||
return {meta: {response}, data: null};
|
||||
if (!result.meta)
|
||||
result.meta = {response};
|
||||
else
|
||||
|
||||
@@ -44,6 +44,8 @@ export default {
|
||||
function _clean_return_value(response) {
|
||||
const result = response.data;
|
||||
delete response.data;
|
||||
if (!result)
|
||||
return {meta: {response}, data: null};
|
||||
if (!result.meta)
|
||||
result.meta = {response};
|
||||
else
|
||||
|
||||
@@ -76,7 +76,7 @@ require_once('dbupdate_3.4/55289_pep_fine_tuning.php');
|
||||
require_once('dbupdate_3.4/55614_perm_verwaltetoe.php');
|
||||
require_once('dbupdate_3.4/25999_C4_dashboard.php');
|
||||
require_once('dbupdate_3.4/61730_Dashboard_Anpassungen.php');
|
||||
|
||||
require_once('dbupdate_3.4/40128_search.php');
|
||||
|
||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
if (!defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
// Activate module pg_trgm
|
||||
if (!$db->db_num_rows(@$db->db_query("SELECT 1
|
||||
FROM pg_extension WHERE extname = 'pg_trgm' LIMIT 1;")))
|
||||
{
|
||||
$qry = "CREATE extension pg_trgm;";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>Module pg_trgm ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'Module pg_trgm: activated<br>';
|
||||
}
|
||||
|
||||
|
||||
// Add additional computed columns
|
||||
// Add column fts_bezeichnung to public.tbl_organisationseinheit
|
||||
if (!@$db->db_query("SELECT fts_bezeichnung FROM public.tbl_organisationseinheit LIMIT 1"))
|
||||
{
|
||||
$qry = "ALTER TABLE public.tbl_organisationseinheit ADD COLUMN fts_bezeichnung tsvector;";
|
||||
$qry .= "COMMENT ON COLUMN public.tbl_organisationseinheit.fts_bezeichnung IS 'used for search - auto generated w triggers';";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong> public.tbl_organisationseinheit ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'public.tbl_organisationseinheit: new column "fts_bezeichnung" added<br>';
|
||||
}
|
||||
|
||||
// Add function tr_update_tbl_organisationseinheit_fts_bezeichnung to public
|
||||
if (!$db->db_num_rows(@$db->db_query("SELECT 1 FROM pg_proc WHERE proname = 'tr_update_tbl_organisationseinheit_fts_bezeichnung' LIMIT 1;")))
|
||||
{
|
||||
$qry = "CREATE FUNCTION tr_update_tbl_organisationseinheit_fts_bezeichnung()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE PLPGSQL
|
||||
AS
|
||||
$$
|
||||
BEGIN
|
||||
IF TG_TABLE_NAME = 'tbl_organisationseinheit' THEN
|
||||
NEW.fts_bezeichnung := to_tsvector('simple', COALESCE((
|
||||
SELECT bezeichnung
|
||||
FROM public.tbl_organisationseinheittyp
|
||||
WHERE organisationseinheittyp_kurzbz = NEW.organisationseinheittyp_kurzbz
|
||||
), '') || ' ' || COALESCE(NEW.bezeichnung, ''));
|
||||
ELSIF TG_TABLE_NAME = 'tbl_organisationseinheittyp' THEN
|
||||
UPDATE public.tbl_organisationseinheit
|
||||
SET fts_bezeichnung = to_tsvector('simple', COALESCE(NEW.bezeichnung, '') || ' ' || COALESCE(bezeichnung, ''))
|
||||
WHERE organisationseinheittyp_kurzbz = NEW.organisationseinheittyp_kurzbz;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong> public.tr_update_tbl_organisationseinheit_fts_bezeichnung ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'public.tr_update_tbl_organisationseinheit_fts_bezeichnung: function created<br>';
|
||||
}
|
||||
|
||||
$update_column = false;
|
||||
// Add trigger tr_organisationseinheit_update_organisationseinheittyp_kurzbz to public.tbl_organisationseinheit
|
||||
if (!$db->db_num_rows(@$db->db_query("
|
||||
SELECT 1
|
||||
FROM information_schema.triggers
|
||||
WHERE event_object_table ='tbl_organisationseinheit'
|
||||
AND trigger_name = 'tr_organisationseinheit_update_organisationseinheittyp_kurzbz'
|
||||
LIMIT 1;
|
||||
")))
|
||||
{
|
||||
$qry = "CREATE TRIGGER tr_organisationseinheit_update_organisationseinheittyp_kurzbz
|
||||
BEFORE UPDATE OF organisationseinheittyp_kurzbz OR INSERT
|
||||
ON public.tbl_organisationseinheit
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION tr_update_tbl_organisationseinheit_fts_bezeichnung();";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong> public.tbl_organisationseinheit ' . $db->db_last_error() . '</strong><br>';
|
||||
else {
|
||||
echo 'public.tbl_organisationseinheit: trigger "tr_organisationseinheit_update_organisationseinheittyp_kurzbz" created<br>';
|
||||
$update_column = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add trigger tr_organisationseinheittyp_update_bezeichnung to public.tbl_organisationseinheittyp
|
||||
if (!$db->db_num_rows(@$db->db_query("
|
||||
SELECT 1
|
||||
FROM information_schema.triggers
|
||||
WHERE event_object_table ='tbl_organisationseinheittyp'
|
||||
AND trigger_name = 'tr_organisationseinheittyp_update_bezeichnung'
|
||||
LIMIT 1;
|
||||
")))
|
||||
{
|
||||
$qry = "CREATE TRIGGER tr_organisationseinheittyp_update_bezeichnung
|
||||
BEFORE UPDATE OF bezeichnung
|
||||
ON public.tbl_organisationseinheittyp
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION tr_update_tbl_organisationseinheit_fts_bezeichnung();";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong> public.tbl_organisationseinheittyp ' . $db->db_last_error() . '</strong><br>';
|
||||
else {
|
||||
echo 'public.tbl_organisationseinheittyp: trigger "tr_organisationseinheittyp_update_bezeichnung" created<br>';
|
||||
$update_column = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update fts_bezeichnung on tbl_organisationseinheit with new triggers
|
||||
if ($update_column)
|
||||
{
|
||||
$qry = "UPDATE public.tbl_organisationseinheittyp SET bezeichnung = bezeichnung;";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong> public.tbl_organisationseinheit ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'public.tbl_organisationseinheit: column "fts_bezeichnung" updated<br>';
|
||||
}
|
||||
|
||||
|
||||
// Add Trigram Indexes
|
||||
// Add index for kontakt to public.tbl_kontakt
|
||||
if ($result = @$db->db_query("SELECT 1
|
||||
FROM pg_indexes WHERE indexname = 'idx_tbl_kontakt_kontakt_trgm';"))
|
||||
{
|
||||
if ($db->db_num_rows($result) == 0)
|
||||
{
|
||||
$qry = "CREATE INDEX idx_tbl_kontakt_kontakt_trgm ON public.tbl_kontakt USING GIN (COALESCE(kontakt, '') gin_trgm_ops);";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_kontakt ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'public.tbl_kontakt: added index "idx_tbl_kontakt_kontakt_trgm"<br>';
|
||||
}
|
||||
}
|
||||
// Add index for vorname to public.tbl_person
|
||||
if ($result = @$db->db_query("SELECT 1
|
||||
FROM pg_indexes WHERE indexname = 'idx_tbl_person_vorname_trgm';"))
|
||||
{
|
||||
if ($db->db_num_rows($result) == 0)
|
||||
{
|
||||
$qry = "CREATE INDEX idx_tbl_person_vorname_trgm ON public.tbl_person USING GIN (COALESCE(vorname, '') gin_trgm_ops);";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_person ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'public.tbl_person: added index "idx_tbl_person_vorname_trgm"<br>';
|
||||
}
|
||||
}
|
||||
// Add index for nachname to public.tbl_person
|
||||
if ($result = @$db->db_query("SELECT 1
|
||||
FROM pg_indexes WHERE indexname = 'idx_tbl_person_nachname_trgm';"))
|
||||
{
|
||||
if ($db->db_num_rows($result) == 0)
|
||||
{
|
||||
$qry = "CREATE INDEX idx_tbl_person_nachname_trgm ON public.tbl_person USING GIN (COALESCE(nachname, '') gin_trgm_ops);";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_person ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'public.tbl_person: added index "idx_tbl_person_nachname_trgm"<br>';
|
||||
}
|
||||
}
|
||||
// Add index for vorname || ' ' || nachname to public.tbl_person
|
||||
if ($result = @$db->db_query("SELECT 1
|
||||
FROM pg_indexes WHERE indexname = 'idx_tbl_person_name_trgm';"))
|
||||
{
|
||||
if ($db->db_num_rows($result) == 0)
|
||||
{
|
||||
$qry = "CREATE INDEX idx_tbl_person_name_trgm ON public.tbl_person USING GIN (COALESCE((vorname || ' ' || nachname), '') gin_trgm_ops);";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_person ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'public.tbl_person: added index "idx_tbl_person_name_trgm"<br>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add Vector Indexes
|
||||
// Add index for fts_bezeichnung to public.tbl_organisationseinheit
|
||||
if (!$db->db_num_rows(@$db->db_query("SELECT 1
|
||||
FROM pg_indexes WHERE indexname = 'idx_tbl_organisationseinheit_fts_bezeichnung_vector' LIMIT 1;")))
|
||||
{
|
||||
$qry = "CREATE INDEX idx_tbl_organisationseinheit_fts_bezeichnung_vector ON public.tbl_organisationseinheit USING GIN (fts_bezeichnung);";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_organisationseinheit ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'public.tbl_organisationseinheit: added index "idx_tbl_organisationseinheit_fts_bezeichnung_vector"<br>';
|
||||
}
|
||||
// Add index for titel || ' ' || content to campus.tbl_contentsprache
|
||||
if (!$db->db_num_rows(@$db->db_query("SELECT 1
|
||||
FROM pg_indexes WHERE indexname = 'idx_tbl_contentsprache_fts_titel_content_vector' LIMIT 1;")))
|
||||
{
|
||||
$qry = "
|
||||
CREATE INDEX idx_tbl_contentsprache_fts_titel_content_vector
|
||||
ON campus.tbl_contentsprache
|
||||
USING GIN ((
|
||||
setweight(to_tsvector('simple', COALESCE(titel, '')), 'A')
|
||||
|| setweight(to_tsvector('simple', COALESCE(content, '')::text), 'B')
|
||||
));
|
||||
";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>campus.tbl_contentsprache ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'campus.tbl_contentsprache: added index "idx_tbl_contentsprache_fts_titel_content_vector"<br>';
|
||||
}
|
||||
// Add index for schlagworte to campus.tbl_dms_version
|
||||
if (!$db->db_num_rows(@$db->db_query("SELECT 1
|
||||
FROM pg_indexes WHERE indexname = 'idx_tbl_dms_version_fts_schlagworte_vector' LIMIT 1;")))
|
||||
{
|
||||
$qry = "
|
||||
CREATE INDEX idx_tbl_dms_version_fts_schlagworte_vector
|
||||
ON campus.tbl_dms_version
|
||||
USING GIN ((to_tsvector('simple', COALESCE(schlagworte, ''))));
|
||||
";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>campus.tbl_dms_version ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo 'campus.tbl_contentsprache: added index "idx_tbl_dms_version_fts_schlagworte_vector"<br>';
|
||||
}
|
||||
@@ -46678,6 +46678,851 @@ and represent the current state of research on the topic. The prescribed citatio
|
||||
)
|
||||
),
|
||||
// FHC-4 Finetuning END
|
||||
|
||||
//**************************** CORE/search
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'input_search_label',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Suche: {types}',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Search: {types}',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'type_employee',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Mitarbeiter',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'employees',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'type_student',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Studenten',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'students',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'type_prestudent',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Prestudenten',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'prestudents',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'type_room',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Räume',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'rooms',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'type_organisationunit',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Organisationseinheiten',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'organisation units',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'type_cms',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Inhalte',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'sites',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'type_dms',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Dokumente',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'documents',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'button_filter_label',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Filter',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Filter',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'applyfilter_label',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Suche filtern nach:',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Filter search for:',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'action_default_label',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Standard Aktion',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Default Action',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_student_uid',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Student UID',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Student UID',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_prestudent_id',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Prestudent ID',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Prestudent ID',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_emails',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Emails',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Emails',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_group_emails',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Gruppen-Email',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Group-Email',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_employee',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'MitarbeiterIn',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Employee',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_stdkst',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Standard-Kostenstelle',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Standard cost center',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_stdkst_none',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'keine',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'none',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_parent_oe',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Übergeordnete OE',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Parent OU',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_oe_none',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'keine',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'none',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_room_address',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Standort',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Site',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_address_floor',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => '{floor} Stockwerk',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => '{floor} floor',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_address_none',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'N/A',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'N/A',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_workplaces',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Sitzplätze',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Seats',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_workplaces_pc',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => '{max_person}, davon {workplaces} PC-Plätze',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => '{max_person}, of which {workplaces} PC-Workstations',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_workplaces_none',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'N/A',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'N/A',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_building',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Gebäude',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Building',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_equipment',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Zusatz Informationen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Additional information',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_leader',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Leiter',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Leader',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_leader_none',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'N.N.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'N/A',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_number_of_employees',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Mitarbeiter-Anzahl',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Number of employees',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_dms_id',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'DMS ID',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'DMS ID',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_version',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Version',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Version',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_keywords',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Schlagwörter',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Keywords',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'result_content_none',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Kein Inhalt',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'No Content',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'error_missing_type',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Kein Ergebnistyp ausgewählt. Bitte mindestens einen Ergebnistyp auswählen.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'No result type selected. Please select at least one result type.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'error_no_results',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Es wurden keine Ergebnisse gefunden.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'No results were found.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'error_unknown_type',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Unbekannter Ergebnistyp: '{type}'.",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Unknown resulttype: '{type}'.",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'error_general',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Bei der Suche ist ein Fehler aufgetreten. {message}',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'An error occurred while searching. {message}',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'error_missing_config',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Such-Konfiguration $config["{type}"] nicht gefunden.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Search config $config["{type}"] not found.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'error_invalid_config',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Such-Konfiguration für $config["{type}"] ist ungültig: Feld "{field}" fehlt, ist leer oder hat einen ungültigen Typ.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Search config for $config["{type}"] is invalid: field {field} is missing, empty or has an invalid type.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'search',
|
||||
'phrase' => 'error_invalid_config_searchfield',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Such-Konfiguration ' .
|
||||
'$config["{type}"]["searchfields"]["{searchfield}"] ' .
|
||||
'ist ungültig: Feld "{field}" fehlt oder ist unglültig.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Search config $config["{type}"]["searchfields"]["{searchfield}"] is invalid: field {field} is missing or invalid.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
//**************************** CORE/search end
|
||||
);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user