mirror of
https://github.com/nasa/openmct.git
synced 2025-06-18 23:28:14 +00:00
Notebook Vue Version (#2160)
* working entries... wip * componentize entries * embed ability with drag into entry * snapshot action partial * working search * abstract EntryController, working search, drag and drop * keep deleteEntry local to entryController * working snapshotOverlay * fix snapshot object * abstract Embed Controller, working context menu, working remove embed * working preview action in embed context menu * add overlay header with timestamp * working annotate and new entry contextual * Remove old notebook * use same key, remove extra style files * working embeds * fixed markup for snapshot overlay
This commit is contained in:
committed by
Pete Richards
parent
c883bbe6c2
commit
3a28caac06
@ -1,294 +0,0 @@
|
|||||||
define([
|
|
||||||
"legacyRegistry",
|
|
||||||
"./src/controllers/NotebookController",
|
|
||||||
"./src/controllers/NewEntryController",
|
|
||||||
"./src/controllers/SelectSnapshotController",
|
|
||||||
"./src/controllers/LayoutNotebookController",
|
|
||||||
"./src/directives/MCTSnapshot",
|
|
||||||
"./src/directives/EntryDnd",
|
|
||||||
"./src/actions/ViewSnapshot",
|
|
||||||
"./src/actions/AnnotateSnapshot",
|
|
||||||
"./src/actions/RemoveEmbed",
|
|
||||||
"./src/actions/RemoveSnapshot",
|
|
||||||
"./src/actions/NewEntryContextual",
|
|
||||||
"./src/capabilities/NotebookCapability",
|
|
||||||
"./src/policies/CompositionPolicy",
|
|
||||||
"./res/templates/notebook.html",
|
|
||||||
"./res/templates/entry.html",
|
|
||||||
"./res/templates/annotation.html",
|
|
||||||
"./res/templates/notifications.html",
|
|
||||||
"../layout/res/templates/frame.html",
|
|
||||||
"./res/templates/controls/embedControl.html",
|
|
||||||
"./res/templates/controls/snapSelect.html"
|
|
||||||
], function (
|
|
||||||
legacyRegistry,
|
|
||||||
NotebookController,
|
|
||||||
NewEntryController,
|
|
||||||
SelectSnapshotController,
|
|
||||||
LayoutNotebookController,
|
|
||||||
MCTSnapshot,
|
|
||||||
MCTEntryDnd,
|
|
||||||
ViewSnapshotAction,
|
|
||||||
AnnotateSnapshotAction,
|
|
||||||
RemoveEmbedAction,
|
|
||||||
RemoveSnapshotAction,
|
|
||||||
newEntryAction,
|
|
||||||
NotebookCapability,
|
|
||||||
CompositionPolicy,
|
|
||||||
notebookTemplate,
|
|
||||||
entryTemplate,
|
|
||||||
annotationTemplate,
|
|
||||||
notificationsTemplate,
|
|
||||||
frameTemplate,
|
|
||||||
embedControlTemplate,
|
|
||||||
snapSelectTemplate
|
|
||||||
) {
|
|
||||||
legacyRegistry.register("platform/features/notebook", {
|
|
||||||
"name": "Notebook Plugin",
|
|
||||||
"description": "Create and save timestamped notes with embedded object snapshots.",
|
|
||||||
"extensions":
|
|
||||||
{
|
|
||||||
"types": [
|
|
||||||
{
|
|
||||||
"key": "notebook",
|
|
||||||
"name": "Notebook",
|
|
||||||
"cssClass": "icon-notebook",
|
|
||||||
"description": "Create and save timestamped notes with embedded object snapshots.",
|
|
||||||
"features": ["creation"],
|
|
||||||
"model": {
|
|
||||||
"entries": [],
|
|
||||||
"composition": [],
|
|
||||||
"entryTypes": [],
|
|
||||||
"defaultSort": "-createdOn"
|
|
||||||
},
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"key": "defaultSort",
|
|
||||||
"name": "Default Sort",
|
|
||||||
"control": "select",
|
|
||||||
"options": [
|
|
||||||
{
|
|
||||||
"name": "Newest First",
|
|
||||||
"value": "-createdOn"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Oldest First",
|
|
||||||
"value": "createdOn"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"cssClass": "l-inline"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"views": [
|
|
||||||
{
|
|
||||||
"key": "notebook.view",
|
|
||||||
"type": "notebook",
|
|
||||||
"cssClass": "icon-notebook",
|
|
||||||
"name": "notebook",
|
|
||||||
"template": notebookTemplate,
|
|
||||||
"editable": false,
|
|
||||||
"uses": [
|
|
||||||
"composition",
|
|
||||||
"action"
|
|
||||||
],
|
|
||||||
"gestures": [
|
|
||||||
"drop"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"controllers": [
|
|
||||||
{
|
|
||||||
"key": "NotebookController",
|
|
||||||
"implementation": NotebookController,
|
|
||||||
"depends": [
|
|
||||||
"$scope",
|
|
||||||
"dialogService",
|
|
||||||
"popupService",
|
|
||||||
"agentService",
|
|
||||||
"objectService",
|
|
||||||
"navigationService",
|
|
||||||
"now",
|
|
||||||
"actionService",
|
|
||||||
"$timeout",
|
|
||||||
"$element",
|
|
||||||
"$sce"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "NewEntryController",
|
|
||||||
"implementation": NewEntryController,
|
|
||||||
"depends": ["$scope",
|
|
||||||
"$rootScope"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "selectSnapshotController",
|
|
||||||
"implementation": SelectSnapshotController,
|
|
||||||
"depends": ["$scope",
|
|
||||||
"$rootScope"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "LayoutNotebookController",
|
|
||||||
"implementation": LayoutNotebookController,
|
|
||||||
"depends": ["$scope"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"representations": [
|
|
||||||
{
|
|
||||||
"key": "draggedEntry",
|
|
||||||
"template": entryTemplate
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "frameLayoutNotebook",
|
|
||||||
"template": frameTemplate
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"templates": [
|
|
||||||
{
|
|
||||||
"key": "annotate-snapshot",
|
|
||||||
"template": annotationTemplate
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "notificationTemplate",
|
|
||||||
"template": notificationsTemplate
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
{
|
|
||||||
"key": "mctSnapshot",
|
|
||||||
"implementation": MCTSnapshot,
|
|
||||||
"depends": [
|
|
||||||
"$rootScope",
|
|
||||||
"$document",
|
|
||||||
"exportImageService",
|
|
||||||
"dialogService",
|
|
||||||
"notificationService"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "mctEntryDnd",
|
|
||||||
"implementation": MCTEntryDnd,
|
|
||||||
"depends": [
|
|
||||||
"$rootScope",
|
|
||||||
"$compile",
|
|
||||||
"dndService",
|
|
||||||
"typeService",
|
|
||||||
"notificationService"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"key": "view-snapshot",
|
|
||||||
"implementation": ViewSnapshotAction,
|
|
||||||
"name": "View Snapshot",
|
|
||||||
"description": "View the large image in a modal",
|
|
||||||
"category": "embed",
|
|
||||||
"depends": [
|
|
||||||
"$compile"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "annotate-snapshot",
|
|
||||||
"implementation": AnnotateSnapshotAction,
|
|
||||||
"name": "Annotate Snapshot",
|
|
||||||
"cssClass": "icon-pencil labeled",
|
|
||||||
"description": "Annotate embed's snapshot",
|
|
||||||
"category": "embed",
|
|
||||||
"depends": [
|
|
||||||
"dialogService",
|
|
||||||
"dndService",
|
|
||||||
"$rootScope"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"key": "remove-embed",
|
|
||||||
"implementation": RemoveEmbedAction,
|
|
||||||
"name": "Remove...",
|
|
||||||
"cssClass": "icon-trash labeled",
|
|
||||||
"description": "Remove this embed",
|
|
||||||
"category": [
|
|
||||||
"embed",
|
|
||||||
"embed-no-snap"
|
|
||||||
],
|
|
||||||
"depends": [
|
|
||||||
"dialogService"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "remove-snapshot",
|
|
||||||
"implementation": RemoveSnapshotAction,
|
|
||||||
"name": "Remove Snapshot",
|
|
||||||
"cssClass": "icon-trash labeled",
|
|
||||||
"description": "Remove Snapshot of the embed",
|
|
||||||
"category": "embed",
|
|
||||||
"depends": [
|
|
||||||
"dialogService"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "notebook-new-entry",
|
|
||||||
"implementation": newEntryAction,
|
|
||||||
"name": "New Notebook Entry",
|
|
||||||
"cssClass": "icon-notebook labeled",
|
|
||||||
"description": "Add a new Notebook entry",
|
|
||||||
"category": [
|
|
||||||
"view-control"
|
|
||||||
],
|
|
||||||
"depends": [
|
|
||||||
"$compile",
|
|
||||||
"$rootScope",
|
|
||||||
"dialogService",
|
|
||||||
"notificationService",
|
|
||||||
"linkService"
|
|
||||||
],
|
|
||||||
"priority": "preferred"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"licenses": [
|
|
||||||
{
|
|
||||||
"name": "painterro",
|
|
||||||
"version": "0.2.65",
|
|
||||||
"author": "Ivan Borshchov",
|
|
||||||
"description": "Painterro is JavaScript paint widget which allows editing images directly in a browser.",
|
|
||||||
"website": "https://github.com/ivictbor/painterro",
|
|
||||||
"copyright": "Copyright 2017 Ivan Borshchov",
|
|
||||||
"license": "MIT",
|
|
||||||
"link": "https://github.com/ivictbor/painterro/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"capabilities": [
|
|
||||||
{
|
|
||||||
"key": "notebook",
|
|
||||||
"name": "Notebook Capability",
|
|
||||||
"description": "Provides a capability for looking for a notebook domain object",
|
|
||||||
"implementation": NotebookCapability,
|
|
||||||
"depends": [
|
|
||||||
"typeService"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"policies": [
|
|
||||||
{
|
|
||||||
"category": "composition",
|
|
||||||
"implementation": CompositionPolicy,
|
|
||||||
"message": "Objects of this type cannot contain objects of that type."
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"controls": [
|
|
||||||
{
|
|
||||||
"key": "embed-control",
|
|
||||||
"template": embedControlTemplate
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "snapshot-select",
|
|
||||||
"template": snapSelectTemplate
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,118 +0,0 @@
|
|||||||
<div ng-controller="NotebookController as controller" class="mct-notebook w-notebook l-flex-col">
|
|
||||||
<div class="l-notebook-head holder l-flex-row flex-elem">
|
|
||||||
<div class="c-search flex-elem holder grows">
|
|
||||||
<input class="c-search__search-input"
|
|
||||||
type="text" tabindex="10000"
|
|
||||||
ng-model="entrySearch"
|
|
||||||
ng-keyup="controller.search()"/>
|
|
||||||
<a class="c-search__clear-input clear-icon icon-x-in-circle"
|
|
||||||
ng-class="{show: !(entrySearch === '' || entrySearch === undefined)}"
|
|
||||||
ng-click="entrySearch = ''; controller.search()"></a>
|
|
||||||
</div>
|
|
||||||
<div class="notebook-view-controls l-flex-row flex-elem holder">
|
|
||||||
<div class="select notebook-view-controls__filter-time">
|
|
||||||
<select ng-model="showTime">
|
|
||||||
<option value="0" selected="selected">Show all</option>
|
|
||||||
<option value="1">Last hour</option>
|
|
||||||
<option value="8">Last 8 hours</option>
|
|
||||||
<option value="24">Last 24 hours</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="select notebook-view-controls__sort">
|
|
||||||
<select ng-model="sortEntries">
|
|
||||||
<option value="-createdOn" selected="selected">Newest first</option>
|
|
||||||
<option value="createdOn">Oldest first</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- drag area -->
|
|
||||||
<div class="holder flex-elem l-flex-row icon-plus labeled l-notebook-drag-area" ng-click="newEntry($event)"
|
|
||||||
id="newEntry" mct-entry-dnd>
|
|
||||||
<span class="label">To start a new entry, click here or drag and drop any object</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- entries -->
|
|
||||||
<div class="holder flex-elem grows w-notebook-entries t-entries-list" ng-mouseover="handleActive()">
|
|
||||||
<ul>
|
|
||||||
<li class="l-flex-row has-local-controls l-notebook-entry s-notebook-entry"
|
|
||||||
id="{{'entry_'+ entry.id}}"
|
|
||||||
ng-if="hoursFilter(showTime,entry.createdOn)"
|
|
||||||
ng-repeat="entry in model.entries | filter:entrySearch | orderBy: sortEntries track by $index"
|
|
||||||
ng-init="$last && finished(model.entries)"
|
|
||||||
mct-entry-dnd>
|
|
||||||
<div class="holder flex-elem l-flex-row grows w-notebook-entry-time-and-content">
|
|
||||||
<div class="holder flex-elem s-notebook-entry-time">
|
|
||||||
<span>{{entry.createdOn | date:'yyyy-MM-dd'}}</span>
|
|
||||||
<span>{{entry.createdOn | date:'HH:mm:ss'}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="holder flex-elem l-flex-col grows l-notebook-entry-content">
|
|
||||||
<div contenteditable="true"
|
|
||||||
ng-blur="textBlur($event, entry.id)"
|
|
||||||
ng-focus="textFocus($event, entry.id)"
|
|
||||||
ng-model="entry.text"
|
|
||||||
placeholder="Enter text here"
|
|
||||||
class="flex-elem s-input-inline t-notebook-entry-input s-notebook-entry-text"
|
|
||||||
ng-bind="entry.text">
|
|
||||||
</div>
|
|
||||||
<!-- embeds -->
|
|
||||||
<div class="flex-elem entry-embeds l-flex-row">
|
|
||||||
<div class="l-flex-row l-entry-embed {{embed.cssClass}}"
|
|
||||||
ng-repeat="embed in entry.embeds track by $index"
|
|
||||||
ng-class="{ 'has-snapshot' : embed.snapshot }"
|
|
||||||
id="{{embed.id}}">
|
|
||||||
<div class="snap-thumb"
|
|
||||||
ng-if="embed.snapshot"
|
|
||||||
ng-click="viewSnapshot($event,embed.snapshot.src,embed.id,entry.createdOn,this,embed)">
|
|
||||||
<img ng-src="{{embed.snapshot.src}}" src="//:0" alt="{{embed.id}}">
|
|
||||||
</div>
|
|
||||||
<div class="embed-info l-flex-col">
|
|
||||||
<div class="embed-title object-header">
|
|
||||||
<a ng-click='navigate($event,embed.type)'>{{embed.name}}</a>
|
|
||||||
<a class='context-available' ng-click='openMenu($event,embed.type)'></a>
|
|
||||||
</div>
|
|
||||||
<div class="hide-menu" ng-show="false">
|
|
||||||
<div class="menu-element context-menu-wrapper mobile-disable-select">
|
|
||||||
<div class="menu context-menu">
|
|
||||||
<ul>
|
|
||||||
<li ng-repeat="menu in menuEmbed"
|
|
||||||
ng-click="menu.perform($event,embed.snapshot.src,embed.id,entry.createdOn,this,embed)"
|
|
||||||
title="{{menu.getMetadata().description}}"
|
|
||||||
class="{{menu.getMetadata().cssClass}}"
|
|
||||||
ng-if="embed.snapshot">
|
|
||||||
{{menu.getMetadata().name}}
|
|
||||||
</li>
|
|
||||||
<li ng-repeat="menu in menuEmbedNoSnap"
|
|
||||||
ng-click="menu.perform($event,embed.snapshot.src,embed.id,entry.createdOn,this)"
|
|
||||||
title="{{menu.getMetadata().description}}"
|
|
||||||
class="{{menu.getMetadata().cssClass}}"
|
|
||||||
ng-if="!embed.snapshot">
|
|
||||||
{{menu.getMetadata().name}}
|
|
||||||
</li>
|
|
||||||
<li ng-repeat="menu in embedActions"
|
|
||||||
ng-click="menu.perform()"
|
|
||||||
title="{{menu.name}}"
|
|
||||||
class="{{menu.cssClass}}">
|
|
||||||
{{menu.name}}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="embed-date"
|
|
||||||
ng-if="embed.snapshot">{{embed.id| date:'yyyy-MM-dd HH:mm:ss'}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- delete entry -->
|
|
||||||
<div class="holder flex-elem local-control local-controls-hidden notebook-entry-delete">
|
|
||||||
<a class="s-icon-button icon-trash" id={{entry.id}} title="Delete Entry" ng-click="deleteEntry($event)"></a>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,8 +0,0 @@
|
|||||||
<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>
|
|
@ -1,34 +0,0 @@
|
|||||||
<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>
|
|
@ -1,72 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,74 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,132 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module defining ViewSnapshot
|
|
||||||
*/
|
|
||||||
|
|
||||||
var OVERLAY_TEMPLATE = '' +
|
|
||||||
' <div class="abs blocker"></div>' +
|
|
||||||
' <div class="abs outer-holder">' +
|
|
||||||
' <a class="close icon-x-in-circle"></a>' +
|
|
||||||
' <div class="abs inner-holder l-flex-col">' +
|
|
||||||
' <div class="t-contents flex-elem holder grows"></div>' +
|
|
||||||
' <div class="bottom-bar flex-elem holder">' +
|
|
||||||
' <a class="t-done s-button major">Done</a>' +
|
|
||||||
' </div>' +
|
|
||||||
' </div>' +
|
|
||||||
' </div>';
|
|
||||||
|
|
||||||
define([
|
|
||||||
'zepto',
|
|
||||||
"../../res/templates/snapshotHeader.html"
|
|
||||||
],
|
|
||||||
function ($, headerTemplate) {
|
|
||||||
|
|
||||||
var toggleOverlay,
|
|
||||||
overlay,
|
|
||||||
closeButton,
|
|
||||||
doneButton,
|
|
||||||
blocker,
|
|
||||||
overlayContainer,
|
|
||||||
img,
|
|
||||||
annotateButton,
|
|
||||||
annotateImg;
|
|
||||||
|
|
||||||
function ViewSnapshot($compile) {
|
|
||||||
this.$compile = $compile;
|
|
||||||
}
|
|
||||||
|
|
||||||
function openOverlay(url, header) {
|
|
||||||
overlay = document.createElement('div');
|
|
||||||
$(overlay).addClass('abs overlay l-large-view');
|
|
||||||
overlay.innerHTML = OVERLAY_TEMPLATE;
|
|
||||||
overlayContainer = overlay.querySelector('.t-contents');
|
|
||||||
closeButton = overlay.querySelector('a.close');
|
|
||||||
closeButton.addEventListener('click', toggleOverlay);
|
|
||||||
doneButton = overlay.querySelector('a.t-done');
|
|
||||||
doneButton.addEventListener('click', toggleOverlay);
|
|
||||||
blocker = overlay.querySelector('.abs.blocker');
|
|
||||||
blocker.addEventListener('click', toggleOverlay);
|
|
||||||
annotateButton = header.querySelector('a.icon-pencil');
|
|
||||||
annotateButton.addEventListener('click', annotateImg);
|
|
||||||
document.body.appendChild(overlay);
|
|
||||||
img = document.createElement('div');
|
|
||||||
$(img).addClass('abs object-holder t-image-holder s-image-holder');
|
|
||||||
img.innerHTML = '<div class="image-main s-image-main" style="background-image: url(' + url + ');"></div>';
|
|
||||||
overlayContainer.appendChild(header);
|
|
||||||
overlayContainer.appendChild(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeOverlay() {
|
|
||||||
overlayContainer.removeChild(img);
|
|
||||||
document.body.removeChild(overlay);
|
|
||||||
closeButton.removeEventListener('click', toggleOverlay);
|
|
||||||
closeButton = undefined;
|
|
||||||
doneButton.removeEventListener('click', toggleOverlay);
|
|
||||||
doneButton = undefined;
|
|
||||||
blocker.removeEventListener('click', toggleOverlay);
|
|
||||||
blocker = undefined;
|
|
||||||
overlayContainer = undefined;
|
|
||||||
overlay = undefined;
|
|
||||||
img = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewSnapshot.prototype.perform = function ($event, snapshot, embedId, entryId, $scope, embed) {
|
|
||||||
var isOpen = false;
|
|
||||||
|
|
||||||
// onclick for menu items in overlay header context menu
|
|
||||||
$scope.menuPerform = function (menu) {
|
|
||||||
menu.perform();
|
|
||||||
closeOverlay();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create the overlay element and add it to the document's body
|
|
||||||
$scope.cssClass = embed.cssClass;
|
|
||||||
$scope.embedType = embed.type;
|
|
||||||
$scope.entryName = embed.name;
|
|
||||||
$scope.snapDate = +embedId;
|
|
||||||
var element = this.$compile(headerTemplate)($scope);
|
|
||||||
|
|
||||||
var annotateAction = $scope.action.getActions({category: 'embed'})[1];
|
|
||||||
|
|
||||||
toggleOverlay = function () {
|
|
||||||
if (!isOpen) {
|
|
||||||
openOverlay(snapshot, element[0]);
|
|
||||||
isOpen = true;
|
|
||||||
} else {
|
|
||||||
closeOverlay();
|
|
||||||
isOpen = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
annotateImg = function () {
|
|
||||||
closeOverlay();
|
|
||||||
annotateAction.perform($event, snapshot, embedId, entryId, $scope);
|
|
||||||
};
|
|
||||||
|
|
||||||
toggleOverlay();
|
|
||||||
};
|
|
||||||
|
|
||||||
return ViewSnapshot;
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,50 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,367 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/*-- main controller file, here is the core functionality of the notebook plugin --*/
|
|
||||||
|
|
||||||
define(
|
|
||||||
['zepto'],
|
|
||||||
function ($) {
|
|
||||||
|
|
||||||
|
|
||||||
function NotebookController(
|
|
||||||
$scope,
|
|
||||||
dialogService,
|
|
||||||
popupService,
|
|
||||||
agentService,
|
|
||||||
objectService,
|
|
||||||
navigationService,
|
|
||||||
now,
|
|
||||||
actionService,
|
|
||||||
$timeout,
|
|
||||||
$element,
|
|
||||||
$sce
|
|
||||||
) {
|
|
||||||
|
|
||||||
$scope.entriesEl = $(document.body).find('.t-entries-list');
|
|
||||||
$scope.sortEntries = $scope.domainObject.getModel().defaultSort;
|
|
||||||
$scope.showTime = "0";
|
|
||||||
$scope.editEntry = false;
|
|
||||||
$scope.entrySearch = '';
|
|
||||||
$scope.entryTypes = [];
|
|
||||||
$scope.embedActions = [];
|
|
||||||
$scope.currentEntryValue = '';
|
|
||||||
|
|
||||||
var SECONDS_IN_AN_HOUR = 60 * 60 * 1000;
|
|
||||||
|
|
||||||
this.scope = $scope;
|
|
||||||
|
|
||||||
$scope.hoursFilter = function (hours,entryTime) {
|
|
||||||
if (+hours) {
|
|
||||||
return entryTime > (Date.now() - SECONDS_IN_AN_HOUR * (+hours));
|
|
||||||
}else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.scrollToTop = function () {
|
|
||||||
var entriesContainer = $scope.entriesEl.parent();
|
|
||||||
entriesContainer[0].scrollTop = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.findEntryEl = function (entryId) {
|
|
||||||
var element = $($scope.entriesEl).find('#entry_' + entryId);
|
|
||||||
|
|
||||||
if (element[0]) {
|
|
||||||
return element.find("[contenteditable='true']");
|
|
||||||
} else {
|
|
||||||
var entries = $scope.entriesEl.children().children(),
|
|
||||||
lastOrFirst = $scope.sortEntries === "-createdOn" ? 0 : (entries.length - 1);
|
|
||||||
|
|
||||||
return $(entries[lastOrFirst]).find("[contenteditable='true']");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.findEntryPositionById = function (id) {
|
|
||||||
var foundId = -1;
|
|
||||||
|
|
||||||
$scope.domainObject.model.entries.forEach(function (element, index) {
|
|
||||||
if (element.id === id) {
|
|
||||||
foundId = index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return foundId;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.newEntry = function ($event) {
|
|
||||||
$scope.scrollToTop();
|
|
||||||
|
|
||||||
var entries = $scope.domainObject.model.entries,
|
|
||||||
lastEntry = entries[entries.length - 1],
|
|
||||||
id = Date.now();
|
|
||||||
|
|
||||||
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
|
|
||||||
var createdEntry = {'id': id, 'createdOn': id};
|
|
||||||
|
|
||||||
$scope.domainObject.useCapability('mutation', function (model) {
|
|
||||||
model.entries.push(createdEntry);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$scope.findEntryEl(lastEntry.id).focus();
|
|
||||||
|
|
||||||
$scope.domainObject.useCapability('mutation', function (model) {
|
|
||||||
model.entries[entries.length - 1].createdOn = id;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$scope.entrySearch = '';
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
$scope.deleteEntry = function ($event) {
|
|
||||||
var delId = +$event.currentTarget.id;
|
|
||||||
var errorDialog = dialogService.showBlockingMessage({
|
|
||||||
severity: "error",
|
|
||||||
title: "This action will permanently delete this Notebook entry. Do you want to continue?",
|
|
||||||
minimized: true, // want the notification to be minimized initially (don't show banner)
|
|
||||||
options: [{
|
|
||||||
label: "OK",
|
|
||||||
callback: function () {
|
|
||||||
errorDialog.dismiss();
|
|
||||||
var elementPos = $scope.findEntryPositionById(delId);
|
|
||||||
|
|
||||||
if (elementPos !== -1) {
|
|
||||||
$scope.domainObject.useCapability('mutation', function (model) {
|
|
||||||
model.entries.splice(elementPos, 1);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
window.console.log('delete error');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
},{
|
|
||||||
label: "Cancel",
|
|
||||||
callback: function () {
|
|
||||||
errorDialog.dismiss();
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.textFocus = function ($event, entryId) {
|
|
||||||
if ($event.srcElement) {
|
|
||||||
$scope.currentEntryValue = $event.srcElement.innerText;
|
|
||||||
} else {
|
|
||||||
$event.target.innerText = '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//On text blur(when focus is removed)
|
|
||||||
$scope.textBlur = function ($event, entryId) {
|
|
||||||
// entryId is the unique numeric based on the original createdOn
|
|
||||||
if ($event.target) {
|
|
||||||
var elementPos = $scope.findEntryPositionById(+entryId);
|
|
||||||
|
|
||||||
// If the text of an entry has been changed, then update the text and the modifiedOn numeric
|
|
||||||
// Otherwise, don't do anything
|
|
||||||
if ($scope.currentEntryValue !== $event.target.innerText) {
|
|
||||||
$scope.domainObject.useCapability('mutation', function (model) {
|
|
||||||
model.entries[elementPos].text = $event.target.innerText;
|
|
||||||
model.entries[elementPos].modified = Date.now();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.finished = function (model) {
|
|
||||||
var lastEntry = model[model.length - 1];
|
|
||||||
|
|
||||||
if (!lastEntry.text) {
|
|
||||||
$scope.findEntryEl(lastEntry.id).focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.handleActive = function () {
|
|
||||||
var newEntry = $scope.entriesEl.find('.active');
|
|
||||||
if (newEntry) {
|
|
||||||
newEntry.removeClass('active');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
$scope.clearSearch = function () {
|
|
||||||
$scope.entrySearch = '';
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.viewSnapshot = function ($event,snapshot,embedId,entryId,$innerScope,domainObject) {
|
|
||||||
var viewAction = $scope.action.getActions({category: 'embed'})[0];
|
|
||||||
viewAction.perform($event, snapshot, embedId, entryId, $innerScope, domainObject);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.renderImage = function (img) {
|
|
||||||
return URL.createObjectURL(img);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.getDomainObj = function (id) {
|
|
||||||
return objectService.getObjects([id]);
|
|
||||||
};
|
|
||||||
|
|
||||||
function refreshComp(change) {
|
|
||||||
if (change && change.length) {
|
|
||||||
change[0].getCapability('action').getActions({key: 'remove'})[0].perform();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.actionToMenuOption = function (action) {
|
|
||||||
return {
|
|
||||||
key: action.getMetadata().key,
|
|
||||||
name: action.getMetadata().name,
|
|
||||||
cssClass: action.getMetadata().cssClass,
|
|
||||||
perform: action.perform
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Maintain all "conclude-editing" and "save" actions in the
|
|
||||||
// present context.
|
|
||||||
function updateActions() {
|
|
||||||
$scope.menuEmbed = $scope.action ?
|
|
||||||
$scope.action.getActions({category: 'embed'}) :
|
|
||||||
[];
|
|
||||||
|
|
||||||
$scope.menuEmbedNoSnap = $scope.action ?
|
|
||||||
$scope.action.getActions({category: 'embed-no-snap'}) :
|
|
||||||
[];
|
|
||||||
|
|
||||||
$scope.menuActions = $scope.action ?
|
|
||||||
$scope.action.getActions({key: 'window'}) :
|
|
||||||
[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update set of actions whenever the action capability
|
|
||||||
// changes or becomes available.
|
|
||||||
$scope.$watch("action", updateActions);
|
|
||||||
|
|
||||||
$scope.navigate = function ($event,embedType) {
|
|
||||||
if ($event) {
|
|
||||||
$event.preventDefault();
|
|
||||||
}
|
|
||||||
$scope.getDomainObj(embedType).then(function (resp) {
|
|
||||||
navigationService.setNavigation(resp[embedType]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.saveSnap = function (url,embedPos,entryPos) {
|
|
||||||
var snapshot = false;
|
|
||||||
if (url) {
|
|
||||||
if (embedPos !== -1 && entryPos !== -1) {
|
|
||||||
var reader = new window.FileReader();
|
|
||||||
reader.readAsDataURL(url);
|
|
||||||
reader.onloadend = function () {
|
|
||||||
snapshot = reader.result;
|
|
||||||
$scope.domainObject.useCapability('mutation', function (model) {
|
|
||||||
if (model.entries[entryPos]) {
|
|
||||||
model.entries[entryPos].embeds[embedPos].snapshot = {
|
|
||||||
'src': snapshot,
|
|
||||||
'type': url.type,
|
|
||||||
'size': url.size,
|
|
||||||
'modified': Date.now()
|
|
||||||
};
|
|
||||||
model.entries[entryPos].embeds[embedPos].id = Date.now();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
$scope.domainObject.useCapability('mutation', function (model) {
|
|
||||||
model.entries[entryPos].embeds[embedPos].snapshot = snapshot;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*---popups menu embeds----*/
|
|
||||||
|
|
||||||
function getEmbedActions(embedType) {
|
|
||||||
if (!$scope.embedActions.length) {
|
|
||||||
$scope.getDomainObj(embedType).then(function (resp) {
|
|
||||||
$scope.embedActions = [];
|
|
||||||
$scope.embedActions.push($scope.actionToMenuOption(
|
|
||||||
$scope.action.getActions({key: 'mct-preview-action', selectedObject: resp[embedType]})[0]
|
|
||||||
));
|
|
||||||
$scope.embedActions.push($scope.actionToMenuOption(
|
|
||||||
$scope.action.getActions({key: 'window', selectedObject: resp[embedType]})[0]
|
|
||||||
));
|
|
||||||
$scope.embedActions.push({
|
|
||||||
key: 'navigate',
|
|
||||||
name: 'Go to Original',
|
|
||||||
cssClass: '',
|
|
||||||
perform: function () {
|
|
||||||
$scope.navigate('', embedType);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.openMenu = function ($event,embedType) {
|
|
||||||
$event.preventDefault();
|
|
||||||
|
|
||||||
getEmbedActions(embedType);
|
|
||||||
|
|
||||||
var body = $(document).find('body'),
|
|
||||||
initiatingEvent = agentService.isMobile() ?
|
|
||||||
'touchstart' : 'mousedown',
|
|
||||||
dismissExistingMenu,
|
|
||||||
menu;
|
|
||||||
|
|
||||||
var container = $($event.currentTarget).parent().parent();
|
|
||||||
|
|
||||||
menu = container.find('.menu-element');
|
|
||||||
|
|
||||||
// Remove the context menu
|
|
||||||
function dismiss() {
|
|
||||||
container.find('.hide-menu').append(menu);
|
|
||||||
body.off("mousedown", dismiss);
|
|
||||||
dismissExistingMenu = undefined;
|
|
||||||
$scope.embedActions = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dismiss any menu which was already showing
|
|
||||||
if (dismissExistingMenu) {
|
|
||||||
dismissExistingMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...and record the presence of this menu.
|
|
||||||
dismissExistingMenu = dismiss;
|
|
||||||
|
|
||||||
popupService.display(menu, [$event.pageX,$event.pageY], {
|
|
||||||
marginX: 0,
|
|
||||||
marginY: -50
|
|
||||||
});
|
|
||||||
|
|
||||||
// Stop propagation so that clicks or touches on the menu do not close the menu
|
|
||||||
menu.on(initiatingEvent, function (event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
$timeout(dismiss, 300);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Dismiss the menu when body is clicked/touched elsewhere
|
|
||||||
// ('mousedown' because 'click' breaks left-click context menus)
|
|
||||||
// ('touchstart' because 'touch' breaks context menus up)
|
|
||||||
body.on(initiatingEvent, dismiss);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
$scope.$watchCollection("composition", refreshComp);
|
|
||||||
|
|
||||||
$scope.$watch('domainObject.getModel().defaultSort', function (newDefaultSort, oldDefaultSort) {
|
|
||||||
if (newDefaultSort !== oldDefaultSort) {
|
|
||||||
$scope.sortEntries = newDefaultSort;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$on('$destroy', function () {});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return NotebookController;
|
|
||||||
});
|
|
@ -1,44 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*
|
|
||||||
* Open MCT includes source code licensed under additional open source
|
|
||||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
|
||||||
* this source code distribution or the Licensing information page available
|
|
||||||
* at runtime from the About dialog for additional information.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
);
|
|
215
src/plugins/notebook/plugin.js
Normal file
215
src/plugins/notebook/plugin.js
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define([
|
||||||
|
"./src/controllers/NotebookController",
|
||||||
|
"./src/controllers/NewEntryController",
|
||||||
|
"./src/controllers/SelectSnapshotController",
|
||||||
|
"./src/actions/NewEntryContextual",
|
||||||
|
"./src/actions/AnnotateSnapshot",
|
||||||
|
"./src/directives/MCTSnapshot",
|
||||||
|
"./src/directives/EntryDnd",
|
||||||
|
"./res/templates/controls/snapSelect.html",
|
||||||
|
"./res/templates/controls/embedControl.html",
|
||||||
|
"./res/templates/annotation.html",
|
||||||
|
"./res/templates/draggedEntry.html"
|
||||||
|
], function (
|
||||||
|
NotebookController,
|
||||||
|
NewEntryController,
|
||||||
|
SelectSnapshotController,
|
||||||
|
newEntryAction,
|
||||||
|
AnnotateSnapshotAction,
|
||||||
|
MCTSnapshotDirective,
|
||||||
|
EntryDndDirective,
|
||||||
|
snapSelectTemplate,
|
||||||
|
embedControlTemplate,
|
||||||
|
annotationTemplate,
|
||||||
|
draggedEntryTemplate
|
||||||
|
) {
|
||||||
|
var installed = false;
|
||||||
|
|
||||||
|
function NotebookPlugin() {
|
||||||
|
return function install(openmct) {
|
||||||
|
if (installed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
installed = true;
|
||||||
|
|
||||||
|
openmct.legacyRegistry.register('notebook', {
|
||||||
|
name: 'Notebook Plugin',
|
||||||
|
extensions: {
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
key: 'notebook',
|
||||||
|
name: 'Notebook',
|
||||||
|
cssClass: 'icon-notebook',
|
||||||
|
description: 'Create and save timestamped notes with embedded object snapshots.',
|
||||||
|
features: 'creation',
|
||||||
|
model: {
|
||||||
|
entries: [],
|
||||||
|
composition: [],
|
||||||
|
entryTypes: [],
|
||||||
|
defaultSort: '-createdOn'
|
||||||
|
},
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
key: 'defaultSort',
|
||||||
|
name: 'Default Sort',
|
||||||
|
control: 'select',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Newest First',
|
||||||
|
value: "-createdOn",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Oldest First',
|
||||||
|
value: "createdOn"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
cssClass: 'l-inline'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
"key": "notebook-new-entry",
|
||||||
|
"implementation": newEntryAction,
|
||||||
|
"name": "New Notebook Entry",
|
||||||
|
"cssClass": "icon-notebook labeled",
|
||||||
|
"description": "Add a new Notebook entry",
|
||||||
|
"category": [
|
||||||
|
"view-control"
|
||||||
|
],
|
||||||
|
"depends": [
|
||||||
|
"$compile",
|
||||||
|
"$rootScope",
|
||||||
|
"dialogService",
|
||||||
|
"notificationService",
|
||||||
|
"linkService"
|
||||||
|
],
|
||||||
|
"priority": "preferred"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "annotate-snapshot",
|
||||||
|
"implementation": AnnotateSnapshotAction,
|
||||||
|
"name": "Annotate Snapshot",
|
||||||
|
"cssClass": "icon-pencil labeled",
|
||||||
|
"description": "Annotate embed's snapshot",
|
||||||
|
"category": "embed",
|
||||||
|
"depends": [
|
||||||
|
"dialogService",
|
||||||
|
"dndService",
|
||||||
|
"$rootScope"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
controllers: [
|
||||||
|
{
|
||||||
|
"key": "NewEntryController",
|
||||||
|
"implementation": NewEntryController,
|
||||||
|
"depends": ["$scope",
|
||||||
|
"$rootScope"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "selectSnapshotController",
|
||||||
|
"implementation": SelectSnapshotController,
|
||||||
|
"depends": ["$scope",
|
||||||
|
"$rootScope"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
controls: [
|
||||||
|
{
|
||||||
|
"key": "snapshot-select",
|
||||||
|
"template": snapSelectTemplate
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "embed-control",
|
||||||
|
"template": embedControlTemplate
|
||||||
|
}
|
||||||
|
],
|
||||||
|
templates: [
|
||||||
|
{
|
||||||
|
"key": "annotate-snapshot",
|
||||||
|
"template": annotationTemplate
|
||||||
|
}
|
||||||
|
],
|
||||||
|
directives: [
|
||||||
|
{
|
||||||
|
"key": "mctSnapshot",
|
||||||
|
"implementation": MCTSnapshotDirective,
|
||||||
|
"depends": [
|
||||||
|
"$rootScope",
|
||||||
|
"$document",
|
||||||
|
"exportImageService",
|
||||||
|
"dialogService",
|
||||||
|
"notificationService"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "mctEntryDnd",
|
||||||
|
"implementation": EntryDndDirective,
|
||||||
|
"depends": [
|
||||||
|
"$rootScope",
|
||||||
|
"$compile",
|
||||||
|
"dndService",
|
||||||
|
"typeService",
|
||||||
|
"notificationService"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
representations: [
|
||||||
|
{
|
||||||
|
"key": "draggedEntry",
|
||||||
|
"template": draggedEntryTemplate
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
openmct.legacyRegistry.enable('notebook');
|
||||||
|
|
||||||
|
openmct.objectViews.addProvider({
|
||||||
|
key: 'notebook-vue',
|
||||||
|
name: 'Notebook View',
|
||||||
|
cssClass: 'icon-notebook',
|
||||||
|
canView: function (domainObject) {
|
||||||
|
return domainObject.type === 'notebook';
|
||||||
|
},
|
||||||
|
view: function (domainObject) {
|
||||||
|
var controller = new NotebookController (openmct, domainObject);
|
||||||
|
|
||||||
|
return {
|
||||||
|
show: controller.show,
|
||||||
|
destroy: controller.destroy
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NotebookPlugin;
|
||||||
|
});
|
@ -25,6 +25,5 @@
|
|||||||
ng-options="opt.value as opt.name for opt in options"
|
ng-options="opt.value as opt.name for opt in options"
|
||||||
ng-required="ngRequired"
|
ng-required="ngRequired"
|
||||||
name="mctControl">
|
name="mctControl">
|
||||||
<!-- <option value="" ng-show="!ngModel[field]">- Select One -</option> -->
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
36
src/plugins/notebook/res/templates/embed.html
Normal file
36
src/plugins/notebook/res/templates/embed.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<div
|
||||||
|
class="l-flex-row l-entry-embed"
|
||||||
|
v-bind:class="[embed.cssClass]">
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="snap-thumb"
|
||||||
|
v-if="embed.snapshot"
|
||||||
|
v-on:click="openSnapshot">
|
||||||
|
<img v-bind:src="embed.snapshot.src">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="embed-info l-flex-col">
|
||||||
|
<div class="embed-title object-header">
|
||||||
|
<a v-on:click="navigate(embed.type)">{{embed.name}}</a>
|
||||||
|
<a class='context-available' v-on:click="toggleActionMenu"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hide-menu hidden">
|
||||||
|
<div class="menu-element context-menu-wrapper mobile-disable-select">
|
||||||
|
<div class="menu context-menu">
|
||||||
|
<ul>
|
||||||
|
<li v-for="action in actions"
|
||||||
|
v-bind:class="[action.cssClass]"
|
||||||
|
v-on:click="action.perform(embed, entry)">
|
||||||
|
{{ action.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="embed-date" v-if="embed.snapshot">
|
||||||
|
{{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
35
src/plugins/notebook/res/templates/entry.html
Normal file
35
src/plugins/notebook/res/templates/entry.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<li class="l-flex-row has-local-controls l-notebook-entry s-notebook-entry"
|
||||||
|
v-on:drop="dropOnEntry(entry.id)"
|
||||||
|
v-on:dragover="dragoverOnEntry"
|
||||||
|
>
|
||||||
|
|
||||||
|
<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>{{formatTime(entry.createdOn, 'YYYY-MM-DD')}}</span>
|
||||||
|
<span>{{formatTime(entry.createdOn, 'HH:mm:ss')}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="holder flex-elem l-flex-col grows l-notebook-entry-content">
|
||||||
|
<div class="flex-elem s-input-inline t-notebook-entry-input s-notebook-entry-text"
|
||||||
|
contenteditable="true"
|
||||||
|
ref="contenteditable"
|
||||||
|
v-on:blur="textBlur($event, entry.id)"
|
||||||
|
v-on:focus="textFocus($event, entry.id)"
|
||||||
|
v-bind:key="entry.id"
|
||||||
|
v-html="entry.text">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-elem entry-embeds l-flex-row">
|
||||||
|
<notebook-embed
|
||||||
|
v-for="(embed, index) in entry.embeds"
|
||||||
|
v-bind:embed="embed"
|
||||||
|
v-bind:entry="entry"
|
||||||
|
></notebook-embed>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="holder flex-elem local-control local-controls-hidden notebook-entry-delete">
|
||||||
|
<a class="s-icon-button icon-trash" title="Delete Entry" v-on:click="deleteEntry"></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
46
src/plugins/notebook/res/templates/notebook.html
Normal file
46
src/plugins/notebook/res/templates/notebook.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<div 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"
|
||||||
|
v-model="entrySearch"
|
||||||
|
v-on:keyup="search($event)"/>
|
||||||
|
<a class="c-search__clear-input clear-icon icon-x-in-circle"
|
||||||
|
v-bind:class="[entrySearch ? 'show': '']"
|
||||||
|
v-on:click="entrySearch = ''; search($event)"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="notebook-view-controls l-flex-row flex-elem holder">
|
||||||
|
<div class="select notebook-view-controls__filter-time">
|
||||||
|
<select v-model="showTime">
|
||||||
|
<option value="0" selected="selected">Show all</option>
|
||||||
|
<option value="1">Last hour</option>
|
||||||
|
<option value="8">Last 8 hours</option>
|
||||||
|
<option value="24">Last 24 hours</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="select notebook-view-controls__sort">
|
||||||
|
<select v-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" v-on: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>
|
||||||
|
<notebook-entry
|
||||||
|
v-for="entry in filterBySearch(entries, entrySearch)"
|
||||||
|
v-bind:entry="entry"
|
||||||
|
></notebook-entry>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
50
src/plugins/notebook/res/templates/viewSnapshot.html
Normal file
50
src/plugins/notebook/res/templates/viewSnapshot.html
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<div class="abs overlay l-large-view">
|
||||||
|
<div class="abs blocker" v-on:click="close"></div>
|
||||||
|
|
||||||
|
<div class="abs outer-holder">
|
||||||
|
|
||||||
|
<a
|
||||||
|
class="close icon-x-in-circle"
|
||||||
|
v-on:click="close">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="abs inner-holder l-flex-col">
|
||||||
|
<div class="t-contents flex-elem holder grows">
|
||||||
|
|
||||||
|
<div class="t-snapshot abs l-view-header">
|
||||||
|
<div class="abs object-browse-bar l-flex-row">
|
||||||
|
<div class="left flex-elem l-flex-row grows">
|
||||||
|
<div class="object-header flex-elem l-flex-row grows">
|
||||||
|
<div class="type-icon flex-elem embed-icon holder" v-bind:class="embed.cssClass"></div>
|
||||||
|
<div class="title-label flex-elem holder flex-can-shrink">{{embed.name}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
|
||||||
|
<div class="flex-elem holder flex-can-shrink s-snapshot-datetime">
|
||||||
|
SNAPSHOT {{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}}
|
||||||
|
</div>
|
||||||
|
<a class="s-button icon-pencil" title="Annotate">
|
||||||
|
<span class="title-label">Annotate</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="abs object-holder t-image-holder s-image-holder">
|
||||||
|
<div
|
||||||
|
class="image-main s-image-main"
|
||||||
|
v-bind:style="{ backgroundImage: 'url(' + embed.snapshot.src + ')' }">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="bottom-bar flex-elem holder"
|
||||||
|
v-on:click="close">
|
||||||
|
|
||||||
|
<a class="t-done s-button major">Done</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -26,6 +26,7 @@
|
|||||||
define(
|
define(
|
||||||
["painterro", "zepto"],
|
["painterro", "zepto"],
|
||||||
function (Painterro, $) {
|
function (Painterro, $) {
|
||||||
|
|
||||||
var annotationStruct = {
|
var annotationStruct = {
|
||||||
title: "Annotate Snapshot",
|
title: "Annotate Snapshot",
|
||||||
template: "annotate-snapshot",
|
template: "annotate-snapshot",
|
@ -90,7 +90,7 @@ define(
|
|||||||
var dialogService = this.dialogService;
|
var dialogService = this.dialogService;
|
||||||
var rootScope = this.$rootScope;
|
var rootScope = this.$rootScope;
|
||||||
rootScope.newEntryText = '';
|
rootScope.newEntryText = '';
|
||||||
// Create the overlay element and add it to the document's body
|
// // Create the overlay element and add it to the document's body
|
||||||
this.$rootScope.selObj = domainObj;
|
this.$rootScope.selObj = domainObj;
|
||||||
this.$rootScope.selValue = "";
|
this.$rootScope.selValue = "";
|
||||||
var newScope = rootScope.$new();
|
var newScope = rootScope.$new();
|
||||||
@ -187,7 +187,7 @@ define(
|
|||||||
var domainObject = context.domainObject;
|
var domainObject = context.domainObject;
|
||||||
|
|
||||||
if (domainObject) {
|
if (domainObject) {
|
||||||
if (domainObject.getModel().type === 'Notebook') {
|
if (domainObject.getModel().type === 'notebook') {
|
||||||
// do not allow in context of a notebook
|
// do not allow in context of a notebook
|
||||||
return false;
|
return false;
|
||||||
} else if (domainObject.getModel().type.includes('imagery')) {
|
} else if (domainObject.getModel().type.includes('imagery')) {
|
130
src/plugins/notebook/src/actions/snapshotAction.js
Normal file
130
src/plugins/notebook/src/actions/snapshotAction.js
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
define(
|
||||||
|
['zepto'],
|
||||||
|
function ($) {
|
||||||
|
|
||||||
|
function SnapshotAction (exportImageService, dialogService, context) {
|
||||||
|
this.exportImageService = exportImageService;
|
||||||
|
this.dialogService = dialogService;
|
||||||
|
this.domainObject = context.domainObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
SnapshotAction.prototype.perform = function () {
|
||||||
|
var elementToSnapshot =
|
||||||
|
$(document.body).find(".overlay .object-holder")[0] ||
|
||||||
|
$(document.body).find("[key='representation.selected.key']")[0];
|
||||||
|
|
||||||
|
$(elementToSnapshot).addClass("s-status-taking-snapshot");
|
||||||
|
|
||||||
|
this.exportImageService.exportPNGtoSRC(elementToSnapshot).then(function (blob) {
|
||||||
|
$(elementToSnapshot).removeClass("s-status-taking-snapshot");
|
||||||
|
|
||||||
|
if (blob) {
|
||||||
|
var reader = new window.FileReader();
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
reader.onloadend = function () {
|
||||||
|
this.saveSnapshot(reader.result, blob.type, blob.size);
|
||||||
|
}.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
SnapshotAction.prototype.saveSnapshot = function (imageURL, imageType, imageSize) {
|
||||||
|
var taskForm = this.generateTaskForm(),
|
||||||
|
domainObject = this.domainObject,
|
||||||
|
domainObjectId = domainObject.getId(),
|
||||||
|
cssClass = domainObject.getCapability('type').typeDef.cssClass,
|
||||||
|
name = domainObject.model.name;
|
||||||
|
|
||||||
|
this.dialogService.getDialogResponse(
|
||||||
|
'overlay-dialog',
|
||||||
|
taskForm,
|
||||||
|
function () {
|
||||||
|
return taskForm.value;
|
||||||
|
}
|
||||||
|
).then(function (options) {
|
||||||
|
var snapshotObject = {
|
||||||
|
src: imageURL,
|
||||||
|
type: imageType,
|
||||||
|
size: imageSize
|
||||||
|
};
|
||||||
|
|
||||||
|
options.notebook.useCapability('mutation', function (model) {
|
||||||
|
var date = Date.now();
|
||||||
|
|
||||||
|
model.entries.push({
|
||||||
|
id: 'entry-' + date,
|
||||||
|
createdOn: date,
|
||||||
|
text: options.entry,
|
||||||
|
embeds: [{
|
||||||
|
name: name,
|
||||||
|
cssClass: cssClass,
|
||||||
|
type: domainObjectId,
|
||||||
|
id: 'embed-' + date,
|
||||||
|
createdOn: date,
|
||||||
|
snapshot: snapshotObject
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
SnapshotAction.prototype.generateTaskForm = function () {
|
||||||
|
var taskForm = {
|
||||||
|
name: "Create a Notebook Entry",
|
||||||
|
hint: "Please select a Notebook",
|
||||||
|
sections: [{
|
||||||
|
rows: [{
|
||||||
|
name: 'Entry',
|
||||||
|
key: 'entry',
|
||||||
|
control: 'textarea',
|
||||||
|
required: false,
|
||||||
|
"cssClass": "l-textarea-sm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Save in Notebook',
|
||||||
|
key: 'notebook',
|
||||||
|
control: 'locator',
|
||||||
|
validate: validateLocation
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
var overlayModel = {
|
||||||
|
title: taskForm.name,
|
||||||
|
message: 'AHAHAH',
|
||||||
|
structure: taskForm,
|
||||||
|
value: {'entry': ""}
|
||||||
|
};
|
||||||
|
|
||||||
|
function validateLocation(newParentObj) {
|
||||||
|
return newParentObj.model.type === 'notebook';
|
||||||
|
}
|
||||||
|
|
||||||
|
return overlayModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
return SnapshotAction;
|
||||||
|
}
|
||||||
|
);
|
198
src/plugins/notebook/src/controllers/EmbedController.js
Normal file
198
src/plugins/notebook/src/controllers/EmbedController.js
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define([
|
||||||
|
'moment',
|
||||||
|
'zepto',
|
||||||
|
'../utils/SnapshotOverlay',
|
||||||
|
],
|
||||||
|
function (
|
||||||
|
Moment,
|
||||||
|
$,
|
||||||
|
SnapshotOverlay
|
||||||
|
) {
|
||||||
|
function EmbedController (openmct, domainObject) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
this.objectService = openmct.$injector.get('objectService');
|
||||||
|
this.navigationService = openmct.$injector.get('navigationService');
|
||||||
|
this.popupService = openmct.$injector.get('popupService');
|
||||||
|
this.agentService = openmct.$injector.get('agentService');
|
||||||
|
this.dialogService = openmct.$injector.get('dialogService');
|
||||||
|
|
||||||
|
|
||||||
|
this.navigate = this.navigate.bind(this);
|
||||||
|
this.exposedData = this.exposedData.bind(this);
|
||||||
|
this.exposedMethods = this.exposedMethods.bind(this);
|
||||||
|
this.toggleActionMenu = this.toggleActionMenu.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
EmbedController.prototype.navigate = function (embedType) {
|
||||||
|
this.objectService.getObjects([embedType]).then(function (objects) {
|
||||||
|
this.navigationService.setNavigation(objects[embedType]);
|
||||||
|
}.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.openSnapshot = function () {
|
||||||
|
if (!this.snapshotOverlay) {
|
||||||
|
this.snapShotOverlay = new SnapshotOverlay(this.embed, this.formatTime);
|
||||||
|
} else {
|
||||||
|
this.snapShotOverlay = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.formatTime = function (unixTime, timeFormat) {
|
||||||
|
return Moment(unixTime).format(timeFormat);
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.findInArray = function (array, id) {
|
||||||
|
var foundId = -1;
|
||||||
|
|
||||||
|
array.forEach(function (element, index) {
|
||||||
|
if (element.id === id) {
|
||||||
|
foundId = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return foundId;
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.actionToMenuDecorator = function (action) {
|
||||||
|
return {
|
||||||
|
name: action.getMetadata().name,
|
||||||
|
cssClass: action.getMetadata().cssClass,
|
||||||
|
perform: action.perform
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.populateActionMenu = function (objectService, actionService) {
|
||||||
|
return function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
objectService.getObjects([self.embed.type]).then(function (resp) {
|
||||||
|
var domainObject = resp[self.embed.type],
|
||||||
|
previewAction = actionService.getActions({key: 'mct-preview-action', domainObject: domainObject})[0];
|
||||||
|
|
||||||
|
self.actions.push(self.actionToMenuDecorator(previewAction));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.removeEmbedAction = function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'Remove Embed',
|
||||||
|
cssClass: 'icon-trash',
|
||||||
|
perform: function (embed, entry) {
|
||||||
|
var entryPosition = self.findInArray(self.domainObject.entries, entry.id),
|
||||||
|
embedPosition = self.findInArray(entry.embeds, embed.id);
|
||||||
|
|
||||||
|
var warningDialog = self.dialogService.showBlockingMessage({
|
||||||
|
severity: "error",
|
||||||
|
title: "This action will permanently delete this embed. Do you wish to continue?",
|
||||||
|
options: [{
|
||||||
|
label: "OK",
|
||||||
|
callback: function () {
|
||||||
|
entry.embeds.splice(embedPosition, 1);
|
||||||
|
var dirString = 'entries[' + entryPosition + '].embeds';
|
||||||
|
|
||||||
|
self.openmct.objects.mutate(self.domainObject, dirString, entry.embeds);
|
||||||
|
|
||||||
|
warningDialog.dismiss();
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
label: "Cancel",
|
||||||
|
callback: function () {
|
||||||
|
warningDialog.dismiss();
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.toggleActionMenu = function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
var body = $(document.body),
|
||||||
|
container = $(event.target.parentElement.parentElement),
|
||||||
|
initiatingEvent = this.agentService.isMobile() ?
|
||||||
|
'touchstart' : 'mousedown',
|
||||||
|
menu = container.find('.menu-element'),
|
||||||
|
dismissExistingMenu;
|
||||||
|
|
||||||
|
// Remove the context menu
|
||||||
|
function dismiss() {
|
||||||
|
container.find('.hide-menu').append(menu);
|
||||||
|
body.off(initiatingEvent, dismiss);
|
||||||
|
menu.off(initiatingEvent, menuClickHandler);
|
||||||
|
dismissExistingMenu = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function menuClickHandler(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
window.setTimeout(dismiss, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dismiss any menu which was already showing
|
||||||
|
if (dismissExistingMenu) {
|
||||||
|
dismissExistingMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...and record the presence of this menu.
|
||||||
|
dismissExistingMenu = dismiss;
|
||||||
|
|
||||||
|
this.popupService.display(menu, [event.pageX,event.pageY], {
|
||||||
|
marginX: 0,
|
||||||
|
marginY: -50
|
||||||
|
});
|
||||||
|
|
||||||
|
// Stop propagation so that clicks or touches on the menu do not close the menu
|
||||||
|
menu.on(initiatingEvent, menuClickHandler);
|
||||||
|
|
||||||
|
body.on(initiatingEvent, dismiss);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.exposedData = function () {
|
||||||
|
return {
|
||||||
|
actions: [this.removeEmbedAction()],
|
||||||
|
showActionMenu: false
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
EmbedController.prototype.exposedMethods = function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
return {
|
||||||
|
navigate: self.navigate,
|
||||||
|
openSnapshot: self.openSnapshot,
|
||||||
|
formatTime: self.formatTime,
|
||||||
|
toggleActionMenu: self.toggleActionMenu,
|
||||||
|
actionToMenuDecorator: self.actionToMenuDecorator
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return EmbedController;
|
||||||
|
});
|
150
src/plugins/notebook/src/controllers/EntryController.js
Normal file
150
src/plugins/notebook/src/controllers/EntryController.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define([
|
||||||
|
'moment'
|
||||||
|
],
|
||||||
|
function (
|
||||||
|
Moment
|
||||||
|
) {
|
||||||
|
|
||||||
|
function EntryController (openmct, domainObject) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
this.dndService = this.openmct.$injector.get('dndService');
|
||||||
|
this.dialogService = this.openmct.$injector.get('dialogService');
|
||||||
|
|
||||||
|
this.currentEntryValue = '';
|
||||||
|
|
||||||
|
this.exposedMethods = this.exposedMethods.bind(this);
|
||||||
|
this.exposedData = this.exposedData.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
EntryController.prototype.entryPosById = function (entryId) {
|
||||||
|
var foundId = -1;
|
||||||
|
|
||||||
|
this.domainObject.entries.forEach(function (element, index) {
|
||||||
|
if (element.id === entryId) {
|
||||||
|
foundId = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return foundId;
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryController.prototype.textFocus = function ($event) {
|
||||||
|
if ($event.target) {
|
||||||
|
this.currentEntryValue = $event.target.innerText;
|
||||||
|
} else {
|
||||||
|
$event.target.innerText = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryController.prototype.textBlur = function ($event, entryId) {
|
||||||
|
if ($event.target) {
|
||||||
|
var entryPos = this.entryPosById(entryId);
|
||||||
|
|
||||||
|
if (this.currentEntryValue !== $event.target.innerText) {
|
||||||
|
this.openmct.objects.mutate(this.domainObject, 'entries[' + entryPos + '].text', $event.target.innerText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryController.prototype.formatTime = function (unixTime, timeFormat) {
|
||||||
|
return Moment(unixTime).format(timeFormat);
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryController.prototype.deleteEntry = function () {
|
||||||
|
var entryPos = this.entryPosById(this.entry.id),
|
||||||
|
domainObject = this.domainObject,
|
||||||
|
openmct = this.openmct;
|
||||||
|
|
||||||
|
if (entryPos !== -1) {
|
||||||
|
|
||||||
|
var errorDialog = this.dialogService.showBlockingMessage({
|
||||||
|
severity: "error",
|
||||||
|
title: "This action will permanently delete this Notebook entry. Do you wish to continue?",
|
||||||
|
options: [{
|
||||||
|
label: "OK",
|
||||||
|
callback: function () {
|
||||||
|
domainObject.entries.splice(entryPos, 1);
|
||||||
|
openmct.objects.mutate(domainObject, 'entries', domainObject.entries);
|
||||||
|
|
||||||
|
errorDialog.dismiss();
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
label: "Cancel",
|
||||||
|
callback: function () {
|
||||||
|
errorDialog.dismiss();
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryController.prototype.dropOnEntry = function (entryId) {
|
||||||
|
var selectedObject = this.dndService.getData('mct-domain-object'),
|
||||||
|
selectedObjectId = selectedObject.getId(),
|
||||||
|
selectedModel = selectedObject.getModel(),
|
||||||
|
cssClass = selectedObject.getCapability('type').typeDef.cssClass,
|
||||||
|
entryPos = this.entryPosById(entryId),
|
||||||
|
currentEntryEmbeds = this.domainObject.entries[entryPos].embeds,
|
||||||
|
newEmbed = {
|
||||||
|
type: selectedObjectId,
|
||||||
|
id: '' + Date.now(),
|
||||||
|
cssClass: cssClass,
|
||||||
|
name: selectedModel.name,
|
||||||
|
snapshot: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
currentEntryEmbeds.push(newEmbed);
|
||||||
|
this.openmct.objects.mutate(this.domainObject, 'entries[' + entryPos + '].embeds', currentEntryEmbeds);
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryController.prototype.dragoverOnEntry = function () {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryController.prototype.exposedData = function () {
|
||||||
|
return {
|
||||||
|
openmct: this.openmct,
|
||||||
|
domainObject: this.domainObject,
|
||||||
|
dndService: this.dndService,
|
||||||
|
dialogService: this.dialogService,
|
||||||
|
currentEntryValue: this.currentEntryValue
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
EntryController.prototype.exposedMethods = function () {
|
||||||
|
return {
|
||||||
|
entryPosById: this.entryPosById,
|
||||||
|
textFocus: this.textFocus,
|
||||||
|
textBlur: this.textBlur,
|
||||||
|
formatTime: this.formatTime,
|
||||||
|
deleteEntry: this.deleteEntry,
|
||||||
|
dropOnEntry: this.dropOnEntry,
|
||||||
|
dragoverOnEntry: this.dragoverOnEntry
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return EntryController;
|
||||||
|
});
|
@ -31,8 +31,7 @@ define(
|
|||||||
$scope.snapshot = undefined;
|
$scope.snapshot = undefined;
|
||||||
$scope.snapToggle = true;
|
$scope.snapToggle = true;
|
||||||
$scope.entryText = '';
|
$scope.entryText = '';
|
||||||
var annotateAction = $rootScope.selObj.getCapability('action').getActions(
|
var annotateAction = $rootScope.selObj.getCapability('action').getActions({key: 'annotate-snapshot'})[0];
|
||||||
{category: 'embed'})[1];
|
|
||||||
|
|
||||||
$scope.$parent.$parent.ngModel[$scope.$parent.$parent.field] = $rootScope.selObj;
|
$scope.$parent.$parent.ngModel[$scope.$parent.$parent.field] = $rootScope.selObj;
|
||||||
$scope.objectName = $rootScope.selObj.getModel().name;
|
$scope.objectName = $rootScope.selObj.getModel().name;
|
174
src/plugins/notebook/src/controllers/NotebookController.js
Normal file
174
src/plugins/notebook/src/controllers/NotebookController.js
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
define([
|
||||||
|
'vue',
|
||||||
|
'./EntryController',
|
||||||
|
'./EmbedController',
|
||||||
|
'../../res/templates/notebook.html',
|
||||||
|
'../../res/templates/entry.html',
|
||||||
|
'../../res/templates/embed.html'
|
||||||
|
],
|
||||||
|
function (
|
||||||
|
Vue,
|
||||||
|
EntryController,
|
||||||
|
EmbedController,
|
||||||
|
NotebookTemplate,
|
||||||
|
EntryTemplate,
|
||||||
|
EmbedTemplate
|
||||||
|
) {
|
||||||
|
|
||||||
|
function NotebookController(openmct, domainObject) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
this.entrySearch = '';
|
||||||
|
this.objectService = openmct.$injector.get('objectService');
|
||||||
|
this.actionService = openmct.$injector.get('actionService');
|
||||||
|
|
||||||
|
this.show = this.show.bind(this);
|
||||||
|
this.destroy = this.destroy.bind(this);
|
||||||
|
this.newEntry = this.newEntry.bind(this);
|
||||||
|
this.entryPosById = this.entryPosById.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
NotebookController.prototype.initializeVue = function (container) {
|
||||||
|
var self = this,
|
||||||
|
entryController = new EntryController(this.openmct, this.domainObject),
|
||||||
|
embedController = new EmbedController(this.openmct, this.domainObject);
|
||||||
|
|
||||||
|
this.container = container;
|
||||||
|
|
||||||
|
var notebookEmbed = {
|
||||||
|
props:['embed', 'entry'],
|
||||||
|
template: EmbedTemplate,
|
||||||
|
data: embedController.exposedData,
|
||||||
|
methods: embedController.exposedMethods(),
|
||||||
|
beforeMount: embedController.populateActionMenu(self.objectService, self.actionService)
|
||||||
|
};
|
||||||
|
|
||||||
|
var entryComponent = {
|
||||||
|
props:['entry'],
|
||||||
|
template: EntryTemplate,
|
||||||
|
components: {
|
||||||
|
'notebook-embed': notebookEmbed
|
||||||
|
},
|
||||||
|
data: entryController.exposedData,
|
||||||
|
methods: entryController.exposedMethods(),
|
||||||
|
mounted: self.focusOnEntry
|
||||||
|
};
|
||||||
|
|
||||||
|
var notebookVue = Vue.extend({
|
||||||
|
template: NotebookTemplate,
|
||||||
|
components: {
|
||||||
|
'notebook-entry': entryComponent
|
||||||
|
},
|
||||||
|
data: function () {
|
||||||
|
return {
|
||||||
|
entrySearch: self.entrySearch,
|
||||||
|
showTime: '0',
|
||||||
|
sortEntries: '-createdOn',
|
||||||
|
entries: self.domainObject.entries,
|
||||||
|
currentEntryValue: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
search: function (event) {
|
||||||
|
if (event.target.value) {
|
||||||
|
this.entrySearch = event.target.value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
newEntry: self.newEntry,
|
||||||
|
filterBySearch: self.filterBySearch
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.NotebookVue = new notebookVue();
|
||||||
|
container.appendChild(this.NotebookVue.$mount().$el);
|
||||||
|
};
|
||||||
|
|
||||||
|
NotebookController.prototype.newEntry = function (event) {
|
||||||
|
|
||||||
|
var entries = this.domainObject.entries,
|
||||||
|
lastEntryIndex = entries.length - 1,
|
||||||
|
lastEntry = entries[lastEntryIndex],
|
||||||
|
date = Date.now();
|
||||||
|
|
||||||
|
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds.length) {
|
||||||
|
var createdEntry = {'id': 'entry-' + date, 'createdOn': date, 'embeds':[]};
|
||||||
|
|
||||||
|
entries.push(createdEntry);
|
||||||
|
this.openmct.objects.mutate(this.domainObject, 'entries', entries);
|
||||||
|
} else {
|
||||||
|
lastEntry.createdOn = date;
|
||||||
|
|
||||||
|
this.openmct.objects.mutate(this.domainObject, 'entries[entries.length-1]', lastEntry);
|
||||||
|
this.focusOnEntry.bind(this.NotebookVue.$children[lastEntryIndex])();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.entrySearch = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
NotebookController.prototype.entryPosById = function (entryId) {
|
||||||
|
var foundId = -1;
|
||||||
|
|
||||||
|
this.domainObject.entries.forEach(function (element, index) {
|
||||||
|
if (element.id === entryId) {
|
||||||
|
foundId = index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return foundId;
|
||||||
|
};
|
||||||
|
|
||||||
|
NotebookController.prototype.focusOnEntry = function () {
|
||||||
|
if (!this.entry.text) {
|
||||||
|
this.$refs.contenteditable.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NotebookController.prototype.filterBySearch = function (entryArray, filterString) {
|
||||||
|
if (filterString) {
|
||||||
|
var lowerCaseFilterString = filterString.toLowerCase();
|
||||||
|
|
||||||
|
return entryArray.filter(function (entry) {
|
||||||
|
if (entry.text) {
|
||||||
|
return entry.text.toLowerCase().includes(lowerCaseFilterString);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return entryArray;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NotebookController.prototype.show = function (container) {
|
||||||
|
this.initializeVue(container);
|
||||||
|
};
|
||||||
|
|
||||||
|
NotebookController.prototype.destroy = function (container) {
|
||||||
|
this.NotebookVue.$destroy(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return NotebookController;
|
||||||
|
});
|
@ -31,9 +31,11 @@ define(['zepto'], function ($) {
|
|||||||
var selectedModel = selectedObject.getModel();
|
var selectedModel = selectedObject.getModel();
|
||||||
var cssClass = selectedObject.getCapability('type').typeDef.cssClass;
|
var cssClass = selectedObject.getCapability('type').typeDef.cssClass;
|
||||||
var entryId = -1;
|
var entryId = -1;
|
||||||
|
var embedId = -1;
|
||||||
$scope.clearSearch();
|
$scope.clearSearch();
|
||||||
if ($element[0].id === 'newEntry') {
|
if ($element[0].id === 'newEntry') {
|
||||||
entryId = $scope.domainObject.model.entries.length;
|
entryId = $scope.domainObject.model.entries.length;
|
||||||
|
embedId = 0;
|
||||||
var lastEntry = $scope.domainObject.model.entries[entryId - 1];
|
var lastEntry = $scope.domainObject.model.entries[entryId - 1];
|
||||||
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
|
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
|
||||||
$scope.domainObject.useCapability('mutation', function (model) {
|
$scope.domainObject.useCapability('mutation', function (model) {
|
||||||
@ -82,6 +84,8 @@ define(['zepto'], function ($) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
embedId = $scope.domainObject.model.entries[entryId].embeds.length - 1;
|
||||||
|
|
||||||
if (selectedObject) {
|
if (selectedObject) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
* Open MCT, Copyright (c) 2014-2018, United States Government
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
* Administration. All rights reserved.
|
* Administration. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -20,35 +20,47 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
|
||||||
* This bundle implements object types and associated views for
|
|
||||||
* display-building.
|
|
||||||
*/
|
|
||||||
define(
|
|
||||||
[],
|
|
||||||
function () {
|
|
||||||
|
|
||||||
/**
|
define([
|
||||||
* The LayoutNotebookController is responsible for supporting the
|
'vue',
|
||||||
* notebook feature creation on theLayout view.
|
'../../res/templates/viewSnapshot.html'
|
||||||
**/
|
], function (
|
||||||
|
Vue,
|
||||||
|
snapshotOverlayTemplate
|
||||||
|
) {
|
||||||
|
function SnapshotOverlay (embedObject, formatTime) {
|
||||||
|
this.embedObject = embedObject;
|
||||||
|
|
||||||
function LayoutNotebookController($scope) {
|
this.snapshotOverlayVue = new Vue({
|
||||||
$scope.hasNotebookAction = undefined;
|
template: snapshotOverlayTemplate,
|
||||||
|
data: function () {
|
||||||
$scope.newNotebook = undefined;
|
return {
|
||||||
|
embed: embedObject
|
||||||
var actions = $scope.domainObject.getCapability('action');
|
|
||||||
var notebookAction = actions.getActions({'key': 'notebook-new-entry'});
|
|
||||||
if (notebookAction.length > 0) {
|
|
||||||
$scope.hasNotebookAction = true;
|
|
||||||
$scope.newNotebook = function () {
|
|
||||||
notebookAction[0].perform();
|
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
close: this.close.bind(this),
|
||||||
|
formatTime: formatTime
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
return LayoutNotebookController;
|
SnapshotOverlay.prototype.open = function () {
|
||||||
}
|
this.overlay = document.createElement('div');
|
||||||
);
|
this.overlay.classList.add('abs');
|
||||||
|
|
||||||
|
document.body.appendChild(this.overlay);
|
||||||
|
|
||||||
|
this.overlay.appendChild(this.snapshotOverlayVue.$mount().$el);
|
||||||
|
};
|
||||||
|
|
||||||
|
SnapshotOverlay.prototype.close = function (event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.snapshotOverlayVue.$destroy();
|
||||||
|
this.overlay.parentNode.removeChild(this.overlay);
|
||||||
|
};
|
||||||
|
|
||||||
|
return SnapshotOverlay;
|
||||||
|
});
|
@ -27,14 +27,14 @@ 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',
|
||||||
'./telemetryMean/plugin',
|
'./telemetryMean/plugin',
|
||||||
'./plot/plugin',
|
'./plot/plugin',
|
||||||
'./telemetryTable/plugin',
|
'./telemetryTable/plugin',
|
||||||
'./staticRootPlugin/plugin'
|
'./staticRootPlugin/plugin',
|
||||||
|
'./notebook/plugin'
|
||||||
], function (
|
], function (
|
||||||
_,
|
_,
|
||||||
UTCTimeSystem,
|
UTCTimeSystem,
|
||||||
@ -42,19 +42,18 @@ define([
|
|||||||
AutoflowPlugin,
|
AutoflowPlugin,
|
||||||
TimeConductorPlugin,
|
TimeConductorPlugin,
|
||||||
ExampleImagery,
|
ExampleImagery,
|
||||||
Notebook,
|
|
||||||
ImportExport,
|
ImportExport,
|
||||||
SummaryWidget,
|
SummaryWidget,
|
||||||
URLIndicatorPlugin,
|
URLIndicatorPlugin,
|
||||||
TelemetryMean,
|
TelemetryMean,
|
||||||
PlotPlugin,
|
PlotPlugin,
|
||||||
TelemetryTablePlugin,
|
TelemetryTablePlugin,
|
||||||
StaticRootPlugin
|
StaticRootPlugin,
|
||||||
|
Notebook
|
||||||
) {
|
) {
|
||||||
var bundleMap = {
|
var bundleMap = {
|
||||||
LocalStorage: 'platform/persistence/local',
|
LocalStorage: 'platform/persistence/local',
|
||||||
MyItems: 'platform/features/my-items',
|
MyItems: 'platform/features/my-items'
|
||||||
Notebook: 'platform/features/notebook'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var plugins = _.mapValues(bundleMap, function (bundleName, pluginName) {
|
var plugins = _.mapValues(bundleMap, function (bundleName, pluginName) {
|
||||||
@ -159,6 +158,7 @@ define([
|
|||||||
plugins.SummaryWidget = SummaryWidget;
|
plugins.SummaryWidget = SummaryWidget;
|
||||||
plugins.TelemetryMean = TelemetryMean;
|
plugins.TelemetryMean = TelemetryMean;
|
||||||
plugins.URLIndicator = URLIndicatorPlugin;
|
plugins.URLIndicator = URLIndicatorPlugin;
|
||||||
|
plugins.Notebook = Notebook;
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
});
|
});
|
||||||
|
@ -76,3 +76,4 @@
|
|||||||
//@import "../styles/app-start";
|
//@import "../styles/app-start";
|
||||||
|
|
||||||
@import "../styles/conductor/time-conductor-snow";
|
@import "../styles/conductor/time-conductor-snow";
|
||||||
|
@import "../styles/notebook/notebook-snow";
|
Reference in New Issue
Block a user