Skip to content

Commit

Permalink
Merge pull request #206 from AtlasOfLivingAustralia/dev
Browse files Browse the repository at this point in the history
Preparing v6.1
  • Loading branch information
chrisala authored Aug 9, 2023
2 parents 09b3b67 + 923d14e commit 8b97853
Show file tree
Hide file tree
Showing 12 changed files with 368 additions and 213 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,20 @@ jobs:
uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b

- name: Run tests and jacoco coverage report with Gradle
uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee
uses: gradle/gradle-build-action@v2.4.2
with:
arguments: -PenableJacoco=true check

- name: Run javascript unit tests
run: node_modules/karma/bin/karma start karma.conf.js --single-run --browsers ChromeHeadless

- name: Clean to remove clover instrumentation
uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee
uses: gradle/gradle-build-action@v2.4.2
with:
arguments: clean

- name: Publish the JAR to the repository
uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee
uses: gradle/gradle-build-action@v2.4.2
with:
arguments: publish
env:
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ plugins {
}


version "6.0"
version "6.1-SNAPSHOT"
group "org.grails.plugins"

apply plugin:"eclipse"
Expand Down
101 changes: 83 additions & 18 deletions grails-app/assets/javascripts/forms-knockout-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,51 @@
}
};

function forceSelect2ToRespectPercentageTableWidths(element, percentageWidth) {
var $parentColumn = $(element).parent('td');
var $parentTable = $parentColumn.closest('table');
var resizeHandler = null;
if ($parentColumn.length) {
var select2 = $parentColumn.find('.select2-container');
function calculateWidth() {
var parentWidth = $parentTable.width();

// If the table has overflowed due to long selections then we need to try and find a parent div
// as the div won't have overflowed.
var windowWidth = window.innerWidth;
if (parentWidth > windowWidth) {
var parent = $parentTable.parent('div');
if (parent.length) {
parentWidth = parent.width();
}
else {
parentWidth = windowWidth;
}
}
var columnWidth = parentWidth*percentageWidth/100;

if (columnWidth > 10) {
select2.css('max-width', columnWidth+'px');
$(element).validationEngine('updatePromptsPosition');
}
else {
// The table is not visible yet, so wait a bit and try again.
setTimeout(calculateWidth, 200);
}
}
resizeHandler = function() {
clearTimeout(calculateWidth);
setTimeout(calculateWidth, 300);
};
$(window).on('resize', resizeHandler);

ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(window).off('resize', resizeHandler);
});
calculateWidth();
}

}
function applySelect2ValidationCompatibility(element) {
var $element = $(element);
var select2 = $element.next('.select2-container');
Expand Down Expand Up @@ -573,6 +618,12 @@
$element.trigger('change');
});
}
if (options.preserveColumnWidth) {
forceSelect2ToRespectPercentageTableWidths(element, options.preserveColumnWidth);
}
else {
applySelect2ValidationCompatibility(element);
}
}
};

Expand All @@ -586,33 +637,43 @@
};
var options = valueAccessor();
var model = options.value;

if (!ko.isObservable(model, ko.observableArray)) {
throw "The options require a key with name 'value' with a value of type ko.observableArray";
}

var constraints;
if (model.hasOwnProperty('constraints')) {
constraints = model.constraints;
}
else {
// Attempt to use the options binding to see if we can observe changes to the constraints
constraints = allBindings.get('options');
}

// Because constraints can be initialised by an AJAX call, constraints can be added after initialisation
// which can result in duplicate OPTIONS tags for pre-selected values, which confuses select2.
// Here we watch for changes to the model constraints and make sure any duplicates are removed.
if (model.hasOwnProperty('constraints')) {
if (ko.isObservable(model.constraints)) {
model.constraints.subscribe(function(val) {
var existing = {};
var duplicates = [];
var currentOptions = $(element).find("option").each(function() {
var val = $(this).val();
if (existing[val]) {
duplicates.push(this);
}
else {
existing[val] = true;
}
});
// Remove any duplicates
for (var i=0; i<duplicates.length; i++) {
element.removeChild(duplicates[i]);
if (constraints && ko.isObservable(constraints)) {

constraints.subscribe(function(val) {
var existing = {};
var duplicates = [];
var currentOptions = $(element).find("option").each(function() {
var val = $(this).val();
if (existing[val]) {
duplicates.push(this);
}
else {
existing[val] = true;
}
});
}
// Remove any duplicates
for (var i=0; i<duplicates.length; i++) {
element.removeChild(duplicates[i]);
}
});

}
delete options.value;
var options = _.defaults(valueAccessor() || {}, defaults);
Expand All @@ -621,6 +682,10 @@
model($(element).val());
});

if (options.preserveColumnWidth) {
forceSelect2ToRespectPercentageTableWidths(element, options.preserveColumnWidth);
}

applySelect2ValidationCompatibility(element);
},
update: function(element, valueAccessor) {
Expand Down
22 changes: 18 additions & 4 deletions grails-app/assets/javascripts/forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,10 +373,16 @@ function orEmptyArray(v) {
return ''.concat(result);
}

function evaluateUntyped(expression, context) {
var result = evaluateInternal(expression, context);
return result;
}

return {
evaluate: evaluateNumber,
evaluateBoolean: evaluateBoolean,
evaluateString: evaluateString
evaluateString: evaluateString,
evaluateUntyped: evaluateUntyped
}

}();
Expand Down Expand Up @@ -643,18 +649,26 @@ function orEmptyArray(v) {
var source = conf.source;
if (source.url) {
var url = (config.prepopUrlPrefix || window.location.href) + source.url;
var params = {};
var params = [];
_.each(source.params || [], function(param) {
var value;
if (param.type && param.type == 'computed') {
// evaluate the expression against the context.
value = ecodata.forms.expressionEvaluator.evaluateString(param.expression, context);
value = ecodata.forms.expressionEvaluator.evaluateUntyped(param.expression, context);
}
else {
// Treat it as a literal
value = param.value;
}
params[param.name] = value;
// Unroll the array to prevent jQuery appending [] to the array typed parameter name.
if (_.isArray(value)) {
for (var i=0; i<value.length; i++) {
params.push({name:param.name, value: value[i]});
}
}
else {
params.push({name:param.name, value: value});
}
});
return $.ajax(url, {data:params, dataType:source.dataType || 'json'});
}
Expand Down
11 changes: 5 additions & 6 deletions grails-app/assets/javascripts/knockout-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
* @param isInitiallyDirty
* @returns an object (function) with the methods 'isDirty' and 'reset'
*/
ko.dirtyFlag = function (root, isInitiallyDirty) {
ko.dirtyFlag = function (root, isInitiallyDirty, rateLimit) {
var result = function () {
};
var _isInitiallyDirty = ko.observable(isInitiallyDirty || false);
Expand All @@ -92,14 +92,13 @@
};
var _initialState = ko.observable(getRepresentation());

result.isDirty = ko.dependentObservable(function () {
result.isDirty = ko.pureComputed(function () {
var dirty = _isInitiallyDirty() || _initialState() !== getRepresentation();
/*if (dirty) {
console.log('Initial: ' + _initialState());
console.log('Actual: ' + getRepresentation());
}*/
return dirty;
});
if (rateLimit) {
result.isDirty = result.isDirty.extend({rateLimit: 500});
}

result.reset = function () {
_initialState(getRepresentation());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* This file overrides the default dropdown placement for select2 to support opening the dropdown on the right side
* of the select2 element. This is useful for select2 elements that are placed on the right side of the page.
* To use the right alignment, add the dropdown-right class to the select element with select2 binding applied.
*/
$.fn.select2.amd.require(["select2/utils",'select2/dropdown/attachBody'], function(Utils, AttachBody) {

AttachBody.prototype._positionDropdown = function () {
var $window = $(window);

var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');

var newDirection = null;

var offset = this.$container.offset();

offset.bottom = offset.top + this.$container.outerHeight(false);

var container = {
height: this.$container.outerHeight(false)
};

container.top = offset.top;
container.bottom = offset.top + container.height;

var dropdown = {
height: this.$dropdown.outerHeight(false)
};

var viewport = {
top: $window.scrollTop(),
bottom: $window.scrollTop() + $window.height()
};

var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);

var containerWidth = this.$container.outerWidth()
var right = ($("body").outerWidth() - (offset.left + containerWidth));

if (this.$element.hasClass("dropdown-right")) {
var css = {
right: right,
top: container.bottom
};
} else {
var css = {
left: offset.left,
top: container.bottom
};
}

// Determine what the parent element is to use for calciulating the offset
var $offsetParent = this.$dropdownParent;

// For statically positoned elements, we need to get the element
// that is determining the offset
if ($offsetParent.css('position') === 'static') {
$offsetParent = $offsetParent.offsetParent();
}

var parentOffset = $offsetParent.offset();

css.top -= parentOffset.top;
css.left -= parentOffset.left;

if (!isCurrentlyAbove && !isCurrentlyBelow) {
newDirection = 'below';
}

if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
newDirection = 'above';
} else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
newDirection = 'below';
}

if (newDirection == 'above' ||
(isCurrentlyAbove && newDirection !== 'below')) {
css.top = container.top - parentOffset.top - dropdown.height;
}

if (newDirection != null) {
this.$dropdown
.removeClass('select2-dropdown--below select2-dropdown--above')
.addClass('select2-dropdown--' + newDirection);
this.$container
.removeClass('select2-container--below select2-container--above')
.addClass('select2-container--' + newDirection);
}

this.$dropdownContainer.css(css);
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.grails.web.json.JSONObject
class ActivityFormService {

static final String ACTIVITY_FORM_PATH = '/activityForm'
static final String ACTIVITY_FORM_SEARCH_PATH = '/activityForm/search'
def webService
def grailsApplication

Expand Down Expand Up @@ -66,6 +67,21 @@ class ActivityFormService {
model
}

/**
* Returns a Map with keys: [resp:List<Map>, statusCode:<>]
* @param criteria Used to build a GORM criteria query, e.g. [category:'paratoo']
*/
Map searchActivityForms(Map criteria) {
String url = grailsApplication.config.getProperty('ecodata.service.url') +
ACTIVITY_FORM_SEARCH_PATH
Map result = webService.doPost(url, criteria)
if (!result || result.error) {
result = null
}

result
}

private Map missingForm(String name, Integer version) {
String message = "No activity form found with name ${name}"
if (version) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ class WebService {
def doPostWithParams(String url, Map params) {
[:]
}

def doPost(String url, Map params) {
[:]
}
}
Loading

0 comments on commit 8b97853

Please sign in to comment.