mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-12 15:04:04 +00:00
formatting freebusy types
This commit is contained in:
@@ -44,13 +44,9 @@ class FreeBusy extends FHCAPI_Controller
|
||||
|
||||
public function getFreeBusyTypes()
|
||||
{
|
||||
$freeBusyTypesResult = $this->FreeBusyTypeModel->getAllFreeBusyTypes();
|
||||
$freeBusyTypesResult = $this->FreeBusyTypeModel->getActiveFreeBusyTypes();
|
||||
$freeBusyTypes = $this->getDataOrTerminateWithError($freeBusyTypesResult);
|
||||
// todo: are we using all types? are we changing base urls? are we changing tables?
|
||||
// tentatively filtering out most types, leaving only sogo and other
|
||||
$freeBusyTypes = array_values(array_filter($freeBusyTypes, function ($freeBusyType) {
|
||||
return in_array($freeBusyType->freebusytyp_kurzbz, ["Sonstiges", "SoGo"]);
|
||||
}));
|
||||
$freeBusyTypes = $this->formatDefaultUrlsInFreeBusyTypes($freeBusyTypes);
|
||||
$this->terminateWithSuccess($freeBusyTypes);
|
||||
|
||||
}
|
||||
@@ -66,7 +62,6 @@ class FreeBusy extends FHCAPI_Controller
|
||||
public function createFreeBusyEntry()
|
||||
{
|
||||
$description = $this->input->post("description");
|
||||
// todo: check if defaulting to other is fine
|
||||
$type = $this->input->post("type") ?? "Sonstiges";
|
||||
$url = $this->input->post("url");
|
||||
$isActive = $this->input->post("isActive");
|
||||
@@ -93,7 +88,6 @@ class FreeBusy extends FHCAPI_Controller
|
||||
{
|
||||
$id = $this->input->post("id");
|
||||
$description = $this->input->post("description");
|
||||
// todo: check if defaulting to other is fine
|
||||
$type = $this->input->post("type") ?? "Sonstiges";
|
||||
$url = $this->input->post("url");
|
||||
$isActive = $this->input->post("isActive");
|
||||
@@ -146,4 +140,20 @@ class FreeBusy extends FHCAPI_Controller
|
||||
{
|
||||
return !!@fopen($url, "r");
|
||||
}
|
||||
|
||||
private function formatDefaultUrlsInFreeBusyTypes($freeBusyTypes)
|
||||
{
|
||||
$uid = getAuthUID();
|
||||
return array_map(function ($freeBusyType) use ($uid) {
|
||||
if (!$freeBusyType->url_vorlage || !strlen($freeBusyType->url_vorlage)) {
|
||||
$freeBusyType->url_default = null;
|
||||
unset($freeBusyType->url_vorlage);
|
||||
return $freeBusyType;
|
||||
}
|
||||
|
||||
$freeBusyType->url_default = str_replace('$uid', $uid, $freeBusyType->url_vorlage);
|
||||
unset($freeBusyType->url_vorlage);
|
||||
return $freeBusyType;
|
||||
}, $freeBusyTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,4 +16,9 @@ class Freebusytyp_model extends DB_Model
|
||||
{
|
||||
return $this->execReadOnlyQuery("SELECT * FROM " . $this->dbTable);
|
||||
}
|
||||
|
||||
public function getActiveFreeBusyTypes()
|
||||
{
|
||||
return $this->execReadOnlyQuery("SELECT * FROM " . $this->dbTable . " WHERE is_active");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ export default {
|
||||
externalSchedules: [],
|
||||
scheduleEditIndex: null,
|
||||
scheduleFormData: null,
|
||||
scheduleTypeOptions: [],
|
||||
scheduleTypes: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getScheduleTypeText(value) {
|
||||
let type = this.scheduleTypeOptions.find(
|
||||
let type = this.scheduleTypes.find(
|
||||
(type) => type.value === value,
|
||||
);
|
||||
return type?.text ?? "Other";
|
||||
@@ -95,11 +95,12 @@ export default {
|
||||
const freeBusyTypesResponse = await this.$api.call(
|
||||
FreeBusyApi.getFreeBusyTypes(),
|
||||
);
|
||||
this.scheduleTypeOptions = freeBusyTypesResponse.data.map(
|
||||
this.scheduleTypes = freeBusyTypesResponse.data.map(
|
||||
(type) => {
|
||||
return {
|
||||
value: type.freebusytyp_kurzbz,
|
||||
text: type.bezeichnung,
|
||||
urlDefault: type.url_default,
|
||||
};
|
||||
},
|
||||
);
|
||||
@@ -110,19 +111,10 @@ export default {
|
||||
);
|
||||
this.externalSchedules = freeBusyEntriesResponse.data.map(
|
||||
(freeBusySchedule) => {
|
||||
// todo: remove type defaulting if switch to using all types
|
||||
let type = this.scheduleTypeOptions.find((type) => {
|
||||
return (
|
||||
type.value === freeBusySchedule.freebusytyp_kurzbz
|
||||
);
|
||||
})
|
||||
? freeBusySchedule.freebusytyp_kurzbz
|
||||
: "Sonstiges";
|
||||
|
||||
return {
|
||||
id: freeBusySchedule.freebusy_id,
|
||||
description: freeBusySchedule.bezeichnung,
|
||||
type,
|
||||
type: freeBusySchedule.freebusytyp_kurzbz,
|
||||
url: freeBusySchedule.url,
|
||||
isActive: freeBusySchedule.aktiv,
|
||||
};
|
||||
@@ -152,34 +144,56 @@ export default {
|
||||
{{ "To effectively use FreeBusy, you must carefully enter and update your calendar data. Your base schedule and planned absences will be displayed by default, but you can add additional schedules (Google, SOGo, etc)." }}
|
||||
</span>
|
||||
</div>
|
||||
<table id="freeBusyTable">
|
||||
<tr>
|
||||
<th class="border-1 py-1 px-2 fw-bold">{{ "Description" }}</th>
|
||||
<th class="border-1 py-1 px-2 fw-bold">{{ "Type" }}</th>
|
||||
<th class="border-1 py-1 px-2 fw-bold" style="width: 50%;">{{ "URL" }}</th>
|
||||
<th class="border-1 py-1 px-2 fw-bold">{{ "Active" }}</th>
|
||||
<th class="border-1 py-1 px-2 fw-bold">{{ "Actions" }}</th>
|
||||
</tr>
|
||||
<tr v-for="defaultSchedule in defaultSchedules">
|
||||
<td class="border-1 py-1 px-2">{{ defaultSchedule.description }}</td>
|
||||
<td class="border-1 py-1 px-2">{{ defaultSchedule.type }}</td>
|
||||
<td class="border-1 py-1 px-2"></td>
|
||||
<td class="border-1 py-1 px-2">{{ "Yes" }}</td>
|
||||
<td class="border-1 py-1 px-2"></td>
|
||||
</tr>
|
||||
<template v-for="(schedule, index) in externalSchedules">
|
||||
<tr v-if="scheduleEditIndex !== index">
|
||||
<td class="border-1 py-1 px-2">{{ schedule.description }}</td>
|
||||
<td class="border-1 py-1 px-2">{{ getScheduleTypeText(schedule.type) }}</td>
|
||||
<td class="border-1 py-1 px-2">{{ schedule.url }}</td>
|
||||
<td class="border-1 py-1 px-2">{{ schedule.isActive ? "Yes" : "No" }}</td>
|
||||
<td class="border-1 py-1 px-2">
|
||||
<div class="w-100 d-flex flex-row gap-1 align-items-center justify-content-evenly">
|
||||
<div @click="openScheduleForm(index)" type="button" class="action py-1 px-1">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
<div class="overflow-x-auto">
|
||||
<table id="freeBusyTable" style="min-width:500px;">
|
||||
<tr>
|
||||
<th class="border-1 py-1 px-2 fw-bold">{{ "Description" }}</th>
|
||||
<th class="border-1 py-1 px-2 fw-bold">{{ "Type" }}</th>
|
||||
<th class="border-1 py-1 px-2 fw-bold" style="width: 50%;">{{ "URL" }}</th>
|
||||
<th class="border-1 py-1 px-2 fw-bold">{{ "Active" }}</th>
|
||||
<th class="border-1 py-1 px-2 fw-bold">{{ "Actions" }}</th>
|
||||
</tr>
|
||||
<tr v-for="defaultSchedule in defaultSchedules">
|
||||
<td class="border-1 py-1 px-2">{{ defaultSchedule.description }}</td>
|
||||
<td class="border-1 py-1 px-2">{{ defaultSchedule.type }}</td>
|
||||
<td class="border-1 py-1 px-2"></td>
|
||||
<td class="border-1 py-1 px-2">{{ "Yes" }}</td>
|
||||
<td class="border-1 py-1 px-2"></td>
|
||||
</tr>
|
||||
<template v-for="(schedule, index) in externalSchedules">
|
||||
<tr v-if="scheduleEditIndex !== index">
|
||||
<td class="border-1 py-1 px-2">{{ schedule.description }}</td>
|
||||
<td class="border-1 py-1 px-2">{{ getScheduleTypeText(schedule.type) }}</td>
|
||||
<td class="border-1 py-1 px-2">{{ schedule.url }}</td>
|
||||
<td class="border-1 py-1 px-2">{{ schedule.isActive ? "Yes" : "No" }}</td>
|
||||
<td class="border-1 py-1 px-2">
|
||||
<div class="w-100 d-flex flex-row gap-1 align-items-center justify-content-evenly">
|
||||
<div @click="openScheduleForm(index)" type="button" class="action py-1 px-1">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</div>
|
||||
<div @click="deleteSchedule(schedule)" type="button" class="action py-1 px-1">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div @click="deleteSchedule(schedule)" type="button" class="action py-1 px-1">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
</td>
|
||||
</tr>
|
||||
<coodle-free-busy-table-form-row
|
||||
v-else
|
||||
v-model:scheduleFormDataModelValue="scheduleFormData"
|
||||
@cancelForm="closeScheduleForm()"
|
||||
@submitForm="submitScheduleForm()"
|
||||
:scheduleTypes="scheduleTypes"
|
||||
/>
|
||||
</template>
|
||||
<tr v-if="scheduleEditIndex !== -1">
|
||||
<td colspan="5" class="border-1">
|
||||
<div
|
||||
@click="openScheduleForm(-1)"
|
||||
type="button"
|
||||
class="action w-100 d-flex flex-row align-items-center justify-content-center py-2"
|
||||
>
|
||||
<div>
|
||||
<i class="fa-solid fa-circle-plus fa-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -189,31 +203,11 @@ export default {
|
||||
v-model:scheduleFormDataModelValue="scheduleFormData"
|
||||
@cancelForm="closeScheduleForm()"
|
||||
@submitForm="submitScheduleForm()"
|
||||
:scheduleTypeOptions="scheduleTypeOptions"
|
||||
:scheduleTypes="scheduleTypes"
|
||||
:uid="$props.uid"
|
||||
/>
|
||||
</template>
|
||||
<tr v-if="scheduleEditIndex !== -1">
|
||||
<td colspan="5" class="border-1">
|
||||
<div
|
||||
@click="openScheduleForm(-1)"
|
||||
type="button"
|
||||
class="action w-100 d-flex flex-row align-items-center justify-content-center py-2"
|
||||
>
|
||||
<div>
|
||||
<i class="fa-solid fa-circle-plus fa-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<coodle-free-busy-table-form-row
|
||||
v-else
|
||||
v-model:scheduleFormDataModelValue="scheduleFormData"
|
||||
@cancelForm="closeScheduleForm()"
|
||||
@submitForm="submitScheduleForm()"
|
||||
:scheduleTypeOptions="scheduleTypeOptions"
|
||||
:uid="$props.uid"
|
||||
/>
|
||||
</table>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@ export default {
|
||||
name: "CoodleFreeBusyTableFormRow",
|
||||
props: {
|
||||
scheduleFormDataModelValue: Object,
|
||||
scheduleTypeOptions: Array,
|
||||
scheduleTypes: Array,
|
||||
uid: Number | null,
|
||||
},
|
||||
emits: ["update:scheduleFormDataModelValue", "submitForm", "cancelForm"],
|
||||
@@ -19,10 +19,10 @@ export default {
|
||||
watch: {
|
||||
"scheduleFormData.type": {
|
||||
handler(newValue) {
|
||||
if (newValue.toLowerCase() !== "sogo") return;
|
||||
const type = this.$props.scheduleTypes.find((type) => type.value === newValue);
|
||||
if (!type || !type.urlDefault?.length) return;
|
||||
|
||||
// todo: use base urls from db if appropriate
|
||||
this.scheduleFormData.url = "sogo url placeholder";
|
||||
this.scheduleFormData.url = type.urlDefault;
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -34,7 +34,7 @@ export default {
|
||||
<td class="border-1 py-2 px-2">
|
||||
<select v-model="scheduleFormData.type" id="scheduleTypeInput" class="w-100 h-100">
|
||||
<option value="null">{{ "--Select--" }}</option>
|
||||
<option v-for="option in $props.scheduleTypeOptions" :value="option.value">{{ option.text }}</option>
|
||||
<option v-for="type in $props.scheduleTypes" :value="type.value">{{ type.text }}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class="border-1 py-2 px-2">
|
||||
|
||||
@@ -124,13 +124,15 @@ export default {
|
||||
template: /*html*/ `
|
||||
<div class="h-100 d-flex flex-column gap-2">
|
||||
<h2 class="m-0">Coodle</h2>
|
||||
<div class="d-flex flex-row gap-2 w-100">
|
||||
<div class="d-flex flex-row gap-2 w-100 overflow-x-auto">
|
||||
<div
|
||||
@click="switchToTab('activeSurveysTable')"
|
||||
:class="getTabStylingClass(view === 'activeSurveysTable')"
|
||||
class="btn d-flex flex-row gap-2 align-items-center py-2"
|
||||
>
|
||||
<i class="fa-solid fa-person-booth fa-lg"></i>
|
||||
<div>
|
||||
<i class="fa-solid fa-person-booth fa-lg"></i>
|
||||
</div>
|
||||
<span class="text-nowrap">{{ "Active surveys" }}</span>
|
||||
</div>
|
||||
<div
|
||||
@@ -138,7 +140,9 @@ export default {
|
||||
:class="getTabStylingClass(view === 'pastSurveysTable')"
|
||||
class="btn d-flex flex-row gap-2 align-items-center py-2"
|
||||
>
|
||||
<i class="fa-solid fa-flag-checkered fa-lg"></i>
|
||||
<div>
|
||||
<i class="fa-solid fa-flag-checkered fa-lg"></i>
|
||||
</div>
|
||||
<span class="text-nowrap">{{ "Past surveys" }}</span>
|
||||
</div>
|
||||
<div
|
||||
@@ -146,7 +150,9 @@ export default {
|
||||
:class="getTabStylingClass(view === 'survey' && !survey?.id)"
|
||||
class="btn d-flex flex-row gap-2 align-items-center py-2"
|
||||
>
|
||||
<i class="fa-solid fa-circle-plus fa-lg"></i>
|
||||
<div>
|
||||
<i class="fa-solid fa-circle-plus fa-lg"></i>
|
||||
</div>
|
||||
<span class="text-nowrap">{{ "Create new survey" }}</span>
|
||||
</div>
|
||||
<div
|
||||
@@ -154,7 +160,9 @@ export default {
|
||||
:class="getTabStylingClass(view === 'freeBusySettings')"
|
||||
class="btn d-flex flex-row gap-2 align-items-center py-2"
|
||||
>
|
||||
<i class="fa-solid fa-gear fa-lg"></i>
|
||||
<div>
|
||||
<i class="fa-solid fa-gear fa-lg"></i>
|
||||
</div>
|
||||
<span class="text-nowrap">{{ "FreeBusy Settings" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user