diff --git a/platform/features/notebook/bundle.js b/platform/features/notebook/bundle.js
deleted file mode 100644
index 28677ee219..0000000000
--- a/platform/features/notebook/bundle.js
+++ /dev/null
@@ -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
- }
- ]
- }
- });
-});
diff --git a/platform/features/notebook/res/templates/notebook.html b/platform/features/notebook/res/templates/notebook.html
deleted file mode 100644
index 53cb8ed4b3..0000000000
--- a/platform/features/notebook/res/templates/notebook.html
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
-
-
- Show all
- Last hour
- Last 8 hours
- Last 24 hours
-
-
-
-
- Newest first
- Oldest first
-
-
-
-
-
-
-
- To start a new entry, click here or drag and drop any object
-
-
-
-
-
-
-
-
- {{entry.createdOn | date:'yyyy-MM-dd'}}
- {{entry.createdOn | date:'HH:mm:ss'}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{embed.id| date:'yyyy-MM-dd HH:mm:ss'}}
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/platform/features/notebook/res/templates/notifications.html b/platform/features/notebook/res/templates/notifications.html
deleted file mode 100644
index 2a9069fa45..0000000000
--- a/platform/features/notebook/res/templates/notifications.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- Notifications
-
-
-
diff --git a/platform/features/notebook/res/templates/snapshotHeader.html b/platform/features/notebook/res/templates/snapshotHeader.html
deleted file mode 100644
index e382ee1eaa..0000000000
--- a/platform/features/notebook/res/templates/snapshotHeader.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
\ No newline at end of file
diff --git a/platform/features/notebook/src/actions/RemoveEmbed.js b/platform/features/notebook/src/actions/RemoveEmbed.js
deleted file mode 100644
index b809859fdd..0000000000
--- a/platform/features/notebook/src/actions/RemoveEmbed.js
+++ /dev/null
@@ -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;
- }
-);
diff --git a/platform/features/notebook/src/actions/RemoveSnapshot.js b/platform/features/notebook/src/actions/RemoveSnapshot.js
deleted file mode 100644
index a675f09f2f..0000000000
--- a/platform/features/notebook/src/actions/RemoveSnapshot.js
+++ /dev/null
@@ -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;
- }
-);
diff --git a/platform/features/notebook/src/actions/ViewSnapshot.js b/platform/features/notebook/src/actions/ViewSnapshot.js
deleted file mode 100644
index a5111bd546..0000000000
--- a/platform/features/notebook/src/actions/ViewSnapshot.js
+++ /dev/null
@@ -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 = '' +
- '
' +
- ' ';
-
-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 = '
';
- 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;
-}
-);
diff --git a/platform/features/notebook/src/capabilities/NotebookCapability.js b/platform/features/notebook/src/capabilities/NotebookCapability.js
deleted file mode 100644
index f8c4e8e4f4..0000000000
--- a/platform/features/notebook/src/capabilities/NotebookCapability.js
+++ /dev/null
@@ -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;
- }
-);
diff --git a/platform/features/notebook/src/controllers/NotebookController.js b/platform/features/notebook/src/controllers/NotebookController.js
deleted file mode 100644
index ffd5d1bc0d..0000000000
--- a/platform/features/notebook/src/controllers/NotebookController.js
+++ /dev/null
@@ -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;
- });
diff --git a/platform/features/notebook/src/policies/CompositionPolicy.js b/platform/features/notebook/src/policies/CompositionPolicy.js
deleted file mode 100644
index fc6ddb2f0d..0000000000
--- a/platform/features/notebook/src/policies/CompositionPolicy.js
+++ /dev/null
@@ -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;
- }
-);
diff --git a/src/plugins/notebook/plugin.js b/src/plugins/notebook/plugin.js
new file mode 100644
index 0000000000..82630b7bdb
--- /dev/null
+++ b/src/plugins/notebook/plugin.js
@@ -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;
+});
diff --git a/platform/features/notebook/res/templates/annotation.html b/src/plugins/notebook/res/templates/annotation.html
similarity index 100%
rename from platform/features/notebook/res/templates/annotation.html
rename to src/plugins/notebook/res/templates/annotation.html
diff --git a/platform/features/notebook/res/templates/controls/embedControl.html b/src/plugins/notebook/res/templates/controls/embedControl.html
similarity index 100%
rename from platform/features/notebook/res/templates/controls/embedControl.html
rename to src/plugins/notebook/res/templates/controls/embedControl.html
diff --git a/platform/features/notebook/res/templates/controls/snapSelect.html b/src/plugins/notebook/res/templates/controls/snapSelect.html
similarity index 93%
rename from platform/features/notebook/res/templates/controls/snapSelect.html
rename to src/plugins/notebook/res/templates/controls/snapSelect.html
index 0f89fb2705..8f4bf64cb5 100644
--- a/platform/features/notebook/res/templates/controls/snapSelect.html
+++ b/src/plugins/notebook/res/templates/controls/snapSelect.html
@@ -25,6 +25,5 @@
ng-options="opt.value as opt.name for opt in options"
ng-required="ngRequired"
name="mctControl">
-
\ No newline at end of file
diff --git a/platform/features/notebook/res/templates/entry.html b/src/plugins/notebook/res/templates/draggedEntry.html
similarity index 100%
rename from platform/features/notebook/res/templates/entry.html
rename to src/plugins/notebook/res/templates/draggedEntry.html
diff --git a/src/plugins/notebook/res/templates/embed.html b/src/plugins/notebook/res/templates/embed.html
new file mode 100644
index 0000000000..7aaa2c6ea7
--- /dev/null
+++ b/src/plugins/notebook/res/templates/embed.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}}
+
+
+
\ No newline at end of file
diff --git a/src/plugins/notebook/res/templates/entry.html b/src/plugins/notebook/res/templates/entry.html
new file mode 100644
index 0000000000..209f03c10f
--- /dev/null
+++ b/src/plugins/notebook/res/templates/entry.html
@@ -0,0 +1,35 @@
+
+
+
+
+ {{formatTime(entry.createdOn, 'YYYY-MM-DD')}}
+ {{formatTime(entry.createdOn, 'HH:mm:ss')}}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/plugins/notebook/res/templates/notebook.html b/src/plugins/notebook/res/templates/notebook.html
new file mode 100644
index 0000000000..5992277468
--- /dev/null
+++ b/src/plugins/notebook/res/templates/notebook.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+ Show all
+ Last hour
+ Last 8 hours
+ Last 24 hours
+
+
+
+
+ Newest first
+ Oldest first
+
+
+
+
+
+
+
+ To start a new entry, click here or drag and drop any object
+
+
+
+
+
\ No newline at end of file
diff --git a/src/plugins/notebook/res/templates/viewSnapshot.html b/src/plugins/notebook/res/templates/viewSnapshot.html
new file mode 100644
index 0000000000..77b23f11b5
--- /dev/null
+++ b/src/plugins/notebook/res/templates/viewSnapshot.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SNAPSHOT {{formatTime(embed.createdOn, 'YYYY-MM-DD HH:mm:ss')}}
+
+
+ Annotate
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/features/notebook/src/actions/AnnotateSnapshot.js b/src/plugins/notebook/src/actions/AnnotateSnapshot.js
similarity index 99%
rename from platform/features/notebook/src/actions/AnnotateSnapshot.js
rename to src/plugins/notebook/src/actions/AnnotateSnapshot.js
index b58973be80..5cbd48dfb2 100644
--- a/platform/features/notebook/src/actions/AnnotateSnapshot.js
+++ b/src/plugins/notebook/src/actions/AnnotateSnapshot.js
@@ -26,6 +26,7 @@
define(
["painterro", "zepto"],
function (Painterro, $) {
+
var annotationStruct = {
title: "Annotate Snapshot",
template: "annotate-snapshot",
diff --git a/platform/features/notebook/src/actions/NewEntryContextual.js b/src/plugins/notebook/src/actions/NewEntryContextual.js
similarity index 98%
rename from platform/features/notebook/src/actions/NewEntryContextual.js
rename to src/plugins/notebook/src/actions/NewEntryContextual.js
index 08be83d59c..1dfbaea325 100644
--- a/platform/features/notebook/src/actions/NewEntryContextual.js
+++ b/src/plugins/notebook/src/actions/NewEntryContextual.js
@@ -90,7 +90,7 @@ define(
var dialogService = this.dialogService;
var rootScope = this.$rootScope;
rootScope.newEntryText = '';
- // Create the overlay element and add it to the document's body
+ // // Create the overlay element and add it to the document's body
this.$rootScope.selObj = domainObj;
this.$rootScope.selValue = "";
var newScope = rootScope.$new();
@@ -187,7 +187,7 @@ define(
var domainObject = context.domainObject;
if (domainObject) {
- if (domainObject.getModel().type === 'Notebook') {
+ if (domainObject.getModel().type === 'notebook') {
// do not allow in context of a notebook
return false;
} else if (domainObject.getModel().type.includes('imagery')) {
diff --git a/src/plugins/notebook/src/actions/snapshotAction.js b/src/plugins/notebook/src/actions/snapshotAction.js
new file mode 100644
index 0000000000..9f3451dd03
--- /dev/null
+++ b/src/plugins/notebook/src/actions/snapshotAction.js
@@ -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;
+ }
+);
diff --git a/src/plugins/notebook/src/controllers/EmbedController.js b/src/plugins/notebook/src/controllers/EmbedController.js
new file mode 100644
index 0000000000..5080206e15
--- /dev/null
+++ b/src/plugins/notebook/src/controllers/EmbedController.js
@@ -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;
+});
diff --git a/src/plugins/notebook/src/controllers/EntryController.js b/src/plugins/notebook/src/controllers/EntryController.js
new file mode 100644
index 0000000000..7c1475fd11
--- /dev/null
+++ b/src/plugins/notebook/src/controllers/EntryController.js
@@ -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;
+});
diff --git a/platform/features/notebook/src/controllers/NewEntryController.js b/src/plugins/notebook/src/controllers/NewEntryController.js
similarity index 95%
rename from platform/features/notebook/src/controllers/NewEntryController.js
rename to src/plugins/notebook/src/controllers/NewEntryController.js
index 6df17225e7..3c092c8b9a 100644
--- a/platform/features/notebook/src/controllers/NewEntryController.js
+++ b/src/plugins/notebook/src/controllers/NewEntryController.js
@@ -31,8 +31,7 @@ define(
$scope.snapshot = undefined;
$scope.snapToggle = true;
$scope.entryText = '';
- var annotateAction = $rootScope.selObj.getCapability('action').getActions(
- {category: 'embed'})[1];
+ var annotateAction = $rootScope.selObj.getCapability('action').getActions({key: 'annotate-snapshot'})[0];
$scope.$parent.$parent.ngModel[$scope.$parent.$parent.field] = $rootScope.selObj;
$scope.objectName = $rootScope.selObj.getModel().name;
diff --git a/src/plugins/notebook/src/controllers/NotebookController.js b/src/plugins/notebook/src/controllers/NotebookController.js
new file mode 100644
index 0000000000..123673d175
--- /dev/null
+++ b/src/plugins/notebook/src/controllers/NotebookController.js
@@ -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;
+});
diff --git a/platform/features/notebook/src/controllers/SelectSnapshotController.js b/src/plugins/notebook/src/controllers/SelectSnapshotController.js
similarity index 100%
rename from platform/features/notebook/src/controllers/SelectSnapshotController.js
rename to src/plugins/notebook/src/controllers/SelectSnapshotController.js
diff --git a/platform/features/notebook/src/directives/EntryDnd.js b/src/plugins/notebook/src/directives/EntryDnd.js
similarity index 70%
rename from platform/features/notebook/src/directives/EntryDnd.js
rename to src/plugins/notebook/src/directives/EntryDnd.js
index 49612ba2b7..9dc0509051 100644
--- a/platform/features/notebook/src/directives/EntryDnd.js
+++ b/src/plugins/notebook/src/directives/EntryDnd.js
@@ -31,32 +31,34 @@ define(['zepto'], function ($) {
var selectedModel = selectedObject.getModel();
var cssClass = selectedObject.getCapability('type').typeDef.cssClass;
var entryId = -1;
+ var embedId = -1;
$scope.clearSearch();
if ($element[0].id === 'newEntry') {
entryId = $scope.domainObject.model.entries.length;
+ embedId = 0;
var lastEntry = $scope.domainObject.model.entries[entryId - 1];
if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries.push({'createdOn': +Date.now(),
- 'id': +Date.now(),
- 'embeds': [{'type': selectedObject.getId(),
- 'id': '' + Date.now(),
- 'cssClass': cssClass,
- 'name': selectedModel.name,
- 'snapshot': ''
- }]
- });
+ 'id': +Date.now(),
+ 'embeds': [{'type': selectedObject.getId(),
+ 'id': '' + Date.now(),
+ 'cssClass': cssClass,
+ 'name': selectedModel.name,
+ 'snapshot': ''
+ }]
+ });
});
}else {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries[entryId - 1] =
{'createdOn': +Date.now(),
- 'embeds': [{'type': selectedObject.getId(),
- 'id': '' + Date.now(),
- 'cssClass': cssClass,
- 'name': selectedModel.name,
- 'snapshot': ''
- }]
+ 'embeds': [{'type': selectedObject.getId(),
+ 'id': '' + Date.now(),
+ 'cssClass': cssClass,
+ 'name': selectedModel.name,
+ 'snapshot': ''
+ }]
};
});
}
@@ -75,13 +77,15 @@ define(['zepto'], function ($) {
$scope.domainObject.useCapability('mutation', function (model) {
model.entries[entryId].embeds.push({'type': selectedObject.getId(),
- 'id': '' + Date.now(),
- 'cssClass': cssClass,
- 'name': selectedModel.name,
- 'snapshot': ''
- });
+ 'id': '' + Date.now(),
+ 'cssClass': cssClass,
+ 'name': selectedModel.name,
+ 'snapshot': ''
+ });
});
+ embedId = $scope.domainObject.model.entries[entryId].embeds.length - 1;
+
if (selectedObject) {
e.preventDefault();
diff --git a/platform/features/notebook/src/directives/MCTSnapshot.js b/src/plugins/notebook/src/directives/MCTSnapshot.js
similarity index 100%
rename from platform/features/notebook/src/directives/MCTSnapshot.js
rename to src/plugins/notebook/src/directives/MCTSnapshot.js
diff --git a/platform/features/notebook/src/controllers/LayoutNotebookController.js b/src/plugins/notebook/src/utils/SnapshotOverlay.js
similarity index 50%
rename from platform/features/notebook/src/controllers/LayoutNotebookController.js
rename to src/plugins/notebook/src/utils/SnapshotOverlay.js
index c516f1dbb1..b0af26c048 100644
--- a/platform/features/notebook/src/controllers/LayoutNotebookController.js
+++ b/src/plugins/notebook/src/utils/SnapshotOverlay.js
@@ -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
* Administration. All rights reserved.
*
@@ -20,35 +20,47 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
-/**
- * This bundle implements object types and associated views for
- * display-building.
- */
-define(
- [],
- function () {
- /**
- * The LayoutNotebookController is responsible for supporting the
- * notebook feature creation on theLayout view.
- **/
+define([
+ 'vue',
+ '../../res/templates/viewSnapshot.html'
+], function (
+ Vue,
+ snapshotOverlayTemplate
+) {
+ function SnapshotOverlay (embedObject, formatTime) {
+ this.embedObject = embedObject;
- function LayoutNotebookController($scope) {
- $scope.hasNotebookAction = undefined;
-
- $scope.newNotebook = undefined;
-
- var actions = $scope.domainObject.getCapability('action');
- var notebookAction = actions.getActions({'key': 'notebook-new-entry'});
- if (notebookAction.length > 0) {
- $scope.hasNotebookAction = true;
- $scope.newNotebook = function () {
- notebookAction[0].perform();
+ this.snapshotOverlayVue = new Vue({
+ template: snapshotOverlayTemplate,
+ data: function () {
+ return {
+ embed: embedObject
};
+ },
+ methods: {
+ close: this.close.bind(this),
+ formatTime: formatTime
}
- }
+ });
- return LayoutNotebookController;
+ this.open();
}
-);
+ 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;
+});
diff --git a/src/plugins/plugins.js b/src/plugins/plugins.js
index e404e8ebca..84922015ba 100644
--- a/src/plugins/plugins.js
+++ b/src/plugins/plugins.js
@@ -27,14 +27,14 @@ define([
'./autoflow/AutoflowTabularPlugin',
'./timeConductor/plugin',
'../../example/imagery/plugin',
- '../../platform/features/notebook/bundle',
'../../platform/import-export/bundle',
'./summaryWidget/plugin',
'./URLIndicatorPlugin/URLIndicatorPlugin',
'./telemetryMean/plugin',
'./plot/plugin',
'./telemetryTable/plugin',
- './staticRootPlugin/plugin'
+ './staticRootPlugin/plugin',
+ './notebook/plugin'
], function (
_,
UTCTimeSystem,
@@ -42,19 +42,18 @@ define([
AutoflowPlugin,
TimeConductorPlugin,
ExampleImagery,
- Notebook,
ImportExport,
SummaryWidget,
URLIndicatorPlugin,
TelemetryMean,
PlotPlugin,
TelemetryTablePlugin,
- StaticRootPlugin
+ StaticRootPlugin,
+ Notebook
) {
var bundleMap = {
LocalStorage: 'platform/persistence/local',
- MyItems: 'platform/features/my-items',
- Notebook: 'platform/features/notebook'
+ MyItems: 'platform/features/my-items'
};
var plugins = _.mapValues(bundleMap, function (bundleName, pluginName) {
@@ -155,10 +154,11 @@ define([
plugins.ExampleImagery = ExampleImagery;
plugins.Plot = PlotPlugin;
plugins.TelemetryTable = TelemetryTablePlugin;
-
+
plugins.SummaryWidget = SummaryWidget;
plugins.TelemetryMean = TelemetryMean;
plugins.URLIndicator = URLIndicatorPlugin;
+ plugins.Notebook = Notebook;
return plugins;
});
diff --git a/src/styles-new/legacy-styles.scss b/src/styles-new/legacy-styles.scss
index 14c816fa04..44547f5bcc 100644
--- a/src/styles-new/legacy-styles.scss
+++ b/src/styles-new/legacy-styles.scss
@@ -75,4 +75,5 @@
//!********************************* APP STARTUP *!
//@import "../styles/app-start";
-@import "../styles/conductor/time-conductor-snow";
\ No newline at end of file
+@import "../styles/conductor/time-conductor-snow";
+@import "../styles/notebook/notebook-snow";
\ No newline at end of file