mirror of
https://github.com/nasa/openmct.git
synced 2025-05-09 12:03:21 +00:00
Notebook integration deep (#1947)
* NASA - OPEN MCT NOTEBOOK UI PROTOTYPE CHALLENGE https://www.topcoder.com/challenge-details/30059614/ Initial submission * Code updates: -Topcoder final fixes -NASA review fixes * drag and drop style fix, new entry focus, delete display fix * NASA reported issues fixed: objects saved in notebook, delete entry dialog, style files, and new entry from drag objects fixed. * Annotation toolbar UI style fixes, added annotation functionality on new entry dialog * painterro .map file issue fixed. * NASA review fixes: css files adjusted notebook children tree removed embed's title links to live object * CouchDB documentation added * CouchDB documentation added Screenshots added. * CouchDB setup documentation added * Test case functional and cosmetic issues fixed. * Test cases functional and cosmetic issues fixed. * updated file saver library * Code issues fixes: NotificationLaunchIndicator deleted. Inappropriate modifications to domain object models fixed. Implemented $destroy listener on entryDnd directive. Naming conventions fixed. Unnecessary changes made to platform handled. Painterro dependency handled gulp verify fix. * names and package fixes * filenames fix * [Notebook] Relocate to platform/features/notebook * [Notebook] Remove obsolete README * [Notebook] Restore original index.html * [Notebook] Expose via openmct.plugins * [Notebook] Remove demo entries * [Notebook] Run gulp fixstyle * [Notebook] Use dot notation instead of brackets ...for checkstyle * [Notebook] Remove extra comma * [Notebook] Run gulp fixstyle * [Notebook] Use dot notation instead of brackets ...for checkstyle * [Notebook] Fix lint issues * [Notebook] Fix lint issues * [Notebook] Fix lint issues * [Notebook] Fix lint issues * [Notebook] Fix lint issues * [Notebook] Fix lint issues * [Notebook] Fix lint issues * [Notebook] Fix lint issues * [Notebook] Fix lint issues * [Notebook] Run gulp fixstyle * [Notebook] Include painterro for tests * [Notebook] Fix require config for painterro * [Merge] WIP markup and styling Fixes #1896 - Very much WIP, currently having issues with hovering and jiggling * [Merge] WIP markup and styling Fixes #1896 - Very much WIP, attempting to convert textarea to contenteditable; * [Merge] JS debugging Fixes #1896 - Very much WIP! * [Merge] JS debugging Fixes #1896 - Really, really WIP - DnD doesn't work properly, and drag to existing entry no longer works. * [Front-end] Notebook thematic styling; test console Fixes #1896 - Added thematic styles and config; - Really, really, really WIP!! - DnD doesn't work properly, and drag to existing entry no longer works. * [Merge] Cleanups in JS Fixes #1896 - Removed and commented out logging statements * [Merge] WIP SCSS and markup polishing Fixes #1896 - Significant style and markup changes; - Styles, layout, etc. relating to embed elements; - Fixes in both notebook.html and embedControl.html; - Class name normalization; * [Merge] WIP Mods related to MCTModalNotebook.js Fixes #1896 Fixes #1906 * fix drag and drop, delete entries * [Front-end] Refined styling of entry embeds Fixes #1896 * [Merge] Generalized hover hide/show of local controls Fixes #1896 * [Merge] Generalized labeled icon-* elements Fixes #1896 * [Frontend] CSS normalizing, apply general styles in markup Fixes #1896 - Notebook class names more individualized; - Apply .labeled and .has-local-controls general classes; - Apply .s-input-inline to contenteditable div; - Look and feel cleanups for drag area and entry elements; * added modifiedOn time for entries that are changed, and fixed issue regarding inner text being filled when new entry button clicked * [Frontend] CSS sanding and cleanups Fixes #1896 - Removing unused classes; - Finessed margin and padding; * [Frontend] Mobile styling Fixes #1896 - Mod .has-local-controls to not apply when in touch context * [Frontend] WIP Mobile styling Fixes #1896 - phone portrait entry layout optimization * fix expand in layout, which was causing snapshot at expand * [Frontend] Fixes to search control Fixes #1896 - Search control now more robust, added .search-filter-by-type class selector; * [Frontend] Fix custom Selects Fixes #1896 - Custom Selects now much more solid, handle width compression better; * remove duplicate code from MCTModalNotebook and roll changes into MCTTriggerModal * [Frontend] WIP Mobile styling Fixes #1896 - Fixed general approach to portrait orientation in mobile/_layout.scss to use media query; - Fixed portrait layout in _notebook_base.scss to use media query; * prevent multiple new notebook entry divs from being created on open overlay, instead create on initialization * [Frontend] WIP Snapshot styling Fixes #1896 - Better class names; - Moved buttons in frame layout; * remove frame layout duplicate and use frame.html * fix issue of preserving line breaks when text is received from a persisted source * add comments, clean out some code, and fix broken tests * fix export image after merging with master * include painterro in karma config * Inlined templates for notebook * disable view policy - to allow layouts to function - needs more investigation * fix layout display overload, remove viewpolicy and notebookLayout.html. Fix delete error - issues found when deploying for testathon * fix (not being able to focus on content editable div to add text, while in layout) - when in layout, the first child of the outermost div is the only one that registers a click, this was causing an issue of not being able to edit notebook entries. My fix includes finding the first child of the div that registers the click and forcing a focus event. * fix focus one new entry issue, cleanup of code related to finding elements, and write more reusable code * abstract findElementById for reusability and improve performance from O^2 to O * user findElementById in entrydnd * change snapshot library to dom-to-image * [Frontend] WIP Snapshot styling Fixes #1896 Fixes #1947 - Significant markup changes to template in ViewSnaphot.js - WIP!!! Keeping own topic branch for now * [Frontend] WIP Snapshot styling Fixes #1896 Fixes #1947 - Significant markup changes to ViewSnaphot.js; - Change in imagery.scss to move non-layout styling to appropriate class; * Removed snapshot from version number to close sprint eagle * Updated version number for Enterprise release * Lock filesaver version (#1956) Lock filesaver version as there have been a large number of broken builds from what should be non-breaking version increases. Fixes currently broken build. * [Frontend] Snapshot styling Fixes #1896 Fixes #1947 - Final tweaks after rebase from notebook-integration-deep-styling * fixes issue of overlay not closing when context menu item in clicked when viewing snapshot * [Frontend] Painterro styling Fixes #1896 Fixes #1947 - WIP - Painterro styling overrides and config - Removed commented code * [Frontend] Painterro styling Fixes #1896 Fixes #1947 - WIP - Painterro styling overrides and config * fixes issue of overlay not closing when context menu item in clicked when viewing snapshot * specify require paths for new library * [Frontend] Local controls CSS added for hide/show of trash can icons Fixes #1896 Fixes #1947 - Also updated frame.scss to use same transition timing * proper shimming * dragging objects to notebook now only creates a link, clicking on snapshot from object view takes a snapshot of the current view, without re-rendering * [Frontend] Local controls CSS added for hide/show of trash can icons Fixes #1896 Fixes #1947 - Also updated frame.scss to use same transition timing * select correct div for snapshot * [Frontend] Adding background color to snapshot Fixes #1896 Fixes #1947 * remove snapshot class after async image render * [Frontend] Adding background color to snapshot Fixes #1896 Fixes #1947 * remove snapshot button from frames in layout * remove snapshot from frame view, add it only to overlay, change mctSnapShot to accomodate taking snaps of overlay/object view * add preview action, working, need styling for notebook action on preview * fix checkstyle * change glyph for preview, use similar tempalte to frame.html * dont allow preview action on objects getting edited currently * changes to browseController and NavigationService to block navigation and show preview of object when trying to navigate to object in tree in edit mode * [Frontend] Painterro styling and config Fixes #1896 Fixes #1947 - Changes mainly related to toolbar styling and labels * [Frontend] Notebook/Preview related sanding and polishing Fixes #1947 - Changed description for notebook-new-entry * [Frontend] Notebook/Preview related sanding and polishing Fixes #1947 - Added new global "hide-in-t-main-view" class; - Apply new class to Preview action to suppress display of that button in main view of navigated object; * code cleanup * [Frontend] Notebook/Preview related sanding and polishing Fixes #1947 - Classes for Notebook Entry button spacing; * abstract overlay into a service/api - to reduce code duplication catch error produced by painterro because of async div creation by dialog service * fix broken mcttriggermodal tests * fix checkstyle and lint * add functionality of being able to add buttons to the browse bar element of overlay when instantiating the overlay service * Reduce frequency of template recompilation in mct-include * Use updated painterro library. Fixes #1981 * add save flag and call done in both cases (clicking on cancel or ok) * fixes #1951 persist modified empty entry on blur * Bump Node Version * fix checkstyle * fixes issue where annotating snapshot that is already saved in notebook does not work * fix painterro button styling issue move jquery logic inside timeout block, because buttons are asynchronously created * remove description required when saving snapshot to notebook * remove create snapshot action from embeds, and add preview action to embeds * fixes edge case for issue #1981 Add a reject callback in the edgecase that user presses the x icon or esc key to cancel annotation, which was leading to the drag drop issue * Add default sort options on creation menu of Notebook * fix auto focus on new entry when in oldest first order, both in layout and regular view * [Frontend] Notebook mobile mods - Hide entry area when mobile; - Disallow entry edit or delete in mobile; * fixes issue 2041 (#2049) * fixes issue 2041 allows user to select caret position in notebook entries while in layout * [Frontend] Restore class, refine selector Fixes #2041 Fixes #2049 - Restored .s-input-inline to editable field; - Refined pointer-events: none to properly target .title-label only; * remove unused files/code and smoke test * remove , add pre-wrap to css and use inner text * make reviewer requested changes 'in progress still' * make reviewer requested changes 'continued' * replace html2canvas with dom-to-image - add in progress dialog to export image service - add error dialog to export image service * Search UI refactored to use flex Fixes #1947 - Fixes broken search inputs in main search and Notebook; - Significant rewrite to search SCSS and markup; * Fixes for Notebook custom selects; polishes to search Fixes #1947 - Better flex styles for custom selects; - Refinements to search styling; - Much better mobile responsive layout for search and controls in portrait layout; * fix preview action for embeds, which was showing current domain object vs selected domain object * Fixed hidden search dropdown menu Fixes #1947 * Revert whitespace change Revert change to whitespace in index.html. #1947. * [Export] Use html2canvas Use html2canvas instead of dom-to-image. Fixes issues with text exports. html2canvas is better supported and under active development and is a better choice for this library. Cleaned up export code, ensure that images are properly saved as the correct types. related to feedback on #1947 * Don't show brackets when timestamp is not specified (#331)
This commit is contained in:
parent
73e38f1955
commit
90a6bbc13e
@ -22,7 +22,6 @@
|
|||||||
"eventemitter3": "^1.2.0",
|
"eventemitter3": "^1.2.0",
|
||||||
"lodash": "3.10.1",
|
"lodash": "3.10.1",
|
||||||
"almond": "~0.3.2",
|
"almond": "~0.3.2",
|
||||||
"html2canvas": "^0.4.1",
|
|
||||||
"moment-timezone": "^0.5.13"
|
"moment-timezone": "^0.5.13"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -69,6 +69,7 @@
|
|||||||
]
|
]
|
||||||
}));
|
}));
|
||||||
openmct.install(openmct.plugins.SummaryWidget());
|
openmct.install(openmct.plugins.SummaryWidget());
|
||||||
|
openmct.install(openmct.plugins.Notebook());
|
||||||
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
|
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
|
||||||
openmct.time.timeSystem('utc');
|
openmct.time.timeSystem('utc');
|
||||||
openmct.start();
|
openmct.start();
|
||||||
|
@ -38,6 +38,8 @@ module.exports = function(config) {
|
|||||||
{pattern: 'node_modules/d3-*/**/*.js', included: false},
|
{pattern: 'node_modules/d3-*/**/*.js', included: false},
|
||||||
{pattern: 'node_modules/vue/**/*.js', included: false},
|
{pattern: 'node_modules/vue/**/*.js', included: false},
|
||||||
{pattern: 'src/**/*', included: false},
|
{pattern: 'src/**/*', included: false},
|
||||||
|
{pattern: 'node_modules/painterro/build/*.js', included: false},
|
||||||
|
{pattern: 'node_modules/html2canvas/dist/*', included: false},
|
||||||
{pattern: 'example/**/*.html', included: false},
|
{pattern: 'example/**/*.html', included: false},
|
||||||
{pattern: 'example/**/*.js', included: false},
|
{pattern: 'example/**/*.js', included: false},
|
||||||
{pattern: 'example/**/*.json', included: false},
|
{pattern: 'example/**/*.json', included: false},
|
||||||
|
14
openmct.js
14
openmct.js
@ -29,7 +29,6 @@ requirejs.config({
|
|||||||
"csv": "bower_components/comma-separated-values/csv.min",
|
"csv": "bower_components/comma-separated-values/csv.min",
|
||||||
"EventEmitter": "bower_components/eventemitter3/index",
|
"EventEmitter": "bower_components/eventemitter3/index",
|
||||||
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
||||||
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
|
|
||||||
"moment": "bower_components/moment/moment",
|
"moment": "bower_components/moment/moment",
|
||||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||||
"moment-timezone": "bower_components/moment-timezone/builds/moment-timezone-with-data",
|
"moment-timezone": "bower_components/moment-timezone/builds/moment-timezone-with-data",
|
||||||
@ -49,7 +48,9 @@ requirejs.config({
|
|||||||
"d3-format": "node_modules/d3-format/build/d3-format.min",
|
"d3-format": "node_modules/d3-format/build/d3-format.min",
|
||||||
"d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
|
"d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
|
||||||
"d3-time": "node_modules/d3-time/build/d3-time.min",
|
"d3-time": "node_modules/d3-time/build/d3-time.min",
|
||||||
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
|
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min",
|
||||||
|
"html2canvas": "node_modules/html2canvas/dist/html2canvas.min",
|
||||||
|
"painterro": "node_modules/painterro/build/painterro.min"
|
||||||
},
|
},
|
||||||
"shim": {
|
"shim": {
|
||||||
"angular": {
|
"angular": {
|
||||||
@ -61,12 +62,12 @@ requirejs.config({
|
|||||||
"EventEmitter": {
|
"EventEmitter": {
|
||||||
"exports": "EventEmitter"
|
"exports": "EventEmitter"
|
||||||
},
|
},
|
||||||
"html2canvas": {
|
|
||||||
"exports": "html2canvas"
|
|
||||||
},
|
|
||||||
"moment-duration-format": {
|
"moment-duration-format": {
|
||||||
"deps": ["moment"]
|
"deps": ["moment"]
|
||||||
},
|
},
|
||||||
|
"painterro": {
|
||||||
|
"exports": "Painterro"
|
||||||
|
},
|
||||||
"saveAs": {
|
"saveAs": {
|
||||||
"exports": "saveAs"
|
"exports": "saveAs"
|
||||||
},
|
},
|
||||||
@ -88,6 +89,9 @@ requirejs.config({
|
|||||||
},
|
},
|
||||||
"d3-axis": {
|
"d3-axis": {
|
||||||
"exports": "d3-axis"
|
"exports": "d3-axis"
|
||||||
|
},
|
||||||
|
"dom-to-image": {
|
||||||
|
"exports": "domtoimage"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
"d3-time-format": "2.1.x",
|
"d3-time-format": "2.1.x",
|
||||||
"express": "^4.13.1",
|
"express": "^4.13.1",
|
||||||
"minimist": "^1.1.1",
|
"minimist": "^1.1.1",
|
||||||
|
"painterro": "^0.2.65",
|
||||||
"request": "^2.69.0",
|
"request": "^2.69.0",
|
||||||
"vue": "^2.5.6"
|
"vue": "^2.5.6"
|
||||||
},
|
},
|
||||||
@ -30,6 +31,7 @@
|
|||||||
"gulp-requirejs-optimize": "^0.3.1",
|
"gulp-requirejs-optimize": "^0.3.1",
|
||||||
"gulp-sass": "^3.1.0",
|
"gulp-sass": "^3.1.0",
|
||||||
"gulp-sourcemaps": "^1.6.0",
|
"gulp-sourcemaps": "^1.6.0",
|
||||||
|
"html2canvas": "^1.0.0-alpha.12",
|
||||||
"jasmine-core": "^2.3.0",
|
"jasmine-core": "^2.3.0",
|
||||||
"jscs-html-reporter": "^0.1.0",
|
"jscs-html-reporter": "^0.1.0",
|
||||||
"jsdoc": "^3.3.2",
|
"jsdoc": "^3.3.2",
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
<div class='split-pane-component t-object pane primary-pane left'>
|
<div class='split-pane-component t-object pane primary-pane left'>
|
||||||
<mct-representation mct-object="navigatedObject"
|
<mct-representation mct-object="navigatedObject"
|
||||||
key="navigatedObject.getCapability('status').get('editing') ? 'edit-object' : 'browse-object'"
|
key="navigatedObject.getCapability('status').get('editing') ? 'edit-object' : 'browse-object'"
|
||||||
class="abs holder holder-object">
|
class="abs holder holder-object t-main-view">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
<a class="mini-tab-icon anchor-right mobile-hide toggle-pane toggle-inspect flush-right"
|
<a class="mini-tab-icon anchor-right mobile-hide toggle-pane toggle-inspect flush-right"
|
||||||
title="{{ modelPaneInspect.visible()? 'Hide' : 'Show' }} the Inspection pane"
|
title="{{ modelPaneInspect.visible()? 'Hide' : 'Show' }} the Inspection pane"
|
||||||
|
@ -47,8 +47,8 @@ define(
|
|||||||
urlService,
|
urlService,
|
||||||
defaultPath
|
defaultPath
|
||||||
) {
|
) {
|
||||||
var initialPath = ($route.current.params.ids || defaultPath).split("/");
|
var initialPath = ($route.current.params.ids || defaultPath).split("/"),
|
||||||
var currentIds;
|
currentIds;
|
||||||
|
|
||||||
$scope.treeModel = {
|
$scope.treeModel = {
|
||||||
selectedObject: undefined,
|
selectedObject: undefined,
|
||||||
@ -56,7 +56,24 @@ define(
|
|||||||
navigationService.setNavigation(object, true);
|
navigationService.setNavigation(object, true);
|
||||||
},
|
},
|
||||||
allowSelection: function (object) {
|
allowSelection: function (object) {
|
||||||
return navigationService.shouldNavigate();
|
var domainObjectInView = navigationService.getNavigation(),
|
||||||
|
isInEditMode = domainObjectInView.getCapability('status').get('editing');
|
||||||
|
|
||||||
|
if (isInEditMode) {
|
||||||
|
|
||||||
|
var actions = object.getCapability('action'),
|
||||||
|
previewAction = actions.getActions({key: 'mct-preview-action'})[0];
|
||||||
|
|
||||||
|
if (previewAction && previewAction.perform) {
|
||||||
|
previewAction.perform();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return navigationService.shouldNavigate();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -162,7 +162,6 @@ define(
|
|||||||
*/
|
*/
|
||||||
NavigationService.prototype.shouldWarnBeforeNavigate = function () {
|
NavigationService.prototype.shouldWarnBeforeNavigate = function () {
|
||||||
var reasons = [];
|
var reasons = [];
|
||||||
|
|
||||||
this.checks.forEach(function (checkFn) {
|
this.checks.forEach(function (checkFn) {
|
||||||
var reason = checkFn();
|
var reason = checkFn();
|
||||||
if (reason) {
|
if (reason) {
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
<div class="top-bar">
|
<div class="top-bar">
|
||||||
<div class="title">{{ngModel.title}}</div>
|
<div class="title">{{ngModel.title}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint + " [" + ngModel.timestamp + "]"}}</div>
|
<div class="hint" ng-hide="ngModel.hint === undefined">
|
||||||
|
{{ngModel.hint}}
|
||||||
|
<span ng-if="ngModel.timestamp !== undefined">[{{ngModel.timestamp}}]</span>
|
||||||
|
</div>
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
<div class="message-action">
|
<div class="message-action">
|
||||||
{{ngModel.actionText}}
|
{{ngModel.actionText}}
|
||||||
|
@ -49,6 +49,8 @@ define([
|
|||||||
"./src/directives/MCTSplitPane",
|
"./src/directives/MCTSplitPane",
|
||||||
"./src/directives/MCTSplitter",
|
"./src/directives/MCTSplitter",
|
||||||
"./src/directives/MCTTree",
|
"./src/directives/MCTTree",
|
||||||
|
"./src/directives/MCTPreview",
|
||||||
|
"./src/actions/MCTPreviewAction",
|
||||||
"./src/filters/ReverseFilter",
|
"./src/filters/ReverseFilter",
|
||||||
"text!./res/templates/bottombar.html",
|
"text!./res/templates/bottombar.html",
|
||||||
"text!./res/templates/controls/action-button.html",
|
"text!./res/templates/controls/action-button.html",
|
||||||
@ -69,6 +71,7 @@ define([
|
|||||||
"text!./res/templates/controls/selector.html",
|
"text!./res/templates/controls/selector.html",
|
||||||
"text!./res/templates/controls/datetime-picker.html",
|
"text!./res/templates/controls/datetime-picker.html",
|
||||||
"text!./res/templates/controls/datetime-field.html",
|
"text!./res/templates/controls/datetime-field.html",
|
||||||
|
"text!./res/templates/preview.html",
|
||||||
'legacyRegistry'
|
'legacyRegistry'
|
||||||
], function (
|
], function (
|
||||||
UrlService,
|
UrlService,
|
||||||
@ -99,6 +102,8 @@ define([
|
|||||||
MCTSplitPane,
|
MCTSplitPane,
|
||||||
MCTSplitter,
|
MCTSplitter,
|
||||||
MCTTree,
|
MCTTree,
|
||||||
|
MCTPreview,
|
||||||
|
MCTPreviewAction,
|
||||||
ReverseFilter,
|
ReverseFilter,
|
||||||
bottombarTemplate,
|
bottombarTemplate,
|
||||||
actionButtonTemplate,
|
actionButtonTemplate,
|
||||||
@ -119,6 +124,7 @@ define([
|
|||||||
selectorTemplate,
|
selectorTemplate,
|
||||||
datetimePickerTemplate,
|
datetimePickerTemplate,
|
||||||
datetimeFieldTemplate,
|
datetimeFieldTemplate,
|
||||||
|
previewTemplate,
|
||||||
legacyRegistry
|
legacyRegistry
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -396,6 +402,31 @@ define([
|
|||||||
"key": "mctTree",
|
"key": "mctTree",
|
||||||
"implementation": MCTTree,
|
"implementation": MCTTree,
|
||||||
"depends": ['gestureService']
|
"depends": ['gestureService']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "mctPreview",
|
||||||
|
"implementation": MCTPreview,
|
||||||
|
"depends": [
|
||||||
|
"$document"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"key": "mct-preview-action",
|
||||||
|
"implementation": MCTPreviewAction,
|
||||||
|
"name": "Preview",
|
||||||
|
"cssClass": "hide-in-t-main-view icon-eye-open",
|
||||||
|
"description": "Preview in large dialog",
|
||||||
|
"category": [
|
||||||
|
"contextual",
|
||||||
|
"view-control"
|
||||||
|
],
|
||||||
|
"depends": [
|
||||||
|
"$compile",
|
||||||
|
"$rootScope"
|
||||||
|
],
|
||||||
|
"priority": "preferred"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"constants": [
|
"constants": [
|
||||||
@ -511,6 +542,10 @@ define([
|
|||||||
{
|
{
|
||||||
"key": "object-inspector",
|
"key": "object-inspector",
|
||||||
"template": objectInspectorTemplate
|
"template": objectInspectorTemplate
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "mct-preview",
|
||||||
|
"template": previewTemplate
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"controls": [
|
"controls": [
|
||||||
|
@ -225,7 +225,8 @@ a.disabled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hide,
|
.hide,
|
||||||
.hidden {
|
.hidden,
|
||||||
|
.t-main-view .hide-in-t-main-view {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[class*="icon-"].labeled {
|
||||||
|
// Moved from .s-button and generalized
|
||||||
|
&:before {
|
||||||
|
// Fend off label from icon when it's included
|
||||||
|
margin-right: $interiorMarginSm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/************************** CHAR UNICODES */
|
/************************** CHAR UNICODES */
|
||||||
|
|
||||||
$glyph-icon-alert-rect: '\e900';
|
$glyph-icon-alert-rect: '\e900';
|
||||||
|
@ -299,7 +299,7 @@
|
|||||||
color: $ic;
|
color: $ic;
|
||||||
}
|
}
|
||||||
@if $bgHov != none {
|
@if $bgHov != none {
|
||||||
&:not(.disabled):hover {
|
&:not([disabled="true"]):not(.disabled):hover {
|
||||||
background: $bgHov;
|
background: $bgHov;
|
||||||
color: $fgHov;
|
color: $fgHov;
|
||||||
>.icon,
|
>.icon,
|
||||||
|
@ -270,37 +270,4 @@
|
|||||||
@extend .s-summary-widget;
|
@extend .s-summary-widget;
|
||||||
@extend .l-summary-widget;
|
@extend .l-summary-widget;
|
||||||
padding: $interiorMarginSm $interiorMargin;
|
padding: $interiorMarginSm $interiorMargin;
|
||||||
}
|
|
||||||
|
|
||||||
// Hide and show elements in the rule-header on hover
|
|
||||||
.l-widget-rule,
|
|
||||||
.l-widget-test-data-item {
|
|
||||||
.grippy,
|
|
||||||
.l-rule-action-buttons-wrapper,
|
|
||||||
.l-condition-action-buttons-wrapper,
|
|
||||||
.l-widget-test-data-item-action-buttons-wrapper {
|
|
||||||
@include trans-prop-nice($props: opacity, $dur: 500ms);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
.grippy,
|
|
||||||
.l-rule-action-buttons-wrapper,
|
|
||||||
.l-widget-test-data-item-action-buttons-wrapper {
|
|
||||||
@include trans-prop-nice($props: opacity, $dur: 0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.l-rule-action-buttons-wrapper {
|
|
||||||
.t-delete {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.t-condition {
|
|
||||||
&:hover {
|
|
||||||
.l-condition-action-buttons-wrapper {
|
|
||||||
@include trans-prop-nice($props: opacity, $dur: 0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -34,11 +34,6 @@ $pad: $interiorMargin * $baseRatio;
|
|||||||
line-height: $btnStdH;
|
line-height: $btnStdH;
|
||||||
padding: 0 $pad;
|
padding: 0 $pad;
|
||||||
|
|
||||||
&.labeled:before {
|
|
||||||
// Icon when it's included
|
|
||||||
margin-right: $interiorMarginSm;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.lg {
|
&.lg {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
@ -59,6 +54,10 @@ $pad: $interiorMargin * $baseRatio;
|
|||||||
.label, .title-label { display: none; }
|
.label, .title-label { display: none; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&[disabled="true"] {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
&.pause-play {
|
&.pause-play {
|
||||||
@extend .icon-pause;
|
@extend .icon-pause;
|
||||||
&.paused {
|
&.paused {
|
||||||
|
@ -139,7 +139,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.s-local-controls {
|
.s-local-controls {
|
||||||
@include trans-prop-nice(opacity);
|
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
&.s-wrapper-transluc {
|
&.s-wrapper-transluc {
|
||||||
// Semi-opaque wrapper to visually distinguish a control
|
// Semi-opaque wrapper to visually distinguish a control
|
||||||
@ -150,6 +149,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.has-local-controls {
|
||||||
|
.local-control {
|
||||||
|
@include trans-prop-nice($props: opacity, $dur: 250ms);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.local-control {
|
||||||
|
@include trans-prop-nice($props: opacity, $dur: 10ms);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************** VIEW CONTROLS */
|
/******************************************************** VIEW CONTROLS */
|
||||||
// Expand/collapse > and v arrows, used in tree and plot legend
|
// Expand/collapse > and v arrows, used in tree and plot legend
|
||||||
// Moved this over from a tree-only context 5/18/17
|
// Moved this over from a tree-only context 5/18/17
|
||||||
@ -338,6 +350,7 @@ input[type="text"].s-input-inline,
|
|||||||
@include btnSubtle($bg: $colorSelectBg);
|
@include btnSubtle($bg: $colorSelectBg);
|
||||||
@extend .icon-arrow-down; // Context arrow
|
@extend .icon-arrow-down; // Context arrow
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
flex: 0 0 auto; // When used in a flex context, controls need to hold their width
|
||||||
padding: 0 $interiorMargin;
|
padding: 0 $interiorMargin;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
}
|
}
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
.l-image-main {
|
.l-image-main {
|
||||||
background-color: $colorPlotBg;
|
|
||||||
margin-bottom: $interiorMargin;
|
margin-bottom: $interiorMargin;
|
||||||
}
|
}
|
||||||
.l-image-main-controlbar {
|
.l-image-main-controlbar {
|
||||||
@ -76,6 +75,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.s-image-main {
|
.s-image-main {
|
||||||
|
background-color: $colorPlotBg;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
&.paused {
|
&.paused {
|
||||||
@extend .s-unsynced;
|
@extend .s-unsynced;
|
||||||
|
@ -71,8 +71,8 @@ body.mobile {
|
|||||||
.pane.left.treeview {
|
.pane.left.treeview {
|
||||||
@include trans-prop-nice(opacity, 250ms, $delay: 250ms);
|
@include trans-prop-nice(opacity, 250ms, $delay: 250ms);
|
||||||
@include background-image(linear-gradient(90deg, rgba(black, 0) 98%, rgba(black, 0.3) 100%));
|
@include background-image(linear-gradient(90deg, rgba(black, 0) 98%, rgba(black, 0.3) 100%));
|
||||||
width: $proporMenuWithView !important;
|
|
||||||
right: auto !important;
|
right: auto !important;
|
||||||
|
width: $proporMenuWithView !important;
|
||||||
}
|
}
|
||||||
// Sets the right representation when the tree is shown.
|
// Sets the right representation when the tree is shown.
|
||||||
.pane.right.items {
|
.pane.right.items {
|
||||||
@ -136,17 +136,16 @@ body.mobile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-device-width: $phoMaxW) and (orientation: portrait) {
|
body.phone.portrait {
|
||||||
body.mobile {
|
.pane-tree-showing {
|
||||||
.pane-tree-showing {
|
.pane.left.treeview {
|
||||||
.pane.left.treeview {
|
width: $proporMenuOnly !important;
|
||||||
width: $proporMenuOnly !important;
|
}
|
||||||
}
|
.pane.right.items {
|
||||||
.pane.right.items {
|
left: 0 !important;
|
||||||
transform: translateX($proporMenuOnly);
|
transform: translateX($proporMenuOnly);
|
||||||
.holder-object-and-inspector {
|
.holder-object-and-inspector {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,87 +26,89 @@
|
|||||||
@include trans-prop-nice((opacity, color), 150ms);
|
@include trans-prop-nice((opacity, color), 150ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.c-search-btn-wrapper,
|
||||||
|
.c-search {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
&:not(:first-child) { margin-left: $interiorMargin; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-search-btn-wrapper {
|
||||||
|
// Holds c-search and Cancel button
|
||||||
|
//@include test();
|
||||||
|
&.holder {
|
||||||
|
margin-bottom: $interiorMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-search {
|
||||||
|
// New approach to search and filter inputs
|
||||||
|
// Block element
|
||||||
|
// Holds magnify glass icon, html input, cancel button, etc.
|
||||||
|
$m: $interiorMarginSm;
|
||||||
|
@include nice-input();
|
||||||
|
flex: 1 1 99%;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
height: $btnStdH;
|
||||||
|
padding: 1px $interiorMargin;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
display: inline-block;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
// Magnify glass icon
|
||||||
|
content: $glyph-icon-magnify;
|
||||||
|
font-family: symbolsfont;
|
||||||
|
opacity: 0.3;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 500ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover:before {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-search__clear-input {
|
||||||
|
// Icon is visible only when there is text input
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
&.show {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.c-search__search-input {
|
||||||
|
background: none !important;
|
||||||
|
box-shadow: none !important; // !important needed to override default for [input]
|
||||||
|
flex: 1 1 99%;
|
||||||
|
min-width: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-search__search-menu-holder {
|
||||||
|
left: 100%;
|
||||||
|
position: absolute;
|
||||||
|
transform: translate(-30px, 10px);
|
||||||
|
z-index: 70;
|
||||||
|
}
|
||||||
|
|
||||||
.holder-search {
|
.holder-search {
|
||||||
$iconWidth: 20px;
|
$iconWidth: 20px;
|
||||||
|
|
||||||
.search-bar {
|
|
||||||
$textInputHeight: 19px; // This is equal to the default value, 19px
|
|
||||||
$iconEdgeM: 4px;
|
|
||||||
$iconD: $treeSearchInputBarH - ($iconEdgeM*2);
|
|
||||||
@extend .icon-magnify;
|
|
||||||
font-size: 0.8em;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.search-input {
|
|
||||||
height: $treeSearchInputBarH;
|
|
||||||
line-height: $treeSearchInputBarH;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before,
|
|
||||||
.clear-input,
|
|
||||||
.menu-icon {
|
|
||||||
// :before is magnify glass icon
|
|
||||||
height: $iconD;
|
|
||||||
width: $iconD;
|
|
||||||
line-height: $iconD;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-input {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
padding-left: $iconD + $interiorMargin !important;
|
|
||||||
padding-right: ($iconD * 2) + ($interiorMargin * 2) !important;
|
|
||||||
|
|
||||||
// Make work for mct-control textfield
|
|
||||||
input {
|
|
||||||
width: inherit; // was 100%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
// Magnify glass icon
|
|
||||||
left: $interiorMarginSm;
|
|
||||||
pointer-events: none;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clear-input {
|
|
||||||
// Hiding for now with addition of Cancel button
|
|
||||||
right: $iconD + $interiorMargin;
|
|
||||||
|
|
||||||
// Icon is visible only when there is text input
|
|
||||||
visibility: hidden;
|
|
||||||
opacity: 0;
|
|
||||||
&.show {
|
|
||||||
visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: pullForward($colorInputIcon, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-icon {
|
|
||||||
// 'v' invoke menu icon
|
|
||||||
font-size: 0.8em;
|
|
||||||
padding-right: $iconEdgeM;
|
|
||||||
right: $iconEdgeM;
|
|
||||||
text-align: right;
|
|
||||||
&:hover {
|
|
||||||
color: pullForward($colorInputIcon, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-menu-holder {
|
|
||||||
float: right;
|
|
||||||
left: -20px;
|
|
||||||
z-index: 70;
|
|
||||||
transition: visibility .05s, opacity .05s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.results-msg {
|
.results-msg {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
@ -123,8 +123,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.t-frame-outer .s-input-inline {
|
&.t-frame-outer .title-label.s-input-inline {
|
||||||
// Prevent inline inputs from being edited when nested in a Layout
|
// Prevent frame titles from being edited when nested in a Layout
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,6 +161,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
|
// 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
|
// Frame template is used because we need to target the lowest nested frame
|
||||||
.object-browse-bar .btn-bar {
|
.object-browse-bar .btn-bar {
|
||||||
|
@include trans-prop-nice($props: opacity, $dur: 250ms);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
@ -169,6 +170,7 @@ body.desktop .frame {
|
|||||||
// Handles the case where we have layouts in layouts.
|
// Handles the case where we have layouts in layouts.
|
||||||
&:hover > .object-browse-bar {
|
&:hover > .object-browse-bar {
|
||||||
.btn-bar {
|
.btn-bar {
|
||||||
|
@include trans-prop-nice($props: opacity, $dur: 10ms);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
pointer-events: inherit;
|
pointer-events: inherit;
|
||||||
}
|
}
|
||||||
|
45
platform/commonUI/general/res/templates/preview.html
Normal file
45
platform/commonUI/general/res/templates/preview.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<div class="t-frame-inner abs t-object-type-{{ domainObject.getModel().type }}" mct-preview>
|
||||||
|
<div class="abs object-browse-bar l-flex-row">
|
||||||
|
<div class="left flex-elem l-flex-row grows">
|
||||||
|
<mct-representation
|
||||||
|
key="'object-header-frame'"
|
||||||
|
mct-object="domainObject"
|
||||||
|
class="l-flex-row flex-elem object-header grows">
|
||||||
|
</mct-representation>
|
||||||
|
</div>
|
||||||
|
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
|
||||||
|
<mct-representation
|
||||||
|
key="'switcher'"
|
||||||
|
ng-model="representation"
|
||||||
|
mct-object="domainObject">
|
||||||
|
</mct-representation>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="abs object-holder">
|
||||||
|
<mct-representation
|
||||||
|
key="representation.selected.key"
|
||||||
|
mct-object="representation.selected.key && domainObject">
|
||||||
|
</mct-representation>
|
||||||
|
</div>
|
||||||
|
</div>
|
55
platform/commonUI/general/src/actions/MCTPreviewAction.js
Normal file
55
platform/commonUI/general/src/actions/MCTPreviewAction.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 () {
|
||||||
|
|
||||||
|
var PREVIEW_TEMPLATE = '<mct-representation key="\'mct-preview\'"' +
|
||||||
|
'class="t-rep-frame holder"' +
|
||||||
|
'mct-object="domainObject">' +
|
||||||
|
'</mct-representation>';
|
||||||
|
|
||||||
|
function MCTPreviewAction($compile, $rootScope, context) {
|
||||||
|
context = context || {};
|
||||||
|
this.domainObject = context.selectedObject || context.domainObject;
|
||||||
|
this.$rootScope = $rootScope;
|
||||||
|
this.$compile = $compile;
|
||||||
|
}
|
||||||
|
|
||||||
|
MCTPreviewAction.prototype.perform = function () {
|
||||||
|
var newScope = this.$rootScope.$new();
|
||||||
|
newScope.domainObject = this.domainObject;
|
||||||
|
|
||||||
|
this.$compile(PREVIEW_TEMPLATE)(newScope);
|
||||||
|
};
|
||||||
|
|
||||||
|
MCTPreviewAction.appliesTo = function (context) {
|
||||||
|
var domainObject = (context || {}).domainObject,
|
||||||
|
status = domainObject.getCapability('status');
|
||||||
|
|
||||||
|
return !(status && status.get('editing'));
|
||||||
|
};
|
||||||
|
|
||||||
|
return MCTPreviewAction;
|
||||||
|
}
|
||||||
|
);
|
64
platform/commonUI/general/src/directives/MCTPreview.js
Normal file
64
platform/commonUI/general/src/directives/MCTPreview.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2016, 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', '../services/Overlay'], function ($, Overlay) {
|
||||||
|
function MCTPreview($document) {
|
||||||
|
|
||||||
|
function link($scope, $element) {
|
||||||
|
var actions = $scope.domainObject.getCapability('action'),
|
||||||
|
notebookAction = actions.getActions({key: 'notebook-new-entry'})[0];
|
||||||
|
|
||||||
|
var notebookButton = notebookAction ?
|
||||||
|
[
|
||||||
|
{
|
||||||
|
class: 'icon-notebook new-notebook-entry',
|
||||||
|
title: 'New Notebook Entry',
|
||||||
|
clickHandler: function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
notebookAction.perform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
] : [];
|
||||||
|
|
||||||
|
var overlayService = new Overlay({
|
||||||
|
$document: $document,
|
||||||
|
$element: $element[0],
|
||||||
|
$scope: $scope,
|
||||||
|
browseBarButtons: notebookButton
|
||||||
|
});
|
||||||
|
|
||||||
|
overlayService.toggleOverlay();
|
||||||
|
|
||||||
|
$scope.$on('$destroy', function () {
|
||||||
|
$element.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: link
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return MCTPreview;
|
||||||
|
|
||||||
|
});
|
185
platform/commonUI/general/src/services/Overlay.js
Normal file
185
platform/commonUI/general/src/services/Overlay.js
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining OverlayService. Created by deeptailor on 03/29/2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
define(['zepto'], function ($) {
|
||||||
|
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>';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An Overlay Service when instantiated creates an overlay dialog.
|
||||||
|
* @param {Object} options The options object required to instantiate the overlay service
|
||||||
|
* options = {
|
||||||
|
* $document: document object,
|
||||||
|
* $scope: angular $scope object,
|
||||||
|
* element: node to be injected into overlay as a view,
|
||||||
|
* overlayWillMount: callback executed before overlay is injected,
|
||||||
|
* overlayWillUnmount: callback executed before overlay is removed,
|
||||||
|
* overlayDidMount: callback executed after overlay is injected,
|
||||||
|
* overlayDidUnmount: callback executed after overlay is removed
|
||||||
|
* browseBarButtons: an array of desired buttons to be added to the browse bar of the overlay.
|
||||||
|
* the array should consist of button objects containing:
|
||||||
|
* a) class - css class to be added to the button div
|
||||||
|
* b) title - desired button title
|
||||||
|
* c) clickHandler - callback to be added to the click event listener of the button
|
||||||
|
* }
|
||||||
|
* $document, $scope and element are required
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Overlay(options) {
|
||||||
|
this.element = options.$element;
|
||||||
|
this.document = options.$document[0];
|
||||||
|
this.$scope = options.$scope;
|
||||||
|
|
||||||
|
this.overlayWillMount = options.overlayWillMount;
|
||||||
|
this.overlayWillUnmount = options.overlayWillUnmount;
|
||||||
|
|
||||||
|
this.overlayDidMount = options.overlayDidMount;
|
||||||
|
this.overlayDidUnmount = options.overlayDidUnmount;
|
||||||
|
|
||||||
|
this.browseBarButtons = options.browseBarButtons || [];
|
||||||
|
this.buttons = [];
|
||||||
|
|
||||||
|
this.openOverlay = this.openOverlay.bind(this);
|
||||||
|
this.closeOverlay = this.closeOverlay.bind(this);
|
||||||
|
this.toggleOverlay = this.toggleOverlay.bind(this);
|
||||||
|
this.removeButtons = this.removeButtons.bind(this);
|
||||||
|
|
||||||
|
this.isOverlayOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Overlay.prototype.openOverlay = function () {
|
||||||
|
|
||||||
|
if (this.overlayWillMount && typeof this.overlayWillMount === 'function') {
|
||||||
|
this.overlayWillMount();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.overlay = this.document.createElement('div');
|
||||||
|
$(this.overlay).addClass('abs overlay l-large-view');
|
||||||
|
this.overlay.innerHTML = OVERLAY_TEMPLATE;
|
||||||
|
|
||||||
|
this.overlayContainer = this.overlay.querySelector('.t-contents');
|
||||||
|
|
||||||
|
this.closeButton = this.overlay.querySelector('a.close');
|
||||||
|
this.closeButton.addEventListener('click', this.toggleOverlay);
|
||||||
|
|
||||||
|
this.doneButton = this.overlay.querySelector('a.t-done');
|
||||||
|
this.doneButton.addEventListener('click', this.toggleOverlay);
|
||||||
|
|
||||||
|
this.blocker = this.overlay.querySelector('.abs.blocker');
|
||||||
|
this.blocker.addEventListener('click', this.toggleOverlay);
|
||||||
|
|
||||||
|
this.document.body.appendChild(this.overlay);
|
||||||
|
|
||||||
|
this.overlayContainer.appendChild(this.element);
|
||||||
|
|
||||||
|
this.browseBar = this.overlay.querySelector('.object-browse-bar .right');
|
||||||
|
|
||||||
|
if (this.browseBarButtons && Array.isArray(this.browseBarButtons)) {
|
||||||
|
this.browseBarButtons.forEach(function (buttonObject) {
|
||||||
|
var button = newButtonTemplate(buttonObject.class, buttonObject.title);
|
||||||
|
this.browseBar.prepend(button);
|
||||||
|
button.addEventListener('click', buttonObject.clickHandler);
|
||||||
|
this.buttons.push(button);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.overlayDidMount && typeof this.overlayDidMount === 'function') {
|
||||||
|
this.overlayDidMount();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Overlay.prototype.closeOverlay = function () {
|
||||||
|
|
||||||
|
if (this.overlayWillUnmount && typeof this.overlayWillUnmount === 'function') {
|
||||||
|
this.overlayWillUnmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.overlayContainer.removeChild(this.element);
|
||||||
|
this.document.body.removeChild(this.overlay);
|
||||||
|
|
||||||
|
this.closeButton.removeEventListener('click', this.toggleOverlay);
|
||||||
|
this.closeButton = undefined;
|
||||||
|
|
||||||
|
this.doneButton.removeEventListener('click', this.toggleOverlay);
|
||||||
|
this.doneButton = undefined;
|
||||||
|
|
||||||
|
this.blocker.removeEventListener('click', this.toggleOverlay);
|
||||||
|
this.blocker = undefined;
|
||||||
|
|
||||||
|
this.overlayContainer = undefined;
|
||||||
|
this.overlay = undefined;
|
||||||
|
|
||||||
|
this.removeButtons();
|
||||||
|
|
||||||
|
if (this.overlayDidUnmount && typeof this.overlayDidUnmount === 'function') {
|
||||||
|
this.overlayDidUnmount();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Overlay.prototype.toggleOverlay = function (event) {
|
||||||
|
if (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isOverlayOpen) {
|
||||||
|
this.openOverlay();
|
||||||
|
this.isOverlayOpen = true;
|
||||||
|
} else {
|
||||||
|
this.closeOverlay();
|
||||||
|
this.isOverlayOpen = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Overlay.prototype.removeButtons = function () {
|
||||||
|
this.buttons.forEach(function (button) {
|
||||||
|
button.remove();
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
this.buttons = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
function newButtonTemplate(classString, title) {
|
||||||
|
var NEW_BUTTON_TEMPLATE = '<a class="s-button labeled' + classString + '">' +
|
||||||
|
'<span class="title-label">' + title + '</span>' +
|
||||||
|
'</a>';
|
||||||
|
|
||||||
|
var button = document.createElement('div');
|
||||||
|
$(button).addClass('holder flex-elem');
|
||||||
|
button.innerHTML = NEW_BUTTON_TEMPLATE;
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Overlay;
|
||||||
|
});
|
@ -21,23 +21,12 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
define([
|
||||||
'zepto'
|
'zepto',
|
||||||
|
'../../../commonUI/general/src/services/Overlay'
|
||||||
], function (
|
], function (
|
||||||
$
|
$,
|
||||||
|
Overlay
|
||||||
) {
|
) {
|
||||||
|
|
||||||
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>';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MCT Trigger Modal is intended for use in only one location: inside the
|
* MCT Trigger Modal is intended for use in only one location: inside the
|
||||||
* object-header to allow views in a layout to be popped out in a modal.
|
* object-header to allow views in a layout to be popped out in a modal.
|
||||||
@ -50,9 +39,11 @@ define([
|
|||||||
* descendent of a `.frame` element.
|
* descendent of a `.frame` element.
|
||||||
*/
|
*/
|
||||||
function MCTTriggerModal($document) {
|
function MCTTriggerModal($document) {
|
||||||
var document = $document[0];
|
|
||||||
|
|
||||||
function link($scope, $element) {
|
function link($scope, $element) {
|
||||||
|
var actions = $scope.domainObject.getCapability('action'),
|
||||||
|
notebookAction = actions.getActions({key: 'notebook-new-entry'})[0];
|
||||||
|
|
||||||
var frame = $element.parent();
|
var frame = $element.parent();
|
||||||
|
|
||||||
for (var i = 0; i < 10; i++) {
|
for (var i = 0; i < 10; i++) {
|
||||||
@ -67,61 +58,39 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
frame = frame[0];
|
frame = frame[0];
|
||||||
var layoutContainer = frame.parentElement,
|
|
||||||
isOpen = false,
|
|
||||||
toggleOverlay,
|
|
||||||
overlay,
|
|
||||||
closeButton,
|
|
||||||
doneButton,
|
|
||||||
blocker,
|
|
||||||
overlayContainer;
|
|
||||||
|
|
||||||
function openOverlay() {
|
var layoutContainer = frame.parentElement;
|
||||||
// Remove frame classes from being applied in a non-frame context
|
|
||||||
$(frame).removeClass('frame frame-template');
|
|
||||||
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);
|
|
||||||
document.body.appendChild(overlay);
|
|
||||||
layoutContainer.removeChild(frame);
|
|
||||||
overlayContainer.appendChild(frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeOverlay() {
|
var notebookButton = notebookAction ?
|
||||||
$(frame).addClass('frame frame-template');
|
[
|
||||||
overlayContainer.removeChild(frame);
|
{
|
||||||
layoutContainer.appendChild(frame);
|
class: 'icon-notebook new-notebook-entry',
|
||||||
document.body.removeChild(overlay);
|
title: 'New Notebook Entry',
|
||||||
closeButton.removeEventListener('click', toggleOverlay);
|
clickHandler: function (event) {
|
||||||
closeButton = undefined;
|
event.stopPropagation();
|
||||||
doneButton.removeEventListener('click', toggleOverlay);
|
notebookAction.perform();
|
||||||
doneButton = undefined;
|
}
|
||||||
blocker.removeEventListener('click', toggleOverlay);
|
}
|
||||||
blocker = undefined;
|
] : [];
|
||||||
overlayContainer = undefined;
|
|
||||||
overlay = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleOverlay = function () {
|
var overlayService = new Overlay ({
|
||||||
if (!isOpen) {
|
$document: $document,
|
||||||
openOverlay();
|
$scope: $scope,
|
||||||
isOpen = true;
|
$element: frame,
|
||||||
} else {
|
overlayWillMount: function () {
|
||||||
closeOverlay();
|
$(frame).removeClass('frame frame-template');
|
||||||
isOpen = false;
|
layoutContainer.removeChild(frame);
|
||||||
}
|
},
|
||||||
};
|
overlayDidUnmount: function () {
|
||||||
|
$(frame).addClass('frame frame-template');
|
||||||
|
layoutContainer.appendChild(frame);
|
||||||
|
},
|
||||||
|
browseBarButtons: notebookButton
|
||||||
|
});
|
||||||
|
|
||||||
$element.on('click', toggleOverlay);
|
$element.on('click', overlayService.toggleOverlay);
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
$element.off('click', toggleOverlay);
|
$element.off('click', overlayService.toggleOverlay);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,12 @@ define([
|
|||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
$scope = jasmine.createSpyObj('$scope', ['$on']);
|
$scope = jasmine.createSpyObj('$scope', ['$on']);
|
||||||
|
$scope.domainObject = { getCapability: function () {
|
||||||
|
return { getActions: function () {
|
||||||
|
return [];
|
||||||
|
}};
|
||||||
|
}};
|
||||||
|
|
||||||
$element = jasmine.createSpyObj('$element', [
|
$element = jasmine.createSpyObj('$element', [
|
||||||
'parent',
|
'parent',
|
||||||
'remove',
|
'remove',
|
||||||
|
307
platform/features/notebook/bundle.js
Normal file
307
platform/features/notebook/bundle.js
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
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",
|
||||||
|
"text!./res/templates/notebook.html",
|
||||||
|
"text!./res/templates/entry.html",
|
||||||
|
"text!./res/templates/annotation.html",
|
||||||
|
"text!./res/templates/notifications.html",
|
||||||
|
"text!../layout/res/templates/frame.html",
|
||||||
|
"text!./res/templates/controls/embedControl.html",
|
||||||
|
"text!./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": []
|
||||||
|
},
|
||||||
|
"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": [
|
||||||
|
"contextual",
|
||||||
|
"view-control"
|
||||||
|
],
|
||||||
|
"depends": [
|
||||||
|
"$compile",
|
||||||
|
"$rootScope",
|
||||||
|
"dialogService",
|
||||||
|
"notificationService",
|
||||||
|
"linkService"
|
||||||
|
],
|
||||||
|
"priority": "preferred"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"name": "painterro",
|
||||||
|
"version": "4.1.0",
|
||||||
|
"author": "Mike Bostock",
|
||||||
|
"description": "D3 (or D3.js) is a JavaScript library for visualizing data using web standards. D3 helps you bring data to life using SVG, Canvas and HTML. D3 combines powerful visualization and interaction techniques with a data-driven approach to DOM manipulation, giving you the full capabilities of modern browsers and the freedom to design the right visual interface for your data.",
|
||||||
|
"website": "https://d3js.org/",
|
||||||
|
"copyright": "Copyright 2010-2016 Mike Bostock",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"link": "https://github.com/d3/d3/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
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stylesheets": [
|
||||||
|
{
|
||||||
|
"stylesheetUrl": "css/notebook.css"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stylesheetUrl": "css/notebook-espresso.css",
|
||||||
|
"theme": "espresso"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stylesheetUrl": "css/notebook-snow.css",
|
||||||
|
"theme": "snow"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
308
platform/features/notebook/res/sass/_notebook-base.scss
Normal file
308
platform/features/notebook/res/sass/_notebook-base.scss
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2016, 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
.w-notebook {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook-view-controls.l-flex-row {
|
||||||
|
> * {
|
||||||
|
// filter and sort selects
|
||||||
|
&:not(:first-child) { margin-left: $interiorMargin; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-notebook-drag-area {
|
||||||
|
padding: 10px;
|
||||||
|
font-style: italic;
|
||||||
|
cursor: pointer;
|
||||||
|
&:before { margin-right: 7px !important; }
|
||||||
|
.label {
|
||||||
|
@include ellipsize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame {
|
||||||
|
.icon-notebook {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay.l-dialog .title{
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-notebook-entries {
|
||||||
|
padding-right: $interiorMarginSm;
|
||||||
|
position: relative;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
.t-entries-list {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-notebook-entry {
|
||||||
|
$p: $interiorMarginSm;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-bottom: $p;
|
||||||
|
padding: $p $interiorMargin;
|
||||||
|
|
||||||
|
.s-notebook-entry-time,
|
||||||
|
.s-notebook-entry-text,
|
||||||
|
.notebook-entry-delete {
|
||||||
|
padding-top: $p;
|
||||||
|
padding-bottom: $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-notebook-entry-time {
|
||||||
|
border: 1px solid transparent; // Needed to maintain vertical alignment with s-notebook-entry-text
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-notebook-entry-content{
|
||||||
|
.s-notebook-entry-text {
|
||||||
|
// Contenteditable div that holds text
|
||||||
|
min-height: 24px; // Needed in Firefox when field is blank
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.entry-embeds{
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.snap-thumb {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-entry-embed {
|
||||||
|
$m: $interiorMarginSm;
|
||||||
|
position: relative;
|
||||||
|
margin: $m $m 0 0;
|
||||||
|
padding: $interiorMarginSm;
|
||||||
|
|
||||||
|
&.has-snapshot {
|
||||||
|
&:before {
|
||||||
|
position: absolute;
|
||||||
|
text-shadow: rgba(black, 0.7) 0 1px 5px;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.snap-thumb {
|
||||||
|
$d: 50px;
|
||||||
|
width: $d;
|
||||||
|
height: $d;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
img {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-info {
|
||||||
|
margin-left: $interiorMargin;
|
||||||
|
.embed-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.t-contents,
|
||||||
|
.snap-annotation {
|
||||||
|
// Todo: don't write this to t-contents, add a l- class
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook-filters {
|
||||||
|
.select {
|
||||||
|
margin-left: $interiorMargin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************* MOBILE */
|
||||||
|
body.mobile {
|
||||||
|
// Hide the start entry area, and disable ability to edit or delete an entry in mobile context
|
||||||
|
.l-notebook-drag-area {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-notebook-entry {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.phone.portrait {
|
||||||
|
.w-notebook-entry-time-and-content {
|
||||||
|
flex-direction: column !important;
|
||||||
|
}
|
||||||
|
.s-notebook-entry-time,
|
||||||
|
.notebook-entry-delete {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body.phone.portrait {
|
||||||
|
.l-notebook-head.l-flex-row {
|
||||||
|
flex-direction: column !important;
|
||||||
|
> * {
|
||||||
|
&:not(:first-child) { margin-top: $interiorMargin; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************* PAINTERRO OVERRIDES */
|
||||||
|
.annotation-dialog .abs.editor {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snap-annotation {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
top: 0; right: 0; bottom: 0; left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snap-annotation-wrapper,
|
||||||
|
#snap-annotation-bar {
|
||||||
|
position: relative;
|
||||||
|
top: auto; right: auto; bottom: auto; left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snap-annotation-wrapper {
|
||||||
|
order: 2;
|
||||||
|
flex: 10 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snap-annotation-bar {
|
||||||
|
order: 1;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
height: auto;
|
||||||
|
background-color: transparent !important;
|
||||||
|
margin-bottom: $interiorMargin;
|
||||||
|
|
||||||
|
> 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;
|
||||||
|
}
|
||||||
|
$h: $btnToolbarH;
|
||||||
|
display: inline-block;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: auto;
|
||||||
|
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: $btnToolbarH !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ptro-icon-btn,
|
||||||
|
.ptro-named-btn {
|
||||||
|
// .s-button class is added via JS in AnnotateSnapshot.js
|
||||||
|
// TODO: redo this so that we don't need to use Zepto and JS
|
||||||
|
i {
|
||||||
|
font-size: 1.25em !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-controls {
|
||||||
|
font-size: 0.8rem !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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************* NO IDEA WHAT THERE ARE APPLYING TO */
|
||||||
|
.context-available {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-element.menu-view{
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay.l-dialog .abs.editor {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
.overlay.l-dialog .outer-holder.annotation-dialog{
|
||||||
|
width: 90%;
|
||||||
|
height: 90%;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
.snap-annotation-wrapper{
|
||||||
|
padding-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.t-console {
|
||||||
|
// Temp console-like reporting element
|
||||||
|
max-height: 200px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
*/
|
92
platform/features/notebook/res/sass/_notebook-thematic.scss
Normal file
92
platform/features/notebook/res/sass/_notebook-thematic.scss
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
.l-notebook-drag-area {
|
||||||
|
border: 1px dashed rgba($colorKey, 0.7);
|
||||||
|
border-radius: $controlCr;
|
||||||
|
color: rgba($colorBodyFg, 0.7);
|
||||||
|
&:hover {
|
||||||
|
background: rgba($colorKey, 0.2);
|
||||||
|
color: $colorBodyFg;
|
||||||
|
}
|
||||||
|
&.drag-active{
|
||||||
|
border-color: $colorKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-notebook-entry {
|
||||||
|
background-color: rgba($colorBodyFg, 0.1);
|
||||||
|
border-radius: $basicCr;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba($colorBodyFg, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-notebook-entry-time {
|
||||||
|
color: rgba($colorBodyFg, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.l-entry-embed {
|
||||||
|
border-radius: $controlCr;
|
||||||
|
background-color: rgba($colorBodyFg, 0.1);
|
||||||
|
&.has-snapshot {
|
||||||
|
&:before {
|
||||||
|
color: $colorBodyFg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-snapshot-datetime {
|
||||||
|
color: rgba($colorBodyFg, 0.4);
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.snap-thumb {
|
||||||
|
border: 1px solid $colorInteriorBorder;
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-status-taking-snapshot,
|
||||||
|
.overlay.snapshot {
|
||||||
|
// Applied to an object view when it's in the process of being snapshotted
|
||||||
|
background: $colorBodyBg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************* PAINTERRO OVERRIDES */
|
||||||
|
.ptro-wrapper {
|
||||||
|
background: rgba($colorBodyBg, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#snap-annotation-bar {
|
||||||
|
.tool-controls {
|
||||||
|
color: $colorBodyFg !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-button.ptro-color-active-control {
|
||||||
|
background: $colorBtnMajorBg !important;
|
||||||
|
color: $colorBtnMajorFg !important;
|
||||||
|
&:hover {
|
||||||
|
background: $colorBtnMajorBgHov !important;
|
||||||
|
color: $colorBtnMajorFgHov !important;
|
||||||
|
}
|
||||||
|
}
|
30
platform/features/notebook/res/sass/notebook-espresso.scss
Normal file
30
platform/features/notebook/res/sass/notebook-espresso.scss
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
$output-bourbon-deprecation-warnings: false;
|
||||||
|
@import "bourbon";
|
||||||
|
|
||||||
|
@import "../../../../commonUI/general/res/sass/constants";
|
||||||
|
@import "../../../../commonUI/general/res/sass/mixins";
|
||||||
|
@import "../../../../commonUI/general/res/sass/glyphs";
|
||||||
|
@import "../../../../commonUI/themes/espresso/res/sass/constants";
|
||||||
|
@import "../../../../commonUI/themes/espresso/res/sass/mixins";
|
||||||
|
@import "notebook-thematic";
|
30
platform/features/notebook/res/sass/notebook-snow.scss
Normal file
30
platform/features/notebook/res/sass/notebook-snow.scss
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
$output-bourbon-deprecation-warnings: false;
|
||||||
|
@import "bourbon";
|
||||||
|
|
||||||
|
@import "../../../../commonUI/general/res/sass/constants";
|
||||||
|
@import "../../../../commonUI/general/res/sass/mixins";
|
||||||
|
@import "../../../../commonUI/general/res/sass/glyphs";
|
||||||
|
@import "../../../../commonUI/themes/snow/res/sass/constants";
|
||||||
|
@import "../../../../commonUI/themes/snow/res/sass/mixins";
|
||||||
|
@import "notebook-thematic";
|
28
platform/features/notebook/res/sass/notebook.scss
Normal file
28
platform/features/notebook/res/sass/notebook.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2015, 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
$output-bourbon-deprecation-warnings: false;
|
||||||
|
@import "bourbon";
|
||||||
|
@import "../../../../commonUI/general/res/sass/constants";
|
||||||
|
@import "../../../../commonUI/general/res/sass/mixins";
|
||||||
|
@import "../../../../commonUI/general/res/sass/mobile/constants";
|
||||||
|
@import "../../../../commonUI/general/res/sass/mobile/mixins";
|
||||||
|
@import "notebook-base";
|
2
platform/features/notebook/res/templates/annotation.html
Normal file
2
platform/features/notebook/res/templates/annotation.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<div class="snap-annotation" id="snap-annotation" ng-controller="ngModel.controller">
|
||||||
|
</div>
|
@ -0,0 +1,51 @@
|
|||||||
|
<!--
|
||||||
|
Open MCT, Copyright (c) 2009-2016, 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 element appears in the overlay dialog when initiating a new Notebook Entry from a view's Notebook button -->
|
||||||
|
<div class='form-control'>
|
||||||
|
<ng-form name="mctControl">
|
||||||
|
<div class='fields' ng-controller="NewEntryController">
|
||||||
|
<div class="l-flex-row new-notebook-entry-embed l-entry-embed {{cssClass}}"
|
||||||
|
ng-class="{ 'has-snapshot' : snapToggle }">
|
||||||
|
<div class="holder flex-elem snap-thumb"
|
||||||
|
ng-if="snapToggle">
|
||||||
|
<img ng-src="{{snapshot.src}}" alt="{{snapshot.modified}}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="holder flex-elem embed-info">
|
||||||
|
<div class="embed-title">{{objectName}}</div>
|
||||||
|
<div class="embed-date"
|
||||||
|
ng-if="snapToggle">{{snapshot.modified| date:'yyyy-MM-dd HH:mm:ss'}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="holder flex-elem annotate-new"
|
||||||
|
ng-if="snapToggle">
|
||||||
|
<a class="s-button flex-elem icon-pencil "
|
||||||
|
title="Annotate this snapshot"
|
||||||
|
ng-click="annotateSnapshot()">
|
||||||
|
<span class="title-label">Annotate</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-form>
|
||||||
|
</div>
|
@ -0,0 +1,30 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<div class='form-control select' ng-controller="selectSnapshotController">
|
||||||
|
<select
|
||||||
|
ng-model="selectModel"
|
||||||
|
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>
|
38
platform/features/notebook/res/templates/entry.html
Normal file
38
platform/features/notebook/res/templates/entry.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<div class="frame snap-frame frame-template t-frame-inner abs t-object-type-{{ representation.selected.key }}">
|
||||||
|
<div class="abs object-browse-bar l-flex-row">
|
||||||
|
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
|
||||||
|
<mct-representation
|
||||||
|
key="'switcher'"
|
||||||
|
ng-model="representation"
|
||||||
|
mct-object="domainObject">
|
||||||
|
</mct-representation>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="abs object-holder" data-entry = "{{parameters.entry}}" data-embed = "{{parameters.embed}}" mct-snapshot ng-if="representation.selected.key">
|
||||||
|
<mct-representation
|
||||||
|
key="representation.selected.key"
|
||||||
|
mct-object="representation.selected.key && domainObject">
|
||||||
|
</mct-representation>
|
||||||
|
</div>
|
||||||
|
</div>
|
118
platform/features/notebook/res/templates/notebook.html
Normal file
118
platform/features/notebook/res/templates/notebook.html
Normal 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 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>
|
@ -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>
|
34
platform/features/notebook/res/templates/snapshotHeader.html
Normal file
34
platform/features/notebook/res/templates/snapshotHeader.html
Normal 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>
|
164
platform/features/notebook/src/actions/AnnotateSnapshot.js
Normal file
164
platform/features/notebook/src/actions/AnnotateSnapshot.js
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 (Originally NewWindowAction). Created by vwoeltje on 11/18/14.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["painterro", "zepto"],
|
||||||
|
function (Painterro, $) {
|
||||||
|
var annotationStruct = {
|
||||||
|
title: "Annotate Snapshot",
|
||||||
|
template: "annotate-snapshot",
|
||||||
|
options: [{
|
||||||
|
name: "OK",
|
||||||
|
key: "ok",
|
||||||
|
description: "save annotation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cancel",
|
||||||
|
key: "cancel",
|
||||||
|
description: "cancel editing"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
function AnnotateSnapshot(dialogService, dndService, $rootScope, context) {
|
||||||
|
context = context || {};
|
||||||
|
|
||||||
|
// Choose the object to be opened into a new tab
|
||||||
|
this.domainObject = context.selectedObject || context.domainObject;
|
||||||
|
this.dialogService = dialogService;
|
||||||
|
this.dndService = dndService;
|
||||||
|
this.$rootScope = $rootScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotateSnapshot.prototype.perform = function ($event, snapshot, embedId, entryId) {
|
||||||
|
|
||||||
|
var DOMAIN_OBJECT = this.domainObject;
|
||||||
|
var ROOTSCOPE = this.$rootScope;
|
||||||
|
var painterro;
|
||||||
|
var save = false;
|
||||||
|
|
||||||
|
var controller = ['$scope', '$timeout', function PainterroController($scope, $timeout) {
|
||||||
|
$(document.body).find('.l-dialog .outer-holder').addClass('annotation-dialog');
|
||||||
|
|
||||||
|
// Timeout is necessary because Painterro uses document.getElementById, and mct-include
|
||||||
|
// hasn't added the dialog to the DOM yet.
|
||||||
|
$timeout(function () {
|
||||||
|
painterro = Painterro({
|
||||||
|
id: 'snap-annotation',
|
||||||
|
activeColor: '#ff0000',
|
||||||
|
activeColorAlpha: 1.0,
|
||||||
|
activeFillColor: '#fff',
|
||||||
|
activeFillColorAlpha: 0.0,
|
||||||
|
backgroundFillColor: '#000',
|
||||||
|
backgroundFillColorAlpha: 0.0,
|
||||||
|
defaultFontSize: 16,
|
||||||
|
defaultLineWidth: 2,
|
||||||
|
defaultTool: 'ellipse',
|
||||||
|
hiddenTools: ['save', 'open', 'close', 'eraser', 'pixelize', 'rotate', 'settings', 'resize'],
|
||||||
|
translation: {
|
||||||
|
name: 'en',
|
||||||
|
strings: {
|
||||||
|
lineColor: 'Line',
|
||||||
|
fillColor: 'Fill',
|
||||||
|
lineWidth: 'Size',
|
||||||
|
textColor: 'Color',
|
||||||
|
fontSize: 'Size',
|
||||||
|
fontStyle: 'Style'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
saveHandler: function (image, done) {
|
||||||
|
if (save) {
|
||||||
|
if (entryId && embedId) {
|
||||||
|
var elementPos = DOMAIN_OBJECT.model.entries.map(function (x) {
|
||||||
|
return x.createdOn;
|
||||||
|
}).indexOf(entryId);
|
||||||
|
var entryEmbeds = DOMAIN_OBJECT.model.entries[elementPos].embeds;
|
||||||
|
var embedPos = entryEmbeds.map(function (x) {
|
||||||
|
return x.id;
|
||||||
|
}).indexOf(embedId);
|
||||||
|
|
||||||
|
saveSnap(image.asBlob(), embedPos, elementPos, DOMAIN_OBJECT);
|
||||||
|
}else {
|
||||||
|
ROOTSCOPE.snapshot = {'src': image.asDataURL('image/png'),
|
||||||
|
'modified': Date.now()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done(true);
|
||||||
|
}
|
||||||
|
}).show(snapshot);
|
||||||
|
|
||||||
|
$(document.body).find('.ptro-icon-btn').addClass('s-button');
|
||||||
|
$(document.body).find('.ptro-input').addClass('s-button');
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
|
||||||
|
annotationStruct.model = {'controller': controller};
|
||||||
|
|
||||||
|
function saveNotes(param) {
|
||||||
|
if (param === 'ok') {
|
||||||
|
save = true;
|
||||||
|
}else {
|
||||||
|
save = false;
|
||||||
|
ROOTSCOPE.snapshot = "annotationCancelled";
|
||||||
|
}
|
||||||
|
painterro.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
function rejectNotes() {
|
||||||
|
save = false;
|
||||||
|
ROOTSCOPE.snapshot = "annotationCancelled";
|
||||||
|
painterro.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveSnap(url, embedPos, entryPos, domainObject) {
|
||||||
|
var snap = false;
|
||||||
|
|
||||||
|
if (embedPos !== -1 && entryPos !== -1) {
|
||||||
|
var reader = new window.FileReader();
|
||||||
|
reader.readAsDataURL(url);
|
||||||
|
reader.onloadend = function () {
|
||||||
|
snap = reader.result;
|
||||||
|
domainObject.useCapability('mutation', function (model) {
|
||||||
|
if (model.entries[entryPos]) {
|
||||||
|
model.entries[entryPos].embeds[embedPos].snapshot = {
|
||||||
|
'src': snap,
|
||||||
|
'type': url.type,
|
||||||
|
'size': url.size,
|
||||||
|
'modified': Date.now()
|
||||||
|
};
|
||||||
|
model.entries[entryPos].embeds[embedPos].id = Date.now();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dialogService.getUserChoice(annotationStruct)
|
||||||
|
.then(saveNotes, rejectNotes);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return AnnotateSnapshot;
|
||||||
|
}
|
||||||
|
);
|
193
platform/features/notebook/src/actions/NewEntryContextual.js
Normal file
193
platform/features/notebook/src/actions/NewEntryContextual.js
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 () {
|
||||||
|
|
||||||
|
var SNAPSHOT_TEMPLATE = '<mct-representation key="\'draggedEntry\'"' +
|
||||||
|
'class="t-rep-frame holder"' +
|
||||||
|
'mct-object="selObj">' +
|
||||||
|
'</mct-representation>';
|
||||||
|
|
||||||
|
var NEW_TASK_FORM = {
|
||||||
|
name: "Create a Notebook Entry",
|
||||||
|
hint: "Please select one Notebook",
|
||||||
|
sections: [{
|
||||||
|
rows: [{
|
||||||
|
name: 'Entry',
|
||||||
|
key: 'entry',
|
||||||
|
control: 'textarea',
|
||||||
|
required: false,
|
||||||
|
"cssClass": "l-textarea-sm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Embed Type',
|
||||||
|
key: 'withSnapshot',
|
||||||
|
control: 'snapshot-select',
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"name": "Link and Snapshot",
|
||||||
|
"value": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Link only",
|
||||||
|
"value": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Embed',
|
||||||
|
key: 'embedObject',
|
||||||
|
control: 'embed-control'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Save in Notebook',
|
||||||
|
key: 'saveNotebook',
|
||||||
|
control: 'locator',
|
||||||
|
validate: validateLocation
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
function NewEntryContextual($compile, $rootScope, dialogService, notificationService, linkService, context) {
|
||||||
|
context = context || {};
|
||||||
|
this.domainObject = context.selectedObject || context.domainObject;
|
||||||
|
this.dialogService = dialogService;
|
||||||
|
this.notificationService = notificationService;
|
||||||
|
this.linkService = linkService;
|
||||||
|
this.$rootScope = $rootScope;
|
||||||
|
this.$compile = $compile;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateLocation(newParentObj) {
|
||||||
|
return newParentObj.model.type === 'notebook';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NewEntryContextual.prototype.perform = function () {
|
||||||
|
var self = this;
|
||||||
|
var domainObj = this.domainObject;
|
||||||
|
var notification = this.notificationService;
|
||||||
|
var dialogService = this.dialogService;
|
||||||
|
var rootScope = this.$rootScope;
|
||||||
|
rootScope.newEntryText = '';
|
||||||
|
// Create the overlay element and add it to the document's body
|
||||||
|
this.$rootScope.selObj = domainObj;
|
||||||
|
this.$rootScope.selValue = "";
|
||||||
|
var newScope = rootScope.$new();
|
||||||
|
newScope.selObj = domainObj;
|
||||||
|
newScope.selValue = "";
|
||||||
|
this.$compile(SNAPSHOT_TEMPLATE)(newScope);
|
||||||
|
|
||||||
|
this.$rootScope.$watch("snapshot", setSnapshot);
|
||||||
|
|
||||||
|
function setSnapshot(value) {
|
||||||
|
if (value === "annotationCancelled") {
|
||||||
|
rootScope.snapshot = rootScope.lastValue;
|
||||||
|
rootScope.lastValue = '';
|
||||||
|
|
||||||
|
} else if (value && value !== rootScope.lastValue) {
|
||||||
|
var overlayModel = {
|
||||||
|
title: NEW_TASK_FORM.name,
|
||||||
|
message: NEW_TASK_FORM.message,
|
||||||
|
structure: NEW_TASK_FORM,
|
||||||
|
value: {'entry': rootScope.newEntryText || ""}
|
||||||
|
};
|
||||||
|
|
||||||
|
rootScope.currentDialog = overlayModel;
|
||||||
|
|
||||||
|
dialogService.getDialogResponse(
|
||||||
|
"overlay-dialog",
|
||||||
|
overlayModel,
|
||||||
|
function () {
|
||||||
|
return overlayModel.value;
|
||||||
|
}
|
||||||
|
).then(addNewEntry);
|
||||||
|
|
||||||
|
rootScope.lastValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNewEntry(options) {
|
||||||
|
options.selectedModel = options.embedObject.getModel();
|
||||||
|
options.cssClass = options.embedObject.getCapability('type').typeDef.cssClass;
|
||||||
|
if (self.$rootScope.snapshot) {
|
||||||
|
options.snapshot = self.$rootScope.snapshot;
|
||||||
|
self.$rootScope.snapshot = undefined;
|
||||||
|
}else {
|
||||||
|
options.snapshot = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.withSnapshot) {
|
||||||
|
options.snapshot = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
createSnap(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSnap(options) {
|
||||||
|
options.saveNotebook.useCapability('mutation', function (model) {
|
||||||
|
var entries = model.entries;
|
||||||
|
var lastEntry = entries[entries.length - 1];
|
||||||
|
var date = Date.now();
|
||||||
|
|
||||||
|
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
|
||||||
|
model.entries.push({
|
||||||
|
'id': date,
|
||||||
|
'createdOn': date,
|
||||||
|
'text': options.entry,
|
||||||
|
'embeds': [{'type': options.embedObject.getId(),
|
||||||
|
'id': '' + date,
|
||||||
|
'cssClass': options.cssClass,
|
||||||
|
'name': options.selectedModel.name,
|
||||||
|
'snapshot': options.snapshot
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}else {
|
||||||
|
model.entries[entries.length - 1] = {
|
||||||
|
'id': date,
|
||||||
|
'createdOn': date,
|
||||||
|
'text': options.entry,
|
||||||
|
'embeds': [{'type': options.embedObject.getId(),
|
||||||
|
'id': '' + date,
|
||||||
|
'cssClass': options.cssClass,
|
||||||
|
'name': options.selectedModel.name,
|
||||||
|
'snapshot': options.snapshot
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
notification.info({
|
||||||
|
title: "Notebook Entry created"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NewEntryContextual.appliesTo = function (context) {
|
||||||
|
var domainObject = context.domainObject;
|
||||||
|
return !!(domainObject && domainObject.getModel().type !== 'notebook');
|
||||||
|
};
|
||||||
|
|
||||||
|
return NewEntryContextual;
|
||||||
|
}
|
||||||
|
);
|
72
platform/features/notebook/src/actions/RemoveEmbed.js
Normal file
72
platform/features/notebook/src/actions/RemoveEmbed.js
Normal 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;
|
||||||
|
}
|
||||||
|
);
|
74
platform/features/notebook/src/actions/RemoveSnapshot.js
Normal file
74
platform/features/notebook/src/actions/RemoveSnapshot.js
Normal 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;
|
||||||
|
}
|
||||||
|
);
|
132
platform/features/notebook/src/actions/ViewSnapshot.js
Normal file
132
platform/features/notebook/src/actions/ViewSnapshot.js
Normal 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',
|
||||||
|
"text!../../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;
|
||||||
|
}
|
||||||
|
);
|
@ -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;
|
||||||
|
}
|
||||||
|
);
|
@ -0,0 +1,54 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 object types and associated views for
|
||||||
|
* display-building.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The LayoutNotebookController is responsible for supporting the
|
||||||
|
* notebook feature creation on theLayout view.
|
||||||
|
**/
|
||||||
|
|
||||||
|
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();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LayoutNotebookController;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,66 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 NewEntryController. */
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
|
||||||
|
function NewEntryController($scope,$rootScope) {
|
||||||
|
|
||||||
|
$scope.snapshot = undefined;
|
||||||
|
$scope.snapToggle = true;
|
||||||
|
$scope.entryText = '';
|
||||||
|
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;
|
||||||
|
$scope.cssClass = $rootScope.selObj.getCapability('type').typeDef.cssClass;
|
||||||
|
|
||||||
|
$scope.annotateSnapshot = function ($event) {
|
||||||
|
if ($rootScope.currentDialog.value) {
|
||||||
|
$rootScope.newEntryText = $scope.$parent.$parent.ngModel.entry;
|
||||||
|
$rootScope.currentDialog.cancel();
|
||||||
|
annotateAction.perform($event, $rootScope.snapshot.src);
|
||||||
|
$rootScope.currentDialog = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateSnapshot(img) {
|
||||||
|
$scope.snapshot = img;
|
||||||
|
}
|
||||||
|
// Update set of actions whenever the action capability
|
||||||
|
// changes or becomes available.
|
||||||
|
$rootScope.$watch("snapshot", updateSnapshot);
|
||||||
|
|
||||||
|
$rootScope.$watch("selValue", toggleEmbed);
|
||||||
|
|
||||||
|
function toggleEmbed(value) {
|
||||||
|
$scope.snapToggle = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewEntryController;
|
||||||
|
}
|
||||||
|
);
|
363
platform/features/notebook/src/controllers/NotebookController.js
Normal file
363
platform/features/notebook/src/controllers/NotebookController.js
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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 || "-createdOn";
|
||||||
|
$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,
|
||||||
|
popup;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
popup = 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.$on('$destroy', function () {});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NotebookController;
|
||||||
|
});
|
@ -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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining SelectSnapshotController. */
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
|
||||||
|
function SelectSnapshotController($scope,$rootScope) {
|
||||||
|
|
||||||
|
$scope.selectModel = true;
|
||||||
|
|
||||||
|
function selectprint(value) {
|
||||||
|
$rootScope.selValue = value;
|
||||||
|
$scope.$parent.$parent.ngModel[$scope.$parent.$parent.field] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.$watch("selectModel", selectprint);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return SelectSnapshotController;
|
||||||
|
}
|
||||||
|
);
|
126
platform/features/notebook/src/directives/EntryDnd.js
Normal file
126
platform/features/notebook/src/directives/EntryDnd.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2016, 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 EntryDnd($rootScope,$compile,dndService,typeService,notificationService) {
|
||||||
|
|
||||||
|
function link($scope, $element) {
|
||||||
|
|
||||||
|
function drop(e) {
|
||||||
|
var selectedObject = dndService.getData('mct-domain-object');
|
||||||
|
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': ''
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}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': ''
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.scrollToTop();
|
||||||
|
notificationService.info({
|
||||||
|
title: "Notebook Entry created"
|
||||||
|
});
|
||||||
|
|
||||||
|
}else {
|
||||||
|
entryId = $scope.findEntryPositionById(Number($element[0].id.replace('entry_', '')));
|
||||||
|
|
||||||
|
if (!$scope.domainObject.model.entries[entryId].embeds) {
|
||||||
|
$scope.domainObject.model.entries[entryId].embeds = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.domainObject.useCapability('mutation', function (model) {
|
||||||
|
model.entries[entryId].embeds.push({'type': selectedObject.getId(),
|
||||||
|
'id': '' + Date.now(),
|
||||||
|
'cssClass': cssClass,
|
||||||
|
'name': selectedModel.name,
|
||||||
|
'snapshot': ''
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
embedId = $scope.domainObject.model.entries[entryId].embeds.length - 1;
|
||||||
|
|
||||||
|
if (selectedObject) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($(e.currentTarget).hasClass('drag-active')) {
|
||||||
|
$(e.currentTarget).removeClass('drag-active');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragover(e) {
|
||||||
|
if (!$(e.currentTarget).hasClass('drag-active')) {
|
||||||
|
$(e.currentTarget).addClass('drag-active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for the drop itself
|
||||||
|
$element.on('dragover', dragover);
|
||||||
|
$element.on('drop', drop);
|
||||||
|
|
||||||
|
|
||||||
|
$scope.$on('$destroy', function () {
|
||||||
|
$element.off('dragover', dragover);
|
||||||
|
$element.off('drop', drop);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: link
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return EntryDnd;
|
||||||
|
|
||||||
|
});
|
86
platform/features/notebook/src/directives/MCTSnapshot.js
Normal file
86
platform/features/notebook/src/directives/MCTSnapshot.js
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2016, 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 MCTSnapshot($rootScope, $document, exportImageService, dialogService, notificationService) {
|
||||||
|
var document = $document[0];
|
||||||
|
|
||||||
|
function link($scope, $element, $attrs) {
|
||||||
|
var objectElement = $(document.body).find('.overlay')[0] || $(document.body).find("[key='representation.selected.key']")[0],
|
||||||
|
takeSnapshot,
|
||||||
|
makeImg,
|
||||||
|
saveImg;
|
||||||
|
|
||||||
|
$(objectElement).addClass("s-status-taking-snapshot");
|
||||||
|
|
||||||
|
saveImg = function (url, entryId, embedId) {
|
||||||
|
$scope.$parent.$parent.$parent.saveSnap(url, embedId, entryId);
|
||||||
|
};
|
||||||
|
|
||||||
|
makeImg = function (el) {
|
||||||
|
var scope = $scope;
|
||||||
|
|
||||||
|
exportImageService.exportPNGtoSRC(el).then(function (img) {
|
||||||
|
|
||||||
|
$(objectElement).removeClass("s-status-taking-snapshot");
|
||||||
|
|
||||||
|
if (img) {
|
||||||
|
if ($element[0].dataset.entry && $element[0].dataset.embed) {
|
||||||
|
saveImg(img, +$element[0].dataset.entry, +$element[0].dataset.embed);
|
||||||
|
} else {
|
||||||
|
var reader = new window.FileReader();
|
||||||
|
reader.readAsDataURL(img);
|
||||||
|
reader.onloadend = function () {
|
||||||
|
$($element[0]).attr("data-snapshot", reader.result);
|
||||||
|
$rootScope.snapshot = {
|
||||||
|
'src': reader.result,
|
||||||
|
'type': img.type,
|
||||||
|
'size': img.size,
|
||||||
|
'modified': Date.now()
|
||||||
|
};
|
||||||
|
scope.$destroy();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
takeSnapshot = function () {
|
||||||
|
makeImg(objectElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
takeSnapshot();
|
||||||
|
|
||||||
|
$scope.$on('$destroy', function () {
|
||||||
|
$element.remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: link
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return MCTSnapshot;
|
||||||
|
|
||||||
|
});
|
44
platform/features/notebook/src/policies/CompositionPolicy.js
Normal file
44
platform/features/notebook/src/policies/CompositionPolicy.js
Normal 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;
|
||||||
|
}
|
||||||
|
);
|
@ -62,8 +62,10 @@ define(
|
|||||||
scope.key && templateMap[scope.key]
|
scope.key && templateMap[scope.key]
|
||||||
);
|
);
|
||||||
|
|
||||||
scope.$watch('key', function (key) {
|
scope.$watch('key', function (newKey, oldKey) {
|
||||||
changeTemplate(key && templateMap[key]);
|
if (newKey !== oldKey) {
|
||||||
|
changeTemplate(newKey && templateMap[newKey]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,33 +21,31 @@
|
|||||||
-->
|
-->
|
||||||
<div class="angular-w l-flex-col flex-elem grows holder" ng-controller="SearchController as controller">
|
<div class="angular-w l-flex-col flex-elem grows holder" ng-controller="SearchController as controller">
|
||||||
<div class="l-flex-col flex-elem grows holder holder-search" ng-controller="SearchMenuController as menuController">
|
<div class="l-flex-col flex-elem grows holder holder-search" ng-controller="SearchMenuController as menuController">
|
||||||
<div class="search-bar l-filter flex-elem l-flex-row"
|
<div class="c-search-btn-wrapper"
|
||||||
ng-controller="ToggleController as toggle"
|
ng-controller="ToggleController as toggle"
|
||||||
ng-class="{ holder: !(ngModel.input === '' || ngModel.input === undefined) }">
|
ng-class="{ holder: !(ngModel.input === '' || ngModel.input === undefined) }">
|
||||||
<div class="holder flex-elem grows">
|
<div class="c-search">
|
||||||
<input class="search-input"
|
<input class="c-search__search-input"
|
||||||
type="text" tabindex="10000"
|
type="text" tabindex="10000"
|
||||||
ng-model="ngModel.input"
|
ng-model="ngModel.input"
|
||||||
ng-keyup="controller.search()"/>
|
ng-keyup="controller.search()"/>
|
||||||
<a class="clear-icon clear-input icon-x-in-circle"
|
<a class="c-search__clear-input clear-icon icon-x-in-circle"
|
||||||
ng-class="{show: !(ngModel.input === '' || ngModel.input === undefined)}"
|
ng-class="{show: !(ngModel.input === '' || ngModel.input === undefined)}"
|
||||||
ng-click="ngModel.input = ''; controller.search()"></a>
|
ng-click="ngModel.input = ''; controller.search()"></a>
|
||||||
|
|
||||||
<!-- To prevent double triggering of clicks on click away, render
|
<!-- To prevent double triggering of clicks on click away, render
|
||||||
non-clickable version of the button when menu active-->
|
non-clickable version of the button when menu active-->
|
||||||
<a ng-if="!toggle.isActive()" class="menu-icon context-available"
|
<a ng-if="!toggle.isActive()" class="menu-icon context-available"
|
||||||
ng-click="toggle.toggle()"></a>
|
ng-click="toggle.toggle()"></a>
|
||||||
<a ng-if="toggle.isActive()" class="menu-icon context-available"></a>
|
<a ng-if="toggle.isActive()" class="menu-icon context-available"></a>
|
||||||
|
|
||||||
<mct-include key="'search-menu'"
|
<mct-include key="'search-menu'"
|
||||||
class="menu-element search-menu-holder"
|
class="menu-element c-search__search-menu-holder"
|
||||||
ng-class="{off: !toggle.isActive()}"
|
ng-class="{off: !toggle.isActive()}"
|
||||||
ng-model="ngModel"
|
ng-model="ngModel"
|
||||||
parameters="{menuVisible: toggle.setState}">
|
parameters="{menuVisible: toggle.setState}">
|
||||||
</mct-include>
|
</mct-include>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a class="holder s-button flex-elem btn-cancel"
|
<a class="s-button c-search__btn-cancel"
|
||||||
ng-show="!(ngModel.input === '' || ngModel.input === undefined)"
|
ng-show="!(ngModel.input === '' || ngModel.input === undefined)"
|
||||||
ng-click="ngModel.input = ''; ngModel.checkAll = true; menuController.checkAll(); controller.search()">
|
ng-click="ngModel.input = ''; ngModel.checkAll = true; menuController.checkAll(); controller.search()">
|
||||||
Cancel</a>
|
Cancel</a>
|
||||||
|
@ -178,9 +178,7 @@ define([
|
|||||||
"key": "exportImageService",
|
"key": "exportImageService",
|
||||||
"implementation": ExportImageService,
|
"implementation": ExportImageService,
|
||||||
"depends": [
|
"depends": [
|
||||||
"$q",
|
"dialogService"
|
||||||
"$timeout",
|
|
||||||
"$log"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
/* global console*/
|
||||||
/**
|
/**
|
||||||
* Module defining ExportImageService. Created by hudsonfoo on 09/02/16
|
* Module defining ExportImageService. Created by hudsonfoo on 09/02/16
|
||||||
*/
|
*/
|
||||||
@ -36,85 +36,71 @@ define(
|
|||||||
/**
|
/**
|
||||||
* The export image service will export any HTML node to
|
* The export image service will export any HTML node to
|
||||||
* JPG, or PNG.
|
* JPG, or PNG.
|
||||||
* @param {object} $q
|
* @param {object} dialogService
|
||||||
* @param {object} $timeout
|
|
||||||
* @param {object} $log
|
|
||||||
* @param {constant} EXPORT_IMAGE_TIMEOUT time in milliseconds before a timeout error is returned
|
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function ExportImageService($q, $timeout, $log) {
|
function ExportImageService(dialogService) {
|
||||||
this.$q = $q;
|
this.exportCount = 0;
|
||||||
this.$timeout = $timeout;
|
this.dialogService = dialogService;
|
||||||
this.$log = $log;
|
|
||||||
this.EXPORT_IMAGE_TIMEOUT = 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeBackgroundColor(element, color) {
|
|
||||||
element.style.backgroundColor = color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders an HTML element into a base64 encoded image
|
* Converts an HTML element into a PNG or JPG Blob.
|
||||||
* as a BLOB, PNG, or JPG.
|
* @private
|
||||||
* @param {node} element that will be converted to an image
|
* @param {node} element that will be converted to an image
|
||||||
* @param {string} type of image to convert the element to
|
* @param {string} type of image to convert the element to.
|
||||||
* @returns {promise}
|
* @returns {promise}
|
||||||
*/
|
*/
|
||||||
ExportImageService.prototype.renderElement = function (element, type, color) {
|
ExportImageService.prototype.renderElement = function (element, imageType, color) {
|
||||||
var defer = this.$q.defer(),
|
var dialogService = this.dialogService,
|
||||||
validTypes = ["png", "jpg", "jpeg"],
|
dialog = dialogService.showBlockingMessage({
|
||||||
renderTimeout,
|
title: "Capturing...",
|
||||||
originalColor;
|
hint: "Capturing an image",
|
||||||
|
unknownProgress: true,
|
||||||
if (validTypes.indexOf(type) === -1) {
|
severity: "info",
|
||||||
this.$log.error("Invalid type requested. Try: (" + validTypes.join(",") + ")");
|
delay: true
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (color) {
|
|
||||||
// Save color to be restored later
|
|
||||||
originalColor = element.style.backgroundColor || '';
|
|
||||||
// Defaulting to white so we can see the chart when printed
|
|
||||||
changeBackgroundColor(element, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTimeout = this.$timeout(function () {
|
|
||||||
defer.reject("html2canvas timed out");
|
|
||||||
this.$log.warn("html2canvas timed out");
|
|
||||||
}.bind(this), this.EXPORT_IMAGE_TIMEOUT);
|
|
||||||
|
|
||||||
try {
|
|
||||||
html2canvas(element, {
|
|
||||||
onrendered: function (canvas) {
|
|
||||||
if (color) {
|
|
||||||
changeBackgroundColor(element, originalColor);
|
|
||||||
}
|
|
||||||
switch (type.toLowerCase()) {
|
|
||||||
case "png":
|
|
||||||
canvas.toBlob(defer.resolve, "image/png");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
case "jpg":
|
|
||||||
case "jpeg":
|
|
||||||
canvas.toBlob(defer.resolve, "image/jpeg");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
defer.reject(e);
|
var mimeType = "image/png";
|
||||||
this.$log.warn("html2canvas failed with error: " + e);
|
if (imageType === "jpg") {
|
||||||
|
mimeType = "image/jpeg";
|
||||||
}
|
}
|
||||||
|
|
||||||
defer.promise.finally(function () {
|
var exportId = 'export-element-' + this.exportCount;
|
||||||
renderTimeout.cancel();
|
this.exportCount++;
|
||||||
if (color) {
|
var oldId = element.id;
|
||||||
changeBackgroundColor(element, originalColor);
|
element.id = exportId;
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return defer.promise;
|
return html2canvas(element, {
|
||||||
|
onclone: function (document) {
|
||||||
|
// Make export style changes to cloned document so that
|
||||||
|
// users don't see view flickering.
|
||||||
|
var clonedElement = document.getElementById(exportId);
|
||||||
|
if (clonedElement && color) {
|
||||||
|
clonedElement.style.backgroundColor = color;
|
||||||
|
}
|
||||||
|
element.id = oldId;
|
||||||
|
}
|
||||||
|
}).then(function (canvas) {
|
||||||
|
dialog.dismiss();
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
return canvas.toBlob(resolve, mimeType);
|
||||||
|
});
|
||||||
|
}, function (error) {
|
||||||
|
console.log('error capturing image', error);
|
||||||
|
dialog.dismiss();
|
||||||
|
var errorDialog = dialogService.showBlockingMessage({
|
||||||
|
title: "Error capturing image",
|
||||||
|
severity: "error",
|
||||||
|
hint: "Image was not captured successfully!",
|
||||||
|
options: [{
|
||||||
|
label: "OK",
|
||||||
|
callback: function () {
|
||||||
|
errorDialog.dismiss();
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +110,7 @@ define(
|
|||||||
* @returns {promise}
|
* @returns {promise}
|
||||||
*/
|
*/
|
||||||
ExportImageService.prototype.exportJPG = function (element, filename, color) {
|
ExportImageService.prototype.exportJPG = function (element, filename, color) {
|
||||||
return this.renderElement(element, "jpeg", color).then(function (img) {
|
return this.renderElement(element, "jpg", color).then(function (img) {
|
||||||
saveAs(img, filename);
|
saveAs(img, filename);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -141,6 +127,17 @@ define(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a screenshot of a DOM node in PNG format.
|
||||||
|
* @param {node} element to be exported
|
||||||
|
* @param {string} filename the exported image
|
||||||
|
* @returns {promise}
|
||||||
|
*/
|
||||||
|
|
||||||
|
ExportImageService.prototype.exportPNGtoSRC = function (element) {
|
||||||
|
return this.renderElement(element, "png");
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* canvas.toBlob() not supported in IE < 10, Opera, and Safari. This polyfill
|
* canvas.toBlob() not supported in IE < 10, Opera, and Safari. This polyfill
|
||||||
* implements the method in browsers that would not otherwise support it.
|
* implements the method in browsers that would not otherwise support it.
|
||||||
@ -149,9 +146,9 @@ define(
|
|||||||
function polyfillToBlob() {
|
function polyfillToBlob() {
|
||||||
if (!HTMLCanvasElement.prototype.toBlob) {
|
if (!HTMLCanvasElement.prototype.toBlob) {
|
||||||
Object.defineProperty(HTMLCanvasElement.prototype, "toBlob", {
|
Object.defineProperty(HTMLCanvasElement.prototype, "toBlob", {
|
||||||
value: function (callback, type, quality) {
|
value: function (callback, mimeType, quality) {
|
||||||
|
|
||||||
var binStr = atob(this.toDataURL(type, quality).split(',')[1]),
|
var binStr = atob(this.toDataURL(mimeType, quality).split(',')[1]),
|
||||||
len = binStr.length,
|
len = binStr.length,
|
||||||
arr = new Uint8Array(len);
|
arr = new Uint8Array(len);
|
||||||
|
|
||||||
@ -159,7 +156,7 @@ define(
|
|||||||
arr[i] = binStr.charCodeAt(i);
|
arr[i] = binStr.charCodeAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(new Blob([arr], {type: type || "image/png"}));
|
callback(new Blob([arr], {type: mimeType || "image/png"}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ define([
|
|||||||
'./autoflow/AutoflowTabularPlugin',
|
'./autoflow/AutoflowTabularPlugin',
|
||||||
'./timeConductor/plugin',
|
'./timeConductor/plugin',
|
||||||
'../../example/imagery/plugin',
|
'../../example/imagery/plugin',
|
||||||
|
'../../platform/features/notebook/bundle',
|
||||||
'../../platform/import-export/bundle',
|
'../../platform/import-export/bundle',
|
||||||
'./summaryWidget/plugin',
|
'./summaryWidget/plugin',
|
||||||
'./URLIndicatorPlugin/URLIndicatorPlugin',
|
'./URLIndicatorPlugin/URLIndicatorPlugin',
|
||||||
@ -40,6 +41,7 @@ define([
|
|||||||
AutoflowPlugin,
|
AutoflowPlugin,
|
||||||
TimeConductorPlugin,
|
TimeConductorPlugin,
|
||||||
ExampleImagery,
|
ExampleImagery,
|
||||||
|
Notebook,
|
||||||
ImportExport,
|
ImportExport,
|
||||||
SummaryWidget,
|
SummaryWidget,
|
||||||
URLIndicatorPlugin,
|
URLIndicatorPlugin,
|
||||||
@ -53,6 +55,7 @@ define([
|
|||||||
Espresso: 'platform/commonUI/themes/espresso',
|
Espresso: 'platform/commonUI/themes/espresso',
|
||||||
LocalStorage: 'platform/persistence/local',
|
LocalStorage: 'platform/persistence/local',
|
||||||
MyItems: 'platform/features/my-items',
|
MyItems: 'platform/features/my-items',
|
||||||
|
Notebook: 'platform/features/notebook',
|
||||||
Snow: 'platform/commonUI/themes/snow'
|
Snow: 'platform/commonUI/themes/snow'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<li class="t-condition">
|
<li class="has-local-controls t-condition">
|
||||||
<label class="t-condition-context">when</label>
|
<label class="t-condition-context">when</label>
|
||||||
<span class="controls">
|
<span class="controls">
|
||||||
<span class="t-configuration"> </span>
|
<span class="t-configuration"> </span>
|
||||||
<span class="t-value-inputs"> </span>
|
<span class="t-value-inputs"> </span>
|
||||||
</span>
|
</span>
|
||||||
<span class="flex-elem l-condition-action-buttons-wrapper">
|
<span class="flex-elem local-control l-condition-action-buttons-wrapper">
|
||||||
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this condition"></a>
|
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this condition"></a>
|
||||||
<a class="s-icon-button icon-trash t-delete" title="Delete this condition"></a>
|
<a class="s-icon-button icon-trash t-delete" title="Delete this condition"></a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="l-widget-rule s-widget-rule l-compact-form">
|
<div class="l-compact-form has-local-controls l-widget-rule s-widget-rule">
|
||||||
<div class="widget-rule-header">
|
<div class="widget-rule-header">
|
||||||
<span class="flex-elem l-widget-thumb-wrapper">
|
<span class="flex-elem l-widget-thumb-wrapper">
|
||||||
<span class="grippy-holder">
|
<span class="grippy-holder">
|
||||||
<span class="t-grippy grippy"></span>
|
<span class="t-grippy grippy local-control"></span>
|
||||||
</span>
|
</span>
|
||||||
<span class="view-control expanded"></span>
|
<span class="view-control expanded"></span>
|
||||||
<span class="t-widget-thumb widget-thumb">
|
<span class="t-widget-thumb widget-thumb">
|
||||||
@ -12,7 +12,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="flex-elem rule-title">Default Title</span>
|
<span class="flex-elem rule-title">Default Title</span>
|
||||||
<span class="flex-elem rule-description grows">Rule description goes here</span>
|
<span class="flex-elem rule-description grows">Rule description goes here</span>
|
||||||
<span class="flex-elem l-rule-action-buttons-wrapper">
|
<span class="flex-elem local-control l-rule-action-buttons-wrapper">
|
||||||
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this rule"></a>
|
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this rule"></a>
|
||||||
<a class="s-icon-button icon-trash t-delete" title="Delete this rule"></a>
|
<a class="s-icon-button icon-trash t-delete" title="Delete this rule"></a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="t-test-data-item l-compact-form l-widget-test-data-item s-widget-test-data-item">
|
<div class="t-test-data-item l-compact-form has-local-controls l-widget-test-data-item s-widget-test-data-item">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<label>Set </label>
|
<label>Set </label>
|
||||||
@ -7,7 +7,7 @@
|
|||||||
<span class="equal-to hidden"> equal to </span>
|
<span class="equal-to hidden"> equal to </span>
|
||||||
<span class="t-value-inputs"></span>
|
<span class="t-value-inputs"></span>
|
||||||
</span>
|
</span>
|
||||||
<span class="flex-elem l-widget-test-data-item-action-buttons-wrapper">
|
<span class="flex-elem local-control l-widget-test-data-item-action-buttons-wrapper">
|
||||||
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this test value"></a>
|
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this test value"></a>
|
||||||
<a class="s-icon-button icon-trash t-delete" title="Delete this test value"></a>
|
<a class="s-icon-button icon-trash t-delete" title="Delete this test value"></a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -55,7 +55,6 @@ requirejs.config({
|
|||||||
"csv": "bower_components/comma-separated-values/csv.min",
|
"csv": "bower_components/comma-separated-values/csv.min",
|
||||||
"EventEmitter": "bower_components/eventemitter3/index",
|
"EventEmitter": "bower_components/eventemitter3/index",
|
||||||
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
||||||
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
|
|
||||||
"moment": "bower_components/moment/moment",
|
"moment": "bower_components/moment/moment",
|
||||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||||
"moment-timezone": "bower_components/moment-timezone/builds/moment-timezone-with-data",
|
"moment-timezone": "bower_components/moment-timezone/builds/moment-timezone-with-data",
|
||||||
@ -75,7 +74,9 @@ requirejs.config({
|
|||||||
"d3-format": "node_modules/d3-format/build/d3-format.min",
|
"d3-format": "node_modules/d3-format/build/d3-format.min",
|
||||||
"d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
|
"d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
|
||||||
"d3-time": "node_modules/d3-time/build/d3-time.min",
|
"d3-time": "node_modules/d3-time/build/d3-time.min",
|
||||||
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
|
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min",
|
||||||
|
"html2canvas": "node_modules/html2canvas/dist/html2canvas.min",
|
||||||
|
"painterro": "node_modules/painterro/build/painterro.min"
|
||||||
},
|
},
|
||||||
|
|
||||||
"shim": {
|
"shim": {
|
||||||
@ -109,6 +110,9 @@ requirejs.config({
|
|||||||
},
|
},
|
||||||
"d3-axis": {
|
"d3-axis": {
|
||||||
"exports": "d3-axis"
|
"exports": "d3-axis"
|
||||||
|
},
|
||||||
|
"dom-to-image": {
|
||||||
|
"exports": "domtoimage"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user