diff options
| author | qsm-odoo <qsm@odoo.com> | 2018-03-12 16:27:41 +0100 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2018-04-18 15:59:15 +0200 |
| commit | b04dec4025013c60e4857c1e177bb20d811cd41a (patch) | |
| tree | db8b38a5e1df34ee6f0402fab9a0bd8b4b769f8e /addons/web/static/src/scss | |
| parent | a6393130e6fcc4ad706f3df08557e5434416e4ab (diff) | |
[REF] *: rename all LESS files to SCSS
This is a simple renaming without adaptation.
Diffstat (limited to 'addons/web/static/src/scss')
49 files changed, 6679 insertions, 0 deletions
diff --git a/addons/web/static/src/scss/animation.scss b/addons/web/static/src/scss/animation.scss new file mode 100644 index 00000000000..6da0a1f9d64 --- /dev/null +++ b/addons/web/static/src/scss/animation.scss @@ -0,0 +1,162 @@ +/************** DEFINITION of ANIMATIONS **************/ +// 'marked' effects +@keyframes markAnim { + 0% { + opacity: 0; + transform: scaleX(0.50) scaleY(0.50); + } + 30% { + opacity: 1; + transform: scaleX(1.00) scaleY(1.00); + } + 100% { + opacity: 0; + transform: scaleX(1.00) scaleY(1.00); + } +} + +@-moz-keyframes markAnim { + 0% { + opacity: 0; + -moz-transform: scaleX(0.50) scaleY(0.50); + } + 30% { + opacity: 1; + -moz-transform: scaleX(1.00) scaleY(1.00); + } + 100% { + opacity: 0; + -moz-transform: scaleX(1.00) scaleY(1.00); + } +} + +@-webkit-keyframes markAnim { + 0% { + opacity: 0; + -webkit-transform: scaleX(0.50) scaleY(0.50); + } + 30% { + opacity: 1; + -webkit-transform: scaleX(1.00) scaleY(1.00); + } + 100% { + opacity: 0; + -webkit-transform: scaleX(1.00) scaleY(1.00); + } +} + +@-o-keyframes markAnim { + 0% { + opacity: 0; + -o-transform: scaleX(0.50) scaleY(0.50); + } + 30% { + opacity: 1; + -o-transform: scaleX(1.00) scaleY(1.00); + } + 100% { + opacity: 0; + -o-transform: scaleX(1.00) scaleY(1.00); + } +} + +@-ms-keyframes markAnim { + 0% { + opacity: 0; + -ms-transform: scaleX(0.50) scaleY(0.50); + } + 30% { + opacity: 1; + -ms-transform: scaleX(1.00) scaleY(1.00); + } + 100% { + opacity: 0; + -ms-transform: scaleX(1.00) scaleY(1.00); + } +} + +// 'bounce' effect +@-webkit-keyframes bounceIn { + 0%, 20%, 40%, 60%, 80%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + 40% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + 80% { + -webkit-transform: scale3d(.97, .97, .97); + transform: scale3d(.97, .97, .97); + } + 100% { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +@keyframes bounceIn { + 0%, 20%, 40%, 60%, 80%, 100% { + -webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); + } + 0% { + opacity: 0; + -webkit-transform: scale3d(.3, .3, .3); + transform: scale3d(.3, .3, .3); + } + 20% { + -webkit-transform: scale3d(1.1, 1.1, 1.1); + transform: scale3d(1.1, 1.1, 1.1); + } + 40% { + -webkit-transform: scale3d(.9, .9, .9); + transform: scale3d(.9, .9, .9); + } + 60% { + opacity: 1; + -webkit-transform: scale3d(1.03, 1.03, 1.03); + transform: scale3d(1.03, 1.03, 1.03); + } + 80% { + -webkit-transform: scale3d(.97, .97, .97); + transform: scale3d(.97, .97, .97); + } + 100% { + opacity: 1; + -webkit-transform: scale3d(1, 1, 1); + transform: scale3d(1, 1, 1); + } +} + +/************** MIXINS for ANIMATIONS **************/ +.o-display-marked(@content, @top, @left, @color) { + .o-position-absolute(@top: @top, @left: @left); + font-size: 300px; + font-family: "FontAwesome"; + content: @content; + color: @color; + .o-transform-origin(); + .o-animation(markAnim, 1s, ease-in-out, 0s, 1, normal, forwards); + + @media (max-width: @screen-sm-max) { + left: 40%; + font-size: 30vw; + } +} diff --git a/addons/web/static/src/scss/base_settings.scss b/addons/web/static/src/scss/base_settings.scss new file mode 100644 index 00000000000..426d8cb557c --- /dev/null +++ b/addons/web/static/src/scss/base_settings.scss @@ -0,0 +1,235 @@ +// VARIABLES +@o-base-settings-mobile-tabs-height: 40px; +@o-base-settings-mobile-tabs-overflow-gap: 3%; + +// MIXINS +.o-base-settings-horizontal-padding(@padding-base: @padding-small-vertical) { + padding: @padding-base @odoo-horizontal-padding; + + @media (min-width: @screen-lg-min) { + padding-left: @odoo-horizontal-padding*2;; + } +} + +// Use a very specif selector to overwrite generic form-view rules +.o_form_view.o_form_nosheet.o_base_settings { + .o-flex-display(); + .o-flex-flow(column, nowrap); + padding: 0px; +} + +// BASE SETTINGS LAYOUT +.o_base_settings { + height: 100%; + + @media (max-width: @screen-xs-max) { + .o-flex-flow(column, nowrap); + } + + .o_control_panel { + .o_panel { + .o-flex-display(); + .o-flex-flow(row, wrap); + margin-bottom: @odoo-sheet-vpadding*0.5; + width: 100%; + + .title, .o_setting_search { + .o-flex(1, 0, auto); + width: @screen-xs-min*0.5; + } + + .o_setting_search { + position: relative; + + .searchInput { + height: 28px; + padding: 0px; + border: 0px; + border-bottom: 1px solid @gray-lighter-darker; + border-color: @gray; + box-shadow: none; + font-weight: 500; + } + + .searchIcon { + .o-position-absolute(4px, 0); + color: @gray; + } + } + } + + .o_form_statusbar { + padding: 0; + margin: 0; + border: 0; + + .btn-primary, .btn-link { + padding: @padding-small-vertical @padding-small-horizontal; + } + + .btn-link { + .o-hover-text-color(@link-color, @link-hover-color); + } + } + } + + .o_setting_container { + .o-flex-display(); + .o-flex(1, 1, auto); + + overflow: auto; + + @media (max-width: @screen-xs-max) { + .o-flex-flow(column, nowrap); + } + + .settings_tab { + .o-flex-display(); + .o-flex(0, 0, auto); + .o-flex-flow(column, nowrap); + background: @gray-dark; + overflow: auto; + padding-top: @odoo-horizontal-padding*0.5; + + @media (max-width: @screen-xs-max) { + .o-flex(0, 0, @o-base-settings-mobile-tabs-height); + .o-inline-flex-display(); + position: relative; + overflow: hidden; + padding: 0; + } + + .selected { + background-color: @gray-darker; + box-shadow: inset 3px 0 0 @odoo-brand-optional; + + .app_name { + color: white; + } + } + + .tab { + .o-flex-display(); + padding: 0 @odoo-horizontal-padding*2 0 @odoo-horizontal-padding; + height: 40px; + color: @gray-lighter-darker; + font-size: 13px; + line-height: 40px; + cursor: pointer; + + .icon { + width: 23px; + margin-right: 10px; + } + + // Mobile Tabs + @media (max-width: @screen-xs-max) { + display: block; + .o-position-absolute(@left:100%); + .size(auto, @o-base-settings-mobile-tabs-height); + padding: @o-base-settings-mobile-tabs-height*0.25 @o-base-settings-mobile-tabs-height*0.4; + text-align: center; + font-size: 14px; + font-weight: 500; + line-height: inherit; + .o-transition(0.2s, all); + .o-transform(translate3d(0,0,0)); + + .app_name { + display: block; + white-space: nowrap; + } + + &:after { + content: ''; + background: @odoo-brand-optional; + opacity: 0; + .o-position-absolute(auto, 0, 0, 0); + .size(100%, 3px); + .o-transition(0.2s, all); + } + + &.previous, &.before { + left: 0% - @o-base-settings-mobile-tabs-overflow-gap; + } + + &.current { + left: 50%; + color: white; + + // Reset default style for 'selected' tabs + box-shadow: none; + background: none; + + &:after { + opacity: 1; + } + } + + &.next, &.after { + left: 100% + @o-base-settings-mobile-tabs-overflow-gap; + } + } + } + } + + .settings { + position: relative; + .o-flex(1, 1, 100%); + background-color: @odoo-view-background-color; + overflow: auto; + + > .app_settings_block { + h2 { + margin-bottom: 0; + .o-base-settings-horizontal-padding(); + background-color: @gray-lighter; + font-size: 15px; + font-weight: bold; + + &:first-of-type { + // Necessary to overwrite mt32 class + margin-top: 10px!important; + } + } + + .o_settings_container { + max-width: @screen-md-min; // Provide a maximum container size to ensure readability + .o-base-settings-horizontal-padding(0); + } + } + + .settingSearchHeader { + .o-flex-display(); + margin: 30px 0 10px; + .o-base-settings-horizontal-padding(); + background-color: @gray-lighter; + + .icon { + .square(25px); + margin-right: 10px; + } + + .appName { + color: @headings-color; + font-size: 17px; + } + } + + .notFound { + color : @text-muted; + text-align: center; + font-size: 25px; + padding-top: 50px; + } + + .highlighter { + background: yellow; + } + } + + .d-block { + display: block!important; + } + } +} diff --git a/addons/web/static/src/scss/bootstrap_overridden.scss b/addons/web/static/src/scss/bootstrap_overridden.scss new file mode 100644 index 00000000000..5bbe61ecdf6 --- /dev/null +++ b/addons/web/static/src/scss/bootstrap_overridden.scss @@ -0,0 +1,168 @@ +// ------------------------------------------------------------------ +// Bootstrap variables +// ------------------------------------------------------------------ + +//== Grid +@grid-gutter-width: @odoo-horizontal-padding*2; + +//== Colors +@brand-primary: @odoo-brand-primary; +@gray-lighter: @odoo-color-silver; + +//== Titles +@font-size-h1: @odoo-font-size-base + 13px; +@font-size-h2: @odoo-font-size-base + 7px; +@font-size-h3: @odoo-font-size-base + 3px; +@font-size-h4: @odoo-font-size-base + 2px; +@font-size-h5: @odoo-font-size-base + 1px; +@font-size-h6: @odoo-font-size-base; + +//== Scaffolding +@body-bg: @odoo-brand-secondary; +@text-color: @odoo-main-text-color; +@link-color: @odoo-brand-optional; +@link-hover-decoration: none; + +//== Typography +@font-family-sans-serif: "Lucida Grande", Helvetica, Verdana, Arial, sans-serif; +@font-size-base: @odoo-font-size-base; +@headings-font-weight: bold; + +//== Components +@component-active-bg: @gray-lighter; +@component-active-color: @odoo-brand-optional; + +//== Badges +@badge-bg: @odoo-brand-optional; +@badge-color: white; +@badge-line-height: @line-height-base; +@badge-font-weight: normal; + +//== Breadcrumbs +@breadcrumb-active-color: #777777; +@breadcrumb-bg: @odoo-control-panel-background-color; +@breadcrumb-color: #777777; +@breadcrumb-padding-horizontal: 0; +@breadcrumb-padding-vertical: 0; + +//== Buttons +@btn-default-bg: white; +@btn-default-border: #cccccc; +@btn-default-color: @odoo-main-text-color; +@btn-primary-bg: @odoo-brand-optional; +@btn-primary-border: @odoo-brand-optional; +@btn-primary-color: white; + +//== Dropdowns +@dropdown-bg: white; +@dropdown-border: @gray-lighter-dark; +@dropdown-divider-bg: @gray-lighter-dark; +@dropdown-link-color: @odoo-main-text-color; +@dropdown-link-hover-color: @gray-dark; +@dropdown-link-hover-bg: @gray-lighter; +@dropdown-link-active-color: @component-active-color; +@dropdown-link-active-bg: @component-active-bg; +@dropdown-link-disabled-color: @gray-light; +@dropdown-header-color: @gray-light; + +//== Modals +@modal-sm: 300px; +@modal-md: 650px; +@modal-lg: 980px; +@modal-inner-padding: @odoo-horizontal-padding; +@modal-title-padding: @odoo-horizontal-padding; + +// Change the z-index of the modal-backdrop elements to be equal to the +// modal elements' ones. Bootstrap does not support multi-modals, and without +// this rule all the modal-backdrops are below all the opened modals. +// Indeed, bootstrap forces them to a lower z-index as the modal-backdrop +// element (unique in their supported cases) might be put after the modal +// element (if the modal is already in the DOM, hidden, then opened). This +// cannot happen in odoo though as modals are not hidden but removed from +// the DOM and are always put at the end of the body when opened. +// +// Note that the variable @zindex-modal-background may be renamed/removed in +// newer versions of bootstrap. +// +// TODO the following code was disabled because it is saas-incompatible +// +// @zindex-modal-background: @zindex-modal; + +//== Navs +@nav-link-padding: 10px 15px; +@nav-pills-border-radius: 0; +@nav-pills-active-link-hover-color: white; +@nav-pills-active-link-hover-bg: @odoo-brand-optional; +@nav-tabs-active-link-hover-bg: white; + +//== Navbar +@navbar-height: @odoo-navbar-height - 2; +@navbar-margin-bottom: 0; +@navbar-inverse-bg: #222222; +@navbar-inverse-link-color: #9d9d9d; +@navbar-inverse-link-hover-bg: #222222; +@navbar-inverse-toggle-hover-bg: #222222; +@navbar-border-radius: 0; + +//== Tables +@table-bg-accent: #efeff8; // FIXME: expose +@table-bg-hover: darken(@table-bg-accent,5%); + +// ------------------------------------------------------------------ +// Bootstrap components rules (non exposed features variables) +// ------------------------------------------------------------------ + +//== Badges +.badge { + margin: 1px 2px 1px 0; + padding-top: 0; + padding-bottom: 0; +} + +//== Buttons +// Mixin to define variations for btn-links and muted btn-links +.o-btn-link-variant(@color, @color-active) { + text-transform: none; + .o-hover-text-color(@default-color: @color, @hover-color: @color-active); + + &, &:hover, &:focus, &:active, &.active { + border-color: transparent; + background-color: transparent + } + + &.text-muted, .text-muted { + .o-hover-opacity(); + .o-hover-text-color(@default-color: @text-muted, @hover-color: @color-active); + } +} +.btn-icon { + .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border); +} +.btn-link { + font-weight: @btn-font-weight; + + &.btn-default { + .o-btn-link-variant(@text-color, @headings-color); + } + &.btn-success, &.text-success { + .o-btn-link-variant(@text-color, @brand-success); + } + &.btn-warning, &.text-warning { + .o-btn-link-variant(@text-color, @brand-warning); + } + &.btn-danger, &.text-danger { + .o-btn-link-variant(@text-color, @brand-danger); + } + &.btn-info, &.text-info { + .o-btn-link-variant(@text-color, darken(@brand-info, 20%)); + } +} + +//== Printing improvements +@media print { + .table-responsive { + overflow-x: initial; + } +} + +@icon-font-path: "/web/static/lib/bootstrap/fonts/"; diff --git a/addons/web/static/src/scss/control_panel.scss b/addons/web/static/src/scss/control_panel.scss new file mode 100644 index 00000000000..325ed25b3ac --- /dev/null +++ b/addons/web/static/src/scss/control_panel.scss @@ -0,0 +1,133 @@ +@breadcrumb-height: 30px; + +.o_control_panel { + .o-flex-display(); + .o-flex-flow(row, wrap); + border-bottom: 1px solid darken(@odoo-control-panel-background-color, 20%); + .o-webclient-padding(@top: 10px, @bottom: 10px); + background-color: @odoo-control-panel-background-color; + + > .breadcrumb { + width: 50%; + margin: 0px; + font-size: 18px; + + > li { + .o-text-overflow(@max-width: 90%); + + > a { + cursor: pointer; + } + } + } + + &.o_breadcrumb_full > .breadcrumb { + width: 100%; + } + + > .o_cp_searchview { + width: 50%; + min-height: @breadcrumb-height; + } + + .btn.o_enable_searchview { + width: 10%; + margin-left: 2%; + padding: 0px; + } + + > .o_cp_left { + .o-flex-display(); + .o-justify-content(space-between); + width: 50%; + margin-top: 5px; + + > .o_cp_sidebar { + padding-right: 10px; + + .o_hidden_input_file { + position: relative; + input.o_input_file { + position: absolute; + top: 1px; + opacity: 0; + width: 100%; + height: 26px; + } + .o_form_binary_form span { + padding: 3px 25px; + color: @btn-default-color; + } + .o_form_binary_form:hover { + background-color: @table-bg-hover; + } + } + .o_sidebar_delete_attachment { + padding: 0px; + position: absolute; + top: 5px; + right: 10px; + } + } + } + + > .o_cp_right { + .o-flex-display(); + width: 50%; + margin-top: 5px; + + > .o_cp_pager { + margin: auto 0 auto auto; + padding-left: 5px; + text-align: center; + .user-select(none); + + > div { + .o-flex-display(); + .o-align-items(center); + } + + .o_pager_counter { + margin-right: 5px; + } + } + + > .o_cp_switch_buttons > .btn:first-child { + margin-left: @odoo-horizontal-padding; + } + } +} + +.o_x2m_control_panel { + .o-flex-display(); + .o-flex-flow(row, wrap); + + .o_cp_buttons { + .o-flex-display(); + margin-right: auto; + > div { + margin-top: 5px; + } + } + .o_cp_pager { + .o-flex-display(); + margin-left: auto; + } +} + +// Pager input (to edit pager values) +.o_pager_value > input { + display: inline-block; + width: 60px; + text-align: right; + + &:focus { + outline: none; + } +} + +@media print { + .o_control_panel { + display: none; + } +} diff --git a/addons/web/static/src/scss/data_export.scss b/addons/web/static/src/scss/data_export.scss new file mode 100644 index 00000000000..01a1da80134 --- /dev/null +++ b/addons/web/static/src/scss/data_export.scss @@ -0,0 +1,109 @@ +.o_web_client .o_export { + .o-flex(1, 1, auto); + .o-flex-display(); + .o-flex-flow(column, nowrap); + min-height: 0; + + > p, > .row { + .o-flex(0, 0, auto); + } + + label { + vertical-align: top; + font-weight: normal; + } + + .o_import_compat, .o_export_format { + display: inline-block; + + > div { + margin-left: 5px; + .o-inline-flex-display(); + .o-align-items(center); + + > label, > input { + margin: 0 0 0 5px; + } + } + } + + .o_export_panel { + .o-flex(1, 1, auto); + position: relative; + min-height: 0; + + > div { + height: 100%; + .o-flex-display(); + .o-flex-flow(column, nowrap); + .o-justify-content(center); + + &.o_left_panel { // Needed because of chrome + .o-position-absolute(@top: 0, @bottom: 0, @left: 0, @right: 57%); + } + &.o_center_panel { // Needed because of chrome + .o-position-absolute(@top: 0, @bottom: 0, @left: 43%, @right: 43%); + } + &.o_right_panel { // Needed because of chrome + .o-position-absolute(@top: 0, @bottom: 0, @left: 57%, @right: 0); + } + + > h4, > div { + .o-flex(0, 0, auto); + } + + > button { + .o-flex(0, 0, auto); + margin-top: 10px; + } + + .o_left_field_panel, .o_fields_list { + border: 1px solid @odoo-brand-lightsecondary; + overflow: auto; + .o-flex(1, 1, auto); + min-height: 0; + } + + .o_export_tree_item { + cursor: pointer; + position: relative; + padding-left: 20px; + .user-select(none); + + &.o_selected > .o_tree_column { + background-color: @odoo-brand-primary; + color: white; + } + + .o_expand_parent { + .o-position-absolute(@top: 4px, @left: 5px); + } + .o_tree_column { + display: block; + + &.o_required { + border-bottom: 2px solid @odoo-main-text-color; + } + } + + &:focus { + outline: none; + } + } + + .o_save_list, .o_exported_lists { + .o-flex-display(); + .o-align-items(baseline); + + > label, > button { + margin: 0 0 5px; + .o-flex(0, 0, auto); + } + > input, > select { + width: 0; + .o-flex(1, 0, auto); + } + } + } + } +} diff --git a/addons/web/static/src/scss/datepicker.scss b/addons/web/static/src/scss/datepicker.scss new file mode 100644 index 00000000000..fdf3a585b57 --- /dev/null +++ b/addons/web/static/src/scss/datepicker.scss @@ -0,0 +1,78 @@ +@odoo-datepicker-week-color: #8f8f8f; +@odoo-datepicker-week-bg-color: lighten(@odoo-datepicker-week-color, 30%); + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0,0,0,0); + border: 0; +} + +.o_datepicker { + position: relative; + + .o_datepicker_input { + width: 100%; + cursor: pointer; + } + + .o_datepicker_button { + .o-position-absolute(2px, 4px); + pointer-events: none; // let click events go through the underlying input + &:after { + .o-caret-down; + } + } +} + +// Need to put datetimepicker widget above everything else +// The '.dropdown-menu' part is needed to override default bootstrap rule as +// this file is unfortunately placed in common assets. +.bootstrap-datetimepicker-widget.dropdown-menu { + z-index: @zindex-modal + 1; +} + +.datepicker { + .table-condensed { + > thead { + color: white; + background-color: @odoo-brand-primary; + + > tr { + &:first-child { + th:hover { + color: white; + background-color: darken(@odoo-brand-primary, 10%); + } + } + + &:last-child { + color: @odoo-datepicker-week-color; + background-color: @odoo-datepicker-week-bg-color; + } + > th { + border-radius: 0; + } + } + } + + > tbody { + > tr { + > td { + &.active, .active { + background-color: @odoo-brand-optional; + border-radius: 100px; + } + + &.today:before { + border-bottom-color: @odoo-brand-optional; + } + } + } + } + } +} diff --git a/addons/web/static/src/scss/debug_manager.scss b/addons/web/static/src/scss/debug_manager.scss new file mode 100644 index 00000000000..74d20dda43a --- /dev/null +++ b/addons/web/static/src/scss/debug_manager.scss @@ -0,0 +1,8 @@ +.modal { + .o_debug_manager { + position: relative; + list-style: none; + margin: 2px 10px 2px 0; + float: left; + } +} diff --git a/addons/web/static/src/scss/domain_selector.scss b/addons/web/static/src/scss/domain_selector.scss new file mode 100644 index 00000000000..70d4c0bd0c8 --- /dev/null +++ b/addons/web/static/src/scss/domain_selector.scss @@ -0,0 +1,204 @@ + +.o_domain_node { + @o-domain-selector-indent: 32px; + @o-domain-selector-panel-space: 60px; + @o-domain-selector-row-height: 35px; // should be greater than a "normal" row so that "header" parts are the same size of rows + @o-domain-animation-bar-height: 15px; + + position: relative; + + // Rows in a domain node (selector) have a minimum height and holds the control panel + .o_domain_selector_row { + .o-flex-display(); + .o-align-items(center); + min-height: @o-domain-selector-row-height; + + > * { + .o-flex(0, 0, auto); + } + + > .o_domain_node_control_panel { + .o-position-absolute(@top: 0, @bottom: 0, @right: -@o-domain-selector-panel-space); + + > button { + float: left; + width: @o-domain-selector-panel-space/2; + height: 100%; + padding: 0; + background-color: transparent; + font-size: 16px; + opacity: 0.2; + cursor: pointer; + + &.o_domain_delete_node_button { + font-size: 12px; + padding-left: 5px; + + &:hover { + color: @brand-danger; + } + } + } + } + } + + // Rules specific to domain parts which contain sub-domain parts + &.o_domain_tree { + > .o_domain_tree_header { + position: relative; + + .o_domain_tree_operator_caret::after { + .o-caret-down(); + } + } + + > .o_domain_node_children_container { + padding-left: @o-domain-selector-indent; + } + + // Rules specific to domain root + &.o_domain_selector { + > .o_domain_tree_header { + min-height: 22px; // prevents "records button" to overflow 1-row domain + } + + > .o_domain_node_children_container { + padding-left: 0; + } + + &.o_edit_mode > .o_domain_node_children_container { + padding-right: @o-domain-selector-panel-space; // delete button is over the row + } + + > .o_domain_debug_container { + display: block; + margin-top: 16px; + padding: 8px 10px 12px; + background: @gray-dark; + color: fade(white, 50%); + font-family: monospace; + font-weight: normal; + + > input { + border: none; + padding-top: 8px; + background: transparent; + color: white; + } + } + } + } + + // Rules specific to domain parts which do not contain sub-domain parts + &.o_domain_leaf { + &.o_read_mode { + .o-inline-flex-display(); + margin-right: 4px; + } + + > .o_domain_leaf_info { + background: @odoo-brand-lightsecondary; + border: 1px solid darken(@odoo-brand-lightsecondary, 10%); + padding: 2px 4px; + + > .o_field_selector { + float: left; + margin-right: 4px; + + > .o_field_selector_value > .o_field_selector_chain_part { + border: none; + font-weight: 700; + } + } + .o_domain_leaf_operator { + font-style: italic; + } + .o_domain_leaf_value { + font-weight: 700; + } + } + + > .o_domain_leaf_edition { + .o-flex-display(); + width: 100%; + padding: 4px (@o-domain-selector-panel-space/2) 4px 0; + + > * { + .o-flex(1, 1, 15%); // operator select + width: auto; + background-color: white; + + &:first-child { // field selector + .o-flex(0, 1, 55%); + } + + &:last-child { // field value + .o-flex(1, 1, 25%); + } + + + * { + margin-left: 4px; + } + + input, select, .o_datepicker, .o_datepicker_input { + height: 100%; + } + } + + .o_domain_leaf_value_tags { + .o-flex-display(); + + > * { + .o-flex(0, 0, auto); + } + > input { + .o-flex(1, 1, auto); + width: 0; + min-width: 50px; + } + .o_domain_leaf_value_remove_tag_button { + cursor: pointer; + } + } + } + } + + // Animation effects + .o-transition(margin-bottom, .05s, ease, .05s); + + &::after { + content: ""; + .o-position-absolute(@left: 0, @right: 0, @top: 100%); + display: block; + height: @o-domain-animation-bar-height; + max-height: 0; + .o-linear-gradient(45deg, fade(@odoo-brand-optional, 40%), fade(@odoo-brand-optional, 10%)); + .o-transition(max-height, .05s, ease, .05s); + } + + &.o_hover_btns, &.o_hover_add_node { + .o_domain_node_control_panel > button { + opacity: 0.5; + &:hover { + opacity: 1.0; + } + } + } + + &.o_hover_btns { + background: darken(white, 3%); + } + + &.o_hover_add_node { + margin-bottom: @o-domain-animation-bar-height; + .o-transition(margin, .15s, ease, .5s); + + &::after { + max-height: @o-domain-animation-bar-height; + .o-transition(max-height, .15s, ease, .5s); + } + &.o_hover_add_inset_node::after { + left: @o-domain-selector-indent; + } + } +} diff --git a/addons/web/static/src/scss/dropdown.scss b/addons/web/static/src/scss/dropdown.scss new file mode 100644 index 00000000000..6501b4cc52c --- /dev/null +++ b/addons/web/static/src/scss/dropdown.scss @@ -0,0 +1,80 @@ +.li-a-padding { + padding: 3px @odoo-dropdown-hpadding; +} + +.ui-autocomplete { // Copy style of bootstrap dropdown + background-image: none; + background-color: @dropdown-bg; + border: 1px solid @dropdown-border; + font-size: @font-size-base; + padding: 5px 0px; + box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.176); + + .ui-menu-item { + padding: 0; + > a { + display: block; + color: @dropdown-link-color; + + .li-a-padding + } + + &.ui-state-focus { + background-image: none; + background-color: @odoo-brand-primary; + border: none; + font-weight: normal; + margin: 0; + } + &.o_m2o_dropdown_option { + padding-left: 20px; + > a { + color: @odoo-brand-primary; + } + } + } +} + +.dropdown-menu { + box-shadow: 0 6px 12px -4px fade(black, 25%); + + .o_inline_dropdown { + position: relative; + + &> .dropdown-menu { + top: 0; + left: 100%; + } + &:hover > .dropdown-menu { + display: block; + } + } +} + +.dropdown-menu-mixin { + .open .dropdown-menu > li { + position: relative; // to allow absolute positionning inside the li + > a { + &:focus, &:active, &:focus:active { + outline: none; + } + + .li-a-padding; + } + + &.dropdown-header { + .li-a-padding; + color: @odoo-main-text-color; + + @media (max-width: @screen-xs-max) { + color: white; + text-decoration: underline; + } + } + } +} + +.dropdown-menu-mixin(); +.navbar-nav { + .dropdown-menu-mixin(); +} diff --git a/addons/web/static/src/scss/dropdown_extra.scss b/addons/web/static/src/scss/dropdown_extra.scss new file mode 100644 index 00000000000..ec38e6d5292 --- /dev/null +++ b/addons/web/static/src/scss/dropdown_extra.scss @@ -0,0 +1,63 @@ +.ui-autocomplete .ui-menu-item { + &.ui-state-focus { + background-color: @odoo-brand-primary; + } + &.o_m2o_dropdown_option > a { + color: @odoo-brand-primary; + } + &.ui-state-focus > a, + &.ui-state-focus.o_m2o_dropdown_option > a { + color: white; + } +} + +@tag-border: #afafb6; +.oe_dropdown, .oe_dropdown_toggle { + position: relative; + cursor: pointer; +} +.oe_dropdown_toggle { + color: #2B2B2B; + font-weight: normal; +} +.oe_dropdown_menu { + display: none; + position: absolute; + z-index: 3; + margin: 0; + border: 1px solid @tag-border; + background: white; + padding: 4px 0; + min-width: 140px; + text-align: left; + box-shadow: 0 1px 4px rgba(0,0,0,0.3); + &.oe_opened { + display: block; + } + > li { + list-style-type: none; + float: none; + display: block; + position: relative; + margin: 0; + padding: 2px 8px; + &:hover { + .o-vertical-gradient(#f0f0fa, #eeeef6); + box-shadow: none; + } + > a { + white-space: nowrap; + display: block; + color: #4c4c4c; + text-decoration: none; + &:hover { + text-decoration: none; + } + } + } +} + +// Buttons used as dropdown toggler +.o_dropdown_toggler_btn { + .btn-default; +} diff --git a/addons/web/static/src/scss/fields.scss b/addons/web/static/src/scss/fields.scss new file mode 100644 index 00000000000..ff6fe9eb20b --- /dev/null +++ b/addons/web/static/src/scss/fields.scss @@ -0,0 +1,385 @@ +// +// This file regroups all the rules which apply to field widgets wherever they +// are in the DOM, in both community and enterprise versions. +// + +// Invalid +.o_field_invalid { + &.o_input, .o_input, &.o_form_label { + color: @brand-danger!important; + border-color: @brand-danger!important; // enterprise o_required_modifier rule overrides this without !important + } +} + +// Empty +.o_field_empty { + display: none!important; +} + +// Numbers +.o_field_number { + white-space: nowrap; +} + +//------------------------------------------------------------------------------ +// Fields +//------------------------------------------------------------------------------ + +.o_field_widget { + // Default display and alignment of widget and internal <input/> + &, input.o_input { + display: inline-block; + text-align: inherit; + } + + // Block fields + &.note-editor, &.oe_form_field_html, &.oe_form_field_html_text, &.oe_form_field_text, &.o_field_domain, &.o_graph_linechart, &.o_graph_barchart { + display: block; + } + + // Flex fields (inline) + &.o_field_many2one, &.o_field_radio, &.o_field_many2manytags, &.o_field_percent_pie, &.o_field_monetary, &.o_field_binary_file { + @media (min-width: @screen-sm-min) { + .o-inline-flex-display(); + } + > span, > button { + .o-flex(0, 0, auto); + } + } + + // Dropdowns input (many2one, ...) + .o_input_dropdown { + .o-flex(1, 1, auto); + position: relative; + width: 100%; + + > input { + height: 100%; + padding-right: 15px; + cursor: pointer; + } + + .o_dropdown_button { + .o-position-absolute(0, 0); + pointer-events: none; + &:after { + .o-caret-down; + } + } + } + + // Text + &.o_field_text, &.oe_form_field_text .oe_form_text_content { + width: 100%; + white-space: pre-wrap; + } + + // Monetary + &.o_field_monetary { + &.o_input { + .o-align-items(baseline); + + > input { + width: 100px; + .o-flex(1, 0, auto); + } + } + } + + // Many2many tags + &.o_field_many2manytags { + .o-flex-flow(row, wrap); + .o-align-items(baseline); + + > .o_field_widget { + .o-flex(1, 0, 100px); + position: initial; + max-width: 100%; + } + + > .badge { + .o-flex(0, 0, auto); + border: 0; + font-size: 12px; + color: white; + cursor: pointer; + + > .o_badge_text { + .o-text-overflow(inline-block); + max-width: 200px; + } + + // o-kanban-colorpicker without customizing + // '&:first-child > a::before' (transparent red-crossed colorpick) + .o-tag-colorpicker() { + @o-tag-colorpicker-padding-right: @odoo-dropdown-hpadding - 2 * @o-kanban-inner-hmargin; + + max-width: 100%; + padding: 3px @o-tag-colorpicker-padding-right 3px @odoo-dropdown-hpadding; + + > li { + display: inline-block; + margin: @o-kanban-inner-hmargin @o-kanban-inner-hmargin 0 0; + border: 1px solid white; + box-shadow: 0 0 0 1px @gray-lighter-dark; + + > a { + display: block; + + &::after { + content: ""; + display: block; + width: 20px; + height: 15px; + } + } + + &:last-of-type { + box-shadow: 0 0 0 0px white; // remove grey border on hide in kanban + color: @odoo-main-text-color; + } + } + } + + > .tagcolor_dropdown_menu { + min-width: 150px; // down from 160px of .dropdown-menu + margin-right: 0px; // cancel right margin of .dropdown-menu + } + + > .o_colorpicker > ul { + .o-tag-colorpicker(); + white-space: normal; + } + + .o_delete { + cursor: pointer; + } + } + + .o-tag-color(@size: 0) when (@size = 0) { + .o_tag_color_@{size} { + & { + background-color: white; + color: ~"@{odoo-color-@{size}}"; + box-shadow: inset 0 0 0 2px ~"@{odoo-color-@{size}}"; + } + &::after { + background-color: ~"@{odoo-color-@{size}}"; + } + } + .o-tag-color(@size + 1); + } + .o-tag-color(@size: 0) when (@size > 0) and (@size < @odoo-nb-ui-color) { + .o_tag_color_@{size} { + &, &::after { + background-color: ~"@{odoo-color-@{size}}"; + } + } + .o-tag-color(@size + 1); + } + .o-tag-color(); + } + + // Stars + &.o_priority { + display: inline-block; + padding: 0; + margin: 0; + vertical-align: baseline; + > .o_priority_star { + display: inline-block; + font-size: 1.35em; + &:hover, &:focus { + text-decoration: none; + outline: none; + } + + + .o_priority_star { + padding-left: 5px; + } + + &.fa-star-o { + color: @odoo-main-color-muted; + } + &.fa-star { + color: gold; + } + } + } + + // Favorite + &.o_favorite { + i.fa { + font-size: 16px; + } + i.fa-star-o { + color: @odoo-main-color-muted; + &:hover { + color: gold; + } + } + i.fa-star { + color: gold; + } + } + + // Specific success color for toggle_button widget + .fa.o_toggle_button_success { + color: @brand-success; + } + + // Handle widget + &.o_row_handle { + cursor: ns-resize; + } + + // Radio buttons + &.o_field_radio { + .o_radio_input { + outline: none; + } + + .o_radio_item { + .o-flex(0, 0, auto); + .o-flex-display(); + .o-align-items(center); + + > input { + .o-flex(0, 0, auto); + margin: 0 @odoo-form-spacing-unit 0 0; + } + > label { + margin: 0; + } + } + + &.o_horizontal { + .o_radio_item { + margin-right: @odoo-form-spacing-unit * 2; + } + } + + &.o_vertical { + .o-flex-flow(column, nowrap); + .o_radio_item { + margin-bottom: @odoo-form-spacing-unit; + } + } + } + + // Percent pie + &.o_field_percent_pie { + .o-align-items(center); + + > .o_pie { + position: relative; + display: inline-block; + vertical-align: middle; + margin-right: 10px; + border-radius: 100%; + overflow: hidden; + background-color: @odoo-brand-optional; + + &:after { // Outside pie border to go over border-radius irregularities + content: " "; + .o-position-absolute(0, 0); + width: 100%; + height: 100%; + border-radius: 100%; + } + + .o_mask { + .o-position-absolute(0, 0); + .o-transform-origin(0); + width: 50%; + height: 100%; + background-color: @odoo-view-background-color; + &.o_full { + background-color: inherit; + } + } + + .o_pie_value { + .o-flex-display(); + .o-justify-content(center); + .o-align-items(center); + + border-radius: 100%; + + font-weight: 700; + color: @odoo-brand-primary; + } + } + } + + // Ace editor + &.o_ace_view_editor { + width: 100%; + .ace-view-editor { + height: 300px; + padding: 0 1em; + } + } + + // Image + &.o_field_image { + position: relative; + + .o_form_image_controls { + .o-position-absolute(0, 0); + width: 100%; + + color: white; + background-color: @odoo-brand-optional; + opacity: 0; + transition: opacity ease 400ms; + + > .fa { + margin: 5px; + cursor: pointer; + } + } + @media (max-width: @screen-xs-min) { + .o_form_image_controls{ + position: initial; + opacity: 1; + > .fa{ + width: 50%; + padding: 6px; + margin: 0px; + text-align: center; + &.o_select_file_button{ + background: @odoo-brand-optional; + } + &.o_clear_file_button{ + background: @brand-danger; + } + } + } + } + + &:hover .o_form_image_controls { + opacity: 0.8; + } + } + + // Input loading/file + .o_form_binary_progress, .o_hidden_input_file .o_input_file { + display: none; + } + + // Domain + &.o_field_domain { + > .o_field_domain_panel { + margin-top: 8px; + } + &.o_inline_mode.o_edit_mode { + position: relative; + + > .o_field_domain_panel { + .o-position-absolute(0, 0); + margin-top: 0; + } + } + } +} diff --git a/addons/web/static/src/scss/fields_extra.scss b/addons/web/static/src/scss/fields_extra.scss new file mode 100644 index 00000000000..577cfacacb4 --- /dev/null +++ b/addons/web/static/src/scss/fields_extra.scss @@ -0,0 +1,59 @@ +// +// This file regroups all the rules which apply to field widgets wherever they +// are in the DOM, in the community version. +// + +// Required +.o_required_modifier { + &.o_input, .o_input { + background-color: #D2D2FF!important; + } +} + +//------------------------------------------------------------------------------ +// Fields +//------------------------------------------------------------------------------ + +.o_field_widget { + // Dropdowns input carret + .o_input_dropdown .o_dropdown_button { + .o-position-absolute(2px, 4px); + } + + // Many2one + &.o_field_many2one .o_external_button { + padding: 0; + margin-left: 2px; + font-size: 19px; + color: #7C7BAD; + border: none; + &:hover { + background-color: transparent; + } + } + + // Percent pie field + &.o_field_percent_pie { + @pie-dimension: 34px; + @pie-ring-width: 4px; + + .o_pie { + width: @pie-dimension; + height: @pie-dimension; + margin-left: 5px; + + &:after { // Outside pie border to go over border-radius irregularities + border: 1px solid @odoo-brand-primary; + } + + .o_pie_value { + .o-position-absolute(@pie-ring-width, @pie-ring-width); + width: @pie-dimension - 2 * @pie-ring-width; + height: @pie-dimension - 2 * @pie-ring-width; + border: 1px solid white; + background-color: white; + font-size: 10px; + } + } + } +} diff --git a/addons/web/static/src/scss/fonts.scss b/addons/web/static/src/scss/fonts.scss new file mode 100644 index 00000000000..c6b19a2ba2f --- /dev/null +++ b/addons/web/static/src/scss/fonts.scss @@ -0,0 +1,37 @@ +// ------------------------------------------------------------------ +// Lato +// ------------------------------------------------------------------ +@lato-font-path: '../fonts/lato'; + +.lato-font(@type, @weight, @style) { + @font-face { + font-family: 'Lato'; + src: url('@{lato-font-path}/Lato-@{type}-webfont.eot'); + src: url('@{lato-font-path}/Lato-@{type}-webfont.eot?#iefix') format('embedded-opentype'), + url('@{lato-font-path}/Lato-@{type}-webfont.woff') format('woff'), + url('@{lato-font-path}/Lato-@{type}-webfont.ttf') format('truetype'), + url('@{lato-font-path}/Lato-@{type}-webfont.svg#Lato') format('svg'); + font-weight: @weight; + font-style: @style; + } + + @font-face { + font-family: 'Lato-@{type}'; + src: url('@{lato-font-path}/Lato-@{type}-webfont.eot'); + src: url('@{lato-font-path}/Lato-@{type}-webfont.eot?#iefix') format('embedded-opentype'), + url('@{lato-font-path}/Lato-@{type}-webfont.woff') format('woff'), + url('@{lato-font-path}/Lato-@{type}-webfont.ttf') format('truetype'), + url('@{lato-font-path}/Lato-@{type}-webfont.svg#Roboto') format('svg'); + } +} + +.lato-font-pair(@type, @weight) { + .lato-font('@{type}', @weight, normal); + .lato-font('@{type}Ita', @weight, italic); +} + +.lato-font-pair('Hai', 100); +.lato-font-pair('Lig', 300); +.lato-font-pair('Reg', 400); +.lato-font-pair('Bol', 700); +.lato-font-pair('Bla', 900); diff --git a/addons/web/static/src/scss/form_view.scss b/addons/web/static/src/scss/form_view.scss new file mode 100644 index 00000000000..1e477aac02d --- /dev/null +++ b/addons/web/static/src/scss/form_view.scss @@ -0,0 +1,747 @@ +.o_form_view { + background-color: @odoo-view-background-color; + + // Utility classes + .oe_form_box_info { + .bg-info; + .o-webclient-padding(@top: 5px, @bottom: 5px); + > p { + margin: auto; + } + } + .oe_text_center { + text-align: center; + } + .oe_grey { + opacity: 0.5; + } + .oe_inline { + width: auto!important; + @media (min-width: @screen-xs-min) { + &.o_inner_group { + width: 1px!important; + } + } + } + .oe_left { + .oe_inline; + float: left!important; + } + .oe_right { + .oe_inline; + float: right!important; + } + + @media (min-width: @screen-xs-min) { + .o_row { + &, &.o_field_widget { // Some field may want to use o_row as root and these rules must prevalue + .o-flex-display(); + width: auto!important; + } + + .o-align-items(baseline); + min-width: 50px; + margin: 0 -@odoo-form-spacing-unit/2; + + > div, > span, > button, > label, > a, > input { // > * did not add a level of priority to the rule + .o-flex(0, 0, auto); + width: auto!important; + margin-right: @odoo-form-spacing-unit/2; + margin-left: @odoo-form-spacing-unit/2; + } + + > .o_row { + margin: 0; + } + > .btn { + padding-top: 0; + padding-bottom: 0; + } + > .o_field_boolean { + .o-align-self(center); + } + } + } + + .o_row > div > .o_field_widget { + width: 100%; + } + + // Readonly specific rules + &.o_form_readonly { + .oe_edit_only { + display: none!important; + } + + .o_row, .o_row > div { + display: inline-block; + } + + } + + .o_form_uri { + display: inline-block; + + color: @odoo-main-text-color; + &:first-line { + color: @link-color; + } + &:hover { + color: darken(@odoo-main-text-color, 1%); // hack required on chrome + &:first-line { + color: darken(@link-color, 15%); + } + } + } + + // Editable specific rules + &.o_form_editable { + .oe_read_only { + display: none!important; + } + + .oe_title { + max-width: @container-sm - (2 * @odoo-horizontal-padding); + } + + @media (min-width: @screen-xs-min) { + .o_row { + > .o_field_widget, > div { + .o-flex(1, 1, auto); + width: 0!important; // 3rd flex argument does not work with input (must be auto and real width 0) + + &.o_field_boolean, &.o_priority { + .o-flex(0, 0, auto); + width: auto!important; + } + } + } + } + } + + // No sheet + &.o_form_nosheet { + display: block; + .o-webclient-padding(@top: @odoo-sheet-vpadding, @bottom: @odoo-sheet-vpadding); + + .o_form_statusbar { + margin: -@odoo-sheet-vpadding -@odoo-horizontal-padding @odoo-sheet-vpadding -@odoo-horizontal-padding; + } + } + + // Non-chatter rules + .o_form_sheet_bg { + position: relative; + + > .o_form_sheet { + margin: @odoo-sheet-vpadding auto; + } + } + + // Statusbar + .o_form_statusbar { + position: relative; // Needed for the "More" dropdown + .o-flex-display(); + .o-justify-content(space-between); + padding-left: @odoo-horizontal-padding; + border-bottom: 1px solid @gray-lighter-darker; + background-color: @odoo-view-background-color; + + > .o_statusbar_buttons, > .o_statusbar_status { + .o-flex-display(); + .o-align-items(center); + .o-align-content(space-around); + } + + > .o_field_widget { + .o-align-self(center); + margin-bottom: 0px; + } + + > .o_statusbar_buttons { + .o-flex-flow(row, wrap); + + > .btn { + @o-statusbar-buttons-vmargin: 4px; + min-height: @odoo-statusbar-height - 2 * @o-statusbar-buttons-vmargin; + margin: @o-statusbar-buttons-vmargin 3px @o-statusbar-buttons-vmargin 0; + padding-top: 2px; + padding-bottom: 2px; + } + } + + > .o_statusbar_status { + margin-left: auto; + .o-flex-flow(row-reverse, wrap-reverse); + .o-align-self(stretch); + .o-align-items(stretch); + overflow-x: hidden; // to prevent horizontal scroll due to last arrow + + > .o_arrow_button { + min-height: @odoo-statusbar-height; + font-size: 11px; + font-weight: bold; + position: relative; + padding-left: @odoo-statusbar-arrow-width*2; + color: @gray; + border-width: 0 0 0; + border-radius: 0; + .o-transition(all, 0.1s); + + &:first-child { + padding-right: @odoo-horizontal-padding; // Compensate container padding + } + &:last-child { + padding-left: @odoo-horizontal-padding - 1; + border-left: 1px solid @gray-lighter-darker; + } + + &:active { + box-shadow: none; + } + + &.disabled { + opacity: 1.0; + color: @text-muted; + pointer-events: none; + border-left: 1px solid @gray-lighter-dark; + } + + &:before, &:after { + content: " "; + display: block; + .o-position-absolute(0, -@odoo-statusbar-arrow-width + 1); + + border-top: floor(@odoo-statusbar-height/2) solid transparent; + border-bottom: ceil(@odoo-statusbar-height/2) solid transparent; + border-right: none; + border-left: @odoo-statusbar-arrow-width solid @odoo-view-background-color; + .o-transition(border, 0.2s); + -moz-transform: scale(0.9999); // Smooth the triangle on firefox + } + + &:not(.disabled) { + &:hover, &:active, &:focus { + color: @odoo-brand-optional; + background-color: @gray-lighter; + + &:after { + border-left-color: @gray-lighter; + } + } + } + + &:before { + right: -@odoo-statusbar-arrow-width; + border-left-color: @gray-lighter-dark; + } + + &.btn-primary.disabled { + color: @odoo-brand-primary; + font-size: 11px; + background-color: @gray-lighter; + cursor: default; + + &:after { + border-left-color: @gray-lighter; + } + } + + .caret { + margin-top: -2px; + } + } + + .o-status-more { + .o-position-absolute(100%, 0); + min-width: 100px; + > li > button { + width: 100%; + text-align: left; + } + } + } + + // Touch device mode + > .o_statusbar_buttons > .btn-group, > .o_statusbar_status { + > .dropdown-toggle { + &:after { + .o-caret-down(); + margin-left: @odoo-form-spacing-unit; + } + } + + > .dropdown-menu { + padding: 5px 0 2px 0; + min-width: 100px; + + > li > .btn { + min-width: 100%; + margin-bottom: 3px; + } + } + } + } + + // Button box + .oe_button_box { + .oe_stat_button { + &:not(:hover) .o_stat_info > .o_hover { + display: none !important; + } + &:hover .o_stat_info > .o_not_hover { + display: none !important + } + } + } + + // Title + .oe_title { + > h1, > h2, > h3 { + width: 100%; // Needed because inline-block when is a hx.o_row + margin-top: 0; + margin-bottom: 0; + line-height: inherit; + } + .o_priority > .o_priority_star { + font-size: inherit; + } + } + + // Groups + .o_group { + display: inline-block; + width: 100%; + margin: 10px 0; + + // o_group contains nested groups + .o-generate-groups(@odoo-form-group-cols); + .o-generate-groups(@n, @i: 1) when (@i =< @n) { + .o_group_col_@{i} { + display: inline-block; + width: floor(100% / 12 * @i); + vertical-align: top; + } + .o-generate-groups(@n, @i + 1); + } + + &.o_inner_group { + display: inline-table; + + > tbody > tr > td { + &.o_td_label { + width: 0%; + padding: 0 15px 0 0; + min-width: 150px; + } + vertical-align: top; + + span, .o_field_boolean, .oe_avatar, .o_form_uri { + &.o_field_widget { + width: auto; + } + } + } + } + + .o_form_label { + font-weight: normal; + } + + .o_field_widget { + width: 100%; + + > .btn { + .o-flex(0, 0, auto); + padding: 0 10px; + } + } + + :not(.o_row) > .o_field_widget, + .o_row > .o_field_widget:last-child { // Note: this does not take care + // of an invisible last-child but + // it does not really matter + // Makes extra buttons (e.g. m2o external button) overflow on the + // right padding of the parent element + .o_input_dropdown { + .o-flex(1, 0, auto); + } + } + + &.o_label_nowrap .o_form_label { + white-space: nowrap; + } + + .o_td_label .o_form_label { + font-weight: bold; + margin-right: 0px; + } + } + + // Separators + .o_horizontal_separator { + font-size: @font-size-h2; + margin: @odoo-form-spacing-unit 0; + &:empty { + height: @odoo-form-spacing-unit * 2; + } + } + + // Notebooks + .o_notebook { + clear: both; // For the notebook not to have alongside floating elements + margin-top: @odoo-form-spacing-unit * 2; + + .nav-tabs > .tab-pane { + min-height: 100px; + } + } + + // Labels + .o_form_label { + margin: 0 @odoo-form-spacing-unit 0 0; + font-size: @font-size-base; // The label muse have the same size whatever their position + line-height: @line-height-base; + } + + // Form fields + .o_field_widget { + margin-bottom: @odoo-form-spacing-unit; + } + .o_field_widget, .btn { + .o_field_widget { + margin-bottom: 0px; + } + } + + // Translate icon + .o_field_translate { + padding: 0; + cursor: pointer; + width: 12px !important; + vertical-align: top; + &::before { // seems to be useful for some old browser + position: relative; + } + } + + // Text field with oe_inline class + .o_field_text.oe_inline { + width: 100%!important; + @media (min-width: @screen-xs-min) { + width: 45%!important; + } + } + + // One2Many, Many2Many outside of group + .o_field_widget { + &.o_field_one2many, &.o_field_many2many { + width: 100%; + > div { + width: 100%; + } + } + } + + // Specific style classes + .o_group.o_inner_group.oe_subtotal_footer { + .oe_right; + + > tbody > tr > td { + padding: 0; + + &.o_td_label { + text-align: right; + } + + .o_form_label { + padding-right: 20px; + + min-width: 0; + white-space: nowrap; + &:after { + content: ":"; + } + } + + .o_field_widget { + text-align: right; + .o-justify-content(flex-end); + width: 100%; + } + } + + > tbody > tr:first-child > td { + padding-top: 4px; + } + + .oe_subtotal_footer_separator { + width: 100%; + text-align: right; + border-top: 1px solid @gray-lighter-dark; + font-weight: bold; + font-size: 1.3em; + } + } + + .o_address_format { + width: 100%; + .o_address_street, .o_address_country { + .o-flex-display; + } + + .o_address_city { + margin-right: 2%; + } + .o_address_state { + margin-right: 2%; + } + &.o_zip_city { + .o_address_zip { + margin-right: 2%; + } + .o_address_city { + margin-right: 0; + } + .o_address_state { + display: block; + margin-right: 0; + } + } + &.o_city_state { + .o_address_state { + margin-right: 0; + } + .o_address_zip { + display: block; + margin-right: 0; + } + } + > span.o_field_widget { + width: auto; + } + } + &.o_form_editable .o_address_format { + .o_address_city { + width: 38%; + } + div.o_address_state { + width: 33%; + } + input.o_address_zip { + width: 25%; + } + &.o_zip_city { + .o_address_zip { + width: 38%; + } + .o_address_city { + width: 60%; + } + .o_address_state { + width: 100%; + } + } + &.o_city_state { + .o_address_city { + width: 50%; + } + .o_address_state { + width: 48%; + } + .o_address_zip { + width: 100%; + } + } + } + + // Boolean + .o_field_boolean { + margin: 0 @odoo-form-spacing-unit 0 0; + } + + // Timezone widget warning + .o_tz_warning { + color: @brand-danger; + cursor: help; + position: absolute; + margin-left: -40px; + margin-top: 5px; + } + + // One2Many Kanban views + .o_field_widget .o_kanban_view.o_kanban_ungrouped { + padding: 0; + .o_kanban_record { + box-shadow: none; + } + } + + // One2Many List views + .o_field_widget .o_list_view { + margin-bottom: 10px; + + > tfoot > tr > td { + padding: 3px; + color: @odoo-main-text-color; + } + } + &.o_form_readonly .o_field_widget .o_list_view .o_row_handle { + display: none; // Hide the handler in non-edit mode + } + + // Attachments + .oe_attachment { + display: inline-block; + border: 1px solid @odoo-brand-lightsecondary; + margin: 0 @odoo-form-spacing-unit @odoo-form-spacing-unit 0; + padding: @odoo-form-spacing-unit; + } + + &.oe_form_configuration { + .o_group .o_form_label { + white-space: nowrap; + } + h2 { + margin-top: 32px !important; + } + } +} + +// Overriden style when form view in modal +.modal .modal-dialog { + .o_form_view { + .o_form_sheet_bg { + padding: 0; + + > * { + margin: 0; + } + + > .o_form_sheet { + box-shadow: none; + width: 100%; + margin: 0 auto; + max-width: none; + } + } + .oe_chatter { + display: none; + } + } + &:not(.modal-lg) .o_form_view { + .o_group { + width: 100%; + } + } +} + +@media print { + .oe_button_box, .o_form_statusbar { + display: none !important; + } +} + +// Buttons in ControlPanel +.o_control_panel .o_form_buttons_view > button:first-child { + float: left; // Unfortunately needed for the bounce effect + margin-right: 4px; +} + +// Light labels (not in bold) for settings forms +label.o_light_label, .o_light_label label { + font-weight: normal; +} + +// XXS form view specific rules +.form-break-table() { + display: block; + margin-bottom: @odoo-form-spacing-unit * 4; + + > tbody { + display: block; + + > tr { + .o-flex-display(); + .o-flex-flow(row, wrap); + + > td { + .o-flex(1, 0, auto); + display: block; + max-width: 100%; + padding: 0; + + width: auto!important; // !important is required to override the width computed in JS + &.o_td_label { + width: 94%!important; // The label must be on its own line except if the form field is small enough (checkbox) + line-height: @odoo-label-font-size-factor; + } + + .o_field_widget { + margin-bottom: @odoo-form-spacing-unit * 2; + &.o_field_boolean { + margin-right: 0; + } + } + + .o_input_dropdown { + width: auto; + max-width: 100%; + } + } + } + } +} +.o_form_view.o_xxs_form_view { + .oe_title { + word-break: break-all; + } + .o_group { + &.o_inner_group { + .form-break-table(); + } + } +} + +// Settings form views +.o_settings_container { + .o-flex-display(); + .o-flex(0, 1, auto); + .o-flex-flow(row, wrap); + .o_setting_box:visible:nth-child(odd) { + clear: left; + } + .text-muted { + color: #aaaaaa; + } + .o_setting_box { + margin-bottom: 8px; + margin-top: 8px; + .o_setting_left_pane { + width: 24px; + float: left; + .o_enterprise_label { + position: absolute; + top: 0px; + right: 40px; + } + } + .o_setting_right_pane { + margin-left: 30px; + border-left: 1px solid #bbbbbb; + padding-left: 10px; + .o_input_dropdown > .o_input { + width: 100%; + } + .o_field_widget { + width: 50%; + } + button.btn-link { + padding: 0; + } + a.oe-link { + font-size: 12px; + } + } + } +} diff --git a/addons/web/static/src/scss/form_view_extra.scss b/addons/web/static/src/scss/form_view_extra.scss new file mode 100644 index 00000000000..95da6a2b35b --- /dev/null +++ b/addons/web/static/src/scss/form_view_extra.scss @@ -0,0 +1,190 @@ +@sheet-max-width: 860px; +@sheet-min-width: 650px; +@sheet-padding: 16px; + +.o_form_view { + &.o_form_nosheet.oe_form_nomargin { + margin: 0; + } + .o_form_sheet_bg { + border-bottom: 1px solid #ddd; + background: url(/web/static/src/img/form_sheetbg.png); + + > .o_form_sheet { + min-width: @sheet-min-width; + max-width: @sheet-max-width; + min-height: 330px; + padding: 16px; + border: 1px solid #c8c8d3; + box-shadow: 0 4px 20px rgba(0,0,0,0.15); + background: white; + + .ui-tabs { + margin: 0 -16px; + } + .oe_notebook_page { + padding: 0 16px; + } + } + } + + // Button box + .oe_button_box { + width: 400px; + text-align: right; + float: right; + + &, & + .oe_avatar { + + .oe_title { + width: 400px; + } + } + + .oe_stat_button { + text-align: left; + width: 132px !important; + height: 40px; + margin: 0px -1px -1px 0px; + padding: 0; + border-radius: 0; + border-color: #ccc; + background: white; + outline: none; + + &:hover { + background-color: #e6e6e6; + } + + .o_button_icon { + display: inline-block; + width: 37px; + padding: 0px 3px; + text-align: center; + vertical-align: middle; + color: #7C7BAD; + font-size: 24px; + } + + // Some buttons only display text without using StatInfo template + .o_stat_info, > span { // contains the value and text + display: inline-block; + vertical-align: middle; + max-width: 70%; + line-height: 1.2; + + .o_stat_value { + .o-text-overflow(block); + font-weight: 700; + color: @odoo-brand-primary; + } + .o_stat_text { + .o-text-overflow(block); + font-size: small; + + .o_stat_value { + display: inline; + } + } + } + > span { + font-size: small; + white-space: normal; // text on several lines if needed + } + + > div { + text-align: left; + padding: 0; + line-height: 120%; + vertical-align: middle; + } + } + + &.o_full { + position: relative; + .o_button_more { + padding: 0 10px; + } + .o_dropdown_more { + .o-position-absolute(@top: 100%, @right: 0); + min-width: 0; + padding: 0px; + } + } + } + + // Avatar + .oe_avatar { + float: left; + > img { + max-height: 90px; + max-width: 90px; + margin-bottom: 10px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); + border: none; + } + + .oe_title { + padding-left: 95px; + margin-left: 5px; + } + } + + // Groups + .o_group { + .o_td_label { + border-right: 1px solid #ddd; + } + .o_td_label + td { + padding: 2px 36px 2px 8px; + } + .o_field_widget.o_text_overflow { + width: 1px!important; // hack to make the table layout believe it is a small element (so that the table does not grow too much) ... + min-width: 100%; // ... but in fact it takes the whole table space + } + } + + // Separators + .o_horizontal_separator { + color: @odoo-brand-optional; + font-weight: bold; + } + + // Translate icon + .o_field_translate { + margin-left: -15px; + } + + // Specific style classes + .o_group.o_inner_group.oe_subtotal_footer { + .oe_subtotal_footer_separator { + border-top: 1px solid #cacaca; + } + .o_td_label { + border-right: none; + } + } + + // Chatter + .oe_chatter { + display: block; + min-width: @sheet-min-width + 2* @sheet-padding; + max-width: @sheet-max-width + 2* @sheet-padding; + margin: 0 auto; + padding: 16px 16px 48px; + } +} + +// Overriden style when form view in modal +.modal .modal-dialog { + .o_form_view { + .o_form_sheet_bg, .o_form_sheet { + border: none; + } + } +} + +// XXS form view specific rules +.o_form_view.o_xxs_form_view { + .o_group .o_td_label { + border: none; + } +} diff --git a/addons/web/static/src/scss/graph_view.scss b/addons/web/static/src/scss/graph_view.scss new file mode 100644 index 00000000000..fc8fc323582 --- /dev/null +++ b/addons/web/static/src/scss/graph_view.scss @@ -0,0 +1,20 @@ +.o_graph { + .o_graph_svg_container { + height: 100%; + overflow: auto; + svg { + background-color: @odoo-view-background-color; + } + } +} + +.nvtooltip thead { + background-color: transparent; +} + +// ------------------------------------------------------------------ +// Control panel buttons +// ------------------------------------------------------------------ +.o_graph_measures_list { + .o-selected-li; +} diff --git a/addons/web/static/src/scss/import_bootstrap.scss b/addons/web/static/src/scss/import_bootstrap.scss new file mode 100644 index 00000000000..cbd46a7afcf --- /dev/null +++ b/addons/web/static/src/scss/import_bootstrap.scss @@ -0,0 +1 @@ +@import "bootstrap"; diff --git a/addons/web/static/src/scss/kanban_column_progressbar.scss b/addons/web/static/src/scss/kanban_column_progressbar.scss new file mode 100644 index 00000000000..f4cffd6c097 --- /dev/null +++ b/addons/web/static/src/scss/kanban_column_progressbar.scss @@ -0,0 +1,152 @@ +@o-kanban-counter-header-height: @o-kanban-header-title-height*0.6; + +.o-kanban-css-filter(@class, @accent-color) { + // Provide CSS reordering and highlight + &.o_kanban_group_show_@{class} { + @mix-soft: mix(@accent-color, @odoo-webclient-background-color, 5%); + @mix-full: mix(@accent-color, @odoo-webclient-background-color); + + &, .o_kanban_header { + background-color: @mix-soft; + border-color: @mix-full; + } + + .progress-bar.bg-@{class}-full { + border: 1px solid white; + } + + .oe_kanban_card_@{class} { + order: 1; + margin-bottom: @o-kanban-inside-vgutter*0.5; + + ~ .oe_kanban_card_@{class} { + margin-top: -@o-kanban-inside-vgutter*0.5 - 1px; + } + + ~ .o_kanban_load_more { + margin-top: -@o-kanban-inside-vgutter*0.5; + } + } + + .o_kanban_load_more { + order: 2; + padding: @o-kanban-inside-vgutter*0.5 0 @o-kanban-inside-vgutter; + } + + .o_kanban_record:not(.oe_kanban_card_@{class}) { + order: 3; + .o-hover-opacity(0.5); + box-shadow: none; + } + } +} + +// If columns has the progressbar, adapt the layout +.o_kanban_view .o_kanban_group.o_kanban_has_progressbar { + > .o_kanban_header .o_kanban_header_title { + height: @o-kanban-counter-header-height; + margin-top: 5px; + } + + &.o_kanban_no_records { + .o_kanban_counter { + opacity: 0.3; + } + } +} + +.o_kanban_counter { + position: relative; + .o-flex-display(); + .o-align-items(center); + .o-transition(opacity, 0.3s); + margin-bottom: @o-kanban-record-margin*2; + + > .o_kanban_counter_progress { + width: 76%; + height: @font-size-small; + margin-bottom: 0; + background-color: @gray-lighter-dark; + box-shadow: none; + + .progress-bar { + margin-bottom: 0; + box-shadow: none; + cursor: pointer; + + // Be sure that a bar with data has a minimun width + &.o_bar_has_records { + min-width: 10px; + } + } + + .o_kanban_counter_label { + font-size: 10px; + .user-select(none); + } + } + + > .o_kanban_counter_side { + width: 21%; + margin-left: 3%; + color: @headings-color; + text-align: right; + white-space: nowrap; + .o-transform-origin(right, center); + + &.o_kanban_grow { + .o-animation(grow, 1s, ease); + } + + &.o_kanban_grow_huge { + .o-animation(grow_huge, 1s, ease); + } + + // Target currency icon + > span { + margin-left: 2px; + } + } +} +.o_column_folded .o_kanban_counter { + display: none; +} + +.o_kanban_view .o_kanban_group { + .o-kanban-css-filter(success, @brand-success); + .o-kanban-css-filter(warning, @brand-warning); + .o-kanban-css-filter(danger, @brand-danger); + + &.o_kanban_group_show { + .o-flex-display(); + .o-flex-flow(column, nowrap); + + > * { + .o-flex(0, 0, auto); + } + } +} + +@keyframes grow { + 0% { + transform: scale3d(1, 1, 1); + } + 30% { + transform: scale3d(1.1, 1.1, 1.1); + } + 100% { + transform: scale3d(1, 1, 1); + } +} + +@keyframes grow_huge { + 0% { + transform: scale3d(1, 1, 1); + } + 30% { + transform: scale3d(1.3, 1.3, 1.3); + } + 100% { + transform: scale3d(1, 1, 1); + } +} diff --git a/addons/web/static/src/scss/kanban_dashboard.scss b/addons/web/static/src/scss/kanban_dashboard.scss new file mode 100644 index 00000000000..83db9319166 --- /dev/null +++ b/addons/web/static/src/scss/kanban_dashboard.scss @@ -0,0 +1,243 @@ +// ------- Kanban dashboard variables ------- + +// Since rows and containers are used inside cards, we're +// forced to set the padding relative to the grid system. +@o-kanban-dashboard-hpadding: @grid-gutter-width*0.5; +@o-kanban-dashboard-vpadding: @grid-gutter-width*0.25; + +// Used to manage spacing in complex dropdown menu +@o-kanban-dashboard-dropdown-complex-gap: 5px; + +// Emulate dropdown links +.o-kanban-dashboard-dropdown-link(@link-padding-gap: @odoo-dropdown-hpadding) { + padding: 0; + + > a { + margin: auto auto auto -@link-padding-gap; + padding: 3px @link-padding-gap; + color: @text-color; + display: block; + + &:hover { + background-color: @gray-lighter-dark; + color: @headings-color; + } + } + &:last-child { + margin-bottom: 5px; + } +} + +.o_kanban_view.o_kanban_dashboard { + // correctly display the no_content_helper in dashboards + .o-flex-flow(row, wrap); + + .o_kanban_record { + position: relative; + .o-flex-display(); + .o-flex-flow(column, nowrap); + .o-justify-content(space-between); + padding: @o-kanban-dashboard-vpadding @o-kanban-dashboard-hpadding; + + @media (max-width: @screen-xs-max) { + margin-bottom: 10px; + } + + &:focus, &:focus-within { + -webkit-box-shadow: 1px 1px 3px 0px rgba(0,0,0,1); + -moz-box-shadow: 1px 1px 3px 0px rgba(0,0,0,1); + box-shadow: 1px 1px 3px 0px rgba(0,0,0,1); + z-index: 1; // show the shadow on top of the previous & next cards in grouped mode + outline: none; + } + + // ------- Generic layout adaptations ------- + .container { + width: 100%; + } + + // ------- Dropdown toggle & menu ------- + @o-kanban-manage-toggle-height: 35px; + + .o_kanban_manage_toggle_button { + .o-kanban-dropdown(@o-kanban-dashboard-hpadding); + height: @o-kanban-manage-toggle-height; + } + + .o_kanban_card_manage_pane { + .dropdown-menu; + .o-kanban-dropdown-menu(); + + // Arbitrary value to place the dropdown-menu exactly below the + // dropdown-toggle (height is forced so that it works on Firefox) + top: @o-kanban-manage-toggle-height - 1; + + > div:not(.o_no_padding_kanban_colorpicker) { + padding: 3px 0 3px 20px; + visibility: visible; + margin-bottom: 5px; + } + + > .o_kanban_card_manage_section { + border-bottom: 1px solid @gray-lighter-dark; + margin-bottom: 10px; + + > div { + .o-kanban-dashboard-dropdown-link(); + } + } + + // Dropdown menu with complex layout + &.container { + width: 95%; + max-width: 400px; + + .row { + .o-flex-display(); + .o-flex-flow(row, nowrap); + .o-justify-content(space-between); + margin-left: 0; + margin-right: 0; + padding-left: @o-kanban-dashboard-dropdown-complex-gap*2; + padding-right: @o-kanban-dashboard-dropdown-complex-gap*2; + } + + div[class*="col-"] { + .o-flex(1, 1, percentage(100/3)); + padding-left: @o-kanban-dashboard-dropdown-complex-gap; + padding-right: @o-kanban-dashboard-dropdown-complex-gap; + + > .o_kanban_card_manage_title { + .h5; + font-weight: 500; + } + > div:not(.o_kanban_card_manage_title) { + .o-kanban-dashboard-dropdown-link(@link-padding-gap: @o-kanban-dashboard-dropdown-complex-gap); + } + } + + .row.o_kanban_card_manage_settings { + border-top: 1px solid @gray-lighter-dark; + padding-top: @o-kanban-dashboard-dropdown-complex-gap*3; + + .oe_kanban_colorpicker { + max-width: none; + padding: 0; + } + + div[class*="col-"] + div[class*="col-"] { + border-left: 1px solid @gray-lighter-dark; + } + + // Default options box + div.text-right { + text-align: left; // :/ + .o-kanban-dashboard-dropdown-link(0); + > a { + margin-left: 40px; + padding-left: 20px; + } + } + } + } + + } + + &.o_dropdown_open { + .o_kanban_card_manage_pane { + display: block; + } + .o_kanban_manage_toggle_button { + .o-kanban-dropdown-open(); + position: absolute; + } + } + + // ------- Kanban Record Titles ------- + // Uniform design across different HTML layouts + + // Provide enough room for the dropdown-toggle + .o_primary { + padding-right: @o-kanban-dashboard-hpadding*2; + } + + // Uniform titles + .o_kanban_card_header_title .o_primary, + .o_kanban_primary_left .o_primary > span:first-child, + .oe_kanban_content > .o_title > h3 { + .o-kanban-record-title(@font-size: 16px); + display: block; + } + + // Identify subtitles without classes + .o_kanban_primary_left .o_primary > span:nth-child(2) > strong { + font-weight: 500; + font-size: @font-size-small; + color: @text-muted; + } + + // Provide enough room to add an icon before the title + &.o_has_icon .o_primary { + padding-left: @o-kanban-record-margin*1.5; + } + + // ------- Kanban Content ------- + .o_kanban_card_content { + display: inline-block; + vertical-align: top; + min-height: 80px; + } + + .o_kanban_card_header + .container.o_kanban_card_content { + .o-flex(1, 0, auto); + .o-flex-display(); + .o-flex-flow(column, nowrap); + .o-justify-content(space-between); + margin-top: @o-kanban-dashboard-vpadding * 2; + padding-right: 0; + padding-left: 0; + + &::before, &::after { + content: normal; // so that space-between works + } + + a { + position: relative; + .o-text-overflow(inline-block); + } + + .o_kanban_primary_bottom { + margin-top: @o-kanban-dashboard-vpadding; + margin-bottom: -@o-kanban-dashboard-vpadding; + + &.bottom_block { + border-top: 1px solid @gray-lighter-dark; + background-color: @gray-lighter; + padding-top: @o-kanban-dashboard-vpadding; + padding-bottom: @o-kanban-dashboard-vpadding; + } + } + } + + .o_dashboard_graph { + overflow: hidden; + margin: (@o-kanban-dashboard-vpadding * 2) -@o-kanban-dashboard-hpadding; + } + } + + .o_favorite, .o_kanban_manage_toggle_button { + .o-position-absolute(0, 0); + padding: @o-kanban-record-margin; + } + + .o_favorite { + top: 3px; + left: 0; + right: auto; + } + + // Emphasize records' colors when necessary + &.o_emphasize_colors .o_kanban_record::after { + width: @o-kanban-color-border-width * 2; + } +} diff --git a/addons/web/static/src/scss/kanban_examples_dialog.scss b/addons/web/static/src/scss/kanban_examples_dialog.scss new file mode 100644 index 00000000000..35a3d914b8e --- /dev/null +++ b/addons/web/static/src/scss/kanban_examples_dialog.scss @@ -0,0 +1,71 @@ +.o_kanban_examples_dialog { + .o-flex-display(); + padding: 0px; + background: @odoo-color-silver; + + // sidebar + .o_kanban_examples_dialog_nav { + .o-flex(0, 0, auto); + border-right: 1px solid @gray-lighter-dark; + background: white; + + > ul > li { + margin: 0; + border-bottom: 1px solid @gray-lighter-dark; + + > a { + padding: 12px 15px; + color: @odoo-main-text-color; + border-left: 3px solid transparent; + &:focus { + outline: none; + } + } + &.active > a { + color: @headings-color; + border-left-color: @odoo-brand-optional; + font-weight: bold; + } + } + } + + // content + .o_kanban_examples_dialog_content { + .o-flex(1, 1, 100%); + + .o_kanban_examples_description { + padding: 16px 16px 0; + text-align: justify; + } + .o_kanban_examples { + .o-flex-display(); + padding: 0 6px; + + .o_kanban_examples_group { + .o-flex(1, 1, 100%); + margin: 10px; + + .o_kanban_examples_ghost { + padding: 5px; + margin-top: -1px; + border: thin solid @gray-lighter-dark; + background-color: white; + .o_ghost_content { + height: 12px; + background: @gray-lighter-dark; + &.o_ghost_tag { + display: inline-block; + width: 40%; + margin-top: 10px; + } + } + .o_ghost_avatar { + height: 20px; + width: 20px; + margin-top: 6px; + } + } + } + } + } +} diff --git a/addons/web/static/src/scss/kanban_view.scss b/addons/web/static/src/scss/kanban_view.scss new file mode 100644 index 00000000000..f9130469665 --- /dev/null +++ b/addons/web/static/src/scss/kanban_view.scss @@ -0,0 +1,648 @@ +@o-kanban-record-margin: @odoo-horizontal-padding/2; +@o-kanban-group-padding: @odoo-horizontal-padding; // Cannot be higher than this + +@o-kanban-default-record-width: 300px; +@o-kanban-small-record-width: 240px; + +@o-kanban-header-title-height: 50px; + +@o-kanban-image-width: 64px; +@o-kanban-inside-vgutter: 8px; +@o-kanban-inside-hgutter: 8px; +@o-kanban-color-border-width: 3px; +@o-kanban-inside-hgutter-mobile: @odoo-horizontal-padding; +@o-kanban-inner-hmargin: 5px; +@o-kanban-progressbar-height: 20px; + +// ------- Kanban grouped mixins ------- +.o-kanban-icon(@base-opacity: 0.5) { + display: block; + text-align: center; + color: @odoo-main-text-color; + font-size: @font-size-small; + cursor: pointer; + .o-hover-opacity(@base-opacity); +} +.o-kanban-tag-color(@size: 0) when (@size < @odoo-nb-ui-color) { + // Note: the 0 color is supposed to be invisible if there is a color field + // but it is used as a default color when there is no color field + &.o_tag_color_@{size} span { + background-color: ~"@{odoo-color-@{size}}"; + } + .o-kanban-tag-color(@size + 1); +} +.o-kanban-record-color(@size: 1) when (@size < @odoo-nb-ui-color) { + // Note: the 0 color is not defined as it is the 'no color' for kanban + .oe_kanban_color_@{size}::after { + background-color: ~"@{odoo-color-@{size}}"; + } + .o-kanban-record-color(@size + 1); +} +.o-kanban-slim-col() { + position: relative; + .o-flex(0, 0, auto); + margin: 0; + padding: 0 floor(@o-kanban-group-padding * 0.7); + cursor: pointer; +} +.o-kanban-header-title() { + .o-flex-display(); + .o-align-items(center); + height: @o-kanban-header-title-height; + line-height: 2.2; + color: @headings-color; +} +.o-kanban-v-title() { + .o-position-absolute(@o-kanban-inside-vgutter * 2, @left: floor(-@o-kanban-inside-vgutter * 1.2)); + .o-transform-origin(left, bottom, @z: 0); + .o-transform(rotate(90deg)); + overflow: visible; + white-space: nowrap; + font-size: 15px; +} + +// ------- Kanban records mixins ------- +.o-kanban-record-title(@font-size) { + color: @headings-color; + font-size: @font-size; + font-weight: 500; + margin-bottom: 0; + margin-top: 0; +} +.o-kanban-dropdown(@padding-base: @o-kanban-inside-vgutter) { + margin: -1px -1px auto auto; // compensate border + padding: @padding-base/2 @padding-base; + border: 1px solid transparent; + border-bottom: none; + vertical-align: top; + color: @text-color; + + &:hover { + color: @headings-color; + } + &:focus, &:active, &:focus:active { + outline: none; + } +} +.o-kanban-dropdown-open() { + position: relative; + background: white; + border-color: @gray-lighter-darker; + z-index: @zindex-dropdown + 1; +} +.o-kanban-dropdown-menu() { + .o-position-absolute(@right: -1px); + margin-top: -1px; + border-color: @gray-lighter-darker; +} +.o-kanban-colorpicker() { + max-width: 150px; + padding: 3px (@odoo-dropdown-hpadding - @o-kanban-inner-hmargin) 3px @odoo-dropdown-hpadding; + + > li { + display: inline-block; + margin: @o-kanban-inner-hmargin @o-kanban-inner-hmargin 0 0; + border: 1px solid white; + box-shadow: 0 0 0 1px @gray-lighter-dark; + + > a { + display: block; + + &::after { + content: ""; + display: block; + width: 20px; + height: 15px; + } + } + + // No Color + &:first-child > a { + position: relative; + &::before { + content: ""; + .o-position-absolute(-2px, @left: 10px); + display: block; + width: 1px; + height: 20px; + .rotate(45deg); + background-color: red; + } + &::after { + background-color: white; + } + } + } +} + +// ------- Kanban View Layout ------- +.o_kanban_view { + .o-flex-display(); + .o-align-content(stretch); + overflow-x: visible; + + @media (max-width: @screen-xs-max) { + padding: 0px!important; + overflow-x: auto; + } + + .o_kanban_record, .o_kanban_quick_create { + padding: @o-kanban-inside-vgutter @o-kanban-inside-hgutter; + border: 1px solid @gray-lighter-dark; + background-color: white; + + @media (max-width: @screen-xs-max) { + padding: @o-kanban-inside-vgutter @o-kanban-inside-hgutter-mobile; + } + &:focus, &:focus-within { + -webkit-box-shadow: 3px 3px 10px 0px rgba(0,0,0,1); + -moz-box-shadow: 3px 3px 10px 0px rgba(0,0,0,1); + box-shadow: 3px 3px 10px 0px rgba(0,0,0,1); + z-index: 1; // show the shadow on top of the previous & next cards in grouped mode + outline: none; + } + } + + .o_kanban_quick_create { + box-shadow: 0 0 20px -10px; + margin: 0 @o-kanban-record-margin -1px @o-kanban-record-margin; + margin-bottom: 8px; + + .o_form_view { + padding: 0; + .o_group.o_inner_group { + margin: 0; + } + } + } + + .o_kanban_record { + position: relative; + display: inline-block; // Force the creation of a block formatting context to clear float items + border-color: @gray-lighter-darker; + min-width: 150px; + margin: 0 0 -1px; + + // ------- Kanban Record, v11 Layout ------- + // Records colours + &::after { + content: ""; + .o-position-absolute(0, auto, 0, -1px); + width: @o-kanban-color-border-width; + } + + // Inner Sections + .o_kanban_record_top, .o_kanban_record_body { + margin-bottom: @o-kanban-inner-hmargin; + } + + .o_kanban_record_top, .o_kanban_record_bottom { + .o-flex-display(); + } + + .o_kanban_record_top { + .o-align-items(flex-start); + + .o_dropdown_kanban { + // For v11 layout, reset positioning to default to properly use + // flex-box + position: relative; + top: auto; + right: auto; + } + + .o_kanban_record_headings { + line-height: 1.2; + .o-flex(1, 1, auto); + // Ensure long word doesn't break out of container + word-wrap: break-word; + overflow: hidden; + } + } + + .o_kanban_record_title { + .o-kanban-record-title (@font-size: 13px); + } + + .o_kanban_record_subtitle { + display: block; + margin-top: @o-kanban-inner-hmargin*0.5; + } + + .o_kanban_record_bottom { + .oe_kanban_bottom_left, .oe_kanban_bottom_right { + .o-flex-display(); + .o-align-items(center); + height: 20px; + } + .oe_kanban_bottom_left { + .o-flex(1, 1, auto); + + > * { + margin-right: 6px; + line-height: 1; + } + + .o_priority_star { + margin-top: 1px; + font-size: 18px; + } + } + .oe_kanban_bottom_right{ + .o-flex(0, 1, auto); + + .oe_kanban_avatar { + width: 20px; + height: 20px; + margin-left: 6px; + } + } + .o_link_muted { + color: @text-color; + &:hover { + color: @brand-primary; + text-decoration: underline; + } + } + } + } + + // ------- Compatibility of old (<= v10) Generic layouts ------- + + // Kanban Records - Uniform Design + // Provide a basic style for different kanban record layouts + // --------------------------------------------------------- + .oe_kanban_card, .o_kanban_record { + // ------- v11 Layout + generic layouts (~v10) ------- + // Kanban Record - Dropdown + .o_dropdown_kanban { + .o-position-absolute(@o-kanban-inside-vgutter, @o-kanban-inside-hgutter); + visibility: hidden; + @media (max-width: @screen-xs-max) { + visibility: visible; + } + + .dropdown-toggle { + .o-kanban-dropdown(); + margin: (-@o-kanban-inside-vgutter - 1px) (-@o-kanban-inside-hgutter - 1px) 0 0; + } + &.open .dropdown-toggle { + .o-kanban-dropdown-open(); + } + .dropdown-menu { + .o-kanban-dropdown-menu(); + right: (-@o-kanban-inside-hgutter - 1); + } + } + + &:hover .o_dropdown_kanban, .o_dropdown_kanban.open { + visibility: visible; + } + + // Kanban Record - Dropdown colorpicker + .oe_kanban_colorpicker { + .o-kanban-colorpicker(); + } + + // Kanban Record - Inner elements + .o_field_many2manytags, .o_kanban_tags { + display: block; + margin-bottom: @o-kanban-inner-hmargin; + line-height: 1.2; + + .o_tag { + display: inline-block; + margin-right: 4px; + font-size: 11px; + font-weight: 500; + background-color: transparent; + .o-kanban-tag-color(); + + span { + display: inline-block; + width: 6px; + height: 6px; + margin-right: 4px; + border-radius: 100%; + } + } + } + + // Commonly used to place an image beside the text + // (e.g. Fleet, Employees, ...) + .o_kanban_image { + text-align: center; + + img { + max-width: 100%; + } + } + + .o_kanban_button { + margin-top: 15px; + + > button, > a { + .o-position-absolute(@right: @o-kanban-record-margin, @bottom: @o-kanban-record-margin); + @media (max-width: @screen-xs-max) { + right: @o-kanban-inside-hgutter-mobile; + } + } + } + + // Kanban Record - Utility classes + &.oe_kanban_global_click, &.oe_kanban_global_click_edit { + cursor: pointer; + } + + &.ui-sortable-helper { + .o-transform(rotate(-3deg)); + box-shadow: 0 5px 25px -10px black; + .transition(~"transform 0.6s, box-shadow 0.3s"); + } + + .o_attachment_image > img { + width: 100%; + height: auto; + margin-bottom: @o-kanban-inner-hmargin; + } + + .o_progressbar { + .o-flex-display(); + height: @o-kanban-progressbar-height; + + .o_progressbar_title { + .o-flex(0, 0, auto); + } + .o_progress { + .o-flex(1, 1, auto); + margin-top: 3px; + } + .o_progressbar_value { + .o-flex(0, 0, auto); + width: auto; + height: 100%; + text-align: right; + } + input.o_progressbar_value { + width: 15%; + margin-left: 8px; + } + } + + .o_kanban_image { + float: left; + width: @o-kanban-image-width; + + + div { + padding-left: @o-kanban-image-width + @o-kanban-inside-hgutter; + @media (max-width: @screen-xs-max) { + padding-left: @o-kanban-image-width + @o-kanban-inside-hgutter-mobile; + } + } + } + + .oe_kanban_details { + width: 100%; + ul { + margin-bottom: @o-kanban-inner-hmargin*0.5;; + padding-left: 0; + list-style: none; + font-size: @font-size-small; + + li { + margin-bottom: 2px; + } + } + } + + .o_kanban_footer { + .o-flex-display(); + .o-justify-content(space-between); + .o-align-items(center); + > * { + .o-flex(0, 0, auto); + } + } + + .oe_kanban_text_red { + color: #A61300; + font-weight: bold; + } + + .o_text_bold { + font-weight: bold; + } + + .o_text_block { + display: block; + } + } + + // Kanban Grouped Layout + &.o_kanban_grouped { + min-height: 100%; + padding: 0; + background-color: @gray-lighter; + + .o_kanban_record, .o_kanban_quick_create { + width: 100%; + margin-left: 0; + margin-right: 0; + } + + &.o_kanban_small_column .o_kanban_group:not(.o_column_folded) { + width: @o-kanban-small-record-width + 2*@o-kanban-group-padding; + } + } + + // Kanban Grouped Layout - Column default + .o_kanban_group { + .o-flex(0, 0, auto); + padding: 0 @o-kanban-group-padding @o-kanban-group-padding @o-kanban-group-padding; + + .o_kanban_header > .o_kanban_header_title { + .o-kanban-header-title(); + + .o_column_title { + .o-flex(1, 1, auto); + .o-text-overflow(); + font-size: 16px; + font-weight: 500; + } + + .o_column_unfold { + display: none; + } + + .o_kanban_quick_add i { + .o-kanban-icon; + margin-left: @o-kanban-inside-hgutter*2; + } + + &:hover .o_kanban_config, .o_kanban_config.open { + visibility: visible; + margin-left: @o-kanban-inside-hgutter; + } + + .o_kanban_config { + visibility: hidden; + + i { + .o-kanban-icon; + } + } + } + + .o_kanban_load_more { + padding: @o-kanban-record-margin 0; + box-shadow: inset 0 10px 13px -13px black; + text-align: center; + } + + &.ui-sortable-helper { + box-shadow: 0 0 30px -10px black; + } + + &:not(.o_column_folded) { + width: @o-kanban-default-record-width + 2*@o-kanban-group-padding; + } + + &.o_kanban_dragged { + background-color: @odoo-main-text-color; + + .o_kanban_record { + visibility: hidden; + } + } + } + + &.ui-sortable .o_kanban_header_title { + cursor: move; + } + + // Kanban Grouped Layout - Column Folded + .o_kanban_group.o_column_folded { + .o-kanban-slim-col(); + background-color: @gray-lighter-dark; + + & + .o_kanban_group.o_column_folded { + margin-left: 1px; + } + + .o_kanban_header_title { + position: relative; + opacity: 0.5; + + .o_column_title { + .o-kanban-v-title(); + } + .o_column_unfold { + .o-kanban-icon(1); + } + } + + > .o_kanban_record, .o_kanban_quick_add, .o_kanban_config, .o_kanban_load_more { + display: none!important; + } + + &:hover, &.o_kanban_hover { + .o_kanban_header_title { + opacity: 1; + } + } + } + + // Kanban Grouped Layout - "Create new column" column + .o_column_quick_create { + .o_quick_create_folded { + cursor: pointer; + padding: 12px 16px; + white-space: nowrap; + color: @text-muted; + opacity: 0.6; + &:hover { + opacity: 1; + } + + .o_kanban_add_column { + display: inline-block; + padding: 10px 14px; + background-color: @odoo-color-silver-dark; + } + .o_kanban_title { + margin-left: 10px; + } + } + + .o_quick_create_unfolded { + padding: @o-kanban-inside-vgutter @o-kanban-inside-hgutter; + width: @o-kanban-small-record-width; + height: 100%; + border: none; + box-shadow: 0 0 20px -10px; + background-color: @gray-lighter; + + .o_kanban_header { + height: 50px; + + .o_kanban_examples { + cursor: pointer; + } + + input, input:focus, input:hover { + margin-top: 3px; + font-size: 16px; + background: transparent; + } + + .o_kanban_add { + margin-left: 10px; + } + } + + .o_kanban_muted_record { + background: @gray-lighter-dark; + height: 70px; + margin: 10px 0px; + } + + } + } + + // Kanban UN-grouped Layout + &.o_kanban_ungrouped { + .o-flex-flow(row, wrap); + .o-justify-content(flex-start); + + padding: @o-kanban-record-margin (@odoo-horizontal-padding - @o-kanban-record-margin); + + .o_kanban_record { + .o-flex(1, 1, auto); + width: @o-kanban-default-record-width; + margin: (@o-kanban-record-margin * 0.5) @o-kanban-record-margin; + + @media (max-width: @screen-xs-max) { + margin: 0 0 -1px 0; + .o-flex(1, 0, 100%); + } + + &.o_kanban_ghost { + height: 0; + min-height: 0!important; // to prevent view writers to override this height + visibility: hidden; + margin-top: 0; + margin-bottom: 0; + padding: 0; + } + } + } + + &.o_kanban_mobile .o_kanban_record { + div.label { + .o-text-overflow(); + } + } + + // Records colours + .o-kanban-record-color(); +} diff --git a/addons/web/static/src/scss/kanban_view_mobile.scss b/addons/web/static/src/scss/kanban_view_mobile.scss new file mode 100644 index 00000000000..d09b6968925 --- /dev/null +++ b/addons/web/static/src/scss/kanban_view_mobile.scss @@ -0,0 +1,52 @@ +@o-kanban-mobile-tabs-height: 40px; + +@media (max-width: @screen-xs-max) { + .o_kanban_view.o_kanban_grouped { + display: block; + position: relative; + overflow: hidden; + + .o_kanban_mobile_tabs { + height: @o-kanban-mobile-tabs-height; + position: relative; + background-color: #5E5E5E; + + .o_kanban_mobile_tab { + .o-position-absolute(@left: 100%); + .o-transform(translateX(-50%)); + height: @o-kanban-mobile-tabs-height; + padding: 10px; + font-size: 14px; + color: white; + + &.o_current { + font-weight: bold; + border-bottom: 3px solid @odoo-brand-optional; + } + .o_column_title { + white-space: nowrap; + } + } + } + + // [class] to get same specificity as elsewhere (kanban_view.less) + &[class] .o_kanban_group:not(.o_column_folded) { + .o-position-absolute(@top: @o-kanban-mobile-tabs-height, @left: 0, @bottom: 0); + overflow-x: scroll; + width: 100%; + padding: 0; + margin-left: 0; // override the margin-left: -1px of the desktop mode + border: none; + + .o_kanban_header { + display: none; + } + .o_kanban_record, .o_kanban_quick_create { + border: none; + border-bottom: 1px solid lightgray; + padding: 10px 16px; + margin: 0; + } + } + } +} diff --git a/addons/web/static/src/scss/layout_background.scss b/addons/web/static/src/scss/layout_background.scss new file mode 100644 index 00000000000..6750705c35b --- /dev/null +++ b/addons/web/static/src/scss/layout_background.scss @@ -0,0 +1,68 @@ +.o_background_footer, .o_background_header, .o_report_layout_background { + font-family: 'Lato'; + color: @gray; +} +.o_background_header { + border-bottom: 1px solid @gray-lighter; + .company_address { + min-width: 300px; + } + img { + max-height: 96px; + max-width: 300px; + margin-right: 16px; + } + h3 { + color: @odoo-brand-primary; + font-weight: 700; + max-width: 300px; + } +} +.o_background_footer { + ul { + border-top: 1px solid @odoo-brand-primary; + border-bottom: 1px solid @odoo-brand-primary; + padding: 4px 0; + margin: 0 0 4px 0; + li { + color: @odoo-brand-primary; + } + } +} +.o_report_layout_background { + background-image: url(/base/static/img/bg_background_template.jpg); + background-size: cover; + background-position: bottom center; + background-repeat: no-repeat; + min-height: 900px; + thead tr th, h2 { + color: @odoo-brand-primary; + } + tbody { + color: @gray; + tr:nth-child(odd) { + background-color: rgba(184, 171, 180, 0.2); + } + tr td { + border-top: none; + } + } + /*Total table*/ + .row > .col-xs-4 > table { + tr:nth-child(odd) { + background-color: transparent !important; + } + tr:first-child td { + /*we could get rid of this rule if .border-black td would be terminated in report.less*/ + border-top: none !important; + } + tr:last-child td { + color: @odoo-brand-primary; + } + } + #total { + table tr:last-child td { + border-bottom: 1px solid black; + } + } +} diff --git a/addons/web/static/src/scss/layout_boxed.scss b/addons/web/static/src/scss/layout_boxed.scss new file mode 100644 index 00000000000..21fcf66efc5 --- /dev/null +++ b/addons/web/static/src/scss/layout_boxed.scss @@ -0,0 +1,73 @@ +.o_boxed_footer, .o_boxed_header, .o_report_layout_boxed { + font-family: 'Lato'; + color: @gray; + font-size: 12px; +} +.o_boxed_header { + border-bottom: 1px solid @gray-lighter; + img { + max-height: 100px; + } + h4 { + color: @o-we-color-text-normal; + font-weight: 700; + text-transform: uppercase; + } +} +.o_boxed_footer { + white-space: nowrap; + border-top: 3px solid @gray; + ul { + margin: 4px 0; + } +} +.o_report_layout_boxed { + // This is not a general rule since the id is not used in all the reports, + // we should make a general structure for report body to use it everywhere + #informations { + border: 1px solid @gray; + padding-top: 10px; + margin: 0; + } + > h2 { + text-transform: uppercase; + } + table { + border: 1px solid @gray; + thead { + tr th { + border-bottom: 3px solid @gray !important; + text-transform: uppercase; + } + } + tbody { + color: @gray; + tr { + td { + border-top: none; + border-right: 1px solid @gray; + } + td:last-child { + background-color: @gray-lighter; + } + } + } + } + /*Total table*/ + .row > .col-xs-4 > table { + td { + border-right: none; + } + tr:last-child td, tr:first-child td { + /*we could get rid of this rule if .border-black td would be terminated in report.less*/ + border-top: none !important; + } + tr:first-child td { + background-color: transparent; + } + tr:last-child td { + background-color: @gray; + color: #fff; + } + } +} diff --git a/addons/web/static/src/scss/layout_clean.scss b/addons/web/static/src/scss/layout_clean.scss new file mode 100644 index 00000000000..869e1f4098f --- /dev/null +++ b/addons/web/static/src/scss/layout_clean.scss @@ -0,0 +1,85 @@ +.o_clean_footer, .o_clean_header, .o_report_layout_clean { + font-family: 'Lato'; + color: #000; +} +.o_clean_header { + img { + max-height: 90px; + max-width: 300px; + } +} +.o_clean_footer { + margin: 0 3px; + border-top: 3px solid @odoo-brand-primary; + h4 { + color: @odoo-brand-primary; + font-weight: bolder; + } + .pagenumber { + width: 35px; + height: 35px; + border: 3px solid @odoo-brand-primary; + background-color: @odoo-brand-optional; + color: white; + padding-top: 6px; + text-align: center; + } +} +.o_report_layout_clean { + h1, h2, h3 { + color: @odoo-brand-optional; + font-weight: bolder; + } + strong { + color: @odoo-brand-primary; + } + table { + thead { + color: @odoo-brand-primary; + tr th { + text-align: left !important; + border-top: 3px solid @odoo-brand-primary !important; + text-transform: uppercase; + } + tr th:last-child { + text-align: right !important; + } + tr th:first-child { + width: 48%; + } + } + tbody { + color: #000; + tr:first-child td { + border-top: none; + } + tr:last-child td { + border-bottom: 3px solid @odoo-brand-primary; + } + tr { + td { + padding: 15px 5px; + text-align: left !important; + } + td:last-child { + text-align: right !important; + } + } + } + } + /*Total table*/ + .row > .col-xs-4 { + width: 43%; + position: relative; + top: -20px; + > table { + tr:last-child td { + border-top: 1px solid @gray-lighter !important; + } + tr:first-child td { + /*we could get rid of this rule if .border-black td would be terminated in report.less*/ + border-top: none !important; + } + } + } +} diff --git a/addons/web/static/src/scss/list_view.scss b/addons/web/static/src/scss/list_view.scss new file mode 100644 index 00000000000..9106cf45a87 --- /dev/null +++ b/addons/web/static/src/scss/list_view.scss @@ -0,0 +1,243 @@ +@odoo-list-group-header-color: lighten(@odoo-brand-lightsecondary, 10%); + +.o_list_view { + position: relative; + cursor: pointer; + background-color: @odoo-view-background-color; + margin-bottom: 0px; + + &.table { + td, th { + vertical-align: middle; + } + } + + thead { + color: @odoo-main-text-color; + border-bottom: 1px solid #cacaca; + > tr > th { + border-left: 1px solid #dfdfdf; + &:not(.o_column_sortable):hover { + cursor: default; + } + } + } + + tfoot { + cursor: default; + color: @odoo-list-footer-color; + background-color: @odoo-list-footer-bg-color; + font-weight: @odoo-list-footer-font-weight; + border-top: 2px solid #cacaca; + border-bottom: 1px solid #cacaca; + } + + .o_column_sortable { + position: relative; + .user-select(none); // Prevent unwanted selection while sorting + + &::after { + font-family: FontAwesome; + content: "\f0d7"; + opacity: 0; + } + &:not(:empty)::after { + margin-left: 6px; + position: absolute; + } + &.o-sort-up { + cursor: n-resize; + &::after { + content: "\f0d7"; + } + } + &.o-sort-down { + cursor: s-resize; + &::after { + content: "\f0d8"; + } + } + &:hover::after { + opacity: 0.3; + } + &.o-sort-up, &.o-sort-down { + color: @headings-color; + &::after { + opacity: 1; + } + } + } + + .o_list_record_selector, .o_list_record_remove, .o_handle_cell { + width: 1px; // to prevent the column to expand + } + + .o_list_record_remove button { + padding: 0px; + background-style: none; + border-style: none; + height: 0px; + display: table-cell; + } + + // Decoration of the row + .text-bf { + font-weight: bold; + } + .text-it { + font-style: italic; + } + .text-muted { + color: lighten(@text-muted, 10%); + } + + // Grouped list views + tbody > tr.o_group_header { + height: 31px; + + .o_group_name { + white-space: nowrap; + } + .o_group_pager { + cursor: text; + .user-select(none); + text-align: right; + padding-top: 0; + padding-bottom: 0; + .o_pager_previous, .o_pager_next { + background-color: @odoo-list-group-header-color; + &:hover { + background-color: darken(@odoo-list-group-header-color, 10%); + } + } + } + } + tbody + tbody { + border-top: none; // Override bootstrap for grouped list views + } + + tbody { + tr:focus-within { + background-color: @odoo-form-lightsecondary; + } + tr{ + .focussed { + background-color: @odoo-form-lightsecondary; + } + } + } + + + // Values styling + .o_list_number { + text-align: right; + white-space: nowrap; + } + .o_list_text { + white-space: pre-wrap; + } + + .o_data_cell.o_invisible_modifier { + // Override display: none to keep table cells aligned. Note: cannot use + // 'initial' as it will force them to 'inline', not 'table-cell'. + display: table-cell!important; + } + + //-------------------------------------------------------------------------- + // Edition + //-------------------------------------------------------------------------- + .o_data_row.o_selected_row > .o_data_cell:not(.o_readonly_modifier) { + position: relative; + + // The in-edition elements will overflow other elements (the rows below, + // the content below the list view, ...). As those might be using + // position: relative, the in-edition elements have to define a z-index. + // Technically, creating a stacking context for a meaningful parent + // (maybe the .o_content) might be required for safety but we should + // consider this later if needed. + z-index: 1; + + // The in-edition elements will overflow other elements (the rows below, + // the content below the list view, ...). As those might be using + // position: relative, the in-edition elements have to define a z-index. + // Technically, creating a stacking context for a meaningful parent + // (maybe the .o_content) might be required for safety but we should + // consider this later if needed. + z-index: 1; + + // Field widgets override + > .o_field_widget { + .o-position-absolute(0, 0, auto, 0); + min-height: 100%; + + &:not(.o_field_text) { + white-space: nowrap; + } + + &.o_field_many2manytags > .badge { + &, > .o_badge_text { + white-space: normal; + max-width: 100%; // Fix a chrome bug where badge would not break on multiple lines + } + } + } + > .o_field_translate { + .o-position-absolute(0, 5px); + width: 16px; // to have some space on the right + } + .o_input { + padding: @table-condensed-cell-padding; + background-color: white; + + .o_input { + padding: 0!important; + } + } + .o_input_dropdown { + min-height: 100%; + } + .o_field_monetary input { + width: 0; + } + .o_field_boolean { + position: relative!important; + } + .o_field_widget { + min-width: 0; + } + .o_input_dropdown, .o_datepicker { + > .o_input { + padding-right: 15px; // To prevent caret overlapping + } + > .o_dropdown_button, .o_datepicker_button { + .o-position-absolute(20%, 5px); + } + } + .o_field_widget > .o_external_button { + padding: 0; + background-color: inherit; + margin-left: 3px; + } + .o_row_handle { + visibility: hidden; // Hide sequence when editing + } + .o_field_boolean { + width: auto!important; // Override the width computed in JS (needed for Chrome) + } + } +} + +// Buttons in ControlPanel +.o_list_buttons { + .o_list_button_save, .o_list_button_discard { + display: none; + } + &.o-editing { // for list view editable + .o_list_button_add { + display: none + } + .o_list_button_save, .o_list_button_discard { + display: inline-block + } + } +} diff --git a/addons/web/static/src/scss/list_view_extra.scss b/addons/web/static/src/scss/list_view_extra.scss new file mode 100644 index 00000000000..9a9413c0dd7 --- /dev/null +++ b/addons/web/static/src/scss/list_view_extra.scss @@ -0,0 +1,10 @@ + +.o_list_view { + thead { + background-color: #eee; + } + + tbody > tr.o_group_header { + .o-vertical-gradient(#fcfcfc, #dedede); + } +} diff --git a/addons/web/static/src/scss/mimetypes.scss b/addons/web/static/src/scss/mimetypes.scss new file mode 100644 index 00000000000..e4d2624dc6d --- /dev/null +++ b/addons/web/static/src/scss/mimetypes.scss @@ -0,0 +1,70 @@ +.o_image { + .square(38px); + display: inline-block; + background-image: url('/web/static/src/img/mimetypes/unknown.svg'); + background-size: contain; + + &[data-mimetype^='image'] { + background-image: url('/web/static/src/img/mimetypes/image.svg'); + } + &[data-mimetype^='audio'] { + background-image: url('/web/static/src/img/mimetypes/audio.svg'); + } + &[data-mimetype^='text'], &[data-mimetype$='rtf'] { + background-image: url('/web/static/src/img/mimetypes/text.svg'); + } + &[data-mimetype*='octet-stream'], &[data-mimetype*='download'], &[data-mimetype*='python'] { + background-image: url('/web/static/src/img/mimetypes/binary.svg'); + } + &[data-mimetype^='video'], &[title$='.mp4'], &[title$='.avi'] { + background-image: url('/web/static/src/img/mimetypes/video.svg'); + } + &[data-mimetype$='archive'], &[data-mimetype$='compressed'], &[data-mimetype*='zip'], &[data-mimetype$='tar'], &[data-mimetype*='package'] { + background-image: url('/web/static/src/img/mimetypes/archive.svg'); + } + &[data-mimetype='application/pdf'] { + background-image: url('/web/static/src/img/mimetypes/pdf.svg'); + } + &[data-mimetype^='text-master'], &[data-mimetype*='document'], &[data-mimetype*='msword'], &[data-mimetype*='wordprocessing'] { + background-image: url('/web/static/src/img/mimetypes/document.svg'); + } + &[data-mimetype*='application/xml'], &[data-mimetype$='html'] { + background-image: url('/web/static/src/img/mimetypes/web_code.svg'); + } + &[data-mimetype$='css'], &[data-mimetype$='less'], &[data-ext$='less'] { + background-image: url('/web/static/src/img/mimetypes/web_style.svg'); + } + &[data-mimetype*='-image'], &[data-mimetype*='diskimage'], &[data-ext$='dmg'] { + background-image: url('/web/static/src/img/mimetypes/disk.svg'); + } + &[data-mimetype$='csv'], &[data-mimetype*='vc'], &[data-mimetype*='excel'], &[data-mimetype$='numbers'], &[data-mimetype$='calc'], &[data-mimetype*='mods'], &[data-mimetype*='spreadsheet'] { + background-image: url('/web/static/src/img/mimetypes/spreadsheet.svg'); + } + &[data-mimetype^='key'] { + background-image: url('/web/static/src/img/mimetypes/certificate.svg'); + } + &[data-mimetype*='presentation'], &[data-mimetype*='keynote'], &[data-mimetype*='teacher'], &[data-mimetype*='slideshow'], &[data-mimetype*='powerpoint'] { + background-image: url('/web/static/src/img/mimetypes/presentation.svg'); + } + &[data-mimetype*='cert'], &[data-mimetype*='rules'], &[data-mimetype*='pkcs'], &[data-mimetype$='stl'], &[data-mimetype$='crl'] { + background-image: url('/web/static/src/img/mimetypes/certificate.svg'); + } + &[data-mimetype*='-font'], &[data-mimetype*='font-'], &[data-ext$='ttf'] { + background-image: url('/web/static/src/img/mimetypes/font.svg'); + } + &[data-mimetype*='-dvi'] { + background-image: url('/web/static/src/img/mimetypes/print.svg'); + } + &[data-mimetype*='script'], &[data-mimetype*='x-sh'], &[data-ext*='bat'], &[data-mimetype$='bat'], &[data-mimetype$='cgi'], &[data-mimetype$='-c'], &[data-mimetype*='java'], &[data-mimetype*='ruby'] { + background-image: url('/web/static/src/img/mimetypes/script.svg'); + } + &[data-mimetype*='javascript'] { + background-image: url('/web/static/src/img/mimetypes/javascript.svg'); + } + &[data-mimetype*='calendar'], &[data-mimetype$='ldif'] { + background-image: url('/web/static/src/img/mimetypes/calendar.svg'); + } + &[data-mimetype$='postscript'], &[data-mimetype$='cdr'], &[data-mimetype$='xara'], &[data-mimetype$='cgm'], &[data-mimetype$='graphics'], &[data-mimetype$='draw'], &[data-mimetype*='svg'] { + background-image: url('/web/static/src/img/mimetypes/vector.svg'); + } +} diff --git a/addons/web/static/src/scss/modal.scss b/addons/web/static/src/scss/modal.scss new file mode 100644 index 00000000000..5b74583ee41 --- /dev/null +++ b/addons/web/static/src/scss/modal.scss @@ -0,0 +1,83 @@ +.modal.o_technical_modal { + + .modal-content { + border-radius: 0; + + .modal-header .o_subtitle { + margin-left: 10px; + } + + .modal-body { + &.o_act_window { + padding: 0; + } + + .o_modal_header { + .o-webclient-padding(@top: 10px, @bottom: 10px); + .clearfix(); + + .o_search_options { + display: inline-block; + } + .o_pager { + float: right; + } + } + } + + .modal-footer { + text-align: left; + } + } + + + @media (min-width: @screen-sm-min) { + .modal-dialog { + height: 100%; + padding: 30px 0; + margin: 0 auto; + + .modal-content { + max-height: 100%; + .o-flex-display(); + .o-flex-flow(column, nowrap); + + .modal-header, .modal-footer { + .o-flex(0, 0, auto); + } + + .modal-body { + overflow: auto; + // fix iOS issue https://github.com/scottjehl/Device-Bugs/issues/8 + -webkit-transform: translate3d(0, 0, 0); + min-height: 0; + + &.o_dialog_error { + overflow: visible; + .o-flex-display(); + .o-flex-flow(column, nowrap); + + > .alert, > button { + .o-flex(0, 0, auto); + } + + > .o_error_detail { + .o-flex(1, 1, auto); + min-height: 0; + overflow: auto; + } + } + } + } + } + } +} + +// Temporary fix for modals which are not instantiated thanks to the Dialog +// JS classes (deprecated case) (see bootstrap_overridden.less) + Frontend. +// +// TODO the following code was disabled because it is saas-incompatible +// +// :not(body) > .modal { +// z-index: @zindex-modal-background + 1; +// } diff --git a/addons/web/static/src/scss/model_field_selector.scss b/addons/web/static/src/scss/model_field_selector.scss new file mode 100644 index 00000000000..aee5bd17867 --- /dev/null +++ b/addons/web/static/src/scss/model_field_selector.scss @@ -0,0 +1,130 @@ + +.o_field_selector { + position: relative; + + > .o_field_selector_value { + .o-flex-display(); + .o-flex-flow(row, wrap); + .o-align-items(center); + height: 100%; + min-height: 20px; // needed when there is no value in it and used standalone + &:active, &:focus, &:active:focus { + outline: none; + } + + > .o_field_selector_chain_part { + padding: 0px 1px; + border: 1px solid darken(@odoo-brand-lightsecondary, 10%); + background: @odoo-brand-lightsecondary; + margin-bottom: 1px; + } + > i { + .o-align-self(center); + margin: 0 2px; + font-size: 10px; + } + } + > .o_field_selector_controls { + .o-position-absolute(0, 0, 1px); + .o-flex-display(); + .o-align-items(center); + cursor: pointer; + } + + &.o_edit_mode { + > .o_field_selector_controls::after { + .o-caret-down(); + } + + > .o_field_selector_popover { + @o-field-selector-arrow-height: 7px; + .o-position-absolute(@top: 100%, @left: 0); + z-index: 1051; + width: 265px; + margin-top: @o-field-selector-arrow-height; + background: white; + box-shadow: 0 3px 10px rgba(0,0,0,.4); + + &:focus { + outline: none; + } + + .o_field_selector_popover_header { + color: white; + background: @brand-primary; + font-weight: bold; + padding: 5px 0 5px 0.4em; + + .o_field_selector_title { + width: 100%; + .o-text-overflow(); + padding: 0px 35px; + text-align: center; + } + .o_field_selector_popover_option { + .o-position-absolute(@top: 0); + padding: 7px 8px 8px 6px; + + &.o_prev_page { + left: 0; + border-right: 1px solid darken(@brand-primary, 10%); + } + &.o_field_selector_close { + right: 0; + border-left: 1px solid darken(@brand-primary, 10%); + } + &:hover { + background: darken(@brand-primary, 10%); + } + } + &:before { + .o-position-absolute(@top: -@o-field-selector-arrow-height, @left: @o-field-selector-arrow-height); + content: ""; + border-left: @o-field-selector-arrow-height solid rgba(0, 0, 0, 0); + border-right: @o-field-selector-arrow-height solid rgba(0, 0, 0, 0); + border-bottom: @o-field-selector-arrow-height solid @brand-primary; + } + } + .o_field_selector_popover_body { + .o_field_selector_page { + position: relative; + max-height: 320px; + overflow: auto; + margin: 0; + padding: 0; + + > .o_field_selector_item { + list-style: none; + position: relative; + padding: 5px 0 5px 0.4em; + cursor: pointer; + font-family: Arial; + font-size: 13px; + color: #444; + border-bottom: 1px solid #eee; + &.active { + background: #f5f5f5; + } + .o_field_selector_item_title { + font-size: 12px; + } + .o_field_selector_relation_icon { + .o-position-absolute(@top: 0, @right: 0, @bottom: 0); + .o-flex-display(); + .o-align-items(center); + padding: 10px; + } + } + } + } + .o_field_selector_popover_footer { + background: @brand-primary; + padding: 5px 0.4em; + + > input { + width: 100%; + } + } + } + } +} diff --git a/addons/web/static/src/scss/navbar.scss b/addons/web/static/src/scss/navbar.scss new file mode 100644 index 00000000000..cf14f9a8615 --- /dev/null +++ b/addons/web/static/src/scss/navbar.scss @@ -0,0 +1,233 @@ + +.o_main_navbar { + position: relative; + height: @odoo-navbar-height; + border-bottom: 1px solid @odoo-navbar-inverse-link-hover-bg; + background-color: @odoo-brand-primary; + color: white; + + > a, > button { + float: left; + height: @odoo-navbar-height; + border: none; + padding: 0 @odoo-horizontal-padding - 4px 0 @odoo-horizontal-padding; + line-height: @odoo-navbar-height; + background-color: transparent; + text-align: center; + color: inherit; + + font-size: 18px; + .user-select(none); + + &:hover, &:focus { + background-color: @odoo-navbar-inverse-link-hover-bg; + color: inherit; + } + &:focus, &:active, &:focus:active { + outline: none; + } + } + + > .o_menu_brand { + display: block; + float: left; + margin-right: 35px; + .user-select(none); + color: white; + font-size: 22px; + font-weight: 500; + line-height: @odoo-navbar-height; + + @media (max-width: @screen-xs-max) { + float: none; + margin: 0; + border-bottom: 1px solid @odoo-navbar-inverse-link-hover-bg; + color: transparent; + } + } + + > .o_menu_toggle { + margin-right: 5px; + } + + > ul { + display: block; + float: left; + margin: 0; + padding: 0; + list-style: none; + + > li { + position: relative; + display: block; + float: left; + + > a { + display: block; + height: @odoo-navbar-height; + padding: 0 10px; + color: white; + line-height: @odoo-navbar-height; + + &:hover { + background-color: @odoo-navbar-inverse-link-hover-bg; + } + + &:focus, &:active, &:focus:active { + outline: none; + } + } + + &.o_extra_menu_items { + > a { + width: @odoo-navbar-height; + text-align: center; + } + &.open > ul { + padding: 0; + + > li { + > a { + background-color: @odoo-brand-primary; + color: white; + border-bottom: 1px solid @odoo-brand-lightsecondary; + + &.dropdown-toggle { + background-color: lighten(@odoo-brand-primary, 15%); + pointer-events: none; // hack to prevent clicking on it because dropdown always opened + } + } + > ul { // remove dropdown-menu default style as it is nested in another one + position: static; + float: none; + display: block; + border: none; + box-shadow: none; + max-height: none; + } + } + } + } + } + + &.o_menu_systray { + float: right; + .open .dropdown-menu { + left: auto; + right: 0; + } + } + } + + .open .dropdown-menu { + max-height: 90vh; // the dropdown should not overstep the viewport + min-width: 100%; + overflow: auto; + margin-top: 0; + + .o-menu-indentation(@index) when (@index < 6) { + > li.o_menu_header_lvl_@{index}, > li .o_menu_entry_lvl_@{index} { + padding-left: @odoo-dropdown-hpadding + (@index - 2)*12px; + } + .o-menu-indentation(@index + 1); + } + .o-menu-indentation(3); + } + + .open .dropdown-toggle { + background-color: @odoo-navbar-inverse-link-hover-bg; + } + .o_user_menu { + margin-left: 6px; + + > a { + padding-right: @odoo-horizontal-padding; + } + + .oe_topbar_avatar { + height: 17px; + .o-transform(translateY(-2px)); + } + } + + @media (max-width: @screen-xs-max) { + .o-transition(height, 200ms, linear); + + position: relative; + height: @odoo-navbar-height; + overflow: hidden; + + > ul { + > li { + float: none; + .dropdown-backdrop { + display: none; + } + + &.open .dropdown-menu { + max-height: none; + } + } + + &.o_menu_sections { + width: 100%; + + > li.open .dropdown-menu { + position: static; + float: none; + background-color: transparent; + box-shadow: none; + border: none; + overflow: visible; + + > li > a { + background-color: transparent; + color: inherit; + } + } + } + + &.o_menu_systray { + .o-position-absolute(0px, @odoo-navbar-height, auto, @odoo-navbar-height); + height: @odoo-navbar-height; + text-align: right; + + > li { + display: inline-block; + + &.open .dropdown-menu { + .o-position-absolute(@odoo-navbar-height, 0, 0, 0); + position: fixed; + width: auto; + } + } + + .o_user_menu .oe_topbar_name { + display: none; + } + } + } + } +} + +@media (max-width: @screen-xs-max) { + body.o_mobile_menu_opened { + overflow: hidden; + height: 100%; + height: 100vh; + + .o_main_navbar { + height: 100%; + overflow: auto; + } + } +} + +@media (max-width: @screen-xs-max) { + .o_switch_company_menu > .dropdown-menu { + padding-top: 0px; + li.bg-info { + padding: 10px; + } + } + } diff --git a/addons/web/static/src/scss/pivot_view.scss b/addons/web/static/src/scss/pivot_view.scss new file mode 100644 index 00000000000..d7dfdd45de5 --- /dev/null +++ b/addons/web/static/src/scss/pivot_view.scss @@ -0,0 +1,78 @@ +.o_pivot { + overflow: auto; + + // Inform the user that he may click on a cell to be redirected to a list view of the + // items corresponding to the clicked cell + &.o_enable_linking { + .o_pivot_cell_value:hover { + color: @odoo-brand-optional; + cursor: pointer; + } + } + + table { + background-color: @odoo-view-background-color; + width: auto; // bootstrap override + + th { + font-weight: normal; // bootstrap override + background-color: lighten(@odoo-brand-secondary, 40%); + } + + .o-pivot-header-cell() { + background-color: lighten(@odoo-brand-secondary, 40%); + cursor: pointer; + white-space: nowrap; + .user-select(none); + &:hover { + background-color: lighten(@odoo-brand-secondary, 30%); + } + } + + .o_pivot_measure_row { + .o-pivot-header-cell; + } + + .o_pivot_header_cell_closed { + .o-pivot-header-cell; + &::before { + font-family: FontAwesome; + content: ""; + margin-right: 8px; + } + } + + .o_pivot_header_cell_opened { + .o-pivot-header-cell; + &::before { + font-family: FontAwesome; + content: ""; + margin-right: 8px; + } + } + + .o_pivot_measure_row_sorted_asc::after { + .o-caret-down; + margin-left: 5px; + } + + .o_pivot_measure_row_sorted_desc::after { + .o-caret-up; + margin-left: 5px; + } + } + + .o_pivot_field_selection::after { + .o-caret-right; + position: absolute; + right: 6px; + top: 9px; + } +} + +// ------------------------------------------------------------------ +// Control panel buttons +// ------------------------------------------------------------------ +.o_pivot_measures_list { + .o-selected-li; +}
\ No newline at end of file diff --git a/addons/web/static/src/scss/progress_bar.scss b/addons/web/static/src/scss/progress_bar.scss new file mode 100644 index 00000000000..25a89d15ecf --- /dev/null +++ b/addons/web/static/src/scss/progress_bar.scss @@ -0,0 +1,36 @@ +.o_progressbar { + + > div { + display: inline-block; + } + + .o_progressbar_title { + white-space: nowrap; + padding-right: 10px; + } + + .o_progress { + width: 100px; + height: 15px; + vertical-align: middle; + + border: 1px solid lighten(@odoo-brand-secondary, 25%); + overflow: hidden; + + background-color: white; + &.o_progress_overflow { + background-color: @odoo-brand-secondary; + } + + .o_progressbar_complete { + background-color: @odoo-brand-optional; + height: 100%; + } + } + + .o_progressbar_value { + width: 100px; + white-space: nowrap; + padding-left: 10px; + } +} diff --git a/addons/web/static/src/scss/rainbow.scss b/addons/web/static/src/scss/rainbow.scss new file mode 100644 index 00000000000..b86387b18ca --- /dev/null +++ b/addons/web/static/src/scss/rainbow.scss @@ -0,0 +1,257 @@ +/************** rainbow *****************/ + +// Variables +@reward-size: 400px; +@reward-size-mobile: 300px; +@reward-text-color: #727880; +@reward-base-time: 1.4s; + +// o_reward +.o_reward { + will-change: transform; + z-index: @zindex-modal; + padding: 50px; + margin: -5% auto 0 -(@reward-size / 2); + @media (max-width: @screen-xs-max) { + margin: -5% auto 0 -(@reward-size-mobile / 2); + } + background-image: -webkit-radial-gradient(#EDEFF4 30%, transparent 70%, transparent); + background-image: -o-radial-gradient(#EDEFF4 30%, transparent 70%, transparent); + background-image: radial-gradient(#EDEFF4 30%, transparent 70%, transparent); + + .o-animation(reward-fading, @reward-base-time * 0.5, ease-in-out, 0s, 1, normal, forwards); + .o-position-absolute(20%, auto, auto, 50%); + .size(@reward-size, @reward-size); + @media (max-width: @screen-xs-max) { + .size(@reward-size-mobile, @reward-size-mobile); + } + + &.o_reward_fading { + display: block; + .o-animation(reward-fading-reverse, (@reward-base-time * 0.4), ease-in-out, 0s, 1, normal, forwards); + + .o_reward_face_group { + .o-animation(reward-jump-reverse, (@reward-base-time * 0.4), ease-in-out, 0s, 1, normal, forwards); + } + + .o_reward_rainbow { + path { + .o-animation(reward-rainbow-reverse, (@reward-base-time * 0.5), ease-out, 0s, 1, normal, forwards); + } + } + + } + + .o_reward_face, .o_reward_stars, .o_reward_shadow, .o_reward_thumbup { + margin: 0 auto; + } + + .o_reward_rainbow { + path { + stroke-dasharray: 600; + stroke-dashoffset: 0; + fill: none; + stroke-linecap: round; + stroke-width: 21px; + .o-animation(reward-rainbow, (@reward-base-time ), ease-out, 0s, 1, normal, forwards); + } + } + + .o_reward_face_group { + transform-origin: center; + .o-animation(reward-jump, @reward-base-time * 0.8, ease-in-out); + .o-position-absolute(6%, 0, 0, 0); + .size(100%, 60%); + } + + .o_reward_face { + display: block; + top: 42%; + position: relative; + border-radius: 100%; + background: center center / contain no-repeat; + .o-animation(reward-float, @reward-base-time, ease-in-out, @reward-base-time, infinite, alternate); + .size(34%, 56.67%); + } + + .o_reward_stars { + display: block; + .size(@reward-size * 0.75, @reward-size / 2); + @media (max-width: @screen-xs-max) { + .size(@reward-size-mobile * 0.75, @reward-size-mobile / 2); + } + .o-position-absolute(18%, 7%); + + svg { + transform-origin: center center; + .o-position-absolute(28%, @left:3%); + .o-animation(reward-stars, @reward-base-time, ease-in-out, 0s, infinite, alternate-reverse); + + &.star2, &.star4 { + .o-animation(reward-stars, (@reward-base-time*1.2), ease-in-out, 0s, infinite, alternate); + } + + &.star2 { + left: 20%; + top: 2%; + } + + &.star3 { + left: 49%; + top: 6%; + } + + &.star4 { + left: 70%; + top: 27%; + } + + } + } + + .o_reward_thumbup { + width: 40px; + display: block; + .o-animation(reward-scale, @reward-base-time * 0.5, ease-in-out, 0s, infinite, alternate); + .o-position-absolute(63%, auto, auto, 65%); + } + + .o_reward_msg_container { + will-change: transform; + padding-top: 11%; + width: 70%; + margin-left: 15%; + + // Translate before animate + .o-transform(translateY(5px)); + + .o-animation(reward-float, @reward-base-time, ease-in-out, @reward-base-time, infinite, alternate-reverse); + .o-position-absolute(85%, auto, auto, 0%); + + .o_reward_thumb_right { + height: 40px; + z-index: 1; + .o-position-absolute(0, auto, auto, 16%); + } + + .o_reward_msg { + margin-left: 7%; + margin-top: -9.5%; + padding: 25px 15px 20px; + background: white; + border: 1px solid #ecf1ff; + border-top-width: 0; + display: inline-block; + + // Reset margins for first and penultimate childs (the last one is shadow) + *:first-child { + margin-top: 0; + } + } + + .o_reward_msg_content { + position: relative; + font-family: sans-serif; + text-align: left; + color: @reward-text-color; + } + + .o_reward_shadow_container { + .o-transform(~"translateY(0px) rotateZ(0)"); + .o-animation(reward-float, @reward-base-time, ease-in-out, @reward-base-time, infinite, alternate); + } + + .o_reward_shadow { + .size(100%, 12px); + background-color: #e7eaf0; + border-radius: 100%; + .o-transform(~"scale(0.8) rotateZ(0)"); + .o-animation(reward-scale, @reward-base-time, ease-in-out, @reward-base-time, infinite, alternate); + .o-position-absolute(auto, auto, -40px, 0); + } + } +} + +@keyframes reward-fading { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +@keyframes reward-fading-reverse { + 100% { + opacity: 0; + } +} + +@keyframes reward-jump { + 0% { + .o-transform(~"scale(0.5)"); + } + 50% { + .o-transform(~"scale(1.05)"); + } + to { + .o-transform(~"scale(1)"); + } +} + +@keyframes reward-jump-reverse { + 0% { + .o-transform(~"scale(1)"); + } + 50% { + .o-transform(~"scale(1.05)"); + } + to { + .o-transform(~"scale(0.5)"); + } +} + +@keyframes reward-rainbow { + 0% { + stroke-dashoffset: -500; + } + to { + stroke-dashoffset: 0; + } +} + +@keyframes reward-rainbow-reverse { + to { + stroke-dashoffset: -500; + } +} + +@keyframes reward-float { + from { + .o-transform(~"translateY(0px)"); + } + to { + .o-transform(~"translateY(5px)"); + } +} + +@keyframes reward-stars { + from { + .o-transform(~"scale(0.3) rotate(0deg)"); + } + 50% { + .o-transform(~"scale(1.0) rotate(20deg)"); + } + to { + .o-transform(~"scale(0.3) rotate(80deg)"); + } +} + +@keyframes reward-scale { + from { + .o-transform(~"scale(0.8)"); + } + to { + .o-transform(~"scale(1.0)"); + } +} diff --git a/addons/web/static/src/scss/report.editor.scss b/addons/web/static/src/scss/report.editor.scss new file mode 100644 index 00000000000..544787ff6b2 --- /dev/null +++ b/addons/web/static/src/scss/report.editor.scss @@ -0,0 +1,26 @@ +.o_editable { + &:not(:empty), &[data-oe-type] { + &[date-oe-model="ir.ui.view"] { + &, th, td { + &:hover { + -moz-box-shadow: #DDCC33 0 0 5px 2px inset; + -webkit-box-shadow: #DDCC33 0 0 5px 2px inset; + box-shadow: #DDCC33 0 0 5px 2px inset; + } + } + } + } +} + +body.o_in_iframe { + margin-top: 40px!important; + div#web_editor-top-edit { + > form { + display: none; + } + } + + .header, .footer { + display: none; + } +} diff --git a/addons/web/static/src/scss/report.scss b/addons/web/static/src/scss/report.scss new file mode 100644 index 00000000000..f34a2393fbe --- /dev/null +++ b/addons/web/static/src/scss/report.scss @@ -0,0 +1,35 @@ +html, body { + height: 100%; +} + +body { + color: #000 !important; + word-wrap: break-word; +} +.border-black td { + border-top: 1px solid black !important; +} + +/* See https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1524 */ +.table-condensed { + > thead > tr > th { + border-bottom: none !important; + } + > tbody > tr { + page-break-inside: avoid !important; + border-top: none !important; + } +} +.zero_min_height { + min-height: 0px !important; +} + +/* To avoid broken snippets in report rendering */ +.jumbotron, .panel, .carousel, section{ + page-break-inside: avoid; +} + +/* Wkhtmltopdf doesn't support very well the media-print CSS (depends on the version) */ +.hidden-print{ + display: none; +} diff --git a/addons/web/static/src/scss/report_backend.scss b/addons/web/static/src/scss/report_backend.scss new file mode 100644 index 00000000000..62252c2d9f7 --- /dev/null +++ b/addons/web/static/src/scss/report_backend.scss @@ -0,0 +1,14 @@ +.o_report_iframe { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: none; +} + +.o_report_no_edit_mode, .o_edit_mode_available, .o_report_edit_mode { + display: inline-block; +} diff --git a/addons/web/static/src/scss/search_view.scss b/addons/web/static/src/scss/search_view.scss new file mode 100644 index 00000000000..0261806631a --- /dev/null +++ b/addons/web/static/src/scss/search_view.scss @@ -0,0 +1,220 @@ +.o-search-options-dropdown-custom-li() { + margin: 3px 25px; + width: auto; + max-width: 250px; +} + +.o_searchview { + .o-flex-display(); + .o-flex-flow(row, wrap); + .o-align-items(flex-end); + position: relative; + padding: 0 20px 1px 0; + + .o_searchview_facet { + @o-searchview-facet-remove-width: 18px; + + .o-flex(0, 0, auto); + max-width: 100%; + .o-flex-display(); + position: relative; + margin: 1px 3px 0 0; + + .o_searchview_facet_label { + .o-flex(0, 0, auto); + .o-text-overflow(); + padding: 0 3px; + color: white; + + .o-flex-display(); + .o-align-items(center); + } + + .o_facet_values { + padding: 0 @o-searchview-facet-remove-width 0 5px; + .o_facet_values_sep { + font-style: italic; + } + } + .o_facet_remove { + .o-flex(0, 0, auto); + .o-flex-display(); + .o-justify-content(center); + .o-align-items(center); + .o-position-absolute(0, 0, 0); + width: @o-searchview-facet-remove-width; + cursor: pointer; + } + } + + .o_searchview_input { + width: 100px; + .o-flex(1, 0, auto); + } + + .o_searchview_more { + font-size: 16px; + cursor: pointer; + } + + .o_searchview_autocomplete { + .o-position-absolute(100%, @left: auto); + width: 100%; + + li { + padding-left: 25px; + position: relative; + &.o-indent { + padding-left: 50px; + } + a { + display: inline-block; + padding-left: 0px; + padding-right: 0px; + &:hover { + background-color: inherit; + } + &.o-expand, &.o-expanded { // caret + .o-position-absolute(@left: 6px); + padding: 3px; + } + &.o-expand:before { + .o-caret-right; + } + &.o-expanded:before { + .o-caret-down; + } + } + } + } +} + +// Searchview and Sidebar dropdowns +// FIXME: move me out of here +.o_dropdown { + white-space: nowrap; // prevent the arrow from going under the dropdown when too little space + .dropdown-toggle:first-child { + // apply the padding to the first element so that when the `favorites` menu goes under + // the `filters` menu, they're still aligned + padding-right: 10px; + } + + display: inline-block; + cursor: pointer; + .user-select(none); // Prevent text selection when toggling the dropdowns + > a { // dropdown togglers + color: @odoo-main-text-color; + &:hover { + text-decoration: none; + font-weight: bold; + color: darken(@odoo-main-text-color, 10%); + } + } + &.open > a { + font-weight: bold; + color: darken(@odoo-main-text-color, 10%); + } +} + +// Searchview dropdowns +.o_search_options { + // Open and closed carets in dropdowns + .o_closed_menu { + position: relative; + a:before { + .o-caret-right; + .o-position-absolute(@top: 50%, @left: 10px); + margin-top: (-@caret-width-base); + } + } + .o_open_menu { + position: relative; + a:before { + .o-caret-down; + .o-position-absolute(@top: 50%, @left: 10px); + margin-top: (-@caret-width-base); + } + } + + // Filters + .o_filters_menu { + .o-selected-li; + + max-height: ~"calc(100vh - 125px)"; + overflow: auto; + + .o_filter_condition { + .o-search-options-dropdown-custom-li; + margin-bottom: 8px; + .o_or_filter { // or between conditions + display: none; // hidden for the first condition + .o-position-absolute(@top: 7px, @left: -18px); + } + } + .o_filter_condition + .o_filter_condition { + .o_or_filter { + display: block; // displayed from second condition + } + } + .o_searchview_extended_prop_op { + margin: 3px 0px; // vertical gap between selects + } + .o_searchview_extended_prop_value { // date fields: datepicker position + .datepickerbutton { + .o-position-absolute(3px, -20px); + cursor: pointer; + } + } + .o_searchview_extended_delete_prop { // delete condition button position + .o-position-absolute(3px, -18px); + cursor: pointer; + } + .o_add_filter_menu { // apply and add buttons + display: none; // Needed by the webclient + .o-search-options-dropdown-custom-li; + } + } + + // Group By + .o_group_by_menu { + .o-selected-li; + + max-height: ~"calc(100vh - 125px)"; + overflow: auto; + + .divider {display: none;} // hide the divider by default (no group) + .o_add_group { // add button + display: none; // Needed by the webclient + .o-search-options-dropdown-custom-li; + } + } + + // Favorites + .o_favorites_menu { + max-height: 75vh; + overflow-y: auto; + .o-selected-li; + + max-height: ~"calc(100vh - 125px)"; + overflow: auto; + + .divider {display: none;} // hide the divider by default (no favorite) + .o-searchview-custom-private, .o-searchview-custom-public { + .o-remove-filter { + .o-position-absolute(50%, 12px); + margin-top: -6px; + cursor: pointer; + } + } + .o-searchview-custom-public a:after { + font-family: FontAwesome; + content: "\f0c0"; + margin-left: 5px; + font-weight: normal; + } + .o_save_name { // save button + display: none; // hidden by default + .o-search-options-dropdown-custom-li; + } + } +} diff --git a/addons/web/static/src/scss/search_view_extra.scss b/addons/web/static/src/scss/search_view_extra.scss new file mode 100644 index 00000000000..9c263976e4d --- /dev/null +++ b/addons/web/static/src/scss/search_view_extra.scss @@ -0,0 +1,43 @@ +.o_searchview { + background-color: white; + border: 1px solid #ccc; + border-radius: @border-radius-base; + padding: 1px 25px 3px 5px; + + .o_searchview_facet { + border: 1px solid @gray-light; + background: lighten(@odoo-brand-primary, 35%); + + .o_searchview_facet_label { + background-color: @gray-light; + } + + .o_facet_remove { + color: @gray-light; + &:hover { + color: @gray; + } + } + } + + .o_searchview_input { + border: none; + padding: 4px 0 0 0; + } + .o_searchview_more { + .o-position-absolute(@top: 6px, @right: 5px); + } + .o_searchview_autocomplete li.o-selection-focus { + background-color: @odoo-brand-primary; + > a { + color: white; + } + } +} + +// Search options: inputs and selects style +.o_search_options { + input[type="text"], select { + .form-control(); + } +} diff --git a/addons/web/static/src/scss/tooltip.scss b/addons/web/static/src/scss/tooltip.scss new file mode 100644 index 00000000000..e071bf04a40 --- /dev/null +++ b/addons/web/static/src/scss/tooltip.scss @@ -0,0 +1,59 @@ + +.tooltip { + padding: 0; + margin: 0; + opacity: 1; + + .tooltip-inner { + max-width: 300px; // fallback for browsers which do not support "vw" unit + max-width: 100vw; + background-color: @odoo-tooltip-background-color; + color: @odoo-tooltip-color; + border-radius: @border-radius-base; + box-shadow: 0px 0px 1px 1px @odoo-brand-secondary; + + padding: 5px; + + text-align: left; + + .oe_tooltip_string { + background-color: @odoo-brand-primary; + color: white; + font-weight: bold; + padding: 5px; + } + .oe_tooltip_help { + white-space: pre-line; + padding: 5px 5px 0; + } + .oe_tooltip_technical { + padding: 0; + margin: 5px 0 5px 20px; + list-style-type: circle; + + .oe_tooltip_technical_title { + font-weight: bold; + } + } + } + + .tooltip-arrow { + -moz-transform: scale(0.9999); + } + &.top, &.top-left, &.top-right { + .tooltip-arrow { + border-top-color: @odoo-tooltip-arrow-color!important; + } + } + &.bottom, &.bottom-left, &.bottom-right { + .tooltip-arrow { + border-bottom-color: @odoo-tooltip-arrow-color!important; + } + } + &.left .tooltip-arrow { + border-left-color: @odoo-tooltip-arrow-color!important; + } + &.right .tooltip-arrow { + border-right-color: @odoo-tooltip-arrow-color!important; + } +} diff --git a/addons/web/static/src/scss/ui.scss b/addons/web/static/src/scss/ui.scss new file mode 100644 index 00000000000..0a387331031 --- /dev/null +++ b/addons/web/static/src/scss/ui.scss @@ -0,0 +1,11 @@ +.o_hidden { + display: none!important; +} + +.o_text_overflow { + .o-text-overflow(); +} + +.ui-autocomplete { + z-index: @zindex-modal + 1; +} diff --git a/addons/web/static/src/scss/ui_extra.scss b/addons/web/static/src/scss/ui_extra.scss new file mode 100644 index 00000000000..0d97c09092e --- /dev/null +++ b/addons/web/static/src/scss/ui_extra.scss @@ -0,0 +1,10 @@ +//------------------------------------------------------------------------------ +// Checkboxes +//------------------------------------------------------------------------------ +div.o_checkbox { + display: inline-block; + vertical-align: sub; + > input + span { + display: none; + } +} diff --git a/addons/web/static/src/scss/utils.scss b/addons/web/static/src/scss/utils.scss new file mode 100644 index 00000000000..e89da21b4f6 --- /dev/null +++ b/addons/web/static/src/scss/utils.scss @@ -0,0 +1,274 @@ +/// +/// This file regroups the odoo mixins. They are available in every asset bundle. +/// + +// ------------------------------------------------------------------ +// Padding +// ------------------------------------------------------------------ +.o-webclient-padding(@top: 0px, @right: @odoo-horizontal-padding, @bottom: 0px, @left: @odoo-horizontal-padding) { + padding-top: @top; + padding-right: @right; + padding-bottom: @bottom; + padding-left: @left; +} + +// ------------------------------------------------------------------ +// Caret +// ------------------------------------------------------------------ +.utils-caret-boilerplate() { + content: ""; + display: inline-block; + width: 0; + height: 0; + vertical-align: middle; +} +.o-caret-down(@caret-width: @caret-width-base) { + .utils-caret-boilerplate; + border-bottom: 0; + border-left: @caret-width solid transparent; + border-right: @caret-width solid transparent; + border-top: @caret-width solid; + -moz-transform: scale(0.9999); // Smooth the caret on firefox +} +.o-caret-up(@caret-width: @caret-width-base) { + .utils-caret-boilerplate; + border-bottom: @caret-width solid; + border-left: @caret-width solid transparent; + border-right: @caret-width solid transparent; + border-top: 0; + -moz-transform: scale(0.9999); // Smooth the caret on firefox +} +.o-caret-left(@caret-width: @caret-width-base) { + .utils-caret-boilerplate; + border-bottom: @caret-width solid transparent; + border-left: 0; + border-right: @caret-width solid; + border-top: @caret-width solid transparent; + -moz-transform: scale(0.9999); // Smooth the caret on firefox +} +.o-caret-right(@caret-width: @caret-width-base) { + .utils-caret-boilerplate; + border-bottom: @caret-width solid transparent; + border-left: @caret-width solid; + border-right: 0; + border-top: @caret-width solid transparent; + -moz-transform: scale(0.9999); // Smooth the caret on firefox +} + +// ------------------------------------------------------------------ +// Vendor prefixes +// ------------------------------------------------------------------ +// Flex +.o-flex-display() { + display: -ms-flexbox; + display: -moz-box; + display: -webkit-box; + display: -webkit-flex; + + display: flex; +} +.o-inline-flex-display() { + display: -ms-inline-flexbox; + display: -moz-inline-box; + display: -webkit-inline-box; + display: -webkit-inline-flex; + + display: inline-flex; +} +.o-flex-flow(@direction, @wrap) { + -ms-flex-flow: @direction @wrap; + -moz-flex-flow: @direction @wrap; + -webkit-flex-flow: @direction @wrap; + + flex-flow: @direction @wrap; +} +.o-flex(@grow, @schrink, @basis) { + -ms-flex: @grow @schrink @basis; + -moz-flex: @grow @schrink @basis; + -webkit-box-flex: @grow; + -webkit-flex: @grow @schrink @basis; + + flex: @grow @schrink @basis; +} +.o-justify-content(@justify) { + -moz-justify-content: @justify; + -webkit-justify-content: @justify; + + justify-content: @justify; +} +.o-align-content(@align) { + -webkit-align-content: @align; + + align-content: @align; +} +.o-align-items(@align) { + -webkit-align-items: @align; + + align-items: @align; +} +.o-align-self(@align) { + -webkit-align-self: @align; + + align-self: @align; +} + +// Background-size +.o-background-size(@size) { + -webkit-background-size: @size; + -moz-background-size: @size; + -o-background-size: @size; + background-size: @size; +} + +// ------------------------------------------------------------------ +// Dropdowns +// ------------------------------------------------------------------ +.o-selected-li() { + li { + position: relative; + > a { + color: @odoo-main-text-color; + &:hover { + color: darken(@odoo-main-text-color, 10%); + } + } + &.selected { + > a { + color: darken(@odoo-main-text-color, 10%); + font-weight: bold; + &:before { + font-family: FontAwesome; + position: absolute; + left: 6px; + content: "\f00c"; + } + } + } + } +} + +// ------------------------------------------------------------------ +// Select Appearance +// ------------------------------------------------------------------ +.o-appearance(@value) { + -webkit-appearance: @value; + -moz-appearance: @value; + appearance: @value; +} + +// ------------------------------------------------------------------ +// Transform +// ------------------------------------------------------------------ +.o-transform-origin(@x: 50%, @y: 50%, @z: 0) { + -ms-transform-origin: @x @y @z; + -webkit-transform-origin: @x @y @z; + -moz-transform-origin: @x @y @z; + transform-origin: @x @y @z; +} + +// ------------------------------------------------------------------ +// Animation +// ------------------------------------------------------------------ +.o-animation(@name: none, @duration: 0s, @timing-function: ease, @delay: 0s, @iteration-count: 1, @direction: normal, @fill-mode: none, @play-state: running) { + -webkit-animation: @name @duration @timing-function @delay @iteration-count @direction @fill-mode @play-state; + -moz-animation: @name @duration @timing-function @delay @iteration-count @direction @fill-mode @play-state; + -o-animation: @name @duration @timing-function @delay @iteration-count @direction @fill-mode @play-state; + animation: @name @duration @timing-function @delay @iteration-count @direction @fill-mode @play-state; +} + +// ------------------------------------------------------------------ +// Transition +// ------------------------------------------------------------------ +.o-transition(@property: all, @duration: 0s, @timing-function: ease, @transition-delay: 0s) { + -webkit-transition: @property @duration @timing-function @transition-delay; + -moz-transition: @property @duration @timing-function @transition-delay; + -o-transition: @property @duration @timing-function @transition-delay; + transition: @property @duration @timing-function @transition-delay; +} + +// ------------------------------------------------------------------ +// Columns +// ------------------------------------------------------------------ +.o-columns(@width: auto, @col: auto) { + -webkit-columns: @width @col; + -moz-columns: @width @col; + columns: @width @col; +} + +// ------------------------------------------------------------------ +// Position absolute +// ------------------------------------------------------------------ +.o-position-absolute(@top: auto, @right: auto, @bottom: auto, @left: auto) { + position: absolute; + top: @top; + left: @left; + bottom: @bottom; + right: @right; +} + +// ------------------------------------------------------------------ +// Text overflow +// ------------------------------------------------------------------ +.o-text-overflow(@display: inline-block, @max-width: 100%) { + display: @display; + max-width: @max-width; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: top; // To update display context changed by overflow:hidden +} + +// ------------------------------------------------------------------ +// Gradients +// ------------------------------------------------------------------ +.o-linear-gradient(@deg: 45deg, @start-color: #555, @end-color: #333) { + background-repeat: repeat-x; + background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); + background-image: -o-linear-gradient(@deg, @start-color, @end-color); + background-image: linear-gradient(@deg, @start-color, @end-color); +} +.o-vertical-gradient(@startColor: #555, @endColor: #333) { + background-color: mix(@startColor, @endColor); + background-image: -webkit-gradient(linear, left top, left bottom, from(@startColor), to(@endColor)); + background-image: -webkit-linear-gradient(top, @startColor, @endColor); + background-image: -moz-linear-gradient(top, @startColor, @endColor); + background-image: -ms-linear-gradient(top, @startColor, @endColor); + background-image: -o-linear-gradient(top, @startColor, @endColor); + background-image: linear-gradient(to bottom, @startColor, @endColor); +} +.o-skew-gradient(@startColor: #555, @endColor: #333) { + background-color: @endColor; + background: -moz-linear-gradient(135deg, @endColor, @startColor); + background: -o-linear-gradient(135deg, @startColor, @endColor); + background: -webkit-gradient(linear, left top, right bottom, from(@startColor), to(@endColor)); + background: -ms-linear-gradient(top, @startColor, @endColor); +} + +// ------------------------------------------------------------------ +// Transform +// ------------------------------------------------------------------ +.o-transform(@transform) { + -webkit-transform: @transform; + -moz-transform: @transform; + -ms-transform: @transform; + -o-transform: @transform; + transform: @transform; +} + +// ------------------------------------------------------------------ +// Hovering effects +// ------------------------------------------------------------------ +.o-hover-opacity(@default-opacity: 0.5, @hover-opacity: 1) { + opacity: @default-opacity; + + &:hover, &:focus, &.focus { + opacity: @hover-opacity; + } +} +.o-hover-text-color(@default-color: @text-color, @hover-color: @link-color) { + color: @default-color; + + &:hover, &:focus, &.focus { + color: @hover-color; + } +} diff --git a/addons/web/static/src/scss/variables.scss b/addons/web/static/src/scss/variables.scss new file mode 100644 index 00000000000..1b4d2f09468 --- /dev/null +++ b/addons/web/static/src/scss/variables.scss @@ -0,0 +1,92 @@ +/// +/// This file regroups the variables that style odoo components. +/// They are available in every asset bundle. +/// + +// Font sizes +@odoo-font-size-base: 13px; + +// Colors +@odoo-brand-primary: #7c7bad; +@odoo-brand-optional: #7c7bad; +@odoo-brand-secondary: #f0eeee; +@odoo-brand-lightsecondary: #e2e2e0; +@odoo-color-silver: #F9F9F9; +@odoo-color-silver-dark: #E5E5E5; +@odoo-color-silver-darker: #d9d7d7; + +// Define @gray-lighter-dark as a minor bootstrap @gray-lighter variation used +// for design purposes only (e.g. cards' borders). We avoid to overwrite the +// default @gray-light because it is deeply used by bootstrap to define muted +// elements. +@gray-lighter-dark: @odoo-color-silver-dark; +@gray-lighter-darker: @odoo-color-silver-darker; + +@odoo-color-pink: #875A7B; // Enterprise @odoo-brand-primary +@odoo-main-color-muted: #a8a8a8; +@odoo-main-text-color: #4c4c4c; + +@odoo-view-background-color: white; +@odoo-shadow-color: #303030; + +@odoo-webclient-background-color: @odoo-color-silver; +@odoo-control-panel-background-color: @odoo-color-silver; +@odoo-form-lightsecondary: #ccc; + +@odoo-list-footer-color: @odoo-main-text-color; +@odoo-list-footer-bg-color: #eee; +@odoo-list-footer-font-weight: bold; + +@odoo-tooltip-background-color: black; +@odoo-tooltip-color: white; +@odoo-tooltip-arrow-color: black; +@odoo-tooltip-text-color: #777777; +@odoo-tooltip-title-text-color: #4c4c4c; + +// UI custom colors for tags, kanban records' colors, ...) +@odoo-nb-ui-color: 12; +@odoo-color-0: @gray-light; +@odoo-color-1: #F06050; +@odoo-color-2: #F4A460; +@odoo-color-3: #F7CD1F; +@odoo-color-4: #6CC1ED; +@odoo-color-5: #814968; +@odoo-color-6: #EB7E7F; +@odoo-color-7: #2C8397; +@odoo-color-8: #475577; +@odoo-color-9: #D6145F; +@odoo-color-10: #30C381; +@odoo-color-11: #9365B8; + +// Layout +@screen-xs-min: 475px; +@screen-xxs-max: (@screen-xs-min - 1); + +@screen-xl-min: 1534px; +@screen-lg-max: (@screen-xl-min - 1); + +@odoo-form-group-cols: 12; +@odoo-form-spacing-unit: 5px; +@odoo-horizontal-padding: 16px; +@odoo-innergroup-rpadding: 45px; +@odoo-dropdown-hpadding: 20px; + +@border-radius-base: 3px; + +@odoo-sheet-vpadding: 24px; + +// Needed for having no spacing between sheet and mail body in mass_mailing: +// Different required cancel paddings between web and web_enterprise +@odoo-sheet-cancel-tpadding: 0px; +@odoo-sheet-cancel-hpadding: @odoo-horizontal-padding; +@odoo-sheet-cancel-bpadding: @odoo-horizontal-padding; + +@odoo-avatar-size: 90px; + +@odoo-statusbar-height: 33px; +@odoo-statusbar-arrow-width: @odoo-statusbar-height/3; +@odoo-statusbar-disabled-bg: lighten(@odoo-brand-lightsecondary, 7%); + +@odoo-label-font-size-factor: 0.8; +@odoo-navbar-height: 34px; +@odoo-navbar-inverse-link-hover-bg: @navbar-inverse-link-active-bg; diff --git a/addons/web/static/src/scss/views.scss b/addons/web/static/src/scss/views.scss new file mode 100644 index 00000000000..0c7936fc570 --- /dev/null +++ b/addons/web/static/src/scss/views.scss @@ -0,0 +1,103 @@ +/** + * This file regroups the rules which apply on elements which are shared between + * all renderers. For field default rules, see the fields.less file. + */ + +// Invisible modifier (can be inside the view, the button area, ...) +.o_invisible_modifier { + display: none!important; +} + +// Status +// This should normally be put in fields.less but these classes are used outside +// of `.o_field_widget` so it needs to be placed at an upper level. +.o_status { + display: inline-block; + height: 12px; + width: 12px; + border-radius: 6px; + vertical-align: middle; + + background-color: @gray-lighter-dark; + + &.o_status_green { + background-color: @brand-success; + } + &.o_status_red { + background-color: @brand-danger; + } +} + +.o_btn-link-as-button { + padding: 2px; + font-size:12px; + + & > a { + margin-bottom: -4px !important; + margin-left: 3px; + } +} + +// No content helper +.o_view_nocontent { + .o-position-absolute(20%, 0, 0, 0); + pointer-events: none; + z-index: 1; + + .o_nocontent_help { + pointer-events: auto; + max-width: 650px; + margin: auto; + padding: 15px; + z-index: 1000; + text-align: center; + color: @odoo-tooltip-text-color; + font-size: 115%; + + > p:first-of-type { + margin-top: 0; + color: @odoo-tooltip-title-text-color; + font-weight: bold; + font-size: 125%; + } + + a { + cursor: pointer; + } + + .o-init-image() { + content: ""; + display: block; + margin: auto; + background-size: cover; + } + + .o_view_nocontent_smiling_face:before { + .o-init-image(); + .size(120px, 140px); + background: transparent url(/web/static/src/img/smiling_face.svg) no-repeat center; + } + + .o_view_nocontent_neutral_face:before { + .o-init-image(); + .size(120px, 140px); + background: transparent url(/web/static/src/img/neutral_face.svg) no-repeat center; + } + + .o_view_nocontent_empty_folder:before { + .o-init-image(); + .size(120px, 80px); + margin-top: 30px; + margin-bottom: 30px; + background: transparent url(/web/static/src/img/empty_folder.svg) no-repeat center; + } + + .o_empty_custom_dashboard { + min-height: 327px; + margin-left: -@grid-gutter-width/2; + margin-top: -@grid-gutter-width/2; + padding: 100px 0 0 137px; + background: transparent url(/web/static/src/img/graph_background.png) no-repeat 0 0; + } + } +} diff --git a/addons/web/static/src/scss/web_calendar.scss b/addons/web/static/src/scss/web_calendar.scss new file mode 100644 index 00000000000..5179552b3b6 --- /dev/null +++ b/addons/web/static/src/scss/web_calendar.scss @@ -0,0 +1,230 @@ +@nb-calendar-colors: 24; + +@keyframes backgroundfade { + from {background-color: fade(@odoo-brand-primary, 50%);} + to {background-color: #f5f5f5;} +} + +.o_calendar_container { + height: 100%; + .o-webclient-padding(@top: @odoo-horizontal-padding/2, @bottom: @odoo-horizontal-padding/2); + .o-flex-display(); + + .calendar_color_loop(@index) when (@index < @nb-calendar-colors+1) { + .o_calendar_color_@{index} { + color: #0D0D0D; + background-color: spin(rgb(255, 192, 192), 360/(@nb-calendar-colors+1) * @index); + border-color: spin(rgb(255, 192, 192), 360/(@nb-calendar-colors+1) * @index); + opacity: 0.7; + &.o_event_hightlight { + font-weight: bold; + opacity: 0.9; + } + &:hover { + color: #666 !important; + } + } + .calendar_color_loop(@index + 1); + } + .calendar_color_loop(1); + + .underline_color_loop(@index) when (@index < @nb-calendar-colors+1) { + .o_underline_color_@{index} { + border-bottom: 4px solid spin(rgba(255, 192, 192, 0.7), 360/(@nb-calendar-colors+1) * @index); + } + .underline_color_loop(@index + 1); + } + .underline_color_loop(1); + + .o_calendar_view { + .o-flex(1, 1, auto); + min-width: 0; + + .o_calendar_widget { + height: 100%; + background-color: @odoo-view-background-color; + * { + z-index: 0; // FIXME + } + .fc-week-number, .fc-widget-header { + background-color: lighten(@odoo-brand-secondary, 30%); + } + .o_avatar_square { + border-radius: 5px; + display: inline-block; + opacity: 1; + border: 1px solid #999; + } + .o_fields img, .o_avatar_square { + vertical-align: middle; + margin-left: 1px; + width: 18px; + height: 18px; + } + .o_field_type_char:first-child { + font-weight: bold; + } + .fc-view { + overflow-x: auto; + } + } + } + + .o_calendar_sidebar_container { + .o-flex(0, 0, @odoo-horizontal-padding); + position: relative; + + &.o_sidebar_hidden { + margin-right: -@odoo-horizontal-padding; // hack to display the toggler in the gutter + .o_calendar_sidebar_toggler { + padding: 4px; + color: darken(@odoo-webclient-background-color, 30%); + } + } + + .o_calendar_sidebar_toggler { + .o-position-absolute(@top: 0, @right: 0); + cursor: pointer; + padding: 6px; + z-index: 1; + &:hover { + color: black; + } + } + + .o_calendar_sidebar { + width: 250px; + margin-left: 8px; + background: @odoo-view-background-color; + } + + .ui-datepicker { + width: 100%; + font-size: 8pt; + border-radius: 0; + border: none; + padding: 0; + + .ui-widget-header { + .o-flex-display(); + background: none; + background-color: lighten(@odoo-brand-secondary, 30%); + border-radius: 0; + + .ui-datepicker-prev, .ui-datepicker-next { + .o-flex(0, 0, auto); + position: static; + cursor: pointer; + padding: 2px; + text-align: center; + color: @odoo-main-text-color; + &.ui-state-hover { + background: none; + border: none; + color: black; + } + .ui-icon { + display: none; + } + } + .ui-datepicker-prev { + order: 1; + &:after { + font-family: FontAwesome; + content: ""; + } + } + .ui-datepicker-next { + order: 3; + &:before { + font-family: FontAwesome; + content: ""; + } + } + .ui-datepicker-title { + .o-flex(0, 0, auto); + order: 2; + display: inline-block; + margin: 0 10px; + } + } + table { + td { + padding: 0 2px 2px 0; + background-color: @odoo-view-background-color; + a { + border: none; + background: none; + background-color: lighten(@odoo-brand-secondary, 40%); + text-align: center; + } + } + .ui-state-default { + color: @odoo-brand-primary; + &:hover { + background: none; + background-color: fade(@odoo-brand-primary, 50%); + border-color: @odoo-brand-primary; + color: @odoo-view-background-color; + }; + } + .ui-state-active { + background: none; + background-color: @odoo-brand-primary; + color: @odoo-view-background-color; + } + .o_selected_range.o_color { + background: none; + background-color: @odoo-brand-primary; + animation: backgroundfade 3s forwards; + } + } + } + .o_calendar_filter { + padding: 8px; + border-top: 1px solid lightgray; + .o_field_many2one { + width: 100%; + } + } + } + + .fc-time-grid-event.fc-short .fc-time:before { + content: ''; + } +} + +.modal { + .o_attendee_head { + width: 32px; + margin-right: 5px; + } +} + +.o_dashboard { + .o_calendar_container .o_calendar_sidebar_container { + display: none; + } +} + +// Mobile rules +@media only screen and (max-width: 768px) { + .o_calendar_container { + padding: 0; + } +} +@media (max-width: @screen-xs-max) { + .o_control_panel { + .o_calendar_button_today { + float: right; + > .o_calendar_text { + margin-top: 3px; + } + } + } + .o_calendar_view { + .fc-day-header { + word-spacing: 1000px; // force line break in week mode + } + } +} diff --git a/addons/web/static/src/scss/webclient.scss b/addons/web/static/src/scss/webclient.scss new file mode 100644 index 00000000000..1de198d282b --- /dev/null +++ b/addons/web/static/src/scss/webclient.scss @@ -0,0 +1,140 @@ +// ------------------------------------------------------------------ +// General +// ------------------------------------------------------------------ +.o_web_client { + position: relative; // normally useless but required by bootstrap-datepicker + background-color: @odoo-webclient-background-color; +} + +// ------------------------------------------------------------------ +// Misc. widgets +// ------------------------------------------------------------------ +@notification-error-bg-color: #F16567; +@notification-info-bg-color: #FCFBEA; +.o_notification_manager { + width: 300px; + max-width: 100%; + + .o-position-absolute(@navbar-height, 0px); + z-index: 1100; // Bootstrap modal z-index is 1050 + + .o_notification { + padding: 0; + margin: 5px 0 0 0; + + opacity: 0; + + background-color: @notification-info-bg-color; + box-shadow: 0px 0px 5px 1px @odoo-main-text-color; + + position: relative; + .o_close { + .o-position-absolute(5px, 5px); + color: rgba(0, 0, 0, 0.3); + text-decoration: none; + } + + .o_notification_title { + .o-flex-display(); + .o-align-items(center); + + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + padding: 10px 10px 10px 20px; + + font-weight: bold; + + .o_icon { + display: inline-block; + margin-right: 20px; + color: rgba(0, 0, 0, 0.3); + } + } + + .o_notification_content { + padding: 10px; + } + + &.o_error { + color: white; + background-color: @notification-error-bg-color; + } + } +} + +// Buttons +.o_icon_button { + background-color: transparent; + border: 0; + padding: 0; + outline: none; +} + +// Boolean Toggle widget +div.o_boolean_toggle { + position: relative; + display: inline-block; + width: 32px !important; + height: 18px; + + > input { + display: none; + } + + .slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #a0a0a0; + border-radius: 24px; + + &:before { + position: absolute; + content: ""; + height: 12px; + width: 12px; + left: 3px; + bottom: 3px; + background-color: white; + border-radius: 50%; + } + } + + > input:checked + .slider { + background-color: @odoo-brand-optional; + + &:before { + .translate(14px; 0px); + } + } +} + +// Full bg colors (bootstrap extension) +.bg-success-full { + background-color: @brand-success; +} +.bg-warning-full { + background-color: @brand-warning; +} +.bg-danger-full { + background-color: @brand-danger; +} +.bg-info-full { + background-color: @brand-info; +} + +.o_web_accesskey_overlay { + font-family: @font-family-sans-serif; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + background-color: rgba(0,0,0,.6); + color: #FFFFFF; + justify-content: center; + display: flex; + align-items: center; +}
\ No newline at end of file diff --git a/addons/web/static/src/scss/webclient_extra.scss b/addons/web/static/src/scss/webclient_extra.scss new file mode 100644 index 00000000000..82798437672 --- /dev/null +++ b/addons/web/static/src/scss/webclient_extra.scss @@ -0,0 +1,46 @@ +//------------------------------------------------------------------------------ +// Inputs and selects (note: put the o_input class to have the style) +//------------------------------------------------------------------------------ +[type="text"], [type="password"], [type="number"], textarea, select { + width: 100%; + display: block; + outline: none; +} +.o_input { + border: 1px solid @odoo-form-lightsecondary; + border-radius: @border-radius-base; + padding: 2px 4px; + color: #1f1f1f; + + .o_input { + border: none!important; + padding: 0; + } +} +select { + background: white; +} + +//------------------------------------------------------------------------------ +// Loading +//------------------------------------------------------------------------------ +.o_loading { + position: fixed; + top: 0; + right: 50%; + padding: 4px 12px; + background-color: @odoo-color-pink; + color: white; + text-align: center; + border-top: none; + border-bottom-right-radius: 8px; + border-bottom-left-radius: 8px; +} + +//------------------------------------------------------------------------------ +// User menu in navbar +//------------------------------------------------------------------------------ +#oe_main_menu_navbar .oe_user_menu_placeholder .o_user_menu .oe_topbar_name { + .o-text-overflow(); + max-width: 150px; +} diff --git a/addons/web/static/src/scss/webclient_layout.scss b/addons/web/static/src/scss/webclient_layout.scss new file mode 100644 index 00000000000..f876d8b3527 --- /dev/null +++ b/addons/web/static/src/scss/webclient_layout.scss @@ -0,0 +1,165 @@ +@odoo-submenu-width: 220px; + +.o_web_client { + .o-flex-display(); + .o-flex-flow(column, nowrap); + overflow: hidden; + + &.o_fullscreen { + #oe_main_menu_navbar { + display: none; + } + .o_main .o_sub_menu { + display: none; + } + } + + + .navbar { + .o-flex(0, 0, auto); + + li > a { + padding: 4px 8px; + margin-top: 2px; + font-size: 13px; + } + + .oe_topbar_avatar { + max-height: 18px; + width: 18px; + } + } + + > .o_main { + .o-flex(1, 1, auto); + .o-flex-display(); + min-height: 0; // Allow flex to shrink this element as much as it wants + height: 100%; + + .o_sub_menu { + .o-flex(0, 0, @odoo-submenu-width); + .o-flex-display(); + .o-flex-flow(column, nowrap); + border-right: 1px solid darken(@odoo-control-panel-background-color, 20%); + background-color: @odoo-control-panel-background-color; + + .o_sub_menu_logo { + .o-flex(0, 0, auto); + text-align: center; + position: relative; + + > img { + margin: 14px 0; + } + + .oe_logo_edit { + position: absolute; + top: 1px; + width: 100%; + padding: 4px; + margin: 14px 0; + display: none; + color: #eee; + background: rgba(37,37,37,0.9); + } + &:hover .oe_logo_edit_admin { + display: block; + } + } + + .o_sub_menu_content { + .o-flex(1, 1, auto); + height:100%; + overflow-y: auto; + + .oe_secondary_menu_section { + font-weight: bold; + margin-left: 8px; + color: @odoo-brand-optional; + } + .oe_secondary_submenu { + margin: 3px 0px 10px; + line-height: 1.1em; + >li:not(.active) > a { + color: @odoo-main-text-color; + } + > li > a { + padding: 4px 4px 4px 18px; + > .badge { + margin-top: -1px; + } + } + .oe_secondary_submenu { + > li > a { + padding-left: 30px; + } + .oe_secondary_submenu > li > a { + padding-left: 42px; + } + } + .oe_menu_text { + .o-text-overflow(); + max-width: 85%; + margin-top: 1px; + } + .oe_menu_toggler:before { + display: inline-block; + width: 0; + height: 0; + content: "&darr"; + opacity: 0.5; + text-indent: -99999px; + vertical-align: top; + margin-left: -12px; + margin-top: 4px; + margin-right: 4px; + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + border-left: 4px solid #4c4c4c; + } + .oe_menu_opened:before { + margin-top: 6px; + margin-left: -16px; + margin-right: 4px; + border-left: 4px solid transparent; + border-right: 4px solid transparent; + border-top: 4px solid #4c4c4c; + } + } + } + + .o_sub_menu_footer { + .o-flex(0, 0, auto); + text-align: center; + + > a { + font-weight: bold; + > span { + color: @odoo-color-pink; + } + } + } + } + + .o_main_content { + .o-flex(1, 1, auto); + .o-flex-display(); + .o-flex-flow(column, nowrap); + + .o_control_panel { + .o-flex(0, 0, auto); + } + .o_content { + .o-flex(1, 1, auto); + height: 100%; + overflow: auto; + position: relative; + + > .o_view_controller { + .o-position-absolute(0, 0, 0, 0); // Get the 100% height of its flex parent + height: 100%; + } + } + } + } +} |
