Skip to content

Commit 0eead5b

Browse files
authored
Merge pull request #19 from brasov2de/feature/datatypes
Feature/datatypes
2 parents 09ae8a8 + 212dd8c commit 0eead5b

20 files changed

+3559
-1348
lines changed

.vscode/settings.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"workbench.colorCustomizations": {
3+
"activityBar.activeBackground": "#ab307e",
4+
"activityBar.activeBorder": "#25320e",
5+
"activityBar.background": "#ab307e",
6+
"activityBar.foreground": "#e7e7e7",
7+
"activityBar.inactiveForeground": "#e7e7e799",
8+
"activityBarBadge.background": "#25320e",
9+
"activityBarBadge.foreground": "#e7e7e7",
10+
"statusBar.background": "#832561",
11+
"statusBar.foreground": "#e7e7e7",
12+
"statusBarItem.hoverBackground": "#ab307e",
13+
"titleBar.activeBackground": "#832561",
14+
"titleBar.activeForeground": "#e7e7e7",
15+
"titleBar.inactiveBackground": "#83256199",
16+
"titleBar.inactiveForeground": "#e7e7e799",
17+
"sash.hoverBorder": "#ab307e",
18+
"statusBarItem.remoteBackground": "#832561",
19+
"statusBarItem.remoteForeground": "#e7e7e7"
20+
},
21+
"peacock.color": "#832561"
22+
}

ColorfulOptionsetGrid/App/ColorfulGrid.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22

3-
import {DetailsList, IColumn, DetailsListLayoutMode, IDetailsHeaderProps, SelectionMode} from '@fluentui/react/lib/DetailsList';
3+
import {DetailsList, IColumn, DetailsListLayoutMode, IDetailsHeaderProps, SelectionMode, ConstrainMode} from '@fluentui/react/lib/DetailsList';
44
import {mergeStyles, DefaultFontStyles } from '@fluentui/react/lib/Styling';
55
import {initializeIcons} from '@fluentui/react/lib/Icons';
66
import {ScrollablePane} from '@fluentui/react/lib/ScrollablePane';
@@ -84,7 +84,7 @@ export const ColorfulGrid = React.memo(function ColorfulGridApp({
8484
const isOptionSetRenderer : boolean = metadataAttributes?.has(column.original.name);
8585
const columnDefaultIcon = displayIconType==="NAME" ? defaultIconNames.get(column.original.name)??defaultIcon : defaultIcon;
8686
return {
87-
...getDefaultColumnSetup(column, dataset),
87+
...getDefaultColumnSetup(column, dataset),
8888
onRender: isOptionSetRenderer===true ? (item : any) => {
8989
return <ColorfulCell
9090
item={item}
@@ -112,6 +112,7 @@ export const ColorfulGrid = React.memo(function ColorfulGridApp({
112112
selectionPreservedOnEmptyClick={true}
113113
selectionMode={SelectionMode.multiple}
114114
layoutMode={DetailsListLayoutMode.justified}
115+
constrainMode={ConstrainMode.unconstrained}
115116
onItemInvoked={onItemInvoked}
116117
ariaLabelForSelectionColumn="Toggle selection"
117118
ariaLabelForSelectAllCheckbox="Toggle selection for all items"

ColorfulOptionsetGrid/App/Controls/ColorfulCell.tsx

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as React from 'react';
33
import { render } from 'react-dom';
44
import { IGridColumn } from '../Generic/Hooks/useColumns';
55
import { ISetupSchemaValue } from '../Utils/interfaces';
6+
import { ColorfulCellItem } from './ColorfulCellItem';
67

78
export interface IColorfulCellProps {
89
item: any;
@@ -14,37 +15,35 @@ export interface IColorfulCellProps {
1415
}
1516

1617
export const ColorfulCell = function ColorfulCell({item, column, metadataOptions, displayTextType, displayIconType, defaultIcon} : IColorfulCellProps) : JSX.Element{
17-
const currentOptionSetValue= item.raw.getValue(column.original.name) as number;
18-
let color = metadataOptions?.get(currentOptionSetValue?.toString() ?? "")?.color ?? "gray";
19-
if(color==="white"){
20-
color = "gray"
18+
19+
if(item.raw.getValue(column.original.name) ==null){
20+
return <div></div>;
2121
}
22-
const icon = metadataOptions?.get(currentOptionSetValue?.toString() ?? "")?.icon ?? defaultIcon;
23-
const iconColor = displayTextType==="BOX" ? "white" : color;
24-
const renderIcon = displayIconType!=="NONE" ? <Icon className="colorIcon" style={{color: iconColor , marginRight: "5px"}} iconName={icon} aria-hidden="true" /> : "";
25-
const style = {
26-
"BORDER" : {
27-
borderWidth: "1px",
28-
borderStyle: "solid",
29-
borderColor: color,
30-
color: color,
31-
borderRadius: "5px"
32-
},
33-
"BOX" : {
34-
backgroundColor: color==="white" ? "gray" : color, color: iconColor, borderRadius: "5px"
35-
},
36-
"SIMPLE" : {
37-
},
38-
"NOTEXT": {
39-
cursor: "pointer"
40-
}
41-
}[displayTextType];
42-
const content = item[column.original.name];
43-
const renderText = displayTextType!=="NOTEXT" ? <span className="cell">{content}</span> : ""
44-
return(<div className="ColorfulCell" style={style} title={content}>
45-
{renderIcon}
46-
{renderText}
47-
</div>);
22+
if(column.original.dataType==="MultiSelectOptionSet" || column.original.dataType==="MultiSelectPicklist"){
23+
const currentValues = (item.raw.getValue(column.original.name) as string ?? "").split(",");
24+
const currentDisplayNames = (item.raw.getFormattedValue(column.original.name) as string ?? "").split(";");
25+
return (<div className="ColorfulCell_MultiSelectOptionSet">
26+
{currentValues.map((currentValue, index) => {
27+
return (<ColorfulCellItem className='ColorfulCellItem'
28+
currentValue={parseInt(currentValue)}
29+
currentDisplayName={currentDisplayNames[index] ?? ""}
30+
defaultIcon={defaultIcon}
31+
displayIconType={displayIconType}
32+
displayTextType={displayTextType}
33+
metadataOptions={metadataOptions}
34+
/>)
35+
})}
36+
</div>)
37+
}
38+
const currentOptionSetValue= item.raw.getValue(column.original.name) as number;
39+
return(<ColorfulCellItem className='ColorfulCell'
40+
currentValue={currentOptionSetValue}
41+
currentDisplayName={item[column.original.name]}
42+
defaultIcon={defaultIcon}
43+
displayIconType={displayIconType}
44+
displayTextType={displayTextType}
45+
metadataOptions={metadataOptions}
46+
/>);
4847

4948

5049
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Icon } from '@fluentui/react/lib/Icon';
2+
import * as React from 'react';
3+
import { render } from 'react-dom';
4+
import { IGridColumn } from '../Generic/Hooks/useColumns';
5+
import { ISetupSchemaValue } from '../Utils/interfaces';
6+
7+
export interface IColorfulCellItemProps {
8+
currentValue ?: number;
9+
currentDisplayName ?: string;
10+
metadataOptions : Map<string, ISetupSchemaValue> | undefined;
11+
displayTextType: "SIMPLE" | "BOX" | "BORDER" | "NOTEXT";
12+
displayIconType : "NONE" | "NAME";//| "ENVIRONMENT";
13+
defaultIcon: string;
14+
className ?: string;
15+
}
16+
17+
export const ColorfulCellItem = function ColorfulCellItem({currentValue, currentDisplayName, metadataOptions, displayTextType, displayIconType, defaultIcon, className} : IColorfulCellItemProps) : JSX.Element{
18+
if(currentValue==null){
19+
return <div></div>;
20+
}
21+
let color = metadataOptions?.get(currentValue?.toString() ?? "")?.color ?? "gray";
22+
if(color==="white"){
23+
color = "gray"
24+
}
25+
const icon = metadataOptions?.get(currentValue?.toString() ?? "")?.icon ?? defaultIcon;
26+
const iconColor = displayTextType==="BOX" ? "white" : color;
27+
const renderIcon = displayIconType!=="NONE" ? <Icon className="colorIcon" style={{color: iconColor , marginRight: "5px"}} iconName={icon} aria-hidden="true" /> : "";
28+
const style = {
29+
"BORDER" : {
30+
borderWidth: "1px",
31+
borderStyle: "solid",
32+
borderColor: color,
33+
color: color,
34+
borderRadius: "5px"
35+
},
36+
"BOX" : {
37+
backgroundColor: color==="white" ? "gray" : color, color: iconColor, borderRadius: "5px"
38+
},
39+
"SIMPLE" : {
40+
},
41+
"NOTEXT": {
42+
cursor: "pointer"
43+
}
44+
}[displayTextType];
45+
const content = currentDisplayName;
46+
const renderText = displayTextType!=="NOTEXT" ? <span className="cell">{content}</span> : ""
47+
return(<div className={className} style={style} title={content}>
48+
{renderIcon}
49+
{renderText}
50+
</div>);
51+
52+
53+
};

ColorfulOptionsetGrid/App/Generic/Components/GridFooter.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ export const GridFooter = ({dataset, selectedCount} : IGridFooterProps) => {
2626
<Stack grow horizontal horizontalAlign="space-between" >
2727
<Stack.Item grow={1} align="center" >{firstItemNumber} - {lastItemNumber} of {totalRecords} ({selectedCount} selected)</Stack.Item>
2828
<Stack.Item grow={1} align="center" className="FooterRight">
29-
<IconButton className="FooterIcon" iconProps={{ iconName: "DoubleChevronLeft"}} onClick={moveToFirst} disabled={!dataset.paging.hasPreviousPage}/>
30-
<IconButton className="FooterIcon" iconProps={{ iconName: "ChevronLeft"}} onClick={movePrevious} disabled={!dataset.paging.hasPreviousPage}/>
29+
<IconButton className="FooterIcon" iconProps={{ iconName: "Rewind"}} onClick={moveToFirst} disabled={!dataset.paging.hasPreviousPage}/>
30+
<IconButton className="FooterIcon" iconProps={{ iconName: "Previous"}} onClick={movePrevious} disabled={!dataset.paging.hasPreviousPage}/>
3131
<span >Page {currentPage}</span>
32-
<IconButton className="FooterIcon" iconProps={{ iconName: "ChevronRight" }} onClick={moveNext} disabled={!dataset.paging.hasNextPage}/>
32+
<IconButton className="FooterIcon" iconProps={{ iconName: "Next" }} onClick={moveNext} disabled={!dataset.paging.hasNextPage}/>
3333
</Stack.Item>
3434
</Stack>
3535
</Stack.Item>

ColorfulOptionsetGrid/App/Generic/Components/GridHeader.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@ export function gridHeader(onColumnClick : Function) : ((props: IDetailsHeaderPr
1111
onColumnClick(name);
1212
}
1313
return ((props: IDetailsHeaderProps | undefined, defaultRender?: IRenderFunction<IDetailsHeaderProps>) => (
14+
props && defaultRender ?
1415
<Sticky stickyPosition={StickyPositionType.Header} isScrollSynced={true} >
1516
{defaultRender!({...props!, onColumnClick : onColumnHeaderClick })}
16-
</Sticky>)
17+
</Sticky>
18+
: <></>
19+
)
1720
);
1821
}
1922

ColorfulOptionsetGrid/App/Generic/Hooks/useColumns.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ColumnActionsMode } from '@fluentui/react';
12
import * as React from 'react';
23
type DataSet = ComponentFramework.PropertyTypes.DataSet;
34
import DataSetInterfaces = ComponentFramework.PropertyHelper.DataSetApi;
@@ -50,6 +51,7 @@ function parseColumns(originalColumns: ComponentFramework.PropertyHelper.DataSet
5051
features: {
5152
width : width,
5253
isVisible : !column.isHidden===true,
54+
isSortable: column.dataType!="MultiSelectPicklist",
5355
order: column.order===-1 ? 100 : column.order
5456
},
5557
minWidth:0,
@@ -96,7 +98,10 @@ export const useColumns = (dataset: DataSet, availableWidth?: number, columnWidt
9698
const [sorting, setSorting] = React.useState<DataSetInterfaces.SortStatus[]>(dataset.sorting);
9799

98100
function onColumnClick(columnClicked : string){
99-
const oldSorting = (sorting || []).find((sort) => sort.name===columnClicked);
101+
const oldSorting = (sorting || []).find((sort) => sort.name===columnClicked);
102+
if(dataset.columns.find((column) => column.name === columnClicked)?.dataType==="MultiSelectPicklist"){
103+
return; //This column is not sortabke
104+
}
100105
const newValue : DataSetInterfaces.SortStatus = {
101106
name: columnClicked,
102107
sortDirection : oldSorting!= null ? (oldSorting.sortDirection === 0 ? 1 : 0) : 0 //0 = ascendinf

ColorfulOptionsetGrid/App/Hooks/useConfig.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const useConfig= (dataset: DataSet, defaultIcon: string, utils: Component
4141
setConfigs(myConfigs);
4242
const myOptionSetColumns = customizedColumnsArray.length >0 //found customized, or take all optionset columns otherwise
4343
? customizedColumnsArray.map((setup) => setup.column?.name ?? "")
44-
: dataset.columns.filter((column) => column.dataType==="OptionSet").map((column) => column.name);
44+
: dataset.columns.filter((column) => column.dataType==="OptionSet" || column.dataType==="TwoOptions" || column.dataType==="MultiSelectOptionSet" || column.dataType==="MultiSelectPicklist").map((column) => column.name);
4545
setOptionSetColumns(myOptionSetColumns);
4646
getAttributes(dataset.getTargetEntityType(), myOptionSetColumns, utils , new Map(myConfigs))
4747
.then(setMetadataAttributes);

ColorfulOptionsetGrid/ControlManifest.Input.xml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22
<manifest>
33
<control namespace="ORBIS" constructor="ColorfulOptionsetGrid" version="0.0.16" display-name-key="ORBIS_ColorfulOptionsetGrid" description-key="ORBIS_ColorfulOptionsetGrid_Description" control-type="standard" preview-image="css/imgs/Preview.png">
44
<!-- dataset node represents a set of entity records on CDS; allow more than one datasets -->
5+
<type-group name="colorfulTypes">
6+
<type>OptionSet</type>
7+
<type>TwoOptions</type>
8+
<type>MultiSelectOptionSet</type>
9+
</type-group>
510
<data-set name="dataset" display-name-key="Dataset" cds-data-set-options="displayCommandBar:true;displayViewSelector:true;displayquickfind:true">
611
<!-- 'property-set' node represents a unique, configurable property that each record in the dataset must provide. -->
7-
<property-set name="optionset1" display-name-key="Optionset 1" description-key="Property_Desc_Key" of-type="OptionSet" usage="bound" required="false" />
8-
<property-set name="optionset2" display-name-key="Optionset 2" description-key="Property_Desc_Key" of-type="OptionSet" usage="bound" required="false" />
9-
<property-set name="optionset3" display-name-key="Optionset 3" description-key="Property_Desc_Key" of-type="OptionSet" usage="bound" required="false" />
12+
<property-set name="optionset1" display-name-key="Optionset 1" description-key="Property_Desc_Key" of-type-group="colorfulTypes" usage="bound" required="false" />
13+
<property-set name="optionset2" display-name-key="Optionset 2" description-key="Property_Desc_Key" of-type-group="colorfulTypes" usage="bound" required="false" />
14+
<property-set name="optionset3" display-name-key="Optionset 3" description-key="Property_Desc_Key" of-type-group="colorfulTypes" usage="bound" required="false" />
1015
<!-- UNCOMMENT TO ADD PROPERTY-SET NODE
1116
<property-set name="samplePropertySet" display-name-key="Property_Display_Key" description-key="Property_Desc_Key" of-type="SingleLine.Text" usage="bound" required="true" />
1217
-->

ColorfulOptionsetGrid/css/ColorfulOptionSetGrid.css

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
width: 100%;
33
position: relative;
44
min-height: 200px ;
5+
font-family: "Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
6+
-webkit-font-smoothing: antialiased;
57
}
68

79
.ORBIS\.ColorfulOptionsetGrid .gridContainer{
@@ -17,7 +19,8 @@
1719
padding-top: 3px;
1820
padding-left: 4px;
1921
padding-bottom: 3px;
20-
height:20px;
22+
padding-right: 4px;
23+
height:20px;
2124
/* display: inline;*/
2225
font-family: 'SegoeUI', 'Segoe UI';
2326
/* font-size: medium;
@@ -26,6 +29,23 @@
2629
padding-top: 3px;
2730
padding-bottom: 3px; */
2831
}
32+
33+
.ORBIS\.ColorfulOptionsetGrid .ColorfulCellItem{
34+
overflow: hidden;
35+
padding-top: 3px;
36+
padding-left: 4px;
37+
padding-bottom: 3px;
38+
padding-right: 4px;
39+
height:20px;
40+
margin-left: 4px;
41+
margin-top: 2px;
42+
font-family: 'SegoeUI', 'Segoe UI';
43+
}
44+
45+
.ORBIS\.ColorfulOptionsetGrid .ColorfulCell_MultiSelectOptionSet{
46+
display: flex;
47+
flex-wrap: wrap;
48+
}
2949

3050
.ORBIS\.ColorfulOptionsetGrid .Footer{
3151
height: 32px;
@@ -37,16 +57,27 @@
3757
border-top: 1px solid #edebe9;
3858
}
3959

60+
.ORBIS\.ColorfulOptionsetGrid .Footer span,
61+
.ORBIS\.ColorfulOptionsetGrid .Footer div{
62+
font-size: 12px;
63+
font-weight: 400;
64+
color: rgb(50, 49, 48);
65+
}
66+
4067
.ORBIS\.ColorfulOptionsetGrid .FooterRight{
4168
text-align: right;
4269
margin-right:10px;
4370
}
4471

4572
.ORBIS\.ColorfulOptionsetGrid .FooterIcon i{
46-
color: #333333;
47-
font-size: 11px;
73+
font-size: 12px;
74+
}
75+
.ORBIS\.ColorfulOptionsetGrid .FooterIcon span{
76+
color: #0078D4;
77+
}
78+
.ORBIS\.ColorfulOptionsetGrid .FooterIcon span:disabled{
79+
color: gray;
4880
}
49-
5081

5182

5283
.ORBIS\.ColorfulOptionsetGrid .colorIcon{
@@ -56,7 +87,7 @@
5687

5788
.ORBIS\.ColorfulOptionsetGrid div{
5889
font-weight: normal;
59-
font-size: 15px;
90+
font-size: 14px;
6091
vertical-align: baseline;
6192
}
6293

0 commit comments

Comments
 (0)