openmct/src/plugins/duplicate/DuplicateAction.js
Andrew Henry 703186adf1
Add script to lock object sub-tree and fix object locking bugs (#7855)
* Script for locking an object tree

* Show lock button if locked

* Do not allow properties editing of locked objects

* Remove package-lock.json

* Added p-debounce

* Allow duplication of locked objects

* Better user feedback

* Add semaphores to prevent file handle exhaustion

* Leverage official Apache Couch library - nano. Clean up dependencies. Default to environment variables for couch config. Simplify batching mechanism to make it synchronouse

* Added lock user attribution

* Remove unused code

* Modify open script for adding auth design doc

* Added script for creating auth design doc

* Add css class for disallow unlock

* Add user attribution to lock button

* Fix import

* Typo

* User it was locked by, not current user. Wow.

* Closes #7877
- Front-end sanding and shimming: displays <span> instead of button when domainObject.disallowUnlock.

* Fixed bug where lock is shown even if object is not locked

---------

Co-authored-by: Charles Hacskaylo <charles.f.hacskaylo@nasa.gov>
Co-authored-by: Jesse Mazzella <ozyx@users.noreply.github.com>
2024-10-10 15:09:39 -07:00

178 lines
5.3 KiB
JavaScript

/*****************************************************************************
* Open MCT, Copyright (c) 2014-2024, 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 DuplicateTask from './DuplicateTask.js';
const DUPLICATE_ACTION_KEY = 'duplicate';
class DuplicateAction {
constructor(openmct) {
this.name = 'Duplicate';
this.key = DUPLICATE_ACTION_KEY;
this.description = 'Duplicate this object.';
this.cssClass = 'icon-duplicate';
this.group = 'action';
this.priority = 7;
this.openmct = openmct;
this.transaction = null;
}
invoke(objectPath) {
this.object = objectPath[0];
this.parent = objectPath[1];
this.showForm(this.object, this.parent);
}
inNavigationPath() {
return this.openmct.router.path.some((objectInPath) =>
this.openmct.objects.areIdsEqual(objectInPath.identifier, this.object.identifier)
);
}
async onSave(changes) {
this.startTransaction();
let inNavigationPath = this.inNavigationPath();
if (inNavigationPath && this.openmct.editor.isEditing()) {
this.openmct.editor.save();
}
let duplicationTask = new DuplicateTask(this.openmct);
if (changes.name && changes.name !== this.object.name) {
duplicationTask.changeName(changes.name);
}
const parentDomainObjectpath = changes.location || [this.parent];
const parent = parentDomainObjectpath[0];
await duplicationTask.duplicate(this.object, parent);
return this.saveTransaction();
}
showForm(domainObject, parentDomainObject) {
const formStructure = {
title: 'Duplicate Item',
sections: [
{
rows: [
{
key: 'name',
control: 'textfield',
name: 'Title',
pattern: '\\S+',
required: true,
cssClass: 'l-input-lg',
value: domainObject.name
},
{
name: 'Location',
cssClass: 'grows',
control: 'locator',
required: true,
parent: parentDomainObject,
validate: this.validate(parentDomainObject),
key: 'location'
}
]
}
]
};
this.openmct.forms.showForm(formStructure).then(this.onSave.bind(this));
}
validate(currentParent) {
return (data) => {
const parentCandidate = data.value[0];
let currentParentKeystring = this.openmct.objects.makeKeyString(currentParent.identifier);
let parentCandidateKeystring = this.openmct.objects.makeKeyString(parentCandidate.identifier);
let objectKeystring = this.openmct.objects.makeKeyString(this.object.identifier);
const isLocked = parentCandidate.locked === true;
if (isLocked || !this.openmct.objects.isPersistable(parentCandidate.identifier)) {
return false;
}
if (!parentCandidateKeystring || !currentParentKeystring) {
return false;
}
if (parentCandidateKeystring === objectKeystring) {
return false;
}
const parentCandidateComposition = parentCandidate.composition;
if (
parentCandidateComposition &&
parentCandidateComposition.indexOf(objectKeystring) !== -1
) {
return false;
}
return parentCandidate && this.openmct.composition.checkPolicy(parentCandidate, this.object);
};
}
appliesTo(objectPath) {
const parent = objectPath[1];
const parentType = parent && this.openmct.types.get(parent.type);
const child = objectPath[0];
const childType = child && this.openmct.types.get(child.type);
const isPersistable = this.openmct.objects.isPersistable(child.identifier);
if (!isPersistable) {
return false;
}
return (
childType &&
childType.definition.creatable &&
parentType &&
parentType.definition.creatable &&
Array.isArray(parent.composition)
);
}
startTransaction() {
if (!this.openmct.objects.isTransactionActive()) {
this.transaction = this.openmct.objects.startTransaction();
}
}
async saveTransaction() {
if (!this.transaction) {
return;
}
await this.transaction.commit();
this.openmct.objects.endTransaction();
this.transaction = null;
}
}
export { DUPLICATE_ACTION_KEY };
export default DuplicateAction;