Skip to content

Commit

Permalink
Add Sample Form: Save and Copy Action (senaite#2123)
Browse files Browse the repository at this point in the history
* Handle Save&Copy action

* Implemented JS logic

* Added sample action

* Changelog added

* Comment only
  • Loading branch information
ramonski authored Sep 8, 2022
1 parent edc6a53 commit ff07a9f
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changelog
2.3.0 (unreleased)
------------------

- #2123 Add Sample Form: Save and Copy Action
- #2119 Fix linked client contact user can not see existing samples
- #2118 Customized Quickinstaller Configlet
- #2117 Customized User/Groups Preferences in Site Configuration
Expand Down
40 changes: 33 additions & 7 deletions src/bika/lims/browser/analysisrequest/add2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1514,8 +1514,15 @@ def check_confirmation(self):
records = self.get_records()
return adapter.check_confirmation(records)

def ajax_cancel(self):
"""Cancel and redirect to configured actions
"""
message = _("Sample creation cancelled")
self.context.plone_utils.addPortalMessage(message, "info")
return self.handle_redirect([], message)

def ajax_submit(self):
"""Submit & create the ARs
"""Create samples and redirect to configured actions
"""
# Check if there is the need to display a confirmation pane
confirmation = self.check_confirmation()
Expand Down Expand Up @@ -1677,23 +1684,42 @@ def ajax_submit(self):
# Display a portal message
self.context.plone_utils.addPortalMessage(message, level)

return self.handle_redirect(ARs.values(), message)

def handle_redirect(self, uids, message):
"""Handle redirect after sample creation or cancel
"""
# Automatic label printing
setup = api.get_setup()
auto_print = setup.getAutoPrintStickers()
immediate_results_entry = setup.getImmediateResultsEntry()
redirect_to = self.context.absolute_url()
sample_uids = ARs.values()
if "register" in auto_print and sample_uids:

# UIDs of the new created samples
sample_uids = ",".join(uids)
# UIDs of previous created samples when save&copy was selected
prev_sample_uids = self.request.get("sample_uids")
if prev_sample_uids:
sample_uids = ",".join([prev_sample_uids, sample_uids])
# Get the submit action (either "Save" or "Save and Copy")
submit_action = self.request.form.get("submit_action", "save")
if submit_action == "save_and_copy":
# redirect to the sample add form, but keep track of
# previous created sample UIDs
redirect_to = "{}/ar_add?copy_from={}&ar_count={}&sample_uids={}" \
.format(self.context.absolute_url(),
",".join(uids), # copy_from
len(uids), # ar_count
sample_uids) # sample_uids
elif "register" in auto_print and sample_uids:
redirect_to = "{}/sticker?autoprint=1&template={}&items={}".format(
self.context.absolute_url(),
setup.getAutoStickerTemplate(),
",".join(sample_uids)
)
sample_uids)
elif immediate_results_entry and sample_uids:
redirect_to = "{}/multi_results?uids={}".format(
self.context.absolute_url(),
",".join(sample_uids)
)
sample_uids)
return {
"success": message,
"redirect_to": redirect_to,
Expand Down
20 changes: 19 additions & 1 deletion src/bika/lims/browser/analysisrequest/templates/ar_add2.pt
Original file line number Diff line number Diff line change
Expand Up @@ -652,14 +652,32 @@

</table>

<input class="btn btn-success btn-sm allowMultiSubmit"
<input class="btn btn-success btn-sm"
type="submit"
name="save_button"
i18n:attributes="value"
value="Save"/>

<input class="btn btn-outline-success btn-sm"
type="submit"
name="save_and_copy_button"
i18n:attributes="value"
value="Save and Copy"/>

<input class="btn btn-outline-secondary btn-sm"
type="submit"
name="cancel_button"
i18n:attributes="value"
value="Cancel"/>

<input type="hidden" id="confirmed" name="confirmed" value="0"/>

<!-- The input[type=submit] fields are not included in the request when submitting via JS.
Therefore, we set the action explicitly in the ajax event handler -->
<input type="hidden" name="submit_action" value="save"/>
<!-- List of previous created sample UIDs from copy&save cycles -->
<input type="hidden" name="sample_uids" value="" tal:attributes="value request/sample_uids|nothing"/>

</form>
<!-- /ADD Form -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
this.set_service_conditions = bind(this.set_service_conditions, this);
this.init_file_fields = bind(this.init_file_fields, this);
this.on_form_submit = bind(this.on_form_submit, this);
this.on_cancel = bind(this.on_cancel, this);
this.on_ajax_end = bind(this.on_ajax_end, this);
this.on_ajax_start = bind(this.on_ajax_start, this);
this.ajax_post_form = bind(this.ajax_post_form, this);
Expand Down Expand Up @@ -91,6 +92,8 @@
$("body").on("click", ".service-listing-header", this.on_service_listing_header_click);
$("body").on("click", "tr.category", this.on_service_category_click);
$("body").on("click", "[name='save_button']", this.on_form_submit);
$("body").on("click", "[name='save_and_copy_button']", this.on_form_submit);
$("body").on("click", "[name='cancel_button']", this.on_cancel);
$("body").on("click", "tr[fieldname=Composite] input[type='checkbox']", this.recalculate_records);
$("body").on("click", "tr[fieldname=InvoiceExclude] input[type='checkbox']", this.recalculate_records);
$("body").on("click", "tr[fieldname=Analyses] input[type='checkbox'].analysisservice-cb", this.on_analysis_checkbox_click);
Expand Down Expand Up @@ -1326,27 +1329,49 @@
/*
* Ajax request started
*/
var button;
var save_and_copy_button, save_button;
console.debug("°°° on_ajax_start °°°");
button = $("input[name=save_button]");
button.prop({
save_button = $("input[name=save_button]");
save_button.prop({
"disabled": true
});
save_button[0].value = _t("Loading ...");
save_and_copy_button = $("input[name=save_and_copy_button]");
return save_and_copy_button.prop({
"disabled": true
});
return button[0].value = _t("Loading ...");
};

AnalysisRequestAdd.prototype.on_ajax_end = function() {

/*
* Ajax request finished
*/
var button;
var save_and_copy_button, save_button;
console.debug("°°° on_ajax_end °°°");
button = $("input[name=save_button]");
button.prop({
save_button = $("input[name=save_button]");
save_button.prop({
"disabled": false
});
save_button[0].value = _t("Save");
save_and_copy_button = $("input[name=save_and_copy_button]");
return save_and_copy_button.prop({
"disabled": false
});
return button[0].value = _t("Save");
};

AnalysisRequestAdd.prototype.on_cancel = function(event, callback) {
var base_url;
console.debug("°°° on_cancel °°°");
event.preventDefault();
base_url = this.get_base_url();
return this.ajax_post_form("cancel").done(function(data) {
if (data["redirect_to"]) {
return window.location.replace(data["redirect_to"]);
} else {
return window.location.replace(base_url);
}
});
};

AnalysisRequestAdd.prototype.on_form_submit = function(event, callback) {
Expand All @@ -1355,10 +1380,17 @@
* Eventhandler for the form submit button.
* Extracts and submits all form data asynchronous.
*/
var base_url, me, portal_url;
var action, action_input, base_url, btn, me, portal_url;
console.debug("°°° on_form_submit °°°");
event.preventDefault();
me = this;
btn = event.currentTarget;
action = "save";
if (btn.name === "save_and_copy_button") {
action = "save_and_copy";
}
action_input = document.querySelector("input[name='submit_action']");
action_input.value = action;
base_url = me.get_base_url();
portal_url = me.get_portal_url();
$("div.error").removeClass("error");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ class window.AnalysisRequestAdd
$("body").on "click", "tr.category", @on_service_category_click
# Save button clicked
$("body").on "click", "[name='save_button']", @on_form_submit
# Save and copy button clicked
$("body").on "click", "[name='save_and_copy_button']", @on_form_submit
# Cancel button clicked
$("body").on "click", "[name='cancel_button']", @on_cancel
# Composite Checkbox clicked
$("body").on "click", "tr[fieldname=Composite] input[type='checkbox']", @recalculate_records
# InvoiceExclude Checkbox clicked
Expand Down Expand Up @@ -1327,10 +1331,14 @@ class window.AnalysisRequestAdd
###
console.debug "°°° on_ajax_start °°°"

# deactivate the button
button = $("input[name=save_button]")
button.prop "disabled": yes
button[0].value = _t("Loading ...")
# deactivate the save button
save_button = $("input[name=save_button]")
save_button.prop "disabled": yes
save_button[0].value = _t("Loading ...")

# deactivate the save and copy button
save_and_copy_button = $("input[name=save_and_copy_button]")
save_and_copy_button.prop "disabled": yes


on_ajax_end: =>
Expand All @@ -1339,10 +1347,26 @@ class window.AnalysisRequestAdd
###
console.debug "°°° on_ajax_end °°°"

# reactivate the button
button = $("input[name=save_button]")
button.prop "disabled": no
button[0].value = _t("Save")
# reactivate the save button
save_button = $("input[name=save_button]")
save_button.prop "disabled": no
save_button[0].value = _t("Save")

# reactivate the save and copy button
save_and_copy_button = $("input[name=save_and_copy_button]")
save_and_copy_button.prop "disabled": no


on_cancel: (event, callback) =>
console.debug "°°° on_cancel °°°"
event.preventDefault()
base_url = this.get_base_url()

@ajax_post_form("cancel").done (data) ->
if data["redirect_to"]
window.location.replace data["redirect_to"]
else
window.location.replace base_url


# Note: Context of callback bound to this object
Expand All @@ -1355,6 +1379,15 @@ class window.AnalysisRequestAdd
event.preventDefault()
me = this

# The clicked submit button is not part of the form data, therefore,
# we pass the name of the button through a hidden field
btn = event.currentTarget
action = "save"
if btn.name == "save_and_copy_button"
action = "save_and_copy"
action_input = document.querySelector("input[name='submit_action']")
action_input.value = action

# get the right base url
base_url = me.get_base_url()

Expand Down

0 comments on commit ff07a9f

Please sign in to comment.