@pnp/spfx-property-controls
Version:
Reusable property pane controls for SharePoint Framework solutions
220 lines • 9.63 kB
JavaScript
import * as React from 'react';
import styles from '../PropertyFieldCollectionDataHost.module.scss';
import { CollectionDataItem } from '../collectionDataItem';
import { PrimaryButton, DefaultButton, Icon } from '@fluentui/react';
import * as strings from 'PropertyControlStrings';
import { cloneDeep, sortBy } from '@microsoft/sp-lodash-subset';
export class CollectionDataViewer extends React.Component {
constructor(props) {
super(props);
this.SORT_IDX = 'sortIdx';
/**
* Add a new item to the collection
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.addItem = (item) => {
this.setState((prevState) => {
let crntItems = [...prevState.crntItems, item];
crntItems = this.updateSortProperty(crntItems);
return {
crntItems,
inCreationItem: null,
inCreationItemValid: null,
};
});
};
/**
* Remove an item from the collection
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.updateItem = (idx, item) => {
this.setState((prevState) => {
const { crntItems } = prevState;
// Update the item in the array
crntItems[idx] = item;
return { crntItems };
});
};
/**
* Remove an item from the collection
*/
this.deleteItem = (idx) => {
this.setState((prevState) => {
let { crntItems } = prevState;
const { validation } = prevState;
crntItems.splice(idx, 1);
delete validation[idx];
// Update the sort propety
crntItems = this.updateSortProperty(crntItems);
return {
crntItems: sortBy(crntItems, this.SORT_IDX),
validation: validation,
};
});
};
/**
* Validate every item
*/
this.validateItem = (idx, isValid) => {
this.setState((prevState) => {
const { validation } = prevState;
validation[idx] = isValid;
return {
validation: prevState.validation,
};
});
};
/**
* Currently in creation
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.addInCreation = (item, isValid) => {
this.setState({
inCreationItem: item,
inCreationItemValid: isValid,
});
};
/**
* Add the item and save the form
*/
this.addAndSave = () => {
// Check if the item is not empty
if (this.state.inCreationItem) {
let crntItems = [...this.state.crntItems, this.state.inCreationItem];
crntItems = this.updateSortProperty(crntItems);
this.props.fOnSave(crntItems);
}
else {
this.onSave();
}
};
/**
* Update the sort order
*/
this.updateSortOrder = (oldIdx, newIdx) => {
this.setState((prevState) => {
const { crntItems } = prevState;
let newOrderedItems = cloneDeep(crntItems);
newOrderedItems = this.moveItemTo(newOrderedItems, oldIdx, newIdx - 1);
newOrderedItems = this.updateSortProperty(newOrderedItems);
newOrderedItems = sortBy(newOrderedItems, this.SORT_IDX);
return {
crntItems: newOrderedItems,
};
});
};
/**
* Save the collection data
*/
this.onSave = () => {
this.props.fOnSave(this.state.crntItems);
};
/**
* Cancel
*/
this.onCancel = () => {
this.props.fOnClose();
};
this.state = {
crntItems: [],
inCreationItem: null,
inCreationItemValid: null,
validation: {},
};
}
/**
* componentDidMount lifecycle hook
*/
componentDidMount() {
let crntItems = this.props.value
? sortBy(cloneDeep(this.props.value), this.SORT_IDX)
: [];
crntItems = crntItems.map((item, idx) => {
if (!item[this.SORT_IDX]) {
item[this.SORT_IDX] = idx + 1;
}
return item;
});
// Update the sort propety
crntItems = this.updateSortProperty(crntItems);
this.setState({
crntItems: sortBy(crntItems, this.SORT_IDX),
});
}
/**
* Check if all items are valid
*/
allItemsValid() {
const { validation } = this.state;
if (validation) {
const keys = Object.keys(validation);
for (const key of keys) {
if (!validation[key]) {
return false;
}
}
}
return true;
}
/**
* Move an item in the array
*
* @param crntItems
* @param oldIdx
* @param newIdx
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
moveItemTo(crntItems, oldIdx, newIdx) {
if (newIdx > -1 && newIdx < crntItems.length) {
const removedElement = crntItems.splice(oldIdx, 1)[0];
if (removedElement) {
crntItems.splice(newIdx, 0, removedElement);
}
}
return crntItems;
}
/**
* Update the sort property
*
* @param crntItems
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
updateSortProperty(crntItems) {
// Update the sort order
return crntItems.map((item, itemIdx) => {
item[this.SORT_IDX] = itemIdx + 1;
return item;
});
}
/**
* Default React render
*/
render() {
const crntItems = [
...this.state.crntItems,
this.state.inCreationItem,
].filter((i) => i);
const visibleFields = this.props.fields.filter((f) => !f.isVisible || f.isVisible(f, crntItems));
return (React.createElement("div", null,
React.createElement("div", { className: `PropertyFieldCollectionData__panel__table ${styles.table} ${this.props.tableClassName || ''}` },
React.createElement("div", { className: `PropertyFieldCollectionData__panel__table-head ${styles.tableRow} ${styles.tableHead}` },
this.props.enableSorting && (React.createElement("span", { className: `PropertyFieldCollectionData__panel__table-cell ${styles.tableCell}` })),
visibleFields.map((f) => (React.createElement("span", { key: `dataviewer-${f.id}`, className: `PropertyFieldCollectionData__panel__table-cell ${styles.tableCell}` },
f.title,
' ',
f.required && (React.createElement(Icon, { className: styles.required, iconName: 'Asterisk' }))))),
React.createElement("span", { className: `PropertyFieldCollectionData__panel__table-cell ${styles.tableCell}` }),
React.createElement("span", { className: `PropertyFieldCollectionData__panel__table-cell ${styles.tableCell}` })),
this.state.crntItems &&
this.state.crntItems.length > 0 &&
this.state.crntItems.map((item, idx, allItems) => (React.createElement(CollectionDataItem, { key: item.uniqueId, fields: visibleFields, index: idx, item: item, totalItems: allItems.length, sortingEnabled: this.props.enableSorting, disableItemDeletion: this.props.disableItemDeletion, fUpdateItem: this.updateItem, fDeleteItem: this.deleteItem, fValidation: this.validateItem, fOnSorting: this.updateSortOrder }))),
!this.props.disableItemCreation && (React.createElement(CollectionDataItem, { fields: visibleFields, index: null, item: null, sortingEnabled: this.props.enableSorting, totalItems: null, fAddItem: this.addItem, fAddInCreation: this.addInCreation }))),
(!this.state.crntItems || this.state.crntItems.length === 0) && (React.createElement("p", { className: `PropertyFieldCollectionData__panel__no-collection-data ${styles.noCollectionData}` }, strings.CollectionDataEmptyValue)),
React.createElement("div", { className: `PropertyFieldCollectionData__panel__actions ${styles.panelActions}` },
this.state.inCreationItem && this.state.inCreationItemValid && (React.createElement(PrimaryButton, { text: this.props.saveAndAddBtnLabel ||
strings.CollectionSaveAndAddButtonLabel, onClick: this.addAndSave, disabled: !this.allItemsValid(), className: 'PropertyFieldCollectionData__panel__action__add' })),
!(this.state.inCreationItem && this.state.inCreationItemValid) && (React.createElement(PrimaryButton, { text: this.props.saveBtnLabel || strings.SaveButtonLabel, onClick: this.onSave, disabled: !this.allItemsValid(), className: 'PropertyFieldCollectionData__panel__action__save' })),
React.createElement(DefaultButton, { text: this.props.cancelBtnLabel || strings.CancelButtonLabel, onClick: this.onCancel, className: 'PropertyFieldCollectionData__panel__action__cancel' }))));
}
}
//# sourceMappingURL=CollectionDataViewer.js.map