Skip to content

Commit fc32c48

Browse files
committed
Added comments and codetours
1 parent 486c02b commit fc32c48

File tree

3 files changed

+186
-11
lines changed

3 files changed

+186
-11
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
{
2+
"title": "React-Enhanced-PowerApps",
3+
"steps": [
4+
{
5+
"title": "Introduction",
6+
"description": "Before you can build this web part, you need to install all the dependencies by using the command-line and running:\r\n\r\n>> npm install\r\n",
7+
"file": "README.md",
8+
"line": 49
9+
},
10+
{
11+
"file": "src/webparts/enhancedPowerApps/components/EnhancedPowerApps.tsx",
12+
"line": 45,
13+
"description": "## Passing theme values to Power Apps\r\n\r\nWe embed Power Apps by using an `IFRAME` which points to the app's web view.\r\n\r\nPower Apps support using query string parameters, so we build a URL with a query string parameter for each theme color name that we selected in the web part's properties.",
14+
"selection": {
15+
"start": {
16+
"line": 45,
17+
"character": 5
18+
},
19+
"end": {
20+
"line": 58,
21+
"character": 6
22+
}
23+
}
24+
},
25+
{
26+
"file": "src/webparts/enhancedPowerApps/components/EnhancedPowerApps.tsx",
27+
"line": 78,
28+
"description": "## Rendering the application\r\n\r\nJust like the out-of-the-box Power Apps web part, we use an IFRAME to embed Power Apps.",
29+
"selection": {
30+
"start": {
31+
"line": 78,
32+
"character": 8
33+
},
34+
"end": {
35+
"line": 80,
36+
"character": 19
37+
}
38+
}
39+
},
40+
{
41+
"file": "src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.ts",
42+
"line": 279,
43+
"description": "## Providing dynamic property metadata\r\n\r\nWhen SharePoint needs to query a web part to see what kinds of dynamic properties it will access, it calls the web part's `propertiesMetadata` property.\r\n\r\nIt returns a list of dynamic property names and the type of data they accept.\r\n\r\nIn this case, `dynamicProp` accepts `string`.",
44+
"selection": {
45+
"start": {
46+
"line": 279,
47+
"character": 3
48+
},
49+
"end": {
50+
"line": 287,
51+
"character": 4
52+
}
53+
}
54+
},
55+
{
56+
"file": "src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.ts",
57+
"line": 88,
58+
"description": "## Resizing proportionally\r\n\r\nWhen the web part renders, we get the web part's `clientWidth` so we can pass it to the IFRAME later. \r\n\r\nWe also calculate the desired height by using the selected aspect ratio (e.g.: 16:9) and multiplying with the width of the web part.",
59+
"selection": {
60+
"start": {
61+
"line": 88,
62+
"character": 5
63+
},
64+
"end": {
65+
"line": 120,
66+
"character": 48
67+
}
68+
}
69+
},
70+
{
71+
"file": "src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.ts",
72+
"line": 53,
73+
"description": "## Defining dynamic properties\r\n\r\nTo add support for dynamic properties, we add a `DynamicProperty<string>` property to the web part's properties. This is where we'll store the dynamic values when they're available.\r\n\r\nTo keep things simple, we treat every dynamic value as a string, because they'll be passed to the Power Apps IFRAME via query string parameters.",
74+
"selection": {
75+
"start": {
76+
"line": 53,
77+
"character": 3
78+
},
79+
"end": {
80+
"line": 53,
81+
"character": 40
82+
}
83+
}
84+
},
85+
{
86+
"file": "src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.ts",
87+
"line": 239,
88+
"description": "## Conditionally adding dynamic property fields\r\n\r\nIf the user selects to use dynamic properties (`this.properties.useDynamicProp === true`) we add a `PropertyPaneDynamicFieldSet` for the `PropertyPaneDynamicField` bound to the web part's `dynamicProp` property.",
89+
"selection": {
90+
"start": {
91+
"line": 239,
92+
"character": 17
93+
},
94+
"end": {
95+
"line": 246,
96+
"character": 20
97+
}
98+
}
99+
},
100+
{
101+
"file": "src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.ts",
102+
"line": 69,
103+
"description": "## Adding theme support\r\n\r\nThis code adds support for theming. \r\n\r\nIt gets the current theme (and stores it to `_themeVariant`) which will be used later to pass the theme variant to the components.\r\n\r\nIt also binds to the `themeChangedEvent`, which will notify the web part when themes change or the section background color changes.",
104+
"selection": {
105+
"start": {
106+
"line": 69,
107+
"character": 3
108+
},
109+
"end": {
110+
"line": 80,
111+
"character": 4
112+
}
113+
}
114+
},
115+
{
116+
"file": "src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.ts",
117+
"line": 298,
118+
"description": "## Handling theme changed events\r\n\r\nWhen the theme changes, we store the new theme variant to `_themeVariant` and cause the web part to re-render -- thus refreshing the web part.",
119+
"selection": {
120+
"start": {
121+
"line": 298,
122+
"character": 3
123+
},
124+
"end": {
125+
"line": 301,
126+
"character": 4
127+
}
128+
}
129+
},
130+
{
131+
"file": "src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.ts",
132+
"line": 126,
133+
"description": "## Passing the theme variant\r\n\r\nWhen rendering the web part, we pass the theme variant we retrieved earlier so that we can forward the theme colors to Power Apps.",
134+
"selection": {
135+
"start": {
136+
"line": 126,
137+
"character": 9
138+
},
139+
"end": {
140+
"line": 126,
141+
"character": 42
142+
}
143+
}
144+
},
145+
{
146+
"file": "src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.manifest.json",
147+
"line": 12,
148+
"description": "## Adding theme support in the manifest\r\n\r\nFor web parts to adapt to changing themes, the manifest needs to add `\"supportsThemeVariants\": true`; otherwise, theme changes will not fire.",
149+
"selection": {
150+
"start": {
151+
"line": 12,
152+
"character": 3
153+
},
154+
"end": {
155+
"line": 12,
156+
"character": 33
157+
}
158+
}
159+
},
160+
{
161+
"file": "src/webparts/enhancedPowerApps/ThemeVariantSlots.ts",
162+
"line": 1,
163+
"description": "## Dropdown theme color names\r\n\r\nTo make it easier to display the list of theme colors, we generated a static list of drop down options. I'm sure that there is a way to enumerate theme variant slots dynamically, but I wanted to keep the code simple."
164+
}
165+
]
166+
}

src/webparts/enhancedPowerApps/EnhancedPowerAppsWebPart.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,14 @@ export default class EnhancedPowerAppsWebPart extends BaseClientSideWebPart<IEnh
8080
}
8181

8282
public render(): void {
83-
const { clientWidth } = this.domElement;
83+
// Context variables and dynamic properties
8484
const dynamicProp: string | undefined = this.properties.dynamicProp.tryGetValue();
8585
const locale: string = this.context.pageContext.cultureInfo.currentCultureName;
8686

87+
// Get the client width. This is how we'll calculate the aspect ratio and resize the iframe
88+
const { clientWidth } = this.domElement;
89+
90+
// Get the aspect width and height based on aspect ratio for the web part
8791
let aspectWidth: number;
8892
let aspectHeight: number;
8993
switch(this.properties.aspectratio) {
@@ -104,10 +108,13 @@ export default class EnhancedPowerAppsWebPart extends BaseClientSideWebPart<IEnh
104108
aspectHeight = 3;
105109
break;
106110
case "Custom":
111+
// Custom aspects just use the width and height properties
107112
aspectWidth = this.properties.width;
108113
aspectHeight = this.properties.height;
109114
}
110115

116+
// If we're using fixed height, we pass the height and don't resize, otherwise we
117+
// calculate the height based on the web part's width and selected aspect ratio
111118
const clientHeight: number = this.properties.layout === 'FixedHeight' ?
112119
this.properties.height :
113120
clientWidth * (aspectHeight/aspectWidth);

src/webparts/enhancedPowerApps/components/EnhancedPowerApps.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@ export default class EnhancedPowerApps extends React.Component<IEnhancedPowerApp
2929
height,
3030
width
3131
} = this.props;
32+
33+
// The only thing we need for this web part to be configured is an app link or app id
3234
const needConfiguration: boolean = !appWebLink;
3335

3436
const { semanticColors }: IReadonlyTheme = themeVariant;
3537

38+
// If we passed a dynamic property, add it as a query string parameter
3639
const dynamicPropValue: string = useDynamicProp && dynamicProp !== undefined ? `&${encodeURIComponent(dynamicPropName)}=${encodeURIComponent(dynamicProp)}`:'';
3740

3841
// We can take an app id or a full link. We'll assume (for now) that people are passing a valid app URL
@@ -43,16 +46,15 @@ export default class EnhancedPowerApps extends React.Component<IEnhancedPowerApp
4346
let themeParams: string = "";
4447

4548
if (themeValues && themeValues.length > 0) {
46-
themeValues.forEach((themeValue: string) => {
47-
try {
48-
49-
const themeColor: string = semanticColors[themeValue];
50-
themeParams = themeParams + `&${themeValue}=${encodeURIComponent(themeColor)}`;
51-
} catch (e) {
52-
console.log(e);
53-
}
54-
55-
});
49+
themeValues.forEach((themeValue: string) => {
50+
try {
51+
52+
const themeColor: string = semanticColors[themeValue];
53+
themeParams = themeParams + `&${themeValue}=${encodeURIComponent(themeColor)}`;
54+
} catch (e) {
55+
console.log(e);
56+
}
57+
});
5658
}
5759

5860

0 commit comments

Comments
 (0)