odex30_standard/odex30_base/resource_booking/templates/portal.xml

561 lines
25 KiB
XML

<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2021 Tecnativa - Jairo Llopis
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<data>
<!--
This template needs these context variables:
- access_token: to allow public access to the record
- booking: the booking record
- calendar: a Calendar object, already configured with the correct first weekday
- now: tz-aware datetime object indicating current time
- res_lang: res.lang record for current context l10n
- slots: available slots, as returned from [resource.booking]._get_available_slots()
- start: datetime when we start displaying the calendar
- weekday_names: dict of mappings between weekday numbers and names, where MON=1
-->
<template id="scheduling_calendar" name="Resource Booking Calendar">
<t t-set="confirm_url" t-value="booking.get_portal_url(suffix='/confirm')" />
<t t-set="date_format" t-value="res_lang.date_format" />
<t t-set="time_format" t-value="res_lang.time_format.replace(':%S', '')" />
<t t-set="start_next" t-value="start + relativedelta(months=1)" />
<t t-set="start_previous" t-value="start - relativedelta(months=1)" />
<div class="o_booking_calendar">
<div class="alert alert-danger" t-if="not slots">
No free slots found this month.
<a
t-att-href="booking.get_portal_url(suffix='/schedule/%d/%d' % (start_next.year, start_next.month))"
class="alert-link"
>
Try next month
<i class="fa fa-chevron-right" />
</a>
</div>
<!-- Monthly calendar -->
<table class="table table-responsive-md text-center">
<thead t-if="booking.requester_advice">
<tr>
<td colspan="7">
<div t-field="booking.requester_advice" />
</td>
</tr>
</thead>
<thead class="thead-dark">
<tr>
<th class="text-left">
<a
t-if="start > now"
t-att-href="booking.get_portal_url(suffix='/schedule/%d/%d' % (start_previous.year, start_previous.month))"
class="btn btn-secondary"
title="Previous month"
>
<i class="fa fa-chevron-left" />
</a>
</th>
<th
class="align-middle"
colspan="5"
t-esc="start.strftime('%B %Y')"
/>
<th class="text-right">
<a
t-att-href="booking.get_portal_url(suffix='/schedule/%d/%d' % (start_next.year, start_next.month))"
class="btn btn-secondary"
title="Next month"
>
<i class="fa fa-chevron-right" />
</a>
</th>
</tr>
</thead>
<thead>
<tr>
<t t-foreach="calendar.iterweekdays()" t-as="weekday">
<th
t-att-title="weekday_names[str(weekday + 1)]"
t-esc="weekday_names[str(weekday + 1)][:3]"
/>
</t>
</tr>
</thead>
<tbody>
<t
t-foreach="calendar.monthdatescalendar(start.year, start.month)"
t-as="week"
>
<tr>
<t t-foreach="week" t-as="day">
<td
t-att-class="day.month != start.month and 'text-muted'"
>
<t
t-if="day.month == start.month and slots.get(day)"
>
<!-- Day dropdown -->
<div class="dropdown">
<button
class="btn btn-primary dropdown-toggle"
type="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
t-esc="day.day"
t-attf-id="dropdown-trigger-#{day.isoformat()}"
/>
<div
class="dropdown-menu slots-dropdown"
t-attf-aria-labelledby="dropdown-trigger-#{day.isoformat()}"
>
<t t-foreach="slots[day]" t-as="slot">
<!-- Hour item to open confirmation -->
<button
class="dropdown-item"
type="button"
data-toggle="modal"
t-attf-data-target="#modal-confirm-#{int(slot.timestamp())}"
t-esc="slot.strftime(time_format)"
/>
</t>
</div>
</div>
</t>
<t t-else="">
<t t-esc="day.day" />
</t>
</td>
</t>
</tr>
</t>
</tbody>
<tfoot>
<tr>
<td colspan="7">
All times are displayed using this timezone:
<strong t-field="booking.type_id.resource_calendar_id.tz" />
</td>
</tr>
</tfoot>
</table>
<!-- Hour confirmation modals -->
<t
t-foreach="calendar.monthdatescalendar(start.year, start.month)"
t-as="week"
>
<t t-foreach="week" t-as="day">
<form
t-foreach="slots.get(day, [])"
t-as="slot"
method="post"
t-att-action="confirm_url"
t-attf-id="modal-confirm-#{int(slot.timestamp())}"
t-attf-aria-labelledby="modal-title-#{int(slot.timestamp())}"
class="modal fade"
>
<input
type="hidden"
name="csrf_token"
t-att-value="request.csrf_token()"
/>
<input
type="hidden"
name="access_token"
t-att-value="access_token"
/>
<input
type="hidden"
name="when"
t-att-value="slot.isoformat()"
/>
<div class="modal-dialog">
<div class="modal-content">
<div
t-attf-id="modal-title-#{int(slot.timestamp())}"
class="modal-header"
>
<h5>Confirm booking</h5>
</div>
<div class="modal-body">
<p>You are about to confirm this booking:</p>
<ul>
<li>
Start:
<strong
t-esc="slot.strftime(date_format)"
/>
<strong
t-esc="slot.strftime(time_format)"
/>
</li>
<li>
Duration:
<strong
t-field="booking.duration"
t-options='{"widget": "float_time"}'
/>
</li>
</ul>
<p>Are you sure?</p>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-dismiss="modal"
>Cancel</button>
<button
type="submit"
class="btn btn-primary"
>Confirm booking</button>
</div>
</div>
</div>
</form>
</t>
</t>
</div>
</template>
<!-- Portal templates -->
<template id="portal_breadcrumbs" inherit_id="portal.portal_breadcrumbs">
<xpath expr="//ol[hasclass('o_portal_submenu')]" position="inside">
<li
t-if="page_name == 'booking' or booking_sudo"
t-attf-class="breadcrumb-item #{'active ' if not booking_sudo else ''}"
>
<a
t-if="booking_sudo"
t-attf-href="/my/bookings?{{ keep_query() }}"
>Bookings</a>
<t t-else="">Bookings</t>
</li>
<t t-if="booking_sudo">
<li
t-attf-class="breadcrumb-item #{'active ' if page_name == 'booking' else ''}"
>
<t t-if="page_name == 'booking_schedule'">
<a
t-att-href="booking_sudo.get_portal_url()"
t-esc="booking_sudo.display_name"
/>
</t>
<t t-else="">
<t t-esc="booking_sudo.name" />
</t>
</li>
<li
class="breadcrumb-item active"
t-if="page_name == 'booking_schedule'"
>Schedule</li>
</t>
</xpath>
</template>
<template id="portal_my_home" inherit_id="portal.portal_my_home">
<xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
<t t-if="booking_count" t-call="portal.portal_docs_entry">
<t t-set="title">Bookings</t>
<t t-set="url" t-value="'/my/bookings'" />
<t t-set="count" t-value="booking_count" />
</t>
</xpath>
</template>
<template id="portal_my_bookings" name="My Bookings">
<t t-call="portal.portal_layout">
<t t-set="breadcrumbs_searchbar" t-value="True" />
<t t-call="portal.portal_searchbar">
<t t-set="title">Bookings</t>
</t>
<t t-if="not bookings">
<p>There are currently no bookings for your account.</p>
</t>
<t t-if="bookings" t-call="portal.portal_table">
<thead>
<tr class="active">
<th>Booking ref.</th>
<th>Type</th>
<th>Resources</th>
<th class="text-center">State</th>
<th class="text-right">Date</th>
</tr>
</thead>
<t t-foreach="bookings" t-as="booking">
<tr>
<td>
<a t-att-href="booking.get_portal_url()">
<span t-field="booking.display_name" />
</a>
</td>
<td>
<span t-field="booking.type_id" />
</td>
<td>
<span t-field="booking.combination_id" />
</td>
<td class="text-center">
<span
class="badge badge-pill badge-info"
t-field="booking.state"
/>
</td>
<td class="text-right">
<span t-field="booking.start" />
</td>
</tr>
</t>
</t>
</t>
</template>
<template id="resource_booking_portal_header" name="Resource Booking Header">
<div class="row no-gutters">
<div class="col-md">
<h5 class="mb-1 mb-md-0">
Booking
<span t-field="booking_sudo.display_name" />
</h5>
</div>
<div class="col-md text-md-right">
<small class="text-right">State:</small>
<span
t-field="booking_sudo.state"
class="badge badge-pill badge-info"
title="Current state of this booking"
/>
</div>
</div>
</template>
<template id="resource_booking_portal_form" name="Booking portal form">
<t t-call="portal.portal_layout">
<t t-set="o_portal_fullwidth_alert" groups="resource_booking.group_user">
<t t-call="portal.portal_back_in_edit_mode">
<t
t-set="backend_url"
t-value="'/web#return_label=Website&amp;model=resource.booking&amp;id=%d&amp;view_type=form' % (booking_sudo.id)"
/>
</t>
</t>
<!-- Form -->
<t t-call="portal.portal_table">
<t t-set="card_header">
<t t-call="resource_booking.resource_booking_portal_header" />
</t>
<t t-set="card_body">
<div class="row">
<div class="col-md">
<div class="mb-1">
<strong>Type:</strong>
<span t-field="booking_sudo.type_id.name" />
</div>
<div class="mb-1">
<strong>Requested by:</strong>
<span t-field="booking_sudo.partner_id.display_name" />
</div>
<div class="mb-1">
<strong>Booked resources:</strong>
<ul>
<t
t-foreach="booking_sudo.combination_id.resource_ids"
t-as="resource"
>
<li>
<span t-field="resource.name" />
</li>
</t>
</ul>
</div>
</div>
<div class="col-md">
<div class="mb-1">
<strong>Location:</strong>
<span t-field="booking_sudo.location" />
</div>
<div class="mb-1">
<strong>Dates:</strong>
<span t-field="booking_sudo.meeting_id.display_time" />
</div>
<div class="mb-1">
<strong>Duration:</strong>
<span
t-field="booking_sudo.duration"
t-options='{"widget": "float_time"}'
/>
</div>
<div t-if="booking_sudo.requester_advice" class="mb-1">
<strong>Advice:</strong>
<span t-field="booking_sudo.requester_advice" />
</div>
<div
t-if="booking_sudo.is_overdue"
role="alert"
class="mb-1 alert alert-warning"
>
This booking exceeded its modifications deadline.
</div>
</div>
</div>
</t>
</t>
<!-- Actions -->
<div class="row justify-content-center text-center d-print-none mt8">
<t t-if="booking_sudo.state == 'pending'">
<div class="col-sm-auto mt8">
<a
role="button"
class="btn btn-primary"
t-att-href="booking_sudo.get_portal_url(suffix='/schedule')"
>
<i class="fa fa-calendar" />
Schedule
</a>
</div>
</t>
<t
t-if="booking_sudo.is_modifiable and booking_sudo.state in {'scheduled', 'accepted'}"
>
<div class="col-sm-auto mt8">
<a
role="button"
class="btn btn-secondary"
t-att-href="booking_sudo.get_portal_url(suffix='/schedule')"
>
<i class="fa fa-calendar" />
Reschedule
</a>
</div>
</t>
<div class="col-sm-auto mt8">
<a role="button" class="btn btn-secondary" href="#discussion">
<i class="fa fa-comment" />
Feedback
</a>
</div>
<t
t-if="booking_sudo.is_modifiable and booking_sudo.state != 'canceled'"
>
<div class="col-sm-auto mt8">
<a
role="button"
class="btn btn-danger"
data-toggle="modal"
data-target="#modal_cancel"
href="#"
>
<i class="fa fa-times" />
Cancel
</a>
</div>
</t>
</div>
<div role="dialog" class="modal fade" id="modal_cancel">
<div class="modal-dialog">
<div class="modal-content">
<input
type="hidden"
name="csrf_token"
t-att-value="request.csrf_token()"
/>
<header class="modal-header">
<h4 class="modal-title">Confirm</h4>
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<i class="fa fa-times" />
</button>
</header>
<main class="modal-body">
<p>
If you cancel this booking:
<ul>
<li>It will disappear from your bookings list.</li>
<li>It will be unscheduled.</li>
</ul>
Please confirm this is really what you want.
</p>
</main>
<footer class="modal-footer">
<a
t-att-href="booking_sudo.get_portal_url(suffix='/cancel')"
class="btn btn-danger"
>
<i class="fa fa-times" />
Cancel this booking
</a>
<button
type="button"
class="btn btn-primary"
data-dismiss="modal"
>Go back</button>
</footer>
</div>
</div>
</div>
<!-- Discuss -->
<div class="mt32">
<h4>Message and communication history</h4>
<t t-call="portal.message_thread">
<t t-set="object" t-value="booking_sudo" />
<t t-set="token" t-value="booking_sudo.access_token" />
<t t-set="pid" t-value="pid" />
<t t-set="hash" t-value="hash" />
</t>
</div>
</t>
</template>
<template
id="alert_availability_lost"
name="Alert Resource Booking Availability was Lost"
>
<div
class="alert alert-danger alert-dismissible rounded-0 fade show d-print-none css_editable_mode_hidden"
>
<div class="container">
<div t-ignore="true" class="text-center">
<strong>The chosen schedule is no longer available.</strong>
<t t-if="error">
<br />
Error details:
<span t-esc="error" />
</t>
</div>
</div>
<button
type="button"
class="close"
data-dismiss="alert"
aria-label="Close"
> &#215;</button>
</div>
</template>
<template id="resource_booking_portal_schedule" name="Resource Booking Scheduling">
<t t-call="portal.portal_layout">
<t t-set="o_portal_fullwidth_alert" groups="project.group_project_user">
<t t-call="portal.portal_back_in_edit_mode">
<t
t-set="backend_url"
t-value="'/web#return_label=Website&amp;model=resource.booking&amp;id=%d&amp;view_type=form' % (booking_sudo.id)"
/>
</t>
</t>
<!-- Error alert -->
<t t-if="error">
<t t-call="resource_booking.alert_availability_lost" />
</t>
<!-- Scheduling form -->
<t t-call="portal.portal_table">
<t t-set="card_header">
<t t-call="resource_booking.resource_booking_portal_header" />
</t>
<t t-set="card_body">
<div class="row">
<div class="col">
<t t-call="resource_booking.scheduling_calendar">
<t t-set="booking" t-value="booking_sudo" />
</t>
</div>
</div>
</t>
</t>
</t>
</template>
</data>