Compare commits

..

12 Commits

Author SHA1 Message Date
Charles Hacskaylo
889350623a [Front-end] min-width added to .s-inline-edit
Fixes #1679
2017-09-07 16:01:52 -07:00
Charles Hacskaylo
aac1f02bd6 [Front-end] Styling for contenteditable span
Fixes #1679
WIP: refactor input-base and nice-input mixins;
styling for span[contenteditable].s-status-editing in _controls.scss;
removed s-filter class;
TODO: figure out baseline text shift on click
2017-09-07 15:54:32 -07:00
Charles Hacskaylo
e759761a04 Merge branch 'inline-edit-issue-1679' of https://github.com/nasa/openmct into inline-edit-issue-1679-styling 2017-09-07 14:27:11 -07:00
Charles Hacskaylo
490567c8e8 [Front-end] Add span contenteditable to input styling
Fixes #1679
2017-09-07 14:26:57 -07:00
Pegah Sarram
ede5b85c93 Changed input to a span with conteneditable flag on. 2017-09-07 14:06:57 -07:00
Pegah Sarram
82f32a57f4 Merge remote-tracking branch 'refs/remotes/origin/inline-edit-issue-1679' into inline-edit-issue-1679 2017-09-06 11:18:42 -07:00
Pegah Sarram
0dd6a4eb44 Fixed a lint error. 2017-09-06 10:40:16 -07:00
Pegah Sarram
4c03a3b31d Fixed checkstyle errors 2017-09-06 10:40:16 -07:00
Pegah Sarram
aaeffb16e3 Added tests. Also, added a check to mutate the name if it's different than the model. 2017-09-06 10:40:16 -07:00
Pegah Sarram
41f6047c96 Changed the title-label span to an input to support inline edit and implemented a controller to handle updaing the name. 2017-09-06 10:40:16 -07:00
Pegah Sarram
c35cdf176f Added tests. Also, added a check to mutate the name if it's different than the model. 2017-09-05 14:00:29 -07:00
Pegah Sarram
05227286c4 Changed the title-label span to an input to support inline edit and implemented a controller to handle updaing the name. 2017-08-29 15:05:40 -07:00
75 changed files with 703 additions and 1252 deletions

View File

@@ -4,6 +4,12 @@ deployment:
commands:
- npm install canvas nomnoml
- ./build-docs.sh
- git fetch --unshallow
- git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master
openmct-demo:
branch: live_demo
heroku:
appname: openmct-demo
openmctweb-staging-deux:
branch: mobile
heroku:

View File

@@ -78,8 +78,8 @@ define([
return this.workerInterface.request(workerRequest);
};
GeneratorProvider.prototype.subscribe = function (domainObject, callback) {
var workerRequest = this.makeWorkerRequest(domainObject, {});
GeneratorProvider.prototype.subscribe = function (domainObject, callback, request) {
var workerRequest = this.makeWorkerRequest(domainObject, request);
return this.workerInterface.subscribe(workerRequest, callback);
};

View File

@@ -127,8 +127,7 @@
{ 'meaning': 'Timer object', 'cssClass': 'icon-timer', 'cssContent': 'e1127', 'htmlEntity': '&#xe1127' },
{ 'meaning': 'Data Topic', 'cssClass': 'icon-topic', 'cssContent': 'e1128', 'htmlEntity': '&#xe1128' },
{ 'meaning': 'Fixed Position object', 'cssClass': 'icon-box-with-dashed-lines', 'cssContent': 'e1129', 'htmlEntity': '&#xe1129' },
{ 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&#xe1130' },
{ 'meaning': 'Notebook object', 'cssClass': 'icon-notebook', 'cssContent': 'e1131', 'htmlEntity': '&#xe1131' }
{ 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&#xe1130' }
];
"></div>

View File

@@ -46,22 +46,9 @@ var gulp = require('gulp'),
name: 'bower_components/almond/almond.js',
include: paths.main.replace('.js', ''),
wrap: {
start: (function () {
var buildVariables = {
version: project.version,
timestamp: moment.utc(Date.now()).format(),
revision: fs.existsSync('.git') ? git.long() : 'Unknown',
branch: fs.existsSync('.git') ? git.branch() : 'Unknown'
};
return fs.readFileSync("src/start.frag", 'utf-8')
.replace(/@@(\w+)/g, function (match, key) {
return buildVariables[key];
});;
}()),
startFile: "src/start.frag",
endFile: "src/end.frag"
},
optimize: 'uglify2',
uglify2: { output: { comments: /@preserve/ } },
mainConfigFile: paths.main,
wrapShim: true
},
@@ -71,6 +58,14 @@ var gulp = require('gulp'),
},
sass: {
sourceComments: true
},
replace: {
variables: {
version: project.version,
timestamp: moment.utc(Date.now()).format(),
revision: fs.existsSync('.git') ? git.long() : 'Unknown',
branch: fs.existsSync('.git') ? git.branch() : 'Unknown'
}
}
};
@@ -81,11 +76,16 @@ if (process.env.NODE_ENV === 'development') {
gulp.task('scripts', function () {
var requirejsOptimize = require('gulp-requirejs-optimize');
var replace = require('gulp-replace-task');
var header = require('gulp-header');
var comment = fs.readFileSync('src/about.frag');
return gulp.src(paths.main)
.pipe(sourcemaps.init())
.pipe(requirejsOptimize(options.requirejsOptimize))
.pipe(sourcemaps.write('.'))
.pipe(replace(options.replace))
.pipe(header(comment, options.replace.variables))
.pipe(gulp.dest(paths.dist));
});

View File

@@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global requirejs,BUILD_CONSTANTS*/
/*global requirejs*/
requirejs.config({
"paths": {
@@ -91,17 +91,12 @@ requirejs.config({
define([
'./platform/framework/src/Main',
'./src/defaultRegistry',
'./src/MCT',
'./src/plugins/buildInfo/plugin'
], function (Main, defaultRegistry, MCT, buildInfo) {
'./src/MCT'
], function (Main, defaultRegistry, MCT) {
var openmct = new MCT();
openmct.legacyRegistry = defaultRegistry;
if (typeof BUILD_CONSTANTS !== 'undefined') {
openmct.install(buildInfo(BUILD_CONSTANTS));
}
openmct.on('start', function () {
return new Main().run(defaultRegistry);
});

View File

@@ -22,10 +22,12 @@
"git-rev-sync": "^1.4.0",
"glob": ">= 3.0.0",
"gulp": "^3.9.1",
"gulp-header": "^1.8.8",
"gulp-jscs": "^3.0.2",
"gulp-jshint": "^2.0.0",
"gulp-jshint-html-reporter": "^0.1.3",
"gulp-rename": "^1.2.2",
"gulp-replace-task": "^0.11.0",
"gulp-requirejs-optimize": "^0.3.1",
"gulp-sass": "^2.2.0",
"gulp-sourcemaps": "^1.6.0",

View File

@@ -37,7 +37,6 @@ define([
"text!./res/templates/browse-object.html",
"text!./res/templates/items/grid-item.html",
"text!./res/templates/browse/object-header.html",
"text!./res/templates/browse/object-header-frame.html",
"text!./res/templates/menu-arrow.html",
"text!./res/templates/back-arrow.html",
"text!./res/templates/items/items.html",
@@ -61,7 +60,6 @@ define([
browseObjectTemplate,
gridItemTemplate,
objectHeaderTemplate,
objectHeaderFrameTemplate,
menuArrowTemplate,
backArrowTemplate,
itemsTemplate,
@@ -184,13 +182,6 @@ define([
"type"
]
},
{
"key": "object-header-frame",
"template": objectHeaderFrameTemplate,
"uses": [
"type"
]
},
{
"key": "menu-arrow",
"template": menuArrowTemplate,

View File

@@ -1,31 +0,0 @@
<!--
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.
-->
<span class='type-icon flex-elem {{type.getCssClass()}}'></span>
<span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller">
<span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
<span class='title-label flex-elem holder flex-can-shrink s-input-inline'>{{model.name}}</span>
<span class='t-object-alert t-alert-unsynced flex-elem holder' title='This object is not currently displaying real-time data'></span>
<mct-representation
key="'menu-arrow'"
mct-object='domainObject'
class="flex-elem context-available-w"></mct-representation>
</span>

View File

@@ -22,8 +22,9 @@
<span class='type-icon flex-elem {{type.getCssClass()}}'></span>
<span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller">
<span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
<span ng-attr-contenteditable="{{ controller.editable ? true : undefined }}"
class='title-label flex-elem holder flex-can-shrink s-input-inline'
<span contenteditable="true"
class='title-label flex-elem holder flex-can-shrink s-inline-edit'
ng-class="{'s-status-editing': inlineEdit}"
ng-click="controller.edit()"
ng-blur="controller.updateName($event)"
ng-keypress="controller.updateName($event)">{{model.name}}</span>

View File

@@ -21,72 +21,56 @@
*****************************************************************************/
define(
[],
function () {
[],
function () {
/**
* Controller to provide the ability to inline edit an object name.
*
* @constructor
* @memberof platform/commonUI/browse
*/
function ObjectHeaderController($scope) {
this.$scope = $scope;
this.domainObject = $scope.domainObject;
this.editable = this.allowEdit();
}
/**
* Controller to provide the ability to inline edit an object name.
*
* @constructor
* @memberof platform/commonUI/browse
*/
function ObjectHeaderController($scope) {
this.$scope = $scope;
this.$scope.inlineEdit = false;
}
/**
* Updates the object name on blur and enter keypress events.
*
* @param event the mouse event
*/
ObjectHeaderController.prototype.updateName = function (event) {
if (!event || !event.currentTarget) {
return;
}
/**
* Handler for the blur and enter/return key press events
* to update the object name.
*
* @param event the mouse event
*/
ObjectHeaderController.prototype.updateName = function (event) {
if (event && (event.type === 'blur' || event.which === 13)) {
var name = event.currentTarget.innerHTML;
if (event.type === 'blur') {
this.updateModel(event);
} else if (event.which === 13) {
this.updateModel(event);
event.currentTarget.blur();
window.getSelection().removeAllRanges();
}
};
if (name.length === 0) {
name = "Unnamed " + this.$scope.domainObject.getCapability("type").typeDef.name;
event.currentTarget.innerHTML = name;
}
/**
* Updates the model.
*
* @param event the mouse event
* @param private
*/
ObjectHeaderController.prototype.updateModel = function (event) {
var name = event.currentTarget.textContent.replace(/\n/g, ' ');
if (name !== this.$scope.domainObject.model.name) {
this.$scope.domainObject.getCapability('mutation').mutate(function (model) {
model.name = name;
});
}
if (name.length === 0) {
name = "Unnamed " + this.domainObject.getCapability("type").typeDef.name;
event.currentTarget.textContent = name;
}
this.$scope.inlineEdit = false;
if (name !== this.domainObject.getModel().name) {
this.domainObject.getCapability('mutation').mutate(function (model) {
model.name = name;
});
}
};
if (event.which === 13) {
event.currentTarget.blur();
}
}
};
/**
* Checks if the domain object is editable.
*
* @private
* @return true if object is editable
*/
ObjectHeaderController.prototype.allowEdit = function () {
var type = this.domainObject && this.domainObject.getCapability('type');
return !!(type && type.hasFeature('creation'));
};
/**
* Handler for the click event to mark the filed as inline edit.
*/
ObjectHeaderController.prototype.edit = function () {
this.$scope.inlineEdit = true;
};
return ObjectHeaderController;
}
return ObjectHeaderController;
}
);

View File

@@ -21,117 +21,74 @@
*****************************************************************************/
define(
["../src/ObjectHeaderController"],
function (ObjectHeaderController) {
["../src/ObjectHeaderController"],
function (ObjectHeaderController) {
describe("The object header controller", function () {
var mockScope,
mockDomainObject,
mockCapabilities,
mockMutationCapability,
mockTypeCapability,
mockEvent,
mockCurrentTarget,
model,
controller;
describe("The object header controller", function () {
var mockScope,
mockDomainObject,
mockMutationCapability,
mockEvent,
mockCurrentTarget,
controller;
beforeEach(function () {
mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]);
mockTypeCapability = jasmine.createSpyObj("type", ["typeDef", "hasFeature"]);
mockTypeCapability.typeDef = { name: ""};
mockTypeCapability.hasFeature.andCallFake(function (feature) {
return feature === 'creation';
});
function getModel() {
return {
name: 'Test name'
};
}
mockCapabilities = {
mutation: mockMutationCapability,
type: mockTypeCapability
};
beforeEach(function () {
mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]);
model = {
name: "Test name"
};
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "getModel"]);
mockDomainObject.getModel.andReturn(model);
mockDomainObject.getCapability.andCallFake(function (key) {
return mockCapabilities[key];
});
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "model"]);
mockDomainObject.model = getModel();
mockDomainObject.getCapability.andReturn(mockMutationCapability);
mockScope = {
domainObject: mockDomainObject
};
mockScope = jasmine.createSpyObj("$scope", ["name"]);
mockScope.domainObject = mockDomainObject;
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "textContent"]);
mockCurrentTarget.blur.andReturn(mockCurrentTarget);
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur"]);
mockCurrentTarget.blur.andReturn({ blur: function () {} });
mockEvent = {
which: {},
type: {},
currentTarget: mockCurrentTarget
};
mockEvent = jasmine.createSpyObj('event', ["which"]);
mockEvent.currentTarget = mockCurrentTarget;
controller = new ObjectHeaderController(mockScope);
});
controller = new ObjectHeaderController(mockScope);
});
it("updates the model with new name on blur", function () {
mockEvent.type = "blur";
mockCurrentTarget.textContent = "New name";
controller.updateName(mockEvent);
it("updates the model with new name", function () {
mockScope.name = 'New name';
controller.updateName();
expect(mockMutationCapability.mutate).toHaveBeenCalled();
});
expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
});
it("updates the model with a default for blank names", function () {
mockEvent.type = "blur";
mockCurrentTarget.textContent = "";
controller.updateName(mockEvent);
it("does not update the model for blank names", function () {
mockScope.name = "";
controller.updateName();
expect(mockCurrentTarget.textContent.length).not.toEqual(0);
expect(mockMutationCapability.mutate).toHaveBeenCalled();
});
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
});
it("does not update the model if the same name", function () {
mockEvent.type = "blur";
mockCurrentTarget.textContent = mockDomainObject.getModel().name;
controller.updateName(mockEvent);
it("updates the model on enter keypress event only", function () {
mockScope.name = 'New name';
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
});
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
it("updates the model on enter keypress event only", function () {
mockCurrentTarget.textContent = "New name";
controller.updateName(mockEvent);
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
expect(mockMutationCapability.mutate).toHaveBeenCalled();
});
mockEvent.which = 13;
controller.updateName(mockEvent);
it("blurs the field on enter key press", function () {
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
mockMutationCapability.mutate.mostRecentCall.args[0](model);
expect(mockDomainObject.getModel().name).toBe("New name");
});
it("blurs the field on enter key press", function () {
mockCurrentTarget.textContent = "New name";
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
});
it("allows editting name when object is creatable", function () {
expect(controller.allowEdit()).toBe(true);
});
it("disallows editting name when object is non-creatable", function () {
mockTypeCapability.hasFeature.andReturn(false);
expect(controller.allowEdit()).toBe(false);
});
});
}
expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
});
});
}
);

View File

@@ -23,7 +23,7 @@
<div class="s-menu-button major create-button" ng-click="createController.toggle()">
<span class="title-label">Create</span>
</div>
<div class="menu super-menu l-create-menu" ng-show="createController.isActive()">
<div class="menu super-menu" ng-show="createController.isActive()">
<mct-representation mct-object="domainObject" key="'create-menu'">
</mct-representation>
</div>

View File

@@ -19,8 +19,8 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div class="w-menu" ng-controller="CreateMenuController">
<div class="col menu-items">
<div class="contents" ng-controller="CreateMenuController">
<div class="pane left menu-items">
<ul>
<li ng-repeat="createAction in createActions" ng-click="createAction.perform()">
<a ng-mouseover="representation.activeMetadata = createAction.getMetadata()"
@@ -31,15 +31,13 @@
</li>
</ul>
</div>
<div class="col menu-item-description">
<div class="pane right menu-item-description">
<div class="desc-area icon {{ representation.activeMetadata.cssClass }}"></div>
<div class="w-title-desc">
<div class="desc-area title">
{{representation.activeMetadata.name}}
</div>
<div class="desc-area description">
{{representation.activeMetadata.description}}
</div>
<div class="desc-area title">
{{representation.activeMetadata.name}}
</div>
<div class="desc-area description">
{{representation.activeMetadata.description}}
</div>
</div>
</div>

View File

@@ -2,7 +2,7 @@
"metadata": {
"name": "openmct-symbols-16px",
"lastOpened": 0,
"created": 1506973656040
"created": 1502487054429
},
"iconSets": [
{
@@ -636,29 +636,13 @@
"code": 921670,
"tempChar": ""
},
{
"order": 138,
"id": 115,
"name": "icon-import",
"prevSize": 24,
"code": 921671,
"tempChar": ""
},
{
"order": 136,
"id": 116,
"name": "icon-export",
"prevSize": 24,
"code": 921672,
"tempChar": ""
},
{
"order": 37,
"prevSize": 24,
"name": "icon-activity",
"id": 32,
"code": 921856,
"tempChar": ""
"tempChar": ""
},
{
"order": 36,
@@ -666,7 +650,7 @@
"name": "icon-activity-mode",
"id": 31,
"code": 921857,
"tempChar": ""
"tempChar": ""
},
{
"order": 52,
@@ -674,7 +658,7 @@
"name": "icon-autoflow-tabular",
"id": 47,
"code": 921858,
"tempChar": ""
"tempChar": ""
},
{
"order": 55,
@@ -682,7 +666,7 @@
"name": "icon-clock",
"id": 50,
"code": 921859,
"tempChar": ""
"tempChar": ""
},
{
"order": 58,
@@ -690,7 +674,7 @@
"name": "icon-database",
"id": 53,
"code": 921860,
"tempChar": ""
"tempChar": ""
},
{
"order": 57,
@@ -698,7 +682,7 @@
"name": "icon-database-query",
"id": 52,
"code": 921861,
"tempChar": ""
"tempChar": ""
},
{
"order": 17,
@@ -706,7 +690,7 @@
"name": "icon-dataset",
"id": 12,
"code": 921862,
"tempChar": ""
"tempChar": ""
},
{
"order": 22,
@@ -714,7 +698,7 @@
"name": "icon-datatable",
"id": 17,
"code": 921863,
"tempChar": ""
"tempChar": ""
},
{
"order": 59,
@@ -722,7 +706,7 @@
"name": "icon-dictionary",
"id": 54,
"code": 921864,
"tempChar": ""
"tempChar": ""
},
{
"order": 62,
@@ -730,7 +714,7 @@
"name": "icon-folder",
"id": 57,
"code": 921865,
"tempChar": ""
"tempChar": ""
},
{
"order": 66,
@@ -738,7 +722,7 @@
"name": "icon-image",
"id": 61,
"code": 921872,
"tempChar": ""
"tempChar": ""
},
{
"order": 68,
@@ -746,7 +730,7 @@
"name": "icon-layout",
"id": 63,
"code": 921873,
"tempChar": ""
"tempChar": ""
},
{
"order": 77,
@@ -754,7 +738,7 @@
"name": "icon-object",
"id": 72,
"code": 921874,
"tempChar": ""
"tempChar": ""
},
{
"order": 78,
@@ -762,7 +746,7 @@
"name": "icon-object-unknown",
"id": 73,
"code": 921875,
"tempChar": ""
"tempChar": ""
},
{
"order": 79,
@@ -770,7 +754,7 @@
"name": "icon-packet",
"id": 74,
"code": 921876,
"tempChar": ""
"tempChar": ""
},
{
"order": 80,
@@ -778,7 +762,7 @@
"name": "icon-page",
"id": 75,
"code": 921877,
"tempChar": ""
"tempChar": ""
},
{
"order": 135,
@@ -786,7 +770,7 @@
"name": "icon-plot-overlay",
"prevSize": 24,
"code": 921878,
"tempChar": ""
"tempChar": ""
},
{
"order": 113,
@@ -794,7 +778,7 @@
"name": "icon-plot-stacked",
"prevSize": 24,
"code": 921879,
"tempChar": ""
"tempChar": ""
},
{
"order": 10,
@@ -802,7 +786,7 @@
"name": "icon-session",
"id": 5,
"code": 921880,
"tempChar": ""
"tempChar": ""
},
{
"order": 24,
@@ -810,7 +794,7 @@
"name": "icon-tabular",
"id": 19,
"code": 921881,
"tempChar": ""
"tempChar": ""
},
{
"order": 7,
@@ -818,7 +802,7 @@
"name": "icon-tabular-lad",
"id": 2,
"code": 921888,
"tempChar": ""
"tempChar": ""
},
{
"order": 6,
@@ -826,7 +810,7 @@
"name": "icon-tabular-lad-set",
"id": 1,
"code": 921889,
"tempChar": ""
"tempChar": ""
},
{
"order": 8,
@@ -834,7 +818,7 @@
"name": "icon-tabular-realtime",
"id": 3,
"code": 921890,
"tempChar": ""
"tempChar": ""
},
{
"order": 23,
@@ -842,7 +826,7 @@
"name": "icon-tabular-scrolling",
"id": 18,
"code": 921891,
"tempChar": ""
"tempChar": ""
},
{
"order": 112,
@@ -850,7 +834,7 @@
"name": "icon-telemetry",
"id": 86,
"code": 921892,
"tempChar": ""
"tempChar": ""
},
{
"order": 90,
@@ -858,7 +842,7 @@
"name": "icon-telemetry-panel",
"id": 85,
"code": 921893,
"tempChar": ""
"tempChar": ""
},
{
"order": 93,
@@ -866,7 +850,7 @@
"name": "icon-timeline",
"id": 88,
"code": 921894,
"tempChar": ""
"tempChar": ""
},
{
"order": 116,
@@ -874,7 +858,7 @@
"name": "icon-timer-v1.5",
"prevSize": 24,
"code": 921895,
"tempChar": ""
"tempChar": ""
},
{
"order": 11,
@@ -882,7 +866,7 @@
"name": "icon-topic",
"id": 6,
"code": 921896,
"tempChar": ""
"tempChar": ""
},
{
"order": 115,
@@ -890,7 +874,7 @@
"name": "icon-box-with-dashed-lines",
"id": 29,
"code": 921897,
"tempChar": ""
"tempChar": ""
},
{
"order": 126,
@@ -898,15 +882,7 @@
"name": "icon-summary-widget",
"prevSize": 24,
"code": 921904,
"tempChar": ""
},
{
"order": 139,
"id": 117,
"name": "icon-notebook",
"prevSize": 24,
"code": 921905,
"tempChar": ""
"tempChar": ""
}
],
"metadata": {
@@ -2707,52 +2683,6 @@
]
}
},
{
"id": 115,
"paths": [
"M832 192.4v639.4c0 0.2-0.2 0.2-0.4 0.4h-319.6v192h320c105.6 0 192-86.4 192-192v-640.2c0-105.6-86.4-192-192-192h-320v192h319.6c0.2 0 0.4 0.2 0.4 0.4z",
"M192 704v192l384-384-384-384v192h-192v384z"
],
"attrs": [
{},
{}
],
"grid": 16,
"tags": [
"icon-import"
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"1161751207457516161751": [
{},
{}
]
}
},
{
"id": 116,
"paths": [
"M192 831.66v-639.32l0.34-0.34h319.66v-192h-320c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192h320v-192h-319.66z",
"M1024 512l-384-384v192h-192v384h192v192l384-384z"
],
"attrs": [
{},
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-export"
],
"colorPermutations": {
"1161751207457516161751": [
{},
{}
]
}
},
{
"paths": [
"M576 64h-256l320 320h-290.256c-44.264-76.516-126.99-128-221.744-128h-128v512h128c94.754 0 177.48-51.484 221.744-128h290.256l-320 320h256l448-448-448-448z"
@@ -3532,29 +3462,6 @@
{}
]
}
},
{
"id": 117,
"paths": [
"M896 110.8c0-79.8-55.4-127.4-123-105.4l-773 250.6h896v-145.2z",
"M896 320h-896v576c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-448c0-70.4-57.6-128-128-128zM832 832h-384v-320h384v320z"
],
"attrs": [
{},
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-notebook"
],
"colorPermutations": {
"1161751207457516161751": [
{},
{}
]
}
}
],
"colorThemes": [

View File

@@ -85,8 +85,6 @@
<glyph unicode="&#xe1044;" glyph-name="icon-grid-snap-no" d="M768 384h192v-64h-192v64zM256 384h192v-64h-192v64zM0 384h192v-64h-192v64zM640 448h-64v-64h-64v-64h64v-64h64v64h64v64h-64zM576 704h64v-192h-64v192zM576 960h64v-192h-64v192zM576 192h64v-192h-64v192z" />
<glyph unicode="&#xe1045;" glyph-name="icon-frame-show" d="M0 896v-896h1024v896h-1024zM896 128h-768v640h768v-640zM192 704h384v-128h-384v128z" />
<glyph unicode="&#xe1046;" glyph-name="icon-frame-hide" d="M128 770h420l104 128h-652v-802.4l128 157.4zM896 130h-420l-104-128h652v802.4l-128-157.4zM832 962l-832-1024h192l832 1024zM392 578l104 128h-304v-128z" />
<glyph unicode="&#xe1047;" glyph-name="icon-import" d="M832 767.6v-639.4c0-0.2-0.2-0.2-0.4-0.4h-319.6v-192h320c105.6 0 192 86.4 192 192v640.2c0 105.6-86.4 192-192 192h-320v-192h319.6c0.2 0 0.4-0.2 0.4-0.4zM192 256v-192l384 384-384 384v-192h-192v-384z" />
<glyph unicode="&#xe1048;" glyph-name="icon-export" d="M192 128.34v639.32l0.34 0.34h319.66v192h-320c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h320v192h-319.66zM1024 448l-384 384v-192h-192v-384h192v-192l384 384z" />
<glyph unicode="&#xe1100;" glyph-name="icon-activity" d="M576 896h-256l320-320h-290.256c-44.264 76.516-126.99 128-221.744 128h-128v-512h128c94.754 0 177.48 51.484 221.744 128h290.256l-320-320h256l448 448-448 448z" />
<glyph unicode="&#xe1101;" glyph-name="icon-activity-mode" d="M512 960c-214.866 0-398.786-132.372-474.744-320h90.744c56.86 0 107.938-24.724 143.094-64h240.906l-192 192h256l320-320-320-320h-256l192 192h-240.906c-35.156-39.276-86.234-64-143.094-64h-90.744c75.958-187.628 259.878-320 474.744-320 282.77 0 512 229.23 512 512s-229.23 512-512 512z" />
<glyph unicode="&#xe1102;" glyph-name="icon-autoflow-tabular" d="M192 960c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h64v1024h-64zM384 960h256v-1024h-256v1024zM832 960h-64v-704h256v512c0 105.6-86.4 192-192 192z" />
@@ -118,5 +116,4 @@
<glyph unicode="&#xe1128;" glyph-name="icon-topic" d="M454.36 483.36l86.3 86.3c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c19.328-19.358 42.832-34.541 69.047-44.082l1.313 171.722-57.64 57.64c-34.407 34.33-81.9 55.558-134.35 55.558s-99.943-21.228-134.354-55.562l-86.296-86.297c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-28.674 28.654v-172.14c19.045-7.022 41.040-11.084 63.984-11.084 52.463 0 99.966 21.239 134.379 55.587zM505.64 412.64l-86.3-86.3c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-86.294 86.294c-2 2-4.2 4-6.36 6v-197.36c33.664-30.72 78.65-49.537 128.031-49.537 52.44 0 99.923 21.22 134.333 55.541l86.296 86.296c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c2-2 4.2-4 6.36-6v197.36c-33.664 30.72-78.65 49.537-128.031 49.537-52.44 0-99.923-21.22-134.333-55.541zM832 960h-128v-192h127.66l0.34-0.34v-639.32l-0.34-0.34h-127.66v-192h128c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM320 128h-127.66l-0.34 0.34v639.32l0.34 0.34h127.66v192h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192z" />
<glyph unicode="&#xe1129;" glyph-name="icon-box-with-dashed-lines" d="M0 576h128v-256h-128v256zM128 831.78l0.22 0.22h191.78v128h-192c-70.606-0.215-127.785-57.394-128-127.979v-192.021h128v191.78zM128 64.22v191.78h-128v-192c0.215-70.606 57.394-127.785 127.979-128h192.021v128h-191.78zM384 960h256v-128h-256v128zM896 64.22l-0.22-0.22h-191.78v-128h192c70.606 0.215 127.785 57.394 128 127.979v192.021h-128v-191.78zM896 960h-192v-128h191.78l0.22-0.22v-191.78h128v192c-0.215 70.606-57.394 127.785-127.979 128zM896 576h128v-256h-128v256zM384 64h256v-128h-256v128zM256 704h512v-512h-512v512z" />
<glyph unicode="&#xe1130;" glyph-name="icon-summary-widget" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM847.8 349.6l-82.6-143.2-189.6 131.6 19.2-230h-165.4l19.2 230-189.6-131.6-82.6 143.2 208.6 98.4-208.8 98.4 82.6 143.2 189.6-131.6-19.2 230h165.4l-19.2-230 189.6 131.6 82.6-143.2-208.6-98.4 208.8-98.4z" />
<glyph unicode="&#xe1131;" glyph-name="icon-notebook" d="M896 849.2c0 79.8-55.4 127.4-123 105.4l-773-250.6h896v145.2zM896 640h-896v-576c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v448c0 70.4-57.6 128-128 128zM832 128h-384v320h384v-320z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -21,7 +21,7 @@
*****************************************************************************/
/************************** FEATURES */
$enableImageryThumbs: true; // Set to true if historical imagery thumbnails are supported
$enableImageryThumbs: false; // Set to true if historical imagery thumbnails are supported
/************************** VERY INFLUENTIAL GLOBAL DIMENSIONS */
$bodyMargin: 10px;
@@ -82,7 +82,7 @@ $tabularTdPadTB: 2px;
/*************** Imagery */
$imageMainControlBarH: 25px;
$imageThumbsD: 120px;
$imageThumbsWrapperH: 155px;
$imageThumbsWrapperH: $imageThumbsD * 1.4;
$imageThumbPad: 1px;
/*************** Ticks */
$ticksH: 25px;

View File

@@ -52,7 +52,6 @@
font-size: 0.8rem;
$p: 1px;
line-height: 100%;
overflow: hidden;
&.l-static-text {
padding: $p;
}

View File

@@ -113,8 +113,6 @@ $glyph-icon-grid-snap-to: '\e1043';
$glyph-icon-grid-snap-no: '\e1044';
$glyph-icon-frame-show: '\e1045';
$glyph-icon-frame-hide: '\e1046';
$glyph-icon-import: '\e1047';
$glyph-icon-export: '\e1048';
$glyph-icon-activity: '\e1100';
$glyph-icon-activity-mode: '\e1101';
$glyph-icon-autoflow-tabular: '\e1102';
@@ -146,7 +144,6 @@ $glyph-icon-timer: '\e1127';
$glyph-icon-topic: '\e1128';
$glyph-icon-box-with-dashed-lines: '\e1129';
$glyph-icon-summary-widget: '\e1130';
$glyph-icon-notebook: '\e1131';
/************************** 16 PX CLASSES */
@@ -228,8 +225,6 @@ $glyph-icon-notebook: '\e1131';
.icon-grid-snap-no { @include glyphBefore($glyph-icon-grid-snap-no); }
.icon-frame-show { @include glyphBefore($glyph-icon-frame-show); }
.icon-frame-hide { @include glyphBefore($glyph-icon-frame-hide); }
.icon-import { @include glyphBefore($glyph-icon-import); }
.icon-export { @include glyphBefore($glyph-icon-export); }
.icon-activity { @include glyphBefore($glyph-icon-activity); }
.icon-activity-mode { @include glyphBefore($glyph-icon-activity-mode); }
.icon-autoflow-tabular { @include glyphBefore($glyph-icon-autoflow-tabular); }
@@ -261,7 +256,6 @@ $glyph-icon-notebook: '\e1131';
.icon-topic { @include glyphBefore($glyph-icon-topic); }
.icon-box-with-dashed-lines { @include glyphBefore($glyph-icon-box-with-dashed-lines); }
.icon-summary-widget { @include glyphBefore($glyph-icon-summary-widget); }
.icon-notebook { @include glyphBefore($glyph-icon-notebook); }
/************************** 12 PX CLASSES */
.icon-crosshair-12px { @include glyphBefore($glyph-icon-crosshair,'symbolsfont-12px'); }

View File

@@ -26,6 +26,5 @@
display: block;
height: 100%;
width: 100%;
border: none;
}
}

View File

@@ -327,17 +327,14 @@
}
}
@mixin s-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@include input-base();
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@include input-base();
background: $bg;
box-shadow: inset $shdw;
color: $fg;
}
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@include s-input($bg, $fg, $shdw);
border: none;
color: $fg;
outline: none;
padding: $inputTextPTopBtm $inputTextPLeftRight;
}
@mixin contextArrow() {

View File

@@ -33,6 +33,7 @@ $pad: $interiorMargin * $baseRatio;
height: $btnStdH;
line-height: $btnStdH;
padding: 0 $pad;
vertical-align: top;
&.labeled:before {
// Icon when it's included

View File

@@ -72,13 +72,11 @@
}
}
// Hyperlink objects
.s-hyperlink {
.label {
font-size: 0.8rem !important;
}
// Hyperlink objects
&:not(.s-button) {
color: $colorKey;
font-size: 0.8rem;
&:hover { color: $colorKeyHov; }
}
}
@@ -234,21 +232,35 @@ textarea {
}
/******************************************************** INPUTS */
%input-base {
@include input-base();
}
input[type="text"],
input[type="search"],
input[type="number"] {
@include nice-input();
vertical-align: baseline;
padding: $inputTextPTopBtm $inputTextPLeftRight;
padding: $inputTextP;
&.numeric {
text-align: right;
}
}
span[contenteditable].s-inline-edit {
@include trans-prop-nice((padding), 250ms);
@include input-base();
border: 1px solid transparent;
min-width: 20px;
&:hover {
border-color: rgba($colorBodyFg, 0.2);
padding-left: $inputTextPLeftRight;
padding-right: $inputTextPLeftRight;
}
}
span[contenteditable].s-inline-edit.s-status-editing {
@include nice-input();
vertical-align: baseline;
padding: 0 $inputTextPLeftRight;
}
.l-input-sm {
input[type="text"],
input[type="search"],
@@ -287,32 +299,6 @@ textarea.lg { position: relative; height: 300px; }
}
}
*[contenteditable].s-input-inline,
input[type="text"].s-input-inline,
.s-input-inline input[type="text"] {
// A text input or contenteditable element that indicates edit affordance on hover and looks like an input on focus
@extend %input-base;
@include trans-prop-nice((padding, box-shadow), 250ms);
background: none;
box-shadow: none;
border: 1px solid transparent;
min-width: 20px;
padding-left: 0;
padding-right: 0;
&:hover,
&:focus {
padding-left: $inputTextPLeftRight;
padding-right: $inputTextPLeftRight;
}
&:hover {
border-color: rgba($colorBodyFg, 0.2);
}
&:focus {
@include s-input();
border-color: transparent;
}
}
/******************************************************** SELECTS */
.select {
@include btnSubtle($bg: $colorSelectBg);
@@ -328,7 +314,6 @@ input[type="text"].s-input-inline,
select {
@include appearance(none);
box-sizing: border-box;
&:focus { outline: 0; }
background: none;
color: $colorSelectFg;
cursor: pointer;
@@ -340,8 +325,9 @@ input[type="text"].s-input-inline,
}
}
&:before {
//@include contextArrow();
pointer-events: none;
color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
color: rgba($colorSelectFg, percentToDecimal($contrastInvokeMenuPercent));
display: block;
position: absolute;
right: $interiorMargin; top: 0;
@@ -753,15 +739,11 @@ body.desktop {
}
.overlay ::-webkit-scrollbar-thumb {
$lr: 15%;
background: $scrollbarThumbColorOverlay;
&:hover { background: $scrollbarThumbColorOverlayHov; }
}
.menu ::-webkit-scrollbar-thumb {
background: $scrollbarThumbColorMenu;
&:hover { background: $scrollbarThumbColorMenuHov; }
}
::-webkit-scrollbar-corner {
background: $scrollbarTrackColorBg;
}

View File

@@ -21,87 +21,92 @@
*****************************************************************************/
/******************************************************** MENU BUTTONS */
.s-menu-button {
// Formerly .btn-menu
@extend .s-button;
span.l-click-area {
// In markup, this element should not enclose anything.
@extend .abs;
}
// Formerly .btn-menu
@extend .s-button;
span.l-click-area {
// In markup, this element should not enclose anything.
@extend .abs;
}
.icon {
font-size: 16px; //120%;
}
.icon {
font-size: 16px; //120%;
}
.title-label {
margin-left: $interiorMarginSm;
}
.title-label {
margin-left: $interiorMarginSm;
}
.color-swatch {
// Used in color menu buttons in toolbar
$d: 10px;
display: inline-block;
border: 1px solid rgba($colorBtnFg, 0.2);
height: $d;
width: $d;
height: $d; width: $d;
vertical-align: middle;
margin-left: $interiorMarginSm;
margin-top: -2px;
}
&:after {
// Adds the downward facing 'context available / invoke menu' arrow element
@include contextArrow();
color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
}
&:after {
// Adds the downward facing 'context available / invoke menu' arrow element
@include contextArrow();
color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
}
&.create-button {
&.create-button {
@extend .icon-plus;
.title-label {
font-size: 1rem;
}
}
.title-label {
font-size: 1rem;
}
}
.menu {
left: 0;
text-align: left;
}
.menu {
left: 0;
text-align: left;
}
}
/******************************************************** MENUS THEMSELVES */
.menu-element {
cursor: pointer;
position: relative;
cursor: pointer;
position: relative;
}
.s-menu {
border-radius: $basicCr;
@include containerSubtle($colorMenuBg, $colorMenuFg);
@include boxShdw($shdwMenu);
@include txtShdw($shdwMenuText);
padding: $interiorMarginSm 0;
}
.menu {
border-radius: $basicCr;
@include containerSubtle($colorMenuBg, $colorMenuFg);
@include boxShdw($shdwMenu);
@include txtShdw($shdwMenuText);
padding: $interiorMarginSm 0;
display: block;
position: absolute;
z-index: 10;
ul {
@include menuUlReset();
li {
box-sizing: border-box;
border-top: 1px solid pullForward($colorMenuBg, 10%);
// TODO: reduce size of icons
@extend .s-menu;
display: block;
position: absolute;
z-index: 10;
ul {
@include menuUlReset();
li {
box-sizing: border-box;
border-top: 1px solid pullForward($colorMenuBg, 10%);
color: $colorMenuFg;
line-height: $menuLineH;
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
position: relative;
white-space: nowrap;
&:first-child {
border: none;
}
&:hover {
background: $colorMenuHovBg;
color: $colorMenuHovFg;
//color: pullForward($colorMenuBg, 60%);
line-height: $menuLineH;
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
position: relative;
white-space: nowrap;
&:first-child {
border: none;
}
&:hover {
background: $colorMenuHovBg;
color: $colorMenuHovFg;
&:before {
color: $colorMenuHovIc;
}
}
}
&:before {
@extend .ui-symbol;
@extend .type-icon;
@@ -109,8 +114,8 @@
display: inline-block;
left: $interiorMargin * 2;
}
}
}
}
}
}
.menu,
@@ -118,97 +123,94 @@
.context-menu,
.super-menu,
.s-menu-button .menu {
pointer-events: auto;
ul li {
a.menu-item-a {
pointer-events: auto;
ul li {
a.menu-item-a {
color: $colorMenuFg;
display: block;
}
}
&:before,
a.menu-item-a:before {
color: $colorMenuIc;
left: $interiorMargin;
}
}
}
}
.checkbox-menu {
// Used in search dropdown in tree
@extend .context-menu;
ul li {
padding-left: 50px;
.checkbox {
$d: 0.7rem;
position: absolute;
left: $interiorMargin;
top: ($menuLineH - $d) / 1.5;
em {
height: $d;
width: $d;
&:before {
font-size: 7px !important;
height: $d;
width: $d;
line-height: $d;
}
}
}
&:before {
// Used in search dropdown in tree
@extend .context-menu;
ul li {
padding-left: 50px;
.checkbox {
$d: 0.7rem;
position: absolute;
left: $interiorMargin;
top: ($menuLineH - $d) / 1.5;
em {
height: $d;
width: $d;
&:before {
font-size: 7px !important;
height: $d;
width: $d;
line-height: $d;
}
}
}
&:before {
// Type icon
left: 25px;
}
}
}
.super-menu,
.super-menu > mct-representation,
.super-menu > .contents {
box-sizing: border-box;
display: block;
position: relative;
left: 25px;
}
}
}
.super-menu {
$plw: 50%;
$prw: 100% - $plw;
position: absolute;
.w-menu {
align-items: stretch;
display: flex;
flex-direction: row;
margin: $interiorMarginLg;
}
.col {
box-sizing: border-box;
flex: 1 1 auto;
overflow-x: hidden;
&.menu-items {
border-right: 1px solid pullForward($colorMenuBg, 10%);
overflow-y: auto;
padding-right: $interiorMargin;
width: $plw;
ul {
li {
border-radius: $controlCr;
padding-left: 30px;
border-top: none;
}
}
}
&.menu-item-description {
$p: $interiorMargin * 3;
overflow-y: hidden;
padding: $p $p 0 $p;
width: $prw;
$w: 500px;
$h: $w - 20;
$plw: 50%;
$prw: 50%;
display: block;
width: $w;
height: $h;
.contents {
@include absPosDefault($interiorMargin);
}
.pane {
box-sizing: border-box;
&.menu-items {
border-right: 1px solid pullForward($colorMenuBg, 10%);
left: 0;
padding-right: $interiorMargin;
right: auto;
width: $plw;
overflow-x: hidden;
overflow-y: auto;
ul {
li {
border-radius: $controlCr;
padding-left: 30px;
border-top: none;
}
}
}
&.menu-item-description {
left: auto;
right: 0;
padding: $interiorMargin * 5;
width: $prw;
.desc-area {
&.icon {
color: $colorCreateMenuLgIcon;
font-size: 8em;
margin-bottom: $interiorMargin * 3;
position: relative;
text-align: center;
}
&.title {
color: $colorCreateMenuText;
font-size: 1.2em;
margin-bottom: $interiorMargin * 2;
}
&.description {
color: pushBack($colorCreateMenuText, 20%);
@@ -216,104 +218,67 @@
line-height: 1.5em;
}
}
}
}
.w-title-desc {
display: flex;
flex-direction: column;
overflow: hidden; // Height set in specific menu instances
}
// Specific menu instances
&.l-create-menu {
width: 500px;
.col {
max-height: 70vh;
}
.w-title-desc {
height: 190px;
}
.desc-area {
&.icon {
font-size: 8em;
height: 135px;
margin-bottom: $interiorMargin * 3;
}
&.title {
font-size: 1.2em;
margin-bottom: $interiorMargin * 2;
}
}
}
}
}
&.mini {
width: 400px;
.col {
max-height: 50vh;
height: 300px;
.pane {
&.menu-items {
font-size: 0.8em;
}
&.menu-item-description {
$p: $interiorMargin * 2;
padding: $p $p 0 $p;
}
}
.w-title-desc {
height: 180px;
}
.desc-area {
&.icon {
font-size: 4em;
height: 70px;
margin-bottom: $interiorMargin * 3;
}
&.title {
font-size: 1em;
margin-bottom: $interiorMargin * 2;
padding: $interiorMargin * 3;
.desc-area {
&.icon {
font-size: 4em;
}
&.title {
font-size: 1em;
}
}
}
}
}
}
.context-menu {
font-size: 0.80rem;
font-size: 0.80rem;
}
.context-menu-holder,
.menu-holder {
position: absolute;
z-index: 120;
.context-menu-wrapper {
position: absolute;
height: 100%;
width: 100%;
}
&.go-left .context-menu,
&.go-left .menu {
right: 0;
}
&.go-up .context-menu,
&.go-up .menu {
bottom: 0;
}
position: absolute;
z-index: 120;
.context-menu-wrapper {
position: absolute;
height: 100%;
width: 100%;
}
&.go-left .context-menu,
&.go-left .menu {
right: 0;
}
&.go-up .context-menu,
&.go-up .menu {
bottom: 0;
}
}
.context-menu-holder {
pointer-events: none;
height: 200px;
width: 170px;
pointer-events: none;
height: 200px;
width: 170px;
}
.btn-bar.right .menu,
.menus-to-left .menu {
z-index: 79;
left: auto;
right: 0;
width: auto;
left: auto;
right: 0;
width: auto;
}
.menus-up .menu {
bottom: $btnStdH;
top: auto;
bottom: $btnStdH; top: auto;
}

View File

@@ -9,6 +9,7 @@
@if $enableImageryThumbs == true {
bottom: $interiorMargin*2 + $imageThumbsWrapperH;
}
min-height: 100px;
min-width: 150px;
.l-image-main {
background-color: $colorPlotBg;
@@ -21,9 +22,7 @@
.l-image-thumbs-wrapper {
top: auto;
min-height: $imageThumbsWrapperH;
max-height: 60%;
box-sizing: border-box;
height: $imageThumbsWrapperH;
}
.l-date,
@@ -44,16 +43,14 @@
.l-image-main-controlbar {
font-size: 0.8em;
line-height: inherit;
.l-datetime-w, .l-controls-w {
.left, .right {
direction: rtl;
overflow: hidden;
}
.l-datetime-w {
@include ellipsize();
margin-right: $interiorMarginSm;
.left {
text-align: left;
}
.l-controls-w {
.right {
z-index: 2;
}
.l-date,
@@ -85,8 +82,9 @@
/*************************************** THUMBS */
.l-image-thumbs-wrapper {
overflow-x: hidden;
overflow-y: auto;
//@include test(green);
overflow-x: auto;
overflow-y: hidden;
padding-bottom: $interiorMargin;
white-space: nowrap;
}
@@ -94,17 +92,8 @@
.l-image-thumb-item {
@include transition(background-color, 0.25s);
box-sizing: border-box;
cursor: pointer;
direction: ltr;
display: inline-block;
float: left;
font-size: 0.8em;
padding: 1px;
margin-left: $interiorMarginSm;
position: relative;
text-align: left;
width: $imageThumbsD + $imageThumbPad*2;
white-space: normal;
position: relative;
.l-thumb,
.l-date,
.l-time {
@@ -114,7 +103,14 @@
.l-time {
padding: 2px 3px;
}
cursor: pointer;
direction: ltr;
display: inline-block;
font-size: 0.8em;
margin-left: $interiorMarginSm;
text-align: left;
width: $imageThumbsD + $imageThumbPad*2;
white-space: normal;
&:hover {
background: $colorThumbHoverBg;
.l-date,
@@ -140,7 +136,6 @@
/*************************************** LOCAL CONTROLS */
.l-local-controls {
max-width: 200px;
min-width: 100px;
width: 35%;
input[type="range"] {
display: block;
@@ -189,8 +184,7 @@
/*************************************** WHEN IN FRAME */
.frame .t-imagery {
.l-image-main-wrapper {
bottom: 0 !important;
height: 100% !important;
bottom: 0;
.l-image-main-controlbar {
font-size: 0.7em;
}
@@ -200,8 +194,7 @@
}
}
}
.l-image-thumbs-wrapper,
mct-splitter {
.l-image-thumbs-wrapper {
display: none;
}
}

View File

@@ -156,8 +156,6 @@
left: 0;
right: 0;
overflow: auto;
padding-right: $interiorMargin;
padding-bottom: $interiorMargin;
.field.l-input-med {
input[type='text'] {
width: 100%;

View File

@@ -47,7 +47,7 @@
&.t-object-type-hyperlink {
// Hide the right side buttons for objects where they don't make sense
// Note that this will hide the view Switcher button if applied
// to an object that has it.
// to an object that it.
.object-browse-bar .right { display: none; }
}
@@ -120,17 +120,9 @@
}
}
&.t-frame-outer .s-input-inline {
// Prevent inline inputs from being edited when nested in a Layout
pointer-events: none !important;
}
/********************************************************** OBJECT TYPES */
/********************************************************** OBJECT TYPES */
.t-object-type-hyperlink {
.object-holder {
overflow: hidden;
}
.l-hyperlink.s-button {
.s-hyperlink.s-button {
// When a hyperlink is a button in a frame, make it expand to fill out to the object-holder
@extend .abs;
.label {
@@ -150,7 +142,7 @@
body.desktop .frame {
// Hide local controls initially and show it them on hover when they're in an element that's in a frame context
// Frame template is used because we need to target the lowest nested frame
.object-browse-bar .btn-bar {
.right {
opacity: 0;
pointer-events: none;
}
@@ -158,7 +150,7 @@ body.desktop .frame {
// Target the first descendant so that we only show the elements in the outermost container.
// Handles the case where we have layouts in layouts.
&:hover > .object-browse-bar {
.btn-bar {
.right {
opacity: 1;
pointer-events: inherit;
}

View File

@@ -240,9 +240,7 @@ body.desktop .pane .mini-tab-icon.toggle-pane {
.top-bar .buttons-main .s-button,
.top-bar .s-menu-button,
.tool-bar .s-button,
.tool-bar .s-menu-button,
.tool-bar .select,
.tool-bar .input-labeled {
.tool-bar .s-menu-button {
$h: $btnToolbarH;
height: $h;
line-height: $h;

View File

@@ -20,7 +20,6 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
.tool-bar {
font-size: 0.7rem;
&.btn-bar {
white-space: nowrap;
}
@@ -31,7 +30,9 @@
input[type="search"],
input[type="number"] {
box-sizing: border-box;
font-size: .8em;
height: $btnToolbarH;
margin-bottom: 1px;
position: relative;
&.sm {
width: $btnToolbarH;

View File

@@ -108,11 +108,8 @@ define(
getMetadata();
});
var mutation = $scope.ngModel.selectedObject.getCapability('mutation');
var unlisten = mutation.listen(getMetadata);
$scope.$on('$destroy', unlisten);
}
return ObjectInspectorController;
}
);

View File

@@ -117,7 +117,9 @@ define(
// Apply styles to child elements
function updateChildren(children) {
position = userWidthPreference || position;
if (alias) {
position = userWidthPreference || position;
}
// Pick out correct elements to update, flowing from
// selected anchor edge.
@@ -180,9 +182,7 @@ define(
}
function setUserWidthPreference(value) {
if (alias) {
userWidthPreference = value;
}
userWidthPreference = value;
}
function persistToLocalStorage(value) {

View File

@@ -39,18 +39,10 @@ define(
beforeEach(function () {
mockScope = jasmine.createSpyObj(
"$scope",
["$watch", "$on"]
["$watch"]
);
mockScope.ngModel = {};
mockScope.ngModel.selectedObject = {
getCapability: function () {
return {
listen: function () {
return true;
}
};
}
};
mockScope.ngModel.selectedObject = 'mock selected object';
mockObjectService = jasmine.createSpyObj(
"objectService",

View File

@@ -201,15 +201,13 @@ $shdwItemTreeIcon: 0.6;
$colorThumbHoverBg: $colorItemTreeHoverBg;
// Scrollbar
$scrollbarTrackSize: 7px;
$scrollbarTrackShdw: rgba(#000, 0.5) 0 1px 5px;
$scrollbarTrackColorBg: transparent; //rgba(#000, 0.4);
$scrollbarTrackSize: 10px;
$scrollbarTrackShdw: rgba(#000, 0.7) 0 1px 5px;
$scrollbarTrackColorBg: rgba(#000, 0.4);
$scrollbarThumbColor: pullForward($colorBodyBg, 10%);
$scrollbarThumbColorHov: pullForward($scrollbarThumbColor, 2%);
$scrollbarThumbColorOverlay: pullForward($colorOvrBg, 10%);
$scrollbarThumbColorOverlayHov: pullForward($scrollbarThumbColorOverlay, 2%);
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 20%);
$scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
// Splitter
// All splitterD* values MUST both be either odd or even numbers

View File

@@ -201,15 +201,13 @@ $shdwItemTreeIcon: none;
$colorThumbHoverBg: $colorItemTreeHoverBg;
// Scrollbar
$scrollbarTrackSize: 7px;
$scrollbarTrackSize: 10px;
$scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px;
$scrollbarTrackColorBg: rgba(#000, 0.2);
$scrollbarThumbColor: darken($colorBodyBg, 50%);
$scrollbarThumbColorHov: $colorKey;
$scrollbarThumbColorOverlay: darken($colorOvrBg, 50%);
$scrollbarThumbColorOverlayHov: $scrollbarThumbColorHov;
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 10%);
$scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
// Splitter
// All splitterD* values MUST both be either odd or even numbers

View File

@@ -94,6 +94,31 @@ define([
}
},
"extensions": {
"versions": [
{
"name": "Version",
"value": "@@version",
"priority": 999
},
{
"name": "Built",
"value": "@@timestamp",
"description": "The date on which this version of the client was built.",
"priority": 990
},
{
"name": "Revision",
"value": "@@revision",
"description": "A unique revision identifier for the client sources.",
"priority": 995
},
{
"name": "Branch",
"value": "@@branch",
"description": "The name of the branch that was used during the build.",
"priority": 994
}
],
"components": [
{
"provides": "objectService",

View File

@@ -1,7 +1,7 @@
$ueTimeConductorH: (25px, 16px, 20px); // Heights for Ticks, Data Visualization, Controls elements
$ueTimeConductorRtH: (25px, 3px, 20px); // Heights for elements in Real-time mode
$timeCondInputTimeSysDefW: 165px; // Default width for datetime value inputs
$timeCondInputDeltaDefW: 65px; // Default width for delta value inputs, typically 00:00:00
$timeCondInputDeltaDefW: 60px; // Default width for delta value inputs, typically 00:00:00
$timeCondTOIIconD: 12px; // height and width of icon used for TOI indicator
$timeCondTOIValOffset: 0px;
$ticksBlockerFadeW: 50px;

View File

@@ -162,6 +162,9 @@
.l-time-conductor-inputs {
pointer-events: auto;
}
input[type="text"] {
@include trans-prop-nice(padding, 250ms);
}
.time-range-input input[type="text"] {
width: $timeCondInputTimeSysDefW;
}
@@ -287,6 +290,18 @@
.l-time-conductor-inputs-holder {
.l-time-range-input-w {
input[type="text"]:not(.error) {
background: transparent;
box-shadow: none;
border-radius: 0;
padding-left: 0;
padding-right: 0;
&:hover,
&:focus {
@include nice-input();
padding: $inputTextP;
}
}
.icon-calendar {
display: none;
}
@@ -294,11 +309,8 @@
display: none;
}
&.end-date {
// Displays the current time
pointer-events: none;
input[type="text"] {
background: none;
box-shadow: none;
color: pullForward($colorTimeCondKeyBg, 5%);
margin-right: $interiorMargin;
tab-index: -1;

View File

@@ -19,8 +19,8 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div class="w-menu">
<div class="col menu-items">
<div class="contents">
<div class="pane left menu-items">
<ul>
<li ng-repeat="metadata in ngModel.options"
ng-click="ngModel.select(metadata)">
@@ -32,15 +32,13 @@
</li>
</ul>
</div>
<div class="col menu-item-description">
<div class="pane right menu-item-description">
<div class="desc-area ui-symbol icon type-icon {{ngModel.activeMetadata.cssClass}}"></div>
<div class="w-title-desc">
<div class="desc-area title">
{{ngModel.activeMetadata.name}}
</div>
<div class="desc-area description">
{{ngModel.activeMetadata.description}}
</div>
<div class="desc-area title">
{{ngModel.activeMetadata.name}}
</div>
<div class="desc-area description">
{{ngModel.activeMetadata.description}}
</div>
</div>
</div>

View File

@@ -24,7 +24,7 @@
ng-click="modeController.toggle()">
<span class="title-label">{{ngModel.selected.name}}</span>
</div>
<div class="menu super-menu mini l-mode-selector-menu"
<div class="menu super-menu mini mode-selector-menu"
ng-show="modeController.isActive()">
<mct-include key="'mode-menu'"
ng-model="ngModel">

View File

@@ -38,7 +38,7 @@
ng-model="boundsModel"
ng-blur="tcController.setOffsetsFromView(boundsModel)"
field="'startOffset'"
class="s-input-inline hrs-min-input">
class="hrs-min-input">
</mct-control>
</span>
</span>
@@ -71,7 +71,7 @@
ng-model="boundsModel"
ng-blur="tcController.setOffsetsFromView(boundsModel)"
field="'endOffset'"
class="s-input-inline hrs-min-input">
class="hrs-min-input">
</mct-control>
</span>
</span>

View File

@@ -201,7 +201,7 @@ define(
var options = [{
key: 'fixed',
name: 'Fixed Timespan Mode',
description: 'Query and explore data that falls between two fixed datetimes.',
description: 'Query and explore data that falls between two fixed datetimes',
cssClass: 'icon-calendar'
}];
var clocks = {};

View File

@@ -122,6 +122,14 @@ define([
"description": "Set border color",
"control": "color"
},
{
"property": "color",
"cssClass": "icon-T",
"title": "Text color",
"description": "Set text color",
"mandatory": true,
"control": "color"
},
{
"property": "url",
"cssClass": "icon-image",
@@ -137,27 +145,6 @@ define([
}
]
},
{
"items": [
{
"property": "color",
"cssClass": "icon-T",
"title": "Text color",
"description": "Set text color",
"mandatory": true,
"control": "color"
},
{
"property": "size",
"title": "Text size",
"description": "Set text size",
"control": "select",
"options": [9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 30, 36, 48, 72, 96].map(function (size) {
return { "name": size + " px", "value": size + "px" };
})
}
]
},
{
"items": [
{
@@ -225,7 +212,11 @@ define([
"control": "numberfield",
"description": "Resize object width",
"min": "1"
},
}
]
},
{
"items": [
{
"property": "useGrid",
"name": "Snap to Grid",

View File

@@ -19,10 +19,10 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<a class="l-hyperlink s-hyperlink" ng-controller="HyperlinkController as hyperlink" href="{{domainObject.getModel().url}}"
<a class="s-hyperlink" ng-controller="HyperlinkController as hyperlink" href="{{domainObject.getModel().url}}"
ng-attr-target="{{hyperlink.openNewTab() ? '_blank' : undefined}}"
ng-class="{
's-button': hyperlink.isButton()
}">
<span class="label">{{domainObject.getModel().displayText}}</span>
<div class="label">{{domainObject.getModel().displayText}}</div>
</a>

View File

@@ -25,12 +25,14 @@ define([
"./src/controllers/ImageryController",
"./src/directives/MCTBackgroundImage",
"text!./res/templates/imagery.html",
"text!./res/templates/imageryTimeline.html",
'legacyRegistry'
], function (
ImageryViewPolicy,
ImageryController,
MCTBackgroundImage,
imageryTemplate,
imageryTimelineTemplate,
legacyRegistry
) {
@@ -48,6 +50,17 @@ define([
"telemetry"
],
"editable": false
},
{
"name": "Historical Imagery",
"key": "historical-imagery",
"cssClass": "icon-image",
"template": imageryTimelineTemplate,
"priority": "preferred",
"needs": [
"telemetry"
],
"editable": false
}
],
"policies": [

View File

@@ -1,6 +1,5 @@
<div class="t-imagery" ng-controller="ImageryController as imagery">
<mct-split-pane class='abs' anchor="bottom" alias="imagery">
<div class="split-pane-component l-image-main-wrapper l-flex-col"
<div class="l-image-main-wrapper l-flex-col"
ng-mouseenter="showLocalControls = true;"
ng-mouseleave="showLocalControls = false;">
<div class="l-local-controls s-local-controls s-wrapper-transluc l-flex-row"
@@ -33,12 +32,12 @@
</div>
<div class="l-image-main-controlbar flex-elem l-flex-row">
<div class="l-datetime-w flex-elem grows">
<div class="left flex-elem grows">
<a class="s-button show-thumbs sm hidden icon-thumbs-strip"
ng-click="showThumbsBubble = (showThumbsBubble) ? false:true"></a>
<span class="l-time">{{imagery.getTime()}}</span>
</div>
<div class="l-controls-w flex-elem">
<div class="right flex-elem">
<a class="s-button pause-play"
ng-click="imagery.paused(!imagery.paused())"
ng-class="{ paused: imagery.paused() }"></a>
@@ -56,14 +55,4 @@
</div>
</div>
</div>
<mct-splitter></mct-splitter>
<div class="split-pane-component l-image-thumbs-wrapper">
<div class="l-image-thumb-item" ng-class="{selected: image.selected}" ng-repeat="image in imageHistory track by $index"
ng-click="imagery.setSelectedImage(image)" ng-init="imagery.scrollToBottom()">
<img class="l-thumb"
ng-src={{imagery.getImageUrl(image)}}>
<div class="l-time">{{imagery.getTime(image)}}</div>
</div>
</div>
</mct-split-pane>
</div>

View File

@@ -0,0 +1,8 @@
<div class="l-image-thumbs-wrapper" ng-controller="ImageryController as imagery">
<div class="l-image-thumb-item" ng-repeat="image in imageHistory track by $index">
<img class="l-thumb" ng-init="imagery.scrollToRight()"
ng-src={{imagery.getImageUrl(image)}} >
<div class="l-time">{{imagery.getTime(image)}}</div>
</div>
</div>

View File

@@ -48,8 +48,9 @@ define(
this.zone = "";
this.imageUrl = "";
this.requestCount = 0;
this.scrollable = $(".l-image-thumbs-wrapper");
this.scrollable = $(element[0]);
this.autoScroll = openmct.time.clock() ? true : false;
this.$scope.imageHistory = [];
this.$scope.filters = {
brightness: 100,
@@ -62,7 +63,6 @@ define(
this.updateHistory = this.updateHistory.bind(this);
this.onBoundsChange = this.onBoundsChange.bind(this);
this.onScroll = this.onScroll.bind(this);
this.setSelectedImage = this.setSelectedImage.bind(this);
this.subscribe(this.$scope.domainObject);
@@ -80,10 +80,10 @@ define(
var metadata = this.openmct
.telemetry
.getMetadata(this.domainObject);
this.timeKey = this.openmct.time.timeSystem().key;
var timeKey = this.openmct.time.timeSystem().key;
this.timeFormat = this.openmct
.telemetry
.getValueFormatter(metadata.value(this.timeKey));
.getValueFormatter(metadata.value(timeKey));
this.imageFormat = this.openmct
.telemetry
.getValueFormatter(metadata.valuesForHints(['image'])[0]);
@@ -161,7 +161,7 @@ define(
/**
* Updates displayable values to match those of the most
* recently received datum.
* recently recieved datum.
* @param {object} [datum] the datum
* @private
*/
@@ -170,6 +170,7 @@ define(
this.nextDatum = datum;
return;
}
this.time = this.timeFormat.format(datum);
this.imageUrl = this.imageFormat.format(datum);
@@ -184,7 +185,8 @@ define(
ImageryController.prototype.updateHistory = function (datum) {
if (this.$scope.imageHistory.length === 0 ||
!_.isEqual(this.$scope.imageHistory.slice(-1)[0], datum)) {
var index = _.sortedIndex(this.$scope.imageHistory, datum, this.timeFormat.format.bind(this.timeFormat));
var index = _.sortedIndex(this.$scope.imageHistory, datum, 'utc');
this.$scope.imageHistory.splice(index, 0, datum);
return true;
}
@@ -194,12 +196,8 @@ define(
ImageryController.prototype.onScroll = function (event) {
this.$window.requestAnimationFrame(function () {
var thumbnailWrapperHeight = this.scrollable[0].offsetHeight;
var thumbnailWrapperWidth = this.scrollable[0].offsetWidth;
if (this.scrollable[0].scrollLeft <
(this.scrollable[0].scrollWidth - this.scrollable[0].clientWidth) - (thumbnailWrapperWidth) ||
this.scrollable[0].scrollTop <
(this.scrollable[0].scrollHeight - this.scrollable[0].clientHeight) - (thumbnailWrapperHeight)) {
(this.scrollable[0].scrollWidth - this.scrollable[0].clientWidth) - 20) {
this.autoScroll = false;
} else {
this.autoScroll = true;
@@ -207,16 +205,12 @@ define(
}.bind(this));
};
/**
* Force history imagery div to scroll to bottom.
*/
ImageryController.prototype.scrollToBottom = function () {
ImageryController.prototype.scrollToRight = function () {
if (this.autoScroll) {
this.scrollable[0].scrollTop = this.scrollable[0].scrollHeight;
this.scrollable[0].scrollLeft = this.scrollable[0].scrollWidth;
}
};
/**
* Get the time portion (hours, minutes, seconds) of the
* timestamp associated with the incoming image telemetry
@@ -249,38 +243,16 @@ define(
* @returns {boolean} the current state
*/
ImageryController.prototype.paused = function (state) {
if (arguments.length > 0 && state !== this.isPaused) {
this.unselectAllImages();
this.isPaused = state;
if (this.nextDatum) {
this.updateValues(this.nextDatum);
delete this.nextDatum;
if (arguments.length > 0 && state !== this.isPaused) {
this.isPaused = state;
if (this.nextDatum) {
this.updateValues(this.nextDatum);
delete this.nextDatum;
}
}
this.autoScroll = true;
}
return this.isPaused;
};
return this.isPaused;
};
/**
* Set the selected image on the state for the large imagery div to use.
* @param {object} [image] the image object to get url from.
*/
ImageryController.prototype.setSelectedImage = function (image) {
this.imageUrl = this.getImageUrl(image);
this.time = this.getTime(image);
this.paused(true);
this.unselectAllImages();
image.selected = true;
};
/**
* Loop through the history imagery data to set all images to unselected.
*/
ImageryController.prototype.unselectAllImages = function () {
for (var i = 0; i < this.$scope.imageHistory.length; i++) {
this.$scope.imageHistory[i].selected = false;
}
};
return ImageryController;
}
);

View File

@@ -226,28 +226,6 @@ define(
expect(controller.updateHistory(mockDatum)).toBe(false);
expect(controller.updateHistory(mockDatum)).toBe(false);
});
describe("user clicks on imagery thumbnail", function () {
var mockDatum = { utc: 1434600258123, url: 'some/url', selected: false};
it("pauses and adds selected class to imagery thumbnail", function () {
controller.setSelectedImage(mockDatum);
expect(controller.paused()).toBeTruthy();
expect(mockDatum.selected).toBeTruthy();
});
it("unselects previously selected image", function () {
$scope.imageHistory = [{ utc: 1434600258123, url: 'some/url', selected: true}];
controller.unselectAllImages();
expect($scope.imageHistory[0].selected).toBeFalsy();
});
it("updates larger image url and time", function () {
controller.setSelectedImage(mockDatum);
expect(controller.getImageUrl()).toEqual(controller.getImageUrl(mockDatum));
expect(controller.getTime()).toEqual(controller.timeFormat.format(mockDatum.utc));
});
});
});
it("initially shows an empty string for date/time", function () {

View File

@@ -21,7 +21,7 @@
-->
<div
class="l-fixed-position-text l-telemetry"
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color(), 'font-size': ngModel.size() }"
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color() }"
>
<span
class="l-elem l-value l-obj-val-format"

View File

@@ -21,7 +21,7 @@
-->
<div
class="l-fixed-position-text l-static-text"
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color(), 'font-size': ngModel.size() }"
ng-style="{ background: ngModel.fill(), 'border-color': ngModel.stroke(), color: ngModel.color() }"
>
{{ngModel.element.text}}
</div>

View File

@@ -23,7 +23,7 @@
<div class="abs object-browse-bar l-flex-row">
<div class="left flex-elem l-flex-row grows">
<mct-representation
key="'object-header-frame'"
key="'object-header'"
mct-object="domainObject"
class="l-flex-row flex-elem object-header grows">
</mct-representation>

View File

@@ -26,12 +26,8 @@
* @namespace platform/features/layout
*/
define(
[
'./LayoutDrag'
],
function (
LayoutDrag
) {
['./LayoutDrag'],
function (LayoutDrag) {
var DEFAULT_DIMENSIONS = [12, 8],
DEFAULT_GRID_SIZE = [32, 32],
@@ -128,10 +124,6 @@ define(
self.select(null, self.droppedIdToSelectAfterRefresh);
delete self.droppedIdToSelectAfterRefresh;
}
if (composition.indexOf(self.selectedId) === -1) {
self.clearSelection();
}
}
});
}

View File

@@ -58,19 +58,6 @@ define(
*/
proxy.text = new AccessorMutator(element, 'text');
/**
* Get and/or set the text size of this element.
*
* @param {string} [size] the new text size (if setting)
* @returns {string} the text size
* @memberof platform/features/layout.TextProxy#
*/
proxy.size = new AccessorMutator(element, 'size');
if (proxy.size() === undefined) {
proxy.size("13px");
}
return proxy;
}

View File

@@ -424,17 +424,6 @@ define(
expect(selectedObj.showFrame).toEqual(jasmine.any(Function));
});
it("deselects the object that is no longer in the composition", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
var childObj = mockCompositionObjects[0];
controller.select(mockEvent, childObj.getId());
var composition = ["b", "c"];
mockScope.$watchCollection.mostRecentCall.args[1](composition);
expect(controller.selected(childObj)).toBe(false);
});
});
}
);

View File

@@ -35,8 +35,7 @@ define(
y: 2,
width: 42,
height: 24,
fill: "transparent",
size: "20px"
fill: "transparent"
};
testElements = [{}, {}, testElement, {}];
proxy = new TextProxy(
@@ -51,20 +50,6 @@ define(
expect(proxy.fill('#FFF')).toEqual('#FFF');
expect(proxy.fill()).toEqual('#FFF');
});
it("provides getter/setter for text size", function () {
expect(proxy.size()).toEqual('20px');
expect(proxy.size('12px')).toEqual('12px');
expect(proxy.size()).toEqual('12px');
});
it("defaults to 13px for unspecified text size", function () {
testElement = {x: 1, y: 2};
proxy = new TextProxy(testElement, 0, [testElement]);
expect(proxy.size()).toEqual('13px');
});
});
}
);

View File

@@ -118,10 +118,7 @@ define([
"policies": [
{
"category": "view",
"implementation": PlotViewPolicy,
"depends": [
"openmct"
]
"implementation": PlotViewPolicy
}
],
"representations": [

View File

@@ -30,32 +30,30 @@ define(
* @constructor
* @memberof platform/features/plot
*/
function PlotViewPolicy(openmct) {
this.openmct = openmct;
function PlotViewPolicy() {
}
PlotViewPolicy.prototype.hasNumericTelemetry = function (domainObject) {
var adaptedObject = domainObject.useCapability('adapter');
function hasNumericTelemetry(domainObject) {
var telemetry = domainObject &&
domainObject.getCapability('telemetry'),
metadata = telemetry ? telemetry.getMetadata() : {},
ranges = metadata.ranges || [];
if (!adaptedObject.telemetry) {
return domainObject.hasCapability('delegation') &&
domainObject.getCapability('delegation')
.doesDelegateCapability('telemetry');
}
var metadata = this.openmct.telemetry.getMetadata(adaptedObject);
var rangeValues = metadata.valuesForHints(['range']);
if (rangeValues.length === 0) {
return false;
}
return !rangeValues.every(function (value) {
return value.format === 'string';
});
};
// Generally, we want to allow Plot for telemetry-providing
// objects (most telemetry is plottable.) We only want to
// suppress this for telemetry which only has explicitly
// non-numeric values.
return ranges.length === 0 || ranges.some(function (range) {
// Assume format is numeric if it is undefined
// (numeric telemetry is the common case)
return range.format === undefined ||
range.format === 'number';
});
}
PlotViewPolicy.prototype.allow = function (view, domainObject) {
if (view.key === 'plot') {
return this.hasNumericTelemetry(domainObject);
return hasNumericTelemetry(domainObject);
}
return true;

View File

@@ -27,97 +27,51 @@ define(
describe("Plot view policy", function () {
var testView,
mockDomainObject,
testAdaptedObject,
openmct,
telemetryMetadata,
mockTelemetry,
testMetadata,
policy;
beforeEach(function () {
testView = { key: "plot" };
testAdaptedObject = { telemetry: {} };
testMetadata = {};
mockDomainObject = jasmine.createSpyObj(
'domainObject',
['useCapability', 'hasCapability', 'getCapability']
['getId', 'getModel', 'getCapability']
);
mockDomainObject.useCapability.andReturn(testAdaptedObject);
openmct = {
telemetry: jasmine.createSpyObj('telemetryAPI', [
'getMetadata'
])
};
telemetryMetadata = jasmine.createSpyObj('telemetryMetadata', [
'valuesForHints'
]);
telemetryMetadata.valuesForHints.andReturn([]);
openmct.telemetry.getMetadata.andReturn(telemetryMetadata);
policy = new PlotViewPolicy(openmct);
});
it('fetches metadata from telem api', function () {
policy.allow(testView, mockDomainObject);
expect(mockDomainObject.useCapability)
.toHaveBeenCalledWith('adapter');
expect(openmct.telemetry.getMetadata)
.toHaveBeenCalledWith(testAdaptedObject);
expect(telemetryMetadata.valuesForHints)
.toHaveBeenCalledWith(['range']);
});
it('returns false if no ranges exist', function () {
telemetryMetadata.valuesForHints.andReturn([]);
expect(policy.allow(testView, mockDomainObject)).toBe(false);
});
it('returns true if any ranges exist', function () {
telemetryMetadata.valuesForHints.andReturn([{}]);
expect(policy.allow(testView, mockDomainObject)).toBe(true);
});
it('returns false if all ranges are strings', function () {
telemetryMetadata.valuesForHints.andReturn([{
format: 'string'
}, {
format: 'string'
}]);
expect(policy.allow(testView, mockDomainObject)).toBe(false);
});
it('returns true if only some ranges are strings', function () {
telemetryMetadata.valuesForHints.andReturn([{
format: 'string'
}, {}]);
expect(policy.allow(testView, mockDomainObject)).toBe(true);
});
it('returns true for telemetry delegators', function () {
delete testAdaptedObject.telemetry;
mockDomainObject.hasCapability.andCallFake(function (c) {
return c === 'delegation';
mockTelemetry = jasmine.createSpyObj(
'telemetry',
['getMetadata']
);
mockDomainObject.getCapability.andCallFake(function (c) {
return c === 'telemetry' ? mockTelemetry : undefined;
});
mockDomainObject.getCapability.andReturn(
jasmine.createSpyObj('delegation', [
'doesDelegateCapability'
])
);
mockDomainObject.getCapability('delegation')
.doesDelegateCapability.andCallFake(function (c) {
return c === 'telemetry';
});
expect(policy.allow(testView, mockDomainObject)).toBe(true);
expect(openmct.telemetry.getMetadata).not.toHaveBeenCalled();
mockTelemetry.getMetadata.andReturn(testMetadata);
policy = new PlotViewPolicy();
});
it('returns true for non-telemetry non-delegators', function () {
delete testAdaptedObject.telemetry;
mockDomainObject.hasCapability.andReturn(false);
expect(policy.allow(testView, mockDomainObject)).toBe(false);
it("allows the imagery view for domain objects with numeric telemetry", function () {
testMetadata.ranges = [{ key: "foo", format: "number" }];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
it("allows the imagery view for domain objects with unspecified telemetry", function () {
testMetadata.ranges = [{ key: "foo" }];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
it("disallows the imagery view for domain objects without image telemetry", function () {
testMetadata.ranges = [{ key: "foo", format: "somethingElse" }];
expect(policy.allow(testView, mockDomainObject)).toBeFalsy();
});
it("allows other views", function () {
testView.key = "somethingElse";
expect(policy.allow(testView, mockDomainObject)).toBe(true);
testMetadata.ranges = [{ key: "foo", format: "somethingElse" }];
expect(policy.allow(testView, mockDomainObject)).toBeTruthy();
});
});
}
);

View File

@@ -47,7 +47,7 @@ define([
"name": "Export as JSON",
"implementation": ExportAsJSONAction,
"category": "contextual",
"cssClass": "icon-export",
"cssClass": "icon-save",
"depends": [
"exportService",
"policyService",
@@ -59,7 +59,7 @@ define([
"name": "Import from JSON",
"implementation": ImportAsJSONAction,
"category": "contextual",
"cssClass": "icon-import",
"cssClass": "icon-download",
"depends": [
"exportService",
"identifierService",

View File

@@ -25,12 +25,10 @@
*/
define(
[
'../../../src/api/objects/object-utils',
'lodash'
'../../../src/api/objects/object-utils'
],
function (
objectUtils,
_
objectUtils
) {
var ZERO = function () {
@@ -191,17 +189,14 @@ define(
return fullRequest;
};
function asSeries(telemetry, defaultDomain, defaultRange, sourceMap) {
function getValue(index, key) {
return telemetry[index][sourceMap[key].source];
}
function asSeries(telemetry, defaultDomain, defaultRange) {
return {
getRangeValue: function (index, range) {
return getValue(index, range || defaultRange);
return telemetry[index][range || defaultRange];
},
getDomainValue: function (index, domain) {
return getValue(index, domain || defaultDomain);
return telemetry[index][domain || defaultDomain];
},
getPointCount: function () {
return telemetry.length;
@@ -228,11 +223,9 @@ define(
var telemetryAPI = this.openmct.telemetry;
var metadata = telemetryAPI.getMetadata(domainObject);
var defaultDomain = metadata.valuesForHints(['domain'])[0].key;
var defaultDomain = metadata.valuesForHints(['domain'])[0].source;
var defaultRange = metadata.valuesForHints(['range'])[0];
defaultRange = defaultRange ? defaultRange.key : undefined;
var sourceMap = _.indexBy(metadata.values(), 'key');
defaultRange = defaultRange ? defaultRange.source : undefined;
var isLegacyProvider = telemetryAPI.findRequestProvider(domainObject) ===
telemetryAPI.legacyProvider;
@@ -257,7 +250,7 @@ define(
requestTelemetryFromService().then(getRelevantResponse);
} else {
return telemetryAPI.request(domainObject, fullRequest).then(function (telemetry) {
return asSeries(telemetry, defaultDomain, defaultRange, sourceMap);
return asSeries(telemetry, defaultDomain, defaultRange);
});
}
};
@@ -293,17 +286,15 @@ define(
var telemetryAPI = this.openmct.telemetry;
var metadata = telemetryAPI.getMetadata(domainObject);
var defaultDomain = metadata.valuesForHints(['domain'])[0].key;
var defaultDomain = metadata.valuesForHints(['domain'])[0].source;
var defaultRange = metadata.valuesForHints(['range'])[0];
defaultRange = defaultRange ? defaultRange.key : undefined;
var sourceMap = _.indexBy(metadata.values(), 'key');
defaultRange = defaultRange ? defaultRange.source : undefined;
var isLegacyProvider = telemetryAPI.findSubscriptionProvider(domainObject) ===
telemetryAPI.legacyProvider;
function update(telemetry) {
callback(asSeries([telemetry], defaultDomain, defaultRange, sourceMap));
callback(asSeries([telemetry], defaultDomain, defaultRange));
}
// Unpack the relevant telemetry series

View File

@@ -34,7 +34,6 @@ define(
mockUnsubscribe,
telemetry,
mockTelemetryAPI,
mockMetadata,
mockAPI;
function mockPromise(value) {
@@ -91,23 +90,14 @@ define(
"findRequestProvider",
"findSubscriptionProvider"
]);
mockMetadata = jasmine.createSpyObj('telemetryMetadata', [
'valuesForHints',
'values'
]);
mockMetadata.valuesForHints.andCallFake(function (hints) {
var hint = hints[0];
var metadatum = {
key: 'default' + hint
};
metadatum[hint] = "foo";
return [metadatum];
mockTelemetryAPI.getMetadata.andReturn({
valuesForHints: function (hint) {
var metadatum = {};
metadatum[hint] = "foo";
return [metadatum];
}
});
mockTelemetryAPI.getMetadata.andReturn(mockMetadata);
mockAPI = {
telemetry: mockTelemetryAPI,
time: {
@@ -160,8 +150,8 @@ define(
key: "testKey", // from model
start: 42, // from argument
domain: 'mockTimeSystem',
domains: [{ domain: "foo", key: 'defaultdomain' }],
ranges: [{ range: "foo", key: 'defaultrange' }]
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
}]);
});
@@ -182,8 +172,8 @@ define(
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo", key: 'defaultdomain' }],
ranges: [{ range: "foo", key: 'defaultrange' }]
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
});
});
@@ -201,8 +191,8 @@ define(
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo", key: 'defaultdomain' }],
ranges: [{ range: "foo", key: 'defaultrange' }]
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
});
});
@@ -250,21 +240,6 @@ define(
var mockProvider = {};
var dunzo = false;
mockMetadata.values.andReturn([
{
key: 'defaultrange',
source: 'prop1'
},
{
key: 'defaultdomain',
source: 'prop2'
},
{
key: 'prop3',
source: 'prop3'
}
]);
mockTelemetryAPI.findRequestProvider.andReturn(mockProvider);
mockTelemetryAPI.request.andReturn(Promise.resolve(mockTelemetry));
@@ -282,18 +257,6 @@ define(
expect(returnedTelemetry.getDomainValue).toBeDefined();
expect(returnedTelemetry.getRangeValue).toBeDefined();
expect(returnedTelemetry.getPointCount()).toBe(2);
// Default domain + remap should work.
expect(returnedTelemetry.getDomainValue(0)).toBe('val2');
expect(returnedTelemetry.getDomainValue(1)).toBe('val5');
// explicit domain should work
expect(returnedTelemetry.getDomainValue(0, 'prop3')).toBe('val3');
expect(returnedTelemetry.getDomainValue(1, 'prop3')).toBe('val6');
// default range + remap should work
expect(returnedTelemetry.getRangeValue(0)).toBe('val1');
expect(returnedTelemetry.getRangeValue(1)).toBe('val4');
// explicit range should work
expect(returnedTelemetry.getRangeValue(0, 'prop3')).toBe('val3');
expect(returnedTelemetry.getRangeValue(1, 'prop3')).toBe('val6');
});
});
@@ -312,8 +275,8 @@ define(
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo", key: "defaultdomain" }],
ranges: [{ range: "foo", key: "defaultrange" }]
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
}]
);

View File

@@ -106,9 +106,9 @@ define([
*
* @type {module:openmct.ViewRegistry}
* @memberof module:openmct.MCT#
* @name objectViews
* @name mainViews
*/
this.objectViews = new ViewRegistry();
this.mainViews = new ViewRegistry();
/**
* Registry for views which should appear in the Inspector area.
@@ -255,18 +255,6 @@ define([
this.legacyExtension('types', legacyDefinition);
}.bind(this));
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');
/**

7
src/about.frag Normal file
View File

@@ -0,0 +1,7 @@
/**
* Open MCT https://nasa.github.io/openmct/
* Version: ${version}
* Built: ${timestamp}
* Revision: ${revision}
* Branch: ${branch}
*/

View File

@@ -24,6 +24,7 @@ define([
'legacyRegistry',
'./actions/ActionDialogDecorator',
'./capabilities/AdapterCapability',
'./controllers/AdaptedViewController',
'./directives/MCTView',
'./services/Instantiate',
'./services/MissingModelCompatibilityDecorator',
@@ -31,11 +32,13 @@ define([
'./policies/AdapterCompositionPolicy',
'./policies/AdaptedViewPolicy',
'./runs/AlternateCompositionInitializer',
'./runs/TimeSettingsURLHandler'
'./runs/TimeSettingsURLHandler',
'text!./templates/adapted-view-template.html'
], function (
legacyRegistry,
ActionDialogDecorator,
AdapterCapability,
AdaptedViewController,
MCTView,
Instantiate,
MissingModelCompatibilityDecorator,
@@ -43,15 +46,15 @@ define([
AdapterCompositionPolicy,
AdaptedViewPolicy,
AlternateCompositionInitializer,
TimeSettingsURLHandler
TimeSettingsURLHandler,
adaptedViewTemplate
) {
legacyRegistry.register('src/adapter', {
"extensions": {
"directives": [
{
key: "mctView",
implementation: MCTView,
depends: ["openmct"]
implementation: MCTView
}
],
capabilities: [
@@ -60,6 +63,16 @@ define([
implementation: AdapterCapability
}
],
controllers: [
{
key: "AdaptedViewController",
implementation: AdaptedViewController,
depends: [
'$scope',
'openmct'
]
}
],
services: [
{
key: "instantiate",
@@ -122,6 +135,12 @@ define([
depends: ["openmct", "$location", "$rootScope"]
}
],
views: [
{
key: "adapted-view",
template: adaptedViewTemplate
}
],
licenses: [
{
"name": "almond",

View File

@@ -22,12 +22,10 @@
define([
'./synchronizeMutationCapability',
'./AlternateCompositionCapability',
'./patchViewCapability'
'./AlternateCompositionCapability'
], function (
synchronizeMutationCapability,
AlternateCompositionCapability,
patchViewCapability
AlternateCompositionCapability
) {
/**
@@ -48,9 +46,6 @@ define([
capabilities.mutation =
synchronizeMutationCapability(capabilities.mutation);
}
if (capabilities.view) {
capabilities.view = patchViewCapability(capabilities.view);
}
if (AlternateCompositionCapability.appliesTo(model, id)) {
capabilities.composition = function (domainObject) {
return new AlternateCompositionCapability(this.$injector, domainObject);

View File

@@ -20,31 +20,21 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
'./plugin'
], function (plugin) {
describe("The buildInfo plugin", function () {
var mockmct;
var testInfo;
define([], function () {
function AdaptedViewController($scope, openmct) {
function refresh(legacyObject) {
if (!legacyObject) {
$scope.view = undefined;
return;
}
beforeEach(function () {
mockmct = jasmine.createSpyObj('openmct', ['legacyExtension']);
testInfo = { foo: 123, bar: "baz" };
plugin(testInfo)(mockmct);
});
var domainObject = legacyObject.useCapability('adapter');
var providers = openmct.mainViews.get(domainObject);
$scope.view = providers[0] && providers[0].view(domainObject);
}
it("registers versions extensions", function () {
Object.keys(testInfo).forEach(function (key) {
expect(mockmct.legacyExtension).toHaveBeenCalledWith(
"versions",
{
key: key,
name: jasmine.any(String),
value: testInfo[key],
description: undefined
}
);
});
});
});
$scope.$watch('domainObject', refresh);
}
return AdaptedViewController;
});

View File

@@ -21,23 +21,18 @@
*****************************************************************************/
define([
'angular',
'./Region'
], function (
angular,
Region
) {
function MCTView(openmct) {
function MCTView() {
return {
restrict: 'E',
restrict: 'A',
link: function (scope, element, attrs) {
var provider = openmct.objectViews.getByProviderKey(attrs.mctProviderKey);
var view = new provider.view(scope.domainObject.useCapability('adapter'));
var domElement = element[0];
view.show(domElement);
if (view.destroy) {
scope.$on('$destroy', function () {
view.destroy(domElement);
});
}
var region = new Region(element[0]);
scope.$watch(attrs.mctView, region.show.bind(region));
}
};
}

View File

@@ -20,41 +20,26 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
'lodash'
], function (
_
) {
function patchViewCapability(viewConstructor) {
return function makeCapability(domainObject) {
var capability = viewConstructor(domainObject);
var oldInvoke = capability.invoke.bind(capability);
capability.invoke = function () {
var availableViews = oldInvoke();
var newDomainObject = capability
.domainObject
.useCapability('adapter');
return _(availableViews).map(function (v, i) {
var vd = {
view: v,
priority: i + 100 // arbitrary to allow new views to
// be defaults by returning priority less than 100.
};
if (v.provider && v.provider.priority) {
vd.priority = v.provider.priority(newDomainObject);
}
return vd;
})
.sortBy('priority')
.map('view')
.value();
};
return capability;
};
define([], function () {
function Region(element) {
this.activeView = undefined;
this.element = element;
}
return patchViewCapability;
Region.prototype.clear = function () {
if (this.activeView) {
this.activeView.destroy();
this.activeView = undefined;
}
};
Region.prototype.show = function (view) {
this.clear();
this.activeView = view;
if (this.activeView) {
this.activeView.show(this.element);
}
};
return Region;
});

View File

@@ -29,9 +29,9 @@ define([], function () {
view,
legacyObject
) {
if (view.hasOwnProperty('provider')) {
if (view.key === 'adapted-view') {
var domainObject = legacyObject.useCapability('adapter');
return view.provider.canView(domainObject);
return this.openmct.mainViews.get(domainObject).length > 0;
}
return true;
};

View File

@@ -1,45 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web 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 Web 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 (
) {
return function (buildInfo) {
return function (openmct) {
var aliases = { timestamp: "Built" };
var descriptions = {
timestamp: "The date on which this version of Open MCT was built.",
revision: "A unique revision identifier for the client sources.",
branch: "The name of the branch that was used during the build."
};
Object.keys(buildInfo).forEach(function (key) {
openmct.legacyExtension("versions", {
key: key,
name: aliases[key] || (key.charAt(0).toUpperCase() + key.substring(1)),
value: buildInfo[key],
description: descriptions[key]
});
});
};
};
});

View File

@@ -37,7 +37,8 @@ define(['EventEmitter'], function (EventEmitter) {
this.key = 'local';
this.cssClass = 'icon-clock';
this.name = 'Local Clock';
this.description = "Provides UTC timestamps every second from the local system clock.";
this.description = "Updates every second, providing UTC timestamps from " +
"user's local computer.";
this.period = period;
this.timeoutHandle = undefined;

View File

@@ -18,14 +18,6 @@
* 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.
*
* Open MCT https://nasa.github.io/openmct/
* Version: @@version
* Built: @@timestamp
* Revision: @@revision
* Branch: @@branch
*
* @preserve
*****************************************************************************/
(function (root, factory) {
@@ -37,9 +29,3 @@
root.openmct = factory();
}
}(this, function() {
var BUILD_CONSTANTS = {
version: "@@version",
timestamp: "@@timestamp",
revision: "@@revision",
branch: "@@branch"
};

View File

@@ -19,7 +19,6 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global console */
define([], function () {
/**
@@ -29,7 +28,7 @@ define([], function () {
* @memberof module:openmct
*/
function ViewRegistry() {
this.providers = {};
this.providers = [];
}
@@ -40,17 +39,9 @@ define([], function () {
* which can provide views of this object
*/
ViewRegistry.prototype.get = function (item) {
return this.getAllProviders()
.filter(function (provider) {
return provider.canView(item);
});
};
/**
* @private
*/
ViewRegistry.prototype.getAllProviders = function () {
return Object.values(this.providers);
return this.providers.filter(function (provider) {
return provider.canView(item);
});
};
/**
@@ -61,22 +52,7 @@ define([], function () {
* @memberof module:openmct.ViewRegistry#
*/
ViewRegistry.prototype.addProvider = function (provider) {
var key = provider.key;
if (key === undefined) {
throw "View providers must have a unique 'key' property defined";
}
if (this.providers[key] !== undefined) {
console.warn("Provider already defined for key '%s'. Provider keys must be unique.", key);
}
this.providers[key] = provider;
};
/**
* @private
*/
ViewRegistry.prototype.getByProviderKey = function (key) {
return this.providers[key];
this.providers.push(provider);
};
/**
@@ -115,12 +91,6 @@ define([], function () {
* Exposes types of views in Open MCT.
*
* @interface ViewProvider
* @property {string} key a unique identifier for this view
* @property {string} name the human-readable name of this view
* @property {string} [description] a longer-form description (typically
* a single sentence or short paragraph) of this kind of view
* @property {string} [cssClass] the CSS class to apply to labels for this
* view (to add icons, for instance)
* @memberof module:openmct
*/
@@ -130,28 +100,15 @@ define([], function () {
* When called by Open MCT, this may include additional arguments
* which are on the path to the object to be viewed; for instance,
* when viewing "A Folder" within "My Items", this method will be
* invoked with "A Folder" (as a domain object) as the first argument
* invoked with "A Folder" (as a domain object) as the first argument,
* and "My Items" as the second argument.
*
* @method canView
* @memberof module:openmct.ViewProvider#
* @param {module:openmct.DomainObject} domainObject the domain object
* to be viewed
* @returns {boolean} 'true' if the view applies to the provided object,
* otherwise 'false'.
*/
/**
* Optional method determining the priority of a given view. If this
* function is not defined on a view provider, then a default priority
* of 100 will be applicable for all objects supported by this view.
*
* @method priority
* @memberof module:openmct.ViewProvider#
* @param {module:openmct.DomainObject} domainObject the domain object
* to be viewed
* @returns {number} The priority of the view. If multiple views could apply
* to an object, the view that returns the lowest number will be
* the default view.
* @returns {boolean} true if this domain object can be viewed using
* this provider
*/
/**
@@ -169,6 +126,27 @@ define([], function () {
* @returns {module:openmct.View} a view of this domain object
*/
/**
* Get metadata associated with this view provider. This may be used
* to populate the user interface with options associated with this
* view provider.
*
* @method metadata
* @memberof module:openmct.ViewProvider#
* @returns {module:openmct.ViewProvider~ViewMetadata} view metadata
*/
/**
* @typedef ViewMetadata
* @memberof module:openmct.ViewProvider~
* @property {string} name the human-readable name of this view
* @property {string} key a machine-readable name for this view
* @property {string} [description] a longer-form description (typically
* a single sentence or short paragraph) of this kind of view
* @property {string} cssClass the CSS class to apply to labels for this
* view (to add icons, for instance)
*/
return ViewRegistry;
});