UNPKG

@mikezimm/fps-library-v2

Version:

Library of reusable typescript/javascript functions, interfaces and constants

864 lines (860 loc) 50.3 kB
/** * CodeAnalizerComment: Updated 5 imports on 2024-09-22 14:49:52 * Update:: import { PanelType } to '@mikezimm/fps-core-v7/lib/types/@fluentUI/@7.199.1/Panel;' * Update:: import { replaceHandleBarsValues } to '@mikezimm/fps-core-v7/lib/logic/Strings/handleBarsSub;' * Update:: import { IDrillItemInfo } to '@mikezimm/fps-core-v7/lib/components/webparts/Drilldown/IDrillItem;' * Update:: import { IQuickButton } to '@mikezimm/fps-core-v7/lib/components/webparts/Drilldown/QuickCommands/IQuickCommands;' * Update:: import { IAnySourceItemAny } to '@mikezimm/fps-core-v7/lib/components/molecules/AnyContent/IAnyContent;' */ /** * CodeAnalizerComment: Updated 3 imports on 2024-09-21 23:07:24 * Update:: import { doesObjectExistInArray } to '@mikezimm/fps-core-v7/lib/logic/Arrays/searching/objectfind;' * Update:: import { check4This } to '@mikezimm/fps-core-v7/lib/logic/Links/CheckSearch;' * Update:: import { IAnySourceItemAny } to '@mikezimm/fps-core-v7/lib/components/molecules/AnyContent/IAnyContent;' */ import * as React from 'react'; import { Icon, } from '@fluentui/react/lib/Icon'; import { Pivot, PivotItem, } from '@fluentui/react/lib/Pivot'; import ReactJson from '@microlink/react-json-view'; import { getMaxRichHeightNum } from '../functions/richHeight'; import { SelectionMode } from '@mikezimm/fps-core-v7/lib/types/spfxControlsReact/@3.12.0/SelectionMode'; import { Panel, PanelType } from '@fluentui/react/lib/Panel'; import { PrimaryButton, DefaultButton } from '@fluentui/react/lib/Button'; import PageArrows from '../../Arrows/PageArrows'; import { replaceHandleBarsValues } from '@mikezimm/fps-core-v7/lib/logic/Strings/handleBarsSub'; import { buildConfirmDialogBig } from '../../../atoms/Elements/confirmDialogBig'; import { makeToggles } from '../atoms/toggleFieldBuilder'; import { autoDetailsList } from '../atoms/detailsList'; import { findParentElementPropLikeThis } from '@mikezimm/fps-core-v7/lib/logic/DOM/Search/domSearch'; import { updateReactListItem } from '../functions/updateReactListItem'; import { doesObjectExistInArray } from '@mikezimm/fps-core-v7/lib/logic/Arrays/searching/objectfind'; import { createPanelButtonsV2 } from '../atoms/createPanelButtonsV2'; import { createPanelAttachmentElements } from '../functions/fetchAttachments'; import { check4This, Check4 } from '@mikezimm/fps-core-v7/lib/logic/Links/CheckSearch'; import { createItemSharingTable } from '../../../atoms/SharedItems/createItemSharingTable'; import { makeAbsoluteUrl } from '@mikezimm/fps-core-v7/lib/logic/Strings/getSiteCollectionUrlFromLink'; import { ReactViewSpecialKeys } from '../interfaces/SpecialViewKeys'; import { getWebPartVersionElement } from '../../../../banner/bannerX/VersionElement'; import { renderPermsStandalone, renderAttachStandalone } from './specialRenders'; require('@mikezimm/fps-styles/dist/reactListView.css'); export default class ReactListItems extends React.Component { /** * createPanelAttachments is identical on ActionNews and Drilldown7 except panelItem interface * @param thisId * @param panelItem */ async _createPanelAttachments(thisId, panelItem) { const attachments = await createPanelAttachmentElements(this.props.bannerProps.fpsSpService, this.props.webUrl, this.props.listTitle, panelItem); this.setState({ panelAttachments: attachments, lastAttachId: thisId, }); } handleExpandedFieldInfoToIViewFields(viewFields) { //Before this line was added, I think it was mutating props causing double render viewFields = JSON.parse(JSON.stringify(viewFields)); viewFields.map(vf => { //2022-03-18: MEMO TO SELF... SOMETHING SEEMS OFF about this replace... vf.name = vf.name.replace(/\//g, ''); }); return viewFields; } createBlankDialog() { let myDialog = { title: '', dialogMessage: '', showDialog: false, confirmButton: '', _confirmDialog: this._confirmUpdateDialog.bind(this), _closeDialog: this._closeDialog.bind(this), }; return myDialog; } constructor(props) { super(props); this._componentWidth = null; this.delim = '|||'; /*** * .o88b. .d88b. d8b db .d8888. d888888b d8888b. db db .o88b. d888888b .d88b. d8888b. * d8P Y8 .8P Y8. 888o 88 88' YP `~~88~~' 88 `8D 88 88 d8P Y8 `~~88~~' .8P Y8. 88 `8D * 8P 88 88 88V8o 88 `8bo. 88 88oobY' 88 88 8P 88 88 88 88oobY' * 8b 88 88 88 V8o88 `Y8b. 88 88`8b 88 88 8b 88 88 88 88`8b * Y8b d8 `8b d8' 88 V888 db 8D 88 88 `88. 88b d88 Y8b d8 88 `8b d8' 88 `88. * `Y88P' `Y88P' VP V8P `8888Y' YP 88 YD ~Y8888P' `Y88P' YP `Y88P' 88 YD * * */ this._ListViewFontSizes = [`default-font-size`, `larger-font-size`, `large-font-size`]; this._onGoToList = () => { if (!this.props.listUrl || this.props.listUrl === null || this.props.listUrl === undefined || this.props.listUrl.length === 0) { return; // Do nothing } let e = event; let isAltClick = e.altKey; let isShfitClick = e.shiftKey; let isCtrlClick = e.ctrlKey; console.log('AltClick, ShfitClick, CtrlClick:', isAltClick, isShfitClick, isCtrlClick); window.open(`${this.props.listUrl}?Source=${window.location.pathname}`, "_blank"); }; this._CreateNewItem = () => { if (this.props.isLibrary === true) { window.open(`${this.props.listUrl}`, "_blank"); } else { // https://github.com/mikezimm/drilldown7/issues/422 if (this.props.listNewForm.indexOf('/sites/') === 0 || this.props.listNewForm.indexOf('http') === 0) { window.open(`${this.props.listNewForm}.aspx?Source=${this.props.itemLinkSource}`, "_blank"); } else { // window.open(`${this.props.listUrl}/NewForm.aspx?Source=${window.location.pathname}&${window.location.search}`, "_blank"); window.open(`${this.props.listUrl}/${this.props.listNewForm}.aspx?Source=${this.props.itemLinkSource}`, "_blank"); } } }; /** * Close the dialog */ this._closeDialog = () => { this.setState({ myDialog: this.createBlankDialog(), }); }; /** * Render permissions / sharing icon cell. Extracted for reuse elsewhere. * fieldName: either 'HasUniqueRoleAssignments' or 'ItemSharingInfo' */ this._renderPerms = (fieldName, item) => { return renderPermsStandalone(fieldName, item, this.props, this._onShowPanel.bind(this)); }; /** * Render attachments icon cell. Reusable for Attach column. */ this._renderAttach = (item) => { return renderAttachStandalone(item, this.props, this._onShowPanel.bind(this)); }; this._onClosePanel = () => { this.setState({ showPanel: false, showAttach: false, clickedAttach: false, }); }; /*** * d8888b. .d8b. d8b db d88888b db d88888b .d88b. .d88b. d888888b d88888b d8888b. * 88 `8D d8' `8b 888o 88 88' 88 88' .8P Y8. .8P Y8. `~~88~~' 88' 88 `8D * 88oodD' 88ooo88 88V8o 88 88ooooo 88 88ooo 88 88 88 88 88 88ooooo 88oobY' * 88~~~ 88~~~88 88 V8o88 88~~~~~ 88 88~~~ 88 88 88 88 88 88~~~~~ 88`8b * 88 88 88 88 V888 88. 88booo. 88 `8b d8' `8b d8' 88 88. 88 `88. * 88 YP YP VP V8P Y88888P Y88888P YP `Y88P' `Y88P' YP Y88888P 88 YD * * */ /** * This was copied from codepen example code to render a footer with buttons: * https://fabricweb.z5.web.core.windows.net/oufr/6.50.2/#/examples/panel * */ this._onRenderFooterContent = () => { return null; return (React.createElement("div", null, React.createElement(PrimaryButton, { onClick: this._onClosePanel, style: { marginRight: '8px' } }, "Save"), React.createElement(DefaultButton, { onClick: this._onClosePanel }, "Cancel"))); }; if (check4This(Check4.sourceResults_Eq_true, false) === true) console.log('listView PROPS: ', this.props); let viewFields = []; if (this.props.viewFields.length > 0) { viewFields = this.handleExpandedFieldInfoToIViewFields(this.props.viewFields); } let groupByFields = []; if (this.props.groupByFields && this.props.groupByFields.length > 0) { //Added this reparse to prevent mutating props groupByFields = JSON.parse(JSON.stringify(this.props.groupByFields)); groupByFields.map(gF => { gF.name = gF.name.replace(/\//g, ''); }); } const richHeightNum = getMaxRichHeightNum(this.props.autoRichHeight, this.props.richHeights[0], this.props.items); this.state = { fontSize: this._ListViewFontSizes[0], maxChars: this.props.maxChars ? this.props.maxChars : 50, viewFields: viewFields, groupByFields: groupByFields, showPanel: false, showAttach: false, panelId: null, lastPanelId: null, panelItem: null, panelAttachments: [], panelRollAssignments: [], lastAttachId: null, clickedAttach: false, myDialog: this.createBlankDialog(), pickedCommand: null, panelWidth: PanelType.medium, richHeightNum: richHeightNum, richHeightStr: `${richHeightNum}em`, firstVisible: 0, lastVisible: this.props.itemsPerPage - 1, commandResult: null, commandError: false, showCommandCode: false, }; } componentDidMount() { //this._getListItems(); } /*** * d8888b. d888888b d8888b. db db d8888b. d8888b. .d8b. d888888b d88888b * 88 `8D `88' 88 `8D 88 88 88 `8D 88 `8D d8' `8b `~~88~~' 88' * 88 88 88 88 88 88 88 88oodD' 88 88 88ooo88 88 88ooooo * 88 88 88 88 88 88 88 88~~~ 88 88 88~~~88 88 88~~~~~ * 88 .8D .88. 88 .8D 88b d88 88 88 .8D 88 88 88 88. * Y8888D' Y888888P Y8888D' ~Y8888P' 88 Y8888D' YP YP YP Y88888P * * */ componentDidUpdate(prevProps, prevState) { /* eslint-disable @typescript-eslint/no-unused-vars */ let redraw = false; let updateViewFields = false; let resetArrows = false; if (JSON.stringify(prevProps.viewFields) !== JSON.stringify(this.props.viewFields)) { updateViewFields = true; redraw = true; } if (JSON.stringify(prevProps.groupByFields) !== JSON.stringify(this.props.groupByFields)) { updateViewFields = true; redraw = true; } if (prevProps.resetArrows !== this.props.resetArrows) { // updateViewFields = true; resetArrows = true; this.setState({ firstVisible: 0, lastVisible: this.props.itemsPerPage - 1, }); } if (prevProps.richHeights.join('') !== this.props.richHeights.join('')) { updateViewFields = true; redraw = true; } // if ( prevProps.items.length !== this.props.items.length ) { // this._setMaxRichHeight( this.props.autoRichHeight, this.props.richHeight, this.props.items ); // redraw = true; } if (prevProps.listUrl !== this.props.listUrl) { redraw = true; } /* eslint-enable @typescript-eslint/no-unused-vars */ this._updateStateOnPropsChange(updateViewFields); } /*** * d8888b. d88888b d8b db d8888b. d88888b d8888b. * 88 `8D 88' 888o 88 88 `8D 88' 88 `8D * 88oobY' 88ooooo 88V8o 88 88 88 88ooooo 88oobY' * 88`8b 88~~~~~ 88 V8o88 88 88 88~~~~~ 88`8b * 88 `88. 88. 88 V888 88 .8D 88. 88 `88. * 88 YD Y88888P VP V8P Y8888D' Y88888P 88 YD * * */ render() { let ListView = this.props.ListView; //console.log( 'ReactListItems props & state: ', this.props, this.state ); // let thisLog = null; let showRichHeightButton = false; //2022-02-01: Updated this from drilldown7 if (this.props.items === null || this.props.items.length === 0) { return (React.createElement("div", { className: '' }, "List View has NO Items to show")); } else { const { bannerProps } = this.props; let attachments = this.state.panelAttachments.length > 0 ? this.state.panelAttachments : null; let dialog = !this.state.myDialog.showDialog ? null : buildConfirmDialogBig(this.state.myDialog); const { quickCommands, } = this.props; const { commandError, commandResult } = this.state; /*** * d888888b .d88b. d888b d888b db d88888b .d8888. * `~~88~~' .8P Y8. 88' Y8b 88' Y8b 88 88' 88' YP * 88 88 88 88 88 88 88ooooo `8bo. * 88 88 88 88 ooo 88 ooo 88 88~~~~~ `Y8b. * 88 `8b d8' 88. ~8~ 88. ~8~ 88booo. 88. db 8D * YP `Y88P' Y888P Y888P Y88888P Y88888P `8888Y' * * */ let toggles = !this.state.showPanel ? null : React.createElement("div", { style: { float: 'right' } }, " ", makeToggles(this.getPageToggles()), " "); const itemLink = React.createElement("div", { style: { cursor: 'pointer', fontSize: 'larger', 'fontWeight': 600, color: 'darkblue', padding: '10px 10px 10px 0px', margin: '20px 0px' }, onClick: () => { window.open(this.state.panelItem.goToPropsLink, '_blank'); } }, "Click to open item"); let UniquePermsElement = !this.state.panelItem || !this.state.panelItem.HasUniqueRoleAssignments ? undefined : React.createElement("div", null, React.createElement("h3", null, renderPermsStandalone('HasUniqueRoleAssignments', this.state.panelItem, this.props, null), "Item has Unique Permissions")); let SharingElement = !this.state.panelItem || !this.state.panelItem.ItemSharingInfo ? undefined : React.createElement("div", null, React.createElement("h3", null, "Sharing History"), createItemSharingTable(this.state.panelItem, true)); let fullPanel = null; if (this.state.showPanel === true && this.state.panelId) { fullPanel = React.createElement(Panel, { isOpen: this.state.showPanel, type: this.state.panelWidth, onDismiss: this._onClosePanel, headerText: this.state.panelId.toString(), closeButtonAriaLabel: "Close", onRenderFooterContent: this._onRenderFooterContent, isLightDismiss: true, isFooterAtBottom: true }, toggles, React.createElement(Pivot, { "aria-label": "React List View Panel", defaultSelectedIndex: 0, style: { paddingTop: '16px' } }, React.createElement(PivotItem, { headerText: "Commands", itemKey: "Commands" }, React.createElement("div", null, itemLink, React.createElement("div", { id: '20pxSpacer', style: { height: '20px' } }), attachments, createPanelButtonsV2(this.props.quickCommands, this.state.panelItem, this.props.sourceUserInfo, this._panelButtonClickedv2.bind(this), this.delim, this.state.showCommandCode), UniquePermsElement, SharingElement)), React.createElement(PivotItem, { headerText: "Details", itemKey: "Details" }, itemLink, UniquePermsElement, SharingElement, autoDetailsList(this.state.panelItem, ["Title", "refiners"], ["search", "meta", "searchString"], true)), React.createElement(PivotItem, { headerText: "JSON", itemKey: "JSON" }, React.createElement("div", { id: "CommandsJSONPanel", style: { paddingTop: '20px' } }, itemLink, React.createElement(ReactJson, { src: this.state.panelItem, name: 'panelItem', collapsed: true, displayDataTypes: true, displayObjectSize: true, enableClipboard: true, style: { padding: '20px 0px' } }), SharingElement))), getWebPartVersionElement(this.props.bannerProps, { paddingTop: '4em' })); } /** * 2022-02-01: This was copied/updated from drilldown7 to actionnews */ let attachPanel = null; if (this.state.showAttach === true && this.state.panelId) { attachPanel = React.createElement(Panel, { isOpen: this.state.showAttach, type: this.state.panelWidth, onDismiss: this._onClosePanel, headerText: this.state.panelId.toString(), closeButtonAriaLabel: "Close", onRenderFooterContent: this._onRenderFooterContent, isLightDismiss: true, isFooterAtBottom: true }, attachments, SharingElement); } let viewFieldsBase = this.state.viewFields; let preFields = []; if (this.props.includePerms) { //Add permissions column: const thisFieldName = `HasUniqueRoleAssignments`; preFields.push({ name: thisFieldName, displayName: 'Perms', sorting: true, minWidth: 25, maxWidth: 35, linkPropertyName: 'goToPermsLink', render: (item) => { return this._renderPerms(thisFieldName, item); }, }); } if (this.props.includeAttach) { //Add attachments column: preFields.push({ name: 'Attachments', displayName: 'Attach', sorting: true, minWidth: 25, maxWidth: 35, render: (item) => { return this._renderAttach(item); }, }); } let viewFields = preFields.concat(viewFieldsBase); let filtered = []; this.props.items.map((item, idx) => { if (idx >= this.state.firstVisible && idx <= this.state.lastVisible) { filtered.push(item); } }); const pageArrows = React.createElement(PageArrows, { itemCount: this.props.items.length, itemsPerPage: this.props.itemsPerPage, setParentStateFirstLast: this._updateFirstLastVisible.bind(this), debugMode: this.props.debugMode, fontSize: this._componentWidth && this._componentWidth > 800 ? 28 : 24, resetArrows: this.props.resetArrows, pageArrowStyles: { marginTop: '-7px' } }); viewFields.map(field => { // https://github.com/mikezimm/drilldown7/issues/337 if (field.name === 'HasUniqueRoleAssignments' || field.name === 'ItemSharingInfo') { // ContactLock field.render = (item) => { return this._renderPerms(field.name, item); }; //This is for: https://github.com/mikezimm/drilldown7/issues/224 } else if (this.props.richColumns.indexOf(field.name) > -1) { showRichHeightButton = true; const fieldStyles = [`list-view-rt`]; if (this.props.richMarginAuto === true) fieldStyles.push('list-view-rt-start'); // fieldStyles.push( this._RichTextRowHeight[ this.state.richHeight ] ); field.render = (item, index) => { return React.createElement("div", { style: { maxHeight: this.state.richHeightStr }, className: fieldStyles.join(' '), dangerouslySetInnerHTML: { __html: item[field.name] } }); }; // field.render = ( item, index ) => { this._renderRich( item, field.name ) } } else if (field.linkSubstitute || field.textSubstitute) { // Testing to see if Url value is valid... has a value, is a string, and either starts with http or /sites/ // Testing to see if Url value is valid... has a value, is a string, and either starts with http or /sites/ // 2025-03-04: added .indexOf('{{') for https://github.com/mikezimm/drilldown7/issues/484 const isValidSubLink = typeof field.linkSubstitute === "string" && (field.linkSubstitute.indexOf("/sites/") === 0 || field.linkSubstitute.indexOf("/teams/") === 0 || field.linkSubstitute.indexOf("http") === 0) || field.linkSubstitute.indexOf('{{') > -1 ? true : false; // Testing to see if Url value is valid... has a value, is a string, and either starts with http or /sites/ const isValidText = typeof field.textSubstitute === "string" ? true : false; if (isValidSubLink !== true && isValidText !== true) { return; } else { // Start on https://github.com/mikezimm/drilldown7/issues/70, https://github.com/mikezimm/drilldown7/issues/268 field.render = (item, index) => { const linkSubstitute = isValidSubLink === true ? replaceHandleBarsValues(item, field.linkSubstitute, true, 20, field.linkSubEmptyHandling) : ''; const textSubstitute = isValidText === true ? replaceHandleBarsValues(item, field.textSubstitute, field.showEmptyAsEmpty === true ? true : false) : item[field.name]; // Return element as a link if the Url passes simple validation. Else just return the displayed value as normal span if (isValidSubLink === true && linkSubstitute) { return React.createElement("a", { href: linkSubstitute }, textSubstitute); } else { return React.createElement("span", null, textSubstitute); } }; // close: field.render = ( item, index ) => { } // close if ( isValid === true ) { /** * 2025-01-27: Added this loop for rendering better link labels * https://github.com/mikezimm/drilldown7/issues/463 */ } else if (field.name.indexOf(`${field.displayName}Show`) === 0) { // This is a special column like const { linkPropertyName, displayName } = field; if (linkPropertyName && ReactViewSpecialKeys.indexOf(linkPropertyName) > -1) { field.render = (item) => { // use the actual column value (strigified) if it exists, else use a const title = displayName && item[displayName] ? JSON.stringify(item[displayName]) : linkPropertyName.replace('goTo', ''); // return <Icon style={{ fontSize: fontSize, color: unique === true ? 'red' : 'gray' }} iconName={ itemIcon } title={ title } />; return React.createElement("a", { style: {}, href: item[linkPropertyName], onClick: (event) => { event.preventDefault(); // Prevent default navigation window.open(item[linkPropertyName], '_blank'); }, title: title }, title); }; } } // close: } else if ( field.linkSubstitute ) { }); // close: viewFields.map ( field => { //=>> address: https://github.com/mikezimm/drilldown7/issues/270 const changeRichHeight = showRichHeightButton !== true ? null : React.createElement("div", { title: `Change row height from ${this.state.richHeightStr}`, onClick: this._updateRichHeightState.bind(this), style: { fontSize: 'larger', fontWeight: 'bolder', width: '25px', textAlign: 'center', cursor: 'pointer' } }, React.createElement(Icon, { iconName: 'CollapseMenu' })); // determine iconFieldName https://github.com/mikezimm/drilldown7/issues/163 const iconFieldName = this.props.isLibrary === true ? 'FileRef' : undefined; //=>> address: https://github.com/mikezimm/drilldown7/issues/169 const changeFont = React.createElement("div", { title: "Change font size", onClick: this._changeFontSize.bind(this), style: { fontSize: 'larger', fontWeight: 'bolder', width: '25px', textAlign: 'center', cursor: 'pointer' } }, React.createElement(Icon, { iconName: 'FontSize' })); let listView = React.createElement("div", { className: this.state.fontSize }, React.createElement(ListView, { items: filtered, viewFields: viewFields, // className={ 'font-size-14' } // listClassName={ stylesL.fontSizeLarger } compact: true, selectionMode: this.props.includeDetails ? SelectionMode.single : SelectionMode.none, /** * https://github.com/mikezimm/drilldown7/issues/519 * This actually works when in the compiled JS but can't figure out the correct way to type it * selection: (item, e) => this._onShowPanel(item, 'Panel', e) or this in JSX: selection={ (item, e) => this._onShowPanel(item, 'Panel', e) } */ selection: this._onShowPanel.bind(this, 'Panel'), showFilter: false, iconFieldName: iconFieldName, //defaultFilter="John" filterPlaceHolder: "Search...", groupByFields: this.props.groupByFields })); // let logTable = itemRows === null ? <div>Nothing to show</div> : <table style={{ display: 'block'}} className={stylesInfo.infoTable}> let barText = this.props.blueBar && this.props.blueBar != null ? this.props.blueBar : React.createElement("span", null, "Items"); // eslint-disable-line eqeqeq let webTitle = null; let listLink = !this.props.includeListLink ? null : React.createElement("div", { className: `info-heading`, onClick: this._onGoToList.bind(this), style: { marginRight: 30, whiteSpace: 'nowrap', paddingTop: 0, cursor: 'pointer', fontSize: 'smaller', background: 'transparent' } }, React.createElement("span", { style: { background: 'transparent' }, className: ['fps-gen-inBlockNoWrap', 'fps-gen-goToLink-theme'].join(' ') }, "Go to list")); let createItemLink = !this.props.createItemLink ? null : React.createElement("div", { title: "Create new item", className: `info-heading`, onClick: this._CreateNewItem.bind(this), style: { marginRight: 30, whiteSpace: 'nowrap', paddingTop: 0, cursor: 'pointer', fontSize: 'larger', background: 'transparent' } }, React.createElement("span", { style: { background: 'transparent' }, className: `` }, React.createElement(Icon, { iconName: "AddTo" }))); // https://github.com/mikezimm/drilldown7/issues/249 let maxBlueBarLeft = createItemLink ? 35 : 40; if (!listLink) maxBlueBarLeft += 15; const headerBarClass = [`info-heading`, `inner-shadow`, `fps-list-header-bar`, this.props.themeClass]; let headerBarStyles = { display: 'flex', justifyContent: 'space-between', }; if (bannerProps.bannerPillShape === true) headerBarStyles = { ...headerBarStyles, ...{ borderRadius: '50px' } }; if (barText !== null) { webTitle = React.createElement("div", { style: headerBarStyles, className: headerBarClass.join(' ') }, React.createElement("span", { className: `blue-bar-left`, style: { maxWidth: `${maxBlueBarLeft}%` }, title: this.props.blueBarTitleText }, "( ", this.props.items.length, " ) ", barText), pageArrows, React.createElement("span", { style: { gridRow: 'nowrap', display: 'inline-flex', gridGap: '.75em', marginRight: '25px' } }, changeFont, changeRichHeight), React.createElement("span", { style: { whiteSpace: 'nowrap', display: 'flex', marginRight: '25px' } }, createItemLink, listLink)); /** * Brought this in directly from Drilldown web part * added quickCommands && due to testing on spfx-v2-tester */ const createFooter = quickCommands && quickCommands.successBanner > 0 ? true : false; //CommandItemNotUpdatedMessage const footerEleClasses = ['quickCommandFooterStyles', commandResult ? 'quickCommandShow' : 'quickCommandHide']; if (!commandResult) { //Do nothing if no result } else if (commandResult.status === 'Success') { } else if (commandResult.status === 'Unknown') { footerEleClasses.push('quickCommandWarn'); } else { footerEleClasses.push('quickCommandError'); } const footerInfo = !commandResult ? '' : commandResult.statusElement ? commandResult.statusElement : commandResult.errorInfo ? commandResult.errorInfo.returnMess : ''; /** * NOTE: You ALWAYS need a footer element if it's active, even if there is nothing to show. * If not, then you do not get the smooth transitions when it is visible. */ const footerElement = createFooter === false ? null : React.createElement("div", { className: footerEleClasses.join(' ') }, footerInfo); /*stylesL.reactListView*/ return (React.createElement("div", { className: '', ref: el => { // el can be null - see https://reactjs.org/docs/refs-and-the-dom.html#caveats-with-callback-refs if (!el) return; this._componentWidth = el.getBoundingClientRect().width; // console.log('componentWidth', this._componentWidth ) ; } }, React.createElement("div", { style: { paddingTop: 10 }, className: `info-pane-tight` }, webTitle, fullPanel, attachPanel, dialog, footerElement, listView))); } } //if ( this.props.items != null && this.props.items.length > 0 ) { } // Render /*** * db db d8888b. d8888b. .d8b. d888888b d88888b .d8888. d888888b .d8b. d888888b d88888b * 88 88 88 `8D 88 `8D d8' `8b `~~88~~' 88' 88' YP `~~88~~' d8' `8b `~~88~~' 88' * 88 88 88oodD' 88 88 88ooo88 88 88ooooo `8bo. 88 88ooo88 88 88ooooo * 88 88 88~~~ 88 88 88~~~88 88 88~~~~~ `Y8b. 88 88~~~88 88 88~~~~~ * 88b d88 88 88 .8D 88 88 88 88. db 8D 88 88 88 88 88. * ~Y8888P' 88 Y8888D' YP YP YP Y88888P `8888Y' YP YP YP YP Y88888P * * */ _updateRichHeightState() { const oldValue = this.state.richHeightNum; const oldIdx = this.props.richHeights.indexOf(oldValue); const nextIdx = oldIdx === this.props.richHeights.length - 1 ? 0 : oldIdx + 1; const richHeightNum = this.props.richHeights[nextIdx]; this.setState({ richHeightNum: richHeightNum, richHeightStr: `${richHeightNum}em` }); } _updateStateOnPropsChange(pushViewFieldsToState) { let viewFields = []; if (this.props.viewFields.length > 0) { viewFields = this.handleExpandedFieldInfoToIViewFields(this.props.viewFields); } let groupByFields = []; if (this.props.groupByFields && this.props.groupByFields.length > 0) { groupByFields = JSON.parse(JSON.stringify(this.props.groupByFields)); groupByFields.map(gF => { gF.name = gF.name.replace(/\//g, ''); }); } if (pushViewFieldsToState === true) { this.setState({ viewFields: viewFields, groupByFields: groupByFields, }); } } /*** * d8888b. db db d888888b d888888b .d88b. d8b db .o88b. db d888888b .o88b. db dD * 88 `8D 88 88 `~~88~~' `~~88~~' .8P Y8. 888o 88 d8P Y8 88 `88' d8P Y8 88 ,8P' * 88oooY' 88 88 88 88 88 88 88V8o 88 8P 88 88 8P 88,8P * 88~~~b. 88 88 88 88 88 88 88 V8o88 8b 88 88 8b 88`8b * 88 8D 88b d88 88 88 `8b d8' 88 V888 Y8b d8 88booo. .88. Y8b d8 88 `88. * Y8888P' ~Y8888P' YP YP `Y88P' VP V8P `Y88P' Y88888P Y888888P `Y88P' YP YD * * */ async _panelButtonClickedv2(b, item, event) { console.log('_panelButtonClickedv2', item); if (!item) { alert('Whoops! Can not find ID of _panelButtonClicked!'); return null; } else { // Add Command Code to panel https://github.com/mikezimm/drilldown7/issues/252 if (event.ctrlKey === true || event.altKey === true) { this.setState({ showCommandCode: !this.state.showCommandCode }); } else { try { await this.startThisQuickUpdate2(b, item); } catch (ev) { console.log('_panelButtonClicked error:', ev); } } } } /** * Open the dialog */ //private _confirmUpdateDialog = () => { async _confirmUpdateDialog(item) { let e = event; // eslint-disable-line @typescript-eslint/no-unused-vars let thisButtonObject = this.state.pickedCommand; await this.completeThisQuickUpdate(this.state.panelId.toString(), thisButtonObject); this.setState({ myDialog: this.createBlankDialog(), }); } //=>> address: https://github.com/mikezimm/drilldown7/issues/169 _changeFontSize() { const oldValue = this.state.fontSize; const oldIdx = this._ListViewFontSizes.indexOf(oldValue); const nextIdx = oldIdx === this._ListViewFontSizes.length - 1 ? 0 : oldIdx + 1; this.setState({ fontSize: this._ListViewFontSizes[nextIdx] }); } async startThisQuickUpdate2(thisButtonObject, item) { const itemId = item.Id; if (!thisButtonObject) { alert('_panelButtonClicked - can not find thisButtonObject - ' + itemId); } else { if (thisButtonObject.updateItem) { let readyToUpdate = true; if (!this.props.webUrl) { alert('Missing listWebUrl for quickCommands'); readyToUpdate = false; } if (!this.props.listTitle) { alert('Missing listTitle for quickCommands'); readyToUpdate = false; } if (readyToUpdate === true) { //Attempt to update item: if (thisButtonObject.confirm && thisButtonObject.confirm.length > 0) { let myDialog = this.createBlankDialog(); myDialog.title = "Are you sure you want to make this update?"; myDialog.dialogMessage = thisButtonObject.confirm + ''; myDialog.confirmButton = thisButtonObject.label + ''; myDialog.showDialog = true; myDialog.maxWidth = 600; this.setState({ pickedCommand: thisButtonObject, myDialog: myDialog, }); } else { await this.completeThisQuickUpdate(itemId, thisButtonObject); } } else { //Don't update item: } } if (thisButtonObject.panelMessage) { this.setState({ panelMessage: thisButtonObject.panelMessage, }); } } } async completeThisQuickUpdate(itemId, thisButtonObject) { /** * https://github.com/mikezimm/drilldown7/issues/407 * added useWeb update to solve this issue here... * will also look upstream as well */ const { webUrl, listTitle, sourceUserInfo, quickCommands, bannerProps } = this.props; const useWeb = makeAbsoluteUrl(webUrl); const result = await updateReactListItem(bannerProps.fpsSpService, useWeb, listTitle, parseInt(itemId), thisButtonObject, sourceUserInfo, this.state.panelItem); //If success (result is error message and null by default ) // if ( result === null && quickCommands.onUpdateReload === true ) { /** * Updated this logic based on returning resultInfo not null for errors: * https://github.com/mikezimm/fps-library-v2/issues/20 */ if (quickCommands.successBanner > 0 && result.status === 'Success') { let updates = Object.keys(thisButtonObject.updateItem).map(k => { return k; }); result.statusElement = React.createElement("div", { style: { marginTop: '5px' } }, " ", [ React.createElement("h3", { key: "h3Finished", style: { paddingTop: '10px' } }, "Finished updating item [ ", itemId, " ]"), React.createElement("div", { key: "bannerIncluding" }, "Including: ", updates.join(', '), " ") ]); quickCommands.refreshCallback(result, false); //https://github.com/mikezimm/fps-library-v2/issues/20 } else if (result) { quickCommands.refreshCallback(result, true); } this.setState({ /** * Added 'as any' to commandResult: result, due to typescript error: * Types of property 'statusElement' are incompatible. Type 'IJsxElement' is not assignable to type 'Element'. Property 'key' is optional in type 'IJsxElement' but required in type 'Element'.ts(2322) */ commandResult: result, commandError: result.status === 'Success' ? false : true, }); if (result) { const delay = result.status !== 'Success' ? 10000 : quickCommands.successBanner; setTimeout(() => { this.setState({ commandResult: null, commandError: false, }); }, delay); } } /** * private._renderSecurity is found in these two places just slightly different... Going to comment out one in reactListView * @mikezimm/fps-library-v2/lib\components\molecules\ReactListV1\component\reactListView.tsx * drilldownwebpart/src\webparts\drilldownV2\components\Drill\drillComponent.tsx * * @param item * @param fieldName * @returns */ /** * Original from reactListView */ // private _renderSecurity = ( item: IAnySourceItemAny , fieldName: string, ) => { // if ( check4This( Check4.fpsReactRender_Eq_true, false ) ) console.log('_renderSecurity: ', fieldName, item ); // const unique : boolean = item.HasUniqueRoleAssignments === true ? true : false; // const itemIcon: string = item.HasUniqueRoleAssignments === true ? 'Shield' : item.ItemSharingInfo ? 'Share' : ''; // return ( item: any, index: number ) => { // const unique = item.HasUniqueRoleAssignments === true ? true : false; // const itemIcon = item.HasUniqueRoleAssignments === true ? 'Shield' : item.ItemSharingInfo ? 'Share' : ''; // if (check4This( Check4.fpsReactRender_Eq_true, false ) ) // console.log('_renderSecurity: ', fieldName, unique, itemIcon, item); // return <Icon style={{ color: unique === true ? 'red' : 'gray' }} iconName={ itemIcon } /> // }; // } /** * Original from Drilldown */ // private _renderSecurity = ( item , fieldName, ) => { // if ( check4This( 'fpsReactRender=true', false) === true ) console.log('renderExecuted: ', fieldName, item ); // const unique : boolean = item.HasUniqueRoleAssignments === true ? true : false; // const itemIcon: string = item.HasUniqueRoleAssignments === true ? 'HasUniqueRoleAssignments' : item.ItemSharingInfo ? 'Share' : ''; // return ( item: any, index: number ) => { return <Icon style={{ color: unique === true ? 'red' : 'gray' }} iconName={ itemIcon } /> }; // } /*** * .d8888. db db .d88b. db d8b db d8888b. .d8b. d8b db d88888b db * 88' YP 88 88 .8P Y8. 88 I8I 88 88 `8D d8' `8b 888o 88 88' 88 * `8bo. 88ooo88 88 88 88 I8I 88 88oodD' 88ooo88 88V8o 88 88ooooo 88 * `Y8b. 88~~~88 88 88 Y8 I8I 88 88~~~ 88~~~88 88 V8o88 88~~~~~ 88 * db 8D 88 88 `8b d8' `8b d8'8b d8' 88 88 88 88 V888 88. 88booo. * `8888Y' YP YP `Y88P' `8b8' `8d8' 88 YP YP VP V8P Y88888P Y88888P * * */ async _onShowPanel(clickType, item, e) { var _a, _b, _c; /** * Had to use this in actual drilldown compiled code or it would not build var ev = e !== undefined && e !== null ? e : (window.event !== undefined && window.event !== null ? window.event : undefined); */ const ev = (_a = e !== null && e !== void 0 ? e : window.event) !== null && _a !== void 0 ? _a : undefined; let isLink = ev && ev.srcElement && ev.srcElement.href && ev.srcElement.href.length > 0 ? true : false; /* https://github.com/mikezimm/drilldown7/issues/519 Added this part to trap special triggers like clicking on the Permissions icon */ if (clickType === 'Perms' && item.length > 0 && item[0].goToPermsLink) { ev.preventDefault(); ev.stopPropagation(); window.open(item[0].goToPermsLink, '_blank'); /** * Added to solve https://github.com/mikezimm/drilldown7/issues/159 * on /sites/ChinaSustainabilitySteeringCommittee/SitePages/Climate-Articles.aspx * Have never seen this error before. Tried same exact config to same list on another site and do not get the error. * */ } else if (ev === undefined) { return; } else if ((ev.isCtrlClick === true || ev.ctrlKey === true) && clickType === 'Panel') { // Skip the initial click and hopefully the onClick from the component kicks in return; } else if (isLink === true) { window.open(ev.srcElement.href, '_blank'); } else { let clickedAttachIcon = ((_c = (_b = ev === null || ev === void 0 ? void 0 : ev.target) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c.iconName) === 'Attach' ? true : false; if (clickedAttachIcon === true || item.length > 0) { let thisID = clickedAttachIcon === true ? findParentElementPropLikeThis(ev.target, 'id', 'ButtonID', 5, 'begins') : item[0].Id; thisID = typeof thisID === 'string' ? thisID.replace('ButtonID', '') : thisID; let panelItem = this._getItemFromId(this.props.items, 'Id', thisID); let lastPanelId = this.state.panelId; let clickedAttach = false; if (ev.srcElement.dataset && ev.srcElement.dataset.iconName === 'Attach') { clickedAttach = true; } await this._createPanelAttachments(thisID, panelItem); let canShowAPanel = thisID === null || thisID === undefined || panelItem === null ? false : true; let showFullPanel = canShowAPanel === true && clickedAttach !== true ? true : false; // 2020-10-13: The last check in this row just didn't seem right... was && this.props.includeListLink === true ? true : false; let showAttachPanel = canShowAPanel === true && clickedAttach === true && this.props.includeAttach === true ? true : false; this.setState({ showPanel: showFullPanel, showAttach: showAttachPanel, clickedAttach: clickedAttach, panelId: thisID, panelItem: panelItem, lastPanelId: lastPanelId, panelAttachments: this.state.lastAttachId === thisID ? this.state.panelAttachments : [], }); } } } _getItemFromId(items, key, val) { let panelItem = null; let showIndex = doesObjectExistInArray(this.props.items, key, val, false); if (showIndex !== false) { panelItem = this.props.items[showIndex]; // console.log('showPanelPropsItem', panelItem ); } return panelItem; } /*** * d888888b .d88b. d888b d888b db d88888b .d8888. * `~~88~~' .8P Y8. 88' Y8b 88' Y8b 88 88' 88' YP * 88 88 88 88 88 88 88ooooo `8bo. * 88 88 88 88 ooo 88 ooo 88 88~~~~~ `Y8b. * 88 `8b d8' 88. ~8~ 88. ~8~ 88booo. 88. db 8D * YP `Y88P' Y888P Y888P Y88888P Y88888P `8888Y' * * */ getPageToggles() { let togRefinerCounts = { //label: <span style={{ color: 'red', fontWeight: 900}}>Rails Off!</span>, label: React.createElement("span", null, "Panel width"), key: 'togggleWidth', _onChange: this.updatePanelWidth.bind(this), checked: this.state.panelWidth === PanelType.medium ? false : true, onText: 'Wide', offText: 'Medium', className: '', styles: '', }; let theseToggles = []; theseToggles.push(togRefinerCounts); let pageToggles = { toggles: theseToggles, childGap: 10, vertical: false, hAlign: 'end', vAlign: 'start', rootStyle: { width: 100, paddingTop: 0, paddingRight: 0, }, //This defines the styles on each toggle }; return pageToggles; } updatePanelWidth() { this.setState({