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 c8d7d9e5533efbb11c62737abe224b51da677d7a..84bcb3dc5c485cf07665a5e522e0b8152492207d 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 @@ -38,7 +38,7 @@ siteDescriptionPage: label: " " description: "Specify a velocity template file to display on the login page" siteDescriptionText: - kind: panel.input.text + kind: panel.textarea id: siteDescriptionText name: siteDescriptionText label: " " @@ -68,7 +68,7 @@ siteUrl: id: siteUrl name: siteUrl label: Site Url - validation: required id onblur + validation: required id description: "" adminEmail: kind: panel.input.email @@ -90,29 +90,33 @@ archiveRootPath: id: archiveRootPath name: archiveRootPath label: Archive Root Path - validation: required id onblur + validation: required path description: "" + value: ??XNAT.data.siteConfig.archiveRootPath cachePath: kind: panel.input.text id: cachePath name: cachePath label: Cache Path - validation: required id onblur + validation: required path description: "" + value: ??XNAT.data.siteConfig.cachePath prearchivePath: kind: panel.input.text id: prearchivePath name: prearchivePath label: Prearchive Path - validation: required id onblur + validation: required path description: "" + value: ??XNAT.data.siteConfig.prearchivePath ftpPath: kind: panel.input.text id: ftpPath name: ftpPath label: FTP Path - validation: required id onblur + validation: required path description: "" + value: ??XNAT.data.siteConfig.cachePath buildPath: kind: panel.input.text id: buildPath @@ -120,6 +124,7 @@ buildPath: label: Build Path validation: required id onblur description: "" + value: ??XNAT.data.siteConfig.cachePath pipelinePath: kind: panel.input.text id: pipelinePath @@ -127,6 +132,7 @@ pipelinePath: label: Pipeline Path validation: required id onblur description: "" + value: ??XNAT.data.siteConfig.cachePath dataFolders: kind: panel.input.text id: dataFolders @@ -181,13 +187,10 @@ generalSecuritySettings: label: Security Channel value: https options: - http: - label: http - value: http - https: - label: https - value: https - config: + # value: label # <- simplest setup + http: http + https: https + element: id: security-channel title: Security Channel requireUserLogin: @@ -201,6 +204,11 @@ userLoginsSessionControls: kind: panel.form name: userLoginsSessionControls label: User Logins / Session Controls + method: POST + action: /xapi/siteConfig/batch + load: + lookup: XNAT.data.siteConfig + refresh: /xapi/siteConfig contents: sessionTimeout: kind: panel.input.number diff --git a/src/main/webapp/page/admin/data/config/site-setup.yaml b/src/main/webapp/page/admin/data/config/site-setup.yaml index ad2562ed05166ac886608f8e84ad8fb35faead12..073f8461e9cc245db4c4f3be44218a52b4169d6c 100644 --- a/src/main/webapp/page/admin/data/config/site-setup.yaml +++ b/src/main/webapp/page/admin/data/config/site-setup.yaml @@ -142,36 +142,36 @@ initialSetup: kind: panel.input.text name: host label: Host - value: ?|XNAT.data.siteConfig.smtpServer.host + value: ?? XNAT.data.siteConfig.smtpServer.host placeholder: localhost port: kind: panel.input.number name: port label: Port - value: ?|XNAT.data.siteConfig.smtpServer.port + value: ?? XNAT.data.siteConfig.smtpServer.port placeholder: 25 username: kind: panel.input.text name: username label: Username - value: ?|XNAT.data.siteConfig.smtpServer.username + value: ?? XNAT.data.siteConfig.smtpServer.username password: kind: panel.input.password name: password label: Password - value: ?|XNAT.data.siteConfig.smtpServer.password + value: ?? XNAT.data.siteConfig.smtpServer.password protocol: kind: panel.input.text name: protocol label: Protocol - value: ?|XNAT.data.siteConfig.smtpServer.protocol + value: ?? XNAT.data.siteConfig.smtpServer.protocol mailServerProperties: - kind: panel.input.group + kind: panel.section name: mailServerProperties label: Mail Server Settings contents: @@ -194,4 +194,4 @@ initialSetup: kind: panel.input.text name: mail.smtp.ssl.trust label: SSL Trust - value: ?|XNAT.data.siteConfig.smtpServer['mail.smtp.ssl.trust'] + value: ?? XNAT.data.siteConfig.smtpServer['mail.smtp.ssl.trust'] diff --git a/src/main/webapp/scripts/globals.js b/src/main/webapp/scripts/globals.js index 42efbd168c7b2dde85c1fc35e946481b5cffd9fa..032b900554c3159b71372375641b0b55db78261e 100644 --- a/src/main/webapp/scripts/globals.js +++ b/src/main/webapp/scripts/globals.js @@ -270,7 +270,7 @@ function extendCopyDeep(){ // return a cloned copy of a single 'obj' function cloneObject(obj){ - return extend(true, {}, obj); + return extend(true, {}, obj || {}); } // add child objects to 'obj' object from string diff --git a/src/main/webapp/scripts/lib/jquery-plugins/jquery.dataAttr.js b/src/main/webapp/scripts/lib/jquery-plugins/jquery.dataAttr.js index c002e2878696ae007d9d77d864d4158633a64326..0728d1217b0ab52533844aa14dc7cac97a15ec28 100644 --- a/src/main/webapp/scripts/lib/jquery-plugins/jquery.dataAttr.js +++ b/src/main/webapp/scripts/lib/jquery-plugins/jquery.dataAttr.js @@ -16,7 +16,7 @@ * jQuery().data().name values override * element.dataset.name properties. * @param {string} name - Name of [data-] attribute - * @param {string|array|object|function} value - The value to assign to name + * @param {string|array|object|function} [value] - The value to assign to name * @return {object} * Returns object map of data attributes and values * OR the jQuery object .dataAttr() was called on diff --git a/src/main/webapp/scripts/xnat/ui/input.js b/src/main/webapp/scripts/xnat/ui/input.js index 8e3451e9561ffa96a9bd0ef4a685d1b779f23818..737e31ad144827582630db4b56e70988b03fd4a0 100644 --- a/src/main/webapp/scripts/xnat/ui/input.js +++ b/src/main/webapp/scripts/xnat/ui/input.js @@ -28,6 +28,39 @@ var XNAT = getObject(XNAT); // as methods and properties to the function input_ = XNAT.ui.input || {}; + function lookupValue(el, lookup){ + var val = ''; + try { + val = eval(lookup.trim()) + } + catch (e) { + val = ''; + console.log(e); + } + el.value = val; + return val; + } + + function lookupObjectValue(root, objStr){ + var val = ''; + if (!objStr) { + objStr = root; + root = window; + } + root = root || window; + objStr.toString().trim().split('.').forEach(function(part, i){ + part = part.trim(); + // start at the root object + if (i === 0) { + val = root[part] || {}; + } + else { + val = val[part]; + } + }); + return val; + } + // ======================================== // MAIN FUNCTION @@ -40,6 +73,16 @@ var XNAT = getObject(XNAT); } config = getObject(config); config.type = type || config.type || 'text'; + // lookup a value if it starts with '??' + var doLookup = '??'; + if (config.value && config.value.toString().indexOf(doLookup) === 0) { + config.value = lookupObjectValue(config.value.split(doLookup)[1]) + } + // lookup a value from a namespaced object + // if no value is given + if (!config.value && config.data && config.data.lookup) { + config.value = lookupObjectValue(config.data.lookup) + } var spawned = spawn('input', config); return { element: spawned, @@ -93,6 +136,16 @@ var XNAT = getObject(XNAT); // save a list of all available input types input.types = [].concat(textTypes, numberTypes, otherTypes); + // after the page is finished loading, set empty + // input values from [data-lookup] attribute + $(window).load(function(){ + $(':input[data-lookup]').each(function(){ + var $input = $(this); + var val = lookupObjectValue($input.dataAttr('lookup')); + $input.changeVal(val); + }); + }); + // add back items that may have been on // a global XNAT.ui.input object or function extend(input, input_); diff --git a/src/main/webapp/scripts/xnat/ui/panel.js b/src/main/webapp/scripts/xnat/ui/panel.js index 561bb6e5ac91bb333f43cc60c1c75151bbc37828..6753bcdaf4e9d8cc65c0bc94e5fb66d0b773a326 100644 --- a/src/main/webapp/scripts/xnat/ui/panel.js +++ b/src/main/webapp/scripts/xnat/ui/panel.js @@ -32,9 +32,48 @@ var XNAT = getObject(XNAT || {}); return obj.data; } + // another way to do this without using eval() + // is to loop over object string using dot notation: + // var myVal = lookupObjectValue(XNAT, 'data.siteConfig.siteId'); + // --> myVal == 'myXnatSiteId' + function lookupObjectValue(root, objStr){ + var val = ''; + if (!objStr) { + objStr = root; + root = window; + } + root = root || window; + objStr.toString().trim().split('.').forEach(function(part, i){ + // start at the root object + if (i === 0) { + val = root[part] || {}; + } + else { + val = val[part]; + } + }); + return val; + } + + // string that indicates to look for a namespaced object value + var doLookupString = '??'; + + function doLookup(input){ + if (!input) return ''; + if (input.toString().trim().indexOf(doLookupString) === 0){ + return lookupObjectValue(window, input.split(doLookupString)[1]); + } + return input; + } + + /** + * Initialize panel. + * @param [opts] {Object} Config object + * @returns {{}} + */ panel.init = function panelInit(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.element = opts.element || opts.config || {}; var _target = spawn('div.panel-body', opts.element), @@ -68,11 +107,10 @@ var XNAT = getObject(XNAT || {}); } }; - // creates a panel that's a form that can be submitted panel.form = function panelForm(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.element = opts.element || opts.config || {}; var _target = spawn('div.panel-body', opts.element), @@ -140,7 +178,7 @@ var XNAT = getObject(XNAT || {}); obj = opts.load || {}; } - obj = extend(true, {}, obj); + obj = cloneObject(obj); obj.form = obj.form || obj.target || obj.element || _formPanel; @@ -321,7 +359,7 @@ var XNAT = getObject(XNAT || {}); // creates a panel that submits all forms contained within panel.multiForm = function(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.element = opts.element || opts.config || {}; var inner = spawn('div.panel-body', opts.element), @@ -407,7 +445,7 @@ var XNAT = getObject(XNAT || {}); panel.element = function(opts){ var _element, _inner = [], _target; - opts = getObject(opts); + opts = cloneObject(opts); opts.element = opts.element || opts.config || {}; if (opts.id || opts.element.id) { opts.element.id = (opts.id || opts.element.id) + '-element'; @@ -443,7 +481,7 @@ var XNAT = getObject(XNAT || {}); }; panel.subhead = function(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.html = opts.html || opts.text || opts.label; return XNAT.ui.template.panelSubhead(opts).spawned; }; @@ -453,7 +491,7 @@ var XNAT = getObject(XNAT || {}); var _section, _inner = [], _body; - opts = getObject(opts); + opts = cloneObject(opts); opts.element = opts.element || opts.config || {}; opts.header = opts.header || opts.label || opts.title || ''; @@ -495,34 +533,34 @@ var XNAT = getObject(XNAT || {}); }; panel.input.number = function panelInputNumber(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.type = 'number'; return XNAT.ui.template.panelInput(opts).spawned; }; panel.input.email = function panelInputEmail(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.type = 'text'; addClassName(opts, 'email'); return XNAT.ui.template.panelInput(opts).spawned; }; panel.input.password = function panelInputPassword(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.type = 'password'; addClassName(opts, 'password'); return XNAT.ui.template.panelInput(opts).spawned; }; panel.input.checkbox = function panelInputCheckbox(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.type = 'checkbox'; //addClassName(opts, 'checkbox'); return XNAT.ui.template.panelInput(opts).spawned; }; panel.input.upload = function panelInputUpload(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.id = (opts.id||randomID('upload-', false)); opts.element = opts.element || opts.config || {}; opts.element.id = opts.id; @@ -560,13 +598,31 @@ var XNAT = getObject(XNAT || {}); } }; + panel.textarea = function(opts){ + opts = cloneObject(opts); + opts.element = opts.element || opts.config || {}; + if (opts.id) opts.element.id = opts.id; + if (opts.name) opts.element.name = opts.name; + opts.element.html = + opts.element.html || + opts.element.value || + opts.value || + opts.text || + opts.html || ''; + + opts.element.html = doLookup(opts.element.html); + + var textarea = spawn('textarea', opts.element); + return XNAT.ui.template.panelDisplay(opts, textarea).spawned; + }; + panel.select = {}; panel.select.menu = function panelSelectSingle(opts, multi){ var _menu; - opts = getObject(opts); + opts = cloneObject(opts); opts.element = opts.element || opts.config || {}; opts.element.name = opts.element.name || opts.name || ''; opts.element.id = opts.element.id || opts.id || toDashed(opts.element.name); @@ -596,7 +652,7 @@ var XNAT = getObject(XNAT || {}); }; panel.selectMenu = function panelSelectMenu(opts){ - opts = getObject(opts); + opts = cloneObject(opts); return XNAT.ui.template.panelSelect(opts).spawned; }; @@ -640,94 +696,6 @@ var XNAT = getObject(XNAT || {}); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - /** - * Initialize panel and optionally render it. - * If 'opts' argument is passed, 'setup' method will run. - * If 'container' argument is passed, the 'render' method will run. - * So if both args are passed, 'setup' and 'render' do NOT need to be called. - * @param [opts] {Object} Config object - * @param [container] {Element} Container for panel - * @returns {{}} - */ - function panel(opts, container){ - - // `this` object - var _panel = {}; - - /** - * Standard panel widget - */ - function newPanel(){ - - var sections = [ - ['div.panel-heading', [ - ['h3.panel-title', _panel.opts.title] - ]], - ['div.panel-body', _panel.opts.body] - ]; - - if (_panel.opts.footer) { - sections.push(['div.panel-footer', _panel.opts.footer]) - } - - return spawn((_panel.opts.tag) + '.panel.panel-default', _panel.opts.attr, sections); - //return $(spawn('div.panel.panel-default')).append(content); - } - - /** - * Sets up elements before rendering to the page - * @param _opts Config object - * @returns {{}} - */ - _panel.setup = function _panelSetup(_opts){ - - _panel.opts = extend(true, {}, _opts); - - _panel.opts.tag = _panel.opts.tag || 'div'; - _panel.opts.title = _panel.opts.title || _panel.opts.header || ''; - _panel.opts.body = _panel.opts.body || _panel.opts.content || ''; - _panel.opts.footer = _panel.opts.footer || ''; - - _panel.opts.attr = _panel.opts.attr || {}; - - if (_panel.opts.id) { - _panel.opts.attr.id = _panel.opts.id - } - - if (_panel.opts.name) { - _panel.opts.attr.data = getObject(_panel.opts.attr.data); - _panel.opts.attr.data.name = _panel.opts.name; - } - - _panel.panel = _panel.element = newPanel(); - - return _panel; - }; - - // if 'opts' arg is passed to .panel(), call .setup() - if (opts) { - _panel.setup(opts); - } - - // render the panel and append to 'container' - _panel.render = function _panelRender(container){ - $$(container).append(_panel.panel); - return _panel; - }; - - // render immediately if 'container' is specified - if (container) { - _panel.render(container); - } - - _panel.get = function _panelGet(){ - return _panel.element; - }; - - return _panel; - - } - /** * Panel widget with default 'Submit' and 'Revert' buttons diff --git a/src/main/webapp/scripts/xnat/ui/templates.js b/src/main/webapp/scripts/xnat/ui/templates.js index 53a87892f6acd5e2855de73bc1b40e135a8e69d3..e61089a4ceeadf7268e1dd12355d5a4da50f3878 100644 --- a/src/main/webapp/scripts/xnat/ui/templates.js +++ b/src/main/webapp/scripts/xnat/ui/templates.js @@ -39,12 +39,50 @@ var XNAT = getObject(XNAT); return obj.data; } + function lookupValue(el, lookup){ + var val = ''; + try { + val = eval(lookup.trim()); + } + catch (e) { + val = ''; + console.log(e); + } + // changeVal() changes the value and triggers + // the 'onchange' event + $(el).changeVal(val).dataAttr('value', val); + return val; + } + + // another way to do this without using eval() + // is to loop over object string using dot notation: + // var myVal = lookupObjectValue(XNAT, 'data.siteConfig.siteId'); + // --> myVal == 'myXnatSiteId' + function lookupObjectValue(root, objStr){ + var val = ''; + if (!objStr) { + objStr = root; + root = window; + } + root = root || window; + objStr.toString().trim().split('.').forEach(function(part, i){ + // start at the root object + if (i === 0) { + val = root[part] || {}; + } + else { + val = val[part]; + } + }); + return val; + } + // ======================================== // subhead element to segment panels template.panelSubhead = function(opts){ var _templ, _spawn, _html; - opts = getObject(opts); + opts = cloneObject(opts); _templ = ['h4.panel-subhead', opts]; _spawn = function(){ return spawn.apply(null, _templ); @@ -65,7 +103,7 @@ var XNAT = getObject(XNAT); // generic panel element template.panelElement = function(opts, content){ var _templ, _spawn, _html; - opts = getObject(opts); + opts = cloneObject(opts); addClassName(opts, 'panel-element'); _templ = [ 'div|data-name='+(opts.name||''), @@ -89,33 +127,41 @@ var XNAT = getObject(XNAT); }; // ======================================== + // ======================================== // display only element for form panels template.panelDisplay = function(opts, element){ - opts = getObject(opts); + + opts = cloneObject(opts); opts.id = opts.id||toDashed(opts.name||''); opts.label = opts.label||opts.title||opts.name||''; + + // pass in an element or create a new 'div' element + element = + element || spawn('div', { + id: opts.id, + className: opts.className||'', + title: opts.title||opts.name||opts.id, + html: opts.value||opts.html||opts.text||opts.body||'' + }); + return template.panelElement(opts, [ - ['label.element-label|for='+opts.id, opts.label], + ['label.element-label|for='+element.id||opts.id, opts.label], ['div.element-wrapper', [ - element || ['div', { - id: opts.id, - name: opts.name, - className: opts.className||'', - size: 25, - title: opts.title||opts.name||opts.id, - html: opts.value||'' - }], - ['div.description', opts.description||opts.body||opts.html] + + element , + + ['div.description', opts.description] ]] ]); }; // ======================================== + // ======================================== // input element for form panels template.panelInput = function(opts, element){ - opts = getObject(opts); + opts = cloneObject(opts); opts.name = opts.name || opts.id || randomID('input-', false); opts.id = opts.id||toDashed(opts.name||''); opts.label = opts.label||opts.title||opts.name||''; @@ -149,45 +195,30 @@ var XNAT = getObject(XNAT); element.checked = true; } - var val = ''; - // set the value of individual form elements - // look up a namespaced object value if the value starts with ?| - var doLookup = '?|'; + // look up a namespaced object value if the value starts with '??' + var doLookup = '??'; if (opts.value && opts.value.toString().indexOf(doLookup) === 0) { - try { - val = eval(opts.value.split(doLookup)[1]); - } - catch (e) { - val = '' - } - $(element).changeVal(val).dataAttr('value', val); + element.value = lookupObjectValue(opts.value.split(doLookup)[1]); } if (opts.load) { if (opts.load.lookup) { - try { - val = eval(opts.load.lookup); - } - catch (e) { - val = '' - } - $(element).changeVal(val).dataAttr('value', val); + lookupValue(element, opts.load.lookup); } else if (opts.load.url){ $.ajax({ method: opts.load.method || 'GET', url: XNAT.url.restUrl(opts.load.url), success: function(data){ - // split object path + // get value from specific object path if (opts.load.prop) { opts.load.prop.split('.').forEach(function(part){ - data = data[part] + data = data[part] || {}; }); + // data = lookupObjectValue(opts.load.prop); } - // changeVal() changes the value and triggers - // the 'onchange' event $(element).changeVal(data).dataAttr('value', data); } }) @@ -210,7 +241,7 @@ var XNAT = getObject(XNAT); // ======================================== // select element for form panels template.panelSelect = function(opts){ - opts = getObject(opts); + opts = cloneObject(opts); opts.name = opts.name || opts.id || randomID('select-', false); opts.id = opts.id || toDashed(opts.name||''); opts.element = extend({ @@ -242,7 +273,7 @@ var XNAT = getObject(XNAT); template.panelElementGroup = function(opts, elements){ - opts = getObject(opts); + opts = cloneObject(opts); return template.panelElement(opts, [ ['label.element-label|for='+opts.id, opts.label||opts.title||opts.name], ['div.element-wrapper', elements] diff --git a/src/main/webapp/scripts/xnat/url.js b/src/main/webapp/scripts/xnat/url.js index c3c81083c5fc2d858f7c3f433fb756f48a63176a..54bb44f7946e964915fdd76bd376551df800e0c1 100644 --- a/src/main/webapp/scripts/xnat/url.js +++ b/src/main/webapp/scripts/xnat/url.js @@ -46,7 +46,7 @@ var XNAT = getObject(XNAT||{}); // make sure the serverRoot string (and only ONE serverRoot string) // is at the beginning of a url function rootUrl(url){ - return fixRoot((window.serverRoot || XNAT.serverRoot || ''), url || '') + return fixRoot((window.serverRoot || XNAT.serverRoot || ''), url) } url.rootUrl = rootUrl;