Compare commits
5 Commits
fix-resize
...
apres-time
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe00a098f5 | ||
|
|
2ea60ee638 | ||
|
|
30997e677d | ||
|
|
8f3492963a | ||
|
|
9e68843651 |
@@ -193,6 +193,7 @@
|
||||
['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
|
||||
{indicator: true}
|
||||
));
|
||||
openmct.install(openmct.plugins.ApresTimeline());
|
||||
openmct.start();
|
||||
</script>
|
||||
</html>
|
||||
|
||||
0
src/plugins/apresTimeline/activityViewProvider.js
Normal file
0
src/plugins/apresTimeline/activityViewProvider.js
Normal file
0
src/plugins/apresTimeline/components/activity.vue
Normal file
0
src/plugins/apresTimeline/components/activity.vue
Normal file
64
src/plugins/apresTimeline/components/timeline.vue
Normal file
64
src/plugins/apresTimeline/components/timeline.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div style="min-width: 100%">
|
||||
<ul style="min-width: 100%; min-height: 100%; position: relative;">
|
||||
<timeline-activity
|
||||
v-for="(activityDomainObject, index) in activities"
|
||||
:key="activityDomainObject.identifier.key"
|
||||
:domainObject="activityDomainObject"
|
||||
:index="index"
|
||||
:isEditing="isEditing"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TimelineActivity from './timelineActivity.vue';
|
||||
|
||||
export default {
|
||||
inject: ['openmct', 'objectPath', 'domainObject'],
|
||||
props: {
|
||||
isEditing: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
components: {
|
||||
TimelineActivity
|
||||
},
|
||||
methods: {
|
||||
addActivity(activityDomainObject) {
|
||||
this.activities.push(activityDomainObject);
|
||||
},
|
||||
removeActivity(activityIndentifier) {
|
||||
console.log(activityIndentifier);
|
||||
},
|
||||
reorderActivities(reorderPlan) {
|
||||
let oldActivities = this.activities.slice();
|
||||
|
||||
reorderPlan.forEach((reorderEvent) => {
|
||||
this.$set(this.activities, reorderEvent.newIndex, oldActivities[reorderEvent.oldIndex]);
|
||||
});
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activities: [],
|
||||
composition: this.openmct.composition.get(this.domainObject),
|
||||
activityHeight: 0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.composition.on('add', this.addActivity);
|
||||
this.composition.on('remove', this.removeActivity);
|
||||
this.composition.on('reorder', this.reorderActivities);
|
||||
this.composition.load();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.composition.off('add', this.addActivity);
|
||||
this.composition.off('remove', this.removeActivity);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
110
src/plugins/apresTimeline/components/timelineActivity.vue
Normal file
110
src/plugins/apresTimeline/components/timelineActivity.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<li
|
||||
:style="activityStyle"
|
||||
@mousedown="onMouseDown"
|
||||
>
|
||||
{{ name }}
|
||||
</li>
|
||||
</template>
|
||||
<script>
|
||||
const PIXEL_MULTIPLIER = 30;
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
props: {
|
||||
domainObject: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default() {
|
||||
return {
|
||||
configuration: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
index: {
|
||||
type: Number
|
||||
},
|
||||
isEditing: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
activityStyle() {
|
||||
return {
|
||||
'position': 'absolute',
|
||||
'top': `${this.index * (this.activityHeight + 4)}px`,
|
||||
'left': `${this.start * PIXEL_MULTIPLIER}px`,
|
||||
'backgroundColor': this.color,
|
||||
'width': `${this.width * PIXEL_MULTIPLIER}px`,
|
||||
'padding': '10px'
|
||||
};
|
||||
}
|
||||
},
|
||||
data() {
|
||||
let configuration = this.domainObject.configuration;
|
||||
|
||||
return {
|
||||
name: this.domainObject.name,
|
||||
start: configuration.startTime,
|
||||
end: configuration.endTime,
|
||||
width: configuration.endTime - configuration.startTime,
|
||||
color: configuration.color,
|
||||
activityHeight: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onDomainObjectChange(domainObject) {
|
||||
let configuration = domainObject.configuration;
|
||||
|
||||
this.name = domainObject.name;
|
||||
this.start = configuration.startTime;
|
||||
this.end = configuration.endTime;
|
||||
this.width = this.end - this.start;
|
||||
this.color = configuration.color;
|
||||
},
|
||||
onMouseDown(event) {
|
||||
if (!this.isEditing) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
document.addEventListener('mousemove', this.move);
|
||||
document.addEventListener('mouseup', this.endMove);
|
||||
|
||||
this.clientX = event.clientX;
|
||||
},
|
||||
move(event) {
|
||||
let delta = (event.clientX - this.clientX) / PIXEL_MULTIPLIER;
|
||||
|
||||
this.start += delta;
|
||||
this.end = this.start + this.width;
|
||||
|
||||
this.clientX = event.clientX;
|
||||
},
|
||||
endMove() {
|
||||
document.removeEventListener('mousemove', this.move);
|
||||
document.removeEventListener('mouseup', this.endMove);
|
||||
|
||||
this.persistMove();
|
||||
},
|
||||
persistMove() {
|
||||
let configuration = {
|
||||
startTime: this.start,
|
||||
endTime: this.end,
|
||||
color: this.color
|
||||
};
|
||||
|
||||
this.openmct.objects.mutate(this.domainObject, 'configuration', configuration);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.unsubscribeFromDomainObjectChanges = this.openmct.objects.observe(this.domainObject, '*', this.onDomainObjectChange);
|
||||
|
||||
let boundingClientRect = this.$el.getBoundingClientRect();
|
||||
|
||||
this.activityHeight = boundingClientRect.height;
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.unsubscribeFromDomainObjectChanges();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
72
src/plugins/apresTimeline/plugin.js
Normal file
72
src/plugins/apresTimeline/plugin.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import ActivityViewProvider from './activityViewProvider';
|
||||
import TimelineViewProvider from './timelineViewProvider';
|
||||
|
||||
export default function () {
|
||||
return function install(openmct) {
|
||||
openmct.types.addType(
|
||||
'apres.timeline.type',
|
||||
{
|
||||
name: 'Apres Timeline',
|
||||
cssClass: 'icon-timeline',
|
||||
creatable: true,
|
||||
initialize: function (domainObject) {
|
||||
domainObject.composition = [];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
openmct.types.addType(
|
||||
'apres.activity.type',
|
||||
{
|
||||
name: 'Apres Timeline Activity',
|
||||
cssClass: 'icon-activity',
|
||||
creatable: true,
|
||||
initialize: function (domainObject) {
|
||||
domainObject.configuration = {
|
||||
startTime: 0,
|
||||
endTime: 10,
|
||||
color: 'rebeccapurple'
|
||||
};
|
||||
},
|
||||
form: [
|
||||
{
|
||||
name: "Start Time",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "startTime",
|
||||
required: true,
|
||||
property: [
|
||||
"configuration",
|
||||
"startTime"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "End Time",
|
||||
control: "numberfield",
|
||||
cssClass: "l-input-sm l-numeric",
|
||||
key: "endTime",
|
||||
required: true,
|
||||
property: [
|
||||
"configuration",
|
||||
"endTime"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Color",
|
||||
control: "textfield",
|
||||
cssClass: "l-input-sm l-text",
|
||||
key: "color",
|
||||
required: true,
|
||||
property: [
|
||||
"configuration",
|
||||
"color"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
openmct.objectViews.addProvider(new TimelineViewProvider(openmct));
|
||||
// openmct.objectViews.addProvider(new ActivityViewProvider(openmct));
|
||||
}
|
||||
};
|
||||
55
src/plugins/apresTimeline/timelineViewProvider.js
Normal file
55
src/plugins/apresTimeline/timelineViewProvider.js
Normal file
@@ -0,0 +1,55 @@
|
||||
import Vue from 'vue';
|
||||
import timelineComponent from './components/timeline.vue';
|
||||
|
||||
export default class TimelineViewProvider{
|
||||
constructor(openmct) {
|
||||
this._openmct = openmct;
|
||||
|
||||
this.name = 'Timeline';
|
||||
this.key = 'apres.timeline.view';
|
||||
this.priority = 1;
|
||||
}
|
||||
|
||||
canView(domainObject) {
|
||||
return domainObject.type === 'apres.timeline.type';
|
||||
}
|
||||
|
||||
canEdit(domainObject) {
|
||||
return domainObject.type === 'apres.timeline.type';
|
||||
}
|
||||
|
||||
view(domainObject, objectPath, isEditing) {
|
||||
let component;
|
||||
|
||||
return {
|
||||
show: (element) => {
|
||||
component = new Vue({
|
||||
el: element,
|
||||
components: {
|
||||
timelineComponent: timelineComponent
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isEditing: isEditing
|
||||
}
|
||||
},
|
||||
provide: {
|
||||
openmct,
|
||||
domainObject,
|
||||
objectPath
|
||||
},
|
||||
template: ` <timeline-component
|
||||
:isEditing="isEditing"
|
||||
>
|
||||
</timeline-component>`
|
||||
});
|
||||
},
|
||||
onEditModeChange: (isEditing) => {
|
||||
component.isEditing = isEditing;
|
||||
},
|
||||
destroy: () => {
|
||||
component.$destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -61,7 +61,8 @@ define([
|
||||
'./timeline/plugin',
|
||||
'./viewDatumAction/plugin',
|
||||
'./interceptors/plugin',
|
||||
'./performanceIndicator/plugin'
|
||||
'./performanceIndicator/plugin',
|
||||
'./apresTimeline/plugin'
|
||||
], function (
|
||||
_,
|
||||
UTCTimeSystem,
|
||||
@@ -103,7 +104,8 @@ define([
|
||||
Timeline,
|
||||
ViewDatumAction,
|
||||
ObjectInterceptors,
|
||||
PerformanceIndicator
|
||||
PerformanceIndicator,
|
||||
ApresTimeline
|
||||
) {
|
||||
const bundleMap = {
|
||||
LocalStorage: 'platform/persistence/local',
|
||||
@@ -200,6 +202,7 @@ define([
|
||||
plugins.ViewDatumAction = ViewDatumAction.default;
|
||||
plugins.ObjectInterceptors = ObjectInterceptors.default;
|
||||
plugins.PerformanceIndicator = PerformanceIndicator.default;
|
||||
plugins.ApresTimeline = ApresTimeline.default;
|
||||
|
||||
return plugins;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user