Calendar: Change form to allow to add invitations and subscriptions - refs BT#19390 BT#20637

pull/5206/head
Angel Fernando Quiroz Campos 2 years ago
parent 69c5f4f4df
commit 2c9584a250
  1. 34
      assets/vue/components/ccalendarevent/CCalendarEventForm.vue
  2. 144
      assets/vue/components/ccalendarevent/CalendarInvitations.vue
  3. 22
      assets/vue/composables/calendar/calendarInvitations.js
  4. 10
      assets/vue/constants/entity/ccalendarevent.js
  5. 25
      assets/vue/services/usergroupService.js
  6. 2
      assets/vue/views/ccalendarevent/CCalendarEventList.vue
  7. 1
      src/CoreBundle/Controller/PlatformConfigurationController.php
  8. 12
      src/CoreBundle/Migrations/Schema/V200/Version20170625145000.php
  9. 4
      src/CoreBundle/Migrations/Schema/V200/Version20230904173400.php
  10. 24
      src/CourseBundle/Entity/CCalendarEvent.php

@ -39,28 +39,7 @@
required
/>
</div>
<Fieldset
v-if="agendaCollectiveInvitations"
:legend="'Invitees'"
collapsed
toggleable
>
<EditLinks
:edit-status="false"
:item="item"
:links-type="linksType"
:show-status="false"
show-share-with-user
/>
<BaseCheckbox
id="is_collective"
v-model="item.collective"
:label="t('Is it editable by the invitees?')"
name="is_collective"
/>
</Fieldset>
<CalendarInvitations v-model="item" />
<slot />
</form>
@ -73,13 +52,7 @@ import { required } from "@vuelidate/validators"
import BaseInputText from "../basecomponents/BaseInputText.vue"
import { useI18n } from "vue-i18n"
import BaseCalendar from "../basecomponents/BaseCalendar.vue"
import Fieldset from "primevue/fieldset"
const store = useStore()
const platformConfigStore = usePlatformConfig()
const agendaCollectiveInvitations = "true" === platformConfigStore.getSetting("agenda.agenda_collective_invitations")
import CalendarInvitations from "./CalendarInvitations.vue"
const { t } = useI18n()
@ -115,7 +88,6 @@ const rules = computed(() => ({
endDate: {
required,
},
collective: {},
},
}))
@ -126,7 +98,7 @@ defineExpose({
v$,
})
const dateRange = ref()
const dateRange = ref([item.value.startDate, item.value.endDate])
watch(dateRange, (newValue) => {
item.value.startDate = newValue[0]

@ -0,0 +1,144 @@
<script setup>
import { computed, ref, watch } from "vue"
import { useI18n } from "vue-i18n"
import Fieldset from "primevue/fieldset"
import SelectButton from "primevue/selectbutton"
import BaseCheckbox from "../basecomponents/BaseCheckbox.vue"
import BaseInputNumber from "../basecomponents/BaseInputNumber.vue"
import BaseSelect from "../basecomponents/BaseSelect.vue"
import EditLinks from "../resource_links/EditLinks.vue"
import { useCalendarInvitations } from "../../composables/calendar/calendarInvitations"
import BaseAutocomplete from "../basecomponents/BaseAutocomplete.vue"
import usergrupService from "../../services/usergroupService"
import { type, subscriptionVisibility } from "../../constants/entity/ccalendarevent"
const model = defineModel({
type: Object,
})
const { t } = useI18n()
const { allowCollectiveInvitations, allowSubscriptions } = useCalendarInvitations()
const showInvitationsFieldset = computed(() => {
if (allowCollectiveInvitations && !allowSubscriptions) {
return true
}
return allowSubscriptions && type.invitation === model.value?.invitationType
})
const showSubscriptionsFieldset = computed(() => {
if (allowSubscriptions && !allowCollectiveInvitations) {
return true
}
return allowCollectiveInvitations && type.subscription === model.value?.invitationType
})
const invitationTypeList = [
{ name: t("Invitations"), value: type.invitation },
{ name: t("Subscriptions"), value: type.subscription },
]
const invitationTypeSelected = ref()
model.value.invitationType = computed(() => invitationTypeSelected.value)
const subscriptionVisibilityList = [
{ label: t("No"), value: subscriptionVisibility.no },
{ label: t("All system users"), value: subscriptionVisibility.all },
{ label: t("Users inside the class"), value: subscriptionVisibility.class },
]
const subscriptionVisibilitySelected = ref(0)
model.value.subscriptionVisibility = computed(() => subscriptionVisibilitySelected.value)
const subscriptionItemSelected = ref()
const subscriptionItemDisabled = computed(() => 2 !== subscriptionVisibilitySelected.value)
const onSubscriptionItemSelected = (event) => (model.value.subscriptionItemId = event.value.id)
watch(subscriptionItemSelected, (newValue) => {
if (!newValue) {
model.value.subscriptionItemId = undefined
}
})
const findUsergroup = async (query) => {
const response = await usergrupService.search(query)
return response.items
}
const maxSubscriptionsDisabled = computed(() => 0 === subscriptionVisibilitySelected.value)
</script>
<template>
<div
v-if="allowCollectiveInvitations && allowSubscriptions"
class="field"
>
<SelectButton
v-model="invitationTypeSelected"
:options="invitationTypeList"
option-label="name"
option-value="value"
/>
</div>
<Fieldset
v-if="showInvitationsFieldset"
:legend="t('Invitations')"
>
<EditLinks
v-model="model"
:edit-status="false"
links-type="user_rel_users"
:show-status="false"
show-share-with-user
/>
<BaseCheckbox
id="is_collective"
v-model="model.collective"
:label="t('Is it editable by the invitees?')"
name="is_collective"
/>
</Fieldset>
<Fieldset
v-if="showSubscriptionsFieldset"
:legend="t('Subscriptions')"
>
<BaseSelect
v-model="subscriptionVisibilitySelected"
:label="t('Allow subscriptions')"
:options="subscriptionVisibilityList"
option-label="label"
option-value="value"
/>
<BaseAutocomplete
id="subscription_item"
v-model="subscriptionItemSelected"
:search="findUsergroup"
:label="t('Social group')"
option-label="title"
:disabled="subscriptionItemDisabled"
@item-select="onSubscriptionItemSelected"
/>
<BaseInputNumber
id="max_subscription"
v-model="model.maxAttendees"
:disabled="maxSubscriptionsDisabled"
:label="t('Maximum number of subscriptions allowed. Leave at 0 to not limit it.')"
min="0"
step="1"
/>
<div
id="form_subscriptions_edit"
style="display: none"
></div>
</Fieldset>
</template>

@ -0,0 +1,22 @@
import { useCidReqStore } from "../../store/cidReq"
import { usePlatformConfig } from "../../store/platformConfig"
import { useSecurityStore } from "../../store/securityStore"
export function useCalendarInvitations() {
const cidReqStore = useCidReqStore()
const platformConfigStore = usePlatformConfig()
const securirtyStore = useSecurityStore()
const isPersonalCalendar = null === cidReqStore.course
const agendaCollectiveInvitations = "true" === platformConfigStore.getSetting("agenda.agenda_collective_invitations")
const agendaEventSubscriptions = "true" === platformConfigStore.getSetting("agenda.agenda_event_subscriptions")
const allowCollectiveInvitations = agendaCollectiveInvitations && isPersonalCalendar
const allowSubscriptions = securirtyStore.isAdmin && agendaEventSubscriptions && isPersonalCalendar
return {
allowCollectiveInvitations,
allowSubscriptions,
}
}

@ -0,0 +1,10 @@
export const type = {
invitation: "invitation",
subscription: "subscription",
}
export const subscriptionVisibility = {
no: 0,
all: 1,
class: 2,
}

@ -0,0 +1,25 @@
import axios from "axios"
export default {
/**
* @param {string} searchTerm
* @returns {Promise<Object>} { totalItems, items }
*/
search: async (searchTerm) => {
const response = {}
try {
const { data } = await axios.get("/api/usergroups/search", {
params: { search: searchTerm },
})
response.totalItems = data["hydra:totalItems"]
response.items = data["hydra:member"]
} catch {
response.totalItems = 0
response.items = []
}
return response
},
}

@ -194,7 +194,6 @@ const calendarLocale = allLocales.find(
const showAddEventDialog = () => {
item.value = {}
item.value["parentResourceNode"] = currentUser.value.resourceNode["id"]
item.value["collective"] = false
dialog.value = true
}
@ -259,7 +258,6 @@ const calendarOptions = ref({
select(info) {
item.value = {}
item.value["parentResourceNode"] = currentUser.value.resourceNode["id"]
item.value["collective"] = false
item.value["allDay"] = info.allDay
item.value["startDate"] = info.start
item.value["endDate"] = info.end

@ -59,6 +59,7 @@ class PlatformConfigurationController extends AbstractController
'agenda.personal_calendar_show_sessions_occupation',
// 'agenda.agenda_reminders',
'agenda.agenda_collective_invitations',
'agenda.agenda_event_subscriptions',
'social.social_enable_messages_feedback',
'social.disable_dislike_option',

@ -48,16 +48,16 @@ class Version20170625145000 extends AbstractMigrationChamilo
$this->addSql('DROP INDEX session_id ON c_calendar_event');
}
if (!$table->hasColumn('collective')) {
$this->addSql('ALTER TABLE c_calendar_event ADD collective TINYINT(1) DEFAULT 0 NOT NULL');
if (!$table->hasColumn('invitation_type')) {
$this->addSql("ALTER TABLE c_calendar_event ADD invitation_type VARCHAR(255) DEFAULT NULL");
}
if (!$table->hasColumn('invitation_type')) {
$this->addSql("ALTER TABLE c_calendar_event ADD invitaion_type VARCHAR(255) DEFAULT 'invitation' NOT NULL");
if (!$table->hasColumn('collective')) {
$this->addSql('ALTER TABLE c_calendar_event ADD collective TINYINT(1) NOT NULL');
}
if (!$table->hasColumn('subscription_visibility')) {
$this->addSql('ALTER TABLE c_calendar_event ADD subscription_visibility INT DEFAULT 0 NOT NULL');
$this->addSql('ALTER TABLE c_calendar_event ADD subscription_visibility INT NOT NULL');
}
if (!$table->hasColumn('subscription_item_id')) {
@ -65,7 +65,7 @@ class Version20170625145000 extends AbstractMigrationChamilo
}
if (!$table->hasColumn('max_attendees')) {
$this->addSql('ALTER TABLE c_calendar_event ADD max_attendees INT DEFAULT 0 NOT NULL');
$this->addSql('ALTER TABLE c_calendar_event ADD max_attendees INT NOT NULL');
}
$table = $schema->getTable('c_calendar_event_attachment');

@ -89,12 +89,12 @@ class Version20230904173400 extends AbstractMigrationChamilo
if ($hasSubscriptions) {
$calendarEvent
->setInvitaionType(CCalendarEvent::TYPE_SUBSCRIPTION)
->setInvitationType(CCalendarEvent::TYPE_SUBSCRIPTION)
->setSubscriptionVisibility($personalAgenda['subscription_visibility'])
->setSubscriptionItemId($personalAgenda['subscription_item_id'])
;
} else {
$calendarEvent->setInvitaionType(CCalendarEvent::TYPE_INVITATION);
$calendarEvent->setInvitationType(CCalendarEvent::TYPE_INVITATION);
$invitationsOrSubscriptionsInfo = $this->getInvitations($subscriptionsEnabled, (int) $personalAgenda['id']);
}

@ -143,21 +143,25 @@ class CCalendarEvent extends AbstractResource implements ResourceInterface, Stri
#[ORM\OneToMany(mappedBy: 'event', targetEntity: CCalendarEventAttachment::class, cascade: ['persist', 'remove'])]
protected Collection $attachments;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[ORM\Column(name: 'invitation_type', type: 'string', nullable: true)]
protected ?string $invitationType = null;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[Assert\NotNull]
#[ORM\Column(name: 'collective', type: 'boolean', nullable: false, options: ['default' => false])]
#[ORM\Column(name: 'collective', type: 'boolean')]
protected bool $collective = false;
#[ORM\Column(name: 'invitaion_type', type: 'string', options: ['default' => self::TYPE_INVITATION])]
protected string $invitaionType = self::TYPE_INVITATION;
#[ORM\Column(name: 'subscription_visibility', type: 'integer', options: ['default' => self::SUBSCRIPTION_VISIBILITY_NO])]
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[ORM\Column(name: 'subscription_visibility', type: 'integer')]
protected int $subscriptionVisibility = self::SUBSCRIPTION_VISIBILITY_NO;
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[ORM\Column(name: 'subscription_item_id', type: 'integer', nullable: true)]
protected ?int $subscriptionItemId = null;
#[ORM\Column(name: 'max_attendees', type: 'integer', nullable: false, options: ['default' => 0])]
#[Groups(['calendar_event:read', 'calendar_event:write'])]
#[ORM\Column(name: 'max_attendees', type: 'integer')]
protected int $maxAttendees = 0;
public function __construct()
@ -381,14 +385,14 @@ class CCalendarEvent extends AbstractResource implements ResourceInterface, Stri
return $this;
}
public function getInvitaionType(): string
public function getInvitationType(): string
{
return $this->invitaionType;
return $this->invitationType;
}
public function setInvitaionType(string $invitaionType): self
public function setInvitationType(string $invitationType): self
{
$this->invitaionType = $invitaionType;
$this->invitationType = $invitationType;
return $this;
}

Loading…
Cancel
Save