Skip to content

Commit

Permalink
detail list grid package updates
Browse files Browse the repository at this point in the history
  • Loading branch information
rwilson504 committed Dec 10, 2024
1 parent af05597 commit ebe23d8
Show file tree
Hide file tree
Showing 6 changed files with 8,304 additions and 5,152 deletions.
27 changes: 27 additions & 0 deletions DetailListGrid/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"env": {
"browser": true,
"es2020": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:promise/recommended"
],
"globals": {
"ComponentFramework": true
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"plugins": [
"@microsoft/power-apps",
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-empty-object-type": "off"
}
}
60 changes: 34 additions & 26 deletions DetailListGrid/DetailListGrid/DetailListGridControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const DetailListGridControl: React.FC<IProps> = (props) => {

// Set the isDataLoaded state based upon the paging totalRecordCount
React.useEffect(() => {
var dataSet = props.pcfContext.parameters.sampleDataSet;
const dataSet = props.pcfContext.parameters.sampleDataSet;
if (dataSet.loading || props.isModelApp) return;
setIsDataLoaded(dataSet.paging.totalResultCount !== -1);
},
Expand Down Expand Up @@ -74,9 +74,9 @@ export const DetailListGridControl: React.FC<IProps> = (props) => {
// this will allow us to utilize the ribbon buttons since they need
// that data set in order to do things such as delete/deactivate/activate/ect..
const _setSelectedItemsOnDataSet = () => {
let selectedKeys = [];
let selections = _selection.getSelection();
for (let selection of selections)
const selectedKeys = [];
const selections = _selection.getSelection();
for (const selection of selections)
{
selectedKeys.push(selection.key as string);
}
Expand All @@ -94,6 +94,7 @@ export const DetailListGridControl: React.FC<IProps> = (props) => {
}

// Reset the items and columns to match the state.
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
setItems(copyAndSort(items, column?.fieldName!, props.pcfContext, isSortedDescending));
setColumns(
columns.map(col => {
Expand Down Expand Up @@ -166,26 +167,28 @@ export const DetailListGridControl: React.FC<IProps> = (props) => {
};

// navigates to the record when user clicks the link in the grid.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const navigate = (item: any, linkReference: string | undefined, pcfContext: ComponentFramework.Context<IInputs>) => {
pcfContext.parameters.sampleDataSet.openDatasetItem(item[linkReference + "_ref"])
};

// get the items from the dataset
const getItems = (columns: IColumn[], pcfContext: ComponentFramework.Context<IInputs>) => {
let dataSet = pcfContext.parameters.sampleDataSet;
const dataSet = pcfContext.parameters.sampleDataSet;

var resultSet = dataSet.sortedRecordIds.map(function (key) {
var record = dataSet.records[key];
var newRecord: any = {
const resultSet = dataSet.sortedRecordIds.map(function (key) {
const record = dataSet.records[key];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const newRecord: any = {
key: record.getRecordId()
};

for (var column of columns)
for (const column of columns)
{
newRecord[column.key] = record.getFormattedValue(column.key);
if (isEntityReference(record.getValue(column.key)))
{
var ref = record.getValue(column.key) as ComponentFramework.EntityReference;
const ref = record.getValue(column.key) as ComponentFramework.EntityReference;
newRecord[column.key + '_ref'] = ref;
}
else if(column.data.isPrimary)
Expand All @@ -202,13 +205,13 @@ const getItems = (columns: IColumn[], pcfContext: ComponentFramework.Context<IIn

// get the columns from the dataset
const getColumns = (pcfContext: ComponentFramework.Context<IInputs>) : IColumn[] => {
let dataSet = pcfContext.parameters.sampleDataSet;
let iColumns: IColumn[] = [];
const dataSet = pcfContext.parameters.sampleDataSet;
const iColumns: IColumn[] = [];

let columnWidthDistribution = getColumnWidthDistribution(pcfContext);
const columnWidthDistribution = getColumnWidthDistribution(pcfContext);

for (var column of dataSet.columns){
let iColumn: IColumn = {
for (const column of dataSet.columns){
const iColumn: IColumn = {
key: column.name,
name: column.displayName,
fieldName: column.alias,
Expand All @@ -226,23 +229,26 @@ const getColumns = (pcfContext: ComponentFramework.Context<IInputs>) : IColumn[]
//create links for primary field and entity reference.
if (column.dataType.startsWith('Lookup.') || column.isPrimary)
{
// eslint-disable-next-line @typescript-eslint/no-explicit-any
iColumn.onRender = (item: any, index: number | undefined, column: IColumn | undefined)=> (
<Link key={item.key} onClick={() => navigate(item, column!.fieldName, pcfContext) }>{item[column!.fieldName!]}</Link>
);
}
else if(column.dataType === 'SingleLine.Email'){
// eslint-disable-next-line @typescript-eslint/no-explicit-any
iColumn.onRender = (item: any, index: number | undefined, column: IColumn | undefined)=> (
<Link href={`mailto:${item[column!.fieldName!]}`} >{item[column!.fieldName!]}</Link>
);
}
else if(column.dataType === 'SingleLine.Phone'){
// eslint-disable-next-line @typescript-eslint/no-explicit-any
iColumn.onRender = (item: any, index: number | undefined, column: IColumn | undefined)=> (
<Link href={`skype:${item[column!.fieldName!]}?call`} >{item[column!.fieldName!]}</Link>
);
}

//set sorting information
let isSorted = dataSet?.sorting?.findIndex(s => s.name === column.name) !== -1 || false
const isSorted = dataSet?.sorting?.findIndex(s => s.name === column.name) !== -1 || false
iColumn.isSorted = isSorted;
if (isSorted){
iColumn.isSortedDescending = dataSet?.sorting?.find(s => s.name === column.name)?.sortDirection === 1 || false;
Expand All @@ -255,11 +261,11 @@ const getColumns = (pcfContext: ComponentFramework.Context<IInputs>) : IColumn[]

const getColumnWidthDistribution = (pcfContext: ComponentFramework.Context<IInputs>): IColumnWidth[] => {

let widthDistribution: IColumnWidth[] = [];
let columnsOnView = pcfContext.parameters.sampleDataSet.columns;
const widthDistribution: IColumnWidth[] = [];
const columnsOnView = pcfContext.parameters.sampleDataSet.columns;

// Considering need to remove border & padding length
let totalWidth:number = pcfContext.mode.allocatedWidth - 250;
const totalWidth:number = pcfContext.mode.allocatedWidth - 250;
//console.log(`new total width: ${totalWidth}`);
let widthSum = 0;

Expand All @@ -272,7 +278,7 @@ const getColumnWidthDistribution = (pcfContext: ComponentFramework.Context<IInpu
columnsOnView.forEach(function (item, index) {
let widthPerCell = 0;
if (index !== columnsOnView.length - 1) {
let cellWidth = Math.round((item.visualSizeFactor / widthSum) * totalWidth);
const cellWidth = Math.round((item.visualSizeFactor / widthSum) * totalWidth);
remainWidth = remainWidth - cellWidth;
widthPerCell = cellWidth;
}
Expand All @@ -288,13 +294,13 @@ const getColumnWidthDistribution = (pcfContext: ComponentFramework.Context<IInpu

// Updates the column widths based upon the current side of the control on the form.
const updateColumnWidths = (columns: IColumn[], pcfContext: ComponentFramework.Context<IInputs>) : IColumn[] => {
let columnWidthDistribution = getColumnWidthDistribution(pcfContext);
let currentColumns = columns;
const columnWidthDistribution = getColumnWidthDistribution(pcfContext);
const currentColumns = columns;

//make sure to use map here which returns a new array, otherwise the state/grid will not update.
return currentColumns.map(col => {

var newMaxWidth = columnWidthDistribution.find(x => x.name === col.fieldName);
const newMaxWidth = columnWidthDistribution.find(x => x.name === col.fieldName);
if (newMaxWidth) col.maxWidth = newMaxWidth.width;

return col;
Expand All @@ -303,8 +309,9 @@ const updateColumnWidths = (columns: IColumn[], pcfContext: ComponentFramework.C

//sort the items in the grid.
const copyAndSort = <T, >(items: T[], columnKey: string, pcfContext: ComponentFramework.Context<IInputs>, isSortedDescending?: boolean): T[] => {
let key = columnKey as keyof T;
let sortedItems = items.slice(0);
const key = columnKey as keyof T;
const sortedItems = items.slice(0);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
sortedItems.sort((a: T, b: T) => (a[key] || '' as any).toString().localeCompare((b[key] || '' as any).toString(), getUserLanguage(pcfContext), { numeric: true }));

if (isSortedDescending) {
Expand All @@ -315,11 +322,12 @@ const copyAndSort = <T, >(items: T[], columnKey: string, pcfContext: ComponentFr
}

const getUserLanguage = (pcfContext: ComponentFramework.Context<IInputs>): string => {
var language = lcid.from(pcfContext.userSettings.languageId);
const language = lcid.from(pcfContext.userSettings.languageId);
return language.substring(0, language.indexOf('_'));
}

// determine if object is an entity reference.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isEntityReference = (obj: any): obj is ComponentFramework.EntityReference => {
return typeof obj?.etn === 'string';
}
10 changes: 6 additions & 4 deletions DetailListGrid/DetailListGrid/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class DetailListGrid implements ComponentFramework.StandardControl<IInput

this._container = container;
this._context = context;
// eslint-disable-next-line no-prototype-builtins
this._isModelApp = window.hasOwnProperty('getGlobalContextObject');
this._dataSetVersion = 0;

Expand Down Expand Up @@ -63,7 +64,8 @@ export class DetailListGrid implements ComponentFramework.StandardControl<IInput
// sets the height based upon the rowSpan which is there but not included in the Mode interace when
// the control is a subgrid.
// Then multiple by 1.5 em which is what MS uses per row.
let rowspan = (this._context.mode as any).rowSpan;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const rowspan = (this._context.mode as any).rowSpan;
if (rowspan) this._detailList.style.height = `${(rowspan * 1.5).toString()}em`;
}

Expand All @@ -80,7 +82,7 @@ export class DetailListGrid implements ComponentFramework.StandardControl<IInput
*/
public updateView(context: ComponentFramework.Context<IInputs>): void
{
var dataSet = context.parameters.sampleDataSet;
const dataSet = context.parameters.sampleDataSet;

if (dataSet.loading) return;

Expand All @@ -93,8 +95,8 @@ export class DetailListGrid implements ComponentFramework.StandardControl<IInput
//Setting the page size in a Canvas app works on the first load of the component. If you navigate
// away from the page on which the component is located though the paging get reset to 25 when you
// navigate back. In order to fix this we need to reset the paging to the count of the records that
// will come back and do a reset on the paging. I beleive this is all due to a MS bug.
//@ts-ignore
// will come back and do a reset on the paging. I believe this is all due to a MS bug.

//console.log(`TS: updateView, dataSet.paging.pageSize ${dataSet.paging.pageSize}`);
//console.log(`TS: updateView, dataSet.paging.totalResultCount ${dataSet.paging.totalResultCount}`)
dataSet.paging.setPageSize(dataSet.paging.totalResultCount);
Expand Down
2 changes: 2 additions & 0 deletions DetailListGrid/featureconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
Loading

0 comments on commit ebe23d8

Please sign in to comment.