[IMP] calendar: revamp views

This commit changes how the calendar module calendar views look, as well as the
 quick create form view for adding a new event.

task-3455051
task-3389317

Part-of: odoo/odoo#138670
This commit is contained in:
Leonardo Pavan Rocha
2023-10-23 20:07:23 +00:00
parent 2afce22326
commit 7dd6e5d1a5
7 changed files with 114 additions and 128 deletions
@@ -7,7 +7,8 @@
<t t-esc="title"/>
<t t-if="!isAllDay">
<t t-if="24 > duration and duration > 0.5">
<br/><t t-esc="startTime"/> - <t t-esc="endTime"/>
<br/>
<span class="fw-normal"><t t-esc="startTime" /> - <t t-esc="endTime" /></span>
</t>
<t t-else="">, <t t-esc="startTime"/></t>
</t>
@@ -2,7 +2,7 @@
<templates xml:space="preserve">
<t t-name="calendar.CalendarQuickCreateButtons" t-inherit="web.FormViewDialog.ToOne.buttons">
<xpath expr="//button[contains(@class, 'o_form_button_cancel')]" position="after">
<button class="btn btn-secondary" t-on-click="goToFullEvent">More Options</button>
<button class="btn btn-secondary ms-auto" t-on-click="goToFullEvent">More Options</button>
</xpath>
</t>
</templates>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="calendar.WeekDays">
<div class="o_recurrent_weekdays mt-2 mb-2 d-flex">
<div class="o_recurrent_weekdays mb-2 d-flex">
<t t-foreach="weekdays" t-as="day" t-key="day">
<div t-attf-class="o_calendar_week_days_rounded {{data[day] ? 'btn-primary' : 'btn-secondary'}}" t-on-click="() => this.onChange(day)">
<t t-esc="props.record.fields[day].string[0]"/>
+104 -117
View File
@@ -126,111 +126,42 @@
</div>
<group>
<group>
<field name="start_date" string="from" invisible="not allday" readonly="not user_can_edit" required="allday" force_save="1"/>
<field name="stop_date" string="to" invisible="not allday" readonly="not user_can_edit" required="allday" force_save="1"/>
<field name="start" string="from" invisible="allday" readonly="not user_can_edit" required="not allday"/>
<field name="stop" string="to" invisible="allday" readonly="not user_can_edit" required="not allday"/>
<label for="duration" invisible="allday"/>
<div invisible="allday">
<field name="duration" widget="float_time" string="Duration" class="oe_inline" readonly="(id and recurrency) or not user_can_edit"/>
<span> hours</span>
<field name="start_date" widget="daterange" options="{'end_date_field': 'stop_date'}" invisible="not allday" required="allday"/>
<field name="start" widget="daterange" options="{'end_date_field': 'stop'}" invisible="allday" required="not allday"/>
<field name="stop_date" invisible="1" />
<field name="stop" invisible="1" />
<div class="d-flex gap-2" colspan="2">
<div invisible="allday">
<label for="duration" class="pe-2 fw-bold text-900" invisible="allday"/>
<field name="duration" widget="float_time" string="Duration" class="oe_inline" readonly="(id and recurrency) or not user_can_edit"/>
<span> hours</span>
</div>
<div>
<label for="allday" class="pe-2 fw-bold text-900"/>
<field name="allday" class="oe_inline" force_save="1" readonly="not user_can_edit" colspan="1"/>
</div>
</div>
<field name="event_tz" invisible="not recurrency" readonly="not user_can_edit"/>
<field name="allday" force_save="1" readonly="not user_can_edit"/>
</group>
<group>
<field name="alarm_ids" widget="many2many_tags" options="{'no_quick_create': True}"/>
<field name="categ_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}"/>
</group>
</group>
<notebook>
<page name="page_details" string="Information">
<group>
<group>
<field name="location" />
<label for="videocall_location" class="opacity-100"/>
<div col="2">
<field name="videocall_location" string="Videocall URL" widget="CopyClipboardChar" force_save="1" readonly="videocall_source == 'discuss'"/>
<button name="clear_videocall_location" type="object" class="btn btn-link"
invisible="not videocall_location" context="{'recurrence_update': recurrence_update}">
<span class="fa fa-times"></span><span> Clear meeting</span>
</button>
<button name="set_discuss_videocall_location" type="object" class="btn btn-link"
invisible="videocall_location" context="{'recurrence_update': recurrence_update}">
<span class="fa fa-plus"></span><span> Add Odoo meeting</span>
</button>
<button name="action_join_video_call" class="btn btn-link" help="Join Video Call" type="object" invisible="not videocall_location">
<span class="oi oi-arrow-right"></span><span> Join video call</span>
</button>
</div>
<field name="videocall_source" invisible="1"/>
<field name="access_token" invisible="1" force_save="1"/>
<label for="privacy"/>
<div class="o_row">
<field name="show_as" readonly="not user_can_edit" nolabel="1"/>
<field name="privacy" readonly="not user_can_edit" nolabel="1"/>
</div>
<field name="user_id" widget="many2one_avatar_user" readonly="not user_can_edit"/>
<field name="description" options="{'height': 100}"/>
</group>
<group>
<div class="o_row" colspan="2">
<div colspan="1">
<field name="attendees_count" class="w-auto oe_inline" nolabel="1"/><span> Attendees</span>
</div>
<div name="send_buttons" class="sm-2" colspan="1">
<button name="action_open_composer" help="Send Email to attendees" type="object" string=" EMAIL" icon="fa-envelope"/>
</div>
</div>
<div colspan="2">
<field name="accepted_count" class="w-auto oe_inline" nolabel="1"/> yes,
<field name="tentative_count" class="w-auto oe_inline" nolabel="1"/> maybe,
<field name="declined_count" class="w-auto oe_inline" nolabel="1"/> no,
<field name="awaiting_count" class="w-auto oe_inline" nolabel="1"/> awaiting
</div>
<div class="d-flex align-items-baseline">
<field name="partner_ids" widget="many2manyattendee"
placeholder="Select attendees..."
context="{'force_email':True}"
domain="[('type','!=','private')]"
class="oe_inline"
readonly="not user_can_edit"
/>
</div>
<div class="alert alert-warning o_form_header mt-2" invisible="not invalid_email_partner_ids" role="status">
<p><strong>The following attendees have invalid email addresses and won't receive any email notifications:</strong></p>
<field name="invalid_email_partner_ids" widget="many2manyattendee" class="oe_inline"/>
</div>
</group>
</group>
</page>
<page name="page_options" string="Options">
<group>
<field name="recurrence_id" invisible="1" />
<field name="rrule_type" invisible="1" />
<group class="mb-0">
<field name="recurrency" />
<field name="rrule_type_ui" class="w-auto" invisible="not recurrency" required="recurrency"/>
</group>
<newline />
<group invisible="not recurrency">
<group class="o_row" invisible="rrule_type_ui != 'custom'">
<field name="interval" string="Repeat every" class="oe_inline w-auto" />
<field name="rrule_type" nolabel="1" class="oe_inline" required="rrule_type_ui == 'custom'"/>
</group>
</group>
<newline />
<group class="gap-0" invisible="rrule_type_ui not in ['weekly', 'custom'] or (rrule_type_ui == 'custom' and rrule_type != 'weekly')">
<span class="fw-bold pe-3">Repeat on</span>
<widget name="calendar_week_days" />
</group>
<group>
<field name="recurrence_id" invisible="1" />
</group>
</group>
<div class="d-flex gap-2" invisible="rrule_type_ui not in ['monthly', 'custom'] or (rrule_type_ui == 'custom' and rrule_type != 'monthly')">
<field name="recurrence_id" invisible="1" />
<field name="rrule_type" invisible="1" />
<field name="recurrency" />
<field name="rrule_type_ui" class="w-auto" invisible="not recurrency" required="recurrency"/>
<div invisible="not recurrency" colspan="2">
<div class="o_row" invisible="rrule_type_ui != 'custom'">
<label for="interval" class="fw-bold text-900"/>
<field name="interval" string="Repeat every" class="oe_inline w-auto" />
<field name="rrule_type" nolabel="1" class="oe_inline" required="rrule_type_ui == 'custom'"/>
</div>
</div>
<div class="d-flex gap-0" colspan="2" invisible="rrule_type_ui not in ['weekly', 'custom'] or (rrule_type_ui == 'custom' and rrule_type != 'weekly')">
<span class="fw-bold pe-3">Repeat on</span>
<widget name="calendar_week_days" />
</div>
<field name="recurrence_id" invisible="1" />
<div class="d-flex gap-2" colspan="2" invisible="rrule_type_ui not in ['monthly', 'custom'] or (rrule_type_ui == 'custom' and rrule_type != 'monthly')">
<label string="Day of Month" for="month_by" />
<field name="month_by" nolabel="1" required="rrule_type_ui == 'monthly' or rrule_type == 'monthly'"/>
<field name="day" nolabel="1"
@@ -246,16 +177,76 @@
invisible="month_by != 'day'"
/>
</div>
<div class="d-flex gap-2" invisible="not recurrency">
<label string="Until" for="end_type" />
<div class="d-flex gap-2" colspan="2" invisible="not recurrency">
<label string="Until" for="end_type" class="fw-bold text-900"/>
<field name="end_type" class="oe_inline w-auto" nolabel="1" required="recurrency"/>
<field name="count" class="oe_inline w-auto" nolabel="1" invisible="end_type != 'count'" required="recurrency"/>
<field name="until" class="oe_inline w-auto" nolabel="1" invisible="end_type != 'end_date'"
required="recurrency and end_type == 'end_date'"
/>
</div>
</page>
<field name="location" placeholder="Online Meeting"/>
<label for="videocall_location" class="opacity-100"/>
<div col="2">
<field name="videocall_location" string="Videocall URL" widget="CopyClipboardChar" force_save="1" readonly="videocall_source == 'discuss'"/>
<button name="clear_videocall_location" type="object" class="btn btn-link"
invisible="not videocall_location" context="{'recurrence_update': recurrence_update}">
<span class="fa fa-times"></span><span> Clear meeting</span>
</button>
<button name="set_discuss_videocall_location" type="object" class="btn btn-link ps-0"
invisible="videocall_location" context="{'recurrence_update': recurrence_update}">
<span class="fa fa-plus"></span><span> Odoo meeting</span>
</button>
<button name="action_join_video_call" class="btn btn-link" help="Join Video Call" type="object" invisible="not videocall_location">
<span class="oi oi-arrow-right"></span><span> Join video call</span>
</button>
</div>
<field name="videocall_source" invisible="1"/>
<field name="access_token" invisible="1" force_save="1"/>
<field name="categ_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True}"/>
<label for="privacy"/>
<div class="o_row">
<field name="show_as" readonly="not user_can_edit" nolabel="1"/>
<field name="privacy" readonly="not user_can_edit" nolabel="1"/>
</div>
<field name="user_id" widget="many2one_avatar_user" readonly="not user_can_edit"/>
<field name="description" options="{'height': 100}"/>
</group>
<group>
<field name="alarm_ids" widget="many2many_tags" options="{'no_quick_create': True}"/>
<div class="o_row" colspan="2">
<div colspan="1">
<field name="attendees_count" class="w-auto oe_inline" nolabel="1"/><span> Attendees</span>
</div>
<div name="send_buttons" class="d-flex gap-2 justify-content-end" colspan="1">
<button name="action_open_composer" help="Send Email to attendees" type="object" string=" EMAIL" icon="fa-envelope"/>
</div>
</div>
<div colspan="2">
<field name="accepted_count" class="w-auto oe_inline" nolabel="1"/> yes,
<field name="tentative_count" class="w-auto oe_inline" nolabel="1"/> maybe,
<field name="declined_count" class="w-auto oe_inline" nolabel="1"/> no,
<field name="awaiting_count" class="w-auto oe_inline" nolabel="1"/> awaiting
</div>
<div class="d-flex align-items-baseline" colspan="2">
<field name="partner_ids" widget="many2manyattendee"
placeholder="Select attendees..."
context="{'force_email':True}"
domain="[('type','!=','private')]"
class="oe_inline"
readonly="not user_can_edit"
/>
</div>
<div class="alert alert-warning o_form_header mt-2" invisible="not invalid_email_partner_ids" role="status">
<p><strong>The following attendees have invalid email addresses and won't receive any email notifications:</strong></p>
<field name="invalid_email_partner_ids" widget="many2manyattendee" class="oe_inline"/>
</div>
</group>
</group>
<notebook>
<page name="page_invitations" string="Invitations" groups="base.group_no_one" invisible="not user_can_edit">
<button name="action_sendmail" type="object" string="Send Invitations" icon="fa-envelope" class="oe_link"/>
<field name="attendee_ids" widget="one2many" mode="tree,kanban" readonly="1">
@@ -315,15 +306,11 @@
<h1 class="w-100"><field name="name" nolabel="1" placeholder="Add title" colspan="2"/></h1>
</div>
<group>
<field name="start_date" string="From" invisible="not allday" required="allday"/>
<field name="stop_date" string="To" invisible="not allday" required="allday"/>
<field name="start" string="From" invisible="allday" required="not allday" options="{'block': True, 'icon': 'fa fa-users'}"/>
<field name="stop" string="To" invisible="allday"/>
</group>
<group>
<field name="start_date" widget="daterange" options="{'end_date_field': 'stop_date'}" invisible="not allday" required="allday"/>
<field name="start" widget="daterange" options="{'end_date_field': 'stop'}" invisible="allday" required="not allday"/>
<field name="stop_date" invisible="1" />
<field name="stop" invisible="1" />
<field name="allday"/>
</group>
<group>
<field name="partner_ids" widget="many2manyattendee"
placeholder="Add attendees..."
context="{'force_email':True}"
@@ -332,19 +319,19 @@
<label for="videocall_location" class="opacity-100"/>
<div col="2">
<field name="videocall_location" string="Videocall URL" widget="CopyClipboardChar" force_save="1" readonly="videocall_source == 'discuss'"/>
<button name="clear_videocall_location" type="object" class="btn btn-link"
<button name="clear_videocall_location" type="object" class="btn btn-link p-0"
invisible="not videocall_location" context="{'recurrence_update': recurrence_update}">
<span class="fa fa-times"></span><span> Clear meeting</span>
</button>
<button name="set_discuss_videocall_location" type="object" class="btn btn-link"
<button name="set_discuss_videocall_location" type="object" class="btn btn-link p-0"
invisible="videocall_location" context="{'recurrence_update': recurrence_update}">
<span class="fa fa-plus"></span><span> Add Odoo meeting</span>
<span class="fa fa-plus"></span> <span>Odoo meeting</span>
</button>
<button name="action_join_video_call" class="btn btn-link" help="Join Video Call" type="object" invisible="not videocall_location">
<span class="oi oi-arrow-right"></span><span> Join video call</span>
</button>
</div>
<field name="description"/>
<field name="description" placeholder="Describe your meeting"/>
</group>
</sheet>
</form>
+1 -1
View File
@@ -19,7 +19,7 @@
</header>
<!-- FIXME: WOWL there is a bug on t-portal on owl, in which t-portal don't work on multinode.
To avoid this we place the footer before the body -->
<footer t-if="props.footer" class="modal-footer justify-content-around justify-content-sm-start flex-wrap gap-1" style="order:2">
<footer t-if="props.footer" class="modal-footer justify-content-around justify-content-sm-start flex-wrap gap-1 w-100" style="order:2">
<t t-slot="footer" close="() => this.data.close()">
<button class="btn btn-primary o-default-button" t-on-click="() => this.data.close()">
<t>Ok</t>
@@ -17,9 +17,7 @@
<t t-name="web.CalendarCommonPopover.popover">
<div class="card-header d-flex justify-content-between py-2 pe-2">
<h4 class="p-0 pt-1">
<span class="popover-header border-0" t-esc="props.record.title" />
</h4>
<span class="popover-header border-0" t-esc="props.record.title" />
<span class="o_cw_popover_close ms-4 mt-2 me-2" t-on-click.stop="() => props.close()">
<i class="fa fa-close" />
</span>
@@ -36,11 +34,11 @@
<ul class="list-group list-group-flush">
<li t-if="date" class="list-group-item">
<i class="fa fa-fw fa-calendar-o" />
<b class="text-capitalize" t-esc="date" /> <small t-if="dateDuration"><b t-esc="`(${dateDuration})`" /></small>
<b class="text-capitalize ms-2" t-esc="date" /> <small t-if="dateDuration"><b t-esc="`(${dateDuration})`" /></small>
</li>
<li t-if="time" class="list-group-item">
<i class="fa fa-fw fa-clock-o" />
<b t-esc="time" /> <small t-if="timeDuration"><b t-esc="`(${timeDuration})`" /></small>
<b class="ms-2" t-esc="time" /> <small t-if="timeDuration"><b t-esc="`(${timeDuration})`" /></small>
</li>
</ul>
<ul class="list-group list-group-flush o_cw_popover_fields_secondary">
@@ -52,7 +50,7 @@
<strong class="me-2" t-if="!fieldInfo.options.noLabel">
<t t-if="fieldInfo.options.icon">
<b>
<i t-att-class="fieldInfo.options.icon" />
<i t-attf-class="fa-fw {{fieldInfo.options.icon}}" />
</b>
</t>
<t t-else="">
@@ -58,7 +58,7 @@
</t>
<t t-name="web.FormView.Buttons">
<div class="o_cp_buttons d-flex align-items-baseline" role="toolbar" aria-label="Main actions" t-ref="cpButtons">
<div class="o_cp_buttons d-flex align-items-baseline w-100" role="toolbar" aria-label="Main actions" t-ref="cpButtons">
<div t-if="model.root.isInEdition" class="o_form_buttons_edit d-flex gap-1">
<button type="button" class="btn btn-primary o_form_button_save" data-hotkey="s" t-on-click.stop="() => this.saveButtonClicked({closable: true})">
Save