Compare commits

..

10 Commits

Author SHA1 Message Date
f8fe37d41f Sanding and shimming on misc styles
- Tree icon shrinkage fixed;
- c-icon-button much better relative sizing;
- Removed c-button-set wrapper from Layout.vue;
- Added uppercasing of Create button for Snow theme;
2018-09-12 14:12:50 -07:00
4f5b9902a6 Object browse bar shippable
- Better layout approach;
- Refinements to button classes;
2018-09-12 10:39:24 -07:00
e5c2d7b256 Object browse bar WIP
- Layout of start-side elements now working with ellipsis;
- TODO: cleanups and consolidation;
2018-09-11 18:01:50 -07:00
6737c71c45 Object browse bar WIP
- view-control renamed to disclosure-triangle;
- Good progress on object browse bar elements;
2018-09-11 11:41:20 -07:00
ca055ab765 Object browse bar VERY WIP 2018-09-11 10:13:30 -07:00
4ba90ff73e Object browse bar IN PROGRESS 2018-09-11 10:13:25 -07:00
eaa971cb56 Vue main section overhaul (#2161)
* Separate browse object from conductor

* Main layout convert to flex; padding and overflow at leaf node

* Inspector converted to BEM - WIP

 - Properties pool upper level styles converted;
 - Grid mixins moved out of Inspector and into _mixins;

* Refinements to misc elements

- user-select: none on tree;
- :before and :after reset globally to use box-sizing: border-box;
- li reset globally;

* Styling for buttons and menus; add Create button

 - WIP

* Context and Create menus

 - WIP

* Add glyph backgrounds as data URIs

- For Create menu, items grid;
- Objects only;

* Create menu refinements

- Min/max height handling;
- Code cleanup;

* Main layout head styling; various sanding

- head layout refined;
- c-icon-button, c-button-set added;
- background glyph mixin refined;
- Antialiasing refined to increase icon sharpness;

* Fix SVG data URLs: encode # chars as %23
2018-09-11 10:10:59 -07:00
0301d88033 [Table] style refactor (#2157)
* [Table] Use Vue SFCs

Use Vue SFCs.  Use inject/provide to pass services to components
instead of wrapping components in closures.

* Convert CSS to BEM  - WIP!

- All in progress;
- Headers table divorced from old;
- Sizing working properly at this point;

* Reset legacy file, undo unintended change commit

* Convert CSS to BEM  - WIP!

- All in progress;
- Sizing table divorced from legacy;

* Convert CSS to BEM  - WIP!

- All in progress;
- Table body divorced from legacy;

* Convert CSS to BEM  - WIP!

- Near done, converted tabular-holder from legacy;
- Unit testing in main view and in Layout frames;
- Modded legacy CSS to properly hide control-bar with new naming
when in Layout frame;

* Convert CSS to BEM - done

- Cleanup and organization;

* Convert CSS to BEM

- Further code cleanup;

* Convert CSS to BEM

- Further code cleanup;
- Remove legacy table style imports;
2018-09-05 15:05:40 -07:00
e2e0cf17db Splitter refinement
- Arrow icons;
- Code cleanup;
2018-09-05 13:29:14 -07:00
01a39f4fb7 [Inspector] More vue
commit 9b735b4f70bf4d21f64a1e418a5f9d7342567104
Author: Pete Richards <peter.l.richards@nasa.gov>
Date:   Fri Aug 31 16:31:48 2018 -0700

    Slight HTML tweak

commit 3e58e140f9ea3640e5551d5f43abf837610c6fb4
Author: Pete Richards <peter.l.richards@nasa.gov>
Date:   Fri Aug 31 16:26:36 2018 -0700

    [Inspector] Wire up elements pool

    Elements pool wired up to show angular elements pool.

commit d9c60f31bd6d32a5d2e2227d5476edd81e2e4360
Author: Pete Richards <peter.l.richards@nasa.gov>
Date:   Fri Aug 31 13:56:04 2018 -0700

    [Inspector] vue inspector

    Create a vue inspctor which responds to selection events and shows
    object properties and inspector views.
2018-08-31 16:34:03 -07:00
43 changed files with 1538 additions and 942 deletions

View File

@ -66,5 +66,4 @@
</mct-representation>
</div>
</div>
<mct-include key="'conductor'" class="abs holder flex-elem flex-fixed l-flex-row l-time-conductor-holder"></mct-include>
</div>

View File

@ -319,6 +319,12 @@ define([
]
}
],
"templates": [
{
key: "elementsPool",
template: elementsTemplate
}
],
"components": [
{
"type": "decorator",

View File

@ -55,7 +55,7 @@ define(
// A view is editable unless explicitly flagged as not
(views || []).forEach(function (view) {
if (isEditable(view) ||
if (view.editable === true ||
(view.key === 'plot' && type.getKey() === 'telemetry.panel') ||
(view.key === 'table' && type.getKey() === 'table') ||
(view.key === 'rt-table' && type.getKey() === 'rttable')
@ -64,14 +64,6 @@ define(
}
});
function isEditable(view) {
if (typeof view.editable === Function) {
return view.editable(domainObject.useCapability('adapter'));
} else {
return view.editable === true;
}
}
return count;
};

View File

@ -31,7 +31,6 @@ define([
'./plugins/plugins',
'./adapter/indicators/legacy-indicators-plugin',
'./plugins/buildInfo/plugin',
'./adapter/vue-adapter/install',
'./ui/registries/ViewRegistry',
'./ui/registries/InspectorViewRegistry',
'./ui/registries/ToolbarRegistry',
@ -51,7 +50,6 @@ define([
plugins,
LegacyIndicatorsPlugin,
buildInfoPlugin,
installVueAdapter,
ViewRegistry,
InspectorViewRegistry,
ToolbarRegistry,
@ -336,8 +334,6 @@ define([
});
domElement.appendChild(appLayout.$mount().$el);
console.log('Attaching adapter');
installVueAdapter(appLayout, this);
this.router.start();
this.emit('start');

View File

@ -1,41 +0,0 @@
define([
], function (
) {
class InspectorAdapter {
constructor(layout, openmct) {
console.log('installing inspector adapter');
this.openmct = openmct;
this.layout = layout;
this.$injector = openmct.$injector;
this.angular = openmct.$angular;
this.objectService = this.$injector.get('objectService');
this.templateLinker = this.$injector.get('templateLinker');
this.$timeout = this.$injector.get('$timeout');
this.templateMap = {};
this.$injector.get('templates[]').forEach((t) => {
this.templateMap[t.key] = this.templateMap[t.key] || t;
});
var $rootScope = this.$injector.get('$rootScope');
this.scope = $rootScope.$new();
this.templateLinker.link(
this.scope,
angular.element(layout.$refs.inspector.$refs.properties),
this.templateMap["inspectorRegion"]
);
this.$timeout(function () {
//hello!
});
}
}
return InspectorAdapter;
});

View File

@ -1,16 +0,0 @@
define([
'./main-adapter',
'./tree-adapter',
'./inspector-adapter'
], function (
MainAdapter,
TreeAdapter,
InspectorAdapter
) {
return function install(layout, openmct) {
let main = new MainAdapter(layout, openmct);
let tree = new TreeAdapter(layout, openmct);
let inspector = new InspectorAdapter(layout, openmct);
}
});

View File

@ -1,153 +0,0 @@
define([
], function (
) {
// Find an object in an array of objects.
function findObject(domainObjects, id) {
var i;
for (i = 0; i < domainObjects.length; i += 1) {
if (domainObjects[i].getId() === id) {
return domainObjects[i];
}
}
}
// recursively locate and return an object inside of a container
// via a path. If at any point in the recursion it fails to find
// the next object, it will return the parent.
function findViaComposition(containerObject, path) {
var nextId = path.shift();
if (!nextId) {
return containerObject;
}
return containerObject.useCapability('composition')
.then(function (composees) {
var nextObject = findObject(composees, nextId);
if (!nextObject) {
return containerObject;
}
if (!nextObject.hasCapability('composition')) {
return nextObject;
}
return findViaComposition(nextObject, path);
});
}
function getLastChildIfRoot(object) {
if (object.getId() !== 'ROOT') {
return object;
}
return object.useCapability('composition')
.then(function (composees) {
return composees[composees.length - 1];
});
}
function pathForObject(domainObject) {
var context = domainObject.getCapability('context'),
objectPath = context ? context.getPath() : [],
ids = objectPath.map(function (domainObj) {
return domainObj.getId();
});
return "/browse/" + ids.slice(1).join("/");
}
class MainAdapter {
constructor(layout, openmct) {
this.openmct = openmct;
this.layout = layout;
this.$injector = openmct.$injector;
this.angular = openmct.$angular;
this.objectService = this.$injector.get('objectService');
this.templateLinker = this.$injector.get('templateLinker');
this.navigationService = this.$injector.get('navigationService');
this.$timeout = this.$injector.get('$timeout');
this.templateMap = {};
this.$injector.get('templates[]').forEach((t) => {
this.templateMap[t.key] = this.templateMap[t.key] || t;
});
var $rootScope = this.$injector.get('$rootScope');
this.scope = $rootScope.$new();
this.scope.representation = {};
openmct.router.route(/^\/browse\/(.*)$/, (path, results) => {
let navigatePath = results[1];
if (!navigatePath) {
navigatePath = 'mine';
}
this.navigateToPath(navigatePath);
});
this.navigationService.addListener(o => this.navigateToObject(o));
}
navigateToPath(path) {
if (!Array.isArray(path)) {
path = path.split('/');
}
return this.getObject('ROOT')
.then(root => {
return findViaComposition(root, path);
})
.then(getLastChildIfRoot)
.then(object => {
this.setMainViewObject(object);
});
}
setMainViewObject(object) {
this.scope.domainObject = object;
this.scope.navigatedObject = object;
this.templateLinker.link(
this.scope,
angular.element(this.layout.$refs.mainContainer),
this.templateMap["browseObject"]
);
document.title = object.getModel().name;
this.scheduleDigest();
}
idsForObject(domainObject) {
return this.urlService
.urlForLocation("", domainObject)
.replace('/', '');
}
navigateToObject(object) {
let path = pathForObject(object);
let views = object.useCapability('view');
let params = this.openmct.router.getParams();
let currentViewIsValid = views.some(v => v.key === params['view']);
if (!currentViewIsValid) {
this.scope.representation = {
selected: views[0]
}
this.openmct.router.update(path, {
view: views[0].key
});
} else {
this.openmct.router.setPath(path);
}
}
scheduleDigest() {
this.$timeout(function () {
// digest done!
});
}
getObject(id) {
return this.objectService.getObjects([id])
.then(function (results) {
return results[id];
});
}
}
return MainAdapter;
});

View File

@ -1,15 +0,0 @@
define([
], function (
) {
class TreeAdapter {
constructor(layout, openmct) {
}
}
return TreeAdapter;
});

View File

@ -20,18 +20,20 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import CSV from 'comma-separated-values';
import {saveAs} from 'file-saver/FileSaver';
class CSVExporter {
export(rows, options) {
let headers = (options && options.headers) ||
(Object.keys((rows[0] || {})).sort());
let filename = (options && options.filename) || "export.csv";
let csvText = new CSV(rows, { header: headers }).encode();
let blob = new Blob([csvText], { type: "text/csv" });
saveAs(blob, filename);
define([
'csv',
'saveAs'
], function (CSV, saveAs) {
class CSVExporter {
export(rows, options) {
let headers = (options && options.headers) ||
(Object.keys((rows[0] || {})).sort());
let filename = (options && options.filename) || "export.csv";
let csvText = new CSV(rows, { header: headers }).encode();
let blob = new Blob([csvText], { type: "text/csv" });
saveAs(blob, filename);
}
}
};
export default CSVExporter;
return CSVExporter;
});

View File

@ -1,123 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import _ from 'lodash';
import MCT from '../../MCT.js';
import ObjectViewsRegistry from '../../ui/registries/ViewRegistry.js';
import InspectorViewsRegistry from '../../ui/registries/InspectorViewRegistry.js';
import TelemetryTableViewProvider from './TelemetryTableViewProvider.js';
import TableConfigurationViewProvider from './TableConfigurationViewProvider.js';
fdescribe('The TelemetryTable plugin', function() {
let openmct;
let tableType;
let objectViewsSpy;
let inspectorViewsSpy;
beforeEach(function () {
objectViewsSpy = spyOn(ObjectViewsRegistry.prototype, 'addProvider');
inspectorViewsSpy = spyOn(InspectorViewsRegistry.prototype, 'addProvider');
openmct = new MCT();
tableType = openmct.types.get('table');
});
describe('defines a telemetry object type', function () {
it('that is registered with the type registry.', function () {
expect(tableType).toBeDefined();
});
it('that is createable.', function () {
expect(tableType.definition.creatable).toBe(true);
});
describe('that initializes new table object.', function () {
let tableObject;
beforeEach(function () {
tableObject = {};
tableType.definition.initialize(tableObject);
});
it('with valid default configuration.', function () {
expect(tableObject.configuration.hiddenColumns).toBeDefined();
});
it('to support composition.', function () {
expect(tableObject.composition).toBeDefined();
});
});
});
it('registers the table view provider', function () {
expect(objectViewsSpy).toHaveBeenCalledWith(new TelemetryTableViewProvider(openmct));
});
it('registers the table configuration view provider', function () {
expect(inspectorViewsSpy).toHaveBeenCalledWith(new TableConfigurationViewProvider(openmct));
});
/*
it('defines a view for telemetry objects', function() {
let tableObject = createTableObject();
let views = openmct.objectViews.get(tableObject);
expect(findTableView(views)).toBeDefined();
});
it('defines a table view for telemetry objects', function() {
let telemetryObject = createTelemetryObject();
let views = openmct.objectViews.get(telemetryObject);
expect(findTableView(views)).toBeDefined();
});
it('defines a configuration view for table objects', function() {
let tableObject = createTableObject();
let selection = createSelection(tableObject);
let views = openmct.inspectorViews.get(selection);
expect(views).toBeDefined();
expect(findTableView(views)).toBeDefined();
});
function findTableView(views) {
return views.find(view => view.key === 'table');
}
function createTableObject() {
let tableObject = {};
tableType.definition.initialize(tableObject);
return tableObject;
}
function createTelemetryObject() {
return {
telemetry: {}
};
}
function createSelection(object) {
return [{
context: {
item: object
}
}];
}
*/
});

View File

@ -1,42 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import _ from 'lodash';
import MCT from '../../MCT.js';
import TelemetryTablePlugin from './plugin.js';
describe('The TelemetryTable view', function() {
let mockTimeSystem;
let openmct;
let tablePlugin;
beforeEach(function () {
openmct = new MCT();
mockTimeSystem = {
key: 'utc'
};
spyOn(openmct.time, 'timeSystem');
openmct.time.timeSystem.and.returnValue(mockTimeSystem);
});
//it('allows editing of table objects');
//it('does not allow editing of telemetry objects');
});

View File

@ -30,11 +30,12 @@ define([], function () {
this.objectKeyString = objectKeyString;
}
getFormattedDatum(headers) {
return Object.keys(headers).reduce((formattedDatum, columnKey) => {
formattedDatum[columnKey] = this.getFormattedValue(columnKey);
return formattedDatum;
}, {});
getFormattedDatum() {
return Object.values(this.columns)
.reduce((formattedDatum, column) => {
formattedDatum[column.getKey()] = this.getFormattedValue(column.getKey());
return formattedDatum;
}, {});
}
getFormattedValue(key) {

View File

@ -30,7 +30,7 @@ define(function () {
initialize(domainObject) {
domainObject.composition = [];
domainObject.configuration = {
hiddenColumns: {}
columns: {}
};
}
}

View File

@ -35,14 +35,12 @@ define([
return {
key: 'table',
name: 'Telemetry Table',
editable: function(domainObject) {
return domainObject.type === 'table';
},
editable: true,
canView: function (domainObject) {
return domainObject.type === 'table' || domainObject.hasOwnProperty('telemetry');
},
view: function (domainObject) {
let csvExporter = new CSVExporter.default();
let csvExporter = new CSVExporter();
let table = new TelemetryTable(domainObject, openmct);
let component;
return {

View File

@ -1,111 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
import _ from 'lodash';
import MCT from '../../../MCT.js';
import SortedTableRowCollection from './SortedTableRowCollection.js';
describe('The SortedTableRowCollection', function() {
let mockTimeSystem;
let openmct;
let rows;
let mockSortedIndex;
beforeEach(function () {
openmct = new MCT();
mockTimeSystem = {
key: 'utc'
};
spyOn(openmct.time, 'timeSystem');
openmct.time.timeSystem.and.returnValue(mockTimeSystem);
rows = new BoundedTableRowCollection(openmct);
});
describe('Shortcut behavior', function() {
let testTelemetry;
beforeEach(function() {
testTelemetry = [
{
datum: {utc: 100}
}, {
datum: {utc: 200}
}, {
datum: {utc: 300}
}, {
datum: {utc: 400}
}
];
rows.add(testTelemetry);
mockSortedIndex = spyOn(_, 'sortedIndex');
mockSortedIndex.and.callThrough();
});
describe('when sorted ascending', function () {
it('Uses lodash sortedIndex to find insertion point when test value is between first and last values', function () {
rows.add({
datum: {utc: 250}
});
expect(mockSortedIndex).toHaveBeenCalled();
});
it('shortcuts insertion point search when test value is greater than last value', function() {
rows.add({
datum: {utc: 500}
});
expect(mockSortedIndex).not.toHaveBeenCalled();
});
it('shortcuts insertion point search when test value is less than or equal to first value', function () {
rows.add({
datum: {utc: 100}
});
rows.add({
datum: {utc: 50}
});
expect(mockSortedIndex).not.toHaveBeenCalled();
});
});
describe('when sorted descending', function () {
it('Uses lodash sortedIndex to find insertion point when test value is between first and last values', function () {
rows.add({
datum: {utc: 250}
});
expect(mockSortedIndex).toHaveBeenCalled();
});
it('shortcuts insertion point search when test value is greater than last value', function() {
rows.add({
datum: {utc: 500}
});
expect(mockSortedIndex).not.toHaveBeenCalled();
});
it('shortcuts insertion point search when test value is less than or equal to first value', function () {
rows.add({
datum: {utc: 100}
});
rows.add({
datum: {utc: 50}
});
expect(mockSortedIndex).not.toHaveBeenCalled();
});
});
it('Evicts old telemetry on bounds change');
it('Does not drop data that falls ahead of end bounds');
});
});

View File

@ -82,7 +82,8 @@ define(
// Going to check for duplicates. Bound the search problem to
// items around the given time. Use sortedIndex because it
// employs a binary search which is O(log n). Can use binary search
// because the array is guaranteed ordered due to sorted insertion.
// based on time stamp because the array is guaranteed ordered due
// to sorted insertion.
let startIx = this.sortedIndex(this.rows, row);
let endIx = undefined;
@ -112,49 +113,26 @@ define(
* @private
*/
sortedIndex(rows, testRow, lodashFunction) {
if (this.rows.length === 0) {
return 0;
}
const sortOptionsKey = this.sortOptions.key;
const testRowValue = testRow.datum[sortOptionsKey];
const firstValue = this.rows[0].datum[sortOptionsKey];
const lastValue = this.rows[this.rows.length - 1].datum[sortOptionsKey];
lodashFunction = lodashFunction || _.sortedIndex;
if (this.sortOptions.direction === 'asc') {
if (testRowValue > lastValue) {
return this.rows.length;
} else if (testRowValue === lastValue) {
return this.rows.length - 1;
} else if (testRowValue <= firstValue) {
return 0;
} else {
return lodashFunction(rows, testRow, (thisRow) => {
return thisRow.datum[sortOptionsKey];
});
}
return lodashFunction(rows, testRow, (thisRow) => {
return thisRow.datum[sortOptionsKey];
});
} else {
if (testRowValue >= firstValue) {
return 0;
} else if (testRowValue < lastValue) {
return this.rows.length;
} else if (testRowValue === lastValue) {
return this.rows.length - 1;
} else {
// Use a custom comparison function to support descending sort.
return lodashFunction(rows, testRow, (thisRow) => {
const thisRowValue = thisRow.datum[sortOptionsKey];
if (testRowValue === thisRowValue) {
return EQUAL;
} else if (testRowValue < thisRowValue) {
return LESS_THAN;
} else {
return GREATER_THAN;
}
});
}
const testRowValue = testRow.datum[this.sortOptions.key];
// Use a custom comparison function to support descending sort.
return lodashFunction(rows, testRow, (thisRow) => {
const thisRowValue = thisRow.datum[sortOptionsKey];
if (testRowValue === thisRowValue) {
return EQUAL;
} else if (testRowValue < thisRowValue) {
return LESS_THAN;
} else {
return GREATER_THAN;
}
});
}
}

View File

@ -15,7 +15,7 @@ export default {
data: function () {
return {
rowTop: (this.rowOffset + this.rowIndex) * this.rowHeight + 'px',
formattedRow: this.row.getFormattedDatum(this.headers),
formattedRow: this.row.getFormattedDatum(),
rowLimitClass: this.row.getRowLimitClass(),
cellLimitClasses: this.row.getCellLimitClasses()
}
@ -59,7 +59,7 @@ export default {
this.rowTop = (rowOffset + this.rowIndex) * this.rowHeight + 'px';
},
formatRow: function (row) {
this.formattedRow = row.getFormattedDatum(this.headers);
this.formattedRow = row.getFormattedDatum();
this.rowLimitClass = row.getRowLimitClass();
this.cellLimitClasses = row.getCellLimitClasses();
}

View File

@ -80,7 +80,8 @@
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
> [class*="__"] + [class*="__"] {
&__control-bar,
&__headers-w {
// Don't allow top level elements to grow or shrink
flex: 0 0 auto;
}
@ -89,6 +90,7 @@
th, td {
display: block;
flex: 1 0 auto;
font-size: 0.7rem; // TEMP LEGACY TODO: refactor this when __main-container font-size is dealt with
white-space: nowrap;
min-width: $min-w;
padding: $tabularTdPadTB $tabularTdPadLR;
@ -203,7 +205,7 @@
/******************************* WRAPPERS */
&__body-w {
// Wraps __body table provides scrolling
flex: 1 1 100% !important; // TODO: temp override on tabular-holder > * { style which sets this to 0 0 auto
flex: 1 1 100%;
overflow-x: auto;
overflow-y: scroll;
}
@ -233,7 +235,7 @@
z-index: -1;
visibility: hidden;
pointer-events: none;
position: absolute !important; // TODO: fix tabular-holder > * { which sets this to pos: relative
position: absolute;
//Add some padding to allow for decorations such as limits indicator
tr {
@ -280,6 +282,7 @@ export default {
data() {
return {
headers: {},
headersCount: 0,
visibleRows: [],
columnWidths: [],
sizingRows: {},
@ -343,6 +346,7 @@ export default {
let headers = this.table.configuration.getVisibleHeaders();
this.headers = headers;
this.headersCount = Object.values(headers).length;
this.$nextTick().then(this.calculateColumnWidths);
},
setSizingTableWidth() {
@ -450,12 +454,12 @@ export default {
}
},
exportAsCSV() {
const headerKeys = Object.keys(this.headers);
const justTheData = this.table.filteredRows.getRows()
.map(row => row.getFormattedDatum(this.headers));
.map(row => row.getFormattedDatum());
const headers = Object.keys(this.headers);
this.csvExporter.export(justTheData, {
filename: this.table.domainObject.name + '.csv',
headers: headerKeys
headers: headers
});
},
outstandingRequests(loading) {

View File

@ -12,6 +12,7 @@
}
// Global
$fontBaseSize: 12px;
$colorBodyBg: #fcfcfc;
$colorBodyFg: #666;
$colorGenBg: #fff;
@ -19,6 +20,7 @@ $colorStatusBarBg: #000;
$colorStatusBarFg: #999;
$colorStatusBarFgHov: #aaa;
$colorKey: #0099cc;
$colorKeyFilter: brightness(0.9) sepia(1) hue-rotate(145deg) saturate(6);
$colorKeySelectedBg: $colorKey;
$colorKeyFg: #fff;
$colorKeyHov: #00c0f6;
@ -36,7 +38,8 @@ $overlayCr: 11px;
$shdwTextSubtle: rgba(black, 0.2) 0 1px 2px;
// Buttons and Controls
$colorBtnBg: pullForward($colorBodyBg, $contrastRatioPercent);
$btnPad: $interiorMargin, $interiorMargin * 1.25;
$colorBtnBg: #aaaaaa;
$colorBtnBgHov: pullForward($colorBtnBg, $hoverRatioPercent);
$colorBtnFg: #fff;
$colorBtnFgHov: $colorBtnFg;
@ -68,6 +71,7 @@ $sliderKnobR: 2px;
$timeControllerToiLineColor: $colorBodyFg;
$timeControllerToiLineColorHov: #0052b5;
$colorTransLucBg: #666; // Used as a visual blocking element over variable backgrounds, like imagery
$createBtnTextTransform: uppercase;
// Foundation Colors
$colorAlt1: #776ba2;
@ -90,17 +94,18 @@ $colorTick: rgba(black, 0.2);
$colorSelectableSelectedPrimary: $colorKey;
$colorSelectableHov: rgba($colorBodyFg, 0.4);
// Menu colors
// Menus
$colorMenuBg: pushBack($colorBodyBg, 10%);
$colorMenuFg: pullForward($colorMenuBg, 70%);
$colorMenuIc: $colorKey;
$colorMenuHovBg: pullForward($colorMenuBg, $hoverRatioPercent);
$colorMenuHovFg: $colorMenuFg;
$colorMenuHovIc: $colorMenuIc;
$colorMenuHovBg: $colorMenuIc; //pullForward($colorMenuBg, $hoverRatioPercent);
$colorMenuHovFg: $colorMenuBg;
$colorMenuHovIc: $colorMenuBg;
$shdwMenu: rgba(black, 0.5) 0 1px 5px;
$shdwMenuText: none;
$colorCreateMenuLgIcon: $colorKey;
$colorCreateMenuText: $colorBodyFg;
$menuItemPad: ($interiorMargin, nth($btnPad, 2));
// Form colors
$colorCheck: $colorKey;
@ -238,13 +243,14 @@ $scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
// Splitter
$splitterD: 7px;
$splitterHandleD: 2px;
$splitterHandleHitMargin: 4px;
$splitterGrippyD: ($splitterHandleD - 4, 75px, 50px); // thickness, length, min-length
$colorSplitterBaseBg: $colorBodyBg;
$colorSplitterBg: pullForward($colorSplitterBaseBg, 20%);
$colorSplitterFg: $colorBodyBg;
$colorSplitterHover: $colorKey; // pullForward($colorSplitterBg, $hoverRatioPercent * 2);
$colorSplitterActive: $colorKey;
$splitterBtnD: (16px, 35px);
$splitterBtnD: (16px, 35px); // height, width
$splitterBtnColorBg: #eee;
$splitterBtnColorFg: #999;
$splitterBtnColorHoverBg: rgba($colorKey, 1);

View File

@ -15,8 +15,10 @@ $interiorMarginLg: 10px;
$inputTextPTopBtm: 2px;
$inputTextPLeftRight: 5px;
$inputTextP: $inputTextPTopBtm $inputTextPLeftRight;
$menuLineH: 1.5rem;
$treeItemIndent: 16px;
$treeTypeIconW: 18px;
/*************** Items */
$itemPadLR: 5px;
$ueBrowseGridItemLg: 200px;
@ -111,6 +113,7 @@ $glyph-icon-frame-show: '\e1045';
$glyph-icon-frame-hide: '\e1046';
$glyph-icon-import: '\e1047';
$glyph-icon-export: '\e1048';
$glyph-icon-minimize: '\e1049'; // 12px only
$glyph-icon-activity: '\e1100';
$glyph-icon-activity-mode: '\e1101';
$glyph-icon-autoflow-tabular: '\e1102';
@ -142,4 +145,38 @@ $glyph-icon-timer: '\e1127';
$glyph-icon-topic: '\e1128';
$glyph-icon-box-with-dashed-lines: '\e1129';
$glyph-icon-summary-widget: '\e1130';
$glyph-icon-notebook: '\e1131';
$glyph-icon-notebook: '\e1131';
/************************** GLYPHS AS DATA URI */
// Only objects have been converted, for use in Create menu and folder views
$bg-icon-activity: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M288 32H160l160 160H174.872C152.74 153.742 111.377 128 64 128H0v256h64c47.377 0 88.74-25.742 110.872-64H320L160 480h128l224-224L288 32z'/%3e%3c/svg%3e");
$bg-icon-activity-mode: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M256 0C148.6 0 56.6 66.2 18.6 160H64c28.4 0 54 12.4 71.5 32H256l-96-96h128l160 160-160 160H160l96-96H135.5C118 339.6 92.4 352 64 352H18.6c38 93.8 129.9 160 237.4 160 141.4 0 256-114.6 256-256S397.4 0 256 0z'/%3e%3c/svg%3e");
$bg-icon-autoflow-tabular: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M96 0C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h32V0H96zM192 0h128v512H192zM416 0h-32v352h128V96c0-52.8-43.2-96-96-96z'/%3e%3c/svg%3e");
$bg-icon-clock: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M256 0C114.62 0 0 114.62 0 256s114.62 256 256 256 256-114.62 256-256S397.38 0 256 0zm135 345a36 36 0 0 1-31.21 18 35.83 35.83 0 0 1-18-4.83l-110.85-64-.14-.08q-.6-.35-1.19-.73l-.43-.28-.93-.64-.63-.45-.63-.48-.85-.67-.32-.27c-.36-.3-.72-.61-1.07-.92a35.76 35.76 0 0 1-6.52-7.9c-.14-.23-.27-.47-.41-.7s-.29-.49-.43-.74a35.75 35.75 0 0 1-3.58-9.59v-.06c-.1-.46-.19-.92-.27-1.38 0-.14-.05-.28-.08-.42-.06-.35-.11-.71-.15-1.07s-.07-.52-.1-.79-.05-.51-.07-.77l-.09-1.12v-.52-1.39V81a36 36 0 0 1 36-36 36 36 0 0 1 36 36v161.22l92.85 53.61A36 36 0 0 1 391 345z' fill='%2300a14b'/%3e%3c/svg%3e");
$bg-icon-database: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M256 256C114.615 256 0 213.019 0 160v256c0 53.019 114.615 96 256 96s256-42.981 256-96V160c0 53.019-114.615 96-256 96z'/%3e%3cellipse fill='%23666666' cx='256' cy='96' rx='256' ry='96'/%3e%3c/svg%3e");
$bg-icon-database-query: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M341.76 409.643C316.369 423.871 287.118 432 256 432c-97.047 0-176-78.953-176-176S158.953 80 256 80s176 78.953 176 176c0 31.118-8.129 60.369-22.357 85.76l95.846 95.846C509.747 430.661 512 423.429 512 416V96c0-53.019-114.615-96-256-96S0 42.981 0 96v320c0 53.019 114.615 96 256 96 63.055 0 120.774-8.554 165.388-22.73l-79.628-79.627z'/%3e%3cpath fill='%23666666' d='M176 256c0 44.112 35.888 80 80 80s80-35.888 80-80-35.888-80-80-80-80 35.888-80 80z'/%3e%3c/svg%3e");
$bg-icon-dataset: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 96H288l-54.6-54.6-18.7-18.7C202.2 10.2 177.6 0 160 0H32C14.4 0 0 14.4 0 32v192c0-35.2 28.8-64 64-64h384c35.2 0 64 28.8 64 64v-64c0-35.2-28.8-64-64-64zM448 224H64c-35.2 0-64 28.8-64 64v160c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64zM160 448H96V288h64v160zm128 0h-64V288h64v160zm128 0h-64V288h64v160z'/%3e%3c/svg%3e");
$bg-icon-datatable: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M256 256C114.6 256 0 213 0 160v256c0 53 114.6 96 256 96s256-43 256-96V160c0 53-114.6 96-256 96zm192 31.5v128c-18.3 7.8-39.9 14.4-64 19.7v-128c24.1-5.3 45.7-11.9 64-19.7zm-320 19.7v128c-24.1-5.2-45.7-11.9-64-19.7v-128c18.3 7.8 39.9 14.4 64 19.7zM192 445V317c20.5 2 41.9 3 64 3s43.5-1.1 64-3v128c-20.5 2-41.9 3-64 3s-43.5-1.1-64-3z'/%3e%3cellipse fill='%23666666' cx='256' cy='96' rx='256' ry='96'/%3e%3c/svg%3e");
$bg-icon-dictionary: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M416 320c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96v160l-64-32-64 32V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96v-96c0 52.8-43.2 96-96 96H96v-96h320z'/%3e%3c/svg%3e");
$bg-icon-folder: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 96H288l-54.6-54.6-18.7-18.7C202.2 10.2 177.6 0 160 0H32C14.4 0 0 14.4 0 32v192c0-35.2 28.8-64 64-64h384c35.2 0 64 28.8 64 64v-64c0-35.2-28.8-64-64-64zM448 224H64c-35.2 0-64 28.8-64 64v160c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64z'/%3e%3c/svg%3e");
$bg-icon-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zm0 448H64V64h384v384z'/%3e%3cpath fill='%23666666' d='M160 128l-64 64v224h320V256l-64-64-64 64z'/%3e%3c/svg%3e");
$bg-icon-layout: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M224 0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h128V0zM416 0H288v288.832h224V96c0-52.8-43.2-96-96-96zM288 512h128c52.8 0 96-43.2 96-96v-64.832H288V512z'/%3e%3c/svg%3e");
$bg-icon-object: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='none' d='M256 96L76.8 208 256 320l179.2-112z'/%3e%3cpath fill='%23666666' d='M256 512l256-160V160L255.99 0 0 160v192l256 160zm0-416l179.2 112L256 320 76.8 208 256 96z'/%3e%3c/svg%3e");
$bg-icon-object-unknown: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M255-1L-1 159v192l256 160 256-160V159L255-1zm37.7 430.6c-10.6 10.4-23 15.4-38 15.4-15.6 0-28.1-4.9-38.1-14.8-10-10-14.8-22.4-14.8-38.1 0-15.2 5.1-27.6 15.5-38.1s22.6-15.6 37.4-15.6c14.8 0 27.1 5.2 37.8 16 10.7 10.8 15.9 23.2 15.9 38-.1 14.5-5.4 27-15.7 37.2zm26.4-156.3c-11.8 5.9-18.7 11-21.7 16.2-1.8 3.1-3 7.4-3.7 13.4v20.5H213v-22.1c0-20.1 2.2-34.9 6.5-44 4-8.6 11.3-15.1 22.4-20l17.4-7.7c16-7.1 24.1-17.6 24.1-31.4 0-8-3-15.2-8.6-20.9-5.6-5.6-12.8-8.6-20.8-8.6-12 0-27.2 5-31.4 28.7l-1.1 6.1H148l.7-8.1c2-22.3 8.5-41.2 19.4-56.1 9.8-13.5 22.8-24.3 38.5-32.3 15.7-8 32.3-12 49.1-12 30.3 0 55.1 9.7 75.7 29.8 20.6 20 30.6 44 30.6 73.6 0 35.4-14.4 60.7-42.9 74.9z'/%3e%3c/svg%3e");
$bg-icon-packet: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='none' d='M256 96L76.8 208 256 320l179.2-112z'/%3e%3cpath fill='%23666666' d='M256 0L0 160v256c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96V160L256 0zm0 96l179.2 112L256 320 76.8 208 256 96z'/%3e%3c/svg%3e");
$bg-icon-page: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M352 256c-52.8 0-96-43.2-96-96V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h320c52.8 0 96-43.2 96-96V256H352z'/%3e%3cpath fill='%23666666' d='M384 192h128L320 0v128c0 35.2 28.8 64 64 64z'/%3e%3c/svg%3e");
$bg-icon-plot-overlay: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M415 0H97C43.65 0 0 43.65 0 97v203.41c7.09 9.32 12.83 14.17 16 15.42 7.14-2.81 27.22-23.77 46.48-73C83.71 188.64 120.64 124 176 124c26.2 0 50.71 14.58 72.85 43.34 18.67 24.25 32.42 54.46 40.67 75.54 19.26 49.19 39.34 70.15 46.48 73 7.14-2.81 27.22-23.77 46.48-73C403.71 188.64 440.64 124 496 124a69.55 69.55 0 0 1 16 1.87V97c0-53.35-43.65-97-97-97z'/%3e%3cpath fill='%23666666' d='M496 196.17c-7.14 2.81-27.22 23.76-46.48 73C428.29 323.36 391.36 388 336 388c-26.2 0-50.71-14.58-72.85-43.34-18.67-24.25-32.42-54.46-40.67-75.54-19.26-49.19-39.34-70.15-46.48-73-7.14 2.81-27.22 23.76-46.48 73C108.29 323.36 71.36 388 16 388a69.56 69.56 0 0 1-16-1.87V415c0 53.35 43.65 97 97 97h318c53.35 0 97-43.65 97-97V211.59c-7.09-9.32-12.83-14.17-16-15.42z'/%3e%3c/svg%3e");
$bg-icon-plot-stacked: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M44.8 156c12.49 0 24.48-13.26 42.76-35.09 22.71-27.14 51-60.91 98-60.91 22.32 0 43.31 7.73 62.4 23 14.34 11.45 25.58 25.21 36.46 38.53C303.63 145 314 156 326.4 156H512V97c0-53.35-43.65-97-97-97H97C43.65 0 0 43.65 0 97v59h44.8z'/%3e%3cpath fill='%23666666' d='M264.75 205.2c-14.12-11.32-25.26-25-36-38.14C211 145.32 199.37 132 185.6 132c-12.53 0-24.54 13.27-42.83 35.12-22.7 27.12-51 60.88-98 60.88H0v56h185.6c22 0 42.77 7.67 61.65 22.8 14.12 11.32 25.26 25 36 38.14C301 366.68 312.63 380 326.4 380c12.53 0 24.54-13.27 42.83-35.12 22.7-27.12 51-60.88 98-60.88H512v-56H326.4c-22.03 0-42.77-7.67-61.65-22.8z'/%3e%3cpath fill='%23666666' d='M467.2 356c-12.49 0-24.48 13.26-42.76 35.09-22.71 27.14-51 60.91-98 60.91-22.32 0-43.31-7.73-62.4-23-14.34-11.45-25.58-25.21-36.46-38.53C208.37 367 198 356 185.6 356H0v59c0 53.35 43.65 97 97 97h318c53.35 0 97-43.65 97-97v-59h-44.8z'/%3e%3c/svg%3e");
$bg-icon-session: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M317.8 262.2c3.3 2.1 6.6 4.3 9.6 6.8l60.2 48.2c14.8 11.9 41.9 11.9 56.7 0l67.6-54c.1-2.4.1-4.7.1-7.1 0-26.1-3.9-51.2-11.1-74.9L423.5 243c-29.1 23.3-70.1 29.6-105.7 19.2zM124.3 317.1l60.2-48.2c29-23.2 70-29.6 105.6-19.2-3.3-2.1-6.6-4.3-9.6-6.8l-60.2-48.2c-14.8-11.9-41.9-11.9-56.7 0L103.5 243c-20 16-45.7 24-71.5 24-10.8 0-21.5-1.4-31.9-4.2v.8c2.5 1.7 5 3.4 7.3 5.3l60.2 48.2c14.9 11.9 41.9 11.9 56.7 0z'/%3e%3cpath fill='%23666666' d='M60.3 189.1l60.2-48.2c40.1-32.1 102.8-32.1 142.9 0l60.2 48.2c14.8 11.9 41.9 11.9 56.7 0l90.5-72.4C425.2 46.5 346 0 256 0 136.7 0 36.4 81.6 8 192.1c15.4 8.8 38.9 7.8 52.3-3zM344.5 371l-60.2-48.2c-14.8-11.9-41.9-11.9-56.7 0L167.5 371c-20 16-45.7 24-71.5 24-23.9 0-47.7-6.9-67.1-20.7C71.7 456.1 157.3 512 256 512s184.3-55.9 227.1-137.7c-40.2 28.7-99.9 27.6-138.6-3.3z'/%3e%3c/svg%3e");
$bg-icon-tabular: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zM320 224H192v-96h128v96zm-128 32h128v96H192v-96zm-32 96H32v-96h128v96zm0-224v96H32v-96h128zM64 480c-8.5 0-16.5-3.3-22.6-9.4S32 456.5 32 448v-64h128v96H64zm128 0v-96h128v96H192zm288-32c0 8.5-3.3 16.5-9.4 22.6S456.5 480 448 480h-96v-96h128v64zm0-96H352v-96h128v96zm0-128H352v-96h128v96z'/%3e%3c/svg%3e");
$bg-icon-tabular-lad: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 0H64C28.7.1.1 28.7 0 64v384c.1 35.3 28.7 63.9 64 64h384c35.3-.1 63.9-28.7 64-64V64c-.1-35.3-28.7-63.9-64-64zM32 128h128v96H32v-96zm0 128h128v96H32v-96zm32 224c-17.6-.1-31.9-14.4-32-32v-64h128v96H64zm128 0v-96h128v96H192zm288-32c-.1 17.6-14.4 31.9-32 32h-96v-96h128v64zm0-192v96H192v-96h32v-32h-32v-96h288v96h-32v32h32z'/%3e%3cpath fill='%23666666' d='M391.2 273.7L336 246.1V160c0-8.8-7.2-16-16-16s-16 7.2-16 16v105.9l72.8 36.4c7.9 4 17.5.8 21.5-7.2 4-7.8.8-17.5-7.1-21.4z'/%3e%3c/svg%3e");
$bg-icon-tabular-lad-set: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M64 384V96c-35.3.1-63.9 28.7-64 64v288c.1 35.3 28.7 63.9 64 64h288c35.3-.1 63.9-28.7 64-64H128c-35.3-.1-63.9-28.7-64-64z'/%3e%3cpath fill='%23666666' d='M448 0H160c-35.3.1-63.9 28.7-64 64v288c.1 35.3 28.7 63.9 64 64h288c35.3-.1 63.9-28.7 64-64V64c-.1-35.3-28.7-63.9-64-64zM128 96h96v64h-96V96zm0 96h96v96h-96v-96zm32 192c-17.6-.1-31.9-14.4-32-32v-32h96v64h-64zm96 0v-64h96v64h-96zm224-32c-.1 17.6-14.4 31.9-32 32h-64v-64h96v32zm0-64H256V96h224v192z'/%3e%3cpath fill='%23666666' d='M416 240c8.8 0 16-7.2 16-16 0-6.9-4.4-13-10.9-15.2L384 196.5V144c0-8.8-7.2-16-16-16s-16 7.2-16 16v75.5l58.9 19.6c1.7.6 3.4.9 5.1.9z'/%3e%3c/svg%3e");
$bg-icon-tabular-realtime: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M0 64v384c0 35.2 28.8 64 64 64h288c35.2 0 64-28.8 64-64V340c-19.8 7.8-41.4 12-64 12-35.4 0-68.4-10.5-96-28.6V352h-96v-96h35.3c-5.2-10.1-9.4-20.8-12.6-32H160v-96h22.7C203.6 54.2 271.6 0 352 0H64C28.8 0 0 28.8 0 64zm288 320h96v64c0 8.5-3.3 16.5-9.4 22.6S360.5 480 352 480h-64v-96zm-160 96H64c-8.5 0-16.5-3.3-22.6-9.4S32 456.5 32 448v-64h96v96zm0-128H32v-96h96v96zm32 32h96v96h-96v-96zm-32-160H32v-96h96v96z'/%3e%3cpath fill='%23666666' d='M192 160c0 88.4 71.6 160 160 160s160-71.6 160-160S440.4 0 352 0 192 71.6 192 160zm49.7 39.8L227 187.5c-1.4-6.4-2.3-12.9-2.7-19.6 15.1-.1 30.1-5 41.9-14.8l39.6-33c7.5-6.2 21.1-6.2 28.6 0l39.6 33c2.8 2.3 5.7 4.3 8.8 6.1-23-11.7-52.7-9.2-72.8 7.5l-39.6 33c-7.6 6.3-21.2 6.3-28.7.1zM352 288c-36.7 0-69.7-15.4-93-40.1 14.2-.6 28.1-5.5 39.2-14.7l39.6-33c7.5-6.2 21.1-6.2 28.6 0l39.6 33c11 9.2 25 14.1 39.2 14.7-23.5 24.7-56.5 40.1-93.2 40.1zm125.9-151.3c1.4 7.5 2.1 15.3 2.1 23.3 0 9.4-1 18.6-3 27.5l-14.7 12.3c-7.5 6.2-21.1 6.2-28.6 0l-39.6-33c-2.8-2.3-5.7-4.3-8.8-6.1 23 11.7 52.7 9.2 72.8-7.5l19.8-16.5zM352 32c46.4 0 87.1 24.7 109.5 61.7l-31.2 26c-7.5 6.2-21.1 6.2-28.6 0l-39.6-33c-23.6-19.7-60.6-19.7-84.3 0l-39.6 33c-2.5 2.1-5.7 3.5-9.1 4.2C244.7 70.8 293.8 32 352 32z'/%3e%3c/svg%3e");
$bg-icon-tabular-scrolling: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M32 0C14.4 0 0 14.4 0 32v96h224V0H32zM512 128V32c0-17.6-14.4-32-32-32H288v128h224zM0 192v96c0 17.6 14.4 32 32 32h192V192H0zM480 320c17.6 0 32-14.4 32-32v-96H288v128h192zM256 512L128 384h256z'/%3e%3c/svg%3e");
$bg-icon-telemetry: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M16 315.83c7.14-2.81 27.22-23.77 46.48-73C83.71 188.64 120.64 124 176 124c26.2 0 50.71 14.58 72.85 43.34 18.67 24.25 32.42 54.46 40.67 75.54 19.26 49.19 39.34 70.15 46.48 73 7.14-2.81 27.22-23.77 46.48-73 18.7-47.75 49.57-103.57 94.47-116.23A255.87 255.87 0 0 0 256 0C114.62 0 0 114.62 0 256a257.18 257.18 0 0 0 5 50.52c4.77 5.39 8.61 8.37 11 9.31z'/%3e%3cpath fill='%23666666' d='M496 196.17c-7.14 2.81-27.22 23.76-46.48 73C428.29 323.36 391.36 388 336 388c-26.2 0-50.71-14.58-72.85-43.34-18.67-24.25-32.42-54.46-40.67-75.54-19.26-49.19-39.34-70.15-46.48-73-7.14 2.81-27.22 23.76-46.48 73-18.7 47.75-49.57 103.57-94.47 116.23A255.87 255.87 0 0 0 256 512c141.38 0 256-114.62 256-256a257.18 257.18 0 0 0-5-50.52c-4.77-5.39-8.61-8.37-11-9.31z'/%3e%3c/svg%3e");
$bg-icon-timeline: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M128 128h192v64H128zM192 224h192v64H192zM160 320h192v64H160z'/%3e%3cpath fill='%23666666' d='M416 0h-64v96h63.8c.1 0 .1.1.2.2v319.7c0 .1-.1.1-.2.2H352v96h64c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96zM96 415.8V96.2c0-.1.1-.1.2-.2H160V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h64v-96H96.2c-.1 0-.2-.1-.2-.2z'/%3e%3c/svg%3e");
$bg-icon-timer: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M288 73.3V32.01a32 32 0 0 0-32-32h-64a32 32 0 0 0-32 32V73.3C67.48 100.84 0 186.54 0 288.01c0 123.71 100.29 224 224 224s224-100.29 224-224c0-101.48-67.5-187.2-160-214.71zm-54 224.71l-131.88 105.5A167.4 167.4 0 0 1 56 288.01c0-92.64 75.36-168 168-168 3.36 0 6.69.11 10 .31v177.69z'/%3e%3c/svg%3e");
$bg-icon-topic: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M227.18 238.32l43.15-43.15a25.18 25.18 0 0 1 35.36 0l43.15 43.15a94.42 94.42 0 0 0 35.18 22.25V174.5l-28.82-28.82a95.11 95.11 0 0 0-134.35 0l-43.15 43.15a25.18 25.18 0 0 1-35.36 0L128 174.5v86.07a95.11 95.11 0 0 0 99.18-22.25z'/%3e%3cpath fill='%23666666' d='M252.82 273.68l-43.15 43.15a25.18 25.18 0 0 1-35.36 0l-43.15-43.15c-1-1-2.1-2-3.18-3v98.68a95.11 95.11 0 0 0 131.18-3l43.15-43.15a25.18 25.18 0 0 1 35.36 0l43.15 43.15c1 1 2.1 2 3.18 3v-98.68a95.11 95.11 0 0 0-131.18 3z'/%3e%3cpath fill='%23666666' d='M416 0h-64v96h63.83l.17.17v319.66l-.17.17H352v96h64c52.8 0 96-43.2 96-96V96c0-52.8-43.2-96-96-96zM160 416H96.17l-.17-.17V96.17l.17-.17H160V0H96C43.2 0 0 43.2 0 96v320c0 52.8 43.2 96 96 96h64v-96z'/%3e%3c/svg%3e");
$bg-icon-box-with-dashed-lines: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M0 192h64v128H0zM64 64.11l.11-.11H160V0H64A64.19 64.19 0 0 0 0 64v96h64V64.11zM64 447.89V352H0v96a64.19 64.19 0 0 0 64 64h96v-64H64.11zM192 0h128v64H192zM448 447.89l-.11.11H352v64h96a64.19 64.19 0 0 0 64-64v-96h-64v95.89zM448 0h-96v64h95.89l.11.11V160h64V64a64.19 64.19 0 0 0-64-64zM448 192h64v128h-64zM192 448h128v64H192zM128 128h256v256H128z'/%3e%3c/svg%3e");
$bg-icon-summary-widget: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 0H64C28.8 0 0 28.8 0 64v384c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V64c0-35.2-28.8-64-64-64zm-24.1 305.2l-41.3 71.6-94.8-65.8 9.6 115h-82.7l9.6-115-94.8 65.8-41.3-71.6L192.5 256 88.1 206.8l41.3-71.6 94.8 65.8-9.6-115h82.7l-9.6 115 94.8-65.8 41.3 71.6L319.5 256l104.4 49.2z'/%3e%3c/svg%3e");
$bg-icon-notebook: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23666666' d='M448 55.4c0-39.9-27.7-63.7-61.5-52.7L0 128h448V55.4zM448 160H0v288c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V224c0-35.2-28.8-64-64-64zm-32 256H224V256h192v160z'/%3e%3c/svg%3e");

View File

@ -0,0 +1,355 @@
/******************************************************** BUTTONS */
%c-control {
@include userSelectNone();
$fs: 1em;
display: inline-flex;
align-items: center;
font-size: $fs;
justify-content: start;
cursor: pointer;
&:before,
&:after {
font-family: symbolsfont;
display: block;
flex: 0 0 auto;
}
&:after {
font-size: 0.8em;
}
[class*="__label"] {
line-height: $fs; // Remove effect on top and bottom padding
font-size: $fs;
}
}
%c-button {
@extend %c-control;
background: $colorBtnBg;
border-radius: $controlCr;
color: $colorBtnFg;
padding: nth($btnPad, 1) nth($btnPad, 2);
&:hover {
background: $colorBtnBgHov;
color: $colorBtnFgHov;
}
&[class*="--major"] {
background: $colorBtnMajorBg;
color: $colorBtnMajorFg;
&:hover {
background: $colorBtnMajorBgHov;
color: $colorBtnMajorFgHov;
}
}
}
/********* Buttons */
// Optionally can include icon in :before
.c-button {
@extend %c-button;
}
/********* Icon Buttons */
.c-icon-button {
// A clickable element that just includes the icon, no background
// Padding is included to facilitate a bigger hit area
// Make the icon bigger relative to its container
@extend %c-control;
$pLR: 3px;
$pTB: 3px;
border-radius: $controlCr;
color: $colorKey;
font-size: $fontBaseSize * 1.2;
padding: $pTB $pLR ;
&:hover {
background: rgba($colorKey, 0.2);
}
&:before {
font-size: 1.1em;
}
}
/********* Button Sets */
.c-button-set {
// Buttons are smashed together with minimal margin
// c-buttons don't have border-radius between buttons, creates a tool-button-strip look
// c-icon-buttons get grouped more closely together
// When one set is adjacent to another, provides a divider between
display: inline-flex;
> * {
// Assume buttons are immediate descendants
flex: 0 0 auto;
&[class^="c-button"] {
// Only apply the following to buttons that have background, eg. c-button
border-radius: 0;
+ * {
margin-left: 1px;
}
&:first-child {
border-top-left-radius: $controlCr;
border-bottom-left-radius: $controlCr;
}
&:last-child {
border-top-right-radius: $controlCr;
border-bottom-right-radius: $controlCr;
}
}
}
+ .c-button-set {
$m: $interiorMarginSm;
&:before {
content: '';
display: block;
width: $m;
border-right: 1px solid $colorInteriorBorder;
margin-right: $m;
}
}
}
/********* Menu Buttons */
// Always includes :after dropdown arrow
// Optionally can include icon in :before
// Default menu position is down and to the right
// Apply c-menu-button--menus-up and c-menu-button--menus-left to --w wrapper element to modify menu position
.c-menu-button {
$m: $interiorMarginSm;
@extend %c-button;
&:before {
margin-right: $m;
}
&:after {
content: $glyph-icon-arrow-down;
font-family: symbolsfont;
margin-left: $m;
opacity: 0.5;
}
&--w {
// Wraps c-menu-button, contains button and menu
.c-menu {
// Default position
top: 100%; left: 0;
}
&.c-menu-button--menus-up {
.c-menu {
top: auto; bottom: 100%;
}
}
&.c-menu-button--menus-left {
.c-menu {
left: auto; right: 0;
}
}
}
}
/******************************************************** DISCLOSURE CONTROLS */
/********* Disclosure Button */
// Provides a downward arrow icon that when clicked displays a context menu
// Always placed AFTER an element
.c-disclosure-button {
@extend .c-icon-button;
margin-left: $interiorMarginSm;
&:before {
content: $glyph-icon-arrow-down;
font-family: symbolsfont;
font-size: 0.7em;
}
}
/********* Disclosure Triangle */
// Provides an arrow icon that when clicked expands an element to reveal its contents.
// Used in tree items. Always placed BEFORE an element.
.c-disclosure-triangle {
$d: 12px;
display: flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
width: $d;
position: relative;
&.is-enabled:before {
$s: .65;
content: $glyph-icon-arrow-right-equilateral;
display: block;
font-family: symbolsfont;
font-size: 1rem * $s;
position: absolute;
transform-origin: floor(($d / 2) * $s); // This is slightly better than 'center'
transition: transform 100ms ease-in-out;
}
&--expanded {
&:before {
transform: rotate(90deg);
}
}
}
/******************************************************** FORM ELEMENTS */
/********* Inline inputs */
// A text input or contenteditable element that indicates edit affordance on hover and looks like an input on focus
.c-input-inline {
@include input-base();
border: 1px solid transparent;
display: block !important;
min-width: 0;
padding-left: 0;
padding-right: 0;
overflow: hidden;
transition: all 250ms ease;
white-space: nowrap;
&:not(:focus) {
text-overflow: ellipsis;
}
&:hover,
&:focus {
padding-left: $inputTextPLeftRight;
padding-right: $inputTextPLeftRight;
}
&:hover {
border-color: rgba($colorBodyFg, 0.2);
}
&:focus {
@include nice-input($shdw: rgba(0, 0, 0, 0.6) 0 1px 3px);
border-color: transparent;
}
}
/******************************************************** MENUS */
@mixin menuOuter() {
border-radius: $basicCr;
background: $colorMenuBg;
text-shadow: $shdwMenuText;
padding: $interiorMarginSm;
box-shadow: $shdwMenu;
display: block;
position: absolute;
z-index: 70;
}
@mixin menuInner() {
color: $colorMenuFg;
li {
@extend %c-control;
color: $colorMenuFg;
display: flex;
padding: nth($menuItemPad, 1) nth($menuItemPad, 2);
transition: $transIn;
white-space: nowrap;
&:hover {
background: $colorMenuHovBg;
color: $colorMenuHovFg;
&:before {
color: $colorMenuHovIc;
}
}
&:before {
color: $colorMenuIc;
font-size: 1em;
margin-right: $interiorMargin;
}
}
}
.c-menu {
@include menuOuter();
@include menuInner();
li {
&:not(:first-child) {
border-top: 1px solid pullForward($colorMenuBg, 10%);
}
}
}
.c-super-menu {
// Two column layout, menu items on left with detail of hover element on right
@include menuOuter();
display: flex;
padding: $interiorMarginLg;
flex-direction: row;
> [class*="__"] {
$m: $interiorMarginLg;
flex: 1 1 50%;
&:first-child {
margin-right: $m;
}
&:last-child {
border-left: 1px solid $colorInteriorBorder;
padding-left: $m;
}
}
&__menu {
@include menuInner();
overflow: auto;
ul {
margin-right: $interiorMarginSm; // Fend off scrollbar
}
li {
border-radius: $controlCr;
}
}
&__item-description {
display: flex;
flex-direction: column;
justify-content: stretch;
.l-item-description {
&__icon,
&__description {
//flex: 1 1 50%;
}
&__name,
&__description {
margin-top: $interiorMarginLg;
}
&__icon {
min-height: 20%;
margin: 10% 25%;
}
&__name {
flex: 0 0 auto;
font-size: 1.25em;
}
&__description {
font-size: $fontBaseSize;
}
}
}
}

View File

@ -28,7 +28,9 @@
}
/******************************* RESETS */
* {
*,
:before,
:after {
box-sizing: border-box;
}
@ -41,6 +43,15 @@ div {
display: contents;
}
.u-space {
// Provides a separator space between elements
&--right {
+ [class*="__"] {
margin-left: $interiorMarginLg !important;
}
}
}
/******************************* BROWSER ELEMENTS */
body.desktop {
::-webkit-scrollbar {
@ -95,8 +106,9 @@ body, html {
body {
-webkit-font-smoothing: subpixel-antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 13px;
font-size: $fontBaseSize;
font-weight: normal;
background-color: $colorBodyBg;
color: $colorBodyFg;
@ -151,6 +163,12 @@ table {
border-collapse: collapse;
}
li {
list-style-type: none;
margin: 0;
padding: 0;
}
/************************** LEGACY */
mct-container {

View File

@ -1,24 +1,3 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
@mixin glyphBefore($unicode, $family: 'symbolsfont') {
&:before {
content: $unicode;
@ -33,16 +12,21 @@
}
}
[class*="icon-"].labeled {
// Moved from .s-button and generalized
&:before {
// Fend off label from icon when it's included
margin-right: $interiorMarginSm;
@mixin glyphBg($glyphUrl) {
background-image: $glyphUrl;
background-position: center;
background-size: contain;
background-repeat: no-repeat;
}
[class*="icon-"] {
&:before, &:after
{
-webkit-font-smoothing: antialiased;
}
}
/************************** 16 PX CLASSES */
.icon-alert-rect { @include glyphBefore($glyph-icon-alert-rect); }
.icon-alert-triangle { @include glyphBefore($glyph-icon-alert-triangle); }
.icon-arrow-down { @include glyphBefore($glyph-icon-arrow-down); }
@ -162,3 +146,36 @@
.icon-folder-12px { @include glyphBefore($glyph-icon-folder,'symbolsfont-12px'); }
.icon-list-view-12px { @include glyphBefore($glyph-icon-list-view,'symbolsfont-12px'); }
.icon-grippy-12px { @include glyphBefore($glyph-icon-grippy,'symbolsfont-12px'); }
/************************** GLYPH BG CLASSES */
.bg-icon-activity { @include glyphBg($bg-icon-activity); }
.bg-icon-activity-mode { @include glyphBg($bg-icon-activity-mode); }
.bg-icon-autoflow-tabular { @include glyphBg($bg-icon-autoflow-tabular); }
.bg-icon-clock { @include glyphBg($bg-icon-clock); }
.bg-icon-database { @include glyphBg($bg-icon-database); }
.bg-icon-database-query { @include glyphBg($bg-icon-database-query); }
.bg-icon-dataset { @include glyphBg($bg-icon-dataset); }
.bg-icon-datatable { @include glyphBg($bg-icon-datatable); }
.bg-icon-dictionary { @include glyphBg($bg-icon-dictionary); }
.bg-icon-folder { @include glyphBg($bg-icon-folder); }
.bg-icon-image { @include glyphBg($bg-icon-image); }
.bg-icon-layout { @include glyphBg($bg-icon-layout); }
.bg-icon-object { @include glyphBg($bg-icon-object); }
.bg-icon-object-unknown { @include glyphBg($bg-icon-object-unknown); }
.bg-icon-packet { @include glyphBg($bg-icon-packet); }
.bg-icon-page { @include glyphBg($bg-icon-page); }
.bg-icon-plot-overlay { @include glyphBg($bg-icon-plot-overlay); }
.bg-icon-plot-stacked { @include glyphBg($bg-icon-plot-stacked); }
.bg-icon-session { @include glyphBg($bg-icon-session); }
.bg-icon-tabular { @include glyphBg($bg-icon-tabular); }
.bg-icon-tabular-lad { @include glyphBg($bg-icon-tabular-lad); }
.bg-icon-tabular-lad-set { @include glyphBg($bg-icon-tabular-lad-set); }
.bg-icon-tabular-realtime { @include glyphBg($bg-icon-tabular-realtime); }
.bg-icon-tabular-scrolling { @include glyphBg($bg-icon-tabular-scrolling); }
.bg-icon-telemetry { @include glyphBg($bg-icon-telemetry); }
.bg-icon-timeline { @include glyphBg($bg-icon-timeline); }
.bg-icon-timer { @include glyphBg($bg-icon-timer); }
.bg-icon-topic { @include glyphBg($bg-icon-topic); }
.bg-icon-box-with-dashed-lines { @include glyphBg($bg-icon-box-with-dashed-lines); }
.bg-icon-summary-widget { @include glyphBg($bg-icon-summary-widget); }
.bg-icon-notebook { @include glyphBg($bg-icon-notebook); }

View File

@ -62,6 +62,36 @@
background-size: $d $d;
}
/************************** LAYOUT */
@mixin gridTwoColumn() {
display: grid;
grid-row-gap: 0;
grid-template-columns: 1fr 2fr;
align-items: start;
[class*="header"] {
border-radius: $smallCr;
background-color: $colorInspectorSectionHeaderBg;
color: $colorInspectorSectionHeaderFg;
margin: 0 0 $interiorMarginSm 0;
padding: $interiorMarginSm $interiorMargin;
&:not(:first-child) {
// Allow multiple headers within a component
margin-top: $interiorMarginLg;
}
}
[class*="span-all"],
[class*="header"] {
@include gridTwoColumnSpanCols();
}
}
@mixin gridTwoColumnSpanCols() {
grid-column: 1 / 3;
}
/************************** TEXT */
@mixin ellipsize() {
overflow: hidden;
@ -80,13 +110,10 @@
}
/************************** CONTROLS, BUTTONS */
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.5) 0 0px 2px) {
@mixin input-base() {
appearance: none;
background: $bg;
border: none;
color: $fg;
border-radius: $controlCr;
box-shadow: inset $shdw;
outline: none;
&:focus {
@ -99,6 +126,15 @@
}
}
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.5) 0 0px 2px) {
@include input-base();
background: $bg;
color: $fg;
box-shadow: inset $shdw;
}
@mixin button($bg: $colorBtnBg, $fg: $colorBtnFg, $radius: $controlCr, $shdw: none) {
background: $bg;
color: $fg;

View File

@ -56,7 +56,7 @@
//
//!********************************* VIEWS *!
@import "../styles/fixed-position";
@import "../styles/lists/tabular";
//@import "../styles/lists/tabular";
@import "../styles/plots/plots-main";
@import "../styles/plots/legend";
@import "../styles/iframe";

View File

@ -0,0 +1,29 @@
<template>
<div class="c-menu">
<ul>
<li v-for="item in contextMenuItems"
:class="item.class"
:title="item.title">
{{ item.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data: function () {
return {
contextMenuItems: [
{name: 'Open In New Tab', class: 'icon-new-window', title: 'Open in a new browser tab'},
{name: 'Preview', class: 'hide-in-t-main-view icon-eye-open', title: 'Preview in large dialog'},
{name: 'Edit Properties...', class: 'major icon-pencil', title: 'Edit properties of this object.'},
{name: 'Duplicate', class: 'icon-duplicate', title: 'Duplicate object to another location.'},
{name: 'Create Link', class: 'icon-link', title: 'Create Link to object in another location.'},
{name: 'Export as JSON', class: 'icon-export', title: 'Export as JSON'},
{name: 'Import from JSON', class: 'icon-import', title: 'Import from JSON'}
]
}
}
}
</script>

View File

@ -0,0 +1,102 @@
<template>
<div class="c-create-button--w">
<div class="c-create-button c-menu-button c-button--major icon-plus"
@click="toggleCreateMenu">
<span class="c-button__label">Create</span>
</div>
<div class="c-create-menu c-super-menu"
v-if="showCreateMenu">
<div class="c-super-menu__menu">
<ul>
<li v-for="item in createMenuItems"
:class="item.class"
:title="item.title"
@mouseover="showItemDescription">
{{ item.name }}
</li>
</ul>
</div>
<div class="c-super-menu__item-description">
<div class="l-item-description__icon bg-icon-plot-stacked"></div>
<div class="l-item-description__name">Name</div>
<div class="l-item-description__description">
A timer that counts up or down to a datetime.
Timers can be started, stopped and reset whenever needed,
and support a variety of display formats.
Each Timer displays the same value to all users.
Timers can be added to Display Layouts.</div>
</div>
</div>
</div>
</template>
<style lang="scss">
@import "~styles/sass-base";
.c-create-button,
.c-create-menu {
&--w {
// Wrapper for Create button and menu
overflow: visible;
}
font-size: 1.1em;
}
.c-create-button .c-button__label {
text-transform: $createBtnTextTransform;
}
.c-create-menu {
max-height: 80vh;
max-width: 500px;
min-height: 250px;
z-index: 70;
[class*="__icon"] {
filter: $colorKeyFilter;
}
[class*="__item-description"] {
min-width: 200px;
}
}
</style>
<script>
export default {
props: {
showCreateMenu: {
type: Boolean,
default: false
}
},
methods: {
toggleCreateMenu: function () {
this.showCreateMenu = !this.showCreateMenu;
},
},
data: function() {
return {
createMenuItems: [
{ name: 'Folder', class: 'icon-folder', title: 'Details will go here' },
{ name: 'Display Layout', class: 'icon-layout', title: 'Details will go here' },
{ name: 'Fixed Position Display', class: 'icon-box-with-dashed-lines', title: 'Details will go here' },
{ name: 'Overlay Plot', class: 'icon-plot-overlay', title: 'Details will go here' },
{ name: 'Stacked Plot', class: 'icon-plot-stacked', title: 'Details will go here' },
{ name: 'Telemetry Table', class: 'icon-tabular-realtime', title: 'Details will go here' },
{ name: 'Clock', class: 'icon-clock', title: 'Details will go here' },
{ name: 'Timer', class: 'icon-timer', title: 'Details will go here' },
{ name: 'Web Page', class: 'icon-page', title: 'Details will go here' },
{ name: 'Event Message Generator', class: 'icon-folder-new', title: 'Details will go here' },
{ name: 'Hyperlink', class: 'icon-chain-links', title: 'Details will go here' },
{ name: 'Notebook', class: 'icon-notebook', title: 'Details will go here' },
{ name: 'State Generator', class: 'icon-telemetry', title: 'Details will go here' },
{ name: 'Sine Wave Generator', class: 'icon-telemetry', title: 'Details will go here' },
{ name: 'Example Imagery', class: 'icon-image', title: 'Details will go here' },
{ name: 'Summary Widget', class: 'icon-summary-widget', title: 'Details will go here' }
]
}
}
}
</script>

View File

@ -0,0 +1,121 @@
<template>
<div class="l-browse-bar">
<div class="l-browse-bar__start">
<a class="l-browse-bar__nav-to-parent-button c-icon-button icon-pointer-left"></a>
<div class="l-browse-bar__object-name--w icon-folder">
<span class="l-browse-bar__object-name c-input-inline" contenteditable>
Object Name Lorem ipsum dolor sit amet
</span>
</div>
<div class="l-browse-bar__context-actions c-disclosure-button"></div>
</div>
<div class="l-browse-bar__end">
<div class="l-browse-bar__view-switcher c-menu-button--w c-menu-button--menus-left">
<div class="c-menu-button icon-thumbs-strip"
title="Switch view type"
@click="toggleMenu">
<span class="c-button__label">Grid</span>
</div>
<MenuPlaceholder v-if="showMenu"></MenuPlaceholder>
</div>
<!-- Action buttons -->
<div class="l-browse-bar__actions">
<div class="l-browse-bar__action c-button icon-eye-open" title="Preview"></div>
<div class="l-browse-bar__action c-button icon-notebook" title="New Notebook entry"></div>
<div class="l-browse-bar__action c-button c-button--major icon-pencil" title="Edit"></div>
</div>
</div>
</div>
</template>
<script>
import MenuPlaceholder from '../controls/ContextMenu.vue';
export default {
props: {
showMenu: {
type: Boolean,
default: false
},
editNameEnabled: {
type: Boolean,
default: false
}
},
methods: {
toggleMenu: function () {
this.showMenu = !this.showMenu;
}
},
components: {
MenuPlaceholder
}
}
</script>
<style lang="scss">
@import "~styles/sass-base";
/******************************* START */
.l-browse-bar {
display: flex;
align-items: center;
justify-content: space-between;
[class*="__"] {
// Removes extraneous horizontal white space
display: inline-flex;
}
&__start {
display: flex;
align-items: center;
flex: 1 1 auto;
font-size: 1.4em;
margin-right: $interiorMargin;
min-width: 0; // Forces interior to compress when pushed on
}
&__end {
display: flex;
align-items: center;
flex: 0 0 auto;
[class*="__"] + [class*="__"] {
margin-left: $interiorMarginSm;
}
}
&__nav-to-parent-button,
&__disclosure-button {
flex: 0 0 auto;
}
&__nav-to-parent-button {
// This is an icon-button
$p: $interiorMarginLg;
margin-right: $interiorMargin;
padding-left: $p;
padding-right: $p;
}
&__object-name--w {
align-items: center;
display: flex;
flex: 0 1 auto;
min-width: 0;
&:before {
// Icon
opacity: 0.5;
margin-right: $interiorMargin;
}
}
&__object-name {
flex: 0 1 auto;
}
}
</style>

View File

@ -28,7 +28,6 @@
<style lang="scss">
@import "~styles/sass-base";
$hitMargin: 4px;
/**************************** BASE - MOBILE AND DESKTOP */
.l-multipane {
display: flex;
@ -86,6 +85,11 @@
transition: opacity 150ms ease;
opacity: 0;
pointer-events: none;
> * {
min-width: 0 !important;
min-height: 0 !important;
}
}
}
@ -110,7 +114,6 @@
padding: $interiorMargin;
pointer-events: inherit;
transition: opacity 250ms ease 250ms;
overflow: auto;
.l-pane__contents {
// Don't pad all nested __contents
@ -149,7 +152,7 @@
&__collapse-button {
$m: 2px;
$h: nth($splitterBtnD, 1) - ($m * 2);
$h: 12px;
color: $splitterBtnColorFg;
flex: 0 0 nth($splitterBtnD, 1);
font-size: $h * .9;
@ -159,27 +162,24 @@
&:after {
// Close icon
background: $splitterBtnColorFg;
border-radius: 2px;
color: $splitterBtnColorBg;
content: $glyph-icon-minus;
background: $colorBtnBg;
border-radius: $smallCr;
color: $colorBtnFg;
content: $glyph-icon-arrow-right-equilateral;
display: block;
font-family: symbolsfont;
font-size: .8em;
height: $h;
line-height: $h;
padding: 0 7px;
font-size: 6px;
line-height: 90%;
padding: 3px 15px;
position: absolute;
right: $m;
top: $m;
text-align: right;
transition: $transOut;
z-index: -1;
}
&:hover {
background: rgba(black, 0.1);
//color: $splitterBtnColorHoverFg;
&:after {
background: $splitterBtnColorHoverBg;
color: $splitterBtnColorHoverFg;
@ -192,6 +192,7 @@
// Name of the pane
@include ellipsize();
display: block;
padding-right: nth($splitterBtnD, 2) + $interiorMargin; // Force label to ellipsis
text-transform: uppercase;
transform-origin: top left;
flex: 1 0 90%;
@ -200,6 +201,10 @@
&--resizing {
// User is dragging the handle and resizing a pane
@include userSelectNone();
+ .l-pane {
@include userSelectNone();
}
}
&[class*="--collapsed"] {
@ -216,10 +221,6 @@
background: $splitterBtnColorFg;
color: $splitterBtnColorBg;
&:after {
content: $glyph-icon-plus;
}
&:hover {
background: $splitterBtnColorHoverBg !important;
}
@ -241,9 +242,9 @@
&:before {
// Extended hit area
top: 0;
right: $hitMargin * -1;
right: $splitterHandleHitMargin * -1;
bottom: 0;
left: $hitMargin * -1;
left: $splitterHandleHitMargin * -1;
}
}
@ -267,7 +268,6 @@
right: auto;
transform: translateX(-50%);
width: auto;
}
}
}
@ -278,6 +278,14 @@
left: 0;
transform: translateX(floor($splitterHandleD / -2)); // Center over the pane edge
}
&[class*="--collapsed"] {
> .l-pane__collapse-button {
&:after {
transform: translateX(-50%) scaleX(-1);
}
}
}
}
/************************** Horizontal Splitter After */
@ -286,6 +294,12 @@
right: 0;
transform: translateX(floor($splitterHandleD / 2));
}
&:not([class*="--collapsed"]) {
> .l-pane__collapse-button:after {
transform: scaleX(-1);
}
}
}
}
@ -299,25 +313,43 @@
&:before {
// Extended hit area
left: 0;
top: $hitMargin * -1;
top: $splitterHandleHitMargin * -1;
right: 0;
bottom: $hitMargin * -1;
bottom: $splitterHandleHitMargin * -1;
}
}
/************************** Vertical Splitter Before */
// Pane collapses downward
&[class*="-before"] {
> .l-pane__handle {
top: 0;
transform: translateY(floor($splitterHandleD / -2)); // Center over the pane edge
transform: translateY(floor($splitterHandleD / -1));
}
> .l-pane__collapse-button:after {
content: $glyph-icon-arrow-down;
}
&.l-pane--collapsed {
> .l-pane__collapse-button:after {
transform: scaleY(-1);
}
}
}
/************************** Vertical Splitter After */
// Pane collapses upward. Not sure we'll ever use this...
&[class*="-after"] {
> .l-pane__handle {
bottom: 0;
transform: translateY(floor($splitterHandleD / 2)); // Center over the pane edge
transform: translateY(floor($splitterHandleD / 1));
}
&:not(.l-pane--collapsed) > .l-pane__collapse-button {
&:after {
transform: scaleY(-1);
}
}
}
}

View File

@ -28,7 +28,7 @@
flex: 0 0 auto;
opacity: 0.5;
overflow: hidden;
padding: 2px; // Prevents clipping
padding: 2px 0; // Prevents clipping
transition: width 250ms ease;
width: 1em;
}

View File

@ -1,43 +1,12 @@
<template>
<span class="c-view-control"
<span class="c-disclosure-triangle"
:class="{
'c-view-control--expanded' : expanded,
'c-disclosure-triangle--expanded' : expanded,
'is-enabled' : enabled
}"
@click="toggle"></span>
</template>
<style lang="scss">
@import "~styles/sass-base";;
.c-view-control {
$d: 12px;
display: flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
width: $d;
position: relative;
&.is-enabled:before {
$s: .65;
content: $glyph-icon-arrow-right-equilateral;
display: block;
font-family: symbolsfont;
font-size: 1rem * $s;
position: absolute;
transform-origin: floor(($d / 2) * $s); // This is slightly better than 'center'
transition: transform 100ms ease-in-out;
}
&--expanded {
&:before {
transform: rotate(90deg);
}
}
}
</style>
<script>
export default {
props: {

View File

@ -0,0 +1,33 @@
<template>
<div></div>
</template>
<script>
export default {
inject: ['openmct'],
mounted() {
let openmct = this.openmct;
let $injector = openmct.$injector;
let angular = openmct.$angular;
let templateLinker = $injector.get('templateLinker');
let templateMap = {};
$injector.get('templates[]').forEach((t) => {
templateMap[t.key] = templateMap[t.key] || t;
});
let $rootScope = $injector.get('$rootScope');
this.$scope = $rootScope.$new();
templateLinker.link(
this.$scope,
angular.element(this.$el),
templateMap.elementsPool
);
},
destroyed() {
this.$scope.$destroy();
}
}
</script>

View File

@ -0,0 +1,167 @@
<template>
<multipane class="c-inspector"
type="vertical">
<pane class="c-inspector__properties">
<properties></properties>
<location></location>
<inspector-view></inspector-view>
</pane>
<pane class="c-inspector__elements"
handle="before"
label="Elements">
<elements></elements>
</pane>
</multipane>
</template>
<style lang="scss">
@import "~styles/sass-base";
.c-inspector {
min-width: 150px;
> [class*="__"] {
min-height: 50px;
+ [class*="__"] {
// Margin between elements
margin-top: $interiorMargin;
}
> .l-pane__contents {
overflow: auto;
> * {
// Fend off scrollbar
margin-right: $interiorMarginSm;
}
}
}
&__elements {
// LEGACY TODO: Refactor when markup is updated, fix scrolling
// so that only tree holder handles overflow
height: 200px;
.tree-item {
.t-object-label {
// Elements pool is a flat list, so don't indent items.
left: 0;
}
}
}
/************************************************************** LEGACY */
// TODO: refactor when markup can be converted
.inspector-location {
display: inline-block;
.location-item {
$h: 1.2em;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
line-height: $h;
position: relative;
padding: 2px 4px;
.t-object-label {
.t-item-icon {
height: $h;
margin-right: $interiorMarginSm;
}
}
&:hover {
background: $colorItemTreeHoverBg;
color: $colorItemTreeHoverFg;
.icon {
color: $colorItemTreeIconHover;
}
}
}
&:not(.last) .t-object-label .t-title-label:after {
color: pushBack($colorInspectorFg, 15%);
content: '\e904';
display: inline-block;
font-family: symbolsfont;
font-size: 8px;
font-style: normal !important;
line-height: inherit;
margin-left: $interiorMarginSm;
width: 4px;
}
}
}
.c-properties {
@include gridTwoColumn();
+ .c-properties {
// Margin between components
margin-top: $interiorMarginLg;
}
&__section,
&__row {
display: contents;
}
&__row + &__row {
> [class*="__"] {
// Row borders, effected via border-top on child elements of the row
border-top: 1px solid $colorInspectorSectionHeaderBg;
}
}
&__header {
font-size: .85em;
text-transform: uppercase;
}
&__label,
&__value {
padding: 3px $interiorMarginLg 3px 0;
}
&__label {
color: $colorInspectorPropName;
&[title] {
// When a cell has a title, assume it's helpful text
cursor: help;
}
}
&__value {
color: $colorInspectorPropVal;
word-break: break-all;
&:first-child {
// If there is no preceding .label element, make value span columns
@include gridTwoColumnSpanCols();
}
}
}
</style>
<script>
import multipane from '../controls/multipane.vue';
import pane from '../controls/pane.vue';
import Elements from './Elements.vue';
import Location from './Location.vue';
import Properties from './Properties.vue';
import InspectorView from './InspectorView.vue';
export default {
inject: ['openmct'],
components: {
multipane,
pane,
Elements,
Properties,
Location,
InspectorView
}
}
</script>

View File

@ -0,0 +1,32 @@
<template>
<div class="c-properties"></div>
</template>
<style>
</style>
<script>
export default {
inject: ['openmct'],
mounted() {
this.openmct.selection.on('change', this.updateSelection);
this.updateSelection(this.openmct.selection.get());
},
destroyed() {
this.openmct.selection.off('change', this.updateSelection);
},
methods: {
updateSelection(selection) {
if (this.selectedView && this.selectedView.destroy) {
this.selectedView.destroy();
}
this.$el.innerHTML = '';
this.selectedView = this.openmct.inspectorViews.get(selection);
if (!this.selectedView) {
return;
}
this.selectedView.show(this.$el);
}
}
}
</script>

View File

@ -0,0 +1,42 @@
<template>
<div class="c-properties c-properties--location">
<div class="c-properties__header" title="The location of this linked object.">Location</div>
<ul class="c-properties__section">
<li class="c-properties__row">
<div class="c-properties__label">This Link</div>
<div class="c-properties__value">TODO</div>
</li>
<li class="c-properties__row">
<div class="c-properties__label">Original</div>
<div class="c-properties__value">TODO</div>
</li>
</ul>
</div>
</template>
<script>
export default {
inject: ['openmct'],
data() {
return {
domainObject: {}
}
},
mounted() {
this.openmct.selection.on('change', this.updateSelection);
this.updateSelection(this.openmct.selection.get());
},
beforeDestroy() {
this.openmct.selection.off('change', this.updateSelection);
},
methods: {
updateSelection(selection) {
if (selection.length === 0) {
this.domainObject = {};
return;
}
this.domainObject = selection[0].context.item;
}
}
}
</script>

View File

@ -0,0 +1,96 @@
<template>
<div class="c-properties c-properties--properties">
<div class="c-properties__header">Properties</div>
<ul class="c-properties__section">
<li class="c-properties__row">
<div class="c-properties__label">Title</div>
<div class="c-properties__value">{{ domainObject.name }}</div>
</li>
<li class="c-properties__row">
<div class="c-properties__label">Type</div>
<div class="c-properties__value">{{ typeName }}</div>
</li>
<li class="c-properties__row" v-if="domainObject.created">
<div class="c-properties__label">Created</div>
<div class="c-properties__value">{{ domainObject.created }}</div>
</li>
<li class="c-properties__row" v-if="domainObject.modified">
<div class="c-properties__label">Modified</div>
<div class="c-properties__value">{{ domainObject.modified }}</div>
</li>
<li class="c-properties__row"
v-for="prop in typeProperties"
:key="prop.name">
<div class="c-properties__label">{{ prop.name }}</div>
<div class="c-properties__value">{{ prop.value }}</div>
</li>
</ul>
</div>
</template>
<script>
export default {
inject: ['openmct'],
data() {
return {
domainObject: {}
}
},
computed: {
type() {
return this.openmct.types.get(this.domainObject.type);
},
typeName() {
if (!this.type) {
return `Unknown: ${this.domainObject.type}`;
}
return this.type.definition.name;
},
typeProperties() {
if (!this.type) {
return [];
}
let definition = this.type.definition;
if (!definition.form || definition.form.length === 0) {
return [];
}
return definition.form
.map((field) => {
let path = field.property
if (typeof path === 'string') {
path = [path];
}
return {
name: field.name,
path
};
})
.filter(field => Array.isArray(field.path))
.map((field) => {
return {
name: field.name,
value: field.path.reduce((object, field) => {
return object[field];
}, this.domainObject)
};
});
}
},
mounted() {
this.openmct.selection.on('change', this.updateSelection);
this.updateSelection(this.openmct.selection.get());
},
beforeDestroy() {
this.openmct.selection.off('change', this.updateSelection);
},
methods: {
updateSelection(selection) {
if (selection.length === 0) {
this.domainObject = {};
return;
}
this.domainObject = selection[0].context.item;
}
}
}
</script>

View File

@ -0,0 +1,159 @@
<template>
<div></div>
</template>
<style lang="scss">
</style>
<script>
// Find an object in an array of objects.
function findObject(domainObjects, id) {
var i;
for (i = 0; i < domainObjects.length; i += 1) {
if (domainObjects[i].getId() === id) {
return domainObjects[i];
}
}
}
// recursively locate and return an object inside of a container
// via a path. If at any point in the recursion it fails to find
// the next object, it will return the parent.
function findViaComposition(containerObject, path) {
var nextId = path.shift();
if (!nextId) {
return containerObject;
}
return containerObject.useCapability('composition')
.then(function (composees) {
var nextObject = findObject(composees, nextId);
if (!nextObject) {
return containerObject;
}
if (!nextObject.hasCapability('composition')) {
return nextObject;
}
return findViaComposition(nextObject, path);
});
}
function getLastChildIfRoot(object) {
if (object.getId() !== 'ROOT') {
return object;
}
return object.useCapability('composition')
.then(function (composees) {
return composees[composees.length - 1];
});
}
function pathForObject(domainObject) {
var context = domainObject.getCapability('context'),
objectPath = context ? context.getPath() : [],
ids = objectPath.map(function (domainObj) {
return domainObj.getId();
});
return "/browse/" + ids.slice(1).join("/");
}
export default {
inject: ["openmct"],
mounted() {
let openmct = this.openmct;
let $injector = openmct.$injector;
let angular = openmct.$angular;
this.objectService = $injector.get('objectService');
this.templateLinker = $injector.get('templateLinker');
this.navigationService = $injector.get('navigationService');
this.$timeout = $injector.get('$timeout');
this.templateMap = {};
$injector.get('templates[]').forEach((t) => {
this.templateMap[t.key] = this.templateMap[t.key] || t;
});
this.$rootScope = $injector.get('$rootScope');
this.$scope = this.$rootScope.$new();
this.$scope.representation = {};
openmct.router.route(/^\/browse\/(.*)$/, (path, results) => {
let navigatePath = results[1];
if (!navigatePath) {
navigatePath = 'mine';
}
this.navigateToPath(navigatePath);
});
this.navigationService.addListener(o => this.navigateToObject(o));
},
destroyed() {
},
methods: {
navigateToPath(path) {
if (!Array.isArray(path)) {
path = path.split('/');
}
return this.getObject('ROOT')
.then(root => {
return findViaComposition(root, path);
})
.then(getLastChildIfRoot)
.then(object => {
this.setMainViewObject(object);
});
},
setMainViewObject(object) {
this.$scope.domainObject = object;
this.$scope.navigatedObject = object;
this.templateLinker.link(
this.$scope,
this.openmct.$angular.element(this.$el),
this.templateMap["browseObject"]
);
document.title = object.getModel().name;
this.scheduleDigest();
},
idsForObject(domainObject) {
return this.urlService
.urlForLocation("", domainObject)
.replace('/', '');
},
navigateToObject(object) {
let path = pathForObject(object);
let views = object.useCapability('view');
let params = this.openmct.router.getParams();
let currentViewIsValid = views.some(v => v.key === params['view']);
if (!currentViewIsValid) {
this.scope.representation = {
selected: views[0]
}
this.openmct.router.update(path, {
view: views[0].key
});
} else {
this.openmct.router.setPath(path);
}
},
scheduleDigest() {
this.$timeout(function () {
// digest done!
});
},
getObject(id) {
return this.objectService.getObjects([id])
.then(function (results) {
return results[id];
});
}
}
}
</script>

View File

@ -0,0 +1,15 @@
<template>
<div></div>
</template>
<style lang="scss">
</style>
<script>
export default {
<mct-include key="'conductor'" class="abs holder flex-elem flex-fixed l-flex-row l-time-conductor-holder"></mct-include>
}
</script>

View File

@ -1,8 +1,12 @@
<template>
<div class="l-shell">
<div class="l-shell__head">
[ Create Button ]
[ App Logo ]
<CreateButton class="l-shell__create-button"></CreateButton>
<div class="l-shell__controls">
<a class="c-icon-button icon-new-window" title="Open in a new browser tab"></a>
<a class="c-icon-button icon-fullscreen-collapse" title="Enable full screen mode"></a>
</div>
<div class="l-shell__app-logo">[ App Logo ]</div>
</div>
<multipane class="l-shell__main"
type="horizontal">
@ -14,17 +18,22 @@
<search class="c-search--major" ref="shell-search"></search>
</div>
<div class="l-shell__tree">
<mct-tree :nodes="treeRoots"></mct-tree>
<mct-tree></mct-tree>
</div>
</pane>
<pane class="l-shell__pane-main">
<div class="l-shell__main-container" ref="mainContainer"></div>
<MainViewBrowseBar class="l-shell__main-view-browse-bar"></MainViewBrowseBar>
<browse-object class="l-shell__main-container">
</browse-object>
<mct-template template-key="conductor"
class="l-shell__time-conductor">
</mct-template>
</pane>
<pane class="l-shell__pane-inspector l-pane--holds-multipane"
handle="before"
label="Inspect"
collapsable>
<MctInspector ref="inspector"></MctInspector>
<Inspector ref="inspector"></Inspector>
</pane>
</multipane>
<div class="l-shell__status">
@ -72,10 +81,10 @@
}
}
&__head,
&__pane-inspector {
body.mobile & {
display: none;
&__pane-main {
> .l-pane__contents {
display: flex;
flex-flow: column nowrap;
}
}
@ -98,13 +107,48 @@
}
}
&__head,
&__pane-inspector {
body.mobile & {
display: none;
}
}
&__head,
&__status {
flex: 0 1 auto;
display: flex;
}
/******************************* HEAD */
&__head {
align-items: center;
justify-content: space-between;
border-bottom: 1px solid $colorInteriorBorder;
padding: $interiorMargin;
> [class*="__"] + [class*="__"] {
margin-left: $interiorMargin;
}
}
&__create-button,
&__app-logo {
flex: 0 0 auto;
}
&__controls {
flex: 1 1 100%;
display: flex;
justify-content: flex-end;
margin-right: 2.5%;
}
/********** MAIN AREA */
&__main-container {
// Wrapper for main views
font-size: 16px; // TEMP FOR LEGACY STYLING
overflow: auto;
position: absolute;
top: $interiorMargin; right: $interiorMarginLg; bottom: $interiorMargin; left: $interiorMarginLg;
flex: 1 1 100%;
font-size: 16px; // TEMP FOR LEGACY STYLING - TODO: REMOVE!
}
&__tree {
@ -115,24 +159,12 @@
&__time-conductor {
border-top: 1px solid $colorInteriorBorder;
min-height: 50px;
padding: $interiorMarginLg;
flex: 0 0 auto;
padding: $interiorMargin;
}
body.desktop & {
/********** HEAD AND STATUS */
&__head,
&__status {
display: block;
flex: 0 1 auto;
}
&__head {
border-bottom: 1px solid $colorInteriorBorder;
height: 40px;
padding: $interiorMarginLg;
}
&__pane-tree,
&__pane-inspector {
max-width: 30%;
@ -150,23 +182,31 @@
</style>
<script>
import MctInspector from './MctInspector.vue';
import MctMain from './MctMain.vue';
import Inspector from '../inspector/Inspector.vue';
import MctStatus from './MctStatus.vue';
import MctTree from './mct-tree.vue';
import BrowseObject from './BrowseObject.vue';
import MctTemplate from '../legacy/mct-template.vue';
import ContextMenu from '../controls/ContextMenu.vue';
import CreateButton from '../controls/CreateButton.vue';
import search from '../controls/search.vue';
import multipane from '../controls/multipane.vue';
import pane from '../controls/pane.vue';
import MainViewBrowseBar from '../controls/MainViewBrowseBar.vue';
export default {
components: {
MctInspector,
MctMain,
Inspector,
MctStatus,
MctTree,
BrowseObject,
'mct-template': MctTemplate,
ContextMenu,
CreateButton,
search,
multipane,
pane
pane,
MainViewBrowseBar
}
}
</script>

View File

@ -1,202 +0,0 @@
<template>
<multipane class="c-inspector"
type="vertical">
<pane class="c-inspector__properties">
<div ref="properties"></div>
</pane>
<pane class="l-pane c-inspector__elements"
handle="before"
label="Elements">
<div ref="elements">c-inspector__elements 1</div>
</pane>
</multipane>
</template>
<style lang="scss">
@import "~styles/sass-base";
@mixin grid-two-column() {
display: grid;
grid-row-gap: 0;
grid-template-columns: 1fr 2fr;
align-items: start;
}
@mixin grid-two-column-span-cols() {
grid-column: 1 / 3;
}
.c-inspector {
min-width: 150px;
> [class*="__"] {
min-height: 50px;
&:not(:last-child) {
margin-bottom: $interiorMargin;
}
> .l-pane__contents > * {
// Provide margin against scrollbar
// TODO: move this into pane.vue
margin-right: $interiorMarginSm;
}
}
&__elements {
height: 200px;
}
.l-inspector-part {
display: contents; // Legacy
}
h2 {
// Legacy, somewhat
@include grid-two-column-span-cols;
border-radius: $smallCr;
background-color: $colorInspectorSectionHeaderBg;
color: $colorInspectorSectionHeaderFg;
font-size: .85em;
font-weight: normal;
margin: $interiorMarginLg 0 $interiorMarginSm 0;
padding: $interiorMarginSm $interiorMargin;
text-transform: uppercase;
&.first {
margin-top: 0;
}
}
.grid-properties {
.label {
color: $colorInspectorPropName;
}
.value {
color: $colorInspectorPropVal;
word-break: break-all;
&:first-child {
// If there is no preceding .label element, make value span columns
@include grid-two-column-span-cols;
}
}
}
}
/******************************* PROPERTIES GRID */
.grid-elem {
&:not(:first-child) {
border-top: 1px solid $colorInteriorBorder;
}
&.label {
background-color: rgba(0,0,128,0.2);
}
&.value {
background-color: rgba(0,128,0,0.2);
}
}
// Properties grids
.grid-properties, // LEGACY
.l-grid-properties {
@include grid-two-column;
}
.grid-row {
display: contents;
}
.grid-span-all {
@include grid-two-column-span-cols;
}
.grid-row {
.grid-cell {
padding: 3px $interiorMarginLg 3px 0;
&[title] {
// When a cell has a title, assume it's helpful text
cursor: help;
}
}
&.force-border,
&:not(:first-of-type) {
// Row borders, effected via border-top on child elements of the row
.grid-cell {
border-top: 1px solid $colorInspectorSectionHeaderBg;
}
}
/************************************************************** LEGACY STYLES */
.tree {
.grid-properties {
margin-left: $treeItemIndent + $interiorMarginLg;
}
}
.inspector-location {
display: inline-block;
.location-item {
$h: 1.2em;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
line-height: $h;
position: relative;
padding: 2px 4px;
.t-object-label {
.t-item-icon {
height: $h;
margin-right: $interiorMarginSm;
}
}
&:hover {
background: $colorItemTreeHoverBg;
color: $colorItemTreeHoverFg;
.icon {
color: $colorItemTreeIconHover;
}
}
}
&:not(.last) .t-object-label .t-title-label:after {
color: pushBack($colorInspectorFg, 15%);
content: '\e904';
display: inline-block;
font-family: symbolsfont;
font-size: 8px;
font-style: normal !important;
line-height: inherit;
margin-left: $interiorMarginSm;
width: 4px;
}
}
// Elements pool
.holder-elements {
.current-elements {
position: relative;
.tree-item {
.t-object-label {
// Elements pool is a flat list, so don't indent items.
/*font-size: 0.75rem;*/
left: 0;
}
}
}
}
}
</style>
<script>
import multipane from '../controls/multipane.vue';
import pane from '../controls/pane.vue';
export default {
components: {
multipane,
pane
}
}
</script>

View File

@ -1,21 +0,0 @@
<template>
<mct-representation key='browse-object'></mct-representation>
</template>
<style lang="scss">
.MCT_Main {
position: absolute;
right: 100px;
top: 0px;
bottom: 20px;
left: 100px;
background: green;
}
</style>
<script>
export default {
}
</script>

View File

@ -10,9 +10,8 @@
<style lang="scss">
@import "~styles/sass-base";
// TODO: make sure hit area encompasses all of the tree item; currently is just the text
.c-tree {
@include userSelectNone();
overflow-x: hidden;
overflow-y: auto;
height: 100%;
@ -70,7 +69,8 @@
&:before {
// Type icon
display: inline-block;
display: block;
flex: 0 0 auto;
font-size: 1.3em;
margin-right: $interiorMarginSm;
}

View File

@ -0,0 +1,38 @@
<template>
<div></div>
</template>
<script>
export default {
inject: ['openmct'],
props: {
templateKey: String
},
mounted() {
let openmct = this.openmct;
let $injector = openmct.$injector;
let angular = openmct.$angular;
let templateLinker = $injector.get('templateLinker');
let templateMap = {};
$injector.get('templates[]').forEach((t) => {
templateMap[t.key] = templateMap[t.key] || t;
});
let $rootScope = $injector.get('$rootScope');
this.$scope = $rootScope.$new();
console.log('mounting', this.templateKey);
console.log('template:', templateMap[this.templateKey]);
templateLinker.link(
this.$scope,
angular.element(this.$el),
templateMap[this.templateKey]
);
},
destroyed() {
this.$scope.$destroy();
}
}
</script>