diff --git a/src/main/webapp/page/admin/data/config/site-admin-sample-new.yaml b/src/main/webapp/page/admin/data/config/site-admin-sample-new.yaml index d2e3f3bb73f499e887419aeb23c1bdcc0c0b3923..f9ef0c4608f0f9b4bb0a02232db8d2ec8273fb69 100644 --- a/src/main/webapp/page/admin/data/config/site-admin-sample-new.yaml +++ b/src/main/webapp/page/admin/data/config/site-admin-sample-new.yaml @@ -2,15 +2,16 @@ root: kind: tabs name: siteAdmin label: Administer XNAT - groups: -# dashboard: Dashboard - xnatSetup: XNAT Setup - manageAccess: Manage Access - manageData: Manage Data - processing: Processing - projectCustomization: Project Customization - advanced: Advanced XNAT Settings - other: Other + meta: + tabGroups: + dashboard: Dashboard + xnatSetup: XNAT Setup + manageAccess: Manage Access + manageData: Manage Data + processing: Processing + projectCustomization: Project Customization + advanced: Advanced XNAT Settings + other: Other contains: tabs tabs: # this property name is the same as 'contains', so it will be treated like 'contents' siteSetup: @@ -49,12 +50,27 @@ root: html: Hello people. style: fontWeight: bold + manageThemes: + kind: panel + name: manageThemes + label: Manage Themes + footer: false + contents: + themeUpload: + kind: panel.input.upload + name: themeUpload + # id: uplode-here + method: PUT + action: '/put/the/thing/in/the/stuff' + label: Upload Theme File + + security: kind: tab name: security label: Security -# group: xnatSetup + group: xnatSetup contents: generalSecuritySettings: kind: panel.form @@ -66,10 +82,9 @@ root: name: securityChannel label: Security Channel value: https -# contains: options options: http: - label: http + # if there's no 'label' property, the value will be used for the label value: http https: label: https diff --git a/src/main/webapp/scripts/lib/spawn/spawn.js b/src/main/webapp/scripts/lib/spawn/spawn.js index c0d0f7ff37baa7933d66a1357334faca2e19009c..d4d43c6d982de7d3e93dd565aceb271e552e8f83 100644 --- a/src/main/webapp/scripts/lib/spawn/spawn.js +++ b/src/main/webapp/scripts/lib/spawn/spawn.js @@ -53,7 +53,8 @@ 'url', 'checkbox', 'radio', - 'hidden' + 'hidden', + 'file' ]; // use these as a shortcut to create <input> elements: @@ -132,7 +133,7 @@ if (tag === '!'){ el = doc.createDocumentFragment(); - appendChildren(el, opts, spawn); + appendChildren(el, opts||'', spawn); return el; } diff --git a/src/main/webapp/scripts/xnat/ui/input.js b/src/main/webapp/scripts/xnat/ui/input.js index 2d5bc1e28985f1a8e3fd91ccde146e6380504937..8e3451e9561ffa96a9bd0ef4a685d1b779f23818 100644 --- a/src/main/webapp/scripts/xnat/ui/input.js +++ b/src/main/webapp/scripts/xnat/ui/input.js @@ -82,7 +82,7 @@ var XNAT = getObject(XNAT); otherTypes = [ 'password', 'date', 'checkbox', - 'radio', 'button', 'hidden' + 'radio', 'button', 'hidden', 'file' ]; otherTypes.forEach(function(type){ input[type] = function(config){ diff --git a/src/main/webapp/scripts/xnat/ui/panel.js b/src/main/webapp/scripts/xnat/ui/panel.js index 04e84294301d0be5ea0c1fb95780abc914f13340..61dbf26d8983e755380af9c9f55eaa026809fd9f 100644 --- a/src/main/webapp/scripts/xnat/ui/panel.js +++ b/src/main/webapp/scripts/xnat/ui/panel.js @@ -16,13 +16,13 @@ var XNAT = getObject(XNAT || {}); XNAT.ui.panel = panel = getObject(XNAT.ui.panel || {}); - + // add new element class without destroying existing class function addClassName(el, newClass){ el.className = [].concat(el.className||[], newClass).join(' ').trim(); return el.className; } - + // add new data object item to be used for [data-] attribute(s) function addDataObjects(obj, attrs){ obj.data = obj.data || {}; @@ -32,15 +32,32 @@ var XNAT = getObject(XNAT || {}); return obj.data; } - panel.init = function(config){ - var _target = spawn('div.panel-body'), + panel.init = function(opts){ + + opts = getObject(opts); + opts.element = opts.element || opts.config || {}; + + var _target = spawn('div.panel-body', opts.element), + + hideFooter = (isDefined(opts.footer) && (opts.footer === false || /^-/.test(opts.footer))), + _panel = spawn('div.panel.panel-default', [ ['div.panel-heading', [ - ['h3.panel-title', config.title || config.label] + ['h3.panel-title', opts.title || opts.label] ]], + + // target is where the next spawned item will render _target, - ['div.panel-footer', config.footer] + + (hideFooter ? ['div.hidden'] : ['div.panel-footer', opts.footer]) + ]); + + // add an id to the outer panel element if present + if (opts.id || opts.element.id) { + _panel.id = (opts.id || opts.element.id) + '-panel'; + } + return { target: _target, element: _panel, @@ -51,8 +68,16 @@ var XNAT = getObject(XNAT || {}); } }; - panel.form = function(config){ - var _target = spawn('div.panel-body', config.config), + // creates a panel that's a form that can be submitted + panel.form = function(opts){ + + opts = getObject(opts); + opts.element = opts.element || opts.config || {}; + + var _target = spawn('div.panel-body', opts.element), + + hideFooter = (isDefined(opts.footer) && (opts.footer === false || /^-/.test(opts.footer))), + _footer = [ ['button.btn.btn-sm.btn-primary.save.pull-right|type=submit', 'Submit'], ['span.pull-right', ' '], @@ -60,15 +85,27 @@ var XNAT = getObject(XNAT || {}); ['button.btn.btn-sm.btn-link.defaults.pull-left', 'Default Settings'], ['div.clear'] ], - _panel = spawn('form.xnat-form-panel.panel.panel-default', [ + + _panel = spawn('form.xnat-form-panel.panel.panel-default', { + method: opts.method || 'POST', + action: opts.action || '#' + }, [ ['div.panel-heading', [ - ['h3.panel-title', config.title || config.label] + ['h3.panel-title', opts.title || opts.label] ]], - + + // target is where the next spawned item will render _target, - - ['div.panel-footer', config.footer || _footer] + + (hideFooter ? ['div.hidden'] : ['div.panel-footer', opts.footer || _footer]) + ]); + + // add an id to the outer panel element if present + if (opts.id || opts.element.id) { + _panel.id = (opts.id || opts.element.id) + '-panel'; + } + return { target: _target, element: _panel, @@ -78,31 +115,34 @@ var XNAT = getObject(XNAT || {}); } } }; - + // create a single generic panel element panel.element = function(opts){ var _element, _inner = [], _target; opts = getObject(opts); - opts.config = opts.config || opts.element || {}; - addClassName(opts.config, 'panel-element'); - addDataObjects(opts.config, { name: opts.name||'' }); + opts.element = opts.element || opts.config || {}; + if (opts.id || opts.element.id) { + opts.element.id = (opts.id || opts.element.id) + '-element'; + } + addClassName(opts.element, 'panel-element'); + addDataObjects(opts.element, { name: opts.name||'' }); opts.label = opts.label||opts.title||opts.name||''; _inner.push(['label.element-label', opts.label]); - + // 'contents' will be inserted into the 'target' element - _target = spawn(['div.element-wrapper']); - + _target = spawn('div.element-wrapper'); + // add the target to the content array _inner.push(_target); - + // add a description if there is one if (opts.description){ _inner.push(['div.description', opts.description||opts.body||opts.html]); } - - _element = spawn('div', opts.config, _inner); - + + _element = spawn('div', opts.element, _inner); + return { target: _target, element: _element, @@ -111,7 +151,7 @@ var XNAT = getObject(XNAT || {}); return _element } } - + }; panel.input = {}; @@ -119,7 +159,7 @@ var XNAT = getObject(XNAT || {}); panel.input.text = function(opts){ return XNAT.ui.template.panelInput(opts).spawned; }; - + panel.input.number = function(opts){ opts = getObject(opts); opts.type = 'number'; @@ -146,9 +186,37 @@ var XNAT = getObject(XNAT || {}); //addClassName(opts, 'checkbox'); return XNAT.ui.template.panelInput(opts).spawned; }; - + + panel.input.upload = function(opts){ + opts = getObject(opts); + opts.id = (opts.id||randomID('upload-', false)); + opts.element = opts.element || opts.config || {}; + opts.element.id = opts.id; + var form = ['form', { + id: opts.id + '-form', + method: opts.method || 'POST', + action: opts.action || '#', + className: addClassName(opts, 'file-upload') + }, [ + ['input', { + type: 'file', + id: opts.id + '-input', + multiple: true, + style: { + width: '270px' + } + }], + ['button', { + type: 'button', + id: opts.id +'-button', + html: 'Upload' + }] + ]]; + return XNAT.ui.template.panelInput(opts, form).spawned; + }; + panel.input.group = function(obj){ - var _inner = spawn('div.element-group'); + var _inner = ['div.element-group']; var _outer = XNAT.ui.template.panelElementGroup(obj, _inner); return { target: _inner, diff --git a/src/main/webapp/scripts/xnat/ui/tabs.js b/src/main/webapp/scripts/xnat/ui/tabs.js index 2fe2bdf9e3691cacd29daf313fb0d0b76fc250a6..ccebcc972b922dcf996cfbe3997f128ffc11ad9a 100755 --- a/src/main/webapp/scripts/xnat/ui/tabs.js +++ b/src/main/webapp/scripts/xnat/ui/tabs.js @@ -122,11 +122,23 @@ var XNAT = getObject(XNAT || {}); }, [ ['a', { title: obj.label, - //href: '#'+obj.config.id, + // href: '#'+obj.config.id, href: '#!', html: obj.label }] ]); + + // setup the footer for the whole tab pane + function paneFooter(){ + return spawn('footer.footer', [ + ['button', { + type: 'button', + html: 'Save All', + classes: 'save-all btn btn-primary pull-right' + }] + ]); + } + _pane = spawn('div.tab-pane', obj.config); if (obj.active) { @@ -140,6 +152,7 @@ var XNAT = getObject(XNAT || {}); function render(element){ $$(element).append(_pane); + $$(element).append(paneFooter()); return _pane; } @@ -199,17 +212,6 @@ var XNAT = getObject(XNAT || {}); // return frag; // } // - // // setup the footer for the whole tab pane - // function paneFooter(){ - // var footer = spawn('footer.footer', [ - // ['button', { - // type: 'button', - // html: 'Save All', - // classes: 'save-all btn btn-primary pull-right' - // }] - // ]); - // return footer; - // } // // return frag;