gd-sprest-bs
Version:
SharePoint JavaScript, TypeScript and Web Components designed using the Bootstrap framework.
296 lines (249 loc) • 9.82 kB
text/typescript
import { Components } from "gd-bs";
import { Types } from "gd-sprest";
import { x as CloseIcon } from "../../icons/svgs/x";
import { IWPListField, IWPListFieldsCfg, IWPListFieldsEditForm, IWPListFieldsInfo } from "./types";
/**
* List Fields WebPart Edit Form
*/
export const WPListFieldsEditForm = (props: IWPListFieldsEditForm = {}): IWPListFieldsEditForm => {
let _ddlFields: Components.IDropdown = null;
let _ddlSelectedFields: Components.IDropdown = null;
let _selectedFields: Array<Components.IDropdownItem> = null;
let _tbFilter: Components.IInputGroup = null;
let _wpInfo: IWPListFieldsInfo = null;
// Adds a selected field
let addField = (field: Components.IDropdownItem) => {
// Add the selected field
_selectedFields.push({
text: field.text,
value: field.value,
onRender: (el => {
// Set the styling
el.classList.add("d-flex");
el.classList.add("justify-content-between");
// Append an icon to remove the field
el.appendChild(CloseIcon(16, 16));
// Set the click event
el.addEventListener("click", () => {
// Remove this field
removeField(field);
});
// Clear the filter
_tbFilter.setValue("");
})
});
// Render the fields
_ddlSelectedFields.setItems(_selectedFields);
}
// Filters the fields dropdown items
let filterFields = (filter: string) => {
// Parse the items
let items = _ddlFields.el.querySelectorAll(".dropdown-item");
for (let i = 0; i < items.length; i++) {
let item = items[i] as HTMLAnchorElement;
let field = (item.innerText || "").toLowerCase();
// See if the field contains this value
if (filter == "" || field.indexOf(filter) >= 0) {
// Show this element
item.classList.remove("d-none");
} else {
// Hide this element
item.classList.add("d-none");
}
}
}
// Gets the selected field values
let getSelectedFields = () => {
let fields: Array<IWPListField> = [];
// Get the selected fields
for (let i = 0; i < _selectedFields.length; i++) {
let field = _selectedFields[i];
// Ensure this is a field
if (field.text && field.value) {
// Save the field
fields.push({
Name: field.value,
Title: field.text
});
}
}
// Return the fields
return fields;
}
// Removes a selected field
let removeField = (field: Components.IDropdownItem) => {
// Parse the selected fields
for (let i = 0; i < _selectedFields.length; i++) {
let selectedField = _selectedFields[i];
// See if this is the target field
if (selectedField.value == field.value) {
// Remove this field
_selectedFields.splice(i, 1);
// Render the items
_ddlSelectedFields.setItems(_selectedFields);
// Stop the loop
break;
}
}
}
// Renders the fields control
let renderFields = (el: HTMLElement, fields: Array<IWPListField>) => {
let filter = "";
// Create the dropdown menu
_ddlFields = Components.Dropdown({
id: "calendarFields",
menuOnly: true,
onChange: item => {
// Close the popover
popover.hide();
// Clear the filter
filterFields("");
// Add the selected field
addField(item as any);
}
});
// Render the textfield
_tbFilter = Components.InputGroup({
el,
placeholder: "Select a Field...",
onChange: value => {
// Set the filter
filter = value;
// Wait for the user to stop typing
setTimeout(() => {
// Ensure the value hasn't changed
if (value != filter) { return; }
// Filter the fields
filterFields(filter.toLowerCase());
// Display the popover
popover.show();
}, 250);
}
});
// Render the selected fields
_ddlSelectedFields = Components.Dropdown({
el,
id: "selectedFields",
menuOnly: true
});
// Add a click event to display the popover
_tbFilter.el.addEventListener("click", () => {
// Display the popover
popover.show();
});
// Create a popover
let popover = Components.Popover({
el,
target: _tbFilter.el,
type: Components.PopoverPlacements.Auto,
options: {
trigger: "click",
content: _ddlFields.el
}
});
}
// Updates the fields
let setItems = (fields: Array<Components.IDropdownItem>, selectedFields: Array<IWPListField> = []) => {
// Update the dropdown
_ddlFields.setItems(fields);
// Parse the selected fields
for (let i = 0; i < selectedFields.length; i++) {
let fieldInfo = selectedFields[i];
// Parse the fields
for (let j = 0; j < fields.length; j++) {
let field = fields[j];
// See if this is the target field
if (field.value == fieldInfo.Name) {
// Add this field
addField(field);
break;
}
}
}
}
// Updates the fields dropdown in the edit panel
let updateFieldsDDL = (list: Types.SP.List, selectedFields: Array<IWPListField> = []) => {
let items: Array<Components.IDropdownItem> = [];
// Clear the dropdown
setItems([{
isHeader: true,
text: list ? "Loading the Fields" : "Select a List"
}]);
// Ensure the list exists
if (list) {
// Get the fields
list.Fields().query({ OrderBy: ["Title"] }).execute(fields => {
// Parse the fields
for (let i = 0; i < fields.results.length; i++) {
let field = fields.results[i];
// Skip the title fields
if (field.InternalName == "LinkTitle" || field.InternalName == "LinkTitleNoMenu") { continue; }
// Skip hidden fields
if (field.Hidden) { continue; }
// Set the dropdown value
items.push({
text: field.Title,
value: field.InternalName
});
}
// Update the dropdown values
setItems(items, selectedFields);
});
}
}
// Return the edit panel
return {
actions: props.actions,
showSaveButton: props.showSaveButton,
onListChanged: (wpInfo, list) => {
// Update the fields dropdown
updateFieldsDDL(list as any);
},
onRenderForm: (wpInfo, list) => {
// Save the webpart information
_wpInfo = wpInfo;
// Clear the selected fields
_selectedFields = [];
// Set the default control
let controls: Array<Components.IFormControlProps> = [
{
name: "Fields",
label: "Fields",
onControlRendered: ctrl => {
// Render the fields control
renderFields(ctrl.el, wpInfo.cfg.Fields);
// Update the fields dropdown
updateFieldsDDL(list as any, wpInfo.cfg.Fields);
}
}
];
// Call the render form event
let returnVal: any = props.onRenderForm ? props.onRenderForm(_wpInfo, list) : null;
if (returnVal) {
// See if this is a promise
if (returnVal.then) {
// Return a promise
return new Promise((resolve, reject) => {
// Wait for the promise to complete
returnVal.then((formControls = []) => {
// Add the form controls
controls = controls.concat(formControls);
// Resolve the promise
resolve(controls);
});
});
}
// Add the form controls
controls = controls.concat(returnVal);
}
// Return the custom properties
return controls;
},
onSave: (cfg: IWPListFieldsCfg, form) => {
// Update the configuration
cfg.Fields = getSelectedFields();
// Return the configuration
return props.onSave ? props.onSave(_wpInfo.cfg, form) : _wpInfo.cfg;
}
};
}