Compare commits
	
		
			3 Commits
		
	
	
		
			readme-upd
			...
			sim-rev0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					4d279481a5 | ||
| 
						 | 
					674f608188 | ||
| 
						 | 
					efd34e54db | 
@@ -25,4 +25,4 @@
 | 
			
		||||
    "html2canvas": "^0.4.1",
 | 
			
		||||
    "moment-timezone": "^0.5.13"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -68,6 +68,7 @@
 | 
			
		||||
                ]
 | 
			
		||||
            }));
 | 
			
		||||
            openmct.install(openmct.plugins.SummaryWidget());
 | 
			
		||||
            openmct.install(openmct.plugins.Notebook());
 | 
			
		||||
            openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
 | 
			
		||||
            openmct.time.timeSystem('utc');
 | 
			
		||||
            openmct.start();
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,8 @@ module.exports = function(config) {
 | 
			
		||||
            {pattern: 'node_modules/d3-*/**/*.js', included: false},
 | 
			
		||||
            {pattern: 'node_modules/vue/**/*.js', included: false},
 | 
			
		||||
            {pattern: 'src/**/*', included: false},
 | 
			
		||||
            {pattern: 'node_modules/@cristian77/**/*.js', included: false},
 | 
			
		||||
            {pattern: 'node_modules/dom-to-image/dist/*', included: false},
 | 
			
		||||
            {pattern: 'example/**/*.html', included: false},
 | 
			
		||||
            {pattern: 'example/**/*.js', included: false},
 | 
			
		||||
            {pattern: 'example/**/*.json', included: false},
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								openmct.js
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								openmct.js
									
									
									
									
									
								
							@@ -49,7 +49,9 @@ requirejs.config({
 | 
			
		||||
        "d3-format": "node_modules/d3-format/build/d3-format.min",
 | 
			
		||||
        "d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
 | 
			
		||||
        "d3-time": "node_modules/d3-time/build/d3-time.min",
 | 
			
		||||
        "d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
 | 
			
		||||
        "d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min",
 | 
			
		||||
        "dom-to-image": "node_modules/dom-to-image/dist/dom-to-image.min",
 | 
			
		||||
        "painterro": "node_modules/@cristian77/painterro/build/painterro.min"
 | 
			
		||||
    },
 | 
			
		||||
    "shim": {
 | 
			
		||||
        "angular": {
 | 
			
		||||
@@ -67,6 +69,9 @@ requirejs.config({
 | 
			
		||||
        "moment-duration-format": {
 | 
			
		||||
            "deps": ["moment"]
 | 
			
		||||
        },
 | 
			
		||||
        "painterro": {
 | 
			
		||||
            "exports": "Painterro"
 | 
			
		||||
        },
 | 
			
		||||
        "saveAs": {
 | 
			
		||||
            "exports": "saveAs"
 | 
			
		||||
        },
 | 
			
		||||
@@ -88,6 +93,9 @@ requirejs.config({
 | 
			
		||||
        },
 | 
			
		||||
        "d3-axis": {
 | 
			
		||||
            "exports": "d3-axis"
 | 
			
		||||
        },
 | 
			
		||||
        "dom-to-image": {
 | 
			
		||||
            "exports": "domtoimage"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,8 @@
 | 
			
		||||
    "d3-selection": "1.3.x",
 | 
			
		||||
    "d3-time": "1.0.x",
 | 
			
		||||
    "d3-time-format": "2.1.x",
 | 
			
		||||
    "@cristian77/painterro": "^0.2.48",
 | 
			
		||||
    "dom-to-image": "^2.6.0",
 | 
			
		||||
    "express": "^4.13.1",
 | 
			
		||||
    "minimist": "^1.1.1",
 | 
			
		||||
    "request": "^2.69.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@
 | 
			
		||||
                        <div class='split-pane-component t-object pane primary-pane left'>
 | 
			
		||||
                            <mct-representation mct-object="navigatedObject"
 | 
			
		||||
                                                key="navigatedObject.getCapability('status').get('editing') ? 'edit-object' : 'browse-object'"
 | 
			
		||||
                                                class="abs holder holder-object">
 | 
			
		||||
                                                class="abs holder holder-object t-main-view">
 | 
			
		||||
                            </mct-representation>
 | 
			
		||||
                            <a class="mini-tab-icon anchor-right mobile-hide toggle-pane toggle-inspect flush-right"
 | 
			
		||||
                               title="{{ modelPaneInspect.visible()? 'Hide' : 'Show' }} the Inspection pane"
 | 
			
		||||
 
 | 
			
		||||
@@ -47,8 +47,10 @@ define(
 | 
			
		||||
            urlService,
 | 
			
		||||
            defaultPath
 | 
			
		||||
        ) {
 | 
			
		||||
            var initialPath = ($route.current.params.ids || defaultPath).split("/");
 | 
			
		||||
            var currentIds;
 | 
			
		||||
            var initialPath = ($route.current.params.ids || defaultPath).split("/"),
 | 
			
		||||
                currentIds,
 | 
			
		||||
                actions,
 | 
			
		||||
                previewAction;
 | 
			
		||||
 | 
			
		||||
            $scope.treeModel = {
 | 
			
		||||
                selectedObject: undefined,
 | 
			
		||||
@@ -56,7 +58,22 @@ define(
 | 
			
		||||
                    navigationService.setNavigation(object, true);
 | 
			
		||||
                },
 | 
			
		||||
                allowSelection: function (object) {
 | 
			
		||||
                    return navigationService.shouldNavigate();
 | 
			
		||||
                    // return navigationService.shouldNavigate();
 | 
			
		||||
                    if (navigationService.anyChecksBeforeNavigation()) {
 | 
			
		||||
 | 
			
		||||
                        actions = actions || $scope.domainObject.getCapability('action');
 | 
			
		||||
                        previewAction =  previewAction || actions.getActions({key: 'mct-preview-action'})[0];
 | 
			
		||||
 | 
			
		||||
                        if (previewAction && previewAction.perform) {
 | 
			
		||||
                            previewAction.perform(object);
 | 
			
		||||
                            return false;
 | 
			
		||||
                        } else {
 | 
			
		||||
                            return navigationService.shouldNavigate();
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -109,6 +109,10 @@ define(
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        NavigationService.prototype.anyChecksBeforeNavigation = function () {
 | 
			
		||||
            return this.checks.length;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Check if navigation should proceed.  May prompt a user for input
 | 
			
		||||
         * if any checkFns return messages.  Returns true if the user wishes to
 | 
			
		||||
@@ -162,7 +166,6 @@ define(
 | 
			
		||||
         */
 | 
			
		||||
        NavigationService.prototype.shouldWarnBeforeNavigate = function () {
 | 
			
		||||
            var reasons = [];
 | 
			
		||||
 | 
			
		||||
            this.checks.forEach(function (checkFn) {
 | 
			
		||||
                var reason = checkFn();
 | 
			
		||||
                if (reason) {
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,8 @@ define([
 | 
			
		||||
    "./src/directives/MCTSplitPane",
 | 
			
		||||
    "./src/directives/MCTSplitter",
 | 
			
		||||
    "./src/directives/MCTTree",
 | 
			
		||||
    "./src/directives/MCTPreview",
 | 
			
		||||
    "./src/actions/MCTPreviewAction",
 | 
			
		||||
    "./src/filters/ReverseFilter",
 | 
			
		||||
    "text!./res/templates/bottombar.html",
 | 
			
		||||
    "text!./res/templates/controls/action-button.html",
 | 
			
		||||
@@ -69,6 +71,7 @@ define([
 | 
			
		||||
    "text!./res/templates/controls/selector.html",
 | 
			
		||||
    "text!./res/templates/controls/datetime-picker.html",
 | 
			
		||||
    "text!./res/templates/controls/datetime-field.html",
 | 
			
		||||
    "text!./res/templates/preview.html",
 | 
			
		||||
    'legacyRegistry'
 | 
			
		||||
], function (
 | 
			
		||||
    UrlService,
 | 
			
		||||
@@ -99,6 +102,8 @@ define([
 | 
			
		||||
    MCTSplitPane,
 | 
			
		||||
    MCTSplitter,
 | 
			
		||||
    MCTTree,
 | 
			
		||||
    MCTPreview,
 | 
			
		||||
    MCTPreviewAction,
 | 
			
		||||
    ReverseFilter,
 | 
			
		||||
    bottombarTemplate,
 | 
			
		||||
    actionButtonTemplate,
 | 
			
		||||
@@ -119,6 +124,7 @@ define([
 | 
			
		||||
    selectorTemplate,
 | 
			
		||||
    datetimePickerTemplate,
 | 
			
		||||
    datetimeFieldTemplate,
 | 
			
		||||
    previewTemplate,
 | 
			
		||||
    legacyRegistry
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
@@ -395,6 +401,38 @@ define([
 | 
			
		||||
                    "key": "mctTree",
 | 
			
		||||
                    "implementation": MCTTree,
 | 
			
		||||
                    "depends": ['gestureService']
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "mctPreview",
 | 
			
		||||
                    "implementation": MCTPreview,
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "$rootScope",
 | 
			
		||||
                        "$document",
 | 
			
		||||
                        "exportImageService",
 | 
			
		||||
                        "dialogService",
 | 
			
		||||
                        "notificationService"
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "actions": [
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "mct-preview-action",
 | 
			
		||||
                    "implementation": MCTPreviewAction,
 | 
			
		||||
                    "name": "Preview",
 | 
			
		||||
                    "cssClass": "hide-in-t-main-view icon-eye-open",
 | 
			
		||||
                    "description": "Preview in large dialog",
 | 
			
		||||
                    "category": [
 | 
			
		||||
                        "contextual",
 | 
			
		||||
                         "view-control"
 | 
			
		||||
                    ],
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                      "$compile",
 | 
			
		||||
                      "$rootScope",
 | 
			
		||||
                      "dialogService",
 | 
			
		||||
                      "notificationService",
 | 
			
		||||
                      "linkService"
 | 
			
		||||
                    ],
 | 
			
		||||
                    "priority": "preferred"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "constants": [
 | 
			
		||||
@@ -510,6 +548,10 @@ define([
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "object-inspector",
 | 
			
		||||
                    "template": objectInspectorTemplate
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "mct-preview",
 | 
			
		||||
                    "template": previewTemplate
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "controls": [
 | 
			
		||||
 
 | 
			
		||||
@@ -225,7 +225,8 @@ a.disabled {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.hide,
 | 
			
		||||
.hidden {
 | 
			
		||||
.hidden,
 | 
			
		||||
.t-main-view .hide-in-t-main-view {
 | 
			
		||||
    display: none !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,14 @@
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[class*="icon-"].labeled {
 | 
			
		||||
    // Moved from .s-button and generalized
 | 
			
		||||
    &:before {
 | 
			
		||||
        // Fend off label from icon when it's included
 | 
			
		||||
        margin-right: $interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/************************** CHAR UNICODES */
 | 
			
		||||
 | 
			
		||||
$glyph-icon-alert-rect: '\e900';
 | 
			
		||||
 
 | 
			
		||||
@@ -299,7 +299,7 @@
 | 
			
		||||
		color: $ic;
 | 
			
		||||
	}
 | 
			
		||||
  @if $bgHov != none {
 | 
			
		||||
      &:not(.disabled):hover {
 | 
			
		||||
      &:not([disabled="true"]):not(.disabled):hover {
 | 
			
		||||
          background: $bgHov;
 | 
			
		||||
          color: $fgHov;
 | 
			
		||||
          >.icon,
 | 
			
		||||
 
 | 
			
		||||
@@ -270,37 +270,4 @@
 | 
			
		||||
    @extend .s-summary-widget;
 | 
			
		||||
    @extend .l-summary-widget;
 | 
			
		||||
    padding: $interiorMarginSm $interiorMargin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Hide and show elements in the rule-header on hover
 | 
			
		||||
.l-widget-rule,
 | 
			
		||||
.l-widget-test-data-item {
 | 
			
		||||
    .grippy,
 | 
			
		||||
    .l-rule-action-buttons-wrapper,
 | 
			
		||||
    .l-condition-action-buttons-wrapper,
 | 
			
		||||
    .l-widget-test-data-item-action-buttons-wrapper {
 | 
			
		||||
        @include trans-prop-nice($props: opacity, $dur: 500ms);
 | 
			
		||||
        opacity: 0;
 | 
			
		||||
    }
 | 
			
		||||
    &:hover {
 | 
			
		||||
        .grippy,
 | 
			
		||||
        .l-rule-action-buttons-wrapper,
 | 
			
		||||
        .l-widget-test-data-item-action-buttons-wrapper {
 | 
			
		||||
            @include trans-prop-nice($props: opacity, $dur: 0);
 | 
			
		||||
            opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    .l-rule-action-buttons-wrapper {
 | 
			
		||||
          .t-delete {
 | 
			
		||||
            margin-left: 10px;
 | 
			
		||||
          }
 | 
			
		||||
    }
 | 
			
		||||
    .t-condition {
 | 
			
		||||
        &:hover {
 | 
			
		||||
            .l-condition-action-buttons-wrapper {
 | 
			
		||||
                @include trans-prop-nice($props: opacity, $dur: 0);
 | 
			
		||||
                opacity: 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -34,11 +34,6 @@ $pad: $interiorMargin * $baseRatio;
 | 
			
		||||
    line-height: $btnStdH;
 | 
			
		||||
    padding: 0 $pad;
 | 
			
		||||
 | 
			
		||||
    &.labeled:before {
 | 
			
		||||
        // Icon when it's included
 | 
			
		||||
        margin-right: $interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	&.lg {
 | 
			
		||||
		font-size: 1rem;
 | 
			
		||||
	}
 | 
			
		||||
@@ -59,6 +54,10 @@ $pad: $interiorMargin * $baseRatio;
 | 
			
		||||
        .label, .title-label { display: none; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &[disabled="true"] {
 | 
			
		||||
        opacity: 0.3;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.pause-play {
 | 
			
		||||
        @extend .icon-pause;
 | 
			
		||||
        &.paused {
 | 
			
		||||
 
 | 
			
		||||
@@ -139,7 +139,6 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-local-controls {
 | 
			
		||||
    @include trans-prop-nice(opacity);
 | 
			
		||||
    font-size: 0.7rem;
 | 
			
		||||
    &.s-wrapper-transluc {
 | 
			
		||||
        // Semi-opaque wrapper to visually distinguish a control
 | 
			
		||||
@@ -150,6 +149,19 @@
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.has-local-controls {
 | 
			
		||||
    .local-control {
 | 
			
		||||
        @include trans-prop-nice($props: opacity, $dur: 250ms);
 | 
			
		||||
        opacity: 0;
 | 
			
		||||
    }
 | 
			
		||||
    &:hover {
 | 
			
		||||
        .local-control {
 | 
			
		||||
            @include trans-prop-nice($props: opacity, $dur: 10ms);
 | 
			
		||||
            opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************** VIEW CONTROLS */
 | 
			
		||||
// Expand/collapse > and v arrows, used in tree and plot legend
 | 
			
		||||
// Moved this over from a tree-only context 5/18/17
 | 
			
		||||
@@ -338,7 +350,7 @@ input[type="text"].s-input-inline,
 | 
			
		||||
    @include btnSubtle($bg: $colorSelectBg);
 | 
			
		||||
    @extend .icon-arrow-down; // Context arrow
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    padding: 0 $interiorMargin;
 | 
			
		||||
    line-height: 180%;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    select {
 | 
			
		||||
@@ -349,8 +361,8 @@ input[type="text"].s-input-inline,
 | 
			
		||||
        color: $colorSelectFg;
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        border: none !important;
 | 
			
		||||
        padding: 4px 25px 2px 0px;
 | 
			
		||||
        width: 130%;
 | 
			
		||||
        padding: 0 20px 0 $interiorMargin;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        option {
 | 
			
		||||
            margin: $interiorMargin 0; // Firefox
 | 
			
		||||
        }
 | 
			
		||||
@@ -359,6 +371,7 @@ input[type="text"].s-input-inline,
 | 
			
		||||
        @include transform(translateY(-50%));
 | 
			
		||||
        color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
 | 
			
		||||
        display: block;
 | 
			
		||||
        font-size: 0.8em;
 | 
			
		||||
        pointer-events: none;
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        right: $interiorMargin;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@
 | 
			
		||||
	}
 | 
			
		||||
	min-width: 150px;
 | 
			
		||||
	.l-image-main {
 | 
			
		||||
		background-color: $colorPlotBg;
 | 
			
		||||
        margin-bottom: $interiorMargin;
 | 
			
		||||
	}
 | 
			
		||||
	.l-image-main-controlbar {
 | 
			
		||||
@@ -76,6 +75,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-image-main {
 | 
			
		||||
    background-color: $colorPlotBg;
 | 
			
		||||
	border: 1px solid transparent;
 | 
			
		||||
	&.paused {
 | 
			
		||||
		@extend .s-unsynced;
 | 
			
		||||
 
 | 
			
		||||
@@ -131,16 +131,18 @@ body.mobile {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body.phone.portrait {
 | 
			
		||||
    .pane-tree-showing {
 | 
			
		||||
        .pane.left.treeview {
 | 
			
		||||
            width: $proporMenuOnly !important;
 | 
			
		||||
        }
 | 
			
		||||
        .pane.right.items {
 | 
			
		||||
            left: 0 !important;
 | 
			
		||||
            @include transform(translateX($proporMenuOnly));
 | 
			
		||||
            .holder-object-and-inspector {
 | 
			
		||||
                opacity: 0;
 | 
			
		||||
@include phonePortrait() {
 | 
			
		||||
    body.phone {
 | 
			
		||||
        .pane-tree-showing {
 | 
			
		||||
            .pane.left.treeview {
 | 
			
		||||
                width: $proporMenuOnly !important;
 | 
			
		||||
            }
 | 
			
		||||
            .pane.right.items {
 | 
			
		||||
                left: 0 !important;
 | 
			
		||||
                @include transform(translateX($proporMenuOnly));
 | 
			
		||||
                .holder-object-and-inspector {
 | 
			
		||||
                    opacity: 0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
		$iconEdgeM: 4px;
 | 
			
		||||
		$iconD: $treeSearchInputBarH - ($iconEdgeM*2);
 | 
			
		||||
        @extend .icon-magnify;
 | 
			
		||||
		font-size: 0.8em;
 | 
			
		||||
		font-size: 0.8rem;
 | 
			
		||||
		position: relative;
 | 
			
		||||
 | 
			
		||||
		.search-input {
 | 
			
		||||
@@ -60,7 +60,7 @@
 | 
			
		||||
			position: relative;
 | 
			
		||||
			width: 100%;
 | 
			
		||||
			padding-left: $iconD + $interiorMargin !important;
 | 
			
		||||
			padding-right: ($iconD * 2) + ($interiorMargin * 2) !important;
 | 
			
		||||
			padding-right: $iconD + $interiorMargin !important;
 | 
			
		||||
 | 
			
		||||
			// Make work for mct-control textfield
 | 
			
		||||
			input {
 | 
			
		||||
@@ -82,8 +82,7 @@
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.clear-input {
 | 
			
		||||
            // Hiding for now with addition of Cancel button
 | 
			
		||||
			right: $iconD + $interiorMargin;
 | 
			
		||||
			right: $interiorMargin;
 | 
			
		||||
 | 
			
		||||
			// Icon is visible only when there is text input
 | 
			
		||||
            visibility: hidden;
 | 
			
		||||
@@ -98,16 +97,25 @@
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.menu-icon {
 | 
			
		||||
            // 'v' invoke menu icon
 | 
			
		||||
			font-size: 0.8em;
 | 
			
		||||
			padding-right: $iconEdgeM;
 | 
			
		||||
			right: $iconEdgeM;
 | 
			
		||||
			text-align: right;
 | 
			
		||||
			&:hover {
 | 
			
		||||
				color: pullForward($colorInputIcon, 10%);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
        &.search-filter-by-type {
 | 
			
		||||
            .search-input {
 | 
			
		||||
                padding-right: ($iconD * 2) + ($interiorMargin * 2) !important; // Allow room for menu-icon
 | 
			
		||||
            }
 | 
			
		||||
            .menu-icon {
 | 
			
		||||
                // 'v' invoke menu icon for filtering by type
 | 
			
		||||
                font-size: 0.8em;
 | 
			
		||||
                padding-right: $iconEdgeM;
 | 
			
		||||
                right: $iconEdgeM;
 | 
			
		||||
                text-align: right;
 | 
			
		||||
                &:hover {
 | 
			
		||||
                    color: pullForward($colorInputIcon, 10%);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            .clear-input {
 | 
			
		||||
                right: $iconD + $interiorMargin;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		.search-menu-holder {
 | 
			
		||||
			float: right;
 | 
			
		||||
 
 | 
			
		||||
@@ -158,6 +158,7 @@ body.desktop .frame {
 | 
			
		||||
    // Hide local controls initially and show it them on hover when they're in an element that's in a frame context
 | 
			
		||||
    // Frame template is used because we need to target the lowest nested frame
 | 
			
		||||
    .object-browse-bar .btn-bar {
 | 
			
		||||
        @include trans-prop-nice($props: opacity, $dur: 250ms);
 | 
			
		||||
        opacity: 0;
 | 
			
		||||
        pointer-events: none;
 | 
			
		||||
    }
 | 
			
		||||
@@ -166,6 +167,7 @@ body.desktop .frame {
 | 
			
		||||
    // Handles the case where we have layouts in layouts.
 | 
			
		||||
    &:hover > .object-browse-bar {
 | 
			
		||||
        .btn-bar {
 | 
			
		||||
            @include trans-prop-nice($props: opacity, $dur: 10ms);
 | 
			
		||||
            opacity: 1;
 | 
			
		||||
            pointer-events: inherit;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								platform/commonUI/general/res/templates/preview.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								platform/commonUI/general/res/templates/preview.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
<!--
 | 
			
		||||
 Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 Administration. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 You may obtain a copy of the License at
 | 
			
		||||
 http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 | 
			
		||||
 Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 License for the specific language governing permissions and limitations
 | 
			
		||||
 under the License.
 | 
			
		||||
 | 
			
		||||
 Open MCT includes source code licensed under additional open source
 | 
			
		||||
 licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class="t-frame-inner abs t-object-type-{{ domainObject.getModel().type }}" mct-preview>
 | 
			
		||||
    <div class="abs object-browse-bar l-flex-row">
 | 
			
		||||
        <div class="left flex-elem l-flex-row grows">
 | 
			
		||||
            <mct-representation
 | 
			
		||||
                    key="'object-header-frame'"
 | 
			
		||||
                    mct-object="domainObject"
 | 
			
		||||
                    class="l-flex-row flex-elem object-header grows">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
 | 
			
		||||
            <mct-representation
 | 
			
		||||
                    key="'switcher'"
 | 
			
		||||
                    ng-model="representation"
 | 
			
		||||
                    mct-object="domainObject">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="abs object-holder">
 | 
			
		||||
        <mct-representation
 | 
			
		||||
                key="representation.selected.key"
 | 
			
		||||
                mct-object="representation.selected.key && domainObject">
 | 
			
		||||
        </mct-representation>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										66
									
								
								platform/commonUI/general/src/actions/MCTPreviewAction.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								platform/commonUI/general/src/actions/MCTPreviewAction.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        var PREVIEW_TEMPLATE = '<mct-representation key="\'mct-preview\'"' +
 | 
			
		||||
                                    'class="t-rep-frame holder"' +
 | 
			
		||||
                                    'mct-object="selObj">' +
 | 
			
		||||
                                '</mct-representation>';
 | 
			
		||||
 | 
			
		||||
        function MCTPreview($compile,$rootScope,dialogService,notificationService,linkService,context) {
 | 
			
		||||
            context = context || {};
 | 
			
		||||
            this.domainObject = context.selectedObject || context.domainObject;
 | 
			
		||||
            this.dialogService = dialogService;
 | 
			
		||||
            this.notificationService = notificationService;
 | 
			
		||||
            this.linkService = linkService;
 | 
			
		||||
            this.$rootScope = $rootScope;
 | 
			
		||||
            this.$compile = $compile;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        MCTPreview.prototype.perform = function (object) {
 | 
			
		||||
            var domainObj = object || this.domainObject,
 | 
			
		||||
                rootScope = this.$rootScope;
 | 
			
		||||
 | 
			
		||||
            rootScope.newEntryText = '';
 | 
			
		||||
            this.$rootScope.selObj = domainObj;
 | 
			
		||||
            this.$rootScope.selValue = "";
 | 
			
		||||
 | 
			
		||||
            var newScope = rootScope.$new();
 | 
			
		||||
            newScope.selObj = domainObj;
 | 
			
		||||
            newScope.selValue = "";
 | 
			
		||||
 | 
			
		||||
            this.$compile(PREVIEW_TEMPLATE)(newScope);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        MCTPreview.appliesTo = function (context) {
 | 
			
		||||
            var domainObject = (context || {}).domainObject,
 | 
			
		||||
                status = domainObject.getCapability('status');
 | 
			
		||||
 | 
			
		||||
            return !(status && status.get('editing'));
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return MCTPreview;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										67
									
								
								platform/commonUI/general/src/directives/MCTPreview.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								platform/commonUI/general/src/directives/MCTPreview.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(['zepto', '../services/Overlay'], function ($, Overlay) {
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
     */
 | 
			
		||||
    function MCTPreview($rootScope,$document,exportImageService,dialogService,notificationService) {
 | 
			
		||||
 | 
			
		||||
        function link($scope, $element, $attrs) {
 | 
			
		||||
            var actions = $scope.domainObject.getCapability('action'),
 | 
			
		||||
                notebookAction = actions.getActions({key: 'notebook-new-entry'})[0];
 | 
			
		||||
 | 
			
		||||
            var notebookButton = notebookAction ?
 | 
			
		||||
            [
 | 
			
		||||
                {
 | 
			
		||||
                    class: 'icon-notebook new-notebook-entry',
 | 
			
		||||
                    title: 'New Notebook Entry',
 | 
			
		||||
                    clickHandler: function (event) {
 | 
			
		||||
                        event.stopPropagation();
 | 
			
		||||
                        notebookAction.perform();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            ] : [];
 | 
			
		||||
 | 
			
		||||
            var overlayService = new Overlay({
 | 
			
		||||
                $document: $document,
 | 
			
		||||
                $element: $element[0],
 | 
			
		||||
                $scope: $scope,
 | 
			
		||||
                browseBarButtons: notebookButton
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            overlayService.toggleOverlay();
 | 
			
		||||
 | 
			
		||||
            $scope.$on('$destroy', function () {
 | 
			
		||||
                $element.remove();
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            restrict: 'A',
 | 
			
		||||
            link: link
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return MCTPreview;
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										191
									
								
								platform/commonUI/general/src/services/Overlay.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								platform/commonUI/general/src/services/Overlay.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2018, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
 /**
 | 
			
		||||
 * Module defining OverlayService. Created by deeptailor on 03/29/2018
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
define(['zepto'], function ($) {
 | 
			
		||||
    var OVERLAY_TEMPLATE = '' +
 | 
			
		||||
'    <div class="abs blocker"></div>' +
 | 
			
		||||
'    <div class="abs outer-holder">' +
 | 
			
		||||
'       <a class="close icon-x-in-circle"></a>' +
 | 
			
		||||
'       <div class="abs inner-holder l-flex-col">' +
 | 
			
		||||
'           <div class="t-contents flex-elem holder grows"></div>' +
 | 
			
		||||
'           <div class="bottom-bar flex-elem holder">' +
 | 
			
		||||
'               <a class="t-done s-button major">Done</a>' +
 | 
			
		||||
'           </div>' +
 | 
			
		||||
'       </div>' +
 | 
			
		||||
'    </div>';
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     *  An Overlay Service when instantiated creates an overlay dialog.
 | 
			
		||||
     *  @param {Object} options The options object required to instantiate the overlay service
 | 
			
		||||
     *  options = {
 | 
			
		||||
     *      $document: document object,
 | 
			
		||||
     *      $scope: angular $scope object,
 | 
			
		||||
     *      element: node to be injected into overlay as a view,
 | 
			
		||||
     *      overlayWillMount: callback executed before overlay is injected,
 | 
			
		||||
     *      overlayWillUnmount: callback executed before overlay is removed,
 | 
			
		||||
     *      overlayDidMount: callback executed after overlay is injected,
 | 
			
		||||
     *      overlayDidUnmount: callback executed after overlay is removed
 | 
			
		||||
     *      browseBarButtons: an array of desired buttons to be added to the browse bar of the overlay.
 | 
			
		||||
     *                        the array should consist of button objects containing:
 | 
			
		||||
     *                              a) class - css class to be added to the button div
 | 
			
		||||
     *                              b) title - desired button title
 | 
			
		||||
     *                              c) clickHandler - callback to be added to the click event listener of the button
 | 
			
		||||
     *  }
 | 
			
		||||
     *  $document, $scope and element are required
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function Overlay(options) {
 | 
			
		||||
        this.element = options.$element;
 | 
			
		||||
        this.document = options.$document[0];
 | 
			
		||||
        this.$scope = options.$scope;
 | 
			
		||||
 | 
			
		||||
        this.overlayWillMount = options.overlayWillMount;
 | 
			
		||||
        this.overlayWillUnmount = options.overlayWillUnmount;
 | 
			
		||||
 | 
			
		||||
        this.overlayDidMount = options.overlayDidMount;
 | 
			
		||||
        this.overlayDidUnmount = options.overlayDidUnmount;
 | 
			
		||||
 | 
			
		||||
        this.browseBarButtons = options.browseBarButtons || [];
 | 
			
		||||
        this.buttons = [];
 | 
			
		||||
 | 
			
		||||
        this.openOverlay = this.openOverlay.bind(this);
 | 
			
		||||
        this.closeOverlay = this.closeOverlay.bind(this);
 | 
			
		||||
        this.toggleOverlay = this.toggleOverlay.bind(this);
 | 
			
		||||
        this.removeButtons = this.removeButtons.bind(this);
 | 
			
		||||
 | 
			
		||||
        this.isOverlayOpen = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Overlay.prototype.openOverlay = function () {
 | 
			
		||||
 | 
			
		||||
        if (this.overlayWillMount && typeof this.overlayWillMount === 'function') {
 | 
			
		||||
            this.overlayWillMount();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.overlay = this.document.createElement('div');
 | 
			
		||||
        $(this.overlay).addClass('abs overlay l-large-view');
 | 
			
		||||
        this.overlay.innerHTML = OVERLAY_TEMPLATE;
 | 
			
		||||
 | 
			
		||||
        this.overlayContainer = this.overlay.querySelector('.t-contents');
 | 
			
		||||
 | 
			
		||||
        this.closeButton =  this.overlay.querySelector('a.close');
 | 
			
		||||
        this.closeButton.addEventListener('click', this.toggleOverlay);
 | 
			
		||||
 | 
			
		||||
        this.doneButton = this.overlay.querySelector('a.t-done');
 | 
			
		||||
        this.doneButton.addEventListener('click', this.toggleOverlay);
 | 
			
		||||
 | 
			
		||||
        this.blocker = this.overlay.querySelector('.abs.blocker');
 | 
			
		||||
        this.blocker.addEventListener('click', this.toggleOverlay);
 | 
			
		||||
 | 
			
		||||
        this.document.body.appendChild(this.overlay);
 | 
			
		||||
 | 
			
		||||
        this.overlayContainer.appendChild(this.element);
 | 
			
		||||
 | 
			
		||||
        this.browseBar = this.overlay.querySelector('.object-browse-bar .right');
 | 
			
		||||
 | 
			
		||||
        if (this.browseBarButtons && Array.isArray(this.browseBarButtons)) {
 | 
			
		||||
            this.browseBarButtons.forEach(function (buttonObject) {
 | 
			
		||||
                var button = newButtonTemplate(buttonObject.class, buttonObject.title);
 | 
			
		||||
                this.browseBar.prepend(button);
 | 
			
		||||
                button.addEventListener('click', buttonObject.clickHandler);
 | 
			
		||||
                this.buttons.push(button);
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.overlayDidMount && typeof this.overlayDidMount === 'function') {
 | 
			
		||||
            this.overlayDidMount();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Overlay.prototype.closeOverlay = function () {
 | 
			
		||||
 | 
			
		||||
        if (this.overlayWillUnmount && typeof this.overlayWillUnmount === 'function') {
 | 
			
		||||
            this.overlayWillUnmount();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.overlayContainer.removeChild(this.element);
 | 
			
		||||
        this.document.body.removeChild(this.overlay);
 | 
			
		||||
 | 
			
		||||
        this.closeButton.removeEventListener('click', this.toggleOverlay);
 | 
			
		||||
        this.closeButton = undefined;
 | 
			
		||||
 | 
			
		||||
        this.doneButton.removeEventListener('click', this.toggleOverlay);
 | 
			
		||||
        this.doneButton = undefined;
 | 
			
		||||
 | 
			
		||||
        this.blocker.removeEventListener('click', this.toggleOverlay);
 | 
			
		||||
        this.blocker = undefined;
 | 
			
		||||
 | 
			
		||||
        this.overlayContainer = undefined;
 | 
			
		||||
        this.overlay = undefined;
 | 
			
		||||
 | 
			
		||||
        // if (this.notebookButton) {
 | 
			
		||||
        //     this.browseBar.removeChild(this.notebookButton);
 | 
			
		||||
        //     this.notebookButton.remove();
 | 
			
		||||
        //     this.notebookButton = undefined;
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        this.removeButtons();
 | 
			
		||||
 | 
			
		||||
        if (this.overlayDidUnmount && typeof this.overlayDidUnmount === 'function') {
 | 
			
		||||
            this.overlayDidUnmount();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Overlay.prototype.toggleOverlay = function (event) {
 | 
			
		||||
        if (event) {
 | 
			
		||||
            event.stopPropagation();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!this.isOverlayOpen) {
 | 
			
		||||
            this.openOverlay();
 | 
			
		||||
            this.isOverlayOpen = true;
 | 
			
		||||
        } else {
 | 
			
		||||
            this.closeOverlay();
 | 
			
		||||
            this.isOverlayOpen = false;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Overlay.prototype.removeButtons = function () {
 | 
			
		||||
        this.buttons.forEach(function (button) {
 | 
			
		||||
            button.remove();
 | 
			
		||||
        }.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.buttons = [];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function newButtonTemplate(classString, title) {
 | 
			
		||||
        var NEW_BUTTON_TEMPLATE = '<a class="s-button labeled' + classString + '">' +
 | 
			
		||||
        '<span class="title-label">' + title + '</span>' +
 | 
			
		||||
        '</a>';
 | 
			
		||||
 | 
			
		||||
        var button = document.createElement('div');
 | 
			
		||||
        $(button).addClass('notebook-button-container holder flex-elem');
 | 
			
		||||
        button.innerHTML = NEW_BUTTON_TEMPLATE;
 | 
			
		||||
        return button;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Overlay;
 | 
			
		||||
});
 | 
			
		||||
@@ -21,23 +21,12 @@
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    'zepto'
 | 
			
		||||
    'zepto',
 | 
			
		||||
    '../../../commonUI/general/src/services/Overlay'
 | 
			
		||||
], function (
 | 
			
		||||
    $
 | 
			
		||||
    $,
 | 
			
		||||
    Overlay
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    var OVERLAY_TEMPLATE = '' +
 | 
			
		||||
'    <div class="abs blocker"></div>' +
 | 
			
		||||
'    <div class="abs outer-holder">' +
 | 
			
		||||
'       <a class="close icon-x-in-circle"></a>' +
 | 
			
		||||
'       <div class="abs inner-holder l-flex-col">' +
 | 
			
		||||
'           <div class="t-contents flex-elem holder grows"></div>' +
 | 
			
		||||
'           <div class="bottom-bar flex-elem holder">' +
 | 
			
		||||
'               <a class="t-done s-button major">Done</a>' +
 | 
			
		||||
'           </div>' +
 | 
			
		||||
'       </div>' +
 | 
			
		||||
'    </div>';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * MCT Trigger Modal is intended for use in only one location: inside the
 | 
			
		||||
     * object-header to allow views in a layout to be popped out in a modal.
 | 
			
		||||
@@ -50,9 +39,11 @@ define([
 | 
			
		||||
     * descendent of a `.frame` element.
 | 
			
		||||
     */
 | 
			
		||||
    function MCTTriggerModal($document) {
 | 
			
		||||
        var document = $document[0];
 | 
			
		||||
 | 
			
		||||
        function link($scope, $element) {
 | 
			
		||||
            var actions = $scope.domainObject.getCapability('action'),
 | 
			
		||||
                notebookAction = actions.getActions({key: 'notebook-new-entry'})[0];
 | 
			
		||||
 | 
			
		||||
            var frame = $element.parent();
 | 
			
		||||
 | 
			
		||||
            for (var i = 0; i < 10; i++) {
 | 
			
		||||
@@ -67,61 +58,39 @@ define([
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            frame = frame[0];
 | 
			
		||||
            var layoutContainer = frame.parentElement,
 | 
			
		||||
                isOpen = false,
 | 
			
		||||
                toggleOverlay,
 | 
			
		||||
                overlay,
 | 
			
		||||
                closeButton,
 | 
			
		||||
                doneButton,
 | 
			
		||||
                blocker,
 | 
			
		||||
                overlayContainer;
 | 
			
		||||
 | 
			
		||||
            function openOverlay() {
 | 
			
		||||
                // Remove frame classes from being applied in a non-frame context
 | 
			
		||||
                $(frame).removeClass('frame frame-template');
 | 
			
		||||
                overlay = document.createElement('div');
 | 
			
		||||
                $(overlay).addClass('abs overlay l-large-view');
 | 
			
		||||
                overlay.innerHTML = OVERLAY_TEMPLATE;
 | 
			
		||||
                overlayContainer = overlay.querySelector('.t-contents');
 | 
			
		||||
                closeButton = overlay.querySelector('a.close');
 | 
			
		||||
                closeButton.addEventListener('click', toggleOverlay);
 | 
			
		||||
                doneButton = overlay.querySelector('a.t-done');
 | 
			
		||||
                doneButton.addEventListener('click', toggleOverlay);
 | 
			
		||||
                blocker = overlay.querySelector('.abs.blocker');
 | 
			
		||||
                blocker.addEventListener('click', toggleOverlay);
 | 
			
		||||
                document.body.appendChild(overlay);
 | 
			
		||||
                layoutContainer.removeChild(frame);
 | 
			
		||||
                overlayContainer.appendChild(frame);
 | 
			
		||||
            }
 | 
			
		||||
            var layoutContainer = frame.parentElement;
 | 
			
		||||
 | 
			
		||||
            function closeOverlay() {
 | 
			
		||||
                $(frame).addClass('frame frame-template');
 | 
			
		||||
                overlayContainer.removeChild(frame);
 | 
			
		||||
                layoutContainer.appendChild(frame);
 | 
			
		||||
                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;
 | 
			
		||||
            }
 | 
			
		||||
            var notebookButton = notebookAction ?
 | 
			
		||||
                [
 | 
			
		||||
                    {
 | 
			
		||||
                        class: 'icon-notebook new-notebook-entry',
 | 
			
		||||
                        title: 'New Notebook Entry',
 | 
			
		||||
                        clickHandler: function (event) {
 | 
			
		||||
                            event.stopPropagation();
 | 
			
		||||
                            notebookAction.perform();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                ] : [];
 | 
			
		||||
 | 
			
		||||
            toggleOverlay = function () {
 | 
			
		||||
                if (!isOpen) {
 | 
			
		||||
                    openOverlay();
 | 
			
		||||
                    isOpen = true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    closeOverlay();
 | 
			
		||||
                    isOpen = false;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            var overlayService = new Overlay ({
 | 
			
		||||
                $document: $document,
 | 
			
		||||
                $scope: $scope,
 | 
			
		||||
                $element: frame,
 | 
			
		||||
                overlayWillMount: function () {
 | 
			
		||||
                    $(frame).removeClass('frame frame-template');
 | 
			
		||||
                    layoutContainer.removeChild(frame);
 | 
			
		||||
                },
 | 
			
		||||
                overlayDidUnmount: function () {
 | 
			
		||||
                    $(frame).addClass('frame frame-template');
 | 
			
		||||
                    layoutContainer.appendChild(frame);
 | 
			
		||||
                },
 | 
			
		||||
                browseBarButtons: notebookButton
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            $element.on('click', toggleOverlay);
 | 
			
		||||
            $element.on('click', overlayService.toggleOverlay);
 | 
			
		||||
            $scope.$on('$destroy', function () {
 | 
			
		||||
                $element.off('click', toggleOverlay);
 | 
			
		||||
                $element.off('click', overlayService.toggleOverlay);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,12 @@ define([
 | 
			
		||||
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            $scope = jasmine.createSpyObj('$scope', ['$on']);
 | 
			
		||||
            $scope.domainObject = { getCapability: function () {
 | 
			
		||||
                return { getActions: function () {
 | 
			
		||||
                    return [];
 | 
			
		||||
                }};
 | 
			
		||||
            }};
 | 
			
		||||
 | 
			
		||||
            $element = jasmine.createSpyObj('$element', [
 | 
			
		||||
                'parent',
 | 
			
		||||
                'remove',
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										314
									
								
								platform/features/notebook/bundle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								platform/features/notebook/bundle.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,314 @@
 | 
			
		||||
define([
 | 
			
		||||
    "legacyRegistry",
 | 
			
		||||
    "./src/controllers/NotebookController",
 | 
			
		||||
    "./src/controllers/NewEntryController",
 | 
			
		||||
    "./src/controllers/SelectSnapshotController",
 | 
			
		||||
    "./src/controllers/LayoutNotebookController",
 | 
			
		||||
    "./src/directives/MCTSnapshot",
 | 
			
		||||
    "../layout/src/MCTTriggerModal",
 | 
			
		||||
    "./src/directives/EntryDnd",
 | 
			
		||||
    "./src/actions/ViewSnapshot",
 | 
			
		||||
    "./src/actions/AnnotateSnapshot",
 | 
			
		||||
    "./src/actions/RemoveEmbed",
 | 
			
		||||
    "./src/actions/CreateSnapshot",
 | 
			
		||||
    "./src/actions/RemoveSnapshot",
 | 
			
		||||
    "./src/actions/NewEntryContextual",
 | 
			
		||||
    "./src/capabilities/NotebookCapability",
 | 
			
		||||
    "./src/policies/CompositionPolicy",
 | 
			
		||||
    "./src/policies/ViewPolicy",
 | 
			
		||||
    "text!./res/templates/layoutNotebook.html",
 | 
			
		||||
    "text!./res/templates/notebook.html",
 | 
			
		||||
    "text!./res/templates/entry.html",
 | 
			
		||||
    "text!./res/templates/annotation.html",
 | 
			
		||||
    "text!./res/templates/notifications.html",
 | 
			
		||||
    "text!../layout/res/templates/frame.html",
 | 
			
		||||
    "text!./res/templates/controls/embedControl.html",
 | 
			
		||||
    "text!./res/templates/controls/snapSelect.html"
 | 
			
		||||
], function (
 | 
			
		||||
    legacyRegistry,
 | 
			
		||||
    NotebookController,
 | 
			
		||||
    NewEntryController,
 | 
			
		||||
    SelectSnapshotController,
 | 
			
		||||
    LayoutNotebookController,
 | 
			
		||||
    MCTSnapshot,
 | 
			
		||||
    MCTModalNotebook,
 | 
			
		||||
    MCTEntryDnd,
 | 
			
		||||
    ViewSnapshotAction,
 | 
			
		||||
    AnnotateSnapshotAction,
 | 
			
		||||
    RemoveEmbedAction,
 | 
			
		||||
    CreateSnapshotAction,
 | 
			
		||||
    RemoveSnapshotAction,
 | 
			
		||||
    newEntryAction,
 | 
			
		||||
    NotebookCapability,
 | 
			
		||||
    CompositionPolicy,
 | 
			
		||||
    ViewPolicy,
 | 
			
		||||
    layoutNotebookTemplate,
 | 
			
		||||
    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": []
 | 
			
		||||
                  }
 | 
			
		||||
            }
 | 
			
		||||
          ],
 | 
			
		||||
            "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"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                 {
 | 
			
		||||
                    "key": "mctModalNotebook",
 | 
			
		||||
                    "implementation": MCTModalNotebook,
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "$document"
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "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": "create-snapshot",
 | 
			
		||||
                    "implementation": CreateSnapshotAction,
 | 
			
		||||
                    "name": "Create Snapshot",
 | 
			
		||||
                    "description": "Create a snapshot for the embed",
 | 
			
		||||
                    "category": "embed-no-snap",
 | 
			
		||||
                    "priority": "preferred",
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                      "$compile"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "notebook-new-entry",
 | 
			
		||||
                    "implementation": newEntryAction,
 | 
			
		||||
                    "name": "New Notebook Entry",
 | 
			
		||||
                    "cssClass": "icon-notebook labeled",
 | 
			
		||||
                    "description": "Add a new Notebook entry",
 | 
			
		||||
                    "category": [
 | 
			
		||||
                        "contextual",
 | 
			
		||||
                         "view-control"
 | 
			
		||||
                    ],
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                      "$compile",
 | 
			
		||||
                      "$rootScope",
 | 
			
		||||
                      "dialogService",
 | 
			
		||||
                      "notificationService",
 | 
			
		||||
                      "linkService"
 | 
			
		||||
                    ],
 | 
			
		||||
                    "priority": "preferred"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "licenses": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "painterro",
 | 
			
		||||
                    "version": "4.1.0",
 | 
			
		||||
                    "author": "Mike Bostock",
 | 
			
		||||
                    "description": "D3 (or D3.js) is a JavaScript library for visualizing data using web standards. D3 helps you bring data to life using SVG, Canvas and HTML. D3 combines powerful visualization and interaction techniques with a data-driven approach to DOM manipulation, giving you the full capabilities of modern browsers and the freedom to design the right visual interface for your data.",
 | 
			
		||||
                    "website": "https://d3js.org/",
 | 
			
		||||
                    "copyright": "Copyright 2010-2016 Mike Bostock",
 | 
			
		||||
                    "license": "BSD-3-Clause",
 | 
			
		||||
                    "link": "https://github.com/d3/d3/blob/master/LICENSE"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "capabilities": [
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "notebook",
 | 
			
		||||
                    "name": "Notebook Capability",
 | 
			
		||||
                    "description": "Provides a capability for looking for a notebook domain object",
 | 
			
		||||
                    "implementation": NotebookCapability,
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "typeService"
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "policies": [
 | 
			
		||||
                {
 | 
			
		||||
                    "category": "composition",
 | 
			
		||||
                    "implementation": CompositionPolicy,
 | 
			
		||||
                    "message": "Objects of this type cannot contain objects of that type."
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "controls": [
 | 
			
		||||
              {
 | 
			
		||||
                  "key": "embed-control",
 | 
			
		||||
                  "template": embedControlTemplate
 | 
			
		||||
              },
 | 
			
		||||
               {
 | 
			
		||||
                  "key": "snapshot-select",
 | 
			
		||||
                  "template":  snapSelectTemplate
 | 
			
		||||
              }
 | 
			
		||||
            ],
 | 
			
		||||
            "stylesheets": [
 | 
			
		||||
                {
 | 
			
		||||
                    "stylesheetUrl": "css/notebook.css"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "stylesheetUrl": "css/notebook-espresso.css",
 | 
			
		||||
                    "theme": "espresso"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "stylesheetUrl": "css/notebook-snow.css",
 | 
			
		||||
                    "theme": "snow"
 | 
			
		||||
                }
 | 
			
		||||
          ]
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										283
									
								
								platform/features/notebook/res/sass/_notebook-base.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								platform/features/notebook/res/sass/_notebook-base.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,283 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
.w-notebook {
 | 
			
		||||
    font-size: 0.8rem;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
    right: 0px;
 | 
			
		||||
    bottom: 0px;
 | 
			
		||||
    left: 0px;
 | 
			
		||||
    width: auto;
 | 
			
		||||
    height: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.l-notebook-drag-area {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
    font-style: italic;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    &:before { margin-right: 7px !important; }
 | 
			
		||||
    .label {
 | 
			
		||||
        @include ellipsize();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.frame {
 | 
			
		||||
   .icon-notebook {
 | 
			
		||||
        margin-right: 5px;
 | 
			
		||||
    } 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay.l-dialog .title{
 | 
			
		||||
    white-space: normal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-notebook-entries {
 | 
			
		||||
    //@include test($a: 0.1);
 | 
			
		||||
    padding-right: $interiorMarginSm;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    overflow-x: hidden;
 | 
			
		||||
    overflow-y: scroll;
 | 
			
		||||
    .t-entries-list {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.l-notebook-entry {
 | 
			
		||||
    $p: $interiorMarginSm;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    margin-bottom: $p;
 | 
			
		||||
    padding: $p $interiorMargin;
 | 
			
		||||
 | 
			
		||||
    .s-notebook-entry-time,
 | 
			
		||||
    .s-notebook-entry-text,
 | 
			
		||||
    .notebook-entry-delete {
 | 
			
		||||
        padding-top: $p;
 | 
			
		||||
        padding-bottom: $p;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .s-notebook-entry-time {
 | 
			
		||||
        border: 1px solid transparent; // Needed to maintain vertical alignment with s-notebook-entry-text
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .l-notebook-entry-content{
 | 
			
		||||
        .s-notebook-entry-text {
 | 
			
		||||
            // Contenteditable div that holds text
 | 
			
		||||
            min-height: 24px; // Needed in Firefox when field is blank
 | 
			
		||||
        }
 | 
			
		||||
        .entry-embeds{
 | 
			
		||||
            flex-wrap: wrap;
 | 
			
		||||
        }
 | 
			
		||||
        .snap-thumb {
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.l-entry-embed {
 | 
			
		||||
    $m: $interiorMarginSm;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    margin: $m $m 0 0;
 | 
			
		||||
    padding: $interiorMarginSm;
 | 
			
		||||
 | 
			
		||||
    &.has-snapshot {
 | 
			
		||||
        &:before {
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            text-shadow: rgba(black, 0.7) 0 1px 5px;
 | 
			
		||||
            z-index: 2;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    .snap-thumb {
 | 
			
		||||
        $d: 50px;
 | 
			
		||||
        width: $d;
 | 
			
		||||
        height: $d;
 | 
			
		||||
        border-radius: 5px;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
        img {
 | 
			
		||||
            height: 100%;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .embed-info {
 | 
			
		||||
        margin-left: $interiorMargin;
 | 
			
		||||
        .embed-title {
 | 
			
		||||
            font-weight: bold;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.t-contents,
 | 
			
		||||
.snap-annotation {
 | 
			
		||||
    // Todo: don't write this to t-contents, add a l- class
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.notebook-filters {
 | 
			
		||||
    .select {
 | 
			
		||||
        margin-left: $interiorMargin;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/********************************************* MOBILE */
 | 
			
		||||
@include phonePortrait() {
 | 
			
		||||
    body.phone {
 | 
			
		||||
        .w-notebook-entry-time-and-content {
 | 
			
		||||
            flex-direction: column !important;
 | 
			
		||||
        }
 | 
			
		||||
        .s-notebook-entry-time,
 | 
			
		||||
        .notebook-entry-delete {
 | 
			
		||||
            padding-top: 0;
 | 
			
		||||
            padding-bottom: 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/********************************************* PAINTERRO OVERRIDES */
 | 
			
		||||
.annotation-dialog .abs.editor {
 | 
			
		||||
    border-radius: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#snap-annotation {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0; right: 0; bottom: 0; left: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#snap-annotation-wrapper,
 | 
			
		||||
#snap-annotation-bar {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: auto; right: auto; bottom: auto; left: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#snap-annotation-wrapper {
 | 
			
		||||
    order: 2;
 | 
			
		||||
    flex: 10 0 auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#snap-annotation-bar {
 | 
			
		||||
    order: 1;
 | 
			
		||||
    flex: 0 0 auto;
 | 
			
		||||
    height: auto;
 | 
			
		||||
    background-color: transparent !important;
 | 
			
		||||
    margin-bottom: $interiorMargin;
 | 
			
		||||
 | 
			
		||||
    > div,
 | 
			
		||||
    > div > span,
 | 
			
		||||
    .ptro-icon-btn,
 | 
			
		||||
    .ptro-named-btn,
 | 
			
		||||
    .ptro-color-btn,
 | 
			
		||||
    .ptro-bordered-btn,
 | 
			
		||||
    .ptro-tool-ctl-name,
 | 
			
		||||
    .ptro-color-btn,
 | 
			
		||||
    .tool-controls,
 | 
			
		||||
    .ptro-input {
 | 
			
		||||
        // Lot of resets for crappy CSS in Painterro
 | 
			
		||||
        &:first-child {
 | 
			
		||||
            margin-left: 0 !important;
 | 
			
		||||
        }
 | 
			
		||||
        $h: $btnToolbarH;
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        font-family: inherit;
 | 
			
		||||
        font-size: auto;
 | 
			
		||||
        height: $h !important;
 | 
			
		||||
        margin: 0 0 0 5px;
 | 
			
		||||
        position: relative;
 | 
			
		||||
        width: auto !important;
 | 
			
		||||
        line-height: $h !important;
 | 
			
		||||
        top: auto;
 | 
			
		||||
        right: auto;
 | 
			
		||||
        bottom: auto;
 | 
			
		||||
        left: auto;
 | 
			
		||||
        vertical-align: top;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .ptro-tool-ctl-name {
 | 
			
		||||
        border-radius: 0;
 | 
			
		||||
        background: none;
 | 
			
		||||
        top: auto;
 | 
			
		||||
        font-family: inherit;
 | 
			
		||||
        padding: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .ptro-color-btn {
 | 
			
		||||
        width: $btnToolbarH !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .ptro-icon-btn,
 | 
			
		||||
    .ptro-named-btn {
 | 
			
		||||
        // .s-button class is added via JS in AnnotateSnapshot.js
 | 
			
		||||
        // TODO: redo this so that we don't need to use Zepto and JS
 | 
			
		||||
        i {
 | 
			
		||||
            font-size: 1.25em !important;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .tool-controls {
 | 
			
		||||
        font-size: 0.8rem !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .ptro-info,
 | 
			
		||||
    .ptro-btn-color-checkers-bar,
 | 
			
		||||
    *[title="Font name"],
 | 
			
		||||
    *[title="Stroke color"],
 | 
			
		||||
    *[title="Stroke width"],
 | 
			
		||||
    *[data-id="fontName"],
 | 
			
		||||
    *[data-id="fontStrokeSize"],
 | 
			
		||||
    *[data-id="stroke"] {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/********************************************* NO IDEA WHAT THERE ARE APPLYING TO */
 | 
			
		||||
.context-available {
 | 
			
		||||
    outline: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu-element.menu-view{
 | 
			
		||||
    z-index: 999;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.overlay.l-dialog .abs.editor {
 | 
			
		||||
    padding-right: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
.overlay.l-dialog .outer-holder.annotation-dialog{
 | 
			
		||||
    width: 90%;
 | 
			
		||||
    height: 90%;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
.snap-annotation-wrapper{
 | 
			
		||||
    padding-top: 40px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.t-console {
 | 
			
		||||
    // Temp console-like reporting element
 | 
			
		||||
    max-height: 200px;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    padding: 5px;
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
							
								
								
									
										92
									
								
								platform/features/notebook/res/sass/_notebook-thematic.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								platform/features/notebook/res/sass/_notebook-thematic.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
.l-notebook-drag-area {
 | 
			
		||||
    border: 1px dashed rgba($colorKey, 0.7);
 | 
			
		||||
    border-radius: $controlCr;
 | 
			
		||||
    color: rgba($colorBodyFg, 0.7);
 | 
			
		||||
    &:hover {
 | 
			
		||||
        background: rgba($colorKey, 0.2);
 | 
			
		||||
        color: $colorBodyFg;
 | 
			
		||||
    }
 | 
			
		||||
    &.drag-active{
 | 
			
		||||
        border-color: $colorKey;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-notebook-entry {
 | 
			
		||||
    background-color: rgba($colorBodyFg, 0.1);
 | 
			
		||||
    border-radius: $basicCr;
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
        background-color: rgba($colorBodyFg, 0.2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .s-notebook-entry-time {
 | 
			
		||||
        color: rgba($colorBodyFg, 0.5);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.l-entry-embed {
 | 
			
		||||
    border-radius: $controlCr;
 | 
			
		||||
    background-color: rgba($colorBodyFg, 0.1);
 | 
			
		||||
    &.has-snapshot {
 | 
			
		||||
        &:before {
 | 
			
		||||
            color: $colorBodyFg;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-snapshot-datetime {
 | 
			
		||||
    color: rgba($colorBodyFg, 0.4);
 | 
			
		||||
    font-size: 0.8em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.snap-thumb {
 | 
			
		||||
    border: 1px solid $colorInteriorBorder;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-status-taking-snapshot,
 | 
			
		||||
.overlay.snapshot {
 | 
			
		||||
    // Applied to an object view when it's in the process of being snapshotted
 | 
			
		||||
    background: $colorBodyBg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/********************************************* PAINTERRO OVERRIDES */
 | 
			
		||||
.ptro-wrapper {
 | 
			
		||||
    background: rgba($colorBodyBg, 0.3) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#snap-annotation-bar {
 | 
			
		||||
    .tool-controls {
 | 
			
		||||
        color: $colorBodyFg !important;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-button.ptro-color-active-control {
 | 
			
		||||
    background: $colorBtnMajorBg  !important;
 | 
			
		||||
    color: $colorBtnMajorFg !important;
 | 
			
		||||
    &:hover {
 | 
			
		||||
        background: $colorBtnMajorBgHov !important;
 | 
			
		||||
        color: $colorBtnMajorFgHov !important;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								platform/features/notebook/res/sass/notebook-espresso.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								platform/features/notebook/res/sass/notebook-espresso.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
$output-bourbon-deprecation-warnings: false;
 | 
			
		||||
@import "bourbon";
 | 
			
		||||
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/mixins";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/glyphs";
 | 
			
		||||
@import "../../../../commonUI/themes/espresso/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/themes/espresso/res/sass/mixins";
 | 
			
		||||
@import "notebook-thematic";
 | 
			
		||||
							
								
								
									
										30
									
								
								platform/features/notebook/res/sass/notebook-snow.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								platform/features/notebook/res/sass/notebook-snow.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
$output-bourbon-deprecation-warnings: false;
 | 
			
		||||
@import "bourbon";
 | 
			
		||||
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/mixins";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/glyphs";
 | 
			
		||||
@import "../../../../commonUI/themes/snow/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/themes/snow/res/sass/mixins";
 | 
			
		||||
@import "notebook-thematic";
 | 
			
		||||
							
								
								
									
										28
									
								
								platform/features/notebook/res/sass/notebook.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								platform/features/notebook/res/sass/notebook.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2015, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
$output-bourbon-deprecation-warnings: false;
 | 
			
		||||
@import "bourbon";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/mixins";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/mobile/constants";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/mobile/mixins";
 | 
			
		||||
@import "notebook-base";
 | 
			
		||||
							
								
								
									
										2
									
								
								platform/features/notebook/res/templates/annotation.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								platform/features/notebook/res/templates/annotation.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
<div class="snap-annotation" id="snap-annotation" ng-controller="ngModel.controller">
 | 
			
		||||
</div>
 | 
			
		||||
@@ -0,0 +1,51 @@
 | 
			
		||||
<!--
 | 
			
		||||
 Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 Administration. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 You may obtain a copy of the License at
 | 
			
		||||
 http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 | 
			
		||||
 Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 License for the specific language governing permissions and limitations
 | 
			
		||||
 under the License.
 | 
			
		||||
 | 
			
		||||
 Open MCT includes source code licensed under additional open source
 | 
			
		||||
 licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<!--
 | 
			
		||||
This element appears in the overlay dialog when initiating a new Notebook Entry from a view's Notebook button -->
 | 
			
		||||
<div class='form-control'>
 | 
			
		||||
    <ng-form name="mctControl">
 | 
			
		||||
        <div class='fields' ng-controller="NewEntryController">
 | 
			
		||||
            <div class="l-flex-row new-notebook-entry-embed l-entry-embed {{cssClass}}"
 | 
			
		||||
                 ng-class="{ 'has-snapshot' : snapToggle }">
 | 
			
		||||
                <div class="holder flex-elem snap-thumb"
 | 
			
		||||
                    ng-if="snapToggle">
 | 
			
		||||
                    <img ng-src="{{snapshot.src}}" alt="{{snapshot.modified}}">
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div class="holder flex-elem embed-info">
 | 
			
		||||
                    <div class="embed-title">{{objectName}}</div>
 | 
			
		||||
                    <div class="embed-date"
 | 
			
		||||
                         ng-if="snapToggle">{{snapshot.modified| date:'yyyy-MM-dd HH:mm:ss'}}</div>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div class="holder flex-elem annotate-new"
 | 
			
		||||
                     ng-if="snapToggle">
 | 
			
		||||
                    <a class="s-button flex-elem icon-pencil "
 | 
			
		||||
                       title="Annotate this snapshot"
 | 
			
		||||
                       ng-click="annotateSnapshot()">
 | 
			
		||||
                        <span class="title-label">Annotate</span>
 | 
			
		||||
                    </a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </ng-form>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -0,0 +1,30 @@
 | 
			
		||||
<!--
 | 
			
		||||
 Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 Administration. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 You may obtain a copy of the License at
 | 
			
		||||
 http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 | 
			
		||||
 Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 License for the specific language governing permissions and limitations
 | 
			
		||||
 under the License.
 | 
			
		||||
 | 
			
		||||
 Open MCT includes source code licensed under additional open source
 | 
			
		||||
 licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class='form-control select' ng-controller="selectSnapshotController">
 | 
			
		||||
    <select
 | 
			
		||||
            ng-model="selectModel"
 | 
			
		||||
            ng-options="opt.value as opt.name for opt in options"
 | 
			
		||||
            ng-required="ngRequired"
 | 
			
		||||
            name="mctControl">
 | 
			
		||||
        <!-- <option value="" ng-show="!ngModel[field]">- Select One -</option> -->
 | 
			
		||||
    </select>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										38
									
								
								platform/features/notebook/res/templates/entry.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								platform/features/notebook/res/templates/entry.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<!--
 | 
			
		||||
 Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 Administration. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 You may obtain a copy of the License at
 | 
			
		||||
 http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 | 
			
		||||
 Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 License for the specific language governing permissions and limitations
 | 
			
		||||
 under the License.
 | 
			
		||||
 | 
			
		||||
 Open MCT includes source code licensed under additional open source
 | 
			
		||||
 licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class="frame snap-frame frame-template t-frame-inner abs t-object-type-{{ representation.selected.key }}">
 | 
			
		||||
    <div class="abs object-browse-bar l-flex-row">
 | 
			
		||||
        <div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
 | 
			
		||||
            <mct-representation
 | 
			
		||||
                    key="'switcher'"
 | 
			
		||||
                    ng-model="representation"
 | 
			
		||||
                    mct-object="domainObject">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="abs object-holder" data-entry = "{{parameters.entry}}" data-embed = "{{parameters.embed}}" mct-snapshot ng-if="representation.selected.key">
 | 
			
		||||
        <mct-representation
 | 
			
		||||
                key="representation.selected.key"
 | 
			
		||||
                mct-object="representation.selected.key && domainObject">
 | 
			
		||||
        </mct-representation>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -0,0 +1,54 @@
 | 
			
		||||
<!--
 | 
			
		||||
 Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 Administration. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 You may obtain a copy of the License at
 | 
			
		||||
 http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 | 
			
		||||
 Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 License for the specific language governing permissions and limitations
 | 
			
		||||
 under the License.
 | 
			
		||||
 | 
			
		||||
 Open MCT includes source code licensed under additional open source
 | 
			
		||||
 licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class="frame frame-template t-frame-inner abs t-object-type-{{ representation.selected.key }}">
 | 
			
		||||
    <div class="abs object-browse-bar l-flex-row">
 | 
			
		||||
        <div class="left flex-elem l-flex-row grows">
 | 
			
		||||
            <mct-representation
 | 
			
		||||
                    key="'object-header-frame'"
 | 
			
		||||
                    mct-object="domainObject"
 | 
			
		||||
                    class="l-flex-row flex-elem object-header grows">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
 | 
			
		||||
            <a class="s-button icon-notebook"
 | 
			
		||||
               title="New Notebook Entry"
 | 
			
		||||
               ng-if="parameters"
 | 
			
		||||
               ng-click="ngModel()">
 | 
			
		||||
            </a>
 | 
			
		||||
            <mct-representation
 | 
			
		||||
                    key="'switcher'"
 | 
			
		||||
                    ng-model="representation"
 | 
			
		||||
                    mct-object="domainObject">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
            <a class="s-button icon-expand t-btn-view-large"
 | 
			
		||||
               title="View large"
 | 
			
		||||
               mct-modal-notebook>
 | 
			
		||||
            </a>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="abs object-holder">
 | 
			
		||||
        <mct-representation
 | 
			
		||||
                key="representation.selected.key"
 | 
			
		||||
                mct-object="representation.selected.key && domainObject">
 | 
			
		||||
        </mct-representation>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										84
									
								
								platform/features/notebook/res/templates/layoutNotebook.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								platform/features/notebook/res/templates/layoutNotebook.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
<!--
 | 
			
		||||
 Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 Administration. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 You may obtain a copy of the License at
 | 
			
		||||
 http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 | 
			
		||||
 Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 License for the specific language governing permissions and limitations
 | 
			
		||||
 under the License.
 | 
			
		||||
 | 
			
		||||
 Open MCT includes source code licensed under additional open source
 | 
			
		||||
 licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<div class="abs l-layout"
 | 
			
		||||
     ng-controller="LayoutController as controller"
 | 
			
		||||
     ng-click="controller.clearSelection()">
 | 
			
		||||
 | 
			
		||||
    <!-- Background grid -->
 | 
			
		||||
    <div class="l-grid-holder" ng-click="controller.clearSelection()">
 | 
			
		||||
        <div class="l-grid l-grid-x"
 | 
			
		||||
             ng-if="!controller.getGridSize()[0] < 3"
 | 
			
		||||
             ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
 | 
			
		||||
        <div class="l-grid l-grid-y"
 | 
			
		||||
             ng-if="!controller.getGridSize()[1] < 3"
 | 
			
		||||
             ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class='abs frame t-frame-outer child-frame panel s-selectable s-moveable s-hover-border'
 | 
			
		||||
         ng-class="{ 'no-frame': !controller.hasFrame(childObject), 's-selected':controller.selected(childObject) }"
 | 
			
		||||
         ng-repeat="childObject in composition"
 | 
			
		||||
         ng-click="controller.select($event, childObject.getId())"
 | 
			
		||||
         ng-style="controller.getFrameStyle(childObject.getId())">
 | 
			
		||||
 | 
			
		||||
         <div ng-controller="LayoutNotebookController as controller">
 | 
			
		||||
            <mct-representation key="'frameLayoutNotebook'"
 | 
			
		||||
                            class="t-rep-frame holder contents abs"
 | 
			
		||||
                            parameters = "hasNotebookAction"
 | 
			
		||||
                            ng-model="newNotebook"
 | 
			
		||||
                            mct-object="childObject">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
         </div>
 | 
			
		||||
        
 | 
			
		||||
        <!-- Drag handles -->
 | 
			
		||||
        <span class="abs t-edit-handle-holder s-hover-border" ng-if="controller.selected(childObject)">
 | 
			
		||||
            <span class="edit-handle edit-move"
 | 
			
		||||
                  mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [0,0])"
 | 
			
		||||
                  mct-drag="controller.continueDrag(delta)"
 | 
			
		||||
                  mct-drag-up="controller.endDrag()">
 | 
			
		||||
            </span>
 | 
			
		||||
 | 
			
		||||
            <span class="edit-corner edit-resize-nw"
 | 
			
		||||
                  mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [-1,-1])"
 | 
			
		||||
                  mct-drag="controller.continueDrag(delta)"
 | 
			
		||||
                  mct-drag-up="controller.endDrag()">
 | 
			
		||||
            </span>
 | 
			
		||||
            <span class="edit-corner edit-resize-ne"
 | 
			
		||||
                  mct-drag-down="controller.startDrag(childObject.getId(), [0,1], [1,-1])"
 | 
			
		||||
                  mct-drag="controller.continueDrag(delta)"
 | 
			
		||||
                  mct-drag-up="controller.endDrag()">
 | 
			
		||||
            </span>
 | 
			
		||||
            <span class="edit-corner edit-resize-sw"
 | 
			
		||||
                  mct-drag-down="controller.startDrag(childObject.getId(), [1,0], [-1,1])"
 | 
			
		||||
                  mct-drag="controller.continueDrag(delta)"
 | 
			
		||||
                  mct-drag-up="controller.endDrag()">
 | 
			
		||||
            </span>
 | 
			
		||||
            <span class="edit-corner edit-resize-se"
 | 
			
		||||
                  mct-drag-down="controller.startDrag(childObject.getId(), [0,0], [1,1])"
 | 
			
		||||
                  mct-drag="controller.continueDrag(delta)"
 | 
			
		||||
                  mct-drag-up="controller.endDrag()">
 | 
			
		||||
            </span>
 | 
			
		||||
        </span>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										124
									
								
								platform/features/notebook/res/templates/notebook.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								platform/features/notebook/res/templates/notebook.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
<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="l-flex-row holder grows holder-search">
 | 
			
		||||
            <div class="search-bar flex-elem l-flex-row grows"
 | 
			
		||||
                 ng-class="{ holder: !(entrySearch === '' || entrySearch === undefined) }">
 | 
			
		||||
                <div class="holder flex-elem grows">
 | 
			
		||||
                    <input class="search-input"
 | 
			
		||||
                           type="text" tabindex="10000"
 | 
			
		||||
                           ng-model="entrySearch"
 | 
			
		||||
                           ng-keyup="controller.search()"/>
 | 
			
		||||
                    <a class="clear-icon clear-input icon-x-in-circle"
 | 
			
		||||
                       ng-class="{show: !(entrySearch === '' || entrySearch === undefined)}"
 | 
			
		||||
                       ng-click="entrySearch = ''; controller.search()"></a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="notebook-filters right l-flex-row flex-elem grows flex-justify-end">
 | 
			
		||||
            <div class="select">
 | 
			
		||||
                <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">
 | 
			
		||||
                <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" ng-click="selectContentEditable($event)">
 | 
			
		||||
                    <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-html="trustedHtml(entry.text)">
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <!-- embeds -->
 | 
			
		||||
                        <div class="flex-elem entry-embeds l-flex-row">
 | 
			
		||||
                            <div class="l-flex-row l-entry-embed {{embed.cssClass}}"
 | 
			
		||||
                                 ng-repeat="embed in entry.embeds track by $index"
 | 
			
		||||
                                 ng-class="{ 'has-snapshot' : embed.snapshot }"
 | 
			
		||||
                                 id="{{embed.id}}">
 | 
			
		||||
                                <div class="snap-thumb"
 | 
			
		||||
                                     ng-if="embed.snapshot"
 | 
			
		||||
                                     ng-click="viewSnapshot($event,embed.snapshot.src,embed.id,entry.createdOn,this,embed)">
 | 
			
		||||
                                    <img ng-src="{{embed.snapshot.src}}" src="//:0" alt="{{embed.id}}">
 | 
			
		||||
                                </div>
 | 
			
		||||
                                <div class="embed-info l-flex-col">
 | 
			
		||||
                                    <div class="embed-title object-header">
 | 
			
		||||
                                        <a ng-click='navigate($event,embed.type)'>{{embed.name}}</a>
 | 
			
		||||
                                        <a class='context-available' ng-click='openMenu($event,embed.type)'></a>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="hide-menu" ng-show="false">
 | 
			
		||||
                                        <div class="menu-element context-menu-wrapper mobile-disable-select">
 | 
			
		||||
                                            <div class="menu context-menu">
 | 
			
		||||
                                                <ul>
 | 
			
		||||
                                                    <li ng-repeat="menu in menuEmbed"
 | 
			
		||||
                                                        ng-click="menu.perform($event,embed.snapshot.src,embed.id,entry.createdOn,this,embed)"
 | 
			
		||||
                                                        title="{{menu.getMetadata().description}}"
 | 
			
		||||
                                                        class="{{menu.getMetadata().cssClass}}"
 | 
			
		||||
                                                        ng-if="embed.snapshot">
 | 
			
		||||
                                                        {{menu.getMetadata().name}}
 | 
			
		||||
                                                    </li>
 | 
			
		||||
                                                    <li ng-repeat="menu in menuEmbedNoSnap"
 | 
			
		||||
                                                        ng-click="menu.perform($event,embed.snapshot.src,embed.id,entry.createdOn,this)"
 | 
			
		||||
                                                        title="{{menu.getMetadata().description}}"
 | 
			
		||||
                                                        class="{{menu.getMetadata().cssClass}}"
 | 
			
		||||
                                                        ng-if="!embed.snapshot">
 | 
			
		||||
                                                        {{menu.getMetadata().name}}
 | 
			
		||||
                                                    </li>
 | 
			
		||||
                                                    <li ng-repeat="menu in embedActions"
 | 
			
		||||
                                                        ng-click="menu.perform()"
 | 
			
		||||
                                                        title="{{menu.name}}"
 | 
			
		||||
                                                        class="{{menu.cssClass}}">
 | 
			
		||||
                                                        {{menu.name}}
 | 
			
		||||
                                                    </li>
 | 
			
		||||
                                                </ul>
 | 
			
		||||
                                            </div>
 | 
			
		||||
                                        </div>
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                    <div class="embed-date"
 | 
			
		||||
                                         ng-if="embed.snapshot">{{embed.id| date:'yyyy-MM-dd HH:mm:ss'}}
 | 
			
		||||
                                    </div>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <!-- delete entry -->
 | 
			
		||||
                <div class="holder flex-elem local-control notebook-entry-delete">
 | 
			
		||||
                    <a class="s-icon-button icon-trash" id={{entry.id}} title="Delete Entry" ng-click="deleteEntry($event)"></a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </li>
 | 
			
		||||
        </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
<span class="status block">
 | 
			
		||||
    <!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
 | 
			
		||||
    <span class="status-indicator icon-bell"></span>
 | 
			
		||||
    <span class="label">
 | 
			
		||||
        Notifications
 | 
			
		||||
    </span>
 | 
			
		||||
    <span class="count"></span>
 | 
			
		||||
</span>
 | 
			
		||||
							
								
								
									
										131
									
								
								platform/features/notebook/src/actions/AnnotateSnapshot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								platform/features/notebook/src/actions/AnnotateSnapshot.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module defining viewSnapshot (Originally NewWindowAction). Created by vwoeltje on 11/18/14.
 | 
			
		||||
 */
 | 
			
		||||
define(
 | 
			
		||||
    ["painterro", "zepto", "../shims/painterro-shim"],
 | 
			
		||||
    function (Painterro, $, painterroShim) {
 | 
			
		||||
        var ANNOTATION_STRUCT = {
 | 
			
		||||
            title: "Annotate Snapshot",
 | 
			
		||||
            template: "annotate-snapshot",
 | 
			
		||||
            options: [{
 | 
			
		||||
                name: "OK",
 | 
			
		||||
                key: "ok",
 | 
			
		||||
                description: "save annotation"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                name: "Cancel",
 | 
			
		||||
                key: "cancel",
 | 
			
		||||
                description: "cancel editing"
 | 
			
		||||
            }]
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        function AnnotateSnapshot(dialogService,dndService,$rootScope,context) {
 | 
			
		||||
            context = context || {};
 | 
			
		||||
 | 
			
		||||
            // Choose the object to be opened into a new tab
 | 
			
		||||
            this.domainObject = context.selectedObject || context.domainObject;
 | 
			
		||||
            this.dialogService = dialogService;
 | 
			
		||||
            this.dndService = dndService;
 | 
			
		||||
            this.$rootScope = $rootScope;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        AnnotateSnapshot.prototype.perform = function ($event,snapshot,embedId,entryId,$scope) {
 | 
			
		||||
 | 
			
		||||
            var DOMAIN_OBJECT = this.domainObject;
 | 
			
		||||
            var ROOTSCOPE = this.$rootScope;
 | 
			
		||||
            var painterro;
 | 
			
		||||
 | 
			
		||||
            var controller = ['$scope', '$timeout', function PainterroController ($scope, $timeout) {
 | 
			
		||||
                $(document.body).find('.l-dialog .outer-holder').addClass('annotation-dialog');
 | 
			
		||||
                $timeout(function () {
 | 
			
		||||
                    painterro = Painterro({
 | 
			
		||||
                        id: 'snap-annotation',
 | 
			
		||||
                        activeColor: '#ff0000',
 | 
			
		||||
                        activeColorAlpha: 1.0,
 | 
			
		||||
                        activeFillColor: '#fff',
 | 
			
		||||
                        activeFillColorAlpha: 0.0,
 | 
			
		||||
                        backgroundFillColor: '#000',
 | 
			
		||||
                        backgroundFillColorAlpha: 0.0,
 | 
			
		||||
                        defaultFontSize: 16,
 | 
			
		||||
                        defaultLineWidth: 2,
 | 
			
		||||
                        defaultTool: 'ellipse',
 | 
			
		||||
                        hiddenTools: ['save', 'open', 'close', 'eraser', 'pixelize', 'rotate', 'settings', 'resize'],
 | 
			
		||||
                        translation: {
 | 
			
		||||
                            name: 'en',
 | 
			
		||||
                            strings: {
 | 
			
		||||
                                lineColor: 'Line',
 | 
			
		||||
                                fillColor: 'Fill',
 | 
			
		||||
                                lineWidth: 'Size',
 | 
			
		||||
                                textColor: 'Color',
 | 
			
		||||
                                fontSize: 'Size',
 | 
			
		||||
                                fontStyle: 'Style'
 | 
			
		||||
                            }
 | 
			
		||||
                        },
 | 
			
		||||
                        saveHandler: function (image, done) {
 | 
			
		||||
                            if (entryId && embedId) {
 | 
			
		||||
                                var elementPos = DOMAIN_OBJECT.model.entries.map(function (x) {
 | 
			
		||||
                                    return x.createdOn;
 | 
			
		||||
                                }).indexOf(entryId);
 | 
			
		||||
                                var entryEmbeds = DOMAIN_OBJECT.model.entries[elementPos].embeds;
 | 
			
		||||
                                var embedPos = entryEmbeds.map(function (x) {
 | 
			
		||||
                                    return x.id;
 | 
			
		||||
                                }).indexOf(embedId);
 | 
			
		||||
                                $scope.saveSnap(image.asBlob(), embedPos, elementPos);
 | 
			
		||||
                            }else {
 | 
			
		||||
                                ROOTSCOPE.snapshot = {'src': image.asDataURL('image/png'),
 | 
			
		||||
                                                    'modified': Date.now()};
 | 
			
		||||
                            }
 | 
			
		||||
                            done(true);
 | 
			
		||||
                        }
 | 
			
		||||
                    }).show(snapshot);
 | 
			
		||||
                });
 | 
			
		||||
                painterroShim(painterro);
 | 
			
		||||
 | 
			
		||||
                $(document.body).find('.ptro-icon-btn').addClass('s-button');
 | 
			
		||||
                $(document.body).find('.ptro-input').addClass('s-button');
 | 
			
		||||
 | 
			
		||||
                $scope.$on('$destroy', function () {
 | 
			
		||||
                    painterro.removeEventHandlers();
 | 
			
		||||
                });
 | 
			
		||||
            }];
 | 
			
		||||
 | 
			
		||||
            ANNOTATION_STRUCT.model = {'controller': controller};
 | 
			
		||||
 | 
			
		||||
            function saveNotes(param) {
 | 
			
		||||
                if (param === 'ok') {
 | 
			
		||||
                    painterro.save();
 | 
			
		||||
                }else {
 | 
			
		||||
                    ROOTSCOPE.snapshot = "annotationCancelled";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.dialogService.getUserChoice(ANNOTATION_STRUCT)
 | 
			
		||||
            .then(saveNotes);
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return AnnotateSnapshot;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										65
									
								
								platform/features/notebook/src/actions/CreateSnapshot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								platform/features/notebook/src/actions/CreateSnapshot.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        var SNAPSHOT_TEMPLATE = '<mct-representation key="\'draggedEntry\'"' +
 | 
			
		||||
                                    'parameters="{entry:entryId,embed:embedId}"' +
 | 
			
		||||
                                    'class="t-rep-frame holder"' +
 | 
			
		||||
                                    'mct-object="selObj">' +
 | 
			
		||||
                                '</mct-representation>';
 | 
			
		||||
 | 
			
		||||
        function CreateSnapshot($compile,context) {
 | 
			
		||||
            context = context || {};
 | 
			
		||||
            this.domainObject = context.selectedObject || context.domainObject;
 | 
			
		||||
            this.context = context;
 | 
			
		||||
            this.$compile = $compile;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        CreateSnapshot.prototype.perform = function ($event,snapshot,embedId,entryId,$scope) {
 | 
			
		||||
            var compile = this.$compile;
 | 
			
		||||
            var model = this.domainObject.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);
 | 
			
		||||
            var embedType = entryEmbeds[embedPos].type;
 | 
			
		||||
 | 
			
		||||
            $scope.getDomainObj(embedType).then(function (resp) {
 | 
			
		||||
                if (entryId >= 0 && embedId >= 0) {
 | 
			
		||||
                    $scope.selObj = resp[embedType];
 | 
			
		||||
                    $scope.entryId = elementPos;
 | 
			
		||||
                    $scope.embedId = embedPos;
 | 
			
		||||
                    compile(SNAPSHOT_TEMPLATE)($scope);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return CreateSnapshot;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										193
									
								
								platform/features/notebook/src/actions/NewEntryContextual.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								platform/features/notebook/src/actions/NewEntryContextual.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        var SNAPSHOT_TEMPLATE = '<mct-representation key="\'draggedEntry\'"' +
 | 
			
		||||
                                    'class="t-rep-frame holder"' +
 | 
			
		||||
                                    'mct-object="selObj">' +
 | 
			
		||||
                                '</mct-representation>';
 | 
			
		||||
 | 
			
		||||
        var NEW_TASK_FORM = {
 | 
			
		||||
            name: "Create a Notebook Entry",
 | 
			
		||||
            hint: "Please select one Notebook",
 | 
			
		||||
            sections: [{
 | 
			
		||||
                rows: [{
 | 
			
		||||
                    name: 'Entry',
 | 
			
		||||
                    key: 'entry',
 | 
			
		||||
                    control: 'textarea',
 | 
			
		||||
                    required: true,
 | 
			
		||||
                    "cssClass": "l-textarea-sm"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Embed Type',
 | 
			
		||||
                    key: 'withSnapshot',
 | 
			
		||||
                    control: 'snapshot-select',
 | 
			
		||||
                    "options": [
 | 
			
		||||
                        {
 | 
			
		||||
                            "name": "Link and Snapshot",
 | 
			
		||||
                            "value": true
 | 
			
		||||
                        },
 | 
			
		||||
                        {
 | 
			
		||||
                            "name": "Link only",
 | 
			
		||||
                            "value": false
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Embed',
 | 
			
		||||
                    key: 'embedObject',
 | 
			
		||||
                    control: 'embed-control'
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Save in Notebook',
 | 
			
		||||
                    key: 'saveNotebook',
 | 
			
		||||
                    control: 'locator',
 | 
			
		||||
                    validate: validateLocation
 | 
			
		||||
                }]
 | 
			
		||||
            }]
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        function NewEntryContextual($compile,$rootScope,dialogService,notificationService,linkService,context) {
 | 
			
		||||
            context = context || {};
 | 
			
		||||
            this.domainObject = context.selectedObject || context.domainObject;
 | 
			
		||||
            this.dialogService = dialogService;
 | 
			
		||||
            this.notificationService = notificationService;
 | 
			
		||||
            this.linkService = linkService;
 | 
			
		||||
            this.$rootScope = $rootScope;
 | 
			
		||||
            this.$compile = $compile;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function validateLocation(newParentObj) {
 | 
			
		||||
            return newParentObj.model.type === 'notebook';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        NewEntryContextual.prototype.perform = function () {
 | 
			
		||||
            var self = this;
 | 
			
		||||
            var domainObj = this.domainObject;
 | 
			
		||||
            var notification = this.notificationService;
 | 
			
		||||
            var dialogService = this.dialogService;
 | 
			
		||||
            var rootScope = this.$rootScope;
 | 
			
		||||
            rootScope.newEntryText = '';
 | 
			
		||||
            // Create the overlay element and add it to the document's body
 | 
			
		||||
            this.$rootScope.selObj = domainObj;
 | 
			
		||||
            this.$rootScope.selValue = "";
 | 
			
		||||
            var newScope = rootScope.$new();
 | 
			
		||||
            newScope.selObj = domainObj;
 | 
			
		||||
            newScope.selValue = "";
 | 
			
		||||
            this.$compile(SNAPSHOT_TEMPLATE)(newScope);
 | 
			
		||||
            //newScope.$destroy();
 | 
			
		||||
 | 
			
		||||
            this.$rootScope.$watch("snapshot", setSnapshot);
 | 
			
		||||
 | 
			
		||||
            function setSnapshot(value) {
 | 
			
		||||
                if (value === "annotationCancelled") {
 | 
			
		||||
                    rootScope.snapshot = rootScope.lastValue;
 | 
			
		||||
                    rootScope.lastValue = '';
 | 
			
		||||
                }else if (value && value !== rootScope.lastValue) {
 | 
			
		||||
                    var overlayModel = {
 | 
			
		||||
                        title: NEW_TASK_FORM.name,
 | 
			
		||||
                        message: NEW_TASK_FORM.message,
 | 
			
		||||
                        structure: NEW_TASK_FORM,
 | 
			
		||||
                        value: {'entry': rootScope.newEntryText || ""}
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    rootScope.currentDialog = overlayModel;
 | 
			
		||||
 | 
			
		||||
                    dialogService.getDialogResponse(
 | 
			
		||||
                        "overlay-dialog",
 | 
			
		||||
                        overlayModel,
 | 
			
		||||
                        function () {
 | 
			
		||||
                            return overlayModel.value;
 | 
			
		||||
                        }
 | 
			
		||||
                    ).then(addNewEntry);
 | 
			
		||||
 | 
			
		||||
                    rootScope.lastValue = value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function addNewEntry(options) {
 | 
			
		||||
                options.selectedModel = options.embedObject.getModel();
 | 
			
		||||
                options.cssClass = options.embedObject.getCapability('type').typeDef.cssClass;
 | 
			
		||||
                if (self.$rootScope.snapshot) {
 | 
			
		||||
                    options.snapshot = self.$rootScope.snapshot;
 | 
			
		||||
                    self.$rootScope.snapshot = undefined;
 | 
			
		||||
                }else {
 | 
			
		||||
                    options.snapshot = undefined;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!options.withSnapshot) {
 | 
			
		||||
                    options.snapshot = '';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                createSnap(options);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function createSnap(options) {
 | 
			
		||||
                options.saveNotebook.useCapability('mutation', function (model) {
 | 
			
		||||
                    var entries = model.entries;
 | 
			
		||||
                    var lastEntry = entries[entries.length - 1];
 | 
			
		||||
                    var date = Date.now();
 | 
			
		||||
 | 
			
		||||
                    if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
 | 
			
		||||
                        model.entries.push({
 | 
			
		||||
                            'id': date,
 | 
			
		||||
                            'createdOn': date,
 | 
			
		||||
                            'text': options.entry,
 | 
			
		||||
                            'embeds': [{'type': options.embedObject.getId(),
 | 
			
		||||
                                       'id': '' + date,
 | 
			
		||||
                                       'cssClass': options.cssClass,
 | 
			
		||||
                                       'name': options.selectedModel.name,
 | 
			
		||||
                                       'snapshot': options.snapshot
 | 
			
		||||
                                     }]
 | 
			
		||||
                        });
 | 
			
		||||
                    }else {
 | 
			
		||||
                        model.entries[entries.length - 1] = {
 | 
			
		||||
                            'id': date,
 | 
			
		||||
                            'createdOn': date,
 | 
			
		||||
                            'text': options.entry,
 | 
			
		||||
                            'embeds': [{'type': options.embedObject.getId(),
 | 
			
		||||
                                       'id': '' + date,
 | 
			
		||||
                                       'cssClass': options.cssClass,
 | 
			
		||||
                                       'name': options.selectedModel.name,
 | 
			
		||||
                                       'snapshot': options.snapshot
 | 
			
		||||
                                     }]
 | 
			
		||||
                        };
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                notification.info({
 | 
			
		||||
                    title: "Notebook Entry created"
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        NewEntryContextual.appliesTo = function (context) {
 | 
			
		||||
            var domainObject = context.domainObject;
 | 
			
		||||
            return !!(domainObject && domainObject.getModel().type !== 'notebook');
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return NewEntryContextual;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										72
									
								
								platform/features/notebook/src/actions/RemoveEmbed.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								platform/features/notebook/src/actions/RemoveEmbed.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        function RemoveEmbed(dialogService,context) {
 | 
			
		||||
            context = context || {};
 | 
			
		||||
 | 
			
		||||
            this.domainObject = context.selectedObject || context.domainObject;
 | 
			
		||||
            this.dialogService = dialogService;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        RemoveEmbed.prototype.perform = function ($event,snapshot,embedId,entryId) {
 | 
			
		||||
            var DOMAIN_OBJ = 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() {
 | 
			
		||||
                DOMAIN_OBJ.useCapability('mutation', function (model) {
 | 
			
		||||
                    var elementPos = model.entries.map(function (x) {
 | 
			
		||||
                        return x.createdOn;
 | 
			
		||||
                    }).indexOf(entryId);
 | 
			
		||||
                    var entryEmbeds = model.entries[elementPos].embeds;
 | 
			
		||||
                    var embedPos = entryEmbeds.map(function (x) {
 | 
			
		||||
                        return x.id;
 | 
			
		||||
                    }).indexOf(embedId);
 | 
			
		||||
                    model.entries[elementPos].embeds.splice(embedPos, 1);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return RemoveEmbed;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										74
									
								
								platform/features/notebook/src/actions/RemoveSnapshot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								platform/features/notebook/src/actions/RemoveSnapshot.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        function RemoveSnapshot(dialogService,context) {
 | 
			
		||||
            context = context || {};
 | 
			
		||||
 | 
			
		||||
            this.domainObject = context.selectedObject || context.domainObject;
 | 
			
		||||
            this.dialogService = dialogService;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        RemoveSnapshot.prototype.perform = function ($event,snapshot,embedId,entryId) {
 | 
			
		||||
 | 
			
		||||
            var DOMAIN_OBJ = 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() {
 | 
			
		||||
                DOMAIN_OBJ.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;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										169
									
								
								platform/features/notebook/src/actions/ViewSnapshot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								platform/features/notebook/src/actions/ViewSnapshot.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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
 | 
			
		||||
 */
 | 
			
		||||
define(
 | 
			
		||||
    ['zepto'],
 | 
			
		||||
    function ($) {
 | 
			
		||||
 | 
			
		||||
        var OVERLAY_TEMPLATE = '' +
 | 
			
		||||
        '    <div class="abs blocker"></div>' +
 | 
			
		||||
        '    <div class="abs outer-holder">' +
 | 
			
		||||
        '       <a class="close icon-x-in-circle"></a>' +
 | 
			
		||||
        '       <div class="abs inner-holder l-flex-col">' +
 | 
			
		||||
        '           <div class="t-contents flex-elem holder grows"></div>' +
 | 
			
		||||
        '           <div class="bottom-bar flex-elem holder">' +
 | 
			
		||||
        '               <a class="t-done s-button major">Done</a>' +
 | 
			
		||||
        '           </div>' +
 | 
			
		||||
        '       </div>' +
 | 
			
		||||
        '    </div>';
 | 
			
		||||
 | 
			
		||||
        var toggleOverlay,
 | 
			
		||||
            overlay,
 | 
			
		||||
            closeButton,
 | 
			
		||||
            doneButton,
 | 
			
		||||
            blocker,
 | 
			
		||||
            overlayContainer,
 | 
			
		||||
            img,
 | 
			
		||||
            annotateButton,
 | 
			
		||||
            annotateImg;
 | 
			
		||||
 | 
			
		||||
        function ViewSnapshot($compile,context) {
 | 
			
		||||
            context = context || {};
 | 
			
		||||
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        function headerTemplate() {
 | 
			
		||||
            var template = '<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><!-- closes object-header -->' +
 | 
			
		||||
                                    '</div><!-- closes left -->' +
 | 
			
		||||
                                    '<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><!-- closes right -->' +
 | 
			
		||||
                                '</div><!-- closes object-browse-bar -->' +
 | 
			
		||||
                            '</div><!-- closes t-snapshot -->';
 | 
			
		||||
            return template;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        ViewSnapshot.prototype.perform = function ($event,snapshot,embedId,entryId,$scope,embed) {
 | 
			
		||||
            var isOpen = false;
 | 
			
		||||
 | 
			
		||||
            // onclick for menu items in overlay header context menu
 | 
			
		||||
            $scope.menuPerform = function (menu) {
 | 
			
		||||
                menu.perform();
 | 
			
		||||
                closeOverlay();
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            // Create the overlay element and add it to the document's body
 | 
			
		||||
            $scope.cssClass = embed.cssClass;
 | 
			
		||||
            $scope.embedType = embed.type;
 | 
			
		||||
            $scope.entryName = embed.name;
 | 
			
		||||
            $scope.snapDate = +embedId;
 | 
			
		||||
            var element = this.$compile(headerTemplate())($scope);
 | 
			
		||||
 | 
			
		||||
            var annotateAction = $scope.action.getActions({category: 'embed'})[1];
 | 
			
		||||
 | 
			
		||||
            toggleOverlay = function () {
 | 
			
		||||
                if (!isOpen) {
 | 
			
		||||
                    openOverlay(snapshot, element[0]);
 | 
			
		||||
                    isOpen = true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    closeOverlay();
 | 
			
		||||
                    isOpen = false;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            annotateImg = function () {
 | 
			
		||||
                closeOverlay();
 | 
			
		||||
                annotateAction.perform($event, snapshot, embedId, entryId, $scope);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            toggleOverlay();
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return ViewSnapshot;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The notebook capability allows a domain object to know whether the
 | 
			
		||||
         * notebook plugin is present or not.
 | 
			
		||||
         *
 | 
			
		||||
         * @constructor
 | 
			
		||||
         */
 | 
			
		||||
        function NotebookCapability(typeService, domainObject) {
 | 
			
		||||
            this.domainObject = domainObject;
 | 
			
		||||
            this.typeService = typeService;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Returns true if there is a notebook domain Object.
 | 
			
		||||
         *
 | 
			
		||||
         * @returns {Boolean}
 | 
			
		||||
         */
 | 
			
		||||
        NotebookCapability.prototype.isNotebook = function () {
 | 
			
		||||
            return !!this.typeService.getType('notebook');
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return NotebookCapability;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
@@ -0,0 +1,54 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This bundle implements object types and associated views for
 | 
			
		||||
 * display-building.
 | 
			
		||||
 */
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * The LayoutNotebookController is responsible for supporting the
 | 
			
		||||
         * notebook feature creation on theLayout view.
 | 
			
		||||
         **/
 | 
			
		||||
 | 
			
		||||
        function LayoutNotebookController($scope) {
 | 
			
		||||
            $scope.hasNotebookAction = undefined;
 | 
			
		||||
 | 
			
		||||
            $scope.newNotebook = undefined;
 | 
			
		||||
 | 
			
		||||
            var actions = $scope.domainObject.getCapability('action');
 | 
			
		||||
            var notebookAction = actions.getActions({'key': 'notebook-new-entry'});
 | 
			
		||||
            if (notebookAction.length > 0) {
 | 
			
		||||
                $scope.hasNotebookAction = true;
 | 
			
		||||
                $scope.newNotebook = function () {
 | 
			
		||||
                    notebookAction[0].perform();
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return LayoutNotebookController;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
@@ -0,0 +1,66 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module defining NewEntryController. */
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        function NewEntryController($scope,$rootScope) {
 | 
			
		||||
 | 
			
		||||
            $scope.snapshot = undefined;
 | 
			
		||||
            $scope.snapToggle = true;
 | 
			
		||||
            $scope.entryText = '';
 | 
			
		||||
            var annotateAction = $rootScope.selObj.getCapability('action').getActions(
 | 
			
		||||
                                                                            {category: 'embed'})[1];
 | 
			
		||||
 | 
			
		||||
            $scope.$parent.$parent.ngModel[$scope.$parent.$parent.field] = $rootScope.selObj;
 | 
			
		||||
            $scope.objectName = $rootScope.selObj.getModel().name;
 | 
			
		||||
            $scope.cssClass = $rootScope.selObj.getCapability('type').typeDef.cssClass;
 | 
			
		||||
 | 
			
		||||
            $scope.annotateSnapshot = function ($event) {
 | 
			
		||||
                if ($rootScope.currentDialog.value) {
 | 
			
		||||
                    $rootScope.newEntryText = $scope.$parent.$parent.ngModel.entry;
 | 
			
		||||
                    $rootScope.currentDialog.cancel();
 | 
			
		||||
                    annotateAction.perform($event, $rootScope.snapshot.src);
 | 
			
		||||
                    $rootScope.currentDialog = undefined;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            function updateSnapshot(img) {
 | 
			
		||||
                $scope.snapshot = img;
 | 
			
		||||
            }
 | 
			
		||||
            // Update set of actions whenever the action capability
 | 
			
		||||
            // changes or becomes available.
 | 
			
		||||
            $rootScope.$watch("snapshot", updateSnapshot);
 | 
			
		||||
 | 
			
		||||
            $rootScope.$watch("selValue", toggleEmbed);
 | 
			
		||||
 | 
			
		||||
            function toggleEmbed(value) {
 | 
			
		||||
                $scope.snapToggle = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return NewEntryController;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										400
									
								
								platform/features/notebook/src/controllers/NotebookController.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										400
									
								
								platform/features/notebook/src/controllers/NotebookController.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,400 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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 = '-createdOn';
 | 
			
		||||
            $scope.showTime = "0";
 | 
			
		||||
            $scope.editEntry = false;
 | 
			
		||||
            $scope.entrySearch = '';
 | 
			
		||||
            $scope.entryTypes = [];
 | 
			
		||||
            $scope.embedActions = [];
 | 
			
		||||
            $scope.currentEntryValue = '';
 | 
			
		||||
 | 
			
		||||
            /*--seconds in an hour--*/
 | 
			
		||||
 | 
			
		||||
            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 {
 | 
			
		||||
                    return $($scope.entriesEl.children().children()[0]).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();
 | 
			
		||||
                        }
 | 
			
		||||
                    }]
 | 
			
		||||
                });
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            function setCaretToEndOfContenteditable(contentEditableElement) {
 | 
			
		||||
                var range,selection;
 | 
			
		||||
                if (document.createRange) {
 | 
			
		||||
                    range = document.createRange();//Create a range (a range is a like the selection but invisible)
 | 
			
		||||
                    range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
 | 
			
		||||
                    range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
 | 
			
		||||
                    selection = window.getSelection();//get the selection object (allows you to change selection)
 | 
			
		||||
                    selection.removeAllRanges();//remove any selections already made
 | 
			
		||||
                    selection.addRange(range);//make the range you have just created the visible selection
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $scope.selectContentEditable = function ($event) {
 | 
			
		||||
                var child = $($event.srcElement).children()[0];
 | 
			
		||||
 | 
			
		||||
                if (child) {
 | 
			
		||||
                    $($event.srcElement).children()[0].focus();
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            $scope.textFocus = function ($event, entryId) {
 | 
			
		||||
                if ($event.srcElement && $event.srcElement.innerText) {
 | 
			
		||||
                    /*
 | 
			
		||||
                     On focus, if the currentTarget isn't blank, set the global currentEntryValue = the
 | 
			
		||||
                     content of the current focus. This will be used at blur to determine if the
 | 
			
		||||
                     current entry has been modified or not.
 | 
			
		||||
                     Not sure this is right, would think we'd always want to set curEntVal even if blank
 | 
			
		||||
                     */
 | 
			
		||||
                    $scope.currentEntryValue = $event.srcElement.innerText;
 | 
			
		||||
                    setCaretToEndOfContenteditable($event.srcElement);
 | 
			
		||||
                } 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 && $event.target.innerText !== "") {
 | 
			
		||||
                    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.parseText = function (text) {
 | 
			
		||||
                if (text) {
 | 
			
		||||
                    return text.split(/\r\n|\r|\n/gi);
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            //parse text and add line breaks where needed
 | 
			
		||||
            $scope.trustedHtml = function (text) {
 | 
			
		||||
                if (text) {
 | 
			
		||||
                    return $sce.trustAsHtml(this.parseText(text).join('<br>'));
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            $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: 'window',selectedObject: resp[embedType]})[0]
 | 
			
		||||
                                              ));
 | 
			
		||||
                        $scope.embedActions.push({
 | 
			
		||||
                                                key: 'navigate',
 | 
			
		||||
                                                name: 'Go to Original',
 | 
			
		||||
                                                cssClass: '',
 | 
			
		||||
                                                perform: function () {
 | 
			
		||||
                                                    $scope.navigate('', embedType);
 | 
			
		||||
                                                }
 | 
			
		||||
                                            });
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $scope.openMenu = function ($event,embedType) {
 | 
			
		||||
                $event.preventDefault();
 | 
			
		||||
 | 
			
		||||
                getEmbedActions(embedType);
 | 
			
		||||
 | 
			
		||||
                var body = $(document).find('body'),
 | 
			
		||||
                    initiatingEvent = agentService.isMobile() ?
 | 
			
		||||
                            'touchstart' : 'mousedown',
 | 
			
		||||
                    dismissExistingMenu,
 | 
			
		||||
                    menu,
 | 
			
		||||
                    popup;
 | 
			
		||||
 | 
			
		||||
                var container = $($event.currentTarget).parent().parent();
 | 
			
		||||
 | 
			
		||||
                menu = container.find('.menu-element');
 | 
			
		||||
 | 
			
		||||
                // Remove the context menu
 | 
			
		||||
                function dismiss() {
 | 
			
		||||
                    container.find('.hide-menu').append(menu);
 | 
			
		||||
                    body.off("mousedown", dismiss);
 | 
			
		||||
                    dismissExistingMenu = undefined;
 | 
			
		||||
                    $scope.embedActions = [];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Dismiss any menu which was already showing
 | 
			
		||||
                if (dismissExistingMenu) {
 | 
			
		||||
                    dismissExistingMenu();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // ...and record the presence of this menu.
 | 
			
		||||
                dismissExistingMenu = dismiss;
 | 
			
		||||
 | 
			
		||||
                popup = popupService.display(menu, [$event.pageX,$event.pageY], {
 | 
			
		||||
                    marginX: 0,
 | 
			
		||||
                    marginY: -50
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // Stop propagation so that clicks or touches on the menu do not close the menu
 | 
			
		||||
                menu.on(initiatingEvent, function (event) {
 | 
			
		||||
                    event.stopPropagation();
 | 
			
		||||
                    $timeout(dismiss, 300);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                // Dismiss the menu when body is clicked/touched elsewhere
 | 
			
		||||
                // ('mousedown' because 'click' breaks left-click context menus)
 | 
			
		||||
                // ('touchstart' because 'touch' breaks context menus up)
 | 
			
		||||
                body.on(initiatingEvent, dismiss);
 | 
			
		||||
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            $scope.$watchCollection("composition", refreshComp);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            $scope.$on('$destroy', function () {});
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return NotebookController;
 | 
			
		||||
    });
 | 
			
		||||
@@ -0,0 +1,44 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module defining SelectSnapshotController. */
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        function SelectSnapshotController($scope,$rootScope) {
 | 
			
		||||
 | 
			
		||||
            $scope.selectModel = true;
 | 
			
		||||
 | 
			
		||||
            function selectprint(value) {
 | 
			
		||||
                $rootScope.selValue = value;
 | 
			
		||||
                $scope.$parent.$parent.ngModel[$scope.$parent.$parent.field] = value;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $scope.$watch("selectModel", selectprint);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return SelectSnapshotController;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										126
									
								
								platform/features/notebook/src/directives/EntryDnd.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								platform/features/notebook/src/directives/EntryDnd.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,126 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(['zepto'], function ($) {
 | 
			
		||||
 | 
			
		||||
    function EntryDnd($rootScope,$compile,dndService,typeService,notificationService) {
 | 
			
		||||
 | 
			
		||||
        function link($scope, $element) {
 | 
			
		||||
 | 
			
		||||
            function drop(e) {
 | 
			
		||||
                var selectedObject = dndService.getData('mct-domain-object');
 | 
			
		||||
                var selectedModel = selectedObject.getModel();
 | 
			
		||||
                var cssClass = selectedObject.getCapability('type').typeDef.cssClass;
 | 
			
		||||
                var entryId = -1;
 | 
			
		||||
                var embedId = -1;
 | 
			
		||||
                $scope.clearSearch();
 | 
			
		||||
                if ($element[0].id === 'newEntry') {
 | 
			
		||||
                    entryId = $scope.domainObject.model.entries.length;
 | 
			
		||||
                    embedId = 0;
 | 
			
		||||
                    var lastEntry = $scope.domainObject.model.entries[entryId - 1];
 | 
			
		||||
                    if (lastEntry === undefined || lastEntry.text || lastEntry.embeds) {
 | 
			
		||||
                        $scope.domainObject.useCapability('mutation', function (model) {
 | 
			
		||||
                            model.entries.push({'createdOn': +Date.now(),
 | 
			
		||||
                                                'id': +Date.now(),
 | 
			
		||||
                                                'embeds': [{'type': selectedObject.getId(),
 | 
			
		||||
                                                       'id': '' + Date.now(),
 | 
			
		||||
                                                       'cssClass': cssClass,
 | 
			
		||||
                                                       'name': selectedModel.name,
 | 
			
		||||
                                                       'snapshot': ''
 | 
			
		||||
                                                     }]
 | 
			
		||||
                                            });
 | 
			
		||||
                        });
 | 
			
		||||
                    }else {
 | 
			
		||||
                        $scope.domainObject.useCapability('mutation', function (model) {
 | 
			
		||||
                            model.entries[entryId - 1] =
 | 
			
		||||
                                                    {'createdOn': +Date.now(),
 | 
			
		||||
                                                     'embeds': [{'type': selectedObject.getId(),
 | 
			
		||||
                                                                'id': '' + Date.now(),
 | 
			
		||||
                                                                'cssClass': cssClass,
 | 
			
		||||
                                                                'name': selectedModel.name,
 | 
			
		||||
                                                                'snapshot': ''
 | 
			
		||||
                                                               }]
 | 
			
		||||
                                                    };
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    $scope.scrollToTop();
 | 
			
		||||
                    notificationService.info({
 | 
			
		||||
                        title: "Notebook Entry created"
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                }else {
 | 
			
		||||
                    entryId = $scope.findEntryPositionById(Number($element[0].id.replace('entry_', '')));
 | 
			
		||||
 | 
			
		||||
                    if (!$scope.domainObject.model.entries[entryId].embeds) {
 | 
			
		||||
                        $scope.domainObject.model.entries[entryId].embeds = [];
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    $scope.domainObject.useCapability('mutation', function (model) {
 | 
			
		||||
                        model.entries[entryId].embeds.push({'type': selectedObject.getId(),
 | 
			
		||||
                                                                          'id': '' + Date.now(),
 | 
			
		||||
                                                                          'cssClass': cssClass,
 | 
			
		||||
                                                                          'name': selectedModel.name,
 | 
			
		||||
                                                                          'snapshot': ''
 | 
			
		||||
                                                                        });
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                    embedId = $scope.domainObject.model.entries[entryId].embeds.length - 1;
 | 
			
		||||
 | 
			
		||||
                    if (selectedObject) {
 | 
			
		||||
                        e.preventDefault();
 | 
			
		||||
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if ($(e.currentTarget).hasClass('drag-active')) {
 | 
			
		||||
                    $(e.currentTarget).removeClass('drag-active');
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function dragover(e) {
 | 
			
		||||
                if (!$(e.currentTarget).hasClass('drag-active')) {
 | 
			
		||||
                    $(e.currentTarget).addClass('drag-active');
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Listen for the drop itself
 | 
			
		||||
            $element.on('dragover', dragover);
 | 
			
		||||
            $element.on('drop', drop);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            $scope.$on('$destroy', function () {
 | 
			
		||||
                $element.off('dragover', dragover);
 | 
			
		||||
                $element.off('drop', drop);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            restrict: 'A',
 | 
			
		||||
            link: link
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return EntryDnd;
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										166
									
								
								platform/features/notebook/src/directives/MCTModalNotebook.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								platform/features/notebook/src/directives/MCTModalNotebook.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    'zepto'
 | 
			
		||||
], function (
 | 
			
		||||
    $
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    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>';
 | 
			
		||||
 | 
			
		||||
    var NEW_NOTEBOOK_BUTTON_TEMPLATE = '<a class="s-button labeled icon-notebook new-notebook-entry" title="New Notebook Entry">' +
 | 
			
		||||
                                    '<span class="title-label">New Notebook Entry</span>' +
 | 
			
		||||
                                '</a>';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * MCT Trigger Modal is intended for use in only one location: inside the
 | 
			
		||||
     * object-header to allow views in a layout to be popped out in a modal.
 | 
			
		||||
     * Users can close the modal and go back to normal, and everything generally
 | 
			
		||||
     * just works fine.
 | 
			
		||||
     *
 | 
			
		||||
     * This code is sensitive to how our html is constructed-- particularly with
 | 
			
		||||
     * how it locates the the container of an element in a layout. However, it
 | 
			
		||||
     * should be able to handle slight relocations so long as it is always a
 | 
			
		||||
     * descendent of a `.frame` element.
 | 
			
		||||
     */
 | 
			
		||||
    function MCTModalNotebook($document) {
 | 
			
		||||
        var document = $document[0];
 | 
			
		||||
 | 
			
		||||
        function link($scope, $element) {
 | 
			
		||||
            var frame = $element.parent();
 | 
			
		||||
 | 
			
		||||
            for (var i = 0; i < 10; i++) {
 | 
			
		||||
                if (frame.hasClass('frame')) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                frame = frame.parent();
 | 
			
		||||
            }
 | 
			
		||||
            if (!frame.hasClass('frame')) {
 | 
			
		||||
                $element.remove();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            frame = frame[0];
 | 
			
		||||
            var layoutContainer = frame.parentElement,
 | 
			
		||||
                isOpen = false,
 | 
			
		||||
                toggleOverlay,
 | 
			
		||||
                overlay,
 | 
			
		||||
                closeButton,
 | 
			
		||||
                doneButton,
 | 
			
		||||
                notebookButton,
 | 
			
		||||
                blocker,
 | 
			
		||||
                overlayContainer,
 | 
			
		||||
                notebookButtonEl;
 | 
			
		||||
 | 
			
		||||
            function openOverlay() {
 | 
			
		||||
                // Remove frame classes from being applied in a non-frame context
 | 
			
		||||
                $(frame).removeClass('frame frame-template');
 | 
			
		||||
                overlay = document.createElement('div');
 | 
			
		||||
                $(overlay).addClass('abs overlay l-large-view');
 | 
			
		||||
                overlay.innerHTML = OVERLAY_TEMPLATE;
 | 
			
		||||
                overlayContainer = overlay.querySelector('.t-contents');
 | 
			
		||||
                closeButton = overlay.querySelector('a.close');
 | 
			
		||||
                closeButton.addEventListener('click', toggleOverlay);
 | 
			
		||||
                doneButton = overlay.querySelector('a.t-done');
 | 
			
		||||
                doneButton.addEventListener('click', toggleOverlay);
 | 
			
		||||
                blocker = overlay.querySelector('.abs.blocker');
 | 
			
		||||
                blocker.addEventListener('click', toggleOverlay);
 | 
			
		||||
                document.body.appendChild(overlay);
 | 
			
		||||
                layoutContainer.removeChild(frame);
 | 
			
		||||
                overlayContainer.appendChild(frame);
 | 
			
		||||
 | 
			
		||||
                //verify if there is a new notebook entry action
 | 
			
		||||
                var actions = $scope.domainObject.getCapability('action');
 | 
			
		||||
                var notebookAction = actions.getActions({'key': 'notebook-new-entry'});
 | 
			
		||||
                if (notebookAction.length > 0) {
 | 
			
		||||
                    notebookButtonEl = document.createElement('div');
 | 
			
		||||
                    $(notebookButtonEl).addClass('notebook-button-container');
 | 
			
		||||
                    notebookButtonEl.innerHTML = NEW_NOTEBOOK_BUTTON_TEMPLATE;
 | 
			
		||||
                    notebookButton = frame.querySelector('.object-browse-bar .right');
 | 
			
		||||
                    notebookButton.prepend(notebookButtonEl);
 | 
			
		||||
                    // $(frame.querySelector('.object-holder')).addClass('container-notebook');
 | 
			
		||||
                    notebookButton.addEventListener('click', function () {
 | 
			
		||||
                        notebookAction[0].perform();
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function closeOverlay() {
 | 
			
		||||
                $(frame).addClass('frame frame-template');
 | 
			
		||||
                overlayContainer.removeChild(frame);
 | 
			
		||||
                layoutContainer.appendChild(frame);
 | 
			
		||||
                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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                if (notebookButton) {
 | 
			
		||||
                    notebookButton.removeChild(notebookButtonEl);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            toggleOverlay = function (event) {
 | 
			
		||||
                event.stopPropagation();
 | 
			
		||||
 | 
			
		||||
                if (!isOpen) {
 | 
			
		||||
                    openOverlay();
 | 
			
		||||
                    isOpen = true;
 | 
			
		||||
                } else {
 | 
			
		||||
                    closeOverlay();
 | 
			
		||||
                    isOpen = false;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            $element.on('click', toggleOverlay);
 | 
			
		||||
            $scope.$on('$destroy', function () {
 | 
			
		||||
                $element.off('click', toggleOverlay);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            restrict: 'A',
 | 
			
		||||
            link: link
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return MCTModalNotebook;
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										104
									
								
								platform/features/notebook/src/directives/MCTSnapshot.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								platform/features/notebook/src/directives/MCTSnapshot.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(['zepto', 'dom-to-image'], function ($) {
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
     */
 | 
			
		||||
    function MCTSnapshot($rootScope,$document,exportImageService,dialogService,notificationService) {
 | 
			
		||||
        var document = $document[0];
 | 
			
		||||
 | 
			
		||||
        function link($scope, $element, $attrs) {
 | 
			
		||||
            var objectElement = $(document.body).find('.overlay')[0] || $(document.body).find("[key='representation.selected.key']")[0],
 | 
			
		||||
                takeSnapshot,
 | 
			
		||||
                makeImg,
 | 
			
		||||
                saveImg;
 | 
			
		||||
 | 
			
		||||
            $(objectElement).addClass("s-status-taking-snapshot");
 | 
			
		||||
 | 
			
		||||
            takeSnapshot = function () {
 | 
			
		||||
                makeImg(objectElement);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            saveImg = function (url,entryId,embedId) {
 | 
			
		||||
                $scope.$parent.$parent.$parent.saveSnap(url, embedId, entryId);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            makeImg = function (el) {
 | 
			
		||||
                var scope = $scope;
 | 
			
		||||
                var dialog = dialogService.showBlockingMessage({
 | 
			
		||||
                        title: "Saving...",
 | 
			
		||||
                        hint: "Taking Snapshot...",
 | 
			
		||||
                        unknownProgress: true,
 | 
			
		||||
                        severity: "info",
 | 
			
		||||
                        delay: true
 | 
			
		||||
                    });
 | 
			
		||||
                window.setTimeout(function () {
 | 
			
		||||
                    window.domtoimage.toBlob(el).then(function (img) {
 | 
			
		||||
                        $(objectElement).removeClass("s-status-taking-snapshot");
 | 
			
		||||
 | 
			
		||||
                        if (img) {
 | 
			
		||||
                            if ($element[0].dataset.entry && $element[0].dataset.embed) {
 | 
			
		||||
                                saveImg(img, +$element[0].dataset.entry, +$element[0].dataset.embed);
 | 
			
		||||
                            } else {
 | 
			
		||||
                                var reader = new window.FileReader();
 | 
			
		||||
                                reader.readAsDataURL(img);
 | 
			
		||||
                                reader.onloadend = function () {
 | 
			
		||||
                                    $($element[0]).attr("data-snapshot", reader.result);
 | 
			
		||||
                                    $rootScope.snapshot = {
 | 
			
		||||
                                        'src': reader.result,
 | 
			
		||||
                                        'type': img.type,
 | 
			
		||||
                                        'size': img.size,
 | 
			
		||||
                                        'modified': Date.now()
 | 
			
		||||
                                    };
 | 
			
		||||
                                    scope.$destroy();
 | 
			
		||||
                                };
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        dialog.dismiss();
 | 
			
		||||
 | 
			
		||||
                    }, function (error) {
 | 
			
		||||
                        if (dialog) {
 | 
			
		||||
                            dialog.dismiss();
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                }, 500);
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            takeSnapshot();
 | 
			
		||||
 | 
			
		||||
            $scope.$on('$destroy', function () {
 | 
			
		||||
                $element.remove();
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            restrict: 'A',
 | 
			
		||||
            link: link
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return MCTSnapshot;
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										44
									
								
								platform/features/notebook/src/policies/CompositionPolicy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								platform/features/notebook/src/policies/CompositionPolicy.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This bundle implements "containment" rules, which determine which objects
 | 
			
		||||
 * can be contained within a notebook.
 | 
			
		||||
 */
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
        function CompositionPolicy() {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        CompositionPolicy.prototype.allow = function (parent, child) {
 | 
			
		||||
            var parentDef = parent.getCapability('type').getName();
 | 
			
		||||
 | 
			
		||||
            if (parentDef === 'Notebook' && child.getCapability('status').list().length) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return CompositionPolicy;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										40
									
								
								platform/features/notebook/src/policies/ViewPolicy.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								platform/features/notebook/src/policies/ViewPolicy.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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 ViewPolicy() {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ViewPolicy.prototype.allow = function (view, domainObject) {
 | 
			
		||||
            // if (view.key === 'layout') {
 | 
			
		||||
            //     return false;
 | 
			
		||||
            // }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return ViewPolicy;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								platform/features/notebook/src/shims/painterro-shim.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								platform/features/notebook/src/shims/painterro-shim.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
define(function () {
 | 
			
		||||
    return function (painterroInstance) {
 | 
			
		||||
        painterroInstance.removeEventHandlers = function() {
 | 
			
		||||
          Object.keys(this.documentHandlers).forEach((key) => {
 | 
			
		||||
            this.doc.removeEventListener(key, this.documentHandlers[key]);
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
          Object.keys(this.windowHandlers).forEach((key) => {
 | 
			
		||||
            window.removeEventListener(key, this.windowHandlers[key]);
 | 
			
		||||
          });
 | 
			
		||||
        }.bind(painterroInstance);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -62,8 +62,10 @@ define(
 | 
			
		||||
                    scope.key && templateMap[scope.key]
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                scope.$watch('key', function (key) {
 | 
			
		||||
                    changeTemplate(key && templateMap[key]);
 | 
			
		||||
                scope.$watch('key', function (newKey, oldKey) {
 | 
			
		||||
                    if (newKey !== oldKey) {
 | 
			
		||||
                        changeTemplate(newKey && templateMap[newKey]);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
-->
 | 
			
		||||
<div class="angular-w l-flex-col flex-elem grows holder" ng-controller="SearchController as controller">
 | 
			
		||||
    <div class="l-flex-col flex-elem grows holder holder-search" ng-controller="SearchMenuController as menuController">
 | 
			
		||||
        <div class="search-bar flex-elem l-flex-row"
 | 
			
		||||
        <div class="search-bar search-filter-by-type flex-elem l-flex-row"
 | 
			
		||||
             ng-controller="ToggleController as toggle"
 | 
			
		||||
             ng-class="{ holder: !(ngModel.input === '' || ngModel.input === undefined) }">
 | 
			
		||||
            <div class="holder flex-elem grows">
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ define(
 | 
			
		||||
 | 
			
		||||
        var CHARTS = [
 | 
			
		||||
                {
 | 
			
		||||
                    MAX_INSTANCES: 16,
 | 
			
		||||
                    MAX_INSTANCES: 14,
 | 
			
		||||
                    API: DrawWebGL,
 | 
			
		||||
                    ALLOCATIONS: []
 | 
			
		||||
                },
 | 
			
		||||
 
 | 
			
		||||
@@ -141,6 +141,17 @@ define(
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Takes a screenshot of a DOM node in PNG format.
 | 
			
		||||
         * @param {node} element to be exported
 | 
			
		||||
         * @param {string} filename the exported image
 | 
			
		||||
         * @returns {promise}
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        ExportImageService.prototype.exportPNGtoSRC = function (element) {
 | 
			
		||||
            return this.renderElement(element, "png");
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * canvas.toBlob() not supported in IE < 10, Opera, and Safari. This polyfill
 | 
			
		||||
         * implements the method in browsers that would not otherwise support it.
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@ define([
 | 
			
		||||
    './autoflow/AutoflowTabularPlugin',
 | 
			
		||||
    './timeConductor/plugin',
 | 
			
		||||
    '../../example/imagery/plugin',
 | 
			
		||||
    '../../platform/features/notebook/bundle',
 | 
			
		||||
    '../../platform/import-export/bundle',
 | 
			
		||||
    './summaryWidget/plugin',
 | 
			
		||||
    './URLIndicatorPlugin/URLIndicatorPlugin',
 | 
			
		||||
@@ -40,6 +41,7 @@ define([
 | 
			
		||||
    AutoflowPlugin,
 | 
			
		||||
    TimeConductorPlugin,
 | 
			
		||||
    ExampleImagery,
 | 
			
		||||
    Notebook,
 | 
			
		||||
    ImportExport,
 | 
			
		||||
    SummaryWidget,
 | 
			
		||||
    URLIndicatorPlugin,
 | 
			
		||||
@@ -53,6 +55,7 @@ define([
 | 
			
		||||
        Espresso: 'platform/commonUI/themes/espresso',
 | 
			
		||||
        LocalStorage: 'platform/persistence/local',
 | 
			
		||||
        MyItems: 'platform/features/my-items',
 | 
			
		||||
        Notebook: 'platform/features/notebook',
 | 
			
		||||
        Snow: 'platform/commonUI/themes/snow'
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,14 @@
 | 
			
		||||
define(['./src/SummaryWidget', './SummaryWidgetsCompositionPolicy'], function (SummaryWidget, SummaryWidgetsCompositionPolicy) {
 | 
			
		||||
define([
 | 
			
		||||
    './SummaryWidgetsCompositionPolicy',
 | 
			
		||||
    './src/telemetry/SummaryWidgetMetadataProvider',
 | 
			
		||||
    './src/telemetry/SummaryWidgetTelemetryProvider',
 | 
			
		||||
    './src/views/SummaryWidgetViewProvider'
 | 
			
		||||
], function (
 | 
			
		||||
    SummaryWidgetsCompositionPolicy,
 | 
			
		||||
    SummaryWidgetMetadataProvider,
 | 
			
		||||
    SummaryWidgetTelemetryProvider,
 | 
			
		||||
    SummaryWidgetViewProvider
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    function plugin() {
 | 
			
		||||
 | 
			
		||||
@@ -9,8 +19,40 @@ define(['./src/SummaryWidget', './SummaryWidgetsCompositionPolicy'], function (S
 | 
			
		||||
            cssClass: 'icon-summary-widget',
 | 
			
		||||
            initialize: function (domainObject) {
 | 
			
		||||
                domainObject.composition = [];
 | 
			
		||||
                domainObject.configuration = {};
 | 
			
		||||
                domainObject.configuration = {
 | 
			
		||||
                    ruleOrder: ['default'],
 | 
			
		||||
                    ruleConfigById: {
 | 
			
		||||
                        default: {
 | 
			
		||||
                            name: 'Default',
 | 
			
		||||
                            label: 'Unnamed Rule',
 | 
			
		||||
                            message: '',
 | 
			
		||||
                            id: 'default',
 | 
			
		||||
                            icon: ' ',
 | 
			
		||||
                            style: {
 | 
			
		||||
                                'color': '#ffffff',
 | 
			
		||||
                                'background-color': '#38761d',
 | 
			
		||||
                                'border-color': 'rgba(0,0,0,0)'
 | 
			
		||||
                            },
 | 
			
		||||
                            description: 'Default appearance for the widget',
 | 
			
		||||
                            conditions: [{
 | 
			
		||||
                                object: '',
 | 
			
		||||
                                key: '',
 | 
			
		||||
                                operation: '',
 | 
			
		||||
                                values: []
 | 
			
		||||
                            }],
 | 
			
		||||
                            jsCondition: '',
 | 
			
		||||
                            trigger: 'any',
 | 
			
		||||
                            expanded: 'true'
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
                    testDataConfig: [{
 | 
			
		||||
                        object: '',
 | 
			
		||||
                        key: '',
 | 
			
		||||
                        value: ''
 | 
			
		||||
                    }]
 | 
			
		||||
                };
 | 
			
		||||
                domainObject.openNewTab = 'thisTab';
 | 
			
		||||
                domainObject.telemetry = {};
 | 
			
		||||
            },
 | 
			
		||||
            form: [
 | 
			
		||||
                {
 | 
			
		||||
@@ -40,26 +82,14 @@ define(['./src/SummaryWidget', './SummaryWidgetsCompositionPolicy'], function (S
 | 
			
		||||
            ]
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        function initViewProvider(openmct) {
 | 
			
		||||
            return {
 | 
			
		||||
                name: 'Widget View',
 | 
			
		||||
                view: function (domainObject) {
 | 
			
		||||
                    return new SummaryWidget(domainObject, openmct);
 | 
			
		||||
                },
 | 
			
		||||
                canView: function (domainObject) {
 | 
			
		||||
                    return (domainObject.type === 'summary-widget');
 | 
			
		||||
                },
 | 
			
		||||
                editable: true,
 | 
			
		||||
                key: 'summaryWidgets'
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return function install(openmct) {
 | 
			
		||||
            openmct.types.addType('summary-widget', widgetType);
 | 
			
		||||
            openmct.objectViews.addProvider(initViewProvider(openmct));
 | 
			
		||||
            openmct.legacyExtension('policies', {category: 'composition',
 | 
			
		||||
                implementation: SummaryWidgetsCompositionPolicy, depends: ['openmct']
 | 
			
		||||
            });
 | 
			
		||||
            openmct.telemetry.addProvider(new SummaryWidgetMetadataProvider(openmct));
 | 
			
		||||
            openmct.telemetry.addProvider(new SummaryWidgetTelemetryProvider(openmct));
 | 
			
		||||
            openmct.objectViews.addProvider(new SummaryWidgetViewProvider(openmct));
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
<li class="t-condition">
 | 
			
		||||
<li class="has-local-controls t-condition">
 | 
			
		||||
    <label class="t-condition-context">when</label>
 | 
			
		||||
    <span class="controls">
 | 
			
		||||
        <span class="t-configuration"> </span>
 | 
			
		||||
        <span class="t-value-inputs"> </span>
 | 
			
		||||
    </span>
 | 
			
		||||
    <span class="flex-elem l-condition-action-buttons-wrapper">
 | 
			
		||||
    <span class="flex-elem local-control l-condition-action-buttons-wrapper">
 | 
			
		||||
        <a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this condition"></a>
 | 
			
		||||
        <a class="s-icon-button icon-trash t-delete" title="Delete this condition"></a>
 | 
			
		||||
    </span>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
<div>
 | 
			
		||||
    <div class="l-widget-rule s-widget-rule l-compact-form">
 | 
			
		||||
    <div class="l-compact-form has-local-controls l-widget-rule s-widget-rule">
 | 
			
		||||
        <div class="widget-rule-header">
 | 
			
		||||
            <span class="flex-elem l-widget-thumb-wrapper">
 | 
			
		||||
                <span class="grippy-holder">
 | 
			
		||||
                    <span class="t-grippy grippy"></span>
 | 
			
		||||
                    <span class="t-grippy grippy local-control"></span>
 | 
			
		||||
                </span>
 | 
			
		||||
                <span class="view-control expanded"></span>
 | 
			
		||||
                <span class="t-widget-thumb widget-thumb">
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
            </span>
 | 
			
		||||
            <span class="flex-elem rule-title">Default Title</span>
 | 
			
		||||
            <span class="flex-elem rule-description grows">Rule description goes here</span>
 | 
			
		||||
            <span class="flex-elem l-rule-action-buttons-wrapper">
 | 
			
		||||
            <span class="flex-elem local-control l-rule-action-buttons-wrapper">
 | 
			
		||||
                <a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this rule"></a>
 | 
			
		||||
                <a class="s-icon-button icon-trash t-delete" title="Delete this rule"></a>
 | 
			
		||||
            </span>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
<div class="t-test-data-item l-compact-form l-widget-test-data-item s-widget-test-data-item">
 | 
			
		||||
<div class="t-test-data-item l-compact-form has-local-controls l-widget-test-data-item s-widget-test-data-item">
 | 
			
		||||
    <ul>
 | 
			
		||||
        <li>
 | 
			
		||||
            <label>Set </label>
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
                <span class="equal-to hidden"> equal to </span>
 | 
			
		||||
                <span class="t-value-inputs"></span>
 | 
			
		||||
            </span>
 | 
			
		||||
            <span class="flex-elem l-widget-test-data-item-action-buttons-wrapper">
 | 
			
		||||
            <span class="flex-elem local-control l-widget-test-data-item-action-buttons-wrapper">
 | 
			
		||||
                <a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this test value"></a>
 | 
			
		||||
                <a class="s-icon-button icon-trash t-delete" title="Delete this test value"></a>
 | 
			
		||||
            </span>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,12 @@
 | 
			
		||||
define ([
 | 
			
		||||
    './ConditionEvaluator',
 | 
			
		||||
    '../../../api/objects/object-utils',
 | 
			
		||||
    'EventEmitter',
 | 
			
		||||
    'zepto',
 | 
			
		||||
    'lodash'
 | 
			
		||||
], function (
 | 
			
		||||
    ConditionEvaluator,
 | 
			
		||||
    objectUtils,
 | 
			
		||||
    EventEmitter,
 | 
			
		||||
    $,
 | 
			
		||||
    _
 | 
			
		||||
@@ -123,21 +125,23 @@ define ([
 | 
			
		||||
     *                   has completed and types have been parsed
 | 
			
		||||
     */
 | 
			
		||||
    ConditionManager.prototype.parsePropertyTypes = function (object) {
 | 
			
		||||
        var telemetryAPI = this.openmct.telemetry,
 | 
			
		||||
            key,
 | 
			
		||||
            type,
 | 
			
		||||
            self = this;
 | 
			
		||||
        var objectId = objectUtils.makeKeyString(object.identifier);
 | 
			
		||||
 | 
			
		||||
        self.telemetryTypesById[object.identifier.key] = {};
 | 
			
		||||
        return telemetryAPI.request(object, {size: 1, strategy: 'latest'}).then(function (telemetry) {
 | 
			
		||||
            Object.entries(telemetry[telemetry.length - 1]).forEach(function (telem) {
 | 
			
		||||
                key = telem[0];
 | 
			
		||||
                type = typeof telem[1];
 | 
			
		||||
                self.telemetryTypesById[object.identifier.key][key] = type;
 | 
			
		||||
                self.subscriptionCache[object.identifier.key][key] = telem[1];
 | 
			
		||||
                self.addGlobalPropertyType(key, type);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        this.telemetryTypesById[objectId] = {};
 | 
			
		||||
        Object.values(this.telemetryMetadataById[objectId]).forEach(function (valueMetadata) {
 | 
			
		||||
            var type;
 | 
			
		||||
            if (valueMetadata.hints.hasOwnProperty('range')) {
 | 
			
		||||
                type = 'number';
 | 
			
		||||
            } else if (valueMetadata.hints.hasOwnProperty('domain')) {
 | 
			
		||||
                type = 'number';
 | 
			
		||||
            } else if (valueMetadata.key === 'name') {
 | 
			
		||||
                type = 'string';
 | 
			
		||||
            } else {
 | 
			
		||||
                type = 'string';
 | 
			
		||||
            }
 | 
			
		||||
            this.telemetryTypesById[objectId][valueMetadata.key] = type;
 | 
			
		||||
            this.addGlobalPropertyType(valueMetadata.key, type);
 | 
			
		||||
        }, this);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -147,23 +151,9 @@ define ([
 | 
			
		||||
     *                   and property types parsed
 | 
			
		||||
     */
 | 
			
		||||
    ConditionManager.prototype.parseAllPropertyTypes = function () {
 | 
			
		||||
        var self = this,
 | 
			
		||||
            index = 0,
 | 
			
		||||
            objs = Object.values(self.compositionObjs),
 | 
			
		||||
            promise = new Promise(function (resolve, reject) {
 | 
			
		||||
                if (objs.length === 0) {
 | 
			
		||||
                    resolve();
 | 
			
		||||
                }
 | 
			
		||||
                objs.forEach(function (obj) {
 | 
			
		||||
                    self.parsePropertyTypes(obj).then(function () {
 | 
			
		||||
                        if (index === objs.length - 1) {
 | 
			
		||||
                            resolve();
 | 
			
		||||
                        }
 | 
			
		||||
                        index += 1;
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        return promise;
 | 
			
		||||
        Object.values(this.compositionObjs).forEach(this.parsePropertyTypes, this);
 | 
			
		||||
        this.metadataLoadComplete = true;
 | 
			
		||||
        this.eventEmitter.emit('metadata');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -187,7 +177,7 @@ define ([
 | 
			
		||||
    ConditionManager.prototype.onCompositionAdd = function (obj) {
 | 
			
		||||
        var compositionKeys,
 | 
			
		||||
            telemetryAPI = this.openmct.telemetry,
 | 
			
		||||
            objId = obj.identifier.key,
 | 
			
		||||
            objId = objectUtils.makeKeyString(obj.identifier),
 | 
			
		||||
            telemetryMetadata,
 | 
			
		||||
            self = this;
 | 
			
		||||
 | 
			
		||||
@@ -195,10 +185,9 @@ define ([
 | 
			
		||||
            self.compositionObjs[objId] = obj;
 | 
			
		||||
            self.telemetryMetadataById[objId] = {};
 | 
			
		||||
 | 
			
		||||
            compositionKeys = self.domainObject.composition.map(function (object) {
 | 
			
		||||
                return object.key;
 | 
			
		||||
            });
 | 
			
		||||
            if (!compositionKeys.includes(obj.identifier.key)) {
 | 
			
		||||
            // FIXME: this should just update based on listener.
 | 
			
		||||
            compositionKeys = self.domainObject.composition.map(objectUtils.makeKeyString);
 | 
			
		||||
            if (!compositionKeys.includes(objId)) {
 | 
			
		||||
                self.domainObject.composition.push(obj.identifier);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -212,6 +201,12 @@ define ([
 | 
			
		||||
            self.subscriptions[objId] = telemetryAPI.subscribe(obj, function (datum) {
 | 
			
		||||
                self.handleSubscriptionCallback(objId, datum);
 | 
			
		||||
            }, {});
 | 
			
		||||
            telemetryAPI.request(obj, {strategy: 'latest', size: 1})
 | 
			
		||||
                .then(function (results) {
 | 
			
		||||
                    if (results && results.length) {
 | 
			
		||||
                        self.handleSubscriptionCallback(objId, results[results.length - 1]);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            /**
 | 
			
		||||
             * if this is the initial load, parsing property types will be postponed
 | 
			
		||||
@@ -234,11 +229,14 @@ define ([
 | 
			
		||||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    ConditionManager.prototype.onCompositionRemove = function (identifier) {
 | 
			
		||||
        var objectId = objectUtils.makeKeyString(identifier);
 | 
			
		||||
        // FIXME: this should just update by listener.
 | 
			
		||||
        _.remove(this.domainObject.composition, function (id) {
 | 
			
		||||
            return id.key === identifier.key;
 | 
			
		||||
            return id.key === identifier.key &&
 | 
			
		||||
                id.namespace === identifier.namespace;
 | 
			
		||||
        });
 | 
			
		||||
        delete this.compositionObjs[identifier.key];
 | 
			
		||||
        this.subscriptions[identifier.key](); //unsubscribe from telemetry source
 | 
			
		||||
        delete this.compositionObjs[objectId];
 | 
			
		||||
        this.subscriptions[objectId](); //unsubscribe from telemetry source
 | 
			
		||||
        this.eventEmitter.emit('remove', identifier);
 | 
			
		||||
 | 
			
		||||
        if (_.isEmpty(this.compositionObjs)) {
 | 
			
		||||
@@ -253,13 +251,9 @@ define ([
 | 
			
		||||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    ConditionManager.prototype.onCompositionLoad = function () {
 | 
			
		||||
        var self = this;
 | 
			
		||||
        self.loadComplete = true;
 | 
			
		||||
        self.eventEmitter.emit('load');
 | 
			
		||||
        self.parseAllPropertyTypes().then(function () {
 | 
			
		||||
            self.metadataLoadComplete = true;
 | 
			
		||||
            self.eventEmitter.emit('metadata');
 | 
			
		||||
        });
 | 
			
		||||
        this.loadComplete = true;
 | 
			
		||||
        this.eventEmitter.emit('load');
 | 
			
		||||
        this.parseAllPropertyTypes();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,10 @@
 | 
			
		||||
define(['./Select'], function (Select) {
 | 
			
		||||
define([
 | 
			
		||||
    './Select',
 | 
			
		||||
    '../../../../api/objects/object-utils'
 | 
			
		||||
], function (
 | 
			
		||||
    Select,
 | 
			
		||||
    objectUtils
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a {Select} element whose composition is dynamically updated with
 | 
			
		||||
@@ -37,7 +43,7 @@ define(['./Select'], function (Select) {
 | 
			
		||||
         * @private
 | 
			
		||||
         */
 | 
			
		||||
        function onCompositionAdd(obj) {
 | 
			
		||||
            self.select.addOption(obj.identifier.key, obj.name);
 | 
			
		||||
            self.select.addOption(objectUtils.makeKeyString(obj.identifier), obj.name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
@@ -75,7 +81,7 @@ define(['./Select'], function (Select) {
 | 
			
		||||
     */
 | 
			
		||||
    ObjectSelect.prototype.generateOptions = function () {
 | 
			
		||||
        var items = Object.values(this.compositionObjs).map(function (obj) {
 | 
			
		||||
            return [obj.identifier.key, obj.name];
 | 
			
		||||
            return [objectUtils.makeKeyString(obj.identifier), obj.name];
 | 
			
		||||
        });
 | 
			
		||||
        this.baseOptions.forEach(function (option, index) {
 | 
			
		||||
            items.splice(index, 0, option);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								src/plugins/summaryWidget/src/telemetry/EvaluatorPool.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/plugins/summaryWidget/src/telemetry/EvaluatorPool.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
    './SummaryWidgetEvaluator',
 | 
			
		||||
    '../../../../api/objects/object-utils'
 | 
			
		||||
], function (
 | 
			
		||||
    SummaryWidgetEvaluator,
 | 
			
		||||
    objectUtils
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    function EvaluatorPool(openmct) {
 | 
			
		||||
        this.openmct = openmct;
 | 
			
		||||
        this.byObjectId = {};
 | 
			
		||||
        this.byEvaluator = new WeakMap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EvaluatorPool.prototype.get = function (domainObject) {
 | 
			
		||||
        var objectId = objectUtils.makeKeyString(domainObject.identifier);
 | 
			
		||||
        var poolEntry = this.byObjectId[objectId];
 | 
			
		||||
        if (!poolEntry) {
 | 
			
		||||
            poolEntry = {
 | 
			
		||||
                leases: 0,
 | 
			
		||||
                objectId: objectId,
 | 
			
		||||
                evaluator: new SummaryWidgetEvaluator(domainObject, this.openmct)
 | 
			
		||||
            };
 | 
			
		||||
            this.byEvaluator.set(poolEntry.evaluator, poolEntry);
 | 
			
		||||
            this.byObjectId[objectId] = poolEntry;
 | 
			
		||||
        }
 | 
			
		||||
        poolEntry.leases += 1;
 | 
			
		||||
        return poolEntry.evaluator;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    EvaluatorPool.prototype.release = function (evaluator) {
 | 
			
		||||
        var poolEntry = this.byEvaluator.get(evaluator);
 | 
			
		||||
        poolEntry.leases -= 1;
 | 
			
		||||
        if (poolEntry.leases === 0) {
 | 
			
		||||
            evaluator.destroy();
 | 
			
		||||
            this.byEvaluator.delete(evaluator);
 | 
			
		||||
            delete this.byObjectId[poolEntry.objectId];
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return EvaluatorPool;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										102
									
								
								src/plugins/summaryWidget/src/telemetry/EvaluatorPoolSpec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/plugins/summaryWidget/src/telemetry/EvaluatorPoolSpec.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
    './EvaluatorPool',
 | 
			
		||||
    './SummaryWidgetEvaluator'
 | 
			
		||||
], function (
 | 
			
		||||
    EvaluatorPool,
 | 
			
		||||
    SummaryWidgetEvaluator
 | 
			
		||||
) {
 | 
			
		||||
    describe('EvaluatorPool', function () {
 | 
			
		||||
        var pool;
 | 
			
		||||
        var openmct;
 | 
			
		||||
        var objectA;
 | 
			
		||||
        var objectB;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            openmct = {
 | 
			
		||||
                composition: jasmine.createSpyObj('compositionAPI', ['get']),
 | 
			
		||||
                objects: jasmine.createSpyObj('objectAPI', ['observe'])
 | 
			
		||||
            };
 | 
			
		||||
            openmct.composition.get.andCallFake(function () {
 | 
			
		||||
                var compositionCollection = jasmine.createSpyObj(
 | 
			
		||||
                    'compositionCollection',
 | 
			
		||||
                    [
 | 
			
		||||
                        'load',
 | 
			
		||||
                        'on',
 | 
			
		||||
                        'off'
 | 
			
		||||
                    ]
 | 
			
		||||
                );
 | 
			
		||||
                compositionCollection.load.andReturn(Promise.resolve());
 | 
			
		||||
                return compositionCollection;
 | 
			
		||||
            });
 | 
			
		||||
            openmct.objects.observe.andCallFake(function () {
 | 
			
		||||
                return function () {};
 | 
			
		||||
            });
 | 
			
		||||
            pool = new EvaluatorPool(openmct);
 | 
			
		||||
            objectA = {
 | 
			
		||||
                identifier: {
 | 
			
		||||
                    namespace: 'someNamespace',
 | 
			
		||||
                    key: 'someKey'
 | 
			
		||||
                },
 | 
			
		||||
                configuration: {
 | 
			
		||||
                    ruleOrder: []
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            objectB = {
 | 
			
		||||
                identifier: {
 | 
			
		||||
                    namespace: 'otherNamespace',
 | 
			
		||||
                    key: 'otherKey'
 | 
			
		||||
                },
 | 
			
		||||
                configuration: {
 | 
			
		||||
                    ruleOrder: []
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('returns new evaluators for different objects', function () {
 | 
			
		||||
            var evaluatorA = pool.get(objectA);
 | 
			
		||||
            var evaluatorB = pool.get(objectB);
 | 
			
		||||
            expect(evaluatorA).not.toBe(evaluatorB);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('returns the same evaluator for the same object', function () {
 | 
			
		||||
            var evaluatorA = pool.get(objectA);
 | 
			
		||||
            var evaluatorB = pool.get(objectA);
 | 
			
		||||
            expect(evaluatorA).toBe(evaluatorB);
 | 
			
		||||
 | 
			
		||||
            var evaluatorC = pool.get(JSON.parse(JSON.stringify(objectA)));
 | 
			
		||||
            expect(evaluatorA).toBe(evaluatorC);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('returns new evaluator when old is released', function () {
 | 
			
		||||
            var evaluatorA = pool.get(objectA);
 | 
			
		||||
            var evaluatorB = pool.get(objectA);
 | 
			
		||||
            expect(evaluatorA).toBe(evaluatorB);
 | 
			
		||||
            pool.release(evaluatorA);
 | 
			
		||||
            pool.release(evaluatorB);
 | 
			
		||||
            var evaluatorC = pool.get(objectA);
 | 
			
		||||
            expect(evaluatorA).not.toBe(evaluatorC);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,80 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
    './operations'
 | 
			
		||||
], function (
 | 
			
		||||
    OPERATIONS
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    function SummaryWidgetCondition(definition) {
 | 
			
		||||
        this.object = definition.object;
 | 
			
		||||
        this.key = definition.key;
 | 
			
		||||
        this.values = definition.values;
 | 
			
		||||
        if (!definition.operation) {
 | 
			
		||||
            // TODO: better handling for default rule.
 | 
			
		||||
            this.evaluate = function () {
 | 
			
		||||
                return true;
 | 
			
		||||
            };
 | 
			
		||||
        } else {
 | 
			
		||||
            this.comparator = OPERATIONS[definition.operation].operation;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetCondition.prototype.evaluate = function (telemetryState) {
 | 
			
		||||
        var stateKeys = Object.keys(telemetryState);
 | 
			
		||||
        var state;
 | 
			
		||||
        var result;
 | 
			
		||||
        var i;
 | 
			
		||||
 | 
			
		||||
        if (this.object === 'any') {
 | 
			
		||||
            for (i = 0; i < stateKeys.length; i++) {
 | 
			
		||||
                state = telemetryState[stateKeys[i]];
 | 
			
		||||
                result = this.evaluateState(state);
 | 
			
		||||
                if (result) {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        } else if (this.object === 'all') {
 | 
			
		||||
            for (i = 0; i < stateKeys.length; i++) {
 | 
			
		||||
                state = telemetryState[stateKeys[i]];
 | 
			
		||||
                result = this.evaluateState(state);
 | 
			
		||||
                if (!result) {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            return this.evaluateState(telemetryState[this.object]);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetCondition.prototype.evaluateState = function (state) {
 | 
			
		||||
        var testValues = [
 | 
			
		||||
            state.formats[this.key].parse(state.lastDatum)
 | 
			
		||||
        ].concat(this.values);
 | 
			
		||||
        return this.comparator(testValues);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return SummaryWidgetCondition;
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,142 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
    './SummaryWidgetCondition'
 | 
			
		||||
], function (
 | 
			
		||||
    SummaryWidgetCondition
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    describe('SummaryWidgetCondition', function () {
 | 
			
		||||
        var condition;
 | 
			
		||||
        var telemetryState;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            // Format map intentionally uses different keys than those present
 | 
			
		||||
            // in datum, which serves to verify conditions use format map to get
 | 
			
		||||
            // data.
 | 
			
		||||
            var formatMap = {
 | 
			
		||||
                adjusted: {
 | 
			
		||||
                    parse: function (datum) {
 | 
			
		||||
                        return datum.value + 10;
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                raw: {
 | 
			
		||||
                    parse: function (datum) {
 | 
			
		||||
                        return datum.value;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            telemetryState = {
 | 
			
		||||
                objectId: {
 | 
			
		||||
                    formats: formatMap,
 | 
			
		||||
                    lastDatum: {
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                otherObjectId: {
 | 
			
		||||
                    formats: formatMap,
 | 
			
		||||
                    lastDatum: {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can evaluate if a single object matches', function () {
 | 
			
		||||
            condition = new SummaryWidgetCondition({
 | 
			
		||||
                object: 'objectId',
 | 
			
		||||
                key: 'raw',
 | 
			
		||||
                operation: 'greaterThan',
 | 
			
		||||
                values: [
 | 
			
		||||
                    10
 | 
			
		||||
                ]
 | 
			
		||||
            });
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 5;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can evaluate if a single object matches (alternate keys)', function () {
 | 
			
		||||
            condition = new SummaryWidgetCondition({
 | 
			
		||||
                object: 'objectId',
 | 
			
		||||
                key: 'adjusted',
 | 
			
		||||
                operation: 'greaterThan',
 | 
			
		||||
                values: [
 | 
			
		||||
                    10
 | 
			
		||||
                ]
 | 
			
		||||
            });
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = -5;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 5;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can evaluate "if all objects match"', function () {
 | 
			
		||||
            condition = new SummaryWidgetCondition({
 | 
			
		||||
                object: 'all',
 | 
			
		||||
                key: 'raw',
 | 
			
		||||
                operation: 'greaterThan',
 | 
			
		||||
                values: [
 | 
			
		||||
                    10
 | 
			
		||||
                ]
 | 
			
		||||
            });
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 0;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 0;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 0;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 15;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 0;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 15;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can evalute "if any object matches"', function () {
 | 
			
		||||
            condition = new SummaryWidgetCondition({
 | 
			
		||||
                object: 'any',
 | 
			
		||||
                key: 'raw',
 | 
			
		||||
                operation: 'greaterThan',
 | 
			
		||||
                values: [
 | 
			
		||||
                    10
 | 
			
		||||
                ]
 | 
			
		||||
            });
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 0;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 0;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 0;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 15;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 0;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 15;
 | 
			
		||||
            expect(condition.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,264 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
    './SummaryWidgetRule',
 | 
			
		||||
    '../eventHelpers',
 | 
			
		||||
    '../../../../api/objects/object-utils',
 | 
			
		||||
    'lodash'
 | 
			
		||||
], function (
 | 
			
		||||
    SummaryWidgetRule,
 | 
			
		||||
    eventHelpers,
 | 
			
		||||
    objectUtils,
 | 
			
		||||
    _
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * evaluates rules defined in a summary widget against either lad or
 | 
			
		||||
     * realtime state.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    function SummaryWidgetEvaluator(domainObject, openmct) {
 | 
			
		||||
        this.openmct = openmct;
 | 
			
		||||
        this.baseState = {};
 | 
			
		||||
 | 
			
		||||
        this.updateRules(domainObject);
 | 
			
		||||
        this.removeObserver = openmct.objects.observe(
 | 
			
		||||
            domainObject,
 | 
			
		||||
            '*',
 | 
			
		||||
            this.updateRules.bind(this)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        var composition = openmct.composition.get(domainObject);
 | 
			
		||||
 | 
			
		||||
        this.listenTo(composition, 'add', this.addChild, this);
 | 
			
		||||
        this.listenTo(composition, 'remove', this.removeChild, this);
 | 
			
		||||
 | 
			
		||||
        this.loadPromise = composition.load();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    eventHelpers.extend(SummaryWidgetEvaluator.prototype);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Subscribes to realtime telemetry for the given summary widget.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.subscribe = function (callback) {
 | 
			
		||||
        var active = true;
 | 
			
		||||
        var unsubscribes = [];
 | 
			
		||||
 | 
			
		||||
        this.getBaseStateClone()
 | 
			
		||||
            .then(function (realtimeStates) {
 | 
			
		||||
                if (!active) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var updateCallback = function () {
 | 
			
		||||
                    var datum = this.evaluateState(
 | 
			
		||||
                        realtimeStates,
 | 
			
		||||
                        this.openmct.time.timeSystem().key
 | 
			
		||||
                    );
 | 
			
		||||
                    callback(datum);
 | 
			
		||||
                }.bind(this);
 | 
			
		||||
 | 
			
		||||
                unsubscribes = _.map(
 | 
			
		||||
                    realtimeStates,
 | 
			
		||||
                    this.subscribeToObjectState.bind(this, updateCallback)
 | 
			
		||||
                );
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
 | 
			
		||||
        return function () {
 | 
			
		||||
            active = false;
 | 
			
		||||
            unsubscribes.forEach(function (unsubscribe) {
 | 
			
		||||
                unsubscribe();
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns a promise for a telemetry datum obtained by evaluating the
 | 
			
		||||
     * current lad data.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.requestLatest = function (options) {
 | 
			
		||||
        return this.getBaseStateClone()
 | 
			
		||||
            .then(function (ladState) {
 | 
			
		||||
                var promises = Object.values(ladState)
 | 
			
		||||
                    .map(this.updateObjectStateFromLAD.bind(this, options));
 | 
			
		||||
 | 
			
		||||
                return Promise.all(promises)
 | 
			
		||||
                    .then(function () {
 | 
			
		||||
                        return ladState;
 | 
			
		||||
                    });
 | 
			
		||||
            }.bind(this))
 | 
			
		||||
            .then(function (ladStates) {
 | 
			
		||||
                return this.evaluateState(ladStates, options.domain);
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.updateRules = function (domainObject) {
 | 
			
		||||
        this.rules = domainObject.configuration.ruleOrder.map(function (ruleId) {
 | 
			
		||||
            return new SummaryWidgetRule(domainObject.configuration.ruleConfigById[ruleId]);
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.addChild = function (childObject) {
 | 
			
		||||
        var childId = objectUtils.makeKeyString(childObject.identifier);
 | 
			
		||||
        var metadata = this.openmct.telemetry.getMetadata(childObject);
 | 
			
		||||
        var formats = this.openmct.telemetry.getFormatMap(metadata);
 | 
			
		||||
 | 
			
		||||
        this.baseState[childId] = {
 | 
			
		||||
            id: childId,
 | 
			
		||||
            domainObject: childObject,
 | 
			
		||||
            metadata: metadata,
 | 
			
		||||
            formats: formats
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.removeChild = function (childObject) {
 | 
			
		||||
        var childId = objectUtils.makeKeyString(childObject.identifier);
 | 
			
		||||
        delete this.baseState[childId];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.load = function () {
 | 
			
		||||
        return this.loadPromise;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * return a promise for a clone of the base state object.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.getBaseStateClone = function () {
 | 
			
		||||
        return this.load()
 | 
			
		||||
            .then(function () {
 | 
			
		||||
                return _(this.baseState)
 | 
			
		||||
                    .values()
 | 
			
		||||
                    .map(_.clone)
 | 
			
		||||
                    .indexBy('id')
 | 
			
		||||
                    .value();
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Subscribes to realtime updates for a given objectState, and invokes
 | 
			
		||||
     * the supplied callback when objectState has been updated.  Returns
 | 
			
		||||
     * a function to unsubscribe.
 | 
			
		||||
     * @private.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.subscribeToObjectState = function (callback, objectState) {
 | 
			
		||||
        return this.openmct.telemetry.subscribe(
 | 
			
		||||
            objectState.domainObject,
 | 
			
		||||
            function (datum) {
 | 
			
		||||
                objectState.lastDatum = datum;
 | 
			
		||||
                objectState.timestamps = this.getTimestamps(objectState.id, datum);
 | 
			
		||||
                callback();
 | 
			
		||||
            }.bind(this)
 | 
			
		||||
        );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Given an object state, will return a promise that is resolved when the
 | 
			
		||||
     * object state has been updated from the LAD.
 | 
			
		||||
     * @private.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.updateObjectStateFromLAD = function (options, objectState) {
 | 
			
		||||
        options = _.extend({}, options, {
 | 
			
		||||
            strategy: 'latest',
 | 
			
		||||
            size: 1
 | 
			
		||||
        });
 | 
			
		||||
        return this.openmct
 | 
			
		||||
            .telemetry
 | 
			
		||||
            .request(
 | 
			
		||||
                objectState.domainObject,
 | 
			
		||||
                options
 | 
			
		||||
            )
 | 
			
		||||
            .then(function (results) {
 | 
			
		||||
                objectState.lastDatum = results[results.length - 1];
 | 
			
		||||
                objectState.timestamps = this.getTimestamps(
 | 
			
		||||
                    objectState.id,
 | 
			
		||||
                    objectState.lastDatum
 | 
			
		||||
                );
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns an object containing all domain values in a datum.
 | 
			
		||||
     * @private.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.getTimestamps = function (childId, datum) {
 | 
			
		||||
        var timestampedDatum = {};
 | 
			
		||||
        this.openmct.time.getAllTimeSystems().forEach(function (timeSystem) {
 | 
			
		||||
            timestampedDatum[timeSystem.key] =
 | 
			
		||||
                this.baseState[childId].formats[timeSystem.key].parse(datum);
 | 
			
		||||
        }, this);
 | 
			
		||||
        return timestampedDatum;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Given a base datum(containing timestamps) and rule index, adds values
 | 
			
		||||
     * from the matching rule.
 | 
			
		||||
     * @private
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.makeDatumFromRule = function (ruleIndex, baseDatum) {
 | 
			
		||||
        var rule = this.rules[ruleIndex];
 | 
			
		||||
 | 
			
		||||
        baseDatum.ruleLabel = rule.label;
 | 
			
		||||
        baseDatum.ruleName = rule.name;
 | 
			
		||||
        baseDatum.message = rule.message;
 | 
			
		||||
        baseDatum.ruleIndex = ruleIndex;
 | 
			
		||||
        baseDatum.backgroundColor = rule.style['background-color'];
 | 
			
		||||
        baseDatum.textColor = rule.style.color;
 | 
			
		||||
        baseDatum.borderColor = rule.style['border-color'];
 | 
			
		||||
        baseDatum.icon = rule.icon;
 | 
			
		||||
 | 
			
		||||
        return baseDatum;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * evaluate a state object and return a summary widget telemetry datum.
 | 
			
		||||
     * Will use the specified timestampKey to decide which timestamps to apply.
 | 
			
		||||
     * @private.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.evaluateState = function (state, timestampKey) {
 | 
			
		||||
        var latestTimestamp = _(state)
 | 
			
		||||
            .map('timestamps')
 | 
			
		||||
            .sortBy(timestampKey)
 | 
			
		||||
            .first();
 | 
			
		||||
 | 
			
		||||
        latestTimestamp = _.clone(latestTimestamp);
 | 
			
		||||
 | 
			
		||||
        for (var i = this.rules.length - 1; i > 0; i--) {
 | 
			
		||||
            if (this.rules[i].evaluate(state, false)) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this.makeDatumFromRule(i, latestTimestamp);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * remove all listeners and clean up any resources.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetEvaluator.prototype.destroy = function () {
 | 
			
		||||
        this.stopListening();
 | 
			
		||||
        this.removeObserver();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return SummaryWidgetEvaluator;
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,119 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
 | 
			
		||||
], function (
 | 
			
		||||
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    function SummaryWidgetMetadataProvider(openmct) {
 | 
			
		||||
        this.openmct = openmct;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetMetadataProvider.prototype.supportsMetadata = function (domainObject) {
 | 
			
		||||
        return domainObject.type === 'summary-widget';
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetMetadataProvider.prototype.getDomains = function (domainObject) {
 | 
			
		||||
        return this.openmct.time.getAllTimeSystems().map(function (ts, i) {
 | 
			
		||||
            return {
 | 
			
		||||
                key: ts.key,
 | 
			
		||||
                name: 'UTC',
 | 
			
		||||
                format: ts.timeFormat,
 | 
			
		||||
                hints: {
 | 
			
		||||
                    domain: i
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetMetadataProvider.prototype.getMetadata = function (domainObject) {
 | 
			
		||||
        var ruleOrder = domainObject.configuration.ruleOrder || [];
 | 
			
		||||
        var enumerations = ruleOrder
 | 
			
		||||
            .filter(function (ruleId) {
 | 
			
		||||
                return !!domainObject.configuration.ruleConfigById[ruleId];
 | 
			
		||||
            })
 | 
			
		||||
            .map(function (ruleId, ruleIndex) {
 | 
			
		||||
                return {
 | 
			
		||||
                    string: domainObject.configuration.ruleConfigById[ruleId].label,
 | 
			
		||||
                    value: ruleIndex
 | 
			
		||||
                };
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        var metadata = {
 | 
			
		||||
            // Generally safe assumption is that we have one domain per timeSystem.
 | 
			
		||||
            values: this.getDomains().concat([
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'state',
 | 
			
		||||
                    key: 'state',
 | 
			
		||||
                    source: 'ruleIndex',
 | 
			
		||||
                    format: 'enum',
 | 
			
		||||
                    enumerations: enumerations,
 | 
			
		||||
                    hints: {
 | 
			
		||||
                        range: 1
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Rule Label',
 | 
			
		||||
                    key: 'ruleLabel',
 | 
			
		||||
                    format: 'string'
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Rule Name',
 | 
			
		||||
                    key: 'ruleName',
 | 
			
		||||
                    format: 'string'
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Message',
 | 
			
		||||
                    key: 'message',
 | 
			
		||||
                    format: 'string'
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Background Color',
 | 
			
		||||
                    key: 'backgroundColor',
 | 
			
		||||
                    format: 'string'
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Text Color',
 | 
			
		||||
                    key: 'textColor',
 | 
			
		||||
                    format: 'string'
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Border Color',
 | 
			
		||||
                    key: 'borderColor',
 | 
			
		||||
                    format: 'string'
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'Display Icon',
 | 
			
		||||
                    key: 'icon',
 | 
			
		||||
                    format: 'string'
 | 
			
		||||
                }
 | 
			
		||||
            ])
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return metadata;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return SummaryWidgetMetadataProvider;
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										73
									
								
								src/plugins/summaryWidget/src/telemetry/SummaryWidgetRule.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/plugins/summaryWidget/src/telemetry/SummaryWidgetRule.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
    './SummaryWidgetCondition'
 | 
			
		||||
], function (
 | 
			
		||||
    SummaryWidgetCondition
 | 
			
		||||
) {
 | 
			
		||||
    function SummaryWidgetRule(definition) {
 | 
			
		||||
        this.name = definition.name;
 | 
			
		||||
        this.label = definition.label;
 | 
			
		||||
        this.id = definition.id;
 | 
			
		||||
        this.icon = definition.icon;
 | 
			
		||||
        this.style = definition.style;
 | 
			
		||||
        this.message = definition.message;
 | 
			
		||||
        this.description = definition.description;
 | 
			
		||||
        this.conditions = definition.conditions.map(function (cDefinition) {
 | 
			
		||||
            return new SummaryWidgetCondition(cDefinition);
 | 
			
		||||
        });
 | 
			
		||||
        this.trigger = definition.trigger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Evaluate the given rule against a telemetryState and return true if it
 | 
			
		||||
     * matches.
 | 
			
		||||
     */
 | 
			
		||||
    SummaryWidgetRule.prototype.evaluate = function (telemetryState) {
 | 
			
		||||
        var i;
 | 
			
		||||
        var result;
 | 
			
		||||
 | 
			
		||||
        if (this.trigger === 'all') {
 | 
			
		||||
            for (i = 0; i < this.conditions.length; i++) {
 | 
			
		||||
                result = this.conditions[i].evaluate(telemetryState);
 | 
			
		||||
                if (!result) {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        } else if (this.trigger === 'any') {
 | 
			
		||||
            for (i = 0; i < this.conditions.length; i++) {
 | 
			
		||||
                result = this.conditions[i].evaluate(telemetryState);
 | 
			
		||||
                if (result) {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        } else {
 | 
			
		||||
            throw new Error('Invalid rule trigger: ' + this.trigger);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return SummaryWidgetRule;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										163
									
								
								src/plugins/summaryWidget/src/telemetry/SummaryWidgetRuleSpec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								src/plugins/summaryWidget/src/telemetry/SummaryWidgetRuleSpec.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
    './SummaryWidgetRule'
 | 
			
		||||
], function (
 | 
			
		||||
    SummaryWidgetRule
 | 
			
		||||
) {
 | 
			
		||||
    describe('SummaryWidgetRule', function () {
 | 
			
		||||
 | 
			
		||||
        var rule;
 | 
			
		||||
        var telemetryState;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            var formatMap = {
 | 
			
		||||
                raw: {
 | 
			
		||||
                    parse: function (datum) {
 | 
			
		||||
                        return datum.value;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            telemetryState = {
 | 
			
		||||
                objectId: {
 | 
			
		||||
                    formats: formatMap,
 | 
			
		||||
                    lastDatum: {
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                otherObjectId: {
 | 
			
		||||
                    formats: formatMap,
 | 
			
		||||
                    lastDatum: {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('allows single condition rules with any', function () {
 | 
			
		||||
            rule = new SummaryWidgetRule({
 | 
			
		||||
                trigger: 'any',
 | 
			
		||||
                conditions: [{
 | 
			
		||||
                    object: 'objectId',
 | 
			
		||||
                    key: 'raw',
 | 
			
		||||
                    operation: 'greaterThan',
 | 
			
		||||
                    values: [
 | 
			
		||||
                        10
 | 
			
		||||
                    ]
 | 
			
		||||
                }]
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 5;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('allows single condition rules with all', function () {
 | 
			
		||||
            rule = new SummaryWidgetRule({
 | 
			
		||||
                trigger: 'all',
 | 
			
		||||
                conditions: [{
 | 
			
		||||
                    object: 'objectId',
 | 
			
		||||
                    key: 'raw',
 | 
			
		||||
                    operation: 'greaterThan',
 | 
			
		||||
                    values: [
 | 
			
		||||
                        10
 | 
			
		||||
                    ]
 | 
			
		||||
                }]
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 5;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can combine multiple conditions with all', function () {
 | 
			
		||||
            rule = new SummaryWidgetRule({
 | 
			
		||||
                trigger: 'all',
 | 
			
		||||
                conditions: [{
 | 
			
		||||
                    object: 'objectId',
 | 
			
		||||
                    key: 'raw',
 | 
			
		||||
                    operation: 'greaterThan',
 | 
			
		||||
                    values: [
 | 
			
		||||
                        10
 | 
			
		||||
                    ]
 | 
			
		||||
                }, {
 | 
			
		||||
                    object: 'otherObjectId',
 | 
			
		||||
                    key: 'raw',
 | 
			
		||||
                    operation: 'greaterThan',
 | 
			
		||||
                    values: [
 | 
			
		||||
                        20
 | 
			
		||||
                    ]
 | 
			
		||||
                }]
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 5;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 5;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 5;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 25;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 5;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 25;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('can combine multiple conditions with any', function () {
 | 
			
		||||
            rule = new SummaryWidgetRule({
 | 
			
		||||
                trigger: 'any',
 | 
			
		||||
                conditions: [{
 | 
			
		||||
                    object: 'objectId',
 | 
			
		||||
                    key: 'raw',
 | 
			
		||||
                    operation: 'greaterThan',
 | 
			
		||||
                    values: [
 | 
			
		||||
                        10
 | 
			
		||||
                    ]
 | 
			
		||||
                }, {
 | 
			
		||||
                    object: 'otherObjectId',
 | 
			
		||||
                    key: 'raw',
 | 
			
		||||
                    operation: 'greaterThan',
 | 
			
		||||
                    values: [
 | 
			
		||||
                        20
 | 
			
		||||
                    ]
 | 
			
		||||
                }]
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 5;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 5;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(false);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 5;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 25;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 5;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
            telemetryState.objectId.lastDatum.value = 15;
 | 
			
		||||
            telemetryState.otherObjectId.lastDatum.value = 25;
 | 
			
		||||
            expect(rule.evaluate(telemetryState)).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,64 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
    './EvaluatorPool'
 | 
			
		||||
], function (
 | 
			
		||||
    EvaluatorPool
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    function SummaryWidgetTelemetryProvider(openmct) {
 | 
			
		||||
        this.pool = new EvaluatorPool(openmct);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetTelemetryProvider.prototype.supportsRequest = function (domainObject, options) {
 | 
			
		||||
        return domainObject.type === 'summary-widget';
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetTelemetryProvider.prototype.request = function (domainObject, options) {
 | 
			
		||||
        if (options.strategy !== 'latest' && options.size !== 1) {
 | 
			
		||||
            return Promise.resolve([]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var evaluator = this.pool.get(domainObject);
 | 
			
		||||
        return evaluator.requestLatest(options)
 | 
			
		||||
            .then(function (latestDatum) {
 | 
			
		||||
                this.pool.release(evaluator);
 | 
			
		||||
                return [latestDatum];
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetTelemetryProvider.prototype.supportsSubscribe = function (domainObject) {
 | 
			
		||||
        return domainObject.type === 'summary-widget';
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetTelemetryProvider.prototype.subscribe = function (domainObject, callback) {
 | 
			
		||||
        var evaluator = this.pool.get(domainObject);
 | 
			
		||||
        var unsubscribe = evaluator.subscribe(callback);
 | 
			
		||||
        return function () {
 | 
			
		||||
            this.pool.release(evaluator);
 | 
			
		||||
            unsubscribe();
 | 
			
		||||
        }.bind(this);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return SummaryWidgetTelemetryProvider;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										197
									
								
								src/plugins/summaryWidget/src/telemetry/operations.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								src/plugins/summaryWidget/src/telemetry/operations.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,197 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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([
 | 
			
		||||
 | 
			
		||||
], function (
 | 
			
		||||
 | 
			
		||||
) {
 | 
			
		||||
    var OPERATIONS = {
 | 
			
		||||
        equalTo: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] === input[1];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is equal to',
 | 
			
		||||
            appliesTo: ['number'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' == ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        notEqualTo: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] !== input[1];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is not equal to',
 | 
			
		||||
            appliesTo: ['number'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' != ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        greaterThan: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] > input[1];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is greater than',
 | 
			
		||||
            appliesTo: ['number'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' > ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        lessThan: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] < input[1];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is less than',
 | 
			
		||||
            appliesTo: ['number'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' < ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        greaterThanOrEq: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] >= input[1];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is greater than or equal to',
 | 
			
		||||
            appliesTo: ['number'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' >= ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        lessThanOrEq: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] <= input[1];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is less than or equal to',
 | 
			
		||||
            appliesTo: ['number'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' <= ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        between: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] > input[1] && input[0] < input[2];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is between',
 | 
			
		||||
            appliesTo: ['number'],
 | 
			
		||||
            inputCount: 2,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' between ' + values[0] + ' and ' + values[1];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        notBetween: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] < input[1] || input[0] > input[2];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is not between',
 | 
			
		||||
            appliesTo: ['number'],
 | 
			
		||||
            inputCount: 2,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' not between ' + values[0] + ' and ' + values[1];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        textContains: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] && input[1] && input[0].includes(input[1]);
 | 
			
		||||
            },
 | 
			
		||||
            text: 'text contains',
 | 
			
		||||
            appliesTo: ['string'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' contains ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        textDoesNotContain: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] && input[1] && !input[0].includes(input[1]);
 | 
			
		||||
            },
 | 
			
		||||
            text: 'text does not contain',
 | 
			
		||||
            appliesTo: ['string'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' does not contain ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        textStartsWith: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0].startsWith(input[1]);
 | 
			
		||||
            },
 | 
			
		||||
            text: 'text starts with',
 | 
			
		||||
            appliesTo: ['string'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' starts with ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        textEndsWith: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0].endsWith(input[1]);
 | 
			
		||||
            },
 | 
			
		||||
            text: 'text ends with',
 | 
			
		||||
            appliesTo: ['string'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' ends with ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        textIsExactly: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return input[0] === input[1];
 | 
			
		||||
            },
 | 
			
		||||
            text: 'text is exactly',
 | 
			
		||||
            appliesTo: ['string'],
 | 
			
		||||
            inputCount: 1,
 | 
			
		||||
            getDescription: function (values) {
 | 
			
		||||
                return ' is exactly ' + values[0];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        isUndefined: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return typeof input[0] === 'undefined';
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is undefined',
 | 
			
		||||
            appliesTo: ['string', 'number'],
 | 
			
		||||
            inputCount: 0,
 | 
			
		||||
            getDescription: function () {
 | 
			
		||||
                return ' is undefined';
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        isDefined: {
 | 
			
		||||
            operation: function (input) {
 | 
			
		||||
                return typeof input[0] !== 'undefined';
 | 
			
		||||
            },
 | 
			
		||||
            text: 'is defined',
 | 
			
		||||
            appliesTo: ['string', 'number'],
 | 
			
		||||
            inputCount: 0,
 | 
			
		||||
            getDescription: function () {
 | 
			
		||||
                return ' is defined';
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return OPERATIONS;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										82
									
								
								src/plugins/summaryWidget/src/views/SummaryWidgetView.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/plugins/summaryWidget/src/views/SummaryWidgetView.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
define([
 | 
			
		||||
    'text!./summary-widget.html'
 | 
			
		||||
], function (
 | 
			
		||||
    summaryWidgetTemplate
 | 
			
		||||
) {
 | 
			
		||||
    function SummaryWidgetView(domainObject, openmct) {
 | 
			
		||||
        this.openmct = openmct;
 | 
			
		||||
        this.domainObject = domainObject;
 | 
			
		||||
        this.hasUpdated = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetView.prototype.updateState = function (datum) {
 | 
			
		||||
        this.hasUpdated = true;
 | 
			
		||||
        this.widget.style.color = datum.textColor;
 | 
			
		||||
        this.widget.style.backgroundColor = datum.backgroundColor;
 | 
			
		||||
        this.widget.style.borderColor = datum.borderColor;
 | 
			
		||||
        this.widget.title = datum.message;
 | 
			
		||||
        this.label.innerHTML = datum.ruleLabel;
 | 
			
		||||
        this.label.className = 'label widget-label ' + datum.icon;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetView.prototype.render = function (domainObject) {
 | 
			
		||||
        if (this.unsubscribe) {
 | 
			
		||||
            this.unsubscribe();
 | 
			
		||||
        }
 | 
			
		||||
        this.hasUpdated = false;
 | 
			
		||||
 | 
			
		||||
        this.container.innerHTML = summaryWidgetTemplate;
 | 
			
		||||
        this.widget = this.container.querySelector('a');
 | 
			
		||||
        this.label = this.container.querySelector('.widget-label');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if (domainObject.url) {
 | 
			
		||||
            this.widget.setAttribute('href', domainObject.url);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.widget.removeAttribute('href');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (domainObject.openNewTab === 'newTab') {
 | 
			
		||||
            this.widget.setAttribute('target', '_blank');
 | 
			
		||||
        } else {
 | 
			
		||||
            this.widget.removeAttribute('target');
 | 
			
		||||
        }
 | 
			
		||||
        var renderTracker = {};
 | 
			
		||||
        this.renderTracker = renderTracker;
 | 
			
		||||
        this.openmct.telemetry.request(this.domainObject, {
 | 
			
		||||
            strategy: 'latest',
 | 
			
		||||
            size: 1
 | 
			
		||||
        }).then(function (results) {
 | 
			
		||||
            if (this.hasUpdated || this.renderTracker !== renderTracker) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            this.updateState(results[results.length - 1]);
 | 
			
		||||
        }.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.unsubscribe = this.openmct
 | 
			
		||||
            .telemetry
 | 
			
		||||
            .subscribe(domainObject, this.updateState.bind(this));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetView.prototype.show = function (container) {
 | 
			
		||||
        this.container = container;
 | 
			
		||||
        this.render(this.domainObject);
 | 
			
		||||
        this.removeMutationListener = this.openmct.objects.observe(
 | 
			
		||||
            this.domainObject,
 | 
			
		||||
            '*',
 | 
			
		||||
            this.render.bind(this)
 | 
			
		||||
        );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    SummaryWidgetView.prototype.destroy = function (container) {
 | 
			
		||||
        this.unsubscribe();
 | 
			
		||||
        this.removeMutationListener();
 | 
			
		||||
        delete this.widget;
 | 
			
		||||
        delete this.label;
 | 
			
		||||
        delete this.openmct;
 | 
			
		||||
        delete this.domainObject;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return SummaryWidgetView;
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,42 @@
 | 
			
		||||
define([
 | 
			
		||||
    '../SummaryWidget',
 | 
			
		||||
    './SummaryWidgetView',
 | 
			
		||||
    '../../../../api/objects/object-utils'
 | 
			
		||||
], function (
 | 
			
		||||
    SummaryWidgetEditView,
 | 
			
		||||
    SummaryWidgetView,
 | 
			
		||||
    objectUtils
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    function SummaryWidgetViewProvider(openmct) {
 | 
			
		||||
        return {
 | 
			
		||||
            key: 'summary-widget-viewer',
 | 
			
		||||
            name: 'Widget View',
 | 
			
		||||
            canView: function (domainObject) {
 | 
			
		||||
                return domainObject.type === 'summary-widget';
 | 
			
		||||
            },
 | 
			
		||||
            view: function (domainObject) {
 | 
			
		||||
                var statusService = openmct.$injector.get('statusService');
 | 
			
		||||
                var objectId = objectUtils.makeKeyString(domainObject.identifier);
 | 
			
		||||
                var statuses = statusService.listStatuses(objectId);
 | 
			
		||||
                var isEditing = statuses.indexOf('editing') !== -1;
 | 
			
		||||
 | 
			
		||||
                if (isEditing) {
 | 
			
		||||
                    return new SummaryWidgetEditView(domainObject, openmct);
 | 
			
		||||
                } else {
 | 
			
		||||
                    return new SummaryWidgetView(domainObject, openmct);
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            editable: true,
 | 
			
		||||
            priority: function (domainObject) {
 | 
			
		||||
                return 1;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return SummaryWidgetViewProvider;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										5
									
								
								src/plugins/summaryWidget/src/views/summary-widget.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/plugins/summaryWidget/src/views/summary-widget.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
<div class="w-summary-widget s-status-no-data">
 | 
			
		||||
    <a class="t-summary-widget l-summary-widget s-summary-widget labeled">
 | 
			
		||||
        <span class="label widget-label">Loading...</span>
 | 
			
		||||
    </a>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -19,6 +19,7 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
            removeCallbackSpy,
 | 
			
		||||
            telemetryCallbackSpy,
 | 
			
		||||
            metadataCallbackSpy,
 | 
			
		||||
            telemetryRequests,
 | 
			
		||||
            mockTelemetryValues,
 | 
			
		||||
            mockTelemetryValues2,
 | 
			
		||||
            mockConditionEvaluator;
 | 
			
		||||
@@ -61,31 +62,43 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
                mockCompObject1: {
 | 
			
		||||
                    property1: {
 | 
			
		||||
                        key: 'property1',
 | 
			
		||||
                        name: 'Property 1'
 | 
			
		||||
                        name: 'Property 1',
 | 
			
		||||
                        format: 'string',
 | 
			
		||||
                        hints: {}
 | 
			
		||||
                    },
 | 
			
		||||
                    property2: {
 | 
			
		||||
                        key: 'property2',
 | 
			
		||||
                        name: 'Property 2'
 | 
			
		||||
                        name: 'Property 2',
 | 
			
		||||
                        hints: {
 | 
			
		||||
                            domain: 1
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                mockCompObject2: {
 | 
			
		||||
                    property3: {
 | 
			
		||||
                        key: 'property3',
 | 
			
		||||
                        name: 'Property 3'
 | 
			
		||||
                        name: 'Property 3',
 | 
			
		||||
                        format: 'string',
 | 
			
		||||
                        hints: {}
 | 
			
		||||
                    },
 | 
			
		||||
                    property4: {
 | 
			
		||||
                        key: 'property4',
 | 
			
		||||
                        name: 'Property 4'
 | 
			
		||||
                        name: 'Property 4',
 | 
			
		||||
                        hints: {
 | 
			
		||||
                            range: 1
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                mockCompObject3: {
 | 
			
		||||
                    property1: {
 | 
			
		||||
                        key: 'property1',
 | 
			
		||||
                        name: 'Property 1'
 | 
			
		||||
                        name: 'Property 1',
 | 
			
		||||
                        hints: {}
 | 
			
		||||
                    },
 | 
			
		||||
                    property2: {
 | 
			
		||||
                        key: 'property2',
 | 
			
		||||
                        name: 'Property 2'
 | 
			
		||||
                        name: 'Property 2',
 | 
			
		||||
                        hints: {}
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
@@ -160,22 +173,20 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
                unregisterSpies[event]();
 | 
			
		||||
            });
 | 
			
		||||
            mockComposition.load.andCallFake(function () {
 | 
			
		||||
                mockEventCallbacks.add(mockCompObject1);
 | 
			
		||||
                mockEventCallbacks.add(mockCompObject2);
 | 
			
		||||
                mockEventCallbacks.load();
 | 
			
		||||
                mockComposition.triggerCallback('add', mockCompObject1);
 | 
			
		||||
                mockComposition.triggerCallback('add', mockCompObject2);
 | 
			
		||||
                mockComposition.triggerCallback('load');
 | 
			
		||||
            });
 | 
			
		||||
            mockComposition.triggerCallback.andCallFake(function (event) {
 | 
			
		||||
            mockComposition.triggerCallback.andCallFake(function (event, obj) {
 | 
			
		||||
                if (event === 'add') {
 | 
			
		||||
                    mockEventCallbacks.add(mockCompObject3);
 | 
			
		||||
                    mockEventCallbacks.add(obj);
 | 
			
		||||
                } else if (event === 'remove') {
 | 
			
		||||
                    mockEventCallbacks.remove({
 | 
			
		||||
                        key: 'mockCompObject2'
 | 
			
		||||
                    });
 | 
			
		||||
                    mockEventCallbacks.remove(obj.identifier);
 | 
			
		||||
                } else {
 | 
			
		||||
                    mockEventCallbacks[event]();
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            telemetryRequests = [];
 | 
			
		||||
            mockTelemetryAPI = jasmine.createSpyObj('telemetryAPI', [
 | 
			
		||||
                'request',
 | 
			
		||||
                'isTelemetryObject',
 | 
			
		||||
@@ -184,9 +195,15 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
                'triggerTelemetryCallback'
 | 
			
		||||
            ]);
 | 
			
		||||
            mockTelemetryAPI.request.andCallFake(function (obj) {
 | 
			
		||||
                return new Promise(function (resolve, reject) {
 | 
			
		||||
                    resolve(mockTelemetryValues[obj.identifer.key]);
 | 
			
		||||
                var req = {
 | 
			
		||||
                    object: obj
 | 
			
		||||
                };
 | 
			
		||||
                req.promise = new Promise(function (resolve, reject) {
 | 
			
		||||
                    req.resolve = resolve;
 | 
			
		||||
                    req.reject = reject;
 | 
			
		||||
                });
 | 
			
		||||
                telemetryRequests.push(req);
 | 
			
		||||
                return req.promise;
 | 
			
		||||
            });
 | 
			
		||||
            mockTelemetryAPI.isTelemetryObject.andReturn(true);
 | 
			
		||||
            mockTelemetryAPI.getMetadata.andCallFake(function (obj) {
 | 
			
		||||
@@ -245,41 +262,50 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
            var allKeys = {
 | 
			
		||||
                property1: {
 | 
			
		||||
                    key: 'property1',
 | 
			
		||||
                    name: 'Property 1'
 | 
			
		||||
                    name: 'Property 1',
 | 
			
		||||
                    format: 'string',
 | 
			
		||||
                    hints: {}
 | 
			
		||||
                },
 | 
			
		||||
                property2: {
 | 
			
		||||
                    key: 'property2',
 | 
			
		||||
                    name: 'Property 2'
 | 
			
		||||
                    name: 'Property 2',
 | 
			
		||||
                    hints: {
 | 
			
		||||
                        domain: 1
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                property3: {
 | 
			
		||||
                    key: 'property3',
 | 
			
		||||
                    name: 'Property 3'
 | 
			
		||||
                    name: 'Property 3',
 | 
			
		||||
                    format: 'string',
 | 
			
		||||
                    hints: {}
 | 
			
		||||
                },
 | 
			
		||||
                property4: {
 | 
			
		||||
                    key: 'property4',
 | 
			
		||||
                    name: 'Property 4'
 | 
			
		||||
                    name: 'Property 4',
 | 
			
		||||
                    hints: {
 | 
			
		||||
                        range: 1
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
            expect(conditionManager.getTelemetryMetadata('all')).toEqual(allKeys);
 | 
			
		||||
            expect(conditionManager.getTelemetryMetadata('any')).toEqual(allKeys);
 | 
			
		||||
            mockComposition.triggerCallback('add');
 | 
			
		||||
            mockComposition.triggerCallback('add', mockCompObject3);
 | 
			
		||||
            expect(conditionManager.getTelemetryMetadata('all')).toEqual(allKeys);
 | 
			
		||||
            expect(conditionManager.getTelemetryMetadata('any')).toEqual(allKeys);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('loads and gets telemetry property types', function () {
 | 
			
		||||
            conditionManager.parseAllPropertyTypes().then(function () {
 | 
			
		||||
                expect(conditionManager.getTelemetryPropertyType('mockCompObject1', 'property1'))
 | 
			
		||||
                    .toEqual('string');
 | 
			
		||||
                expect(conditionManager.getTelemetryPropertyType('mockCompObject2', 'property4'))
 | 
			
		||||
                    .toEqual('number');
 | 
			
		||||
                expect(conditionManager.metadataLoadComplete()).toEqual(true);
 | 
			
		||||
                expect(metadataCallbackSpy).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
            conditionManager.parseAllPropertyTypes();
 | 
			
		||||
            expect(conditionManager.getTelemetryPropertyType('mockCompObject1', 'property1'))
 | 
			
		||||
                .toEqual('string');
 | 
			
		||||
            expect(conditionManager.getTelemetryPropertyType('mockCompObject2', 'property4'))
 | 
			
		||||
                .toEqual('number');
 | 
			
		||||
            expect(conditionManager.metadataLoadCompleted()).toEqual(true);
 | 
			
		||||
            expect(metadataCallbackSpy).toHaveBeenCalled();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('responds to a composition add event and invokes the appropriate handlers', function () {
 | 
			
		||||
            mockComposition.triggerCallback('add');
 | 
			
		||||
            mockComposition.triggerCallback('add', mockCompObject3);
 | 
			
		||||
            expect(addCallbackSpy).toHaveBeenCalledWith(mockCompObject3);
 | 
			
		||||
            expect(conditionManager.getComposition()).toEqual({
 | 
			
		||||
                mockCompObject1: mockCompObject1,
 | 
			
		||||
@@ -289,7 +315,7 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('responds to a composition remove event and invokes the appropriate handlers', function () {
 | 
			
		||||
            mockComposition.triggerCallback('remove');
 | 
			
		||||
            mockComposition.triggerCallback('remove', mockCompObject2);
 | 
			
		||||
            expect(removeCallbackSpy).toHaveBeenCalledWith({
 | 
			
		||||
                key: 'mockCompObject2'
 | 
			
		||||
            });
 | 
			
		||||
@@ -300,7 +326,7 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('unregisters telemetry subscriptions and composition listeners on destroy', function () {
 | 
			
		||||
            mockComposition.triggerCallback('add');
 | 
			
		||||
            mockComposition.triggerCallback('add', mockCompObject3);
 | 
			
		||||
            conditionManager.destroy();
 | 
			
		||||
            Object.values(unsubscribeSpies).forEach(function (spy) {
 | 
			
		||||
                expect(spy).toHaveBeenCalled();
 | 
			
		||||
@@ -311,7 +337,19 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('populates its LAD cache with historial data on load, if available', function () {
 | 
			
		||||
            conditionManager.parseAllPropertyTypes().then(function () {
 | 
			
		||||
            expect(telemetryRequests.length).toBe(2);
 | 
			
		||||
            expect(telemetryRequests[0].object).toBe(mockCompObject1);
 | 
			
		||||
            expect(telemetryRequests[1].object).toBe(mockCompObject2);
 | 
			
		||||
 | 
			
		||||
            expect(telemetryCallbackSpy).not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
            telemetryRequests[0].resolve([mockTelemetryValues.mockCompObject1]);
 | 
			
		||||
            telemetryRequests[1].resolve([mockTelemetryValues.mockCompObject2]);
 | 
			
		||||
 | 
			
		||||
            waitsFor(function () {
 | 
			
		||||
                return telemetryCallbackSpy.calls.length === 2;
 | 
			
		||||
            });
 | 
			
		||||
            runs(function () {
 | 
			
		||||
                expect(conditionManager.subscriptionCache.mockCompObject1.property1).toEqual('Its a string');
 | 
			
		||||
                expect(conditionManager.subscriptionCache.mockCompObject2.property4).toEqual(66);
 | 
			
		||||
            });
 | 
			
		||||
@@ -352,12 +390,10 @@ define(['../src/ConditionManager'], function (ConditionManager) {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('gets the human-readable name of a telemetry field', function () {
 | 
			
		||||
            conditionManager.parseAllPropertyTypes().then(function () {
 | 
			
		||||
                expect(conditionManager.getTelemetryPropertyName('mockCompObject1', 'property1'))
 | 
			
		||||
                    .toEqual('Property 1');
 | 
			
		||||
                expect(conditionManager.getTelemetryPropertyName('mockCompObject2', 'property4'))
 | 
			
		||||
                    .toEqual('Property 4');
 | 
			
		||||
            });
 | 
			
		||||
            expect(conditionManager.getTelemetryPropertyName('mockCompObject1', 'property1'))
 | 
			
		||||
                .toEqual('Property 1');
 | 
			
		||||
            expect(conditionManager.getTelemetryPropertyName('mockCompObject2', 'property4'))
 | 
			
		||||
                .toEqual('Property 4');
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('gets its associated ConditionEvaluator', function () {
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,9 @@ requirejs.config({
 | 
			
		||||
        "d3-format": "node_modules/d3-format/build/d3-format.min",
 | 
			
		||||
        "d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
 | 
			
		||||
        "d3-time": "node_modules/d3-time/build/d3-time.min",
 | 
			
		||||
        "d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
 | 
			
		||||
        "d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min",
 | 
			
		||||
        "dom-to-image": "node_modules/dom-to-image/dist/dom-to-image.min",
 | 
			
		||||
        "painterro": "node_modules/@cristian77/painterro/build/painterro.min"
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    "shim": {
 | 
			
		||||
@@ -109,6 +111,9 @@ requirejs.config({
 | 
			
		||||
        },
 | 
			
		||||
        "d3-axis": {
 | 
			
		||||
            "exports": "d3-axis"
 | 
			
		||||
        },
 | 
			
		||||
        "dom-to-image": {
 | 
			
		||||
            "exports": "domtoimage"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user