Compare commits

..

14 Commits

Author SHA1 Message Date
24fcad8152 Continuing work on table tests 2018-09-11 10:09:59 -07:00
a6f9e0420c Fixed telemetry table object initialization 2018-09-10 17:50:19 +01:00
ccfd9eed00 Defined test spec for Telemetry Table plugin 2018-09-10 17:48:26 +01:00
df0ee1f99b Added spec for BoundedTableRowCollection 2018-09-10 17:13:21 +01:00
dacbf928a1 Shortcut sortedIndex in insert if value is outside of first or last value in collection 2018-09-05 13:31:54 +01:00
6153dce261 CSVExporter now only exports visible columns. Updated CSVExporter to ES6 exports / imports 2018-09-04 17:24:36 +01:00
0fcddb3547 Allow 'editable' property on view providers to optionally be a function 2018-09-04 12:08:52 +01:00
c6628b6e72 Convert CSS to BEM - done
- Cleanup and organization;
2018-08-31 18:34:45 -07:00
ec7889e5ff 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;
2018-08-31 18:16:27 -07:00
416d8f60fe Convert CSS to BEM - WIP!
- All in progress;
- Table body divorced from legacy;
2018-08-31 17:47:40 -07:00
74293d4fda Convert CSS to BEM - WIP!
- All in progress;
- Sizing table divorced from legacy;
2018-08-31 16:52:35 -07:00
73fc686851 Reset legacy file, undo unintended change commit 2018-08-31 16:40:07 -07:00
d21abd95b1 Convert CSS to BEM - WIP!
- All in progress;
- Headers table divorced from old;
- Sizing working properly at this point;
2018-08-31 16:38:36 -07:00
eb5ef28a73 [Table] Use Vue SFCs
Use Vue SFCs.  Use inject/provide to pass services to components
instead of wrapping components in closures.
2018-08-31 13:15:11 -07:00
83 changed files with 2289 additions and 3320 deletions

View File

@ -1,21 +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.
-->

View File

@ -66,4 +66,5 @@
</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,12 +319,6 @@ define([
]
}
],
"templates": [
{
key: "elementsPool",
template: elementsTemplate
}
],
"components": [
{
"type": "decorator",

View File

@ -0,0 +1,294 @@
define([
"legacyRegistry",
"./src/controllers/NotebookController",
"./src/controllers/NewEntryController",
"./src/controllers/SelectSnapshotController",
"./src/controllers/LayoutNotebookController",
"./src/directives/MCTSnapshot",
"./src/directives/EntryDnd",
"./src/actions/ViewSnapshot",
"./src/actions/AnnotateSnapshot",
"./src/actions/RemoveEmbed",
"./src/actions/RemoveSnapshot",
"./src/actions/NewEntryContextual",
"./src/capabilities/NotebookCapability",
"./src/policies/CompositionPolicy",
"./res/templates/notebook.html",
"./res/templates/entry.html",
"./res/templates/annotation.html",
"./res/templates/notifications.html",
"../layout/res/templates/frame.html",
"./res/templates/controls/embedControl.html",
"./res/templates/controls/snapSelect.html"
], function (
legacyRegistry,
NotebookController,
NewEntryController,
SelectSnapshotController,
LayoutNotebookController,
MCTSnapshot,
MCTEntryDnd,
ViewSnapshotAction,
AnnotateSnapshotAction,
RemoveEmbedAction,
RemoveSnapshotAction,
newEntryAction,
NotebookCapability,
CompositionPolicy,
notebookTemplate,
entryTemplate,
annotationTemplate,
notificationsTemplate,
frameTemplate,
embedControlTemplate,
snapSelectTemplate
) {
legacyRegistry.register("platform/features/notebook", {
"name": "Notebook Plugin",
"description": "Create and save timestamped notes with embedded object snapshots.",
"extensions":
{
"types": [
{
"key": "notebook",
"name": "Notebook",
"cssClass": "icon-notebook",
"description": "Create and save timestamped notes with embedded object snapshots.",
"features": ["creation"],
"model": {
"entries": [],
"composition": [],
"entryTypes": [],
"defaultSort": "-createdOn"
},
"properties": [
{
"key": "defaultSort",
"name": "Default Sort",
"control": "select",
"options": [
{
"name": "Newest First",
"value": "-createdOn"
},
{
"name": "Oldest First",
"value": "createdOn"
}
],
"cssClass": "l-inline"
}
]
}
],
"views": [
{
"key": "notebook.view",
"type": "notebook",
"cssClass": "icon-notebook",
"name": "notebook",
"template": notebookTemplate,
"editable": false,
"uses": [
"composition",
"action"
],
"gestures": [
"drop"
]
}
],
"controllers": [
{
"key": "NotebookController",
"implementation": NotebookController,
"depends": [
"$scope",
"dialogService",
"popupService",
"agentService",
"objectService",
"navigationService",
"now",
"actionService",
"$timeout",
"$element",
"$sce"
]
},
{
"key": "NewEntryController",
"implementation": NewEntryController,
"depends": ["$scope",
"$rootScope"
]
},
{
"key": "selectSnapshotController",
"implementation": SelectSnapshotController,
"depends": ["$scope",
"$rootScope"
]
},
{
"key": "LayoutNotebookController",
"implementation": LayoutNotebookController,
"depends": ["$scope"]
}
],
"representations": [
{
"key": "draggedEntry",
"template": entryTemplate
},
{
"key": "frameLayoutNotebook",
"template": frameTemplate
}
],
"templates": [
{
"key": "annotate-snapshot",
"template": annotationTemplate
},
{
"key": "notificationTemplate",
"template": notificationsTemplate
}
],
"directives": [
{
"key": "mctSnapshot",
"implementation": MCTSnapshot,
"depends": [
"$rootScope",
"$document",
"exportImageService",
"dialogService",
"notificationService"
]
},
{
"key": "mctEntryDnd",
"implementation": MCTEntryDnd,
"depends": [
"$rootScope",
"$compile",
"dndService",
"typeService",
"notificationService"
]
}
],
"actions": [
{
"key": "view-snapshot",
"implementation": ViewSnapshotAction,
"name": "View Snapshot",
"description": "View the large image in a modal",
"category": "embed",
"depends": [
"$compile"
]
},
{
"key": "annotate-snapshot",
"implementation": AnnotateSnapshotAction,
"name": "Annotate Snapshot",
"cssClass": "icon-pencil labeled",
"description": "Annotate embed's snapshot",
"category": "embed",
"depends": [
"dialogService",
"dndService",
"$rootScope"
]
},
{
"key": "remove-embed",
"implementation": RemoveEmbedAction,
"name": "Remove...",
"cssClass": "icon-trash labeled",
"description": "Remove this embed",
"category": [
"embed",
"embed-no-snap"
],
"depends": [
"dialogService"
]
},
{
"key": "remove-snapshot",
"implementation": RemoveSnapshotAction,
"name": "Remove Snapshot",
"cssClass": "icon-trash labeled",
"description": "Remove Snapshot of the embed",
"category": "embed",
"depends": [
"dialogService"
]
},
{
"key": "notebook-new-entry",
"implementation": newEntryAction,
"name": "New Notebook Entry",
"cssClass": "icon-notebook labeled",
"description": "Add a new Notebook entry",
"category": [
"view-control"
],
"depends": [
"$compile",
"$rootScope",
"dialogService",
"notificationService",
"linkService"
],
"priority": "preferred"
}
],
"licenses": [
{
"name": "painterro",
"version": "0.2.65",
"author": "Ivan Borshchov",
"description": "Painterro is JavaScript paint widget which allows editing images directly in a browser.",
"website": "https://github.com/ivictbor/painterro",
"copyright": "Copyright 2017 Ivan Borshchov",
"license": "MIT",
"link": "https://github.com/ivictbor/painterro/blob/master/LICENSE"
}
],
"capabilities": [
{
"key": "notebook",
"name": "Notebook Capability",
"description": "Provides a capability for looking for a notebook domain object",
"implementation": NotebookCapability,
"depends": [
"typeService"
]
}
],
"policies": [
{
"category": "composition",
"implementation": CompositionPolicy,
"message": "Objects of this type cannot contain objects of that type."
}
],
"controls": [
{
"key": "embed-control",
"template": embedControlTemplate
},
{
"key": "snapshot-select",
"template": snapSelectTemplate
}
]
}
});
});

View File

@ -25,5 +25,6 @@
ng-options="opt.value as opt.name for opt in options"
ng-required="ngRequired"
name="mctControl">
<!-- <option value="" ng-show="!ngModel[field]">- Select One -</option> -->
</select>
</div>

View File

@ -0,0 +1,118 @@
<div ng-controller="NotebookController as controller" class="mct-notebook w-notebook l-flex-col">
<div class="l-notebook-head holder l-flex-row flex-elem">
<div class="c-search flex-elem holder grows">
<input class="c-search__search-input"
type="text" tabindex="10000"
ng-model="entrySearch"
ng-keyup="controller.search()"/>
<a class="c-search__clear-input clear-icon icon-x-in-circle"
ng-class="{show: !(entrySearch === '' || entrySearch === undefined)}"
ng-click="entrySearch = ''; controller.search()"></a>
</div>
<div class="notebook-view-controls l-flex-row flex-elem holder">
<div class="select notebook-view-controls__filter-time">
<select ng-model="showTime">
<option value="0" selected="selected">Show all</option>
<option value="1">Last hour</option>
<option value="8">Last 8 hours</option>
<option value="24">Last 24 hours</option>
</select>
</div>
<div class="select notebook-view-controls__sort">
<select ng-model="sortEntries">
<option value="-createdOn" selected="selected">Newest first</option>
<option value="createdOn">Oldest first</option>
</select>
</div>
</div>
</div>
<!-- drag area -->
<div class="holder flex-elem l-flex-row icon-plus labeled l-notebook-drag-area" ng-click="newEntry($event)"
id="newEntry" mct-entry-dnd>
<span class="label">To start a new entry, click here or drag and drop any object</span>
</div>
<!-- entries -->
<div class="holder flex-elem grows w-notebook-entries t-entries-list" ng-mouseover="handleActive()">
<ul>
<li class="l-flex-row has-local-controls l-notebook-entry s-notebook-entry"
id="{{'entry_'+ entry.id}}"
ng-if="hoursFilter(showTime,entry.createdOn)"
ng-repeat="entry in model.entries | filter:entrySearch | orderBy: sortEntries track by $index"
ng-init="$last && finished(model.entries)"
mct-entry-dnd>
<div class="holder flex-elem l-flex-row grows w-notebook-entry-time-and-content">
<div class="holder flex-elem s-notebook-entry-time">
<span>{{entry.createdOn | date:'yyyy-MM-dd'}}</span>
<span>{{entry.createdOn | date:'HH:mm:ss'}}</span>
</div>
<div class="holder flex-elem l-flex-col grows l-notebook-entry-content">
<div contenteditable="true"
ng-blur="textBlur($event, entry.id)"
ng-focus="textFocus($event, entry.id)"
ng-model="entry.text"
placeholder="Enter text here"
class="flex-elem s-input-inline t-notebook-entry-input s-notebook-entry-text"
ng-bind="entry.text">
</div>
<!-- embeds -->
<div class="flex-elem entry-embeds l-flex-row">
<div class="l-flex-row l-entry-embed {{embed.cssClass}}"
ng-repeat="embed in entry.embeds track by $index"
ng-class="{ 'has-snapshot' : embed.snapshot }"
id="{{embed.id}}">
<div class="snap-thumb"
ng-if="embed.snapshot"
ng-click="viewSnapshot($event,embed.snapshot.src,embed.id,entry.createdOn,this,embed)">
<img ng-src="{{embed.snapshot.src}}" src="//:0" alt="{{embed.id}}">
</div>
<div class="embed-info l-flex-col">
<div class="embed-title object-header">
<a ng-click='navigate($event,embed.type)'>{{embed.name}}</a>
<a class='context-available' ng-click='openMenu($event,embed.type)'></a>
</div>
<div class="hide-menu" ng-show="false">
<div class="menu-element context-menu-wrapper mobile-disable-select">
<div class="menu context-menu">
<ul>
<li ng-repeat="menu in menuEmbed"
ng-click="menu.perform($event,embed.snapshot.src,embed.id,entry.createdOn,this,embed)"
title="{{menu.getMetadata().description}}"
class="{{menu.getMetadata().cssClass}}"
ng-if="embed.snapshot">
{{menu.getMetadata().name}}
</li>
<li ng-repeat="menu in menuEmbedNoSnap"
ng-click="menu.perform($event,embed.snapshot.src,embed.id,entry.createdOn,this)"
title="{{menu.getMetadata().description}}"
class="{{menu.getMetadata().cssClass}}"
ng-if="!embed.snapshot">
{{menu.getMetadata().name}}
</li>
<li ng-repeat="menu in embedActions"
ng-click="menu.perform()"
title="{{menu.name}}"
class="{{menu.cssClass}}">
{{menu.name}}
</li>
</ul>
</div>
</div>
</div>
<div class="embed-date"
ng-if="embed.snapshot">{{embed.id| date:'yyyy-MM-dd HH:mm:ss'}}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- delete entry -->
<div class="holder flex-elem local-control local-controls-hidden notebook-entry-delete">
<a class="s-icon-button icon-trash" id={{entry.id}} title="Delete Entry" ng-click="deleteEntry($event)"></a>
</div>
</li>
</ul>
</div>
</div>

View File

@ -0,0 +1,8 @@
<span class="status block">
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<span class="status-indicator icon-bell"></span>
<span class="label">
Notifications
</span>
<span class="count"></span>
</span>

View File

@ -0,0 +1,34 @@
<div class="t-snapshot abs l-view-header">
<div class="abs object-browse-bar l-flex-row">
<div class="left flex-elem l-flex-row grows">
<div class="object-header flex-elem l-flex-row grows">
<div class="type-icon flex-elem embed-icon holder" ng-class="cssClass"></div>
<div class="title-label flex-elem holder flex-can-shrink">{{entryName}}</div>
<a class="context-available flex-elem holder" ng-click="openMenu($event,embedType)"></a>
<div class="hide-menu" ng-show="false">
<div class="menu-element menu-view context-menu-wrapper mobile-disable-select">
<div class="menu context-menu">
<ul>
<li ng-repeat="menu in embedActions"
ng-click="menuPerform(menu)"
title="{{menu.name}}"
class="{{menu.cssClass}}">
{{menu.name}}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
<div class="flex-elem holder flex-can-shrink s-snapshot-datetime">
SNAPSHOT {{snapDate | date:'yyyy-MM-dd HH:mm:ss'}}
</div>
<a class="s-button icon-pencil" title="Annotate">
<span class="title-label">Annotate</span>
</a>
</div>
</div>
</div>

View File

@ -26,7 +26,6 @@
define(
["painterro", "zepto"],
function (Painterro, $) {
var annotationStruct = {
title: "Annotate Snapshot",
template: "annotate-snapshot",
@ -108,6 +107,9 @@ define(
done(true);
}
}).show(snapshot);
$(document.body).find('.ptro-icon-btn').addClass('s-button');
$(document.body).find('.ptro-input').addClass('s-button');
});
}];

View File

@ -90,7 +90,7 @@ define(
var dialogService = this.dialogService;
var rootScope = this.$rootScope;
rootScope.newEntryText = '';
// // Create the overlay element and add it to the document's body
// Create the overlay element and add it to the document's body
this.$rootScope.selObj = domainObj;
this.$rootScope.selValue = "";
var newScope = rootScope.$new();
@ -187,7 +187,7 @@ define(
var domainObject = context.domainObject;
if (domainObject) {
if (domainObject.getModel().type === 'notebook') {
if (domainObject.getModel().type === 'Notebook') {
// do not allow in context of a notebook
return false;
} else if (domainObject.getModel().type.includes('imagery')) {

View File

@ -0,0 +1,72 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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.
*****************************************************************************/
define(
[],
function () {
function RemoveEmbed(dialogService,context) {
context = context || {};
this.domainObject = context.selectedObject || context.domainObject;
this.dialogService = dialogService;
}
RemoveEmbed.prototype.perform = function ($event,snapshot,embedId,entryId) {
var domainObject = this.domainObject;
var errorDialog = this.dialogService.showBlockingMessage({
severity: "error",
title: "This action will permanently delete this Embed. Do you want to continue?",
minimized: true, // want the notification to be minimized initially (don't show banner)
options: [{
label: "OK",
callback: function () {
errorDialog.dismiss();
remove();
}
},{
label: "Cancel",
callback: function () {
errorDialog.dismiss();
}
}]
});
function remove() {
domainObject.useCapability('mutation', function (model) {
var elementPos = model.entries.map(function (x) {
return x.createdOn;
}).indexOf(entryId);
var entryEmbeds = model.entries[elementPos].embeds;
var embedPos = entryEmbeds.map(function (x) {
return x.id;
}).indexOf(embedId);
model.entries[elementPos].embeds.splice(embedPos, 1);
});
}
};
return RemoveEmbed;
}
);

View File

@ -0,0 +1,74 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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.
*****************************************************************************/
define(
[],
function () {
function RemoveSnapshot(dialogService, context) {
context = context || {};
this.domainObject = context.selectedObject || context.domainObject;
this.dialogService = dialogService;
}
RemoveSnapshot.prototype.perform = function ($event, snapshot, embedId, entryId) {
var domainObject = this.domainObject;
var errorDialog = this.dialogService.showBlockingMessage({
severity: "error",
title: "This action will permanently delete this Snapshot. Do you want to continue?",
minimized: true, // want the notification to be minimized initially (don't show banner)
options: [{
label: "OK",
callback: function () {
errorDialog.dismiss();
remove();
}
},{
label: "Cancel",
callback: function () {
errorDialog.dismiss();
}
}]
});
function remove() {
domainObject.useCapability('mutation', function (model) {
var elementPos = model.entries.map(function (x) {
return x.createdOn;
}).indexOf(entryId);
var entryEmbeds = model.entries[elementPos].embeds;
var embedPos = entryEmbeds.map(function (x) {
return x.id;
}).indexOf(embedId);
model.entries[elementPos].embeds[embedPos].snapshot = "";
});
}
};
return RemoveSnapshot;
}
);

View File

@ -0,0 +1,132 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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.
*****************************************************************************/
/**
* Module defining ViewSnapshot
*/
var OVERLAY_TEMPLATE = '' +
' <div class="abs blocker"></div>' +
' <div class="abs outer-holder">' +
' <a class="close icon-x-in-circle"></a>' +
' <div class="abs inner-holder l-flex-col">' +
' <div class="t-contents flex-elem holder grows"></div>' +
' <div class="bottom-bar flex-elem holder">' +
' <a class="t-done s-button major">Done</a>' +
' </div>' +
' </div>' +
' </div>';
define([
'zepto',
"../../res/templates/snapshotHeader.html"
],
function ($, headerTemplate) {
var toggleOverlay,
overlay,
closeButton,
doneButton,
blocker,
overlayContainer,
img,
annotateButton,
annotateImg;
function ViewSnapshot($compile) {
this.$compile = $compile;
}
function openOverlay(url, header) {
overlay = document.createElement('div');
$(overlay).addClass('abs overlay l-large-view');
overlay.innerHTML = OVERLAY_TEMPLATE;
overlayContainer = overlay.querySelector('.t-contents');
closeButton = overlay.querySelector('a.close');
closeButton.addEventListener('click', toggleOverlay);
doneButton = overlay.querySelector('a.t-done');
doneButton.addEventListener('click', toggleOverlay);
blocker = overlay.querySelector('.abs.blocker');
blocker.addEventListener('click', toggleOverlay);
annotateButton = header.querySelector('a.icon-pencil');
annotateButton.addEventListener('click', annotateImg);
document.body.appendChild(overlay);
img = document.createElement('div');
$(img).addClass('abs object-holder t-image-holder s-image-holder');
img.innerHTML = '<div class="image-main s-image-main" style="background-image: url(' + url + ');"></div>';
overlayContainer.appendChild(header);
overlayContainer.appendChild(img);
}
function closeOverlay() {
overlayContainer.removeChild(img);
document.body.removeChild(overlay);
closeButton.removeEventListener('click', toggleOverlay);
closeButton = undefined;
doneButton.removeEventListener('click', toggleOverlay);
doneButton = undefined;
blocker.removeEventListener('click', toggleOverlay);
blocker = undefined;
overlayContainer = undefined;
overlay = undefined;
img = undefined;
}
ViewSnapshot.prototype.perform = function ($event, snapshot, embedId, entryId, $scope, embed) {
var isOpen = false;
// onclick for menu items in overlay header context menu
$scope.menuPerform = function (menu) {
menu.perform();
closeOverlay();
};
// Create the overlay element and add it to the document's body
$scope.cssClass = embed.cssClass;
$scope.embedType = embed.type;
$scope.entryName = embed.name;
$scope.snapDate = +embedId;
var element = this.$compile(headerTemplate)($scope);
var annotateAction = $scope.action.getActions({category: 'embed'})[1];
toggleOverlay = function () {
if (!isOpen) {
openOverlay(snapshot, element[0]);
isOpen = true;
} else {
closeOverlay();
isOpen = false;
}
};
annotateImg = function () {
closeOverlay();
annotateAction.perform($event, snapshot, embedId, entryId, $scope);
};
toggleOverlay();
};
return ViewSnapshot;
}
);

View File

@ -0,0 +1,50 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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.
*****************************************************************************/
define(
function () {
/**
* The notebook capability allows a domain object to know whether the
* notebook plugin is present or not.
*
* @constructor
*/
function NotebookCapability(typeService, domainObject) {
this.domainObject = domainObject;
this.typeService = typeService;
return this;
}
/**
* Returns true if there is a notebook domain Object.
*
* @returns {Boolean}
*/
NotebookCapability.prototype.isNotebook = function () {
return !!this.typeService.getType('notebook');
};
return NotebookCapability;
}
);

View File

@ -1,5 +1,5 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* Open MCT, Copyright (c) 2014-2017, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
@ -20,47 +20,35 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/**
* This bundle implements object types and associated views for
* display-building.
*/
define(
[],
function () {
define([
'vue',
'../../res/templates/viewSnapshot.html'
], function (
Vue,
snapshotOverlayTemplate
) {
function SnapshotOverlay (embedObject, formatTime) {
this.embedObject = embedObject;
/**
* The LayoutNotebookController is responsible for supporting the
* notebook feature creation on theLayout view.
**/
this.snapshotOverlayVue = new Vue({
template: snapshotOverlayTemplate,
data: function () {
return {
embed: embedObject
function LayoutNotebookController($scope) {
$scope.hasNotebookAction = undefined;
$scope.newNotebook = undefined;
var actions = $scope.domainObject.getCapability('action');
var notebookAction = actions.getActions({'key': 'notebook-new-entry'});
if (notebookAction.length > 0) {
$scope.hasNotebookAction = true;
$scope.newNotebook = function () {
notebookAction[0].perform();
};
},
methods: {
close: this.close.bind(this),
formatTime: formatTime
}
});
}
this.open();
return LayoutNotebookController;
}
);
SnapshotOverlay.prototype.open = function () {
this.overlay = document.createElement('div');
this.overlay.classList.add('abs');
document.body.appendChild(this.overlay);
this.overlay.appendChild(this.snapshotOverlayVue.$mount().$el);
};
SnapshotOverlay.prototype.close = function (event) {
event.stopPropagation();
this.snapshotOverlayVue.$destroy();
this.overlay.parentNode.removeChild(this.overlay);
};
return SnapshotOverlay;
});

View File

@ -31,7 +31,8 @@ define(
$scope.snapshot = undefined;
$scope.snapToggle = true;
$scope.entryText = '';
var annotateAction = $rootScope.selObj.getCapability('action').getActions({key: 'annotate-snapshot'})[0];
var annotateAction = $rootScope.selObj.getCapability('action').getActions(
{category: 'embed'})[1];
$scope.$parent.$parent.ngModel[$scope.$parent.$parent.field] = $rootScope.selObj;
$scope.objectName = $rootScope.selObj.getModel().name;

View File

@ -0,0 +1,367 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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.
*****************************************************************************/
/*-- main controller file, here is the core functionality of the notebook plugin --*/
define(
['zepto'],
function ($) {
function NotebookController(
$scope,
dialogService,
popupService,
agentService,
objectService,
navigationService,
now,
actionService,
$timeout,
$element,
$sce
) {
$scope.entriesEl = $(document.body).find('.t-entries-list');
$scope.sortEntries = $scope.domainObject.getModel().defaultSort;
$scope.showTime = "0";
$scope.editEntry = false;
$scope.entrySearch = '';
$scope.entryTypes = [];
$scope.embedActions = [];
$scope.currentEntryValue = '';
var SECONDS_IN_AN_HOUR = 60 * 60 * 1000;
this.scope = $scope;
$scope.hoursFilter = function (hours,entryTime) {
if (+hours) {
return entryTime > (Date.now() - SECONDS_IN_AN_HOUR * (+hours));
}else {
return true;
}
};
$scope.scrollToTop = function () {
var entriesContainer = $scope.entriesEl.parent();
entriesContainer[0].scrollTop = 0;
};
$scope.findEntryEl = function (entryId) {
var element = $($scope.entriesEl).find('#entry_' + entryId);
if (element[0]) {
return element.find("[contenteditable='true']");
} else {
var entries = $scope.entriesEl.children().children(),
lastOrFirst = $scope.sortEntries === "-createdOn" ? 0 : (entries.length - 1);
return $(entries[lastOrFirst]).find("[contenteditable='true']");
}
};
$scope.findEntryPositionById = function (id) {
var foundId = -1;
$scope.domainObject.model.entries.forEach(function (element, index) {
if (element.id === id) {
foundId = index;
return;
}
});
return foundId;
};
$scope.newEntry = function ($event) {
$scope.scrollToTop();
var entries = $scope.domainObject.model.entries,
lastEntry = entries[entries.length - 1],
id = Date.now();
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
var createdEntry = {'id': id, 'createdOn': id};
$scope.domainObject.useCapability('mutation', function (model) {
model.entries.push(createdEntry);
});
} else {
$scope.findEntryEl(lastEntry.id).focus();
$scope.domainObject.useCapability('mutation', function (model) {
model.entries[entries.length - 1].createdOn = id;
});
}
$scope.entrySearch = '';
};
$scope.deleteEntry = function ($event) {
var delId = +$event.currentTarget.id;
var errorDialog = dialogService.showBlockingMessage({
severity: "error",
title: "This action will permanently delete this Notebook entry. Do you want to continue?",
minimized: true, // want the notification to be minimized initially (don't show banner)
options: [{
label: "OK",
callback: function () {
errorDialog.dismiss();
var elementPos = $scope.findEntryPositionById(delId);
if (elementPos !== -1) {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries.splice(elementPos, 1);
});
} else {
window.console.log('delete error');
}
}
},{
label: "Cancel",
callback: function () {
errorDialog.dismiss();
}
}]
});
};
$scope.textFocus = function ($event, entryId) {
if ($event.srcElement) {
$scope.currentEntryValue = $event.srcElement.innerText;
} else {
$event.target.innerText = '';
}
};
//On text blur(when focus is removed)
$scope.textBlur = function ($event, entryId) {
// entryId is the unique numeric based on the original createdOn
if ($event.target) {
var elementPos = $scope.findEntryPositionById(+entryId);
// If the text of an entry has been changed, then update the text and the modifiedOn numeric
// Otherwise, don't do anything
if ($scope.currentEntryValue !== $event.target.innerText) {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries[elementPos].text = $event.target.innerText;
model.entries[elementPos].modified = Date.now();
});
}
}
};
$scope.finished = function (model) {
var lastEntry = model[model.length - 1];
if (!lastEntry.text) {
$scope.findEntryEl(lastEntry.id).focus();
}
};
$scope.handleActive = function () {
var newEntry = $scope.entriesEl.find('.active');
if (newEntry) {
newEntry.removeClass('active');
}
};
$scope.clearSearch = function () {
$scope.entrySearch = '';
};
$scope.viewSnapshot = function ($event,snapshot,embedId,entryId,$innerScope,domainObject) {
var viewAction = $scope.action.getActions({category: 'embed'})[0];
viewAction.perform($event, snapshot, embedId, entryId, $innerScope, domainObject);
};
$scope.renderImage = function (img) {
return URL.createObjectURL(img);
};
$scope.getDomainObj = function (id) {
return objectService.getObjects([id]);
};
function refreshComp(change) {
if (change && change.length) {
change[0].getCapability('action').getActions({key: 'remove'})[0].perform();
}
}
$scope.actionToMenuOption = function (action) {
return {
key: action.getMetadata().key,
name: action.getMetadata().name,
cssClass: action.getMetadata().cssClass,
perform: action.perform
};
};
// Maintain all "conclude-editing" and "save" actions in the
// present context.
function updateActions() {
$scope.menuEmbed = $scope.action ?
$scope.action.getActions({category: 'embed'}) :
[];
$scope.menuEmbedNoSnap = $scope.action ?
$scope.action.getActions({category: 'embed-no-snap'}) :
[];
$scope.menuActions = $scope.action ?
$scope.action.getActions({key: 'window'}) :
[];
}
// Update set of actions whenever the action capability
// changes or becomes available.
$scope.$watch("action", updateActions);
$scope.navigate = function ($event,embedType) {
if ($event) {
$event.preventDefault();
}
$scope.getDomainObj(embedType).then(function (resp) {
navigationService.setNavigation(resp[embedType]);
});
};
$scope.saveSnap = function (url,embedPos,entryPos) {
var snapshot = false;
if (url) {
if (embedPos !== -1 && entryPos !== -1) {
var reader = new window.FileReader();
reader.readAsDataURL(url);
reader.onloadend = function () {
snapshot = reader.result;
$scope.domainObject.useCapability('mutation', function (model) {
if (model.entries[entryPos]) {
model.entries[entryPos].embeds[embedPos].snapshot = {
'src': snapshot,
'type': url.type,
'size': url.size,
'modified': Date.now()
};
model.entries[entryPos].embeds[embedPos].id = Date.now();
}
});
};
}
}else {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries[entryPos].embeds[embedPos].snapshot = snapshot;
});
}
};
/*---popups menu embeds----*/
function getEmbedActions(embedType) {
if (!$scope.embedActions.length) {
$scope.getDomainObj(embedType).then(function (resp) {
$scope.embedActions = [];
$scope.embedActions.push($scope.actionToMenuOption(
$scope.action.getActions({key: 'mct-preview-action', selectedObject: resp[embedType]})[0]
));
$scope.embedActions.push($scope.actionToMenuOption(
$scope.action.getActions({key: 'window', selectedObject: resp[embedType]})[0]
));
$scope.embedActions.push({
key: 'navigate',
name: 'Go to Original',
cssClass: '',
perform: function () {
$scope.navigate('', embedType);
}
});
});
}
}
$scope.openMenu = function ($event,embedType) {
$event.preventDefault();
getEmbedActions(embedType);
var body = $(document).find('body'),
initiatingEvent = agentService.isMobile() ?
'touchstart' : 'mousedown',
dismissExistingMenu,
menu;
var container = $($event.currentTarget).parent().parent();
menu = container.find('.menu-element');
// Remove the context menu
function dismiss() {
container.find('.hide-menu').append(menu);
body.off("mousedown", dismiss);
dismissExistingMenu = undefined;
$scope.embedActions = [];
}
// Dismiss any menu which was already showing
if (dismissExistingMenu) {
dismissExistingMenu();
}
// ...and record the presence of this menu.
dismissExistingMenu = dismiss;
popupService.display(menu, [$event.pageX,$event.pageY], {
marginX: 0,
marginY: -50
});
// Stop propagation so that clicks or touches on the menu do not close the menu
menu.on(initiatingEvent, function (event) {
event.stopPropagation();
$timeout(dismiss, 300);
});
// Dismiss the menu when body is clicked/touched elsewhere
// ('mousedown' because 'click' breaks left-click context menus)
// ('touchstart' because 'touch' breaks context menus up)
body.on(initiatingEvent, dismiss);
};
$scope.$watchCollection("composition", refreshComp);
$scope.$watch('domainObject.getModel().defaultSort', function (newDefaultSort, oldDefaultSort) {
if (newDefaultSort !== oldDefaultSort) {
$scope.sortEntries = newDefaultSort;
}
});
$scope.$on('$destroy', function () {});
}
return NotebookController;
});

View File

@ -31,34 +31,32 @@ define(['zepto'], function ($) {
var selectedModel = selectedObject.getModel();
var cssClass = selectedObject.getCapability('type').typeDef.cssClass;
var entryId = -1;
var embedId = -1;
$scope.clearSearch();
if ($element[0].id === 'newEntry') {
entryId = $scope.domainObject.model.entries.length;
embedId = 0;
var lastEntry = $scope.domainObject.model.entries[entryId - 1];
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries.push({'createdOn': +Date.now(),
'id': +Date.now(),
'embeds': [{'type': selectedObject.getId(),
'id': '' + Date.now(),
'cssClass': cssClass,
'name': selectedModel.name,
'snapshot': ''
}]
});
'id': +Date.now(),
'embeds': [{'type': selectedObject.getId(),
'id': '' + Date.now(),
'cssClass': cssClass,
'name': selectedModel.name,
'snapshot': ''
}]
});
});
}else {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries[entryId - 1] =
{'createdOn': +Date.now(),
'embeds': [{'type': selectedObject.getId(),
'id': '' + Date.now(),
'cssClass': cssClass,
'name': selectedModel.name,
'snapshot': ''
}]
'embeds': [{'type': selectedObject.getId(),
'id': '' + Date.now(),
'cssClass': cssClass,
'name': selectedModel.name,
'snapshot': ''
}]
};
});
}
@ -77,15 +75,13 @@ define(['zepto'], function ($) {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries[entryId].embeds.push({'type': selectedObject.getId(),
'id': '' + Date.now(),
'cssClass': cssClass,
'name': selectedModel.name,
'snapshot': ''
});
'id': '' + Date.now(),
'cssClass': cssClass,
'name': selectedModel.name,
'snapshot': ''
});
});
embedId = $scope.domainObject.model.entries[entryId].embeds.length - 1;
if (selectedObject) {
e.preventDefault();

View File

@ -0,0 +1,44 @@
/******************************************************************************
* Open MCT, Copyright (c) 2014-2017, 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.
*****************************************************************************/
/**
* This bundle implements "containment" rules, which determine which objects
* can be contained within a notebook.
*/
define(
[],
function () {
function CompositionPolicy() {
}
CompositionPolicy.prototype.allow = function (parent, child) {
var parentDef = parent.getCapability('type').getName();
if (parentDef === 'Notebook' && child.getCapability('status').list().length) {
return false;
}
return true;
};
return CompositionPolicy;
}
);

View File

@ -31,14 +31,13 @@ define([
'./plugins/plugins',
'./adapter/indicators/legacy-indicators-plugin',
'./plugins/buildInfo/plugin',
'./adapter/vue-adapter/install',
'./ui/registries/ViewRegistry',
'./ui/registries/InspectorViewRegistry',
'./ui/registries/ToolbarRegistry',
'./ui/router/ApplicationRouter',
'./ui/router/Browse',
'../platform/framework/src/Main',
'./styles-new/core.scss',
'./styles-new/notebook.scss',
'./ui/components/layout/Layout.vue',
'vue'
], function (
@ -52,14 +51,13 @@ define([
plugins,
LegacyIndicatorsPlugin,
buildInfoPlugin,
installVueAdapter,
ViewRegistry,
InspectorViewRegistry,
ToolbarRegistry,
ApplicationRouter,
Browse,
Main,
coreStyles,
NotebookStyles,
Layout,
Vue
) {
@ -277,7 +275,6 @@ define([
}.bind(this)
});
// TODO: remove with legacy types.
this.types.listKeys().forEach(function (typeKey) {
var type = this.types.get(typeKey);
var legacyDefinition = type.toLegacyDefinition();
@ -285,6 +282,26 @@ define([
this.legacyExtension('types', legacyDefinition);
}.bind(this));
// TODO: move this to adapter bundle.
this.legacyExtension('runs', {
depends: ['types[]'],
implementation: (types) => {
this.types.importLegacyTypes(types);
}
});
this.objectViews.getAllProviders().forEach(function (p) {
this.legacyExtension('views', {
key: p.key,
provider: p,
name: p.name,
cssClass: p.cssClass,
description: p.description,
editable: p.editable,
template: '<mct-view mct-provider-key="' + p.key + '"/>'
});
}, this);
legacyRegistry.register('adapter', this.legacyBundle);
legacyRegistry.enable('adapter');
@ -309,6 +326,8 @@ define([
// something has depended upon objectService. Cool, right?
this.$injector.get('objectService');
console.log('Rendering app layout.');
var appLayout = new Vue({
mixins: [Layout.default],
provide: {
@ -317,8 +336,9 @@ define([
});
domElement.appendChild(appLayout.$mount().$el);
this.layout = appLayout;
Browse(this);
console.log('Attaching adapter');
installVueAdapter(appLayout, this);
this.router.start();
this.emit('start');
}.bind(this));

View File

@ -34,9 +34,7 @@ define([
'./runs/TimeSettingsURLHandler',
'./runs/TypeDeprecationChecker',
'./runs/LegacyTelemetryProvider',
'./runs/RegisterLegacyTypes',
'./services/LegacyObjectAPIInterceptor',
'./views/installLegacyViews'
'./services/LegacyObjectAPIInterceptor'
], function (
legacyRegistry,
ActionDialogDecorator,
@ -51,9 +49,7 @@ define([
TimeSettingsURLHandler,
TypeDeprecationChecker,
LegacyTelemetryProvider,
RegisterLegacyTypes,
LegacyObjectAPIInterceptor,
installLegacyViews
LegacyObjectAPIInterceptor
) {
legacyRegistry.register('src/adapter', {
"extensions": {
@ -153,21 +149,6 @@ define([
"openmct",
"instantiate"
]
},
{
implementation: installLegacyViews,
depends: [
"openmct",
"views[]",
"instantiate"
]
},
{
implementation: RegisterLegacyTypes,
depends: [
"types[]",
"openmct"
]
}
],
licenses: [

View File

@ -1,17 +0,0 @@
define([
], function (
) {
function RegisterLegacyTypes(types, openmct) {
types.forEach(function (legacyDefinition) {
if (!openmct.types.get(legacyDefinition.key)) {
console.warn(`DEPRECATION WARNING: Migrate type ${legacyDefinition.key} from ${legacyDefinition.bundle.path} to use the new Types API. Legacy type support will be removed soon.`);
}
});
openmct.types.importLegacyTypes(types);
}
return RegisterLegacyTypes;
});

View File

@ -1,93 +0,0 @@
define([
], function (
) {
function LegacyViewProvider(legacyView, openmct, convertToLegacyObject) {
console.warn(`DEPRECATION WARNING: Migrate ${legacyView.key} from ${legacyView.bundle.path} to use the new View APIs. Legacy view support will be removed soon.`);
return {
key: legacyView.key,
name: legacyView.name,
cssClass: legacyView.cssClass,
description: legacyView.description,
editable: legacyView.editable,
canView: function (domainObject) {
if (!domainObject || !domainObject.identifier) {
return false;
}
if (legacyView.type) {
return domainObject.type === legacyView.type;
}
let legacyObject = convertToLegacyObject(domainObject);
if (legacyView.needs) {
let meetsNeeds = legacyView.needs.every(k => legacyObject.hasCapability(k));
if (!meetsNeeds) {
return false;
}
}
return openmct.$injector.get('policyService').allow(
'view', legacyView, legacyObject
);
},
view: function (domainObject) {
let $rootScope = openmct.$injector.get('$rootScope');
let templateLinker = openmct.$injector.get('templateLinker');
let scope = $rootScope.$new();
let legacyObject = convertToLegacyObject(domainObject);
let isDestroyed = false;
scope.domainObject = legacyObject;
scope.model = legacyObject.getModel();
return {
show: function (container) {
// TODO: implement "gestures" support ?
let uses = legacyView.uses || [];
let promises = [];
let results = uses.map(function (capabilityKey, i) {
let result = legacyObject.useCapability(capabilityKey);
if (result.then) {
promises.push(result.then(function (r) {
results[i] = r;
}));
}
return result;
});
function link() {
if (isDestroyed) {
return;
}
uses.forEach(function (key, i) {
scope[key] = results[i];
});
templateLinker.link(
scope,
openmct.$angular.element(container),
legacyView
);
container.style.height = '100%';
}
if (promises.length) {
Promise.all(promises)
.then(function () {
link();
scope.$digest();
});
} else {
link();
}
},
destroy: function () {
scope.$destroy();
}
}
}
};
};
return LegacyViewProvider;
});

View File

@ -1,22 +0,0 @@
define([
'./LegacyViewProvider',
'../../api/objects/object-utils'
], function (
LegacyViewProvider,
objectUtils
) {
function installLegacyViews(openmct, legacyViews, instantiate) {
function convertToLegacyObject(domainObject) {
let keyString = objectUtils.makeKeyString(domainObject.identifier);
let oldModel = objectUtils.toOldFormat(domainObject);
return instantiate(oldModel, keyString);
}
legacyViews.forEach(function (legacyView) {
openmct.objectViews.addProvider(new LegacyViewProvider(legacyView, openmct, convertToLegacyObject));
});
}
return installLegacyViews;
});

View File

@ -0,0 +1,41 @@
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

@ -0,0 +1,16 @@
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

@ -0,0 +1,153 @@
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

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

View File

@ -89,13 +89,12 @@ define(function () {
}
}
}
if (legacyDefinition.features && legacyDefinition.features.includes("creation")) {
if (Array.isArray(legacyDefinition.creatable) && 'creation' in legacyDefinition.creatable) {
definition.creatable = true;
}
return definition;
};
}
return Type;
});

View File

@ -1,215 +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.
*****************************************************************************/
define([
"./src/controllers/NotebookController",
"./src/controllers/NewEntryController",
"./src/controllers/SelectSnapshotController",
"./src/actions/NewEntryContextual",
"./src/actions/AnnotateSnapshot",
"./src/directives/MCTSnapshot",
"./src/directives/EntryDnd",
"./res/templates/controls/snapSelect.html",
"./res/templates/controls/embedControl.html",
"./res/templates/annotation.html",
"./res/templates/draggedEntry.html"
], function (
NotebookController,
NewEntryController,
SelectSnapshotController,
newEntryAction,
AnnotateSnapshotAction,
MCTSnapshotDirective,
EntryDndDirective,
snapSelectTemplate,
embedControlTemplate,
annotationTemplate,
draggedEntryTemplate
) {
var installed = false;
function NotebookPlugin() {
return function install(openmct) {
if (installed) {
return;
}
installed = true;
openmct.legacyRegistry.register('notebook', {
name: 'Notebook Plugin',
extensions: {
types: [
{
key: 'notebook',
name: 'Notebook',
cssClass: 'icon-notebook',
description: 'Create and save timestamped notes with embedded object snapshots.',
features: 'creation',
model: {
entries: [],
composition: [],
entryTypes: [],
defaultSort: '-createdOn'
},
properties: [
{
key: 'defaultSort',
name: 'Default Sort',
control: 'select',
options: [
{
name: 'Newest First',
value: "-createdOn",
},
{
name: 'Oldest First',
value: "createdOn"
}
],
cssClass: 'l-inline'
}
]
}
],
actions: [
{
"key": "notebook-new-entry",
"implementation": newEntryAction,
"name": "New Notebook Entry",
"cssClass": "icon-notebook labeled",
"description": "Add a new Notebook entry",
"category": [
"view-control"
],
"depends": [
"$compile",
"$rootScope",
"dialogService",
"notificationService",
"linkService"
],
"priority": "preferred"
},
{
"key": "annotate-snapshot",
"implementation": AnnotateSnapshotAction,
"name": "Annotate Snapshot",
"cssClass": "icon-pencil labeled",
"description": "Annotate embed's snapshot",
"category": "embed",
"depends": [
"dialogService",
"dndService",
"$rootScope"
]
}
],
controllers: [
{
"key": "NewEntryController",
"implementation": NewEntryController,
"depends": ["$scope",
"$rootScope"
]
},
{
"key": "selectSnapshotController",
"implementation": SelectSnapshotController,
"depends": ["$scope",
"$rootScope"
]
}
],
controls: [
{
"key": "snapshot-select",
"template": snapSelectTemplate
},
{
"key": "embed-control",
"template": embedControlTemplate
}
],
templates: [
{
"key": "annotate-snapshot",
"template": annotationTemplate
}
],
directives: [
{
"key": "mctSnapshot",
"implementation": MCTSnapshotDirective,
"depends": [
"$rootScope",
"$document",
"exportImageService",
"dialogService",
"notificationService"
]
},
{
"key": "mctEntryDnd",
"implementation": EntryDndDirective,
"depends": [
"$rootScope",
"$compile",
"dndService",
"typeService",
"notificationService"
]
}
],
representations: [
{
"key": "draggedEntry",
"template": draggedEntryTemplate
}
]
}
});
openmct.legacyRegistry.enable('notebook');
openmct.objectViews.addProvider({
key: 'notebook-vue',
name: 'Notebook View',
cssClass: 'icon-notebook',
canView: function (domainObject) {
return domainObject.type === 'notebook';
},
view: function (domainObject) {
var controller = new NotebookController (openmct, domainObject);
return {
show: controller.show,
destroy: controller.destroy
};
}
});
};
}
return NotebookPlugin;
});

View File

@ -1,32 +0,0 @@
<div class="c-ne__embed">
<div class="c-ne__embed__snap-thumb"
v-if="embed.snapshot"
v-on:click="openSnapshot">
<img v-bind:src="embed.snapshot.src">
</div>
<div class="c-ne__embed__info">
<div class="c-ne__embed__name">
<a class="c-ne__embed__link"
v-on:click="navigate(embed.type)"
v-bind:class="[embed.cssClass]">{{embed.name}}</a>
<a class="c-ne__embed__context-available icon-arrow-down"
v-on:click="toggleActionMenu"></a>
</div>
<div class="hide-menu hidden">
<div class="menu-element context-menu-wrapper mobile-disable-select">
<div class="menu context-menu">
<ul>
<li v-for="action in actions"
v-bind:class="[action.cssClass]"
v-on:click="action.perform(embed, entry)">
{{ action.name }}
</li>
</ul>
</div>
</div>
</div>
<div class="c-ne__embed__time" v-if="embed.snapshot">
{{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}}
</div>
</div>
</div>

View File

@ -1,35 +0,0 @@
<li class="c-notebook__entry c-ne has-local-controls"
v-on:drop="dropOnEntry(entry.id)"
v-on:dragover="dragoverOnEntry"
>
<div class="c-ne__time-and-content">
<div class="c-ne__time">
<span>{{formatTime(entry.createdOn, 'YYYY-MM-DD')}}</span>
<span>{{formatTime(entry.createdOn, 'HH:mm:ss')}}</span>
</div>
<div class="c-ne__content">
<!-- TODO: fix styling for c-input-inline when SCSS is merged and remove s-input-inline class here -->
<div class="c-ne__text c-input-inline s-input-inline"
contenteditable="true"
ref="contenteditable"
v-on:blur="textBlur($event, entry.id)"
v-on:focus="textFocus($event, entry.id)"
v-bind:key="entry.id"
v-html="entry.text">
</div>
<div class="c-ne__embeds">
<notebook-embed
v-for="(embed, index) in entry.embeds"
v-bind:embed="embed"
v-bind:entry="entry"
></notebook-embed>
</div>
</div>
</div>
<div class="c-ne__local-controls--hidden">
<a class="c-icon-button icon-trash"
title="Delete this entry"
v-on:click="deleteEntry"></a>
</div>
</li>

View File

@ -1,37 +0,0 @@
<div class="c-notebook">
<div class="c-notebook__head">
<search class="c-notebook__search"
v-model="entrySearch"
v-on:input="search($event)"
v-on:clear="entrySearch = ''; search($event)"></search>
<div class="c-notebook__controls">
<div class="select c-notebook__controls__time">
<select v-model="showTime">
<option value="0" selected="selected">Show all</option>
<option value="1">Last hour</option>
<option value="8">Last 8 hours</option>
<option value="24">Last 24 hours</option>
</select>
</div>
<div class="select c-notebook__controls__sort">
<select v-model="sortEntries">
<option value="-createdOn" selected="selected">Newest first</option>
<option value="createdOn">Oldest first</option>
</select>
</div>
</div>
</div>
<div class="c-notebook__drag-area icon-plus"
v-on:click="newEntry($event)"
id="newEntry" mct-entry-dnd>
<span class="c-notebook__drag-area__label">To start a new entry, click here or drag and drop any object</span>
</div>
<div class="c-notebook__entries" ng-mouseover="handleActive()">
<ul>
<notebook-entry
v-for="entry in filterBySearch(entries, entrySearch)"
v-bind:entry="entry"
></notebook-entry>
</ul>
</div>
</div>

View File

@ -1,50 +0,0 @@
<div class="abs overlay l-large-view">
<div class="abs blocker" v-on:click="close"></div>
<div class="abs outer-holder">
<a
class="close icon-x-in-circle"
v-on:click="close">
</a>
<div class="abs inner-holder l-flex-col">
<div class="t-contents flex-elem holder grows">
<div class="t-snapshot abs l-view-header">
<div class="abs object-browse-bar l-flex-row">
<div class="left flex-elem l-flex-row grows">
<div class="object-header flex-elem l-flex-row grows">
<div class="type-icon flex-elem embed-icon holder" v-bind:class="embed.cssClass"></div>
<div class="title-label flex-elem holder flex-can-shrink">{{embed.name}}</div>
</div>
</div>
</div>
</div>
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
<div class="flex-elem holder flex-can-shrink s-snapshot-datetime">
SNAPSHOT {{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}}
</div>
<a class="s-button icon-pencil" title="Annotate">
<span class="title-label">Annotate</span>
</a>
</div>
<div class="abs object-holder t-image-holder s-image-holder">
<div
class="image-main s-image-main"
v-bind:style="{ backgroundImage: 'url(' + embed.snapshot.src + ')' }">
</div>
</div>
</div>
<div
class="bottom-bar flex-elem holder"
v-on:click="close">
<a class="t-done s-button major">Done</a>
</div>
</div>
</div>
</div>

View File

@ -1,130 +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.
*****************************************************************************/
define(
['zepto'],
function ($) {
function SnapshotAction (exportImageService, dialogService, context) {
this.exportImageService = exportImageService;
this.dialogService = dialogService;
this.domainObject = context.domainObject;
}
SnapshotAction.prototype.perform = function () {
var elementToSnapshot =
$(document.body).find(".overlay .object-holder")[0] ||
$(document.body).find("[key='representation.selected.key']")[0];
$(elementToSnapshot).addClass("s-status-taking-snapshot");
this.exportImageService.exportPNGtoSRC(elementToSnapshot).then(function (blob) {
$(elementToSnapshot).removeClass("s-status-taking-snapshot");
if (blob) {
var reader = new window.FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
this.saveSnapshot(reader.result, blob.type, blob.size);
}.bind(this);
}
}.bind(this));
};
SnapshotAction.prototype.saveSnapshot = function (imageURL, imageType, imageSize) {
var taskForm = this.generateTaskForm(),
domainObject = this.domainObject,
domainObjectId = domainObject.getId(),
cssClass = domainObject.getCapability('type').typeDef.cssClass,
name = domainObject.model.name;
this.dialogService.getDialogResponse(
'overlay-dialog',
taskForm,
function () {
return taskForm.value;
}
).then(function (options) {
var snapshotObject = {
src: imageURL,
type: imageType,
size: imageSize
};
options.notebook.useCapability('mutation', function (model) {
var date = Date.now();
model.entries.push({
id: 'entry-' + date,
createdOn: date,
text: options.entry,
embeds: [{
name: name,
cssClass: cssClass,
type: domainObjectId,
id: 'embed-' + date,
createdOn: date,
snapshot: snapshotObject
}]
});
});
});
};
SnapshotAction.prototype.generateTaskForm = function () {
var taskForm = {
name: "Create a Notebook Entry",
hint: "Please select a Notebook",
sections: [{
rows: [{
name: 'Entry',
key: 'entry',
control: 'textarea',
required: false,
"cssClass": "l-textarea-sm"
},
{
name: 'Save in Notebook',
key: 'notebook',
control: 'locator',
validate: validateLocation
}]
}]
};
var overlayModel = {
title: taskForm.name,
message: 'AHAHAH',
structure: taskForm,
value: {'entry': ""}
};
function validateLocation(newParentObj) {
return newParentObj.model.type === 'notebook';
}
return overlayModel;
};
return SnapshotAction;
}
);

View File

@ -1,198 +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.
*****************************************************************************/
define([
'moment',
'zepto',
'../utils/SnapshotOverlay',
],
function (
Moment,
$,
SnapshotOverlay
) {
function EmbedController (openmct, domainObject) {
this.openmct = openmct;
this.domainObject = domainObject;
this.objectService = openmct.$injector.get('objectService');
this.navigationService = openmct.$injector.get('navigationService');
this.popupService = openmct.$injector.get('popupService');
this.agentService = openmct.$injector.get('agentService');
this.dialogService = openmct.$injector.get('dialogService');
this.navigate = this.navigate.bind(this);
this.exposedData = this.exposedData.bind(this);
this.exposedMethods = this.exposedMethods.bind(this);
this.toggleActionMenu = this.toggleActionMenu.bind(this);
}
EmbedController.prototype.navigate = function (embedType) {
this.objectService.getObjects([embedType]).then(function (objects) {
this.navigationService.setNavigation(objects[embedType]);
}.bind(this));
};
EmbedController.prototype.openSnapshot = function () {
if (!this.snapshotOverlay) {
this.snapShotOverlay = new SnapshotOverlay(this.embed, this.formatTime);
} else {
this.snapShotOverlay = undefined;
}
};
EmbedController.prototype.formatTime = function (unixTime, timeFormat) {
return Moment(unixTime).format(timeFormat);
};
EmbedController.prototype.findInArray = function (array, id) {
var foundId = -1;
array.forEach(function (element, index) {
if (element.id === id) {
foundId = index;
return;
}
});
return foundId;
};
EmbedController.prototype.actionToMenuDecorator = function (action) {
return {
name: action.getMetadata().name,
cssClass: action.getMetadata().cssClass,
perform: action.perform
};
};
EmbedController.prototype.populateActionMenu = function (objectService, actionService) {
return function () {
var self = this;
objectService.getObjects([self.embed.type]).then(function (resp) {
var domainObject = resp[self.embed.type],
previewAction = actionService.getActions({key: 'mct-preview-action', domainObject: domainObject})[0];
self.actions.push(self.actionToMenuDecorator(previewAction));
});
};
};
EmbedController.prototype.removeEmbedAction = function () {
var self = this;
return {
name: 'Remove Embed',
cssClass: 'icon-trash',
perform: function (embed, entry) {
var entryPosition = self.findInArray(self.domainObject.entries, entry.id),
embedPosition = self.findInArray(entry.embeds, embed.id);
var warningDialog = self.dialogService.showBlockingMessage({
severity: "error",
title: "This action will permanently delete this embed. Do you wish to continue?",
options: [{
label: "OK",
callback: function () {
entry.embeds.splice(embedPosition, 1);
var dirString = 'entries[' + entryPosition + '].embeds';
self.openmct.objects.mutate(self.domainObject, dirString, entry.embeds);
warningDialog.dismiss();
}
},{
label: "Cancel",
callback: function () {
warningDialog.dismiss();
}
}]
});
}
};
};
EmbedController.prototype.toggleActionMenu = function (event) {
event.preventDefault();
var body = $(document.body),
container = $(event.target.parentElement.parentElement),
initiatingEvent = this.agentService.isMobile() ?
'touchstart' : 'mousedown',
menu = container.find('.menu-element'),
dismissExistingMenu;
// Remove the context menu
function dismiss() {
container.find('.hide-menu').append(menu);
body.off(initiatingEvent, dismiss);
menu.off(initiatingEvent, menuClickHandler);
dismissExistingMenu = undefined;
}
function menuClickHandler(e) {
e.stopPropagation();
window.setTimeout(dismiss, 300);
}
// Dismiss any menu which was already showing
if (dismissExistingMenu) {
dismissExistingMenu();
}
// ...and record the presence of this menu.
dismissExistingMenu = dismiss;
this.popupService.display(menu, [event.pageX,event.pageY], {
marginX: 0,
marginY: -50
});
// Stop propagation so that clicks or touches on the menu do not close the menu
menu.on(initiatingEvent, menuClickHandler);
body.on(initiatingEvent, dismiss);
};
EmbedController.prototype.exposedData = function () {
return {
actions: [this.removeEmbedAction()],
showActionMenu: false
};
};
EmbedController.prototype.exposedMethods = function () {
var self = this;
return {
navigate: self.navigate,
openSnapshot: self.openSnapshot,
formatTime: self.formatTime,
toggleActionMenu: self.toggleActionMenu,
actionToMenuDecorator: self.actionToMenuDecorator
};
};
return EmbedController;
});

View File

@ -1,150 +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.
*****************************************************************************/
define([
'moment'
],
function (
Moment
) {
function EntryController (openmct, domainObject) {
this.openmct = openmct;
this.domainObject = domainObject;
this.dndService = this.openmct.$injector.get('dndService');
this.dialogService = this.openmct.$injector.get('dialogService');
this.currentEntryValue = '';
this.exposedMethods = this.exposedMethods.bind(this);
this.exposedData = this.exposedData.bind(this);
}
EntryController.prototype.entryPosById = function (entryId) {
var foundId = -1;
this.domainObject.entries.forEach(function (element, index) {
if (element.id === entryId) {
foundId = index;
return;
}
});
return foundId;
};
EntryController.prototype.textFocus = function ($event) {
if ($event.target) {
this.currentEntryValue = $event.target.innerText;
} else {
$event.target.innerText = '';
}
};
EntryController.prototype.textBlur = function ($event, entryId) {
if ($event.target) {
var entryPos = this.entryPosById(entryId);
if (this.currentEntryValue !== $event.target.innerText) {
this.openmct.objects.mutate(this.domainObject, 'entries[' + entryPos + '].text', $event.target.innerText);
}
}
};
EntryController.prototype.formatTime = function (unixTime, timeFormat) {
return Moment(unixTime).format(timeFormat);
};
EntryController.prototype.deleteEntry = function () {
var entryPos = this.entryPosById(this.entry.id),
domainObject = this.domainObject,
openmct = this.openmct;
if (entryPos !== -1) {
var errorDialog = this.dialogService.showBlockingMessage({
severity: "error",
title: "This action will permanently delete this Notebook entry. Do you wish to continue?",
options: [{
label: "OK",
callback: function () {
domainObject.entries.splice(entryPos, 1);
openmct.objects.mutate(domainObject, 'entries', domainObject.entries);
errorDialog.dismiss();
}
},{
label: "Cancel",
callback: function () {
errorDialog.dismiss();
}
}]
});
}
};
EntryController.prototype.dropOnEntry = function (entryId) {
var selectedObject = this.dndService.getData('mct-domain-object'),
selectedObjectId = selectedObject.getId(),
selectedModel = selectedObject.getModel(),
cssClass = selectedObject.getCapability('type').typeDef.cssClass,
entryPos = this.entryPosById(entryId),
currentEntryEmbeds = this.domainObject.entries[entryPos].embeds,
newEmbed = {
type: selectedObjectId,
id: '' + Date.now(),
cssClass: cssClass,
name: selectedModel.name,
snapshot: ''
};
currentEntryEmbeds.push(newEmbed);
this.openmct.objects.mutate(this.domainObject, 'entries[' + entryPos + '].embeds', currentEntryEmbeds);
};
EntryController.prototype.dragoverOnEntry = function () {
};
EntryController.prototype.exposedData = function () {
return {
openmct: this.openmct,
domainObject: this.domainObject,
dndService: this.dndService,
dialogService: this.dialogService,
currentEntryValue: this.currentEntryValue
};
};
EntryController.prototype.exposedMethods = function () {
return {
entryPosById: this.entryPosById,
textFocus: this.textFocus,
textBlur: this.textBlur,
formatTime: this.formatTime,
deleteEntry: this.deleteEntry,
dropOnEntry: this.dropOnEntry,
dragoverOnEntry: this.dragoverOnEntry
};
};
return EntryController;
});

View File

@ -1,177 +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.
*****************************************************************************/
define([
'vue',
'./EntryController',
'./EmbedController',
'../../res/templates/notebook.html',
'../../res/templates/entry.html',
'../../res/templates/embed.html',
'../../../../ui/components/controls/search.vue'
],
function (
Vue,
EntryController,
EmbedController,
NotebookTemplate,
EntryTemplate,
EmbedTemplate,
search
) {
function NotebookController(openmct, domainObject) {
this.openmct = openmct;
this.domainObject = domainObject;
this.entrySearch = '';
this.objectService = openmct.$injector.get('objectService');
this.actionService = openmct.$injector.get('actionService');
this.show = this.show.bind(this);
this.destroy = this.destroy.bind(this);
this.newEntry = this.newEntry.bind(this);
this.entryPosById = this.entryPosById.bind(this);
}
NotebookController.prototype.initializeVue = function (container) {
var self = this,
entryController = new EntryController(this.openmct, this.domainObject),
embedController = new EmbedController(this.openmct, this.domainObject);
this.container = container;
var notebookEmbed = {
props:['embed', 'entry'],
template: EmbedTemplate,
data: embedController.exposedData,
methods: embedController.exposedMethods(),
beforeMount: embedController.populateActionMenu(self.objectService, self.actionService)
};
var entryComponent = {
props:['entry'],
template: EntryTemplate,
components: {
'notebook-embed': notebookEmbed
},
data: entryController.exposedData,
methods: entryController.exposedMethods(),
mounted: self.focusOnEntry
};
var notebookVue = Vue.extend({
template: NotebookTemplate,
components: {
'notebook-entry': entryComponent,
'search': search.default
},
data: function () {
return {
entrySearch: self.entrySearch,
showTime: '0',
sortEntries: '-createdOn',
entries: self.domainObject.entries,
currentEntryValue: ''
};
},
methods: {
search: function (event) {
if (event.target.value) {
this.entrySearch = event.target.value;
}
},
newEntry: self.newEntry,
filterBySearch: self.filterBySearch
}
});
this.NotebookVue = new notebookVue();
container.appendChild(this.NotebookVue.$mount().$el);
};
NotebookController.prototype.newEntry = function (event) {
var entries = this.domainObject.entries,
lastEntryIndex = entries.length - 1,
lastEntry = entries[lastEntryIndex],
date = Date.now();
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds.length) {
var createdEntry = {'id': 'entry-' + date, 'createdOn': date, 'embeds':[]};
entries.push(createdEntry);
this.openmct.objects.mutate(this.domainObject, 'entries', entries);
} else {
lastEntry.createdOn = date;
this.openmct.objects.mutate(this.domainObject, 'entries[entries.length-1]', lastEntry);
this.focusOnEntry.bind(this.NotebookVue.$children[lastEntryIndex])();
}
this.entrySearch = '';
};
NotebookController.prototype.entryPosById = function (entryId) {
var foundId = -1;
this.domainObject.entries.forEach(function (element, index) {
if (element.id === entryId) {
foundId = index;
return;
}
});
return foundId;
};
NotebookController.prototype.focusOnEntry = function () {
if (!this.entry.text) {
this.$refs.contenteditable.focus();
}
};
NotebookController.prototype.filterBySearch = function (entryArray, filterString) {
if (filterString) {
var lowerCaseFilterString = filterString.toLowerCase();
return entryArray.filter(function (entry) {
if (entry.text) {
return entry.text.toLowerCase().includes(lowerCaseFilterString);
} else {
return false;
}
});
} else {
return entryArray;
}
};
NotebookController.prototype.show = function (container) {
this.initializeVue(container);
};
NotebookController.prototype.destroy = function (container) {
this.NotebookVue.$destroy(true);
};
return NotebookController;
});

View File

@ -27,14 +27,14 @@ define([
'./autoflow/AutoflowTabularPlugin',
'./timeConductor/plugin',
'../../example/imagery/plugin',
'../../platform/features/notebook/bundle',
'../../platform/import-export/bundle',
'./summaryWidget/plugin',
'./URLIndicatorPlugin/URLIndicatorPlugin',
'./telemetryMean/plugin',
'./plot/plugin',
'./telemetryTable/plugin',
'./staticRootPlugin/plugin',
'./notebook/plugin'
'./staticRootPlugin/plugin'
], function (
_,
UTCTimeSystem,
@ -42,18 +42,19 @@ define([
AutoflowPlugin,
TimeConductorPlugin,
ExampleImagery,
Notebook,
ImportExport,
SummaryWidget,
URLIndicatorPlugin,
TelemetryMean,
PlotPlugin,
TelemetryTablePlugin,
StaticRootPlugin,
Notebook
StaticRootPlugin
) {
var bundleMap = {
LocalStorage: 'platform/persistence/local',
MyItems: 'platform/features/my-items'
MyItems: 'platform/features/my-items',
Notebook: 'platform/features/notebook'
};
var plugins = _.mapValues(bundleMap, function (bundleName, pluginName) {
@ -158,7 +159,6 @@ define([
plugins.SummaryWidget = SummaryWidget;
plugins.TelemetryMean = TelemetryMean;
plugins.URLIndicator = URLIndicatorPlugin;
plugins.Notebook = Notebook;
return plugins;
});

View File

@ -15,8 +15,7 @@ define([
function SummaryWidgetViewProvider(openmct) {
return {
key: 'summary-widget-viewer',
name: 'Summary View',
cssClass: 'icon-summary-widget',
name: 'Widget View',
canView: function (domainObject) {
return domainObject.type === 'summary-widget';
},

View File

@ -0,0 +1,123 @@
/*****************************************************************************
* 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

@ -19,3 +19,24 @@
* 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

@ -48,12 +48,7 @@ define(function () {
}
getFormattedValue(telemetryDatum) {
let formattedValue = this.formatter.format(telemetryDatum);
if (typeof formattedValue !== 'string') {
return formattedValue.toString();
} else {
return formattedValue;
}
return this.formatter.format(telemetryDatum);
}
};

View File

@ -39,7 +39,7 @@ define([], function () {
getFormattedValue(key) {
let column = this.columns[key];
return column && column.getFormattedValue(this.datum[key]);
return column.getFormattedValue(this.datum[key]);
}
getRowLimitClass() {

View File

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

View File

@ -35,7 +35,6 @@ define([
return {
key: 'table',
name: 'Telemetry Table',
cssClass: 'icon-tabular-realtime',
editable: function(domainObject) {
return domainObject.type === 'table';
},

View File

@ -0,0 +1,111 @@
/*****************************************************************************
* 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

@ -32,9 +32,7 @@ export default {
columnWidths: {
type: Array,
required: false,
default() {
return [];
},
default: [],
},
rowIndex: {
type: Number,
@ -50,6 +48,10 @@ export default {
type: Number,
required: false,
default: 0
},
configuration: {
type: Object,
required: true
}
},
methods: {

View File

@ -19,16 +19,16 @@
:class="['is-sortable', sortOptions.key === key ? 'is-sorting' : '', sortOptions.direction].join(' ')"
:style="{ width: columnWidths[headerIndex], 'max-width': columnWidths[headerIndex]}">{{title}}</th>
</tr>
<tr>
<tr class="s-filters">
<th v-for="(title, key, headerIndex) in headers"
:style="{
width: columnWidths[headerIndex],
'max-width': columnWidths[headerIndex],
}">
<search class="c-table__search"
v-model="filters[key]"
v-on:input="filterChanged(key)"
v-on:clear="clearFilter(key)" />
<div class="holder l-filter flex-elem grows" :class="{active: filters[key]}">
<input type="text" v-model="filters[key]" v-on:input="filterChanged(key)" />
<a class="clear-icon clear-input icon-x-in-circle" :class="{show: filters[key]}" @click="clearFilter(key)"></a>
</div>
</th>
</tr>
</thead>
@ -80,8 +80,7 @@
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
&__control-bar,
&__headers-w {
> [class*="__"] + [class*="__"] {
// Don't allow top level elements to grow or shrink
flex: 0 0 auto;
}
@ -90,7 +89,6 @@
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;
@ -205,7 +203,7 @@
/******************************* WRAPPERS */
&__body-w {
// Wraps __body table provides scrolling
flex: 1 1 100%;
flex: 1 1 100% !important; // TODO: temp override on tabular-holder > * { style which sets this to 0 0 auto
overflow-x: auto;
overflow-y: scroll;
}
@ -235,7 +233,7 @@
z-index: -1;
visibility: hidden;
pointer-events: none;
position: absolute;
position: absolute !important; // TODO: fix tabular-holder > * { which sets this to pos: relative
//Add some padding to allow for decorations such as limits indicator
tr {
@ -266,7 +264,6 @@
<script>
import TelemetryTableRow from './table-row.vue';
import search from '../../../ui/components/controls/search.vue';
import _ from 'lodash';
const VISIBLE_ROW_COUNT = 100;
@ -276,8 +273,7 @@ const AUTO_SCROLL_TRIGGER_HEIGHT = 20;
export default {
components: {
TelemetryTableRow,
search
TelemetryTableRow
},
inject: ['table', 'openmct', 'csvExporter'],
props: ['configuration'],

View File

@ -1,6 +1,6 @@
@import "constants";
// Functions
// Mixins
@function pullForward($c: $colorBodyBg, $p: 20%) {
// For dark interfaces, lighter things come forward - opposite for light interfaces
@return darken($c, $p);
@ -12,7 +12,6 @@
}
// Global
$fontBaseSize: 12px;
$colorBodyBg: #fcfcfc;
$colorBodyFg: #666;
$colorGenBg: #fff;
@ -20,7 +19,6 @@ $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;
@ -38,8 +36,7 @@ $overlayCr: 11px;
$shdwTextSubtle: rgba(black, 0.2) 0 1px 2px;
// Buttons and Controls
$btnPad: $interiorMargin, $interiorMargin * 1.25;
$colorBtnBg: #aaaaaa;
$colorBtnBg: pullForward($colorBodyBg, $contrastRatioPercent);
$colorBtnBgHov: pullForward($colorBtnBg, $hoverRatioPercent);
$colorBtnFg: #fff;
$colorBtnFgHov: $colorBtnFg;
@ -71,7 +68,6 @@ $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;
@ -94,18 +90,17 @@ $colorTick: rgba(black, 0.2);
$colorSelectableSelectedPrimary: $colorKey;
$colorSelectableHov: rgba($colorBodyFg, 0.4);
// Menus
// Menu colors
$colorMenuBg: pushBack($colorBodyBg, 10%);
$colorMenuFg: pullForward($colorMenuBg, 70%);
$colorMenuIc: $colorKey;
$colorMenuHovBg: $colorMenuIc; //pullForward($colorMenuBg, $hoverRatioPercent);
$colorMenuHovFg: $colorMenuBg;
$colorMenuHovIc: $colorMenuBg;
$colorMenuHovBg: pullForward($colorMenuBg, $hoverRatioPercent);
$colorMenuHovFg: $colorMenuFg;
$colorMenuHovIc: $colorMenuIc;
$shdwMenu: rgba(black, 0.5) 0 1px 5px;
$shdwMenuText: none;
$colorCreateMenuLgIcon: $colorKey;
$colorCreateMenuText: $colorBodyFg;
$menuItemPad: ($interiorMargin, nth($btnPad, 2));
// Form colors
$colorCheck: $colorKey;
@ -243,14 +238,13 @@ $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); // height, width
$splitterBtnD: (16px, 35px);
$splitterBtnColorBg: #eee;
$splitterBtnColorFg: #999;
$splitterBtnColorHoverBg: rgba($colorKey, 1);
@ -294,16 +288,3 @@ $colorLoadingBg: rgba($colorLoadingFg, 0.1);
// Transitions
$transIn: all 50ms ease-in;
$transOut: all 250ms ease-out;
// Discrete items, like Notebook entries, Widget rules
@mixin discreteItem() {
background: rgba($colorBodyFg,0.1);
border: 1px solid $colorInteriorBorder;
border-radius: $controlCr;
.c-input-inline:hover {
background: $colorBodyBg;
}
}
@mixin discreteItemInnerElem() {
border: 1px solid $colorBodyBg;
border-radius: $controlCr; }

View File

@ -15,10 +15,8 @@ $interiorMarginLg: 10px;
$inputTextPTopBtm: 2px;
$inputTextPLeftRight: 5px;
$inputTextP: $inputTextPTopBtm $inputTextPLeftRight;
$menuLineH: 1.5rem;
$treeItemIndent: 16px;
$treeTypeIconW: 18px;
/*************** Items */
$itemPadLR: 5px;
$ueBrowseGridItemLg: 200px;
@ -113,7 +111,6 @@ $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';
@ -146,37 +143,3 @@ $glyph-icon-topic: '\e1128';
$glyph-icon-box-with-dashed-lines: '\e1129';
$glyph-icon-summary-widget: '\e1130';
$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

@ -1,356 +0,0 @@
/******************************************************** 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 via markup
.c-button,
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,9 +28,7 @@
}
/******************************* RESETS */
*,
:before,
:after {
* {
box-sizing: border-box;
}
@ -43,15 +41,6 @@ div {
display: contents;
}
.u-space {
// Provides a separator space between elements
&--right {
+ [class*="__"] {
margin-left: $interiorMarginLg !important;
}
}
}
/******************************* BROWSER ELEMENTS */
body.desktop {
::-webkit-scrollbar {
@ -106,9 +95,8 @@ body, html {
body {
-webkit-font-smoothing: subpixel-antialiased;
-moz-osx-font-smoothing: grayscale;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: $fontBaseSize;
font-size: 13px;
font-weight: normal;
background-color: $colorBodyBg;
color: $colorBodyFg;
@ -163,54 +151,6 @@ table {
border-collapse: collapse;
}
li {
list-style-type: none;
margin: 0;
padding: 0;
}
/******************************************************** HAS */
// Local Controls: Controls placed in proximity to or overlaid on components and views
body.desktop .has-local-controls {
// Provides hover ability to show local controls
&:hover [class*="local-controls--hidden"] {
transition: opacity 50ms ease-in-out;
opacity: 1;
pointer-events: inherit;
}
[class*="local-controls--hidden"] {
transition: opacity 500ms ease-in-out;
opacity: 0;
pointer-events: none;
}
}
//[class*="local-controls"] {
// // An explicit outer holder for controls. Typically placed in upper right.
// //font-size: 0.7rem;
// display: flex;
// align-items: center;
// justify-content: flex-end;
//
//
// &.h-local-controls-overlay-content {
// // Imagery controls
// $p: $interiorMargin;
// position: absolute;
// top: $p; right: $p;
// z-index: 2;
// }
//.l-btn-set,
//.s-button {
// &:not(:first-child) {
// margin-left: $interiorMargin;
// }
//}
//}
/************************** LEGACY */
mct-container {

View File

@ -1,3 +1,24 @@
/*****************************************************************************
* 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;
@ -12,21 +33,16 @@
}
}
@mixin glyphBg($glyphUrl) {
background-image: $glyphUrl;
background-position: center;
background-size: contain;
background-repeat: no-repeat;
}
[class*="icon-"] {
&:before, &:after
{
-webkit-font-smoothing: antialiased;
[class*="icon-"].labeled {
// Moved from .s-button and generalized
&:before {
// Fend off label from icon when it's included
margin-right: $interiorMarginSm;
}
}
/************************** 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); }
@ -146,36 +162,3 @@
.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,36 +62,6 @@
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;
@ -110,10 +80,13 @@
}
/************************** CONTROLS, BUTTONS */
@mixin input-base() {
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.5) 0 0px 2px) {
appearance: none;
background: $bg;
border: none;
color: $fg;
border-radius: $controlCr;
box-shadow: inset $shdw;
outline: none;
&:focus {
@ -126,15 +99,6 @@
}
}
@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";
@ -64,7 +64,7 @@
@import "../styles/items/item";
@import "../styles/mobile/item";
@import "../styles/table";
//@import "../styles/notebook/notebook";
@import "../styles/notebook/notebook";
//
//!********************************* TO BE MOVED *!
@import "../styles/autoflow";
@ -76,4 +76,3 @@
//@import "../styles/app-start";
@import "../styles/conductor/time-conductor-snow";
//@import "../styles/notebook/notebook-snow";

View File

@ -1,385 +0,0 @@
/*********************************************** NOTEBOOK */
@import "sass-base.scss";
.c-notebook {
//@include test(orange);
display: flex;
flex-direction: column;
overflow: hidden;
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
> [class*="__"] + [class*="__"] {
margin-top: $interiorMargin;
}
&__head,
&__controls,
&__drag-area,
&__entries {
display: flex;
flex-wrap: nowrap;
}
&__head,
&__drag-area,
&__controls {
flex: 0 0 auto;
}
&__head {
[class*="__"] + [class*="__"] {
margin-left: $interiorMargin;
}
}
&__search {
flex: 1 1 auto;
}
&__drag-area {
background: rgba($colorKey, 0.1);
border: 1px dashed rgba($colorKey, 0.7);
border-radius: $controlCr;
color: rgba($colorBodyFg, 0.7);
padding: 10px;
cursor: pointer;
&:before {
margin-right: 7px !important;
}
[class*="__label"] {
font-style: italic;
@include ellipsize();
}
&:hover {
background: rgba($colorKey, 0.2);
color: $colorBodyFg;
}
&.drag-active,
&.is-active {
// Not currently working
border-color: $colorKey;
}
body.mobile & {
display: none;
}
}
&__entries {
flex-direction: column;
flex: 1 1 auto;
padding-right: $interiorMarginSm;
overflow-x: hidden;
overflow-y: scroll;
[class*="__entry"] + [class*="__entry"] {
margin-top: $interiorMarginSm;
}
}
}
/****************************** ENTRIES */
.c-ne {
// A Notebook entry
$p: $interiorMarginSm;
@include discreteItem();
display: flex;
//flex-wrap: wrap;
padding: $interiorMarginSm $interiorMarginSm $interiorMarginSm $interiorMargin;
&__time,
&__text,
&__local-controls {
padding-top: $p;
padding-bottom: $p;
}
&__time,
&__embed__time {
opacity: 0.7;
}
&__time-and-content {
display: flex;
flex: 1 1 auto;
flex-wrap: wrap;
}
&__time {
flex: 0 1 auto;
min-width: 130px;
margin-right: $interiorMarginLg;
* {
white-space: nowrap;
}
}
&__content {
flex: 1 1 auto;
> [class*="__"] + [class*="__"] {
margin-top: $interiorMarginSm;
}
}
&__text {
min-height: 24px; // Needed in Firefox when field is blank
white-space: pre-wrap;
&.is-blank-notebook-entry {
&:not(:focus):before {
content: 'Blank entry';
font-style: italic;
opacity: 0.5;
}
}
}
&__embeds {
flex-wrap: wrap;
> [class*="__embed"] {
margin: 0 $interiorMarginSm $interiorMarginSm 0;
}
}
}
/****************************** EMBEDS */
@mixin snapThumb() {
// LEGACY: TODO: refactor when .snap-thumb in New Entry dialog is refactored
$d: 50px;
border: 1px solid $colorInteriorBorder;
cursor: pointer;
width: $d;
height: $d;
border-radius: 5px;
overflow: hidden;
img {
height: 100%;
width: 100%;
}
}
.snap-thumb {
// LEGACY,
@include snapThumb();
}
.c-ne__embed {
@include discreteItemInnerElem();
display: inline-flex;
flex: 0 0 auto;
padding: $interiorMargin;
[class*="__"] + [class*="__"] {
margin-left: $interiorMargin;
}
&__info {
display: flex;
flex-direction: column;
a {
color: $colorKey;
}
}
&__name,
&__link {
// Holds __link and __context-available
display: flex;
align-items: center;
}
&__link {
&:before {
display: block;
font-size: 0.85em;
margin-right: $interiorMarginSm;
}
}
&__context-available {
font-size: 0.7em;
margin-left: $interiorMarginSm;
}
&__snap-thumb {
@include snapThumb();
}
}
/****************************** SNAPSHOTTING */
// LEGACY: TODO: refactor these names
.t-contents,
.snap-annotation {
overflow: hidden;
}
.s-status-taking-snapshot,
.overlay.snapshot {
// Handle overflow-y issues with tables and html2canvas
.l-sticky-headers .l-tabular-body { overflow: auto; }
}
/****************************** PAINTERRO OVERRIDES */
.annotation-dialog .abs.editor {
border-radius: 0;
}
#snap-annotation {
$m: $interiorMargin;
display: flex;
flex-direction: column;
position: absolute;
top: $m; right: 0; bottom: $m; left: 0; // LEGACY, deal with .editor border-radius clipping stuff
}
#snap-annotation-wrapper,
#snap-annotation-bar {
position: relative;
top: auto; right: auto; bottom: auto; left: auto;
}
#snap-annotation-wrapper {
background: rgba($colorBodyFg, 0.1);
border: 1px solid $colorInteriorBorder;
order: 2;
flex: 10 0 auto;
}
#snap-annotation-bar {
// Holds tool buttons, color selectors, etc.
$h: 22px;
$fs: 0.8rem;
order: 1;
flex: 0 0 auto;
height: auto;
background-color: transparent !important;
margin-bottom: $interiorMargin;
> div > span {
display: flex;
align-items: center;
font-size: $fs;
}
> div,
> div > span,
.ptro-icon-btn,
.ptro-named-btn,
.ptro-color-btn,
.ptro-bordered-btn,
.ptro-tool-ctl-name,
.ptro-color-btn,
.tool-controls,
.ptro-input {
// Lot of resets for crappy CSS in Painterro
&:first-child {
margin-left: 0 !important;
}
display: inline-block;
font-family: inherit;
font-size: $fs !important;
height: $h !important;
margin: 0 0 0 5px;
position: relative;
width: auto !important;
line-height: $h !important;
top: auto;
right: auto;
bottom: auto;
left: auto;
vertical-align: top;
}
.ptro-tool-ctl-name {
border-radius: 0;
background: none;
top: auto;
font-family: inherit;
padding: 0;
}
.ptro-color-btn {
width: $h !important;
}
.ptro-color-control,
.ptro-icon-btn,
.ptro-named-btn {
// Buttons in toolbar. Why the f* they're named like this is a mystery
background-color: $colorBtnBg;
color: $colorBtnFg;
padding: 0 $interiorMargin;
&:hover {
background: $colorBtnBgHov;
color: $colorBtnFgHov;
}
i {
display: contents;
font-size: $fs * 1.2;
line-height: inherit;
}
}
.ptro-color-active-control {
background: $colorBtnMajorBg !important;
color: $colorBtnMajorFg !important;
}
.ptro-info,
.ptro-btn-color-checkers-bar,
*[title="Font name"],
*[title="Stroke color"],
*[title="Stroke width"],
*[data-id="fontName"],
*[data-id="fontStrokeSize"],
*[data-id="stroke"] {
display: none;
}
}
/****************************** MOBILE */
body.mobile {
.c-notebook__drag-area { display: none; }
.c-notebook__entry {
[class*="local-controls"] {
display: none;
}
}
&.phone.portrait {
.c-notebook__head,
.c-notebook__entry {
flex-direction: column;
> [class*="__"] + [class*="__"] {
margin-left: 0;
margin-top: $interiorMargin;
}
}
.c-notebook__entry {
[class*="text"] {
min-height: 0;
padding: 0;
pointer-events: none;
}
}
}
}

View File

@ -1,29 +0,0 @@
<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

@ -1,102 +0,0 @@
<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, index) in items"
:key="index"
:class="item.class"
:title="item.title"
@mouseover="showItemDescription(item)">
{{ item.name }}
</li>
</ul>
</div>
<div class="c-super-menu__item-description">
<div :class="['l-item-description__icon', 'bg-' + selectedMenuItem.class]"></div>
<div class="l-item-description__name">{{selectedMenuItem.name}}</div>
<div class="l-item-description__description">{{selectedMenuItem.title}}</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 {
inject: ['openmct'],
props: {
showCreateMenu: {
type: Boolean,
default: false
}
},
methods: {
toggleCreateMenu: function () {
this.showCreateMenu = !this.showCreateMenu;
},
showItemDescription: function (menuItem) {
this.selectedMenuItem = menuItem;
}
},
data: function() {
let items = [];
this.openmct.types.listKeys().forEach(key => {
let menuItem = openmct.types.get(key).definition;
if (menuItem.creatable) {
let menuItemTemplate = {
name: menuItem.name,
class: menuItem.cssClass,
title: menuItem.description
};
items.push(menuItemTemplate);
}
});
return {
items: items,
selectedMenuItem: {}
}
}
}
</script>

View File

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

View File

@ -1,12 +1,9 @@
<template>
<div class="c-search"
:class="{ 'is-active': active === true }">
<input class="c-search__input"
tabindex="10000"
type="search"
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"/>
<input class="c-search__input" type="search"
v-bind:value="searchInput"
@input="handleInput($event)"/>
<a class="c-search__clear-input icon-x-in-circle"
v-on:click="clearInput"></a>
</div>
@ -31,7 +28,7 @@
flex: 0 0 auto;
opacity: 0.5;
overflow: hidden;
padding: 2px 0; // Prevents clipping
padding: 2px; // Prevents clipping
transition: width 250ms ease;
width: 1em;
}
@ -50,7 +47,7 @@
&__input {
background: none !important;
box-shadow: none !important; // !important needed to override default for [input]
flex: 1 1 auto;
flex: 0 1 100%;
padding-left: 2px !important;
padding-right: 2px !important;
min-width: 10px; // Must be set to allow input to collapse below browser min
@ -74,36 +71,26 @@
</style>
<script>
/* Emits input and clear events */
export default {
inheritAttrs: false,
props: {
value: String
},
computed: {
inputListeners: function () {
let vm = this;
return Object.assign({},
this.$listeners,
{
input: function (event) {
vm.$emit('input', event.target.value);
vm.active = (event.target.value.length > 0);
}
}
)
}
},
data: function() {
return {
searchInput: '',
active: false
}
},
methods: {
handleInput(e) {
// Grab input as the user types it
// and set 'active' based on input length > 0
this.searchInput = e.target.value;
this.active = (this.searchInput.length > 0);
},
clearInput() {
// Clear the user's input and set 'active' to false
this.value = '';
this.$emit('clear','');
this.searchInput = '';
this.active = false;
}
}

View File

@ -0,0 +1,133 @@
<template>
<div class="c-splitter" :class="{
'c-splitter-vertical' : align === 'vertical',
'c-splitter-horizontal' : align === 'horizontal',
'c-splitter-collapse-left' : collapse === 'to-left',
'c-splitter-collapse-right' : collapse === 'to-right',
}">
<a class="c-splitter__btn"></a>
</div>
</template>
<style lang="scss">
@import "~styles/constants";
@import "~styles/constants-snow";
@import "~styles/mixins";
@import "~styles/glyphs";
$c: #06f;
$size: $splitterHandleD;
$margin: 0px;
$hitMargin: 4px;
.c-splitter {
background: $colorSplitterBg;
transition: $transOut;
&:before {
// Bigger hit area
//@include test();
content: '';
display: block;
position: absolute;
z-index: 1;
}
&:active, &:hover {
transition: $transIn;
}
&:active {
background: $colorSplitterActive;
}
&:hover {
background: $colorSplitterHover;
}
&-vertical {
cursor: col-resize;
width: $size;
margin: 0 $margin;
&:before {
top: 0;
right: $hitMargin * -1;
bottom: 0;
left: $hitMargin * -1;
}
}
&-horizontal {
cursor: row-resize;
height: $size;
margin: $margin 0;
&:before {
top: $hitMargin * -1;
right: 0;
bottom: $hitMargin * -1;
left: 0;
}
}
}
.c-splitter__btn {
// Collapse button
background: $colorSplitterBg;
display: none; // Only display if splitter is collapsible, see below
width: $splitterD;
height: 40px;
transition: $transOut;
&:active, &:hover {
transition: $transIn;
}
&:hover {
background: $colorSplitterHover;
}
&:active {
background: $colorSplitterActive;
}
[class*="collapse"] & {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
z-index: 3;
&:before {
color: $colorSplitterFg;
display: block;
font-size: 0.8em;
font-family: symbolsfont;
}
}
[class*="collapse-left"] & {
border-bottom-left-radius: $controlCr;
right: 0;
&:before {
content: $glyph-icon-arrow-left;
}
}
[class*="collapse-right"] & {
border-bottom-right-radius: $controlCr;
left: 0;
&:before {
content: $glyph-icon-arrow-right;
}
}
}
</style>
<script>
export default {
props: {
align: String,
collapse: String
}
}
</script>

View File

@ -1,12 +1,43 @@
<template>
<span class="c-disclosure-triangle"
<span class="c-view-control"
:class="{
'c-disclosure-triangle--expanded' : expanded,
'c-view-control--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

@ -1,33 +0,0 @@
<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

@ -1,167 +0,0 @@
<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

@ -1,32 +0,0 @@
<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

@ -1,42 +0,0 @@
<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

@ -1,96 +0,0 @@
<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

@ -1,177 +0,0 @@
<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"
:class="type.cssClass">
<span
class="l-browse-bar__object-name c-input-inline"
v-on:blur="updateName"
contenteditable>
{{ domainObject.name }}
</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"
v-if="views.length > 1">
<div class="c-menu-button"
:class="currentView.cssClass"
title="Switch view type"
@click="toggleViewMenu">
<span class="c-button__label">
{{ currentView.name }}
</span>
</div>
<div class="c-menu" v-show="showViewMenu">
<ul>
<li v-for="(view, index) in views"
@click="setView(view)"
:key="index"
:class="view.cssClass"
:title="view.name">
{{ view.name }}
</li>
</ul>
</div>
</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>
export default {
inject: ['openmct'],
methods: {
toggleViewMenu: function (event) {
event.stopPropagation();
this.showViewMenu = !this.showViewMenu;
},
updateName: function (event) {
// TODO: handle isssues with contenteditable text escaping.
if (event.target.innerText !== this.domainObject.name) {
this.openmct.objects.mutate(this.domainObject, 'name', event.target.innerText);
}
},
setView: function (view) {
this.viewKey = view.key;
this.openmct.router.updateParams({
view: this.viewKey
});
}
},
data: function () {
return {
showViewMenu: false,
domainObject: {},
viewKey: undefined
}
},
computed: {
currentView() {
return this.views.filter(v => v.key === this.viewKey)[0] || {};
},
views() {
return this
.openmct
.objectViews
.get(this.domainObject)
.map((p) => {
return {
key: p.key,
cssClass: p.cssClass,
name: p.name
};
});
},
type() {
let objectType = this.openmct.types.get(this.domainObject.type);
if (!objectType) {
return {}
}
return objectType.definition;
}
},
mounted: function () {
document.addEventListener('click', () => {
if (this.showViewMenu) {
this.showViewMenu = false;
}
});
}
}
</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

@ -1,15 +0,0 @@
<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,12 +1,8 @@
<template>
<div class="l-shell">
<div class="l-shell__head">
<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>
[ Create Button ]
[ App Logo ]
</div>
<multipane class="l-shell__main"
type="horizontal">
@ -18,25 +14,17 @@
<search class="c-search--major" ref="shell-search"></search>
</div>
<div class="l-shell__tree">
<mct-tree></mct-tree>
<mct-tree :nodes="treeRoots"></mct-tree>
</div>
</pane>
<pane class="l-shell__pane-main">
<browse-bar class="l-shell__main-view-browse-bar"
ref="browseBar">
</browse-bar>
<object-view class="l-shell__main-container"
ref="browseObject">
</object-view>
<mct-template template-key="conductor"
class="l-shell__time-conductor">
</mct-template>
<div class="l-shell__main-container" ref="mainContainer"></div>
</pane>
<pane class="l-shell__pane-inspector l-pane--holds-multipane"
handle="before"
label="Inspect"
collapsable>
<Inspector ref="inspector"></Inspector>
<MctInspector ref="inspector"></MctInspector>
</pane>
</multipane>
<div class="l-shell__status">
@ -84,11 +72,10 @@
}
}
&__pane-main,
&__pane-tree {
> .l-pane__contents {
display: flex;
flex-flow: column nowrap;
&__head,
&__pane-inspector {
body.mobile & {
display: none;
}
}
@ -111,53 +98,13 @@
}
}
&__head,
&__pane-inspector {
body.mobile & {
display: none;
}
}
&__head,
&__status {
flex: 0 0 auto;
display: flex;
}
/******************************* HEAD */
&__main-view-browse-bar {
flex: 0 0 auto;
}
&__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
flex: 1 1 auto;
font-size: 16px; // TEMP FOR LEGACY STYLING
overflow: auto;
//font-size: 16px; // TEMP FOR LEGACY STYLING
position: absolute;
top: $interiorMargin; right: $interiorMarginLg; bottom: $interiorMargin; left: $interiorMarginLg;
}
&__tree {
@ -168,12 +115,24 @@
&__time-conductor {
border-top: 1px solid $colorInteriorBorder;
flex: 0 0 auto;
padding: $interiorMargin;
min-height: 50px;
padding: $interiorMarginLg;
}
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%;
@ -191,31 +150,23 @@
</style>
<script>
import Inspector from '../inspector/Inspector.vue';
import MctInspector from './MctInspector.vue';
import MctMain from './MctMain.vue';
import MctStatus from './MctStatus.vue';
import MctTree from './mct-tree.vue';
import ObjectView from './ObjectView.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 BrowseBar from './BrowseBar.vue';
export default {
components: {
Inspector,
MctInspector,
MctMain,
MctStatus,
MctTree,
ObjectView,
'mct-template': MctTemplate,
ContextMenu,
CreateButton,
search,
multipane,
pane,
BrowseBar
pane
}
}
</script>

View File

@ -0,0 +1,202 @@
<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

@ -0,0 +1,21 @@
<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

@ -1,74 +0,0 @@
<template>
</template>
<style lang="scss">
.l-object-view {
display: contents;
}
</style>
<script>
import _ from "lodash"
export default {
inject: ["openmct"],
props: {
view: String,
object: Object
},
destroyed() {
this.clear();
},
watch: {
view(newView, oldView) {
this.viewKey = newView;
this.debounceUpdateView();
},
object(newObject, oldObject) {
this.currentObject = newObject;
this.debounceUpdateView();
}
},
created() {
this.debounceUpdateView = _.debounce(this.updateView, 10);
},
mounted() {
this.updateView();
},
methods: {
clear() {
if (this.currentView) {
this.currentView.destroy();
this.$el.innerHTML = '';
}
delete this.viewContainer;
delete this.currentView;
},
updateView() {
this.clear();
if (!this.currentObject) {
return;
}
this.viewContainer = document.createElement('div');
this.viewContainer.classList.add('l-object-view');
this.$el.append(this.viewContainer);
let provider = this.openmct.objectViews.getByProviderKey(this.viewKey);
if (!provider) {
provider = this.openmct.objectViews.get(this.currentObject)[0];
if (!provider) {
return;
}
}
this.currentView = provider.view(this.currentObject);
this.currentView.show(this.viewContainer);
},
show(object, viewKey) {
this.currentObject = object;
this.viewKey = viewKey;
this.updateView();
}
}
}
</script>

View File

@ -10,8 +10,9 @@
<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%;
@ -69,8 +70,7 @@
&:before {
// Type icon
display: block;
flex: 0 0 auto;
display: inline-block;
font-size: 1.3em;
margin-right: $interiorMarginSm;
}

View File

@ -1,36 +0,0 @@
<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();
templateLinker.link(
this.$scope,
angular.element(this.$el),
templateMap[this.templateKey]
);
},
destroyed() {
this.$scope.$destroy();
}
}
</script>

View File

@ -101,7 +101,7 @@ class ApplicationRouter extends EventEmitter {
doPathChange(newPath, oldPath, newLocation) {
let route = this.routes.filter(r => r.matcher.test(newPath))[0];
if (route) {
route.callback(newPath, route.matcher.exec(newPath), this.currentLocation.params);
route.callback(newPath, route.matcher.exec(newPath));
}
this.emit('change:path', newPath, oldPath);
}

View File

@ -1,80 +0,0 @@
define([
], function (
) {
return function install(openmct) {
let navigateCall = 0;
let browseObject;
function viewObject(object, viewProvider) {
openmct.layout.$refs.browseObject.show(object, viewProvider.key);
openmct.layout.$refs.browseBar.domainObject = object;
openmct.layout.$refs.browseBar.viewKey = viewProvider.key;
};
function navigateToPath(path, currentViewKey) {
navigateCall++;
let currentNavigation = navigateCall;
if (!Array.isArray(path)) {
path = path.split('/');
}
let keyString = path[path.length - 1];
// TODO: retain complete path in navigation.
return openmct.objects.get(keyString)
.then((object) => {
if (currentNavigation !== navigateCall) {
return; // Prevent race.
}
openmct.layout.$refs.browseBar.domainObject = object;
browseObject = object;
if (!object) {
openmct.layout.$refs.browseObject.clear();
return;
}
let currentProvider = openmct
.objectViews
.getByProviderKey(currentViewKey)
if (currentProvider && currentProvider.canView(object)) {
viewObject(object, currentProvider);
return;
}
let defaultProvider = openmct.objectViews.get(object)[0];
if (defaultProvider) {
openmct.router.updateParams({
view: defaultProvider.key
});
} else {
openmct.router.updateParams({
view: undefined
});
openmct.layout.$refs.browseObject.clear();
}
});
}
openmct.router.route(/^\/browse\/(.*)$/, (path, results, params) => {
let navigatePath = results[1];
if (!navigatePath) {
navigatePath = 'mine';
}
navigateToPath(navigatePath, params.view);
});
openmct.router.on('change:params', function (newParams, oldParams, changed) {
if (changed.view && browseObject) {
let provider = openmct
.objectViews
.getByProviderKey(changed.view);
viewObject(browseObject, provider);
}
});
}
});