From 55d9eaa963f7781a520041c498eae5470216f78a Mon Sep 17 00:00:00 2001 From: csmig Date: Sun, 12 Nov 2023 19:09:12 -0500 Subject: [PATCH] fix: ui scaling retains borders --- client/src/css/dark-mode.css | 8 +- client/src/css/stigman.css | 36 +- client/src/img/remove.svg | 10 +- client/src/img/trash.svg | 40 +- client/src/js/SM/CollectionClone.js | 4 +- client/src/js/SM/CollectionForm.js | 568 ++++++++++++++-------------- client/src/js/SM/CollectionStig.js | 4 +- client/src/js/collectionManager.js | 2 +- client/src/js/overrides.js | 32 ++ client/src/js/stigman.js | 1 - 10 files changed, 376 insertions(+), 329 deletions(-) diff --git a/client/src/css/dark-mode.css b/client/src/css/dark-mode.css index abbe5b3e6..274f4dda5 100644 --- a/client/src/css/dark-mode.css +++ b/client/src/css/dark-mode.css @@ -253,8 +253,7 @@ fieldset.x-panel-collapsed { } .x-btn button.sm-error-icon { - background-color: #602020; - background-image: url("../img/remove.svg") + background-color: #602020 } .x-btn-bc, .x-btn-bl, .x-btn-br, .x-btn-mc, .x-btn-ml, .x-btn-mr, .x-btn-tc, .x-btn-tl, .x-btn-tr { @@ -2421,11 +2420,6 @@ td.sort-asc, td.sort-desc, td.x-grid3-hd-menu-open, td.x-grid3-hd-over { background-color: initial!important } -.icon-del { - background-image: url("../img/remove.svg"); - background-color: initial -} - .icon-save { background-image: url("../img/save.gif")!important; background-color: initial!important diff --git a/client/src/css/stigman.css b/client/src/css/stigman.css index 15de738e5..72261ccfc 100644 --- a/client/src/css/stigman.css +++ b/client/src/css/stigman.css @@ -1050,7 +1050,8 @@ td.x-grid3-hd-over .x-grid3-hd-inner { border-radius: 25px; border: none; margin: 10px; - height: 400px + height: 400px; + width: 380px } .sm-home-widget-header { background-color: #d3d3d3 @@ -1149,7 +1150,10 @@ td.x-grid3-hd-over .x-grid3-hd-inner { background: url(../img/edit.svg) 0 no-repeat!important } .icon-del { - background: url(../img/remove.svg) 0 0/16px 16px + background: url(../img/trash.svg) 0 0/16px 16px +} +.icon-remove { + background: url(../img/remove.svg); } .icon-save { background: url(../img/save.gif) 0 no-repeat!important @@ -2033,6 +2037,26 @@ td.x-grid3-hd-over .x-grid3-hd-inner { font-size: 10px; line-height: 16px; } +.x-tool.x-tool-trash { + background-image: url(../img/trash.svg); + background-repeat: no-repeat; + background-size: 14px 14px; + color: grey; + width: auto; + padding-left: 15px; + font-size: 10px; + line-height: 16px; +} +.x-tool.x-tool-clone { + background-image: url(../img/clone.svg); + background-repeat: no-repeat; + background-size: 14px 14px; + color: grey; + width: auto; + padding-left: 15px; + font-size: 10px; + line-height: 16px; +} .x-tool.x-tool-spacer { width: 10px; background-image: unset; @@ -2040,7 +2064,7 @@ td.x-grid3-hd-over .x-grid3-hd-inner { .x-tool.x-tool-logout { background-image: url(../img/logout.svg); background-repeat: no-repeat; - background-size: 12px 15px; + background-size: 14px 14px; } .x-tool.x-tool-toggle.x-tool-collapse-west { background-image: url(../img/collapse-left.svg); @@ -2113,7 +2137,8 @@ td.x-grid3-hd-over .x-grid3-hd-inner { background-color: #e5e5e5 } .x-btn-text-icon .x-btn-icon-small-left .x-btn-text { - background-size: 14px 14px + background-size: 14px 14px; + background-position: 0px 1px; } .sm-hover-icon { opacity: 0.75; @@ -2201,3 +2226,6 @@ td.x-grid3-hd-over .x-grid3-hd-inner { .sm-grabbing *, .sm-grabbing .sm-grid3-draggable .x-grid3-row-selected *, .sm-grabbing .sm-grid3-draggable .x-grid3-row-selected { cursor: url("../img/drag-drop-light.svg"), grabbing; } +.x-item-disabled { + filter: saturate(0) +} \ No newline at end of file diff --git a/client/src/img/remove.svg b/client/src/img/remove.svg index dc9aaf798..10ee19e51 100644 --- a/client/src/img/remove.svg +++ b/client/src/img/remove.svg @@ -27,9 +27,9 @@ inkscape:deskcolor="#d1d1d1" inkscape:zoom="1.03375" inkscape:cx="400" - inkscape:cy="400" - inkscape:window-width="1920" - inkscape:window-height="1022" + inkscape:cy="400.48368" + inkscape:window-width="3440" + inkscape:window-height="1372" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1" @@ -41,7 +41,7 @@ stroke-linecap="round" stroke-linejoin="round" id="path1" - style="stroke:#d92626;stroke-opacity:1" /> + style="stroke:#903d3d;stroke-opacity:1" /> + style="stroke:#903d3d;stroke-opacity:1" /> diff --git a/client/src/img/trash.svg b/client/src/img/trash.svg index b6aa041c6..027daa0f9 100644 --- a/client/src/img/trash.svg +++ b/client/src/img/trash.svg @@ -1,12 +1,5 @@ + inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> @@ -37,27 +37,31 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="1920" - inkscape:window-height="1015" + inkscape:window-width="1720" + inkscape:window-height="1372" id="namedview9" showgrid="false" inkscape:zoom="1.6484375" - inkscape:cx="256.60664" - inkscape:cy="231.7346" + inkscape:cx="256.90995" + inkscape:cy="232.34123" inkscape:window-x="0" inkscape:window-y="0" - inkscape:window-maximized="1" - inkscape:current-layer="Layer_1" /> + inkscape:window-maximized="0" + inkscape:current-layer="Layer_1" + inkscape:showpageshadow="2" + inkscape:pagecheckerboard="0" + inkscape:deskcolor="#d1d1d1" /> + style="fill:#8f3d3d;fill-opacity:1"> + style="fill:#8f3d3d;fill-opacity:1" /> + style="fill:#8f3d3d;fill-opacity:1" + sodipodi:nodetypes="sccssccss" /> diff --git a/client/src/js/SM/CollectionClone.js b/client/src/js/SM/CollectionClone.js index 29c16c233..65595e2cc 100644 --- a/client/src/js/SM/CollectionClone.js +++ b/client/src/js/SM/CollectionClone.js @@ -74,7 +74,7 @@ SM.CollectionClone.CloneFormPanel = Ext.extend(Ext.form.FormPanel, { name: 'name', allowBlank: false, value: this.sourceName ? `Clone of ${this.sourceName}` : '', - anchor: '100%', + anchor: '-5', listeners: { keyup: handleInput } @@ -83,7 +83,7 @@ SM.CollectionClone.CloneFormPanel = Ext.extend(Ext.form.FormPanel, { fieldLabel: 'Description', labelStyle: 'font-weight: 600;', name: 'description', - anchor: '100%', + anchor: '-5', value: `Cloned from ${this.sourceName} on ${new Date().toLocaleDateString('en-CA')} by ${curUser.displayName}` }) const grantsCb = new SM.Global.HelperCheckbox({ diff --git a/client/src/js/SM/CollectionForm.js b/client/src/js/SM/CollectionForm.js index e81ac23dc..dc69ede75 100644 --- a/client/src/js/SM/CollectionForm.js +++ b/client/src/js/SM/CollectionForm.js @@ -73,9 +73,9 @@ Ext.reg('sm-accesslevel-field', SM.AccessLevelField); SM.MetadataGrid = Ext.extend(Ext.grid.GridPanel, { initComponent: function () { const _this = this - let fields = ['key', 'value'] - let newFields = ['key', 'value'] - let fieldsConstructor = Ext.data.Record.create(fields) + const fields = ['key', 'value'] + const newFields = ['key', 'value'] + const fieldsConstructor = Ext.data.Record.create(fields) this.newRecordConstructor = Ext.data.Record.create(newFields) this.editor = new Ext.ux.grid.RowEditor({ saveText: 'Save', @@ -110,106 +110,125 @@ SM.MetadataGrid = Ext.extend(Ext.grid.GridPanel, { } } }) - this.totalTextCmp = new Ext.Toolbar.TextItem({ - text: '0 records', - width: 80 - }) - let writer = new Ext.data.DataWriter() - let tbar = new SM.RowEditorToolbar({ + const writer = new Ext.data.DataWriter() + const tbar = new SM.RowEditorToolbar({ itemString: 'key', editor: this.editor, gridId: this.id, deleteProperty: 'key', newRecord: this.newRecordConstructor }) + const store = new Ext.data.ArrayStore({ + grid: this, + writer: writer, + autoSave: false, + fields: fieldsConstructor, + sortInfo: { + field: 'key', + direction: 'ASC' + }, + root: '', + restful: true, + idProperty: 'key', + listeners: { + remove: (store, record, index) => { + store.grid.fireEvent('metadatachanged', store.grid) + } + } + }) + const totalTextCmp = new SM.RowCountTextItem ({ + store, + noun: 'key', + iconCls: 'sm-database-save-icon' + }) + const bbar = new Ext.Toolbar({ + items: [ + { + xtype: 'exportbutton', + hasMenu: false, + gridBasename: 'Metadata', + exportType: 'grid', + iconCls: 'sm-export-icon', + text: 'CSV' + }, + { + xtype: 'tbfill' + }, + { + xtype: 'tbseparator' + }, + totalTextCmp + ] + }) + const view = new SM.ColumnFilters.GridView({ + emptyText: this.emptyText || 'No records to display', + deferEmptyText: false, + forceFit: true + }) + const sm = new Ext.grid.RowSelectionModel({ + singleSelect: true, + listeners: { + selectionchange: function (sm) { + tbar.delButton.setDisabled(!sm.hasSelection()) + } + } + }) + const cm = new Ext.grid.ColumnModel({ + columns: [ + { + header: "Key", + dataIndex: 'key', + sortable: true, + width: 150, + editor: new Ext.form.TextField({ + grid: this, + submitValue: false, + validator: function (v) { + // Don't keep the form from validating when I'm not active + if (this.grid.editor.editing == false) return true + + // blanks + if (v === "") return "Blank values not allowed" + + // duplicates + // already in store? + const searchIdx = this.grid.store.findExact('key', v) + // is it this record? + const isMe = this.grid.selModel.isSelected(searchIdx) + if (!(searchIdx == -1 || isMe)) return "Duplicate keys not allowed" + + // ignored key + if (_this.ignoreKeys.includes(v)) return "Reserved keys not allowed" + + return true + } + }) + }, + { + header: "Value", + dataIndex: 'value', + sortable: false, + width: 250, + editor: new Ext.form.TextField({ + submitValue: false + }) + } + ] + }) tbar.delButton.disable() - let config = { - //title: this.title || 'Parent', + const config = { isFormField: true, ignoreKeys: _this.ignoreKeys || [], allowBlank: true, layout: 'fit', height: 150, - border: true, plugins: [this.editor], - style: { - }, - listeners: { - }, - store: new Ext.data.ArrayStore({ - grid: this, - writer: writer, - autoSave: false, - fields: fieldsConstructor, - sortInfo: { - field: 'key', - direction: 'ASC' - }, - root: '', - restful: true, - idProperty: 'key', - listeners: { - remove: (store, record, index) => { - store.grid.fireEvent('metadatachanged', store.grid) - } - } - }), - view: new SM.ColumnFilters.GridView({ - emptyText: this.emptyText || 'No records to display', - deferEmptyText: false, - forceFit: true - }), - sm: new Ext.grid.RowSelectionModel({ - singleSelect: true, - listeners: { - selectionchange: function (sm) { - tbar.delButton.setDisabled(!sm.hasSelection()) - } - } - }), - cm: new Ext.grid.ColumnModel({ - columns: [ - { - header: "Key", - dataIndex: 'key', - sortable: true, - width: 150, - editor: new Ext.form.TextField({ - grid: this, - submitValue: false, - validator: function (v) { - // Don't keep the form from validating when I'm not active - if (this.grid.editor.editing == false) return true - - // blanks - if (v === "") return "Blank values not allowed" - - // duplicates - // already in store? - const searchIdx = this.grid.store.findExact('key', v) - // is it this record? - const isMe = this.grid.selModel.isSelected(searchIdx) - if (!(searchIdx == -1 || isMe)) return "Duplicate keys not allowed" - - // ignored key - if (_this.ignoreKeys.includes(v)) return "Reserved keys not allowed" - - return true - } - }) - }, - { - header: "Value", - dataIndex: 'value', - sortable: false, - width: 250, - editor: new Ext.form.TextField({ - submitValue: false - }) - } - ] - }), - tbar: tbar, + store, + view, + sm, + cm, + tbar, + bbar, getValue: function () { let value = {} this.store.data.items.forEach((i) => { @@ -250,11 +269,10 @@ SM.UserSelectionField = Ext.extend(Ext.form.ComboBox, { root: '', sortInfo: { field: 'displayName', - direction: 'ASC' // or 'DESC' (case sensitive for local sorting) + direction: 'ASC' }, idProperty: 'userId' }) - // const tpl = `
{displayName}
{username}
` const tpl = new Ext.XTemplate( '', '
{[this.highlightQuery(values.displayName)]}
{[this.highlightQuery(values.username)]}
', @@ -338,10 +356,7 @@ SM.UserGrantsGrid = Ext.extend(Ext.grid.GridPanel, { 'accessLevel' ] this.newRecordConstructor = Ext.data.Record.create(newFields) - const totalTextCmp = new Ext.Toolbar.TextItem({ - text: '0 records', - width: 80 - }) + this.proxy = new Ext.data.HttpProxy({ restful: true, url: this.url, @@ -356,7 +371,7 @@ SM.UserGrantsGrid = Ext.extend(Ext.grid.GridPanel, { idProperty: 'userId', sortInfo: { field: 'displayName', - direction: 'ASC' // or 'DESC' (case sensitive for local sorting) + direction: 'ASC' }, listeners: { load: function (store, records) { @@ -368,6 +383,11 @@ SM.UserGrantsGrid = Ext.extend(Ext.grid.GridPanel, { } } }) + const totalTextCmp = new SM.RowCountTextItem ({ + store: grantStore, + noun: 'grant', + iconCls: 'sm-users-icon' + }) const userSelectionField = new SM.UserSelectionField({ submitValue: false, grid: this, @@ -391,12 +411,11 @@ SM.UserGrantsGrid = Ext.extend(Ext.grid.GridPanel, { dataIndex: 'userId', sortable: true, renderer: function (v, m, r) { - return `
${r.data.displayName ?? ''}
${r.data.username ?? ''}
` + return `
${r.data.displayName ?? ''}
${r.data.username ?? ''}
` }, editor: userSelectionField }, { - // header: "Access Level", header: 'Access Level', width: 50, dataIndex: 'accessLevel', @@ -484,9 +503,7 @@ SM.UserGrantsGrid = Ext.extend(Ext.grid.GridPanel, { } }) } - const config = { - //title: this.title || 'Parent', isFormField: true, name: 'grants', allowBlank: false, @@ -544,6 +561,24 @@ SM.UserGrantsGrid = Ext.extend(Ext.grid.GridPanel, { }, }), tbar: tbar, + bbar: new Ext.Toolbar({ + items: [ + { + xtype: 'exportbutton', + hasMenu: false, + gridBasename: 'CollectionGrants', + exportType: 'grid', + iconCls: 'sm-export-icon', + text: 'CSV' + },{ + xtype: 'tbfill' + },{ + xtype: 'tbseparator' + }, + totalTextCmp + ] + }), + listeners: { viewready: function (grid) { // Setup the tooltip for column 'accessLevel' @@ -650,7 +685,6 @@ SM.Collection.CreateForm = Ext.extend(Ext.form.FormPanel, { title: 'Metadata', iconCls: 'sm-database-save-icon', name: 'metadata', - // ignoreKeys: ['importOptions'], anchor: '100% 0', border: true, hidden: true @@ -773,7 +807,6 @@ SM.Collection.CreateForm = Ext.extend(Ext.form.FormPanel, { hideLabels: true, border: false, baseCls: 'x-plain', - // style: 'background-color: white;', items: [ { layoutConfig: { @@ -797,7 +830,6 @@ SM.Collection.CreateForm = Ext.extend(Ext.form.FormPanel, { return ret; } }, - // style: 'background-color: white;', xtype: 'fieldset', region: 'north', height: 180, @@ -829,8 +861,7 @@ SM.Collection.CreateForm = Ext.extend(Ext.form.FormPanel, { } }) -SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { - // SM.Collection.ManagePanel = Ext.extend(Ext.Panel, { +SM.Collection.ManagePanel = Ext.extend(Ext.Panel, { initComponent: function () { let _this = this this.canModifyOwners = !!this.canModifyOwners @@ -868,7 +899,7 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { value: _this.apiCollection?.name, name: 'name', allowBlank: false, - anchor: '100%', + anchor: '-5', enableKeyEvents: true, keys: [ { @@ -911,65 +942,12 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { } } }) - const delButton = new Ext.Button({ - iconCls: 'sm-hover-icon sm-trash-icon', - tooltip: 'Delete', - width: 25, - template: new Ext.Template( - '', - '', - '', - '', - '
  
  
  
'), - border: false, - handler: async function () { - try { - var confirmStr = "Deleting this Collection will permanently remove all data associated with the Collection. This includes all Assets and their associated assessments. The deleted data cannot be recovered.

Do you wish to delete the Collection?"; - Ext.Msg.confirm("Confirm", confirmStr, async function (btn, text) { - if (btn == 'yes') { - let result = await Ext.Ajax.requestPromise({ - url: `${STIGMAN.Env.apiBase}/collections/${_this.collectionId}`, - method: 'DELETE' - }) - let apiCollection = JSON.parse(result.response.responseText) - SM.Dispatcher.fireEvent('collectiondeleted', apiCollection.collectionId) - } - }) - } - catch (e) { - SM.Error.handleError(e) - } - } - }) - const cloneButton = new Ext.Button({ - iconCls: 'sm-hover-icon sm-clone-icon', - tooltip: 'Clone', - width: 25, - template: new Ext.Template( - '', - '', - '', - '', - '
  
  
  
'), - border: false, - handler: async function () { - try { - await SM.CollectionClone.showCollectionClone({ - collectionId: _this.collectionId, - sourceName: nameField.getValue() - }) - } - catch (e) { - SM.Error.handleError(e) - } - } - }) const descriptionField = new Ext.form.TextArea({ fieldLabel: 'Description', labelStyle: 'font-weight: 600;', value: _this.apiCollection?.description, name: 'description', - anchor: '100% 0', + anchor: '-5 -35', listeners: { change: async (field, newValue, oldValue) => { try { @@ -992,9 +970,7 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { title: 'Metadata', iconCls: 'sm-database-save-icon', name: 'metadata', - // ignoreKeys: ['importOptions'], - anchor: '100% 0', - border: true, + border: false, listeners: { metadatachanged: async grid => { try { @@ -1004,8 +980,6 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { method: 'PATCH', jsonData: data }) - // const apiCollection = JSON.parse(result.response.responseText) - // SM.Dispatcher.fireEvent('collectionchanged', apiCollection) const sortstate = grid.store.getSortState() grid.store.sort([sortstate]) } @@ -1022,7 +996,6 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { iconCls: 'sm-stig-icon', fieldSettings: _this.apiCollection?.settings?.fields, border: true, - autoHeight: true, onFieldSelect: async function (fieldset) { try { const apiCollection = await updateSettings() @@ -1079,19 +1052,6 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { } }) - let firstItem = nameField - if (this.allowDelete || this.allowClone) { - const items = [nameField] - if (this.allowClone) items.push(cloneButton) - if (this.allowDelete) items.push(delButton) - nameField.flex = 1 - firstItem = { - xtype: 'compositefield', - labelStyle: 'font-weight: 600;', - items - } - } - const grantHandler = async grid => { try { let data = grid.getValue() @@ -1120,7 +1080,7 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { projection: 'grants' }, title: 'Grants', - border: true, + border: false, listeners: { grantschanged: grantHandler, grantsremoved: grantHandler @@ -1132,7 +1092,7 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { collectionId: _this.apiCollection.collectionId, iconCls: 'sm-label-icon', title: 'Labels', - border: true, + border: false, listeners: { labeldeleted: async (labelId) => { try { @@ -1196,12 +1156,55 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { }) this.labelGrid.setValue(_this.apiCollection.labels) + const tools = [] + if (this.allowDelete) { + tools.push({ + id: 'trash', + qtip: 'Delete', + handler: async function () { + try { + var confirmStr = "Deleting this Collection will permanently remove all data associated with the Collection. This includes all Assets and their associated assessments. The deleted data cannot be recovered.

Do you wish to delete the Collection?"; + Ext.Msg.confirm("Confirm", confirmStr, async function (btn, text) { + if (btn == 'yes') { + let result = await Ext.Ajax.requestPromise({ + url: `${STIGMAN.Env.apiBase}/collections/${_this.collectionId}`, + method: 'DELETE' + }) + let apiCollection = JSON.parse(result.response.responseText) + SM.Dispatcher.fireEvent('collectiondeleted', apiCollection.collectionId) + } + }) + } + catch (e) { + SM.Error.handleError(e) + } + } + }) + } + if (this.allowClone) { + tools.push({ + id: 'clone', + qtip: 'Clone', + handler: async function () { + try { + await SM.CollectionClone.showCollectionClone({ + collectionId: _this.collectionId, + sourceName: nameField.getValue() + }) + } + catch (e) { + SM.Error.handleError(e) + } + } + }) + } + let config = { title: this.title || 'Collection properties', - layout: 'form', + collapseFirst: false, + tools, + layout: 'border', cls: 'sm-collection-manage-layout sm-round-panel', - labelWidth: 100, - padding: 15, getFieldValues: function (dirtyOnly) { // Override Ext.form.FormPanel implementation to check submitValue let o = {}, n, key, val; @@ -1225,76 +1228,45 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { }, items: [ { - layout: 'border', - anchor: '100% 0', - hideLabels: true, + xtype: 'panel', border: false, - baseCls: 'x-plain', - // style: 'background-color: white;', - items: [ - { - layoutConfig: { - getLayoutTargetSize : function() { - var target = this.container.getLayoutTarget(), ret = {}; - if (target) { - ret = target.getViewSize(); - - // IE in strict mode will return a width of 0 on the 1st pass of getViewSize. - // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly - // with getViewSize - if (Ext.isIE9m && Ext.isStrict && ret.width == 0){ - ret = target.getStyleSize(); - } - ret.width -= target.getPadding('lr'); - ret.height -= target.getPadding('tb'); - // change in this override to account for space used by - // the Result combo box and the 4px bottom-margin of each textarea - ret.height -= 30 - } - return ret; - } - }, - // style: 'background-color: white;', - xtype: 'fieldset', - region: 'north', - height: 200, - split: true, - title: 'Information', - items: [ firstItem, descriptionField] - }, + region: 'north', + height: 160, + layout: 'form', + margins: '15 15 15 15', + items: [ nameField, descriptionField] + }, + { + xtype: 'tabpanel', + region: 'center', + activeTab: 0, + border: false, + items: [ + grantGrid, { - xtype: 'tabpanel', - style: { - paddingTop: "10px" + xtype: 'panel', + bodyStyle: { + overflowY: 'auto', + overflowX: 'hidden' }, - region: 'center', - activeTab: 0, + title: 'Settings', + layout: 'form', + iconCls: 'sm-setting-icon', border: false, - items: [ - grantGrid, - { - xtype: 'panel', - title: 'Settings', - autoScroll: true, - layout: 'form', - iconCls: 'sm-setting-icon', - border: true, - padding: 10, - items: [ - settingsReviewFields, - settingsStatusFields, - settingsHistoryFields, - settingsImportOptions - ] - }, - metadataGrid, - this.labelGrid - ] - - } - - ] + padding: 10, + items: [ + settingsReviewFields, + settingsStatusFields, + settingsHistoryFields, + settingsImportOptions + ] + }, + metadataGrid, + this.labelGrid + ] + } + ] } Ext.apply(this, Ext.apply(this.initialConfig, config)) @@ -1302,6 +1274,7 @@ SM.Collection.ManagePanel = Ext.extend(Ext.form.FormPanel, { } }) + Ext.reg('sm-collection-panel', SM.Collection.ManagePanel); Ext.ns('SM.Collection.FieldSettings') @@ -1412,7 +1385,7 @@ SM.Collection.FieldSettings.ReviewFields = Ext.extend(Ext.form.FieldSet, { name: 'detailRequired', enabledField: detailEnabledCombo, value: _this.fieldSettings.detail.required, - anchor: '100%', + anchor: '-5', listeners: { select: onSelect } @@ -1431,7 +1404,7 @@ SM.Collection.FieldSettings.ReviewFields = Ext.extend(Ext.form.FieldSet, { name: 'commentRequired', enabledField: commentEnabledCombo, value: _this.fieldSettings.comment.required, - anchor: '100%', + anchor: '-5', listeners: { select: onSelect } @@ -1475,7 +1448,7 @@ SM.Collection.FieldSettings.ReviewFields = Ext.extend(Ext.form.FieldSet, { baseCls: 'x-plain', items: [ { - columnWidth: .34, + width: 140, layout: 'form', hideLabels: true, border: false, @@ -1501,7 +1474,7 @@ SM.Collection.FieldSettings.ReviewFields = Ext.extend(Ext.form.FieldSet, { ] }, { - columnWidth: .33, + columnWidth: .5, border: false, hideLabels: true, layout: 'form', @@ -1516,7 +1489,7 @@ SM.Collection.FieldSettings.ReviewFields = Ext.extend(Ext.form.FieldSet, { ] }, { - columnWidth: .33, + columnWidth: .5, layout: 'form', hideLabels: true, border: false, @@ -1626,7 +1599,7 @@ SM.Collection.StatusSettings.StatusFields = Ext.extend(Ext.form.FieldSet, { }) const grantComboBox = new SM.Collection.StatusSettings.GrantComboBox({ name: 'minAcceptGrant', - fieldLabel: 'Grant required to set Accept or Reject', + fieldLabel: 'Grant required to set Accept or Reject', disabled: !_this.statusSettings.canAccept, width: 125, value: _this.statusSettings.minAcceptGrant, @@ -1895,11 +1868,6 @@ SM.Collection.LabelNameEditor = Ext.extend(Ext.form.Field, { } } }) - // cpm.palette.renderTo = undefined - // cpm.palette.colors = [ - // '4568F2', '7000FF', 'E46300', '8A5000', '019900', 'DF584B', - // '99CCFF', 'D1ADFF', 'FFC399', 'FFF699', 'A3EA8F', 'F5A3A3', - // ] this.grid.editor.cpm = cpm this.namefield = new Ext.form.TextField({ value: this.ownerCt.record.data.name, @@ -2102,7 +2070,7 @@ SM.Collection.LabelsGrid = Ext.extend(Ext.grid.GridPanel, { editor: new Ext.form.TextField({submitValue: false}) }, { - header: '', + header: '', width: 15, dataIndex: 'uses', align: 'center', @@ -2129,11 +2097,54 @@ SM.Collection.LabelsGrid = Ext.extend(Ext.grid.GridPanel, { text: 'Tag Assets...', handler: function () { var r = _this.getSelectionModel().getSelected(); - // Ext.getBody().mask('Getting asset list for ' + r.get('name') + '...'); SM.Collection.showLabelAssetsWindow(_this.collectionId, r.get('labelId')); } }) + const cm = new Ext.grid.ColumnModel({ + columns + }) + const sm = new Ext.grid.RowSelectionModel({ + singleSelect: true, + listeners: { + selectionchange: function (sm) { + tbar.delButton.setDisabled(!sm.hasSelection()) + _this.assetBtn.setDisabled(!sm.hasSelection()) + } + } + }) + const view = new SM.ColumnFilters.GridView({ + emptyText: this.emptyText || 'No records to display', + deferEmptyText: false, + forceFit: true, + markDirty: false + }) + const totalTextCmp = new SM.RowCountTextItem ({ + store: labelStore, + noun: 'label', + iconCls: 'sm-label-icon' + }) + const bbar = new Ext.Toolbar({ + items: [ + { + xtype: 'exportbutton', + hasMenu: false, + gridBasename: 'CollectionLabels', + exportType: 'grid', + iconCls: 'sm-export-icon', + text: 'CSV', + gridSource: this + }, + { + xtype: 'tbfill' + }, + { + xtype: 'tbseparator' + }, + totalTextCmp + ] + }) + const config = { isFormField: true, name: 'labels', @@ -2142,31 +2153,11 @@ SM.Collection.LabelsGrid = Ext.extend(Ext.grid.GridPanel, { height: 150, plugins: [this.editor], store: labelStore, - cm: new Ext.grid.ColumnModel({ - columns: columns - }), - sm: new Ext.grid.RowSelectionModel({ - singleSelect: true, - listeners: { - selectionchange: function (sm) { - tbar.delButton.setDisabled(!sm.hasSelection()) - _this.assetBtn.setDisabled(!sm.hasSelection()) - } - } - }), - view: new SM.ColumnFilters.GridView({ - emptyText: this.emptyText || 'No records to display', - deferEmptyText: false, - forceFit: true, - markDirty: false - }), - listeners: { - // instances should handle 'labelchanged' - // instances should handle 'labelcreated' - // instances should handle 'labelremoved' - }, - tbar: tbar, - + cm, + sm, + view, + tbar, + bbar, getValue: function () { const labels = [] labelStore.data.items.forEach((i) => { @@ -2363,7 +2354,6 @@ SM.Collection.LabelAssetsForm = Ext.extend(Ext.form.FormPanel, { const config = { baseCls: 'x-plain', - // height: 400, labelWidth: 80, monitorValid: true, trackResetOnLoad: true, diff --git a/client/src/js/SM/CollectionStig.js b/client/src/js/SM/CollectionStig.js index 85d61a634..3233f1cc3 100644 --- a/client/src/js/SM/CollectionStig.js +++ b/client/src/js/SM/CollectionStig.js @@ -183,12 +183,12 @@ SM.CollectionStigsGrid = Ext.extend(Ext.grid.GridPanel, { } }) const deleteBtn = new Ext.Button({ - iconCls: 'icon-del', + iconCls: 'icon-remove', text: 'Unassign STIG...', disabled: true, handler: function() { try { - var confirmStr="Removing this STIG will remove all related Asset assignments. If the STIG is added in the future, the assignments will need to be established again."; + var confirmStr="Unassigning this STIG will remove all related Asset assignments. If the STIG is added in the future, the assignments will need to be established again."; Ext.Msg.confirm("Confirm", confirmStr, async function (btn,text) { if (btn == 'yes') { const stigRecord = _this.getSelectionModel().getSelected() diff --git a/client/src/js/collectionManager.js b/client/src/js/collectionManager.js index 054747116..335003828 100644 --- a/client/src/js/collectionManager.js +++ b/client/src/js/collectionManager.js @@ -28,7 +28,7 @@ async function addCollectionManager( params ) { let collectionPanel = new SM.Collection.ManagePanel({ collectionId: collectionId, apiCollection: apiCollection, - title: `Collection Properties (ID ${collectionId})`, + title: `Manage Collection (${collectionId})`, cls: 'sm-round-panel', margins: { top: SM.Margin.top, right: SM.Margin.adjacent, bottom: SM.Margin.bottom, left: SM.Margin.edge }, region: 'west', diff --git a/client/src/js/overrides.js b/client/src/js/overrides.js index 39c458bd8..6a3b33c57 100644 --- a/client/src/js/overrides.js +++ b/client/src/js/overrides.js @@ -1217,5 +1217,37 @@ Ext.Element.addMethods({ me.removeClass([XMASKED, XMASKEDRELATIVE]); } }, + // addStyles : function(sides, styles){ + // var ttlSize = 0, + // sidesArr = sides.match(wordsRe), + // side, + // size, + // i, + // len = sidesArr.length; + // for (i = 0; i < len; i++) { + // side = sidesArr[i]; + // size = side && parseInt(this.getStyle(styles[side]), 10); + // if (size) { + // ttlSize += MATH.abs(size); + // } + // } + // return ttlSize; + // }, }) +Ext.Element.prototype.addStyles = function(sides, styles){ + var ttlSize = 0, + sidesArr = sides.match(/\w/g), + side, + size, + i, + len = sidesArr.length; + for (i = 0; i < len; i++) { + side = sidesArr[i]; + size = side && parseFloat(this.getStyle(styles[side])); + if (size) { + ttlSize += Math.abs(size); + } + } + return ttlSize; +} diff --git a/client/src/js/stigman.js b/client/src/js/stigman.js index 180a44b29..c34168b03 100644 --- a/client/src/js/stigman.js +++ b/client/src/js/stigman.js @@ -118,7 +118,6 @@ async function loadApp () { layoutConfig: { tableAttrs: { style: { - width: '100%', padding: '20px', "table-layout": 'fixed'