Skip to content

Commit 89c48fd

Browse files
authored
Merge branch 'main' into 1460-no-language-defined-in-example-pages
2 parents ac3573b + 67ea4e2 commit 89c48fd

File tree

12 files changed

+286
-38
lines changed

12 files changed

+286
-38
lines changed

build-power-apps/button/DBButton/strings/DBButton.1031.resx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,11 @@
130130
<value>Text ausblenden</value>
131131
</data>
132132
<data name="width_Display_Key" xml:space="preserve">
133-
<value>Icon Breite</value>
133+
<value>Button Breite</value>
134134
</data>
135135
<data name="clicked_Display_Key" xml:space="preserve">
136136
<value>Clicked</value>
137137
</data>
138-
<data name="componentHeight_Display_Key" xml:space="preserve">
139-
<value>Höhe</value>
140-
</data>
141-
<data name="componentWidth_Display_Key" xml:space="preserve">
142-
<value>Breite</value>
143-
</data>
144138
<data name="DBButton_Display_Key" xml:space="preserve">
145139
<value>DB Button</value>
146140
</data>

build-power-apps/button/DBButton/strings/DBButton.1033.resx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,11 @@
130130
<value>Hide text</value>
131131
</data>
132132
<data name="width_Display_Key" xml:space="preserve">
133-
<value>Icon width</value>
133+
<value>Button width</value>
134134
</data>
135135
<data name="clicked_Display_Key" xml:space="preserve">
136136
<value>Clicked</value>
137137
</data>
138-
<data name="componentHeight_Display_Key" xml:space="preserve">
139-
<value>Height</value>
140-
</data>
141-
<data name="componentWidth_Display_Key" xml:space="preserve">
142-
<value>Width</value>
143-
</data>
144138
<data name="DBButton_Display_Key" xml:space="preserve">
145139
<value>DB Button</value>
146140
</data>

packages/components/_templates/power-apps/new/comp-xml.ejs.t

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ force: true
1010
control-type="standard">
1111

1212
<% if(locals.props){ locals.props.forEach((prop)=>{ -%>
13-
<property name="<%= prop.name %>" display-name-key="<%= prop.name %>_Display_Key"
13+
<property name="<%= prop.powerAppsName || prop.name %>" display-name-key="<%= prop.name %>_Display_Key"
1414
1515
description-key="<%= prop.name %>_Desc_Key"
1616
@@ -359,11 +359,6 @@ force: true
359359
description-key="clicked_Desc_Key" of-type="TwoOptions" usage="bound" required="false"/>
360360
<% } -%>
361361

362-
<property name="componentHeight" display-name-key="componentHeight_Display_Key"
363-
description-key="componentHeight_Desc_Key" of-type="Decimal" usage="bound" required="false"/>
364-
<property name="componentWidth" display-name-key="componentWidth_Display_Key"
365-
description-key="componentWidth_Desc_Key" of-type="Decimal" usage="bound" required="false"/>
366-
367362
<resources>
368363
<code path="index.ts" order="1"/>
369364
<resx path="strings/DB<%= h.capitalize(name) %>.1031.resx" version="<%= version %>" />

packages/components/_templates/power-apps/new/index.ejs.t

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as React from "react";
99
import * as ReactDOM from "react-dom";
1010
import DB<%= h.capitalize(name) %>React from "./<%= name %>";
1111
import { DB<%= h.capitalize(name) %>Props } from "./model";
12+
import { initMutationObserver, startCustomControlProcess } from "./utils";
1213

1314
export class DB<%= h.capitalize(name) %>
1415
implements ComponentFramework.StandardControl<IInputs, IOutputs>
@@ -20,8 +21,9 @@ export class DB<%= h.capitalize(name) %>
2021
<% if(typeof hasOnClick !== 'undefined' && hasOnClick){ -%>
2122
private clicked: boolean;
2223
<% } -%>
23-
private componentHeight: number;
24-
private componentWidth: number;
24+
25+
private canvasWidthState = "<%= canvasWidth %>";
26+
private canvasHeightState = "<%= canvasHeight %>";
2527

2628
constructor() {
2729
}
@@ -40,18 +42,29 @@ export class DB<%= h.capitalize(name) %>
4042
<% if(locals.props && Object.keys(locals.props).length){ -%>
4143
if (currentPageContext) {
4244
<% locals.props.forEach((prop)=>{ -%>
43-
this.props.<%= prop.name %> = currentPageContext.<%= prop.name %>;
45+
this.props.<%= prop.name %> = currentPageContext.<%= prop.powerAppsName || prop.name %>;
4446
<% }) -%>
4547
}
4648
<% } -%>
49+
context.mode.trackContainerResize(true);
4750
this._notifyOutputChanged = notifyOutputChanged;
4851
this.overViewContainer = container;
49-
}
52+
this.overViewContainer.setAttribute(
53+
'data-canvas-height-state',
54+
this.canvasHeightState
55+
);
56+
this.overViewContainer.setAttribute(
57+
'data-canvas-width-state',
58+
this.canvasWidthState
59+
);
5060

61+
initMutationObserver();
62+
setTimeout(startCustomControlProcess, 500);
63+
}
5164

5265
public updateView(context: ComponentFramework.Context<IInputs>): void {
5366
<% if(locals.props){ locals.props.forEach((prop)=>{ -%>
54-
this.props.<%= prop.name %> = context.parameters.<%= prop.name %>.raw || undefined;
67+
this.props.<%= prop.name %> = context.parameters.<%= prop.powerAppsName || prop.name %>.raw || undefined;
5568
<% if(typeof prop.onChange !== 'undefined' && prop.onChange){ -%>
5669
this.props.onChange = (event:any)=> {
5770
this.props.<%= prop.name %> = event?.target?.["<%= prop.onChange %>"] as unknown;
@@ -82,17 +95,11 @@ export class DB<%= h.capitalize(name) %>
8295
shouldUpdate = true;
8396
}
8497
<% } -%>
85-
if (this.overViewContainer.offsetHeight !== this.componentHeight) {
86-
this.componentHeight = this.overViewContainer.offsetHeight;
87-
shouldUpdate = true;
88-
}
89-
if (this.overViewContainer.offsetWidth !== this.componentWidth) {
90-
this.componentWidth = this.overViewContainer.offsetWidth;
91-
shouldUpdate = true;
92-
}
9398
if (shouldUpdate) {
9499
this._notifyOutputChanged();
95100
}
101+
102+
startCustomControlProcess();
96103
}
97104
98105
public getOutputs(): IOutputs {
@@ -103,8 +110,6 @@ export class DB<%= h.capitalize(name) %>
103110
<% if(typeof hasOnClick !== 'undefined' && hasOnClick){ -%>
104111
clicked: this.clicked,
105112
<% } -%>
106-
componentHeight: this.overViewContainer.offsetHeight,
107-
componentWidth: this.overViewContainer.offsetWidth,
108113
};
109114
}
110115
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
---
2+
to: ../../output/power-apps/<%= name %>/DB<%= h.capitalize(name) %>/utils.ts
3+
force: true
4+
---
5+
const isDev = () => !!document.querySelector('[class="harness-root"]');
6+
const isProdEditor = () => document.querySelector('[class="studio web"]');
7+
const getControlSideBar = () =>
8+
document.querySelector(
9+
isDev() ? '[class="io-pane"]' : '[id="control-sidebar"]'
10+
);
11+
12+
export const initMutationObserver = async () => {
13+
if (isDev() || isProdEditor()) {
14+
let initCanvasTries = 0;
15+
let element: Element | null = null;
16+
while (!element && initCanvasTries < 5) {
17+
element = getControlSideBar();
18+
initCanvasTries++;
19+
if (element) {
20+
await new Promise((resolve) => setTimeout(resolve, 200));
21+
}
22+
}
23+
24+
if (element && !element.hasAttribute('mutation-observer')) {
25+
const config = {
26+
childList: true,
27+
subtree: true
28+
};
29+
const callback = (mutationList: MutationRecord[]) => {
30+
// SideBar has a change try to find the canvasSize Elements
31+
startCustomControlProcess();
32+
};
33+
const observer = new MutationObserver(callback);
34+
observer.observe(element, config);
35+
element.setAttribute('mutation-observer', 'true');
36+
startCustomControlProcess();
37+
}
38+
}
39+
};
40+
41+
const isDBUIElementSelected = () => {
42+
const sideBarDBUIInputs =
43+
getControlSideBar()?.querySelectorAll('[id*="DBUI"]');
44+
const currentSelectedControlContent = document.getElementById(
45+
'currentSelectedControl'
46+
)?.textContent;
47+
48+
if (sideBarDBUIInputs && currentSelectedControlContent) {
49+
return (
50+
currentSelectedControlContent.includes('DBUI') &&
51+
sideBarDBUIInputs.length > 0
52+
);
53+
}
54+
55+
return false;
56+
};
57+
58+
export const startCustomControlProcess = () => {
59+
if (isDev() || isProdEditor()) {
60+
if (isDev() || isDBUIElementSelected()) {
61+
let customControl;
62+
63+
if (isDev()) {
64+
customControl = document.querySelector('[class*="customControl"]');
65+
} else {
66+
const selectedContainers = getSelectedContainers();
67+
if (selectedContainers?.length >= 2) {
68+
customControl = selectedContainers[0].querySelector(
69+
'[class*="customControl"]'
70+
);
71+
}
72+
}
73+
74+
if (customControl) {
75+
const canvasHeightState = customControl.getAttribute(
76+
'data-canvas-height-state'
77+
);
78+
const canvasWidthState = customControl.getAttribute(
79+
'data-canvas-width-state'
80+
);
81+
handleCanvasSize(
82+
customControl,
83+
canvasHeightState,
84+
canvasWidthState
85+
);
86+
}
87+
} else {
88+
const canvasSizeElements = getCanvasSizeElements();
89+
if (canvasSizeElements?.length === 2) {
90+
const canvasWidthElement = canvasSizeElements[0];
91+
const canvasHeightElement = canvasSizeElements[1];
92+
if (canvasHeightElement) {
93+
canvasHeightElement.disabled = false;
94+
}
95+
if (canvasWidthElement) {
96+
canvasWidthElement.disabled = false;
97+
}
98+
}
99+
}
100+
}
101+
};
102+
103+
const getReactEventHandlers = (element: any): any | undefined => {
104+
const keys = Object.keys(element);
105+
const foundEventHandlersKey = keys.find((key) =>
106+
key.includes('__reactEventHandlers')
107+
);
108+
if (foundEventHandlersKey) {
109+
return element[foundEventHandlersKey];
110+
}
111+
112+
return undefined;
113+
};
114+
115+
const getSelectedContainers = (): any => {
116+
const selectedContainer: any = document.querySelector(
117+
'[class*="selectedAdornersContainer"]'
118+
);
119+
120+
if (selectedContainer) {
121+
const foundEventHandlers = getReactEventHandlers(selectedContainer);
122+
if (foundEventHandlers) {
123+
const dataControlId = foundEventHandlers['data-control-id'];
124+
return document.querySelectorAll(
125+
`[data-control-id="${dataControlId}"]`
126+
);
127+
}
128+
}
129+
130+
return undefined;
131+
};
132+
133+
const changeCanvasSize = (element: any, size: number) => {
134+
const keys = Object.keys(element);
135+
if (keys) {
136+
if (isDev()) {
137+
const foundReactPropsKey = keys.find((key) =>
138+
key.includes('__reactProps')
139+
);
140+
if (foundReactPropsKey) {
141+
element[foundReactPropsKey].onChange({
142+
target: { value: (size + 1).toString() }
143+
});
144+
}
145+
} else {
146+
const foundEventHandlers = getReactEventHandlers(element);
147+
148+
if (foundEventHandlers) {
149+
foundEventHandlers.onBlur({
150+
currentTarget: { value: size.toString() }
151+
});
152+
}
153+
}
154+
}
155+
};
156+
157+
const getCanvasSizeElements = (): HTMLInputElement[] => {
158+
const devControlContainer = document.getElementById('control-dimensions');
159+
let inputs;
160+
if (devControlContainer) {
161+
inputs = Array.from(devControlContainer.getElementsByTagName('input'));
162+
} else {
163+
inputs = document.querySelectorAll('input[id*="SizeGroup"]');
164+
}
165+
166+
return inputs as HTMLInputElement[];
167+
};
168+
169+
const handleCanvasSize = (
170+
customControl: any,
171+
canvasHeightState: string,
172+
canvasWidthState: string
173+
): void => {
174+
const canvasSizeElements = getCanvasSizeElements();
175+
if (canvasSizeElements?.length === 2) {
176+
const canvasWidthElement = canvasSizeElements[0];
177+
const canvasHeightElement = canvasSizeElements[1];
178+
179+
if (canvasHeightElement) {
180+
if (canvasHeightState !== 'fixed') {
181+
canvasHeightElement.disabled = false;
182+
canvasHeightElement.type = 'number';
183+
// TODO: Add min size for this based on config
184+
customControl.style.height = '100%';
185+
} else {
186+
customControl.style.height = 'fit-content';
187+
changeCanvasSize(
188+
canvasHeightElement,
189+
customControl.offsetHeight
190+
);
191+
canvasHeightElement.disabled = true;
192+
//hideResizers(true);
193+
}
194+
}
195+
196+
if (canvasWidthElement) {
197+
const unchangeable =
198+
canvasWidthState === 'fixed' ||
199+
(canvasWidthState === 'dynamic' &&
200+
customControl.querySelector('[data-width="auto"]'));
201+
if (unchangeable) {
202+
customControl.style.width = 'fit-content';
203+
changeCanvasSize(canvasWidthElement, customControl.offsetWidth);
204+
canvasWidthElement.disabled = true;
205+
//hideResizers(false);
206+
} else {
207+
canvasWidthElement.disabled = false;
208+
canvasWidthElement.type = 'number';
209+
// TODO: Add min size for this based on config
210+
customControl.style.width = '100%';
211+
}
212+
}
213+
}
214+
};
215+
216+
/*const hideResizers = (isHeight: boolean) => {
217+
if (isProdEditor()) {
218+
const resizers = document.querySelectorAll("[class^='resizerCommon']");
219+
220+
if (resizers?.length === 8) {
221+
Array.from(resizers)
222+
.filter((_, index: number) => {
223+
if (isHeight) {
224+
return index !== 2 && index !== 3;
225+
} else {
226+
return index !== 0 && index !== 1;
227+
}
228+
})
229+
.forEach((resizer) => resizer.setAttribute('hidden', ''));
230+
}
231+
}
232+
};*/
233+
234+
export default { initMutationObserver, startCustomControlProcess };

0 commit comments

Comments
 (0)