Skip to content

Commit

Permalink
Allow manual reordering of report samples (#135)
Browse files Browse the repository at this point in the history
* Allow listing table reordering

* Added event handler for listing table reordering

* Added configuration setting for auto reloading

* Removed unused import

* Pass in the config value to the impress controller

* Added upgrade step

* Allow row reordering

* Bind the event handler on the listing root element

* Changelog updated

* Added sample point column

* Return the title or ID for the sample point

* Reomve old layer to make room for the new one

---------

Co-authored-by: Jordi Puiggené <jp@naralabs.com>
  • Loading branch information
ramonski and xispa authored Feb 14, 2023
1 parent eb30909 commit e238025
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/Changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
------------------

- #136 Change default browserlayer
- #135 Allow manual reordering of report samples
- #134 Convert impress header table to senaite.app.listing
- #133 Refactor publish view controls and content table to viewlets
- #132 Add custom action provider for direct PDF sharing via email
Expand Down
1 change: 1 addition & 0 deletions src/senaite/impress/ajax.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ def ajax_config(self):
"format": self.get_default_paperformat(),
"orientation": self.get_default_orientation(),
"template": self.get_default_template(),
"reload_after_reorder": self.get_reload_after_reorder(),
"allow_save": self.get_allow_publish_save(),
"allow_email": self.get_allow_publish_email(),
"custom_actions": custom_actions,
Expand Down
15 changes: 15 additions & 0 deletions src/senaite/impress/browser/publish/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def __init__(self, context, request):
self.show_workflow_action_buttons = False
self.show_table_footer = False
self.omit_form = True
self.allow_row_reorder = True

# Show categories
self.categories = []
Expand All @@ -49,6 +50,10 @@ def __init__(self, context, request):
"title": _("Sample Type"),
"sortable": False,
"toggle": True}),
("SamplePoint", {
"title": _("Sample Point"),
"sortable": False,
"toggle": True}),
("created", {
"title": _("Registered"),
"sortable": False,
Expand Down Expand Up @@ -185,6 +190,16 @@ def _folder_item_sample(self, obj, item):
return
item["SampleType"] = obj.getSampleTypeTitle()

# sample point
sp = obj.getSamplePoint()
if sp:
sp_id = api.get_id(sp)
sp_title = api.get_title(sp)
sp_url = api.get_url(sp)
item["SamplePoint"] = api.get_title(sp)
item["replace"]["SamplePoint"] = get_link(
sp_url, value=sp_title or sp_id, target="_blank")

client = obj.getClient()
client_url = api.get_url(client)
client_id = client.getClientID()
Expand Down

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/senaite/impress/browser/static/resources.pt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/jquery/jquery.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/popperjs/popper.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/bootstrap/js/bootstrap.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/react/react.production.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/react-dom/react-dom.production.min.js"></script><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}/++plone++senaite.impress.static/modules/fontawesome-free/css/all.min.css"/><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/thirdparty/jquery-barcode-2.2.0.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/thirdparty/jquery-qrcode-0.17.0.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/thirdparty/d3.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/js/bika.lims.graphics.range.js"></script><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}/++plone++senaite.impress.static/css/bootstrap.min.css"/><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}/++plone++senaite.impress.static/css/bootstrap-print.css"/><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}/++plone++senaite.impress.static/css/print.css"/><script tal:attributes="src string:${view/site_url}//++plone++senaite.impress.static/bundles/senaite.impress.js"></script><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}//++plone++senaite.impress.static/bundles/senaite.impress.css"/>
<script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/jquery/jquery.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/popperjs/popper.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/bootstrap/js/bootstrap.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/bootstrap-confirmation2/bootstrap-confirmation.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/bootstrap-select/js/bootstrap-select.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/react/react.production.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/modules/react-dom/react-dom.production.min.js"></script><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}/++plone++senaite.impress.static/modules/fontawesome-free/css/all.min.css"/><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/thirdparty/jquery-barcode-2.2.0.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/thirdparty/jquery-qrcode-0.17.0.min.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/thirdparty/d3.js"></script><script tal:attributes="src string:${view/site_url}/++plone++senaite.core.static/js/bika.lims.graphics.range.js"></script><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}/++plone++senaite.impress.static/css/bootstrap.min.css"/><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}/++plone++senaite.impress.static/css/bootstrap-print.css"/><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}/++plone++senaite.impress.static/css/print.css"/><script tal:attributes="src string:${view/site_url}//++plone++senaite.impress.static/bundles/senaite.impress.js"></script><link href="#" rel="stylesheet" tal:attributes="href string:${view/site_url}//++plone++senaite.impress.static/bundles/senaite.impress.css"/>
8 changes: 8 additions & 0 deletions src/senaite/impress/controlpanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ class IImpressControlPanel(Interface):
required=False,
)

reload_after_reorder = schema.Bool(
title=_(u"Reload after reorder"),
description=_(u"Reload report automatically when items order changed"),
default=False,
required=False,
)

###
# Fieldsets
###
Expand All @@ -132,6 +139,7 @@ class IImpressControlPanel(Interface):
label=_(u"Advanced"),
# description=_(""),
fields=[
"reload_after_reorder",
"allow_pdf_download",
"allow_pdf_email_share",
"store_multireports_individually",
Expand Down
2 changes: 1 addition & 1 deletion src/senaite/impress/profiles/default/metadata.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<metadata>
<version>2403</version>
<version>2404</version>
</metadata>
11 changes: 10 additions & 1 deletion src/senaite/impress/publishview.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from six.moves.collections_abc import Iterable

from bika.lims import api
from bika.lims.permissions import TransitionPublishResults
from plone.resource.utils import iterDirectoriesOfType
from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
Expand Down Expand Up @@ -407,6 +406,16 @@ def is_printview(self):
return True
return False

def get_reload_after_reorder(self, default=False):
"""Check if auto reloading after reordering is enabled
"""
# lookup configuration settings
reload_after_reorder = api.get_registry_record(
"senaite.impress.reload_after_reorder")
if reload_after_reorder is None:
return default
return reload_after_reorder

def get_allow_pdf_download(self, default=False):
"""Check if direct PDF download is allowed
"""
Expand Down
11 changes: 11 additions & 0 deletions src/senaite/impress/upgrades/v02_04_000.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-

from plone.browserlayer.utils import unregister_layer
from senaite.impress import logger

PROFILE_ID = "profile-senaite.impress:default"
Expand Down Expand Up @@ -32,5 +33,15 @@ def import_browserlayer(tool):
:param tool: portal_setup tool
"""
logger.info("Import SENAITE IMPRESS browser layer ...")

# ensure the old layer is removed first to make room for the new one
try:
unregister_layer("senaite.impress")
except KeyError:
# KeyError: 'No browser layer with name senaite.impress is registered
pass

# reimport browser layer to register ISenaiteImpressLayer
tool.runImportStepFromProfile(PROFILE_ID, "browserlayer")

logger.info("Import SENAITE IMPRESS browser layer [DONE]")
8 changes: 8 additions & 0 deletions src/senaite/impress/upgrades/v02_04_000.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,12 @@
handler="senaite.impress.upgrades.v02_04_000.import_browserlayer"
profile="senaite.impress:default"/>

<genericsetup:upgradeStep
title="SENAITE IMPRESS 2.4.0: Import registry"
description="Import registry profile for controlpanel settings"
source="2403"
destination="2404"
handler="senaite.impress.upgrades.v02_04_000.import_registry"
profile="senaite.impress:default"/>

</configure>
32 changes: 32 additions & 0 deletions webpack/app/senaite.impress.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class PublishController extends React.Component
@handleModalSubmit = @handleModalSubmit.bind(this)
@loadReports = @loadReports.bind(this)
@saveReports = @saveReports.bind(this)
@on_row_order_change = @on_row_order_change.bind(this)
# Rendered by the listing viewlet
@listing_el = document.getElementById("impress-contents-table")

@state =
items: @api.get_items()
Expand All @@ -59,6 +62,8 @@ class PublishController extends React.Component
allow_save: yes
allow_email: yes
custom_actions: []
reload_after_reorder: no
reload_required: no

window.impress = @

Expand All @@ -80,13 +85,18 @@ class PublishController extends React.Component

componentDidMount: ->
console.debug "PublishController::componentDidMount"
@listing_el.addEventListener("listing:row_order_change", @on_row_order_change, false);

@api.fetch_config().then (
(config) ->
@setState config, @loadReports
).bind(this)


componentWillUnmount: ->
@listing_el.removeEventListener("listing:row_order_change", @on_row_order_change, false);


getRequestOptions: ->
###
* Options to be sent to the server
Expand Down Expand Up @@ -134,6 +144,7 @@ class PublishController extends React.Component
error: ""
loading: yes
loadtext: "Loading Reports..."
reload_required: no

# fetch the rendered reports via the API asynchronously
promise = @api.render_reports @getRequestOptions()
Expand Down Expand Up @@ -438,9 +449,30 @@ class PublishController extends React.Component
return @postAction url


###
* Event handler when the object order was changed in the listing table
*
* @param {CustomEvent} event: provides the current `folderitems` of the listing
###
on_row_order_change: (event) ->
uids = event.detail.folderitems.map (item) => item.uid

if @state.reload_after_reorder
@setState items: uids, @loadReports
else
@setState items: uids, reload_required: yes


render: ->
<div className="col-sm-12">
<Modal className="modal fade" id="impress_modal" />
{@state.reload_required and
<div className="alert alert-warning">
<h4 className="alert-heading">
<span className="mr-2">Reload is required</span>
<Button name="reload" title="" onClick={@loadReports} className="btn btn-sm btn-outline-success" />
</h4>
</div>}
<form name="publishform" onSubmit={this.handleSubmit}>
<div className="form-group">
<div className="input-group">
Expand Down

0 comments on commit e238025

Please sign in to comment.