diff options
| author | Jigar Patel <jat@openerp.com> | 2019-05-10 07:27:16 +0000 |
|---|---|---|
| committer | Dharmraj Jhala <dja@odoo.com> | 2019-10-16 06:09:02 +0000 |
| commit | 316d5afdd3798ff75a3742e07b0640c84ab177fc (patch) | |
| tree | 2254b9925b9d0714758fa3ec1322bc159f2b5fb7 /addons | |
| parent | f703271c0a79cc5bd989d83695a11f04d348f044 (diff) | |
[IMP] stock: add hierarchical view for stock location
Diffstat (limited to 'addons')
| -rw-r--r-- | addons/stock/models/stock_location.py | 26 | ||||
| -rw-r--r-- | addons/stock/static/src/js/stock_location_hierarchy.js | 19 | ||||
| -rw-r--r-- | addons/stock/static/src/scss/stock_location_hierarchy.scss | 105 | ||||
| -rw-r--r-- | addons/stock/views/stock_location_views.xml | 49 | ||||
| -rw-r--r-- | addons/stock/views/stock_template.xml | 2 |
5 files changed, 201 insertions, 0 deletions
diff --git a/addons/stock/models/stock_location.py b/addons/stock/models/stock_location.py index 6ce9ac1019b..120bc1d590b 100644 --- a/addons/stock/models/stock_location.py +++ b/addons/stock/models/stock_location.py @@ -163,6 +163,32 @@ class Location(models.Model): self.ensure_one() return self.usage in ('supplier', 'customer', 'inventory', 'production') or self.scrap_location + def _qweb_prepare_qcontext(self, view_id, domain): + values = super()._qweb_prepare_qcontext(view_id, domain) + result = self.search_read(domain, ['name', 'location_id', 'usage', 'barcode']) + roots = [] + + locations = {location['id']: dict(location, **{'childs': []}) for location in result} + + for location in locations.values(): + parent_location_id = location['location_id'] + if parent_location_id and parent_location_id[0] in locations: + locations[parent_location_id[0]]['childs'].append(location) + else: + roots.append(location) + + values['data'] = roots + return values + + @api.model + def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False): + result = super().fields_view_get(view_id, view_type, toolbar, submenu) + + view_location_qweb = self.env.ref('stock.view_location_qweb', raise_if_not_found=False) + if result['type'] == 'qweb' and view_location_qweb and result['view_id'] == view_location_qweb.id: + result['arch'] = '<qweb js_class="stock_location_hierarchy_qweb"/>' + return result + class Route(models.Model): _name = 'stock.location.route' diff --git a/addons/stock/static/src/js/stock_location_hierarchy.js b/addons/stock/static/src/js/stock_location_hierarchy.js new file mode 100644 index 00000000000..29fb287de3f --- /dev/null +++ b/addons/stock/static/src/js/stock_location_hierarchy.js @@ -0,0 +1,19 @@ +odoo.define('stock.stock_location_hierarchy_qweb', function (require) { +"use strict"; + +var QwebView = require('web.qweb'); +var registry = require('web.view_registry'); + + +var QWebView = QwebView.View.extend({ + icon: 'fa-sitemap', + searchMenuTypes: ['filter', 'favorite'], +}); + +registry.add('stock_location_hierarchy_qweb', QWebView); + +return { + View: QWebView, +}; + +}); diff --git a/addons/stock/static/src/scss/stock_location_hierarchy.scss b/addons/stock/static/src/scss/stock_location_hierarchy.scss new file mode 100644 index 00000000000..6ea799ff508 --- /dev/null +++ b/addons/stock/static/src/scss/stock_location_hierarchy.scss @@ -0,0 +1,105 @@ +$o-hierarchical-highlight-color: $o-brand-primary; +$o-hierarchical-border-color: gray('500'); +$o-hierarchical-border-width: 1px; +$o-hierarchical-border-radius: 4px; + +@mixin o-stock-hierarchy-level { + position: relative; + padding: 1em 0; + text-align: center; +} + +.o_stock_location_hierarchy { + .o_hierarchy_container { + border: 1px solid gray('300'); + background-color: lighten(gray('200'), 2%); + border-radius: .5rem; + white-space: nowrap; + overflow-x: auto; + @include o-stock-hierarchy-level(); + ul.o_hierarchy_level { + @include o-stock-hierarchy-level(); + &:before { + content: ''; + @include o-position-absolute($top: 0, $left: 50%); + border-left: $o-hierarchical-border-width solid $o-hierarchical-border-color; + height: 1.2rem; + } + } + li.o_hierarchy_item { + display: inline-block; + vertical-align: top; + position: relative; + padding: 1rem .5rem 0 .5rem; + .o_hierarchy_box { + position: relative; + border: $o-hierarchical-border-width solid gray('white'); + padding: .5rem .75rem; + display: inline-block; + border-radius: $o-hierarchical-border-radius; + transition: 0.2s; + background: gray('white'); + box-shadow: 0 1px 3px rgba(gray('black'), 0.12), 0 1px 2px rgba(gray('black'), 0.14); + &.disabled { + background-color: #f1f1f1; + border-color: #f1f1f1; + } + .o_hierarchy_box_title, .o_hierarchy_box_subtitle { + max-width: 170px; + } + .o_hierarchy_action { + display: none; + @include o-position-absolute($left: 0, $right: 0, $bottom: -10px); + z-index: 1; + .o_hierarchy_add_child .fa { + background-color: gray('white'); + border-radius: 8rem; + } + } + @include media-breakpoint-up(md) { + &:hover .o_hierarchy_action { + display: block; + } + &:hover, &:hover + ul li .o_hierarchy_box { + background: lighten($o-hierarchical-highlight-color, 65); + border: $o-hierarchical-border-width solid $o-hierarchical-highlight-color; + } + &:hover + ul li::after, + &:hover + ul li::before, + &:hover + ul::before, + &:hover + ul ul::before { + border-color: $o-hierarchical-highlight-color; + } + } + } + &::before, &::after { + content: ''; + @include o-position-absolute($top: 0, $right: 50%); + border-top: $o-hierarchical-border-width solid $o-hierarchical-border-color; + width: 52%; + height: 1em; + } + &::after { + right: auto; + left: 50%; + border-left: $o-hierarchical-border-width solid $o-hierarchical-border-color; + } + &:only-child::after, &:only-child::before { + display: none; + } + &:only-child { + padding-top: 0; + } + &:first-child::before, &:last-child::after { + border: 0 none; + } + &:last-child::before { + border-right: $o-hierarchical-border-width solid $o-hierarchical-border-color; + border-radius: 0 $o-hierarchical-border-radius 0 0; + } + &:first-child::after { + border-radius: $o-hierarchical-border-radius 0 0 0; + } + } + } +} diff --git a/addons/stock/views/stock_location_views.xml b/addons/stock/views/stock_location_views.xml index dc0b83af390..7d0ea34a729 100644 --- a/addons/stock/views/stock_location_views.xml +++ b/addons/stock/views/stock_location_views.xml @@ -53,6 +53,53 @@ </field> </record> + <record id="view_location_qweb" model="ir.ui.view"> + <field name="name">stock.location.qweb</field> + <field name="type">qweb</field> + <field name="model">stock.location</field> + <field name="arch" type="xml"> + <div class="container-fluid o_stock_location_hierarchy"> + <div class="row"> + <t t-if="data"> + <div class="col-12 py-3" t-foreach="data" t-as="location"> + <ul class="o_hierarchy_container mb-0"> + <t t-call="stock.stock_location_hierarchy"/> + </ul> + </div> + </t> + <t t-else=""> + <div class="col py-4 text-center"> + <h1>No data available.</h1> + </div> + </t> + </div> + </div> + </field> + </record> + + <template id="stock_location_hierarchy" name="Stock Location Hierarchy"> + <li class="o_hierarchy_item"> + <div t-attf-class="o_hierarchy_box #{location['usage'] == 'view' and 'disabled' or ''}"> + <a href="#" type="action" t-att-data-res-id="location['id']" class="o_hierarchy_box_title text-truncate" t-att-title="location['name']"> + <t t-esc="location['name']"/> + </a> + <small class="o_hierarchy_box_subtitle text-truncate text-muted d-block" t-att-title="location['barcode']"> + <t t-esc="location['barcode']"/> + </small> + <div class="o_hierarchy_action"> + <a href="#" type="action" data-views='[[false, "form"]]' t-attf-data-context='{"default_location_id": #{location["id"]}}' class="o_hierarchy_add_child" title="Add a new child record"> + <i class="fa fa-plus-circle"/> + </a> + </div> + </div> + <ul class="o_hierarchy_level" t-if="len(location['childs'])"> + <t t-foreach="location['childs']" t-as="location"> + <t t-call="stock.stock_location_hierarchy"/> + </t> + </ul> + </li> + </template> + <record id="stock_location_view_form_editable" model="ir.ui.view"> <field name="name">stock.location.form.editable</field> <field name="model">stock.location</field> @@ -111,6 +158,8 @@ <field name="name">Locations</field> <field name="res_model">stock.location</field> <field name="type">ir.actions.act_window</field> + <field name="view_type">form</field> + <field name="view_mode">tree,form,qweb</field> <field name="view_id" ref="view_location_tree2"/> <field name="search_view_id" ref="view_location_search"/> <field name="context">{'search_default_in_location':1}</field> diff --git a/addons/stock/views/stock_template.xml b/addons/stock/views/stock_template.xml index 64561ddd527..54bad8cea54 100644 --- a/addons/stock/views/stock_template.xml +++ b/addons/stock/views/stock_template.xml @@ -11,7 +11,9 @@ <script type="text/javascript" src="/stock/static/src/js/inventory_validate_button_view.js"></script> <script type="text/javascript" src="/stock/static/src/js/stock_traceability_report_backend.js"></script> <script type="text/javascript" src="/stock/static/src/js/stock_traceability_report_widgets.js"></script> + <script type="text/javascript" src="/stock/static/src/js/stock_location_hierarchy.js"></script> <link rel="stylesheet" type="text/scss" href="/stock/static/src/scss/stock_traceability_report.scss"/> + <link rel="stylesheet" type="text/scss" href="/stock/static/src/scss/stock_location_hierarchy.scss"/> </xpath> </template> |
