mirror of
https://github.com/nasa/openmct.git
synced 2025-05-31 22:50:49 +00:00
Timestrip plan Inspection (#3863)
* Stub in static HTML for Timestrip Activity Inspection - Added static markup with placeholder values and display logic; - Refined approach for Links; * Refactor duration formatting * Display activity name when it's available * Don't use indices for keys * Don't show properties with no labels
This commit is contained in:
parent
2a1e322230
commit
96dd581a67
@ -1,3 +1,25 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2020, 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.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div ref="plan"
|
||||
class="c-plan c-timeline-holder"
|
||||
@ -28,7 +50,6 @@ import SwimLane from "@/ui/components/swim-lane/SwimLane.vue";
|
||||
import { getValidatedPlan } from "./util";
|
||||
import Vue from "vue";
|
||||
|
||||
//TODO: UI direction needed for the following property values
|
||||
const PADDING = 1;
|
||||
const OUTER_TEXT_PADDING = 12;
|
||||
const INNER_TEXT_PADDING = 17;
|
||||
@ -281,7 +302,9 @@ export default {
|
||||
exceeds: {
|
||||
start: this.xScale(this.viewBounds.start) > this.xScale(activity.start),
|
||||
end: this.xScale(this.viewBounds.end) < this.xScale(activity.end)
|
||||
}
|
||||
},
|
||||
start: activity.start,
|
||||
end: activity.end
|
||||
},
|
||||
textLines: textLines,
|
||||
textStart: textStart,
|
||||
@ -339,6 +362,9 @@ export default {
|
||||
components: {
|
||||
SwimLane
|
||||
},
|
||||
provide: {
|
||||
openmct: this.openmct
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
heading,
|
||||
@ -376,7 +402,6 @@ export default {
|
||||
activityRows.forEach((row) => {
|
||||
const items = activitiesByRow[row];
|
||||
items.forEach(item => {
|
||||
//TODO: Don't draw the left-border of the rectangle if the activity started before viewBounds.start
|
||||
this.plotActivity(item, parseInt(row, 10), groupSVG);
|
||||
});
|
||||
});
|
||||
@ -399,6 +424,9 @@ export default {
|
||||
element.setAttributeNS(null, key, attributes[key]);
|
||||
});
|
||||
},
|
||||
getNSAttributesForElement(element, attribute) {
|
||||
return element.getAttributeNS(null, attribute);
|
||||
},
|
||||
// Experimental for now - unused
|
||||
addForeignElement(svgElement, label, x, y) {
|
||||
let foreign = document.createElementNS('http://www.w3.org/2000/svg', "foreignObject");
|
||||
@ -443,6 +471,10 @@ export default {
|
||||
fill: activity.color
|
||||
});
|
||||
|
||||
rectElement.addEventListener('click', (event) => {
|
||||
this.setSelectionForActivity(event.currentTarget, activity, event.metaKey);
|
||||
});
|
||||
|
||||
svgElement.appendChild(rectElement);
|
||||
|
||||
item.textLines.forEach((line, index) => {
|
||||
@ -456,6 +488,9 @@ export default {
|
||||
|
||||
const textNode = document.createTextNode(line);
|
||||
textElement.appendChild(textNode);
|
||||
textElement.addEventListener('click', (event) => {
|
||||
this.setSelectionForActivity(event.currentTarget, activity, event.metaKey);
|
||||
});
|
||||
svgElement.appendChild(textElement);
|
||||
});
|
||||
// this.addForeignElement(svgElement, activity.name, item.textStart, item.textY - LINE_HEIGHT);
|
||||
@ -482,6 +517,22 @@ export default {
|
||||
const cBrightness = ((hR * 299) + (hG * 587) + (hB * 114)) / 1000;
|
||||
|
||||
return cBrightness > cThreshold ? "#000000" : "#ffffff";
|
||||
},
|
||||
setSelectionForActivity(element, activity, multiSelect) {
|
||||
this.openmct.selection.select([{
|
||||
element: element,
|
||||
context: {
|
||||
type: 'activity',
|
||||
activity: activity
|
||||
}
|
||||
}, {
|
||||
element: this.openmct.layout.$refs.browseObject.$el,
|
||||
context: {
|
||||
item: this.domainObject,
|
||||
supportsMultiSelect: true
|
||||
}
|
||||
}], multiSelect);
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
52
src/plugins/plan/inspector/ActivityProperty.vue
Normal file
52
src/plugins/plan/inspector/ActivityProperty.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2020, 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.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<li class="c-inspect-properties__row">
|
||||
<div class="c-inspect-properties__label">
|
||||
{{ label }}
|
||||
</div>
|
||||
<div class="c-inspect-properties__value">
|
||||
{{ value }}
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default() {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default() {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
206
src/plugins/plan/inspector/PlanActivitiesView.vue
Normal file
206
src/plugins/plan/inspector/PlanActivitiesView.vue
Normal file
@ -0,0 +1,206 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2021, 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.
|
||||
-->
|
||||
<template>
|
||||
<div class="c-inspector__properties c-inspect-properties">
|
||||
<plan-activity-view v-for="activity in activities"
|
||||
:key="activity.id"
|
||||
:activity="activity"
|
||||
:heading="heading"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PlanActivityView from "./PlanActivityView.vue";
|
||||
import { getPreciseDuration } from "utils/duration";
|
||||
import uuid from 'uuid';
|
||||
|
||||
const propertyLabels = {
|
||||
'start': 'Start DateTime',
|
||||
'end': 'End DateTime',
|
||||
'duration': 'Duration',
|
||||
'earliestStart': 'Earliest Start',
|
||||
'latestEnd': 'Latest End',
|
||||
'gap': 'Gap',
|
||||
'overlap': 'Overlap',
|
||||
'totalTime': 'Total Time'
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PlanActivityView
|
||||
},
|
||||
inject: ['openmct', 'selection'],
|
||||
data() {
|
||||
return {
|
||||
name: '',
|
||||
activities: [],
|
||||
heading: ''
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.setFormatters();
|
||||
this.getPlanData(this.selection);
|
||||
this.getActivities();
|
||||
this.openmct.selection.on('change', this.updateSelection);
|
||||
this.openmct.time.on('timeSystem', this.setFormatters);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.openmct.selection.off('change', this.updateSelection);
|
||||
this.openmct.time.off('timeSystem', this.setFormatters);
|
||||
},
|
||||
methods: {
|
||||
setFormatters() {
|
||||
let timeSystem = this.openmct.time.timeSystem();
|
||||
this.timeFormatter = this.openmct.telemetry.getValueFormatter({
|
||||
format: timeSystem.timeFormat
|
||||
}).formatter;
|
||||
},
|
||||
updateSelection(newSelection) {
|
||||
this.getPlanData(newSelection);
|
||||
this.getActivities();
|
||||
},
|
||||
getPlanData(selection) {
|
||||
this.selectedActivities = [];
|
||||
selection.forEach((selectionItem) => {
|
||||
if (selectionItem[0].context.type === 'activity') {
|
||||
const activity = selectionItem[0].context.activity;
|
||||
if (activity) {
|
||||
this.selectedActivities.push(activity);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getActivities() {
|
||||
if (this.selectedActivities.length <= 1) {
|
||||
this.heading = 'Time';
|
||||
this.setSingleActivityProperties();
|
||||
} else {
|
||||
this.heading = 'Convex Hull';
|
||||
this.setMultipleActivityProperties();
|
||||
}
|
||||
},
|
||||
setSingleActivityProperties() {
|
||||
this.activities.splice(0);
|
||||
this.selectedActivities.forEach((selectedActivity, index) => {
|
||||
const activity = {
|
||||
id: uuid(),
|
||||
start: {
|
||||
label: propertyLabels.start,
|
||||
value: this.formatTime(selectedActivity.start)
|
||||
},
|
||||
end: {
|
||||
label: propertyLabels.end,
|
||||
value: this.formatTime(selectedActivity.end)
|
||||
},
|
||||
duration: {
|
||||
label: propertyLabels.duration,
|
||||
value: this.formatDuration(selectedActivity.end - selectedActivity.start)
|
||||
}
|
||||
};
|
||||
this.$set(this.activities, index, activity);
|
||||
});
|
||||
},
|
||||
sortFn(a, b) {
|
||||
const numA = parseInt(a.start, 10);
|
||||
const numB = parseInt(b.start, 10);
|
||||
if (numA > numB) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (numA < numB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
setMultipleActivityProperties() {
|
||||
this.activities.splice(0);
|
||||
|
||||
let earliestStart;
|
||||
let latestEnd;
|
||||
let gap;
|
||||
let overlap;
|
||||
|
||||
//Sort by start time
|
||||
let selectedActivities = this.selectedActivities.sort(this.sortFn);
|
||||
selectedActivities.forEach((selectedActivity, index) => {
|
||||
if (selectedActivities.length === 2 && index > 0) {
|
||||
const previous = selectedActivities[index - 1];
|
||||
//they're on different rows so there must be overlap
|
||||
if (previous.end > selectedActivity.start) {
|
||||
overlap = previous.end - selectedActivity.start;
|
||||
} else if (previous.end < selectedActivity.start) {
|
||||
gap = selectedActivity.start - previous.end;
|
||||
}
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
earliestStart = Math.min(earliestStart, selectedActivity.start);
|
||||
latestEnd = Math.max(latestEnd, selectedActivity.end);
|
||||
} else {
|
||||
earliestStart = selectedActivity.start;
|
||||
latestEnd = selectedActivity.end;
|
||||
}
|
||||
});
|
||||
let totalTime = latestEnd - earliestStart;
|
||||
|
||||
const activity = {
|
||||
id: uuid(),
|
||||
'earliestStart': {
|
||||
label: propertyLabels.earliestStart,
|
||||
value: this.formatTime(earliestStart)
|
||||
},
|
||||
'latestEnd': {
|
||||
label: propertyLabels.latestEnd,
|
||||
value: this.formatTime(latestEnd)
|
||||
}
|
||||
};
|
||||
|
||||
if (gap) {
|
||||
activity.gap = {
|
||||
label: propertyLabels.gap,
|
||||
value: this.formatDuration(gap)
|
||||
};
|
||||
} else if (overlap) {
|
||||
activity.overlap = {
|
||||
label: propertyLabels.overlap,
|
||||
value: this.formatDuration(overlap)
|
||||
};
|
||||
}
|
||||
|
||||
activity.totalTime = {
|
||||
label: propertyLabels.totalTime,
|
||||
value: this.formatDuration(totalTime)
|
||||
};
|
||||
|
||||
this.$set(this.activities, 0, activity);
|
||||
},
|
||||
formatDuration(duration) {
|
||||
return getPreciseDuration(duration);
|
||||
},
|
||||
formatTime(time) {
|
||||
return this.timeFormatter.format(time);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
84
src/plugins/plan/inspector/PlanActivityView.vue
Normal file
84
src/plugins/plan/inspector/PlanActivityView.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<!--
|
||||
Open MCT, Copyright (c) 2014-2020, 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.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div v-if="timeProperties.length"
|
||||
class="u-contents"
|
||||
>
|
||||
<div class="c-inspect-properties__header">
|
||||
{{ heading }}
|
||||
</div>
|
||||
<ul v-for="timeProperty in timeProperties"
|
||||
:key="timeProperty.id"
|
||||
class="c-inspect-properties__section"
|
||||
>
|
||||
<activity-property :label="timeProperty.label"
|
||||
:value="timeProperty.value"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ActivityProperty from './ActivityProperty.vue';
|
||||
import uuid from 'uuid';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ActivityProperty
|
||||
},
|
||||
props: {
|
||||
activity: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
heading: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
timeProperties: []
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.setProperties();
|
||||
},
|
||||
methods: {
|
||||
setProperties() {
|
||||
Object.keys(this.activity).forEach((key) => {
|
||||
if (this.activity[key].label) {
|
||||
const label = this.activity[key].label;
|
||||
const value = String(this.activity[key].value);
|
||||
|
||||
this.$set(this.timeProperties, this.timeProperties.length, {
|
||||
id: uuid(),
|
||||
label,
|
||||
value
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
69
src/plugins/plan/inspector/PlanInspectorViewProvider.js
Normal file
69
src/plugins/plan/inspector/PlanInspectorViewProvider.js
Normal file
@ -0,0 +1,69 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
import PlanActivitiesView from "./PlanActivitiesView.vue";
|
||||
import Vue from 'vue';
|
||||
|
||||
export default function PlanInspectorViewProvider(openmct) {
|
||||
return {
|
||||
key: 'plan-inspector',
|
||||
name: 'Plan Inspector View',
|
||||
canView: function (selection) {
|
||||
if (selection.length === 0 || selection[0].length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let context = selection[0][0].context;
|
||||
|
||||
return context
|
||||
&& context.type === 'activity';
|
||||
},
|
||||
view: function (selection) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: function (element) {
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
PlanActivitiesView: PlanActivitiesView
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
selection: selection
|
||||
},
|
||||
template: '<plan-activities-view></plan-activities-view>'
|
||||
});
|
||||
},
|
||||
destroy: function () {
|
||||
if (component) {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
priority: function () {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
@ -1,3 +1,25 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
.c-plan {
|
||||
svg {
|
||||
text-rendering: geometricPrecision;
|
||||
|
@ -21,6 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import PlanViewProvider from './PlanViewProvider';
|
||||
import PlanInspectorViewProvider from "./inspector/PlanInspectorViewProvider";
|
||||
|
||||
export default function () {
|
||||
return function install(openmct) {
|
||||
@ -44,6 +45,7 @@ export default function () {
|
||||
}
|
||||
});
|
||||
openmct.objectViews.addProvider(new PlanViewProvider(openmct));
|
||||
openmct.inspectorViews.addProvider(new PlanInspectorViewProvider(openmct));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,25 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
export function getValidatedPlan(domainObject) {
|
||||
let body = domainObject.selectFile.body;
|
||||
let json = {};
|
||||
|
@ -39,9 +39,8 @@ const DEFAULT_DURATION_FORMATTER = 'duration';
|
||||
const LOCAL_STORAGE_HISTORY_KEY_FIXED = 'tcHistory';
|
||||
const LOCAL_STORAGE_HISTORY_KEY_REALTIME = 'tcHistoryRealtime';
|
||||
const DEFAULT_RECORDS = 10;
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
const ONE_HOUR = ONE_MINUTE * 60;
|
||||
const ONE_DAY = ONE_HOUR * 24;
|
||||
|
||||
import { getDuration } from "utils/duration";
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'configuration'],
|
||||
@ -143,7 +142,7 @@ export default {
|
||||
let description = `${startTime} - ${this.formatTime(timespan.end)}`;
|
||||
|
||||
if (this.timeSystem.isUTCBased && !this.openmct.time.clock()) {
|
||||
name = `${startTime} ${this.getDuration(timespan.end - timespan.start)}`;
|
||||
name = `${startTime} ${getDuration(timespan.end - timespan.start)}`;
|
||||
} else {
|
||||
name = description;
|
||||
}
|
||||
@ -176,41 +175,6 @@ export default {
|
||||
};
|
||||
});
|
||||
},
|
||||
getDuration(numericDuration) {
|
||||
let result;
|
||||
let age;
|
||||
|
||||
if (numericDuration > ONE_DAY - 1) {
|
||||
age = this.normalizeAge((numericDuration / ONE_DAY).toFixed(2));
|
||||
result = `+ ${age} day`;
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
} else if (numericDuration > ONE_HOUR - 1) {
|
||||
age = this.normalizeAge((numericDuration / ONE_HOUR).toFixed(2));
|
||||
result = `+ ${age} hour`;
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
} else {
|
||||
age = this.normalizeAge((numericDuration / ONE_MINUTE).toFixed(2));
|
||||
result = `+ ${age} min`;
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
normalizeAge(num) {
|
||||
const hundredtized = num * 100;
|
||||
const isWhole = hundredtized % 100 === 0;
|
||||
|
||||
return isWhole ? hundredtized / 100 : num;
|
||||
},
|
||||
getHistoryFromLocalStorage() {
|
||||
const localStorageHistory = localStorage.getItem(this.storageKey);
|
||||
const history = localStorageHistory ? JSON.parse(localStorageHistory) : undefined;
|
||||
|
@ -20,7 +20,12 @@
|
||||
<span class="c-object-label__type-icon"
|
||||
:class="typeCssClass"
|
||||
></span>
|
||||
<span class="c-object-label__name">Layout Object</span>
|
||||
<span v-if="!activity"
|
||||
class="c-object-label__name"
|
||||
>Layout Object</span>
|
||||
<span v-else
|
||||
class="c-object-label__name"
|
||||
>{{ activity.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="multiSelect"
|
||||
@ -37,6 +42,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
domainObject: {},
|
||||
activity: undefined,
|
||||
keyString: undefined,
|
||||
multiSelect: false,
|
||||
itemsSelected: 0,
|
||||
@ -51,6 +57,10 @@ export default {
|
||||
return this.openmct.types.get(this.item.type);
|
||||
},
|
||||
typeCssClass() {
|
||||
if (this.activity) {
|
||||
return 'icon-activity';
|
||||
}
|
||||
|
||||
if (this.type.definition.cssClass === undefined) {
|
||||
return 'icon-object';
|
||||
}
|
||||
@ -97,7 +107,7 @@ export default {
|
||||
} else {
|
||||
this.multiSelect = false;
|
||||
this.domainObject = selection[0][0].context.item;
|
||||
|
||||
this.activity = selection[0][0].context.activity;
|
||||
if (this.domainObject) {
|
||||
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||
this.status = this.openmct.status.get(this.keyString);
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<div class="c-inspector__properties c-inspect-properties">
|
||||
<div v-if="!activity"
|
||||
class="c-inspector__properties c-inspect-properties"
|
||||
>
|
||||
<div class="c-inspect-properties__header">
|
||||
Details
|
||||
</div>
|
||||
@ -81,6 +83,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
domainObject: {},
|
||||
activity: undefined,
|
||||
multiSelect: false
|
||||
};
|
||||
},
|
||||
@ -157,6 +160,7 @@ export default {
|
||||
} else {
|
||||
this.multiSelect = false;
|
||||
this.domainObject = selection[0][0].context.item;
|
||||
this.activity = selection[0][0].context.activity;
|
||||
}
|
||||
},
|
||||
formatTime(unixTime) {
|
||||
|
85
src/utils/duration.js
Normal file
85
src/utils/duration.js
Normal file
@ -0,0 +1,85 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2021, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
const ONE_HOUR = ONE_MINUTE * 60;
|
||||
const ONE_DAY = ONE_HOUR * 24;
|
||||
|
||||
function normalizeAge(num) {
|
||||
const hundredtized = num * 100;
|
||||
const isWhole = hundredtized % 100 === 0;
|
||||
|
||||
return isWhole ? hundredtized / 100 : num;
|
||||
}
|
||||
|
||||
function toDoubleDigits(num) {
|
||||
if (num >= 10) {
|
||||
return num;
|
||||
} else {
|
||||
return `0${num}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function getDuration(numericDuration) {
|
||||
let result;
|
||||
let age;
|
||||
|
||||
if (numericDuration > ONE_DAY - 1) {
|
||||
age = normalizeAge((numericDuration / ONE_DAY)).toFixed(2);
|
||||
result = `+ ${age} day`;
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
} else if (numericDuration > ONE_HOUR - 1) {
|
||||
age = normalizeAge((numericDuration / ONE_HOUR).toFixed(2));
|
||||
result = `+ ${age} hour`;
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
} else {
|
||||
age = normalizeAge((numericDuration / ONE_MINUTE).toFixed(2));
|
||||
result = `+ ${age} min`;
|
||||
|
||||
if (age !== 1) {
|
||||
result += 's';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getPreciseDuration(numericDuration) {
|
||||
let result;
|
||||
|
||||
const days = toDoubleDigits(Math.floor((numericDuration) / (24 * 60 * 60 * 1000)));
|
||||
let remaining = (numericDuration) % (24 * 60 * 60 * 1000);
|
||||
const hours = toDoubleDigits(Math.floor((remaining) / (60 * 60 * 1000)));
|
||||
remaining = (remaining) % (60 * 60 * 1000);
|
||||
const minutes = toDoubleDigits(Math.floor((remaining) / (60 * 1000)));
|
||||
remaining = (remaining) % (60 * 1000);
|
||||
const seconds = toDoubleDigits(Math.floor((remaining) / (1000)));
|
||||
result = `${days}:${hours}:${minutes}:${seconds}`;
|
||||
|
||||
return result;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user