Skip to content

Commit 32dc483

Browse files
committed
First version of page transformation guidance
1 parent 6b16d08 commit 32dc483

7 files changed

+262
-13
lines changed

docs/toc.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,11 @@
12961296
items:
12971297
- name: Maximize use of modern lists and libraries
12981298
href: transform/modernize-userinterface-lists-and-libraries.md
1299+
- name: Transform classic pages to modern client-side pages
1300+
href: transform/modernize-userinterface-site-pages.md
1301+
items:
1302+
- name: Page transformation model
1303+
href: transform/modernize-userinterface-site-pages-model.md
12991304
- name: Modernize customizations
13001305
href: transform/modernize-customizations.md
13011306
- name: Modernize site branding
Loading
Loading

docs/transform/modernize-classic-sites.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,17 @@ However, if you navigate your site, you will notice that the following pages sti
3333
- Home page and all other site pages (wiki pages and/or web part pages)
3434
- List and library pages for certain lists and libraries
3535

36-
You probably already have the out-of-the-box modern user interface for lists and libraries enabled at the tenant level, so it makes sense to further maximize its use. SharePoint tries to show your lists and libraries by using the modern user interface, but you might have customizations or configurations that prevent this.
36+
You probably already have the out-of-the-box modern user interface for lists and libraries enabled at the tenant level, so it makes sense to further maximize its use. SharePoint tries to show your lists and libraries by using the modern user interface, but you might have customizations or configurations that prevent this.
3737

38-
To maximize the use of the modern user interface for your site pages and list and library pages, see [Modernize the user interface](modernize-userinterface.md).
38+
To maximize the use of the modern user interface for your site pages and list and library pages, see [Modernize the user interface](modernize-userinterface.md).
3939

4040
To learn more about how to unblock your lists and libraries when using the modern user interface, see [Maximize use of modern lists and libraries](modernize-userinterface-lists-and-libraries.md).
4141

4242
You will also need to modernize your customizations as explained in [Modernize customizations](modernize-customizations.md).
4343

4444
## Connect your site to an Office 365 group
4545

46-
Classic (team) sites are not connected to an Office 365 group, whereas modern team sites are. Connecting your site to an Office 365 group is an essential part of modernizing a site. The connection to an Office 365 group enables the site to consume other Office 365 services such as Teams, Planner, and Outlook.
46+
Classic (team) sites are not connected to an Office 365 group, whereas modern team sites are. Connecting your site to an Office 365 group is an essential part of modernizing a site. The connection to an Office 365 group enables the site to consume other Office 365 services such as Teams, Planner, and Outlook.
4747

4848
There are two options to connect your sites to an Office 365 group:
4949

@@ -52,12 +52,11 @@ There are two options to connect your sites to an Office 365 group:
5252

5353
For more information about connecting to an Office 365 group and performing a group-connection, see [Connect to an Office 365 group](modernize-connect-to-office365-group.md).
5454

55-
5655
## Switch to a modern tenant-scoped branding
5756

5857
Connecting your site to an Office 365 group not only gives you the benefits of a group-connected site, but also provides you with a new modern site home page. Depending on your needs, this new home page might be adequate, but you can choose to create your own modern home page. At that point, it makes sense to include other modernization tasks as well, such as switching to a modern site theme.
5958

60-
Using your company branding on SharePoint (team) sites is very common, and for classic sites you used one or more of the following components: site themes, alternate CSS, and master pages. However, alternate CSS and master pages are not compatible with the modern user interface, so you must evaluate whether these branding customizations are still relevant.
59+
Using your company branding on SharePoint (team) sites is very common, and for classic sites you used one or more of the following components: site themes, alternate CSS, and master pages. However, alternate CSS and master pages are not compatible with the modern user interface, so you must evaluate whether these branding customizations are still relevant.
6160

6261
While classic site themes are respected in a modern user interface, we now have tenant-controlled site theming, so switching over to that model will future-proof your modernized site.
6362

@@ -67,9 +66,7 @@ For more information, see [Modernize site branding](modernize-branding.md).
6766

6867
The final step in a site transformation is transforming your site pages. After you have completed the other steps, your site pages still appear in the classic user interface. Page transformation is not a simple process because there's no one-on-one mapping between the functionality offered by classic web parts and what's offered by the first-party client-side web parts on modern pages. Therefore, we recommend that you transform only the pages that are frequently used.
6968

70-
Information about transforming site pages is coming soon. In the meantime, you can find an overview at [Modernize the user interface](modernize-userinterface.md).
71-
72-
<!--For more information about page transformation, see [Transform classic pages to modern client-side pages](modernize-userinterface-site-pages.md).-->
69+
For more information about page transformation, see [Transform classic pages to modern client-side pages](modernize-userinterface-site-pages.md).
7370

7471
## See also
7572

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
---
2+
title: Understanding and configuring the page transformation model
3+
description: Provides detailed guidance on how to configure and use the page transformation model
4+
ms.date: 05/16/2018
5+
ms.prod: sharepoint
6+
---
7+
8+
# Understanding and configuring the page transformation model
9+
10+
The heart of the page transformation solution is the model that feeds the transformation: the model tells the engine which web part properties are important, allows you to manipulate these properties and dynamically choose a mapping for your web part.The page transformation model is expressed in XMl and comes with a schema that's used to validate the correctness of the model.
11+
12+
> [!IMPORTANT]
13+
> The SharePoint PnP Modernization framework is currently in preview. If you encounter issues please file a issue in the [PnP Tools GitHub issue list](https://github.com/SharePoint/PnP-Tools/issues).
14+
15+
## Page transformation model structure
16+
17+
When you open the page transformation model the following top level elements are present:
18+
19+
- **BaseWebPart**: this element contains the configuration that applies to all web parts e.g. it describes that the property "Title" will be fetched for all web parts. It's also the place that defines the default web part mapping: if a web part has no mapping defined the engine will fall back to this mapping to represent the web part on the target client side page.
20+
21+
- **AddOns**: as user of page transformation you might have the needed to apply custom logic to realize your needs e.g. you need to transform a given property in a way that it can work with your custom client side web part. The framework supports this by allowing you to add your assemblies with functions and selectors...simply defining them in the AddOn section and then referencing your custom functions and selectors later on by prefixing them with the given name will make the page transformation use your custom code.
22+
23+
- **WebParts**: this element contains information for each web part that you want to transform. For each web part you'll find a definition of the properties to use, the functions to execute on those properties, the possible mappings that define the target of the transformation combined with a selector that you dynamically select the needed mapping.
24+
25+
Upcoming chapters will provide more details.
26+
27+
## WebPart definition in the page transformation model
28+
29+
Let's analyze how a web part is configured in the page transformation model, which is best done based upon a simplified sample of the XsltListViewWebPart definition:
30+
31+
```Xml
32+
<!-- XsltListView web part -->
33+
<WebPart Type="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
34+
<Properties>
35+
<Property Name="XmlDefinitionLink" Type="string" />
36+
<Property Name="ListUrl" Type="string" />
37+
<Property Name="ListId" Type="guid" Functions="{ListWebRelativeUrl} = ListAddWebRelativeUrl({ListId}); {ListServerRelativeUrl} = ListAddServerRelativeUrl({ListId})"/>
38+
<Property Name="Direction" Type="string"/>
39+
<Property Name="GhostedXslLink" Type="string" />
40+
<Property Name="DisableViewSelectorMenu" Type="bool"/>
41+
<Property Name="XmlDefinition" Type="string" Functions="{ListViewId} = ListDetectUsedView({ListId},{XmlDefinition})"/>
42+
<Property Name="SelectParameters" Type="string"/>
43+
</Properties>
44+
<!-- This selector outputs: Library, List -->
45+
<Mappings Selector="ListSelectorListLibrary({ListId})">
46+
<Mapping Name="List" Default="true">
47+
<ClientSideText Text="You can map a source web part ({Title}) to a combination of client side controls :-)" Order="10" />
48+
<ClientSideWebPart Type="List" Order="20" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;false,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
49+
</Mapping>
50+
<Mapping Name="Library" Default="false">
51+
<ClientSideWebPart Type="List" Order="10" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;true,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
52+
</Mapping>
53+
</Mappings>
54+
</WebPart>
55+
```
56+
57+
### Properties element
58+
59+
For each web part the model defines the properties that might be useful to configure the target client side web part(s). If you miss certain properties you can simply extend them in the model. On some of the properties you'll see a Functions attribute: this attribute contains one or more functions (separate functions via a ;) that are executed when the source web part is mapped to a target client side web part. The anatomy of a function is the following:
60+
61+
```C#
62+
{Output} = FunctionName({Input1}, {Input2})
63+
```
64+
65+
A function can have one or more input values which can be:
66+
67+
- Properties defined on this web part (e.g. {ListId})
68+
- Properties defined on the base web part (e.g. {Title})
69+
- Properties that were the output of previous function executions (e.g. {ListWebRelativeUrl})
70+
- Default site scoped properties: {Host}, {Web}, {Site}, {WebId}, {SiteId}
71+
72+
When a function runs it's output will either be:
73+
74+
- A single string value: this value ({Output} in the presented model) will be added to the list of web part properties with name "Output" and value the value that was returned from running `FunctionName`.
75+
- A list of key/value pairs (Dictionary<string,string>): in this case each returned key/value pair is added to the list of web part properties
76+
77+
If the function does not define the output parameter then value of the web part property that defines the function will be overwritten with the function result.
78+
79+
Let's clarify with a sample:
80+
81+
```Xml
82+
<Property Name="ListId" Type="guid" Functions="FormatGuid({ListId})"/>
83+
```
84+
85+
Let's assume that the web part property originally contains a guid formatted like {AAFAD7D0-D57A-4BB1-8706-969A608C686B}. After `FormatGuid` has been executed the value will be set to the output of `FormatGuid` (e.g. a guid without brackets AAFAD7D0-D57A-4BB1-8706-969A608C686B).
86+
87+
If a function returns multiple values then each returned key/value pair that already exists as web part property overwrites that properties value.
88+
89+
### Mappings element
90+
91+
This element defines one or more possible target configurations for the given source web part. Since you can define multiple targets there needs to be a mechanism to determine which mapping to use:
92+
93+
- If the mapping element contains a filled Selector attribute then the output of the selector execution is used to find the correct mapping by name (e.g. selector function `ListSelectorListLibrary` return string "Library" which results in the mapping with name "Library" being used). Selectors are identical to functions that return a single value, so you can specify any web part attribute as input to your selector function
94+
- If there's only one mapping then that's taken if there was no selector result
95+
- If there's no selector result and there are multiple mappings defined then the mapping marked as Default is taken
96+
97+
Next up is explain the Mapping element itself.
98+
99+
### Mapping element
100+
101+
Inside a Mapping element you can have one or more ClientSideText or ClientSideWebPart elements as shown in below snippet:
102+
103+
```Xml
104+
<Mapping Name="List" Default="true">
105+
<ClientSideText Text="You can map a source web part ({Title}) to a combination of client side controls :-)" Order="10" />
106+
<ClientSideWebPart Type="List" Order="20" JsonControlData="&#123;&quot;serverProcessedContent&quot;&#58;&#123;&quot;htmlStrings&quot;&#58;&#123;&#125;,&quot;searchablePlainTexts&quot;&#58;&#123;&#125;,&quot;imageSources&quot;&#58;&#123;&#125;,&quot;links&quot;&#58;&#123;&#125;&#125;,&quot;dataVersion&quot;&#58;&quot;1.0&quot;,&quot;properties&quot;&#58;&#123;&quot;isDocumentLibrary&quot;&#58;false,&quot;selectedListId&quot;&#58;&quot;{ListId}&quot;,&quot;listTitle&quot;&#58;&quot;{Title}&quot;,&quot;selectedListUrl&quot;&#58;&quot;{ListServerRelativeUrl}&quot;,&quot;webRelativeListUrl&quot;&#58;&quot;{ListWebRelativeUrl}&quot;,&quot;webpartHeightKey&quot;&#58;4,&quot;selectedViewId&quot;&#58;&quot;{ListViewId}&quot;&#125;&#125;" />
107+
</Mapping>
108+
```
109+
110+
In above sample the source XSLTListView web part is mapped to a client side text part (`ClientSideText`) and a client side web part (`ClientSideWebPart`):
111+
112+
- Use the `Order` attribute to determine which one comes first
113+
- For a `ClientSideWebPart` you need to specify the `Type` of the web part, if you choose `Custom` as type you'll also need to specify the `ControlId` property to identify the needed custom web part
114+
- The `Text`, `JsonControlData` and `ControlId` properties can contain tokens in the form of {Token} which are replaced by actual values at runtime. Each token defined needs be able as web part property or function result as explained earlier on
115+
116+
## AddOns definition in the page transformation model
117+
118+
Add-ons allow you to insert your custom logic into the mapping model by following these 2 steps:
119+
120+
- Create a custom assembly hosting your custom functions/selectors
121+
- Declare this custom assembly in the AddOns elements
122+
123+
### Create your custom functions/selectors assembly
124+
125+
To create your own functions you'll need to reference the SharePoint.Modernization.Framework assembly in your project and then create a class inheriting the `SharePoint.Modernization.Framework.Functions.FunctionsBase` class:
126+
127+
```C#
128+
using Microsoft.SharePoint.Client;
129+
using SharePoint.Modernization.Framework.Functions;
130+
using System;
131+
132+
namespace SharePoint.Modernization.Framework.SampleAddOn
133+
{
134+
public class MyCustomFunctions: FunctionsBase
135+
{
136+
public MyCustomFunctions(ClientContext clientContext) : base(clientContext)
137+
{
138+
}
139+
140+
public string MyListAddServerRelativeUrl(Guid listId)
141+
{
142+
if (listId == Guid.Empty)
143+
{
144+
return "";
145+
}
146+
else
147+
{
148+
var list = this.clientContext.Web.GetListById(listId);
149+
list.EnsureProperties(p => p.RootFolder.ServerRelativeUrl);
150+
return list.RootFolder.ServerRelativeUrl;
151+
}
152+
}
153+
154+
}
155+
}
156+
```
157+
158+
### Declare your custom assembly
159+
160+
Before custom functions can be used they need to be declared in the model by adding one reference per library/class into the AddOns element:
161+
162+
```Xml
163+
<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="Contoso.Modernization.dll" />
164+
```
165+
166+
or (note the fully qualified path)
167+
168+
```Xml
169+
<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="c:\transform\Contoso.Modernization.dll" />
170+
```
171+
172+
Note that each declaration has a name, "Custom" in above sample.
173+
174+
### Use your custom functions/selectors
175+
176+
Now that the assembly has been defined you can use your functions and selectors be referencing them by the name like you see the "Custom" prefix in below sample:
177+
178+
```Xml
179+
<Property Name="ListId" Type="guid" Functions="{ListServerRelativeUrl} = Custom.MyListAddServerRelativeUrl({ListId})"/>
180+
```

0 commit comments

Comments
 (0)