diff --git a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml index 3724ccc9e80c2cfefc2d07c9ce6184ee43b498a1..8117452b170ec0ee00577716d23f8e2d9ea15ea1 100644 --- a/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml +++ b/src/main/resources/META-INF/xnat/spawner/site-admin-elements.yaml @@ -491,12 +491,8 @@ passwords: name: passwordReuseRestriction label: Password Reuse Restriction options: - None: - label: None - value: None - Historical: - label: Historical - value: Historical + None: None + Historical: Historical passwordHistoryDuration: kind: panel.input.text id: passwordHistoryDuration @@ -789,7 +785,7 @@ pluginTable: dataModelBeans: label: Contents cells: - apply: JSON.stringify # function that accepts value as sole argument + apply: formatJSON # function that accepts value as sole argument html: > <a href="#!" class="view-plugin-info link">View Plugin Info</a> <div class="hidden plugin-json-string">__VALUE__</div> @@ -810,14 +806,14 @@ pluginTableScript: var _url = XNAT.url.restUrl('/xapi/plugins/' + _id); XNAT.xhr.getJSON(_url).done(function(data){ var _source = spawn('textarea', JSON.stringify(data, null, 4)); - XNAT.app.codeEditor.init(_source, { - language: 'json' - }).openEditor({ - title: 'Plugin Info', - classes: 'plugin-json', - footerContent: '(read-only)', - buttons: { close: { label: 'Close' } } - }); + XNAT.app.codeEditor.init(_source, { + language: 'json' + }).openEditor({ + title: 'Plugin Info', + classes: 'plugin-json', + footerContent: '(read-only)', + buttons: { close: { label: 'Close' } } + }); }); }); $body.on('focus', '.plugin-json textarea.ace_text-input', function(){ @@ -1195,6 +1191,8 @@ dicomScpReceivers: action: /xapi/dicomscp contentType: json contents: + pad: + tag: div.pad20top scpId: kind: panel.input.hidden id: scp-id diff --git a/src/main/webapp/scripts/globals.js b/src/main/webapp/scripts/globals.js index 86e852b64185759ad2b90f43d3195f6a59758d9b..5ca2b6b8a8f91e41fe8938106d11f1258d269dc4 100644 --- a/src/main/webapp/scripts/globals.js +++ b/src/main/webapp/scripts/globals.js @@ -127,6 +127,9 @@ function isEqual( a, b ){ function isEqualLower(a, b){ return isEqual(stringLower(a||''), stringLower(b||'')); } +function isFunction( func ){ + return typeof func == 'function'; +} function isObject( obj ){ // returns true for objects, arrays, and null return typeof obj == 'object'; @@ -142,7 +145,7 @@ function isEmptyObject( obj ){ return true; } function getObject( obj ){ - return isPlainObject(obj) ? obj : {}; + return (isPlainObject(obj) || isFunction(obj)) ? obj : {}; } function isArray( arr ){ if ( Array.isArray ) { @@ -177,9 +180,6 @@ function isEmpty( x, args ){ } return (x === null || isUndefined(x) || !isFunction(x)); } -function isFunction( func ){ - return typeof func == 'function'; -} function isNumber( num ){ return (typeof num == 'number' && !isNaN(num)); } @@ -1203,6 +1203,11 @@ function loadCSS( url, parent ){ parent.appendChild(scriptElement(url, min, name)); } +// basic indentation formatting only +function formatJSON(json, indent){ + return JSON.stringify(json, null, indent || 4); +} + function prettifyJSON(data, indent) { var json; if (typeof data != 'string') { diff --git a/src/main/webapp/scripts/xnat/admin/dicomScpManager.js b/src/main/webapp/scripts/xnat/admin/dicomScpManager.js index 695feb59d6630ab76166583fcf0d675da765d810..10885b22a6c53e560f0ee0eee9e1c517188ab1c5 100644 --- a/src/main/webapp/scripts/xnat/admin/dicomScpManager.js +++ b/src/main/webapp/scripts/xnat/admin/dicomScpManager.js @@ -209,23 +209,27 @@ var XNAT = getObject(XNAT || {}); // TODO: move event listeners to parent elements - events will bubble up // ^-- this will reduce the number of event listeners function enabledCheckbox(item){ + var ckbox = spawn('input.enabled', { + type: 'checkbox', + checked: !!item.enabled, + onchange: function(){ + // save the status when clicked + var enabled = this.checked; + XNAT.xhr.put({ + url: scpUrl(item.id + '/enabled/' + enabled), + success: function(){ + var status = (enabled ? ' enabled' : ' disabled'); + XNAT.ui.banner.top(1000, '<b>' + item.aeTitle + '</b> ' + status, 'success'); + console.log(item.id + (enabled ? ' enabled' : ' disabled')) + } + }); + } + }); return spawn('div.center', [ - ['input.enabled', { - type: 'checkbox', - checked: !!item.enabled, - onclick: function(){ - // save the status when clicked - var enabled = this.checked; - XNAT.xhr.put({ - url: scpUrl(item.id + '/enabled/' + enabled), - success: function(){ - var status = (enabled ? ' enabled' : ' disabled'); - XNAT.ui.banner.top(1000, '<b>' + item.aeTitle + '</b> ' + status, 'success'); - console.log(item.id + (enabled ? ' enabled' : ' disabled')) - } - }); - } - }] + spawn('label.switchbox', [ + ckbox, + ['span.switchbox-outer', [['span.switchbox-inner']]] + ]) ]); } diff --git a/src/main/webapp/scripts/xnat/event.js b/src/main/webapp/scripts/xnat/event.js index 804b29969e411fbb9d039adb4daa8e9ebc9add25..6534550b872f269b5b37395b512e00f41f6df04f 100644 --- a/src/main/webapp/scripts/xnat/event.js +++ b/src/main/webapp/scripts/xnat/event.js @@ -147,10 +147,3 @@ var XNAT = getObject(XNAT||{}); //////////////////////////////////////////////////////////// })(XNAT); - -function isPlainObject( obj ){ - return Object.prototype.toString.call(obj) === '[object Object]'; -} -function getObject( obj ){ - return isPlainObject(obj) ? obj : {}; -} diff --git a/src/main/webapp/scripts/xnat/validate.js b/src/main/webapp/scripts/xnat/validate.js index 7e4030c8831c3e5ba1996036c01d445678499fb5..b5dab661e86717e709ade2f2f6ccbc5ea325d154 100644 --- a/src/main/webapp/scripts/xnat/validate.js +++ b/src/main/webapp/scripts/xnat/validate.js @@ -111,10 +111,10 @@ var XNAT = getObject(XNAT); cronDay: /^((\*|\?|([0-9]|[1-2][0-9]|3[0-1]))(\/\d+)?)$/, cronMonth: /^((\*|\?|([0-9]|1[0-2]))(\/\d+)?)$/, cronMonths: /^(((\*|\?|([0-9]|1[0-2]))(\/\d+)?)|(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|DEC))$/i, - cronMonthNames: /^(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|DEC)$/i, + cronMonthNames: /^(\*|\?|JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|DEC)$/i, cronWeekday: /^((\*|\?|([0-7]))(\/\d+)?)$/, cronWeekdays: /^(((\*|\?|([0-7]))(\/\d+)?)|(MON|TUE|WED|THU|FRI|SAT|SUN))$/i, - cronWeekdayNames: /^(MON|TUE|WED|THU|FRI|SAT|SUN)$/i, + cronWeekdayNames: /^(\*|\?|MON|TUE|WED|THU|FRI|SAT|SUN)$/i, // cronAlt: /^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|([0-6])|\*\/([0-6]))$/, // cron regex lifted from this post: http://stackoverflow.com/questions/235504/validating-crontab-entries-w-php // cron: /^\s*($|#|\w+\s*=|(\*(?:\/\d+)?|(?:[0-5]?\d)(?:-(?:[0-5]?\d)(?:\/\d+)?)?(?:,(?:[0-5]?\d)(?:-(?:[0-5]?\d)(?:\/\d+)?)?)*)\s+(\*(?:\/\d+)?|(?:[01]?\d|2[0-3])(?:-(?:[01]?\d|2[0-3])(?:\/\d+)?)?(?:,(?:[01]?\d|2[0-3])(?:-(?:[01]?\d|2[0-3])(?:\/\d+)?)?)*)\s+(\*(?:\/\d+)?|(?:0?[1-9]|[12]\d|3[01])(?:-(?:0?[1-9]|[12]\d|3[01])(?:\/\d+)?)?(?:,(?:0?[1-9]|[12]\d|3[01])(?:-(?:0?[1-9]|[12]\d|3[01])(?:\/\d+)?)?)*)\s+(\*(?:\/\d+)?|(?:[1-9]|1[012])(?:-(?:[1-9]|1[012])(?:\/\d+)?)?(?:,(?:[1-9]|1[012])(?:-(?:[1-9]|1[012])(?:\/\d+)?)?)*|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+(\*(?:\/\d+)?|(?:[0-6])(?:-(?:[0-6])(?:\/\d+)?)?(?:,(?:[0-6])(?:-(?:[0-6])(?:\/\d+)?)?)*|mon|tue|wed|thu|fri|sat|sun)\s+|(@reboot|@yearly|@annually|@monthly|@weekly|@daily|@midnight|@hourly)\s+)([^\s]+)\s+(.*)$/, @@ -122,7 +122,7 @@ var XNAT = getObject(XNAT); }; // aliases regex.int = regex.integer; - regex.number = regex.numeric; + //regex.number = regex.numeric; regex.float = regex.decimal; regex.hex = regex.hexadecimal; regex.alphaNumeric = regex.alphaNum; @@ -147,7 +147,7 @@ var XNAT = getObject(XNAT); // define custom test methods for more complex validations var test = {}; - test.numeric = function(value){ + test.numeric = test.number = function(value){ console.log('numeric'); return isNumeric(value); }; @@ -176,98 +176,35 @@ var XNAT = getObject(XNAT); // match to 6-field cron syntax: // 0 0 * * * * - test.cronFn = function(value){ + test.cron = test.cronSyntax = function(value){ - // TODO: replace all this with regex tests + value = (value+'').trim(); - /* - var WORDS = ('reboot yearly annually monthly ' + - 'weekly daily midnight hourly').split(/\s+/).map(function(word){ - return '@' + word - }); - var MONTHS = ('JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC').split(/\s+/); - var DAYS = ('MON TUE WED THU FRI SAT SUN').split(/\s+/); - - // is it a special cron keyword? - if (WORDS.indexOf(value) > -1) { - return true + // easiest test - use words + if (regex.cronWords.test(value)) { + return true; } - // split passed value into separate fields - var FIELDS = (value+'').trim().split(/\s+/); - - // check for 6 fields - if (FIELDS.length < 6) { - return false - } + // split value to test parts + var parts = value.split(/\s+/); - var SECONDS = FIELDS[0].split('/'); - var MINUTES = FIELDS[1].split('/'); - var HOURS = FIELDS[2].split('/'); - var DAY = FIELDS[3]; - var MONTH = FIELDS[4]; - var WEEKDAY = FIELDS[5]; + // array of regexes to match 'parts' array + var tests = [ + regex.cronSeconds, + regex.cronMinutes, + regex.cronHours, + regex.cronDay, + regex.cronMonths, + regex.cronWeekdays + ]; var errors = 0; - function isWild(val){ - return /[*?/]/.test((val+'').trim()); - } - - function isRange(val){ - return /[a-z0-9]-[a-z0-9]/i.test(val) - } - - function isError(val, regex){ - var notWild = !isWild(val); - var notMatch = regex ? !regex.test(val) : false; - if (notWild && notMatch) { - errors++ - } - } - - function checkTime(val, limit, regex){ - - val = [].concat(val); - - var notWild = !isWild(val[0]); - - if (notWild){ - if (+val[0] < 0 || +val[0] > limit) { - isError(val, regex) - } - } - - // seconds interval must be a number - if (val[1] && !/[0-9]/.test(val[1])) { - errors++ - } - - } - - // seconds - checkTime(SECONDS, 59); - - // minutes - checkTime(MINUTES, 59); - - // hours - checkTime(HOURS, 23); - - // day - checkTime(DAY, 31); - - // month - var monthRegex = /JAN|FEB|MAR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC/i; - checkTime(MONTH, 12, monthRegex); - - // day of the week - var weekdayRegex = /MON|TUE|WED|THU|FRI|SAT|SUN/i; - checkTime(WEEKDAY, 7, weekdayRegex); - - return (errors === 0); + parts.forEach(function(part, i){ + errors = tests[i].test(part) ? 0 : errors + 1; + }); - */ + return errors === 0; }; @@ -347,6 +284,47 @@ var XNAT = getObject(XNAT); }; test.equals = test.equalTo; + // date checks + test.greaterThanDate = function(field, date){ + var enteredDate = getValidDate(field.value), + validDate = getValidDate(date); + if (!validDate || !enteredDate) { + return false; + } + return enteredDate > validDate; + }; + test.gtDate = test.greaterThanDate; + test.greaterThanOrEqualDate = function(field, date){ + var enteredDate = getValidDate(field.value), + validDate = getValidDate(date); + if (!validDate || !enteredDate) { + return false; + } + return enteredDate >= validDate; + }; + test.greaterThanOrEqualToDate = test.greaterThanOrEqualDate; + test.gteDate = test.greaterThanOrEqualDate; + test.lessThanDate = function(field, date){ + var enteredDate = getValidDate(field.value), + validDate = getValidDate(date); + if (!validDate || !enteredDate) { + return false; + } + return enteredDate < validDate; + }; + test.ltDate = test.lessThanDate; + test.lessThanOrEqualDate = function(field, date){ + var enteredDate = getValidDate(field.value), + validDate = getValidDate(date); + if (!validDate || !enteredDate) { + return false; + } + return enteredDate <= validDate; + }; + test.lessThanOrEqualToDate = test.lessThanOrEqualDate; + test.lteDate = test.lessThanOrEqualDate; + + // XNAT.validate('input.credit-card').is('creditCard').check(); test.creditCard = function(value){ // Luhn Check Code from https://gist.github.com/4075533 @@ -429,9 +407,16 @@ var XNAT = getObject(XNAT); return obj; } + // TODO: get this working function getValidDate(date){ - if (!date.match('today') && !date.match(regex[date])) { + var regexDateMatch = ( + date.match(regex['dateISO']) || + date.match(regex['dateUS']) || + date.match(regex['dateEU']) + ); + + if (!date.match('today') && !regexDateMatch) { return false; } @@ -439,7 +424,7 @@ var XNAT = getObject(XNAT); validDateArray; if (!date.match('today')) { - validDateArray = date.split(/[\s.-]+/); + validDateArray = date.split(/[\s.-/]+/); validDate.setFullYear(validDateArray[0]); validDate.setMonth(validDateArray[1] - 1); validDate.setDate(validDateArray[2]); diff --git a/src/main/webapp/style/app.css b/src/main/webapp/style/app.css index 67b911efcee3d86b9a5445617ca7f111c0885126..557c85704bc51a023aa03eedb45417961e17b387 100644 --- a/src/main/webapp/style/app.css +++ b/src/main/webapp/style/app.css @@ -3725,5 +3725,13 @@ textarea.xml-formatted { .pad5h { padding-left: 5px; padding-right: 5px; } .pad10h { padding-left: 10px; padding-right: 10px; } .pad20h { padding-left: 20px; padding-right: 20px; } +.pad1v { padding-top: 1px; padding-bottom: 1px; } +.pad5v { padding-top: 5px; padding-bottom: 5px; } +.pad10v { padding-top: 10px; padding-bottom: 10px; } +.pad20v { padding-top: 20px; padding-bottom: 20px; } +.pad1top, .pad-top-1 { padding-top: 5px; } +.pad5top, .pad-top-5 { padding-top: 5px; } +.pad10top, .pad-top-10 { padding-top: 10px; } +.pad20top, .pad-top-20 { padding-top: 20px; } .inline { display: inline }