Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O centro da solução de transformação de páginas é o modelo que alimenta a transformação: o modelo indica ao motor quais as propriedades da peça Web que são importantes, permite-lhe manipular estas propriedades e escolher dinamicamente um mapeamento para a sua peça Web. O modelo de transformação de página é expresso em XML e vem com um esquema que é utilizado para validar a correção do modelo.
Importante
A modernização do SharePoint PnP faz parte da Estrutura PnP e está em constante evolução, verifique as notas de versão para se manter atualizado sobre as alterações mais recentes. Se você tiver problemas, registre-o na lista de problemas do GitHub sobre Estrutura PnP.
Arquitetura alto nível de transformação de página
Veja a seguir a imagem explicativa da transformação de página em 4 etapas:
- No início, é preciso informar ao mecanismo de transformação de que forma você deseja transformar as páginas. Isso é feito fornecendo um modelo de transformação de página. Este modelo é um arquivo XML que descreve como cada web part clássica precisa ser mapeada para uma equivalente moderna. O modelo contém uma lista de propriedades relevantes e informações de mapeamento por web part clássica. Confira o artigo sobre como entender e configurar o modelo de transformação de página para saber mais. Se você quiser entender a comparação entre web parts clássicas e web parts modernas é recomendável verificar o arquivoExperiências de web part clássica e moderna.
- A próxima etapa será analisar a página que você quer transformar: o mecanismo de transformação irá quebrar a página em uma coleção de web parts (o texto de wiki é quebrado em uma ou mais web parts de texto de wiki) e ele tentará detectar o layout usado.
- As informações recuperadas da análise na etapa 2 geralmente não são suficientes para mapear a web part para uma equivalente moderna. Dessa forma, na etapa 3, a informação será aprimorada chamando funções: essas funções obtêm as propriedades recuperadas na etapa 2 e geram novas propriedades com base naquelas inseridas na etapa 2. Após o passo 3, temos todas as informações necessárias para mapear a peça Web... exceto que, opcionalmente, precisamos de chamar o seletor definido para compreender de que mapeamento vamos precisar caso uma peça Web clássica possa ser mapeada para múltiplas configurações modernas.
- O passo final é criar e configurar a página moderna, seguido da adição das peças Web modernas mapeadas à mesma.
Estrutura do modelo da transformação de página
Ao abrir o modelo de transformação de página, os seguintes elementos de nível superior estarão presentes:
BaseWebPart: este elemento contém a configuração que se aplica a todas as web parts, por exemplo, ele descreve que a propriedade “Title” será obtida para todas as web parts. É também o local que define o mapeamento de peças Web predefinido: se uma peça Web não tiver um mapeamento definido, o motor reverterá para este mapeamento para representar a peça Web na página de destino.
AddOns: como utilizador da transformação de página, poderá ter precisado de aplicar lógica personalizada para perceber as suas necessidades, por exemplo, tem de transformar uma determinada propriedade de uma forma que possa funcionar com a sua peça Web SPFX personalizada. O mecanismo oferece suporte a isso permitindo que você adicione seus assemblies com funções e seletores. Simplesmente defina-os na seção AddOn (suplementos) e, então, faça referência às suas funções e seletores personalizados posteriormente colocando um prefixo neles junto do referido nome. Isso fará com que a transformação de página use seu código personalizado.
Web Parts: esse elemento contém informações de cada web part que você deseja transformar. Para cada web part, você encontrará uma definição das propriedades a serem usadas, das funções a serem executadas nessas propriedades, dos mapeamentos possíveis que definem o destino da transformação combinada com um seletor que você seleciona dinamicamente o mapeamento necessário.
Os próximos capítulos oferecerão mais detalhes.
Definição de Web Part no modelo de transformação de página
Vamos analisar como uma web part é configurada no modelo de transformação de página, o qual é mais bem feito com base em um exemplo simplificado da definição XsltListViewWebPart:
<!-- XsltListView web part -->
<WebPart Type="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
<Properties>
<Property Name="XmlDefinitionLink" Type="string" />
<Property Name="ListUrl" Type="string" />
<Property Name="ListId" Type="guid" Functions="{ListWebRelativeUrl} = ListAddWebRelativeUrl({ListId}); {ListServerRelativeUrl} = ListAddServerRelativeUrl({ListId})"/>
<Property Name="Direction" Type="string"/>
<Property Name="GhostedXslLink" Type="string" />
<Property Name="DisableViewSelectorMenu" Type="bool"/>
<Property Name="XmlDefinition" Type="string" Functions="{ListViewId} = ListDetectUsedView({ListId},{XmlDefinition})"/>
<Property Name="SelectParameters" Type="string"/>
</Properties>
<!-- This selector outputs: Library, List -->
<Mappings Selector="ListSelectorListLibrary({ListId})">
<Mapping Name="List" Default="true">
<ClientSideText Text="You can map a source web part ({Title}) to a combination of modern web parts :-)" Order="10" />
<ClientSideWebPart Type="List" Order="20" JsonControlData="{"serverProcessedContent":{"htmlStrings":{},"searchablePlainTexts":{},"imageSources":{},"links":{}},"dataVersion":"1.0","properties":{"isDocumentLibrary":false,"selectedListId":"{ListId}","listTitle":"{Title}","selectedListUrl":"{ListServerRelativeUrl}","webRelativeListUrl":"{ListWebRelativeUrl}","webpartHeightKey":4,"selectedViewId":"{ListViewId}"}}" />
</Mapping>
<Mapping Name="Library" Default="false">
<ClientSideWebPart Type="List" Order="10" JsonControlData="{"serverProcessedContent":{"htmlStrings":{},"searchablePlainTexts":{},"imageSources":{},"links":{}},"dataVersion":"1.0","properties":{"isDocumentLibrary":true,"selectedListId":"{ListId}","listTitle":"{Title}","selectedListUrl":"{ListServerRelativeUrl}","webRelativeListUrl":"{ListWebRelativeUrl}","webpartHeightKey":4,"selectedViewId":"{ListViewId}"}}" />
</Mapping>
</Mappings>
</WebPart>
Elemento Properties
Para cada peça Web, o modelo define as propriedades que podem ser úteis para configurar as peças Web modernas de destino. Se você não vir certas propriedades, é possível simplesmente estendê-las no modelo. Em algumas das propriedades, verá um atributo Funções: este atributo contém uma ou mais funções (funções separadas através de um ;) que são executadas quando a peça Web de origem é mapeada para uma peça Web moderna de destino. A anatomia de uma função é a seguinte:
{Output} = FunctionName({Input1}, {Input2})
Uma função pode ter um ou mais valores de entrada que podem ser:
- Propriedades definidas nessa web part (por exemplo {ListId})
- Propriedades definidas na web part básica (por exemplo {Title})
- Propriedades que foram a saída de execuções de função anteriores (por exemplo {ListWebRelativeUrl})
- Propriedades com escopo do site padrão: {Host}, {Web}, {Site}, {WebId}, {SiteId}
Quando uma função executa o resultado, o resultado será:
- Um valor de uma única cadeia de caracteres: esse valor ({Output} no modelo apresentado) será adicionado à lista de propriedades da web part com o nome "Output" e terá o valor que retornou da execução de
FunctionName. - Uma lista de pares chave/valor (Cadeia de<dicionário,cadeia>): neste caso, cada par chave/valor devolvido é adicionado à lista de propriedades da peça Web
Se a função não definir o parâmetro de saída, o valor da propriedade de web part que define a função será substituído pelo resultado da função.
Vamos esclarecer com um exemplo:
<Property Name="ListId" Type="guid" Functions="FormatGuid({ListId})"/>
Vamos supor que a propriedade da web part contenha originalmente um guid formatado como {AAFAD7D0-D57A-4BB1-8706-969A608C686B}. Após o FormatGuid ser executado, o valor será definido como a saída de FormatGuid (por exemplo, um guid sem as chaves AAFAD7D0-D57A-4BB1-8706-969A608C686B).
Se uma função retornar diversos valores, cada par chave/valor retornado que ainda exista como propriedade de web part substituirá esse valor de propriedades.
Observação
Todas as funções prontas para uso são descritas em Funções e Seletores de Transformação de Páginas
Elemento Mappings
Esse elemento define uma ou mais configurações de destino possíveis para a referida web part de origem. Como você pode definir vários destinos é necessário haver um mecanismo para determinar qual mapeamento usar:
- Se o elemento de mapeamento contiver um atributo Selector preenchido, a saída da execução do seletor será usada para encontrar o mapeamento correto pelo nome (por exemplo, função seletor
ListSelectorListLibraryretorna a cadeia de caracteres "Library", que resulta no mapeamento com nome "Library" sendo usado). Os seletores são idênticos a funções que retornam um único valor, então, você poderá especificar qualquer atributo de web part como entrada para a função de seletor - Se houver apenas um único mapeamento, então, é considerado como se não houvesse nenhum resultado do seletor.
- Se não houver nenhum resultado do seletor e houver vários mapeamentos definidos, será considerado, então, o mapeamento marcado como Padrão
Observação
Todas as funções prontas para uso são descritas em Funções e Seletores de Transformação de Páginas
A seguir, vamos explicar o elemento Mapping propriamente dito.
Elemento Mapping
Dentro de um elemento Mapeamento, pode ter um ou mais elementos ClientSideText ou ClientSideWebPart, conforme mostrado no fragmento abaixo. Tenha em atenção que pode executar funções num Mapeamento, o que é útil caso pretenda efetuar o processamento apenas se tiver sido selecionado um mapeamento específico.
<Mapping Name="List" Default="true" Functions="{SampleVariable} = SampleFunction({ListId})>
<ClientSideText Text="You can map a source web part ({Title}) to a combination of modern web parts :-)" Order="10" />
<ClientSideWebPart Type="List" Order="20" JsonControlData="{"serverProcessedContent":{"htmlStrings":{},"searchablePlainTexts":{},"imageSources":{},"links":{}},"dataVersion":"1.0","properties":{"isDocumentLibrary":false,"selectedListId":"{ListId}","listTitle":"{Title}","selectedListUrl":"{ListServerRelativeUrl}","webRelativeListUrl":"{ListWebRelativeUrl}","webpartHeightKey":4,"selectedViewId":"{ListViewId}"}}" />
</Mapping>
No exemplo acima, a peça Web XSLTListView de origem está mapeada para uma peça de texto moderna (ClientSideText) e uma peça Web moderna (ClientSideWebPart):
- Use o atributo
Orderpara determinar qual será a primeira - Para uma
ClientSideWebPart, é preciso especificar oTypeda web part, caso escolhaCustomcomo tipo. Também será preciso especificar a propriedadeControlIdpara identificar a web part personalizada necessária. - As propriedades
Text,JsonControlDataeControlIdpodem conter tokens na forma de {Token} que são substituídos por valores reais na hora da execução. Cada token definido precisa ser como uma propriedade de web part ou resultado de função, conforme explicado anteriormente
Definição de AddOns (complementos) no modelo de transformação de página
Os complementos permitem que você insira sua lógica personalizada no modelo de mapeamento seguindo estas duas etapas:
- Crie um assembly personalizado que hospede seus seletores/funções personalizados
- Declare este assembly personalizado nos elementos AddOns
Criar seu assembly de funções/seletores personalizado
Para criar suas próprias funções, você precisará fazer referência ao assembly SharePoint.Modernization.Framework no projeto e criar uma classe que herde a classe SharePointPnP.Modernization.Framework.Functions.FunctionsBase:
using Microsoft.SharePoint.Client;
using SharePointPnP.Modernization.Framework.Functions;
using System;
namespace Contoso.Modernization
{
public class MyCustomFunctions: FunctionsBase
{
public MyCustomFunctions(ClientContext clientContext) : base(clientContext)
{
}
public string MyListAddServerRelativeUrl(Guid listId)
{
if (listId == Guid.Empty)
{
return "";
}
else
{
var list = this.clientContext.Web.GetListById(listId);
list.EnsureProperties(p => p.RootFolder.ServerRelativeUrl);
return list.RootFolder.ServerRelativeUrl;
}
}
}
}
Declarar seu assembly personalizado
Antes de as funções personalizadas poderem ser usadas, elas precisam ser declaradas no modelo, incluindo uma referência por biblioteca/classe no elemento AddOns:
<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="Contoso.Modernization.dll" />
ou (observe o caminho qualificado completo)
<AddOn Name="Custom" Type="Contoso.Modernization.MyCustomFunctions" Assembly="c:\transform\Contoso.Modernization.dll" />
Observe que cada declaração tem um nome "Custom" (personalizado) no exemplo acima.
Usar seus seletores/funções personalizados
Agora que o assembly foi definido, você poderá usar as funções e seletores fazendo referência a eles pelo nome, como você pode ver o prefixo "Custom" no exemplo abaixo:
<Property Name="ListId" Type="guid" Functions="{ListServerRelativeUrl} = Custom.MyListAddServerRelativeUrl({ListId})"/>