diff --git a/src/main/webapp/WEB-INF/tags/page/xnat.tag b/src/main/webapp/WEB-INF/tags/page/xnat.tag index 5169186ca6c128a5d9a23b2498301bd9b639d75b..dd6dfea352a6b2b9bd2040f2299200b36ff6be40 100644 --- a/src/main/webapp/WEB-INF/tags/page/xnat.tag +++ b/src/main/webapp/WEB-INF/tags/page/xnat.tag @@ -567,19 +567,19 @@ ${bodyTop} jq('.main_header').height(hdr_logo_height + 10); } - ## Commented out 2016/09/02 (XNAT-4501). I don't think we want to do this (See home page when this takes effect) - ##// adjust width of main nav if logo is wider than 175px - ##var hdr_logo_width = header_logo$.width(); - ##if (hdr_logo_width > 175) { - ## jq('#main_nav').width(932 - hdr_logo_width - 20); - ##} + //Commented out 2016/09/02 (XNAT-4501). I don't think we want to do this (See home page when this takes effect) + // adjust width of main nav if logo is wider than 175px + //var hdr_logo_width = header_logo$.width(); + //if (hdr_logo_width > 175) { + // jq('#main_nav').width(932 - hdr_logo_width - 20); + //} // //var recent_proj_height = jq('#min_projects_list > div').height(); var recent_proj_height = 67; //jq('#min_projects_list, #min_expt_list').height(recent_proj_height * 5).css({'min-width':349,'overflow-y':'scroll'}); - } + }; // initialize the advanced search method toggler XNAT.app.searchMethodToggler = function(parent$){ @@ -587,9 +587,9 @@ ${bodyTop} parent$ = $$(parent$ || 'body'); var INPUTS = 'input, select, textarea, :input', - SEARCH_METHOD_CKBOXES = 'input.search-method', - searchGroups$ = parent$.find('div.search-group'), - searchMethodInputs$ = parent$.find(SEARCH_METHOD_CKBOXES); + SEARCH_METHOD_CKBOXES = 'input.search-method', + searchGroups$ = parent$.find('div.search-group'), + searchMethodInputs$ = parent$.find(SEARCH_METHOD_CKBOXES); // disable 'by-id' search groups by default searchGroups$.filter('.by-id').addClass('disabled').find(INPUTS).not(SEARCH_METHOD_CKBOXES).changeVal('') diff --git a/src/main/webapp/scripts/xnat/spawner.js b/src/main/webapp/scripts/xnat/spawner.js index ed0a1cbb9f137f810d5e1e623617f6cfa15fe220..f587a363189c30f14d96e4d58739505d1eb24a99 100644 --- a/src/main/webapp/scripts/xnat/spawner.js +++ b/src/main/webapp/scripts/xnat/spawner.js @@ -53,10 +53,20 @@ var XNAT = getObject(XNAT); forOwn(obj, function(item, prop){ - var kind, methodName, method, spawnedElement, $spawnedElement; - - // save the config properties in a new object - prop = cloneObject(prop); + var kind, element, method, spawnedElement, $spawnedElement; + + // 'prop' can be a new or existing DOM element + if (prop instanceof Element) { + element = prop; + prop = { + kind: 'element', + element: element + }; + } + else { + // save the config properties in a new object + prop = cloneObject(prop); + } prop.element = prop.element || prop.config || {}; @@ -65,12 +75,12 @@ var XNAT = getObject(XNAT); // lastly use the object's own name prop.name = prop.name || item; - prop.id = prop.id || prop.element.id || toDashed(prop.name); + //prop.id = prop.id || prop.element.id || toDashed(prop.name); // accept 'kind' or 'type' property name // but 'kind' will take priority // with a fallback to a generic div - kind = prop.kind || prop.type || 'div.spawned'; + kind = prop.kind || prop.type || null; // make 'href' 'src' and 'action' properties // start at the site root if starting with '/' @@ -93,8 +103,14 @@ var XNAT = getObject(XNAT); prop.content = prop.content || prop.children || ''; try { - spawnedElement = - spawn(prop.tag || prop.element.tag || 'div', prop.element, prop.content); + // if setting up Spawner elements in JS, allow a + // DOM element to be passed in the 'element' property + if (prop.element instanceof Element) { + spawnedElement = prop.element; + } + else { + spawnedElement = spawn(prop.tag || prop.element.tag || 'span', prop.element, prop.content); + } // convert relative URIs for href, src, and action attributes if (spawnedElement.href) { @@ -118,6 +134,9 @@ var XNAT = getObject(XNAT); spawner.notSpawned.push(prop); } } + else if (/^(text|html)$/i.test(kind)) { + $frag.append(prop.content||prop.html||prop.text) + } else { // check for a matching XNAT.ui method to call: @@ -135,6 +154,9 @@ var XNAT = getObject(XNAT); // XNAT.ui.kind() lookupObjectValue(NAMESPACE + '.' + kind) || + // XNAT.element.kind() + lookupObjectValue(XNAT, 'element.' + kind) || + // kind.init() lookupObjectValue(kind + '.init') || diff --git a/src/main/webapp/scripts/xnat/ui/panel.js b/src/main/webapp/scripts/xnat/ui/panel.js index 7f031905bf2799aae89f2846c887c77683440212..efea821715fbbd44cc901a887479e19741af7905 100644 --- a/src/main/webapp/scripts/xnat/ui/panel.js +++ b/src/main/webapp/scripts/xnat/ui/panel.js @@ -512,11 +512,12 @@ var XNAT = getObject(XNAT || {}); $$(form).serializeArray().forEach(function(item) { if (!item.name) return; var name = item.name.replace(/^:/,''); + var val = firstDefined(item.value+'', ''); if (typeof json[name] == 'undefined') { - json[name] = item.value || ''; + json[name] = val; } else { - json[name] = [].concat(json[name], item.value||[]) ; + json[name] = [].concat(json[name], val||[]) ; } }); return json; @@ -909,7 +910,7 @@ var XNAT = getObject(XNAT || {}); className: opts.className || opts.classes || '', name: opts.name, id: opts.id || toDashed(opts.name), - value: opts.value || '' + value: firstDefined(opts.value+'', '') }, opts.element); addClassName(opts.element, 'hidden'); if (opts.validation || opts.validate) { @@ -975,12 +976,17 @@ var XNAT = getObject(XNAT || {}); 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 || ''; + var val1 = opts.element.value; + var val2 = opts.value; + + opts.element.value = firstDefined(val1, val2, ''); + + opts.element.html = firstDefined( + opts.element.html+'', + opts.element.value+'', + opts.text+'', + opts.html+'', + ''); opts.element.html = lookupValue(opts.element.html); opts.element.title = 'Double-click to open in code editor.'; @@ -1033,7 +1039,7 @@ var XNAT = getObject(XNAT || {}); name: opts.name, className: opts.className||'', title: opts.title||opts.name||opts.id||'', - value: opts.value||'' + value: firstDefined(opts.value+'', '') }, opts.element); if (multi) { diff --git a/src/main/webapp/scripts/xnat/xhr.js b/src/main/webapp/scripts/xnat/xhr.js index 9ea911b3f7280ab38ea799dcede2d9f66e1ada87..ff51eae79c990831bacb28221ef6c6e012e154a0 100755 --- a/src/main/webapp/scripts/xnat/xhr.js +++ b/src/main/webapp/scripts/xnat/xhr.js @@ -456,6 +456,13 @@ var XNAT = getObject(XNAT||{}), var $this = $(this); var val = lookupObjectValue(dataObj, this.name||this.title); + // don't set values of inputs with EXISTING + // values that start with "@?" + // -- those get parsed on submission + if (!val && this.value && /^(@\?)/.test(this.value)) { + return; + } + if (Array.isArray(val)) { val = val.join(', '); $this.addClass('array-list') @@ -536,7 +543,16 @@ var XNAT = getObject(XNAT||{}), // don't pass 'callback' property into the AJAX request delete opts.callback; - var inputs = $form.find(':input').not('button, [type="submit"]').toArray(); + var $inputs = $form.find(':input').not('button, [type="submit"]'); + + // inputs with a value that starts with + // @? will get values from another source + $inputs.filter('[value^="@?"]').each(function(){ + var source = this.value.replace(/^@\?[:=\s]*/, ''); + this.value = eval(source); + }); + + var inputs = $inputs.toArray(); if (/POST|PUT/i.test(opts.method)) { if ($form.hasClass('json') || /json/i.test(opts.contentType||'')){ @@ -545,6 +561,9 @@ var XNAT = getObject(XNAT||{}), opts.processData = false; opts.contentType = 'application/json'; } + else { + opts.data = $form.find(':input').not('.ignore').serialize(); + } opts.success = function(data){ callback.apply($form, arguments); // repopulate 'real' data after success diff --git a/src/main/webapp/setup/index.jsp b/src/main/webapp/setup/index.jsp index 7810ad1a44772dcb9f518c1afe55790e89ac818c..53265527213fb6630c010cae5f8a5f5d7bba0508 100644 --- a/src/main/webapp/setup/index.jsp +++ b/src/main/webapp/setup/index.jsp @@ -23,11 +23,16 @@ <pg:restricted msg="${message}"> <c:import url="/xapi/siteConfig" var="siteConfig"/> + <c:import url="/xapi/notifications" var="notifications"/> <script> + var XNAT = getObject(XNAT); XNAT.data = extend({}, XNAT.data, { - siteConfig: ${siteConfig} + siteConfig: ${siteConfig}, + notifications: ${notifications} }); + XNAT.data['/xapi/siteConfig'] = XNAT.data.siteConfig; + XNAT.data['/xapi/notifications'] = XNAT.data.notifications; // get rid of the 'targetSource' property delete XNAT.data.siteConfig.targetSource; </script> @@ -57,9 +62,9 @@ <script> - // XNAT.app.setupComplete = function(){ - // XNAT.xhr.form('#site-setup', {}); - // }; + //XNAT.app.setupComplete = function(){ + // XNAT.xhr.form('#site-setup', {}); + //}; XNAT.xhr.get({ url: XNAT.url.rootUrl('/setup/site-setup.yaml'), @@ -68,8 +73,12 @@ if (typeof data === 'string') { data = YAML.parse(data); } - var setupPanels = XNAT.spawner.spawn(data); - setupPanels.render('#site-setup-panels'); + + console.log(data); + + XNAT.spawner + .spawn(data) + .render('#site-setup-panels'); } }); diff --git a/src/main/webapp/setup/site-setup.yaml b/src/main/webapp/setup/site-setup.yaml index 239e2a19c8e1490e47f843b547bc532636342713..f5c764ef4459ebea0d4c98021b4d667e38fbd4e6 100644 --- a/src/main/webapp/setup/site-setup.yaml +++ b/src/main/webapp/setup/site-setup.yaml @@ -25,7 +25,6 @@ siteSetup: method: POST url: /xapi/siteConfig contentType: json - load: XNAT.data.siteConfig contents: siteId: @@ -38,7 +37,7 @@ siteSetup: The id used to refer to this site (also used to generate ids). The Site ID must start with a letter and contain only letters, numbers and underscores. It should be a short, one-word name or acronym which describes your site. - validation: required id + validation: required id-strict siteUrl: kind: panel.input.text @@ -63,30 +62,44 @@ siteSetup: description: Email address for site administrator. validation: required email -# this is buggy - disabling for now -# notificationRecipients: -# type: panel.form -# classes: hidden -# header: false -# footer: false -# method: POST -# url: /xapi/notifications -# contentType: json -# contents: -# adminEmail: -# tag: input.disabled | disabled, type=hidden, data-value-from=#site-admin-email, name=adminEmail -# value: !? $('#site-admin-email').val() -# # copy adminEmail value to these properties: -# help: -# tag: input| type=hidden, data-value-from=#site-admin-email, name=notifications.helpContactInfo -# errorMessages: -# tag: input| type=hidden, data-value-from=#site-admin-email, name=notifications.emailRecipientErrorMessages -# issueReports: -# tag: input| type=hidden, data-value-from=#site-admin-email, name=notifications.emailRecipientIssueReports -# newUserAlert: -# tag: input| type=hidden, data-value-from=#site-admin-email, name=notifications.emailRecipientNewUserAlert -# update: -# tag: input| type=hidden, data-value-from=#site-admin-email, name=notifications.emailRecipientUpdate + # this seems to work now... + # copy values from admin email to recipient list + # ========================= + # EMAIL RECIPIENTS + notificationRecipients: + type: panel.form + classes: hidden + header: false + footer: false + method: POST + url: /xapi/notifications + contentType: json + contents: + vars: + tag: script + content: > + window.siteAdminEmailInput = $('#site-admin-email')[0] + # copy adminEmail value to these properties: + helpContactInfo: + kind: input.hidden + name: helpContactInfo + value: @?=window.siteAdminEmailInput.value + errorMessages: + kind: input.hidden + name: emailRecipientErrorMessages + value: @?=window.siteAdminEmailInput.value + issueReports: + kind: input.hidden + name: emailRecipientIssueReports + value: @?=window.siteAdminEmailInput.value + newUserAlert: + kind: input.hidden + name: emailRecipientNewUserAlert + value: @?=window.siteAdminEmailInput.value + update: + kind: input.hidden + name: emailRecipientUpdate + value: @?=window.siteAdminEmailInput.value # ========================= # DATA STORAGE @@ -194,12 +207,12 @@ siteSetup: text: Mail Server Settings smtpAuth: - kind: panel.input.checkbox + kind: panel.input.switchbox name: mail.smtp.auth label: SMTP Auth? smtpStartTls: - kind: panel.input.checkbox + kind: panel.input.switchbox name: mail.smtp.starttls.enable label: Start TLS? @@ -220,15 +233,15 @@ siteSetup: contentType: json contents: - requireLogin: - kind: panel.input.checkbox + requireLogin: + kind: panel.input.switchbox id: requireLogin name: requireLogin label: Require User Login description: "If checked, then only registered users will be able to access your site. If false, anyone visiting your site will automatically be logged in as 'guest' with access to public data." - autoEnableUserRegistration: - kind: panel.input.checkbox + autoEnableUserRegistration: + kind: panel.input.switchbox id: autoEnableUserRegistration name: userRegistration label: "Auto-enable User Registration?" @@ -237,8 +250,8 @@ siteSetup: projects immediately. If false, the site administrator will be required to manually enable user accounts. Either way the administrator receives an email notification when a user registers. - enableCsrfToken: - kind: panel.input.checkbox + enableCsrfToken: + kind: panel.input.switchbox id: enableCsrfToken name: enableCsrfToken label: Require CSRF Token?