From ed9a9d024adf9749ed5844ec3af35a0dae910828 Mon Sep 17 00:00:00 2001 From: Bruno Boi Date: Mon, 26 Sep 2022 12:56:41 +0000 Subject: [PATCH] [REF] *: calendar view in owl This commit introduces the new calendar view written in owl. closes odoo/odoo#101185 X-original-commit: e88988f58582d5b49a32d7102a74a176f40c4c69 Related: odoo/enterprise#31808 Signed-off-by: Aaron Bohy (aab) Signed-off-by: Bruno Boi (boi) Co-authored-by: Bruno Boi Co-authored-by: Jorge Pinna Puissant --- .../hr_holidays/static/src/scss/time_off.scss | 2 +- .../tests/tours/project_update_tour_tests.js | 2 +- addons/web/__manifest__.py | 6 +- addons/web/static/src/core/l10n/dates.js | 11 + .../js/views/calendar/calendar_renderer.js | 2 +- addons/web/static/src/legacy/scss/views.scss | 5 +- .../static/src/legacy/scss/web_calendar.scss | 333 +- .../static/src/legacy/xml/web_calendar.xml | 2 +- .../src/search/control_panel/control_panel.js | 1 + .../search/control_panel/control_panel.scss | 2 +- .../search/control_panel/control_panel.xml | 13 +- .../views/calendar/calendar_arch_parser.js | 195 + .../calendar_common_popover.js | 98 + .../calendar_common_popover.scss | 71 + .../calendar_common_popover.xml | 82 + .../calendar_common_renderer.js | 296 ++ .../calendar_common_renderer.xml | 18 + .../src/views/calendar/calendar_controller.js | 221 + .../views/calendar/calendar_controller.scss | 239 + .../views/calendar/calendar_controller.xml | 76 + .../calendar/calendar_controller_mobile.scss | 48 + .../src/views/calendar/calendar_model.js | 821 ++++ .../src/views/calendar/calendar_renderer.js | 37 + .../src/views/calendar/calendar_renderer.scss | 697 +++ .../src/views/calendar/calendar_renderer.xml | 16 + .../calendar/calendar_renderer_mobile.scss | 34 + .../src/views/calendar/calendar_view.js | 38 + .../calendar_year/calendar_year_popover.js | 91 + .../calendar_year/calendar_year_popover.xml | 68 + .../calendar_year/calendar_year_renderer.js | 192 + .../calendar_year/calendar_year_renderer.xml | 18 + .../web/static/src/views/calendar/colors.js | 24 + .../date_picker/calendar_date_picker.js | 101 + .../filter_panel/calendar_filter_panel.js | 226 + .../filter_panel/calendar_filter_panel.scss | 13 + .../filter_panel/calendar_filter_panel.xml | 150 + addons/web/static/src/views/calendar/hooks.js | 118 + .../calendar_mobile_filter_panel.js | 28 + .../calendar_mobile_filter_panel.xml | 25 + .../quick_create/calendar_quick_create.js | 86 + .../quick_create/calendar_quick_create.xml | 32 + .../many2many_tags/many2many_tags_field.js | 3 + .../src/views/fields/relational_utils.xml | 1 + addons/web/static/src/views/record.js | 19 +- .../web/static/src/views/relational_model.js | 5 +- addons/web/static/src/views/view.js | 9 +- .../src/webclient/actions/action_service.js | 11 +- addons/web/static/tests/helpers/utils.js | 2 +- .../tests/legacy/core/owl_dialog_tests.js | 3 + .../tests/legacy/views/calendar_tests.js | 11 +- addons/web/static/tests/mobile/helpers.js | 66 + .../tests/mobile/views/calendar_view_tests.js | 396 ++ .../calendar/calendar_arch_parser_tests.js | 169 + .../calendar/calendar_common_popover_tests.js | 222 + .../calendar_common_renderer_tests.js | 162 + .../calendar/calendar_date_picker_tests.js | 117 + .../calendar/calendar_filter_panel_tests.js | 213 + .../calendar/calendar_quick_create_tests.js | 119 + .../views/calendar/calendar_view_tests.js | 3937 +++++++++++++++++ .../calendar/calendar_year_popover_tests.js | 120 + .../calendar/calendar_year_renderer_tests.js | 139 + .../static/tests/views/calendar/helpers.js | 536 +++ addons/web/tooling/_eslintrc.json | 1 + odoo/addons/test_lint/tests/eslintrc | 1 + 64 files changed, 10439 insertions(+), 361 deletions(-) create mode 100644 addons/web/static/src/views/calendar/calendar_arch_parser.js create mode 100644 addons/web/static/src/views/calendar/calendar_common/calendar_common_popover.js create mode 100644 addons/web/static/src/views/calendar/calendar_common/calendar_common_popover.scss create mode 100644 addons/web/static/src/views/calendar/calendar_common/calendar_common_popover.xml create mode 100644 addons/web/static/src/views/calendar/calendar_common/calendar_common_renderer.js create mode 100644 addons/web/static/src/views/calendar/calendar_common/calendar_common_renderer.xml create mode 100644 addons/web/static/src/views/calendar/calendar_controller.js create mode 100644 addons/web/static/src/views/calendar/calendar_controller.scss create mode 100644 addons/web/static/src/views/calendar/calendar_controller.xml create mode 100644 addons/web/static/src/views/calendar/calendar_controller_mobile.scss create mode 100644 addons/web/static/src/views/calendar/calendar_model.js create mode 100644 addons/web/static/src/views/calendar/calendar_renderer.js create mode 100644 addons/web/static/src/views/calendar/calendar_renderer.scss create mode 100644 addons/web/static/src/views/calendar/calendar_renderer.xml create mode 100644 addons/web/static/src/views/calendar/calendar_renderer_mobile.scss create mode 100644 addons/web/static/src/views/calendar/calendar_view.js create mode 100644 addons/web/static/src/views/calendar/calendar_year/calendar_year_popover.js create mode 100644 addons/web/static/src/views/calendar/calendar_year/calendar_year_popover.xml create mode 100644 addons/web/static/src/views/calendar/calendar_year/calendar_year_renderer.js create mode 100644 addons/web/static/src/views/calendar/calendar_year/calendar_year_renderer.xml create mode 100644 addons/web/static/src/views/calendar/colors.js create mode 100644 addons/web/static/src/views/calendar/date_picker/calendar_date_picker.js create mode 100644 addons/web/static/src/views/calendar/filter_panel/calendar_filter_panel.js create mode 100644 addons/web/static/src/views/calendar/filter_panel/calendar_filter_panel.scss create mode 100644 addons/web/static/src/views/calendar/filter_panel/calendar_filter_panel.xml create mode 100644 addons/web/static/src/views/calendar/hooks.js create mode 100644 addons/web/static/src/views/calendar/mobile_filter_panel/calendar_mobile_filter_panel.js create mode 100644 addons/web/static/src/views/calendar/mobile_filter_panel/calendar_mobile_filter_panel.xml create mode 100644 addons/web/static/src/views/calendar/quick_create/calendar_quick_create.js create mode 100644 addons/web/static/src/views/calendar/quick_create/calendar_quick_create.xml create mode 100644 addons/web/static/tests/mobile/views/calendar_view_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_arch_parser_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_common_popover_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_common_renderer_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_date_picker_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_filter_panel_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_quick_create_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_view_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_year_popover_tests.js create mode 100644 addons/web/static/tests/views/calendar/calendar_year_renderer_tests.js create mode 100644 addons/web/static/tests/views/calendar/helpers.js diff --git a/addons/hr_holidays/static/src/scss/time_off.scss b/addons/hr_holidays/static/src/scss/time_off.scss index a549bf18356..ccad3e23d9d 100644 --- a/addons/hr_holidays/static/src/scss/time_off.scss +++ b/addons/hr_holidays/static/src/scss/time_off.scss @@ -30,7 +30,7 @@ color: #adb5bd; } - .o_calendar_view .o_calendar_widget .fc-dayGridMonth-view { + .o_legacy_calendar_view .o_calendar_widget .fc-dayGridMonth-view { .fc-week-number { padding-top: 0.2rem !important; padding-bottom: 0.3rem !important; diff --git a/addons/project/static/tests/tours/project_update_tour_tests.js b/addons/project/static/tests/tours/project_update_tour_tests.js index 5dd5daf5e90..f4b5f56f916 100644 --- a/addons/project/static/tests/tours/project_update_tour_tests.js +++ b/addons/project/static/tests/tours/project_update_tour_tests.js @@ -173,7 +173,7 @@ tour.register('project_update_tour', { }, ...openProjectUpdateAndReturnToTasks("Pivot", "o_pivot_view"), { trigger: '.o_switch_view.o_calendar', content: 'Open Calendar View of Tasks', -}, ...openProjectUpdateAndReturnToTasks("Calendar", "o_calendar_view"), { +}, ...openProjectUpdateAndReturnToTasks("Calendar", "o_legacy_calendar_view"), { trigger: '.o_switch_view.o_activity', content: 'Open Activity View of Tasks', }, ...openProjectUpdateAndReturnToTasks("Activity", "o_activity_view"), diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py index 7c3e9e1e33c..57d02c4bbda 100644 --- a/addons/web/__manifest__.py +++ b/addons/web/__manifest__.py @@ -86,6 +86,7 @@ This module provides the core of the Odoo Web Client. 'web/static/lib/underscore/underscore.js', 'web/static/lib/underscore.string/lib/underscore.string.js', 'web/static/lib/moment/moment.js', + 'web/static/lib/luxon/luxon.js', 'web/static/lib/owl/owl.js', 'web/static/src/owl2_compatibility/*.js', 'web/static/src/legacy/js/component_extension.js', @@ -204,7 +205,6 @@ This module provides the core of the Odoo Web Client. 'web/static/src/env.js', 'web/static/lib/jquery.scrollTo/jquery.scrollTo.js', - 'web/static/lib/luxon/luxon.js', 'web/static/lib/py.js/lib/py.js', 'web/static/lib/py.js/lib/py_extras.js', 'web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js', @@ -601,6 +601,7 @@ This module provides the core of the Odoo Web Client. 'web/static/lib/fullcalendar/daygrid/main.js', 'web/static/lib/fullcalendar/timegrid/main.js', 'web/static/lib/fullcalendar/list/main.js', + 'web/static/lib/fullcalendar/luxon/main.js', 'web/static/lib/ace/ace.js', 'web/static/lib/ace/javascript_highlight_rules.js', @@ -620,7 +621,7 @@ This module provides the core of the Odoo Web Client. 'web/static/tests/helpers/**/*.js', 'web/static/tests/views/helpers.js', 'web/static/tests/search/helpers.js', - 'web/static/tests/views/helpers.js', + 'web/static/tests/views/calendar/helpers.js', 'web/static/tests/webclient/**/helpers.js', 'web/static/tests/qunit.js', 'web/static/tests/main.js', @@ -645,6 +646,7 @@ This module provides the core of the Odoo Web Client. ('remove', 'web/static/tests/search/helpers.js'), 'web/static/tests/views/**/*.js', ('remove', 'web/static/tests/views/helpers.js'), + ('remove', 'web/static/tests/views/calendar/helpers.js'), 'web/static/tests/webclient/**/*.js', ('remove', 'web/static/tests/webclient/**/helpers.js'), 'web/static/tests/legacy/**/*.js', diff --git a/addons/web/static/src/core/l10n/dates.js b/addons/web/static/src/core/l10n/dates.js index 05db2bace57..48f4956bedc 100644 --- a/addons/web/static/src/core/l10n/dates.js +++ b/addons/web/static/src/core/l10n/dates.js @@ -168,6 +168,17 @@ export const luxonToMomentFormat = memoize(function luxonToMomentFormat(format) // Formatting // ----------------------------------------------------------------------------- +/** + * Returns true if the given format is a 24-hour format. + * Returns false otherwise. + * + * @param {string} [format=localization.timeFormat] + * @returns true if the format contains a 24 hour format + */ +export function is24HourFormat(format) { + return (format || localization.timeFormat).indexOf("H") !== -1; +} + /** * Formats a DateTime object to a date string * diff --git a/addons/web/static/src/legacy/js/views/calendar/calendar_renderer.js b/addons/web/static/src/legacy/js/views/calendar/calendar_renderer.js index ee51cbce9d1..37fe3b66ef6 100644 --- a/addons/web/static/src/legacy/js/views/calendar/calendar_renderer.js +++ b/addons/web/static/src/legacy/js/views/calendar/calendar_renderer.js @@ -674,7 +674,7 @@ return AbstractRenderer.extend({ * @override */ async _renderView() { - this.$('.o_calendar_view')[0].prepend(this.calendarElement); + this.$('.o_legacy_calendar_view')[0].prepend(this.calendarElement); if (this._isInDOM) { this._renderCalendar(); } diff --git a/addons/web/static/src/legacy/scss/views.scss b/addons/web/static/src/legacy/scss/views.scss index 0ee60cf000e..a268abdf71c 100644 --- a/addons/web/static/src/legacy/scss/views.scss +++ b/addons/web/static/src/legacy/scss/views.scss @@ -3,7 +3,10 @@ * all renderers. For field default rules, see the fields.scss file. */ -.o_debug .o_legacy_form_view, .o_debug .o_legacy_kanban_view, .o_debug .o_legacy_list_view { +.o_debug .o_legacy_form_view, +.o_debug .o_legacy_kanban_view, +.o_debug .o_legacy_list_view, +.o_debug .o_legacy_calendar_view { border-top: 3px solid red; } diff --git a/addons/web/static/src/legacy/scss/web_calendar.scss b/addons/web/static/src/legacy/scss/web_calendar.scss index ee29e606d8d..a40b30d2a7b 100644 --- a/addons/web/static/src/legacy/scss/web_calendar.scss +++ b/addons/web/static/src/legacy/scss/web_calendar.scss @@ -1,20 +1,4 @@ -// Variables -$o-cw-color-today-accent: #FC3D39; -$o-cw-popup-avatar-size: 16px; -$o-cw-filter-avatar-size: 20px; - -// Animations -@keyframes backgroundfade { - from { background-color: rgba($info, 0.5); } - to { background-color: rgba($info, 0.1); } -} - -.o_calendar_container { - height: 100%; - display: flex; -} - -.o_calendar_view { +.o_legacy_calendar_view { flex: 1 1 auto; min-width: 0; height: 100%; @@ -558,289 +542,11 @@ $o-cw-filter-avatar-size: 20px; } } -.o_calendar_sidebar_container { - flex: 0 0 auto; - position: relative; - @include o-webclient-padding($top: $o-horizontal-padding/2); - background-color: $o-view-background-color; - border-left: 1px solid $border-color; - overflow-y:auto; - - .o_calendar_sidebar { - width: 200px; - font-size: 14px; - - @include media-breakpoint-up('xl') { - width: 250px; - } - // sync buttons are only displayed on calendar.event views - .o_calendar_sync { - padding-top: 0.5em; - } - } - - .ui-datepicker { - margin: 0; - width: 100%; - padding: 0; - - &, td, .ui-datepicker-header, td a, td span { - border: 0; - } - - th { - padding: .7em .2em; - width: 14%; - - > span { - color: #666666; - } - } - - td { - padding: 0; - - a, span { - padding: 5px 0; - background: none; - text-align: center; - vertical-align: middle; - font-size: 1.2rem; - color: map-get($grays, '900'); - font-weight: 400; - } - - &.ui-datepicker-current-day a { - background: $info; - color: color-contrast($info); - font-weight: bold; - } - - &.ui-datepicker-today a { - margin: auto; - border-radius: 100%; - padding: .1em; - width: 25px; - background: mix($o-cw-color-today-accent, white, 80%); - color: white; - } - - &.ui-datepicker-current-day.ui-datepicker-today a { - background: $o-cw-color-today-accent; - } - } - - .ui-datepicker-header { - background: none; - } - - .ui-datepicker-header { - border-radius: 0; - - .ui-datepicker-title { - color: map-get($grays, '600'); - font-size: 1.2rem; - font-weight: normal; - } - - .ui-icon { - background-image: none; - text-indent: 0; - color: transparent; - - &:before { - font: normal normal normal 13px/1 FontAwesome; - content: "\f053"; - color: map-get($grays, '400'); - } - &.ui-icon-circle-triangle-e:before { - content: "\f054" - } - } - - .ui-state-hover.ui-datepicker-next-hover, .ui-state-hover.ui-datepicker-prev-hover { - background: none; - border: none; - cursor: pointer; - - span:before { - color: map-get($grays, '800'); - } - } - } - - .o_selected_range.o_color:not(.ui-datepicker-unselectable) { - background-color: $info; - animation: backgroundfade 2s forwards; - } - } - - .o_calendar_filter { - font-size: 0.9em; - padding: 2em 0 1em; - - .o_cw_filter_collapse_icon { - transition: all 0.3s ease; - @include o-hover-opacity(); - font-size: 0.7em; - } - - .collapsed .o_cw_filter_collapse_icon { - transform: rotate(90deg); - opacity: 1; - } - - .o_calendar_filter_items_checkall, .o_calendar_filter_item { - cursor: pointer; - overflow: hidden; - - input { - z-index: -1; - opacity: 0; - } - - .o_cw_filter_input_bg { - width: 1.3em; - height: 1.3em; - border-width: 2px; - border-style: solid; - border-radius: 1px; - overflow: hidden; - - &.o_beside_avatar { - width: $o-cw-filter-avatar-size; - height: $o-cw-filter-avatar-size; - border-radius: 2px; - object-fit: cover; - } - } - - input:not(:checked) + label .o_cw_filter_input_bg { - background: transparent!important; - - i.fa { - visibility: hidden; - } - } - - - .o_cw_filter_avatar { - width: $o-cw-filter-avatar-size; - height: $o-cw-filter-avatar-size; - border-radius: 2px; - - &.fa { - padding: 4px 3px; - } - } - - .o_cw_filter_title { - line-height: $o-line-height-base; - flex-grow: 1; - } - - button.o_remove { - @include o-position-absolute(0,0,0); - transform: translateX(100%); - transition: transform 0.2s; - } - - &:hover { - button.o_remove { - transform: translateX(0%); - } - } - } - - .o_field_many2one { - margin-top: 1rem; - width: 100%; - } - } -} - -.o_cw_popover { - min-width: 256px; - max-width: 328px; - font-size: $font-size-base; - - .card-header, .card-header .popover-header { - font-size: 1.05em; - font-weight: 500; - line-height: 1; - } - - .card-footer { - background: none; - } - - .o_footer_shrink { - padding-top: 0px; - padding-bottom: 0px; - } - .o_cw_popover_close { - cursor: pointer; - } - - .o_calendar_avatars { - line-height: 1; - } - - .o_calendar_avatars img { - margin-right: 0.4rem; - width: $o-cw-popup-avatar-size; - height: $o-cw-popup-avatar-size; - border-radius: 100%; - } - - .list-group-item { - padding: 0.5rem 1rem; - border: none; - } - - .o_cw_popover_fields_secondary { - max-height: 170px; // Fallback for old browsers - max-height: 25vh; - overflow: auto; - padding-bottom: 1px; // prevents the scrollbar to show when not needed - - &::-webkit-scrollbar { - background: map-get($grays, '200'); - width: 6px; - } - &::-webkit-scrollbar-thumb { - background: map-get($grays, '500'); - } - } - - .fc-rtl & { - text-align: right; - .o_calendar_avatars { - > div { - justify-content: flex-end; - } - img { - order: 2; - margin: 0 0 0 0.4rem; - } - } - } -} - -// Generated with http://phrogz.net/css/distinct-colors.html -// Do not modify the first 12 colors of this list or it will break the colors in the Time Off Calendar -$o-filter_colors: lighten(#000, 46.7%), #F06050, #F4A460, #F7CD1F, #6CC1ED, #814968, #EB7E7F, #2C8397, #475577, - #D6145F, #30C381, #9365B8, #ff1e00, #bf9600, #0003b3, #ff006a, #cc3300, #ffea00, #00cc85, - #007ab3, #6900cc, #ff0048, #c2cc00, #00ffc8, #008cff, #bf0036, #b24400, #d0ff00, #00ffea, - #0062b3, #ea00ff, #ff0026, #8bcc00, #00bfaf, #006aff, #af00bf, #bf001d, #bf6300, #8cff00, - #00f2ff, #004ab3, #ff00d0, #ffa600, #3acc00, #00b6bf, #0048ff, #bf7c00, #04ff00, #00d0ff, - #0036bf, #ff008c, #00bf49, #0092b3, #0004ff, #b20062, #649173 !default; - // =============== Generate color classes =============== @for $i from 1 through length($o-filter_colors) { $color: nth($o-filter_colors, $i); - .o_calendar_view .fc-view { + .o_legacy_calendar_view .fc-view { .o_calendar_hatched_#{$i - 1} { background: repeating-linear-gradient( 45deg, @@ -947,39 +653,4 @@ $o-filter_colors: lighten(#000, 46.7%), #F06050, #F4A460, #F7CD1F, #6CC1ED, #814 } } } - - .o_cw_filter_color_#{$i - 1} { - .o_cw_filter_input_bg { - border-color: $color; - background: $color; - color: color-contrast($color); - } - } - - .o_cw_popover.o_calendar_color_#{$i - 1} { - $color-subdle: mix(white, $color, 90%); - - .card-header, .card-header .popover-header { - background-color: $color-subdle; - color: color-contrast($color-subdle); - } - - .card-header { - padding-left: 2px; - border-color: mix($card-border-color, mix(white, $color)); - } - } -} - -.modal { - .o_attendee_head { - width: 32px; - margin-right: 5px; - } -} - -.o_dashboard { - .o_calendar_container .o_calendar_sidebar_container { - display: none; - } } diff --git a/addons/web/static/src/legacy/xml/web_calendar.xml b/addons/web/static/src/legacy/xml/web_calendar.xml index 6d511f565c3..1972507c360 100644 --- a/addons/web/static/src/legacy/xml/web_calendar.xml +++ b/addons/web/static/src/legacy/xml/web_calendar.xml @@ -1,6 +1,6 @@