mirror of
https://github.com/nasa/openmct.git
synced 2025-02-20 17:33:23 +00:00
[Display Layout] support ordering items (#2266)
* Add a toolbar menu for changing the display order of items. * - Wire up orderItem - Modify the toolbar API to support function as alternative for property path.
This commit is contained in:
parent
8ef53d85c4
commit
9e811e722f
@ -73,10 +73,13 @@ define([], function () {
|
||||
return openmct.$injector.get('dialogService').getUserInput(form, {});
|
||||
}
|
||||
|
||||
function getPath() {
|
||||
return `configuration.items[${selection[0].context.index}]`;
|
||||
}
|
||||
|
||||
let selectedParent = selection[1] && selection[1].context.item,
|
||||
selectedObject = selection[0].context.item,
|
||||
layoutItem = selection[0].context.layoutItem,
|
||||
layoutItemIndex = selection[0].context.index,
|
||||
toolbar = [];
|
||||
|
||||
if (selectedObject && selectedObject.type === 'layout') {
|
||||
@ -121,7 +124,6 @@ define([], function () {
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
let path = `configuration.items[${layoutItemIndex}]`;
|
||||
let separator = {
|
||||
control: "separator"
|
||||
};
|
||||
@ -140,7 +142,7 @@ define([], function () {
|
||||
label: 'Ok',
|
||||
emphasis: 'true',
|
||||
callback: function () {
|
||||
removeItem(layoutItem, layoutItemIndex);
|
||||
removeItem(layoutItem, selection[0].context.index);
|
||||
prompt.dismiss();
|
||||
}
|
||||
},
|
||||
@ -154,10 +156,43 @@ define([], function () {
|
||||
});
|
||||
}
|
||||
};
|
||||
let stackOrder = {
|
||||
control: "menu",
|
||||
domainObject: selectedParent,
|
||||
icon: "icon-layers",
|
||||
title: "Move the selected object above or below other objects",
|
||||
options: [
|
||||
{
|
||||
name: "Move to Top",
|
||||
value: "top",
|
||||
class: "icon-arrow-double-up"
|
||||
},
|
||||
{
|
||||
name: "Move Up",
|
||||
value: "up",
|
||||
class: "icon-arrow-up"
|
||||
},
|
||||
{
|
||||
name: "Move Down",
|
||||
value: "down",
|
||||
class: "icon-arrow-down"
|
||||
},
|
||||
{
|
||||
name: "Move to Bottom",
|
||||
value: "bottom",
|
||||
class: "icon-arrow-double-down"
|
||||
}
|
||||
],
|
||||
method: function (option) {
|
||||
selection[1].context.orderItem(option.value, selection[0].context.index);
|
||||
}
|
||||
};
|
||||
let useGrid = {
|
||||
control: "toggle-button",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".useGrid",
|
||||
property: function () {
|
||||
return getPath() + ".useGrid";
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
@ -177,10 +212,14 @@ define([], function () {
|
||||
toolbar.push(separator);
|
||||
}
|
||||
|
||||
toolbar.push(stackOrder);
|
||||
toolbar.push(separator);
|
||||
toolbar.push({
|
||||
control: "toggle-button",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".hasFrame",
|
||||
property: function () {
|
||||
return getPath() + ".hasFrame";
|
||||
},
|
||||
options: [
|
||||
{
|
||||
value: false,
|
||||
@ -194,6 +233,7 @@ define([], function () {
|
||||
}
|
||||
]
|
||||
});
|
||||
toolbar.push(separator);
|
||||
toolbar.push(useGrid);
|
||||
toolbar.push(separator);
|
||||
toolbar.push(remove);
|
||||
@ -202,21 +242,27 @@ define([], function () {
|
||||
let fill = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".fill",
|
||||
property: function () {
|
||||
return getPath() + ".fill";
|
||||
},
|
||||
icon: "icon-paint-bucket",
|
||||
title: "Set fill color"
|
||||
},
|
||||
stroke = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".stroke",
|
||||
property: function () {
|
||||
return getPath() + ".stroke";
|
||||
},
|
||||
icon: "icon-line-horz",
|
||||
title: "Set border color"
|
||||
},
|
||||
color = {
|
||||
control: "color-picker",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".color",
|
||||
property: function () {
|
||||
return getPath() + ".color";
|
||||
},
|
||||
icon: "icon-font",
|
||||
mandatory: true,
|
||||
title: "Set text color",
|
||||
@ -225,7 +271,9 @@ define([], function () {
|
||||
size = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".size",
|
||||
property: function () {
|
||||
return getPath() + ".size";
|
||||
},
|
||||
title: "Set text size",
|
||||
options: TEXT_SIZE.map(size => {
|
||||
return {
|
||||
@ -237,7 +285,9 @@ define([], function () {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".x",
|
||||
property: function () {
|
||||
return getPath() + ".x";
|
||||
},
|
||||
label: "X:",
|
||||
title: "X position"
|
||||
},
|
||||
@ -245,7 +295,9 @@ define([], function () {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".y",
|
||||
property: function () {
|
||||
return getPath() + ".y";
|
||||
},
|
||||
label: "Y:",
|
||||
title: "Y position",
|
||||
},
|
||||
@ -253,7 +305,9 @@ define([], function () {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: path + ".width",
|
||||
property: function () {
|
||||
return getPath() + ".width";
|
||||
},
|
||||
label: 'W:',
|
||||
title: 'Resize object width'
|
||||
},
|
||||
@ -261,7 +315,9 @@ define([], function () {
|
||||
control: 'input',
|
||||
type: 'number',
|
||||
domainObject: selectedParent,
|
||||
property: path + ".height",
|
||||
property: function () {
|
||||
return getPath() + ".height";
|
||||
},
|
||||
label: 'H:',
|
||||
title: 'Resize object height'
|
||||
};
|
||||
@ -270,7 +326,9 @@ define([], function () {
|
||||
let displayMode = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".displayMode",
|
||||
property: function () {
|
||||
return getPath() + ".displayMode";
|
||||
},
|
||||
title: "Set display mode",
|
||||
options: [
|
||||
{
|
||||
@ -290,7 +348,9 @@ define([], function () {
|
||||
value = {
|
||||
control: "select-menu",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".value",
|
||||
property: function () {
|
||||
return getPath() + ".value";
|
||||
},
|
||||
title: "Set value",
|
||||
options: openmct.telemetry.getMetadata(selectedObject).values().map(value => {
|
||||
return {
|
||||
@ -304,6 +364,7 @@ define([], function () {
|
||||
separator,
|
||||
value,
|
||||
separator,
|
||||
stackOrder,
|
||||
fill,
|
||||
stroke,
|
||||
color,
|
||||
@ -314,7 +375,6 @@ define([], function () {
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
separator,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
@ -323,30 +383,34 @@ define([], function () {
|
||||
let text = {
|
||||
control: "button",
|
||||
domainObject: selectedParent,
|
||||
property: path,
|
||||
property: function () {
|
||||
return getPath();
|
||||
},
|
||||
icon: "icon-gear",
|
||||
title: "Edit text properties",
|
||||
dialog: DIALOG_FORM['text']
|
||||
};
|
||||
toolbar = [
|
||||
stackOrder,
|
||||
fill,
|
||||
stroke,
|
||||
color,
|
||||
separator,
|
||||
color,
|
||||
size,
|
||||
separator,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
text,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
];
|
||||
} else if (layoutItem.type === 'box-view') {
|
||||
toolbar = [
|
||||
stackOrder,
|
||||
fill,
|
||||
stroke,
|
||||
separator,
|
||||
@ -354,7 +418,6 @@ define([], function () {
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
separator,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
@ -363,21 +426,24 @@ define([], function () {
|
||||
let url = {
|
||||
control: "button",
|
||||
domainObject: selectedParent,
|
||||
property: path,
|
||||
property: function () {
|
||||
return getPath();
|
||||
},
|
||||
icon: "icon-image",
|
||||
title: "Edit image properties",
|
||||
dialog: DIALOG_FORM['image']
|
||||
};
|
||||
toolbar = [
|
||||
stackOrder,
|
||||
stroke,
|
||||
separator,
|
||||
x,
|
||||
y,
|
||||
height,
|
||||
width,
|
||||
useGrid,
|
||||
separator,
|
||||
url,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
];
|
||||
@ -386,7 +452,9 @@ define([], function () {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".x2",
|
||||
property: function () {
|
||||
return getPath() + ".x2";
|
||||
},
|
||||
label: "X2:",
|
||||
title: "X2 position"
|
||||
},
|
||||
@ -394,18 +462,20 @@ define([], function () {
|
||||
control: "input",
|
||||
type: "number",
|
||||
domainObject: selectedParent,
|
||||
property: path + ".y2",
|
||||
property: function () {
|
||||
return getPath() + ".y2";
|
||||
},
|
||||
label: "Y2:",
|
||||
title: "Y2 position",
|
||||
};
|
||||
toolbar = [
|
||||
stackOrder,
|
||||
stroke,
|
||||
separator,
|
||||
x,
|
||||
y,
|
||||
x2,
|
||||
y2,
|
||||
separator,
|
||||
useGrid,
|
||||
separator,
|
||||
remove
|
||||
|
@ -117,6 +117,12 @@
|
||||
'text-view': TextView,
|
||||
'image-view': ImageView
|
||||
};
|
||||
const ORDERS = {
|
||||
top: Number.POSITIVE_INFINITY,
|
||||
up: 1,
|
||||
down: -1,
|
||||
bottom: Number.NEGATIVE_INFINITY
|
||||
};
|
||||
|
||||
function getItemDefinition(itemType, ...options) {
|
||||
let itemView = ITEM_TYPE_VIEW_MAP[itemType];
|
||||
@ -163,42 +169,45 @@
|
||||
let itemIndex = selection[0].context.index;
|
||||
|
||||
if (itemIndex !== undefined) {
|
||||
let path = `configuration.items[${itemIndex}]`;
|
||||
this.removeSelectionListener = this.openmct.objects.observe(this.internalDomainObject, path + ".useGrid", function (value) {
|
||||
let item = this.layoutItems[itemIndex];
|
||||
|
||||
if (value) {
|
||||
item.x = Math.round(item.x / this.gridSize[0]);
|
||||
item.y = Math.round(item.y / this.gridSize[1]);
|
||||
item.width = Math.round(item.width / this.gridSize[0]);
|
||||
item.height = Math.round(item.height / this.gridSize[1]);
|
||||
|
||||
if (item.x2) {
|
||||
item.x2 = Math.round(item.x2 / this.gridSize[0]);
|
||||
}
|
||||
if (item.y2) {
|
||||
item.y2 = Math.round(item.y2 / this.gridSize[1]);
|
||||
}
|
||||
} else {
|
||||
item.x = this.gridSize[0] * item.x;
|
||||
item.y = this.gridSize[1] * item.y;
|
||||
item.width = this.gridSize[0] * item.width;
|
||||
item.height = this.gridSize[1] * item.height;
|
||||
|
||||
if (item.x2) {
|
||||
item.x2 = this.gridSize[0] * item.x2;
|
||||
}
|
||||
if (item.y2) {
|
||||
item.y2 = this.gridSize[1] * item.y2;
|
||||
}
|
||||
}
|
||||
item.useGrid = value;
|
||||
this.mutate(`configuration.items[${itemIndex}]`, item);
|
||||
}.bind(this));
|
||||
this.attachSelectionListener(itemIndex);
|
||||
}
|
||||
|
||||
this.updateDrilledIn();
|
||||
},
|
||||
attachSelectionListener(index) {
|
||||
let path = `configuration.items[${index}].useGrid`;
|
||||
this.removeSelectionListener = this.openmct.objects.observe(this.internalDomainObject, path, function (value) {
|
||||
let item = this.layoutItems[index];
|
||||
|
||||
if (value) {
|
||||
item.x = Math.round(item.x / this.gridSize[0]);
|
||||
item.y = Math.round(item.y / this.gridSize[1]);
|
||||
item.width = Math.round(item.width / this.gridSize[0]);
|
||||
item.height = Math.round(item.height / this.gridSize[1]);
|
||||
|
||||
if (item.x2) {
|
||||
item.x2 = Math.round(item.x2 / this.gridSize[0]);
|
||||
}
|
||||
if (item.y2) {
|
||||
item.y2 = Math.round(item.y2 / this.gridSize[1]);
|
||||
}
|
||||
} else {
|
||||
item.x = this.gridSize[0] * item.x;
|
||||
item.y = this.gridSize[1] * item.y;
|
||||
item.width = this.gridSize[0] * item.width;
|
||||
item.height = this.gridSize[1] * item.height;
|
||||
|
||||
if (item.x2) {
|
||||
item.x2 = this.gridSize[0] * item.x2;
|
||||
}
|
||||
if (item.y2) {
|
||||
item.y2 = this.gridSize[1] * item.y2;
|
||||
}
|
||||
}
|
||||
item.useGrid = value;
|
||||
this.mutate(`configuration.items[${index}]`, item);
|
||||
}.bind(this));
|
||||
},
|
||||
updateDrilledIn(drilledInItem) {
|
||||
let identifier = drilledInItem && this.openmct.objects.makeKeyString(drilledInItem.identifier);
|
||||
this.drilledIn = identifier;
|
||||
@ -369,6 +378,22 @@
|
||||
});
|
||||
this.mutate("configuration.items", layoutItems);
|
||||
this.$el.click();
|
||||
},
|
||||
orderItem(position, index) {
|
||||
let delta = ORDERS[position];
|
||||
let newIndex = Math.max(Math.min(index + delta, this.layoutItems.length - 1), 0);
|
||||
let item = this.layoutItems[index];
|
||||
|
||||
if (newIndex !== index) {
|
||||
this.layoutItems.splice(index, 1);
|
||||
this.layoutItems.splice(newIndex, 0, item);
|
||||
this.mutate('configuration.items', this.layoutItems);
|
||||
|
||||
if (this.removeSelectionListener) {
|
||||
this.removeSelectionListener();
|
||||
this.attachSelectionListener(newIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -61,7 +61,8 @@ export default function () {
|
||||
return {
|
||||
item: domainObject,
|
||||
addElement: component && component.$refs.displayLayout.addElement,
|
||||
removeItem: component && component.$refs.displayLayout.removeItem
|
||||
removeItem: component && component.$refs.displayLayout.removeItem,
|
||||
orderItem: component && component.$refs.displayLayout.orderItem
|
||||
}
|
||||
},
|
||||
destroy() {
|
||||
|
@ -67,7 +67,7 @@
|
||||
if (formKeys.length > 0) {
|
||||
toolbarItem.value = this.getFormValue(domainObject, toolbarItem);
|
||||
} else {
|
||||
toolbarItem.value = _.get(domainObject, item.property);
|
||||
toolbarItem.value = _.get(domainObject, this.getItemProperty(item));
|
||||
}
|
||||
|
||||
this.registerListener(domainObject);
|
||||
@ -116,7 +116,7 @@
|
||||
if (toolbarItem.formKeys) {
|
||||
toolbarItem.value = this.getFormValue(newObject, toolbarItem);
|
||||
} else {
|
||||
toolbarItem.value = _.get(newObject, item.property);
|
||||
toolbarItem.value = _.get(newObject, this.getItemProperty(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -135,10 +135,13 @@
|
||||
getFormValue(domainObject, toolbarItem) {
|
||||
let value = {};
|
||||
toolbarItem.formKeys.map(key => {
|
||||
value[key] = _.get(domainObject, toolbarItem.property + "." + key);
|
||||
value[key] = _.get(domainObject, this.getItemProperty(toolbarItem) + "." + key);
|
||||
});
|
||||
return value;
|
||||
},
|
||||
getItemProperty(item) {
|
||||
return (typeof item.property === "function") ? item.property() : item.property;
|
||||
},
|
||||
removeListeners() {
|
||||
if (this.unObserveObjects) {
|
||||
this.unObserveObjects.forEach((unObserveObject) => {
|
||||
@ -156,7 +159,7 @@
|
||||
if (domainObject) {
|
||||
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
|
||||
if (changedItemId === id && item.property === s.property) {
|
||||
if (changedItemId === id && this.getItemProperty(item) === this.getItemProperty(s)) {
|
||||
toolbarItem.value = value;
|
||||
}
|
||||
}
|
||||
@ -170,12 +173,12 @@
|
||||
this.structure.map(s => {
|
||||
if (s.formKeys) {
|
||||
s.formKeys.forEach(key => {
|
||||
this.openmct.objects.mutate(item.domainObject, item.property + "." + key, value[key]);
|
||||
this.openmct.objects.mutate(item.domainObject, this.getItemProperty(item) + "." + key, value[key]);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.openmct.objects.mutate(item.domainObject, item.property, value);
|
||||
this.openmct.objects.mutate(item.domainObject, this.getItemProperty(item), value);
|
||||
}
|
||||
},
|
||||
triggerMethod(item, event) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user