Valo - Intranet Documentation &copy; 2022 Made with #ValoLove 61 Architecture Overview Architecture Overview Last updated on 2021-02-22 • 1 min read Summary This is the overview of the Valo Intranet Architecture. Valo Intranet Architecture As you can see on the architecture overview above, there are various components for running an intranet for SharePoint Online. Most of the components run on the client's environment, except for the Valo License Manager and Telemetry Proxy. &copy; 2022 Made with #ValoLove 62 Azure Components Azure Components Last updated on 2021-03-26 • 2 min read Summary Valo Intranet relies heavily on an Azure back-end for processing some of the information (content creation, navigation building, notifications, etc.). This set of resources is mandatory and needs to be deployed prior to any SharePoint component. Overview Diagram We use Azure Functions as the back-end to process all this information. The Azure Functions app will be secured by Azure AD, so that no APIs can be anonymously called. Here you see how the authentication flow goes from SharePoint-to-Azure and back: &copy; 2022 Made with #ValoLove 63 Azure Components OAuth In order to authenticate from SharePoint components to Azure, Valo uses Implicit flow. As this method is not recommended anymore, since version 1.8 we added a possibility using OAuth Authorization Code Flow with PKCE. In version 1.8, this method will be supported only as experimental feature and it will require manual configuration. To enable OAuth Authorization Code Flow with PKCE, follow instructions in Configure/Admin/Oauth. Note More information about the APIs of the Azure Functions can be found here: Architecture/API Documentation. Once the intranet components are installed, there will be a regular check if the tenant is licensed correctly. In the following overview you can see the license check flow: &copy; 2022 Made with #ValoLove 64 &copy; 2022 Made with #ValoLove Azure Components 65 SharePoint Components SharePoint Components Last updated on 2021-03-25 • 2 min read Summary Valo Intranet is sitting on top of SharePoint Modern. In order to be fully modern, we are believing in the Modern Information Architecture concepts. This will mean more Site Collections rather than subsites (which are not recommended in any Modern SharePoint deployments) and will leverage the concepts of hubs to group content. Overview Diagram Azure behind Microsoft 365 Microsoft 365 is built on top of Azure and Azure Active Directory (Azure behind SharePoint have limited functionalities and therefore separate Azure subscription for back-end processes are needed). Valo uses Azure Active Directory Applications to authenticate API calls securely to back-end services. When Valo is installed to Microsoft 365 there will be three Azure Active Directory applications added to Azure Active Directory. &copy; 2022 Made with #ValoLove 66 SharePoint Components Note • {TenantName}-valo-sharepoint-app ◦ App is used to authenticate back-end Azure functions calls to SharePoint • {TenantName}-valo-functions ◦ App is used to secure calls from SharePoint to back-end Azure functions • {TenantName}-valo-tokens ◦ App is used to get authentication tokens for back-end calls • Valo Intranet Installer ◦ Multi-tenant app which is used to provision Intranet using Genesis. Here you see how the authentication flow goes from SharePoint-to-Azure and back: Warning This Azure Environment is (potentially) different from the Azure Subscription used to host back-end Azure components (Function Application, Storage, Cognitive Services, etc.). Once the intranet components are installed, there will be a regular check if the tenant is licensed correctly. In the following overview you can see the license check flow: &copy; 2022 Made with #ValoLove 67 SharePoint Components Telemetry In order to get to know which components/web parts/functionality gets used, we started to track the usage of our components. Here you can see the telemetry flow: &copy; 2022 Made with #ValoLove 68 Note You can read more about our telemetry story here: Valo Telemetry. &copy; 2022 Made with #ValoLove SharePoint Components 490 Extending your Valo Extending your Valo Last updated on 2022-03-28 • 2 min read Summary Valo Intranet offers a couple of ways to extend the UI and its behaviour. Under this section you can find out more about all the options which are available. Templates The Valo Universal and Search web parts both make use of Handlebars JS templates. This templating engine allows you to fully customize the experience from both of our web parts. You can find more details on how to start creating your own templates in the customize template section. Organization Chart Templates The Valo Organisation Chart web part allows to use custom templates as well. In order to make them available to select in the web part, it is required to upload them to Valo Templates site collection and set DataSource field to "OrganisationChart". The web part also allows to use a custom Open Position template. To make it available, upload it to ValoTemplates and give it the same name as the User Template, but with "-OpenPosition" suffix, e.g. * User template name: CustomTemplate.html * Open position template name: CustomTemplate-OpenPosition.html Please note to set DataSource field to "OrganisationChart" as well. When "Show job postings in the organization chart" feature is enabled, and custom handlebars template will be selected, custom open position template will be applied automatically. Extensibility framework Warning This is currently only available when running in experimental mode (More info about experimental features). Since release 1.4 of Valo Intranet, we have an extensibility framework in place which allows you to fully gain control over the Valo UI experience. With the extensibility framework you can do the following things: • Add your own components to Valo Intranet • Using our services/providers • Creating custom data sources which can be used in the Valo Universal Web Part You can find more details on how to start using the Valo Extensibility framework under the extensibility section. Experimental features Valo Intranet contains a couple of experimental features. The purpose of these features is to test out some functionality before it makes it officially to the product. This allows you to test it out and provide us feedback. The following things are currently available in experimental mode: • Universal Web Part ◦ HTTP / Rest data data source ◦ Microsoft Graph data source ◦ SharePoint data source ◦ Custom data sources &copy; 2022 Made with #ValoLove 491 Extending your Valo • Extensibility framework ◦ Extension points ◦ Providers/services ◦ Custom data sources Follow the next steps in order to enable the experimental features on your environment: • Go to your Valo Admin site • Click on the Manage Configuration option • From the dropdown on the configuration page, select Enable the experimental features [ExperimentalFeaturesEnabled] option if available. • When the option is not available, select <<Add new Configuration Property>> • In the next dropdown select Enable the experimental features [ExperimentalFeaturesEnabled] • Enable the toggle (True) • Save or update the new configuration &copy; 2022 Made with #ValoLove 492 Valo Intranet templates Valo Intranet templates Last updated on 2022-02-03 • 11 min read Summary The Valo Universal and Search web parts both make use of Handlebars JS templates. This templating engine allows you to fully customize the experience from both of our web parts. The Valo Organisation Chart web part also supports the Handlebars templates, but only with a subset of features. The limitations of the features for that web part are listed in the chapter Organisation Chart web part. To make the template creation process easier, we released the Yeoman - Valo Template Generator. More information about the generator can be found here: • https://www.npmjs.com/package/@valo/generator-template • https://github.com/ValoIntranet/valo-templates Information Since version 1.8, custom web components are supported in all your Handlebar templates. More information can be found here: Creating web components. Warning Since version 1.6, we are using the Universal Web Part as the default web part to retrieve and show data. If you have created custom templates in the past for our Search Web Part and want to use them on the Universal Web Part, you will have to do a small modification. All you need to do is to update the items reference to dsData.items in your custom HTML template. Creating your own template The easiest way is to start from an existing template which can be found in the Partner Pack. You can find all of our templates under the following directory location: PartnerPack\Samples\Templates. Once you picked one, open it in a text/code editor like Visual Studio Code (or something similar). Each template is built up with the following content elements: 1. Metadata 2. Template 3. Styling (optional) 4. Placeholder (optional) 5. Custom helpers (optional) Note &copy; 2022 Made with #ValoLove 493 Valo Intranet templates When creating your own templates, set the web part in debug mode. This will bypass the template caching system. You can find this setting in the property pane underneath Styling > Enable debug mode. Metadata The metadata content element defines the default settings which the Universal or Search web part should use to render your content. 1 2 3 <content id="metadata" type="x-handlebars-metadata"> { } </content> Based on the template you will use, it could contain things like: • fields: specifies the field to be retrieved with the search call • query: specifies the query to perform • sorting: specifies the sorting order of the search results • parameters: allows you to specify template settings, which can be configured in the web part • resources: custom language resources • ... Adding configurable parameters/settings The parameters option allows you to specify template settings. These parameters/settings can be configured in the web part's property pane. Parameters allow the following configuration values: 1 2 3 4 5 6 7 8 9 10 11 12 13 "parameters": [ { "name": "Url", "value": "https://www.valointranet.com/insights/blog/feed/", "description": "The URL of the RSS feed" }, { "name": "OptionField", "value": "", "description": "Allows you to specify a couple of options", "options": ["option 1", "option 2"] } ] &copy; 2022 Made with #ValoLove 494 Valo Intranet templates In the web part's property pane, you can change these parameter settings. The current sample will render the following output: These parameters can be used in the template section as follows: 1 \{\{parameters.NameOfYourParameter\}\} Adding localization resources All the Valo Intranet components have their own localization in place, but when creating your own templates for a multilingual environment. You might want to add your own localization resources. We allow this by using the resources option. The resources option expects the following configuration: 1 2 3 4 5 6 7 8 9 10 11 "resources": [ { "key": "title", "values": { "default": "Title", "nl-nl": "Titel", "fr-fr": "Titre" } }, ... ] Once your resource keys are in place, you can use them in the template zone as follows: 1 \{\{resources.NameOfYourKey\}\} Adding UI behaviours To help you build user-friendly interactions, we are providing some behaviours that can be leveraged in your templates. Currently, we support the following behaviours: • Expand/Collapse behaviour (Valo__ExpandCollapseBehaviour): Enables a expand/ collapse feature on parts of your the content. • Filter content behaviour (Valo__FilterContentBehaviour): Enables a basic filtering feature (show/hide) on parts of your content. • Flip toggle behaviour (Valo__FlipToggleBehaviour): Enables a basic flipping card feature. See both faces of a card item in your content. • Show more behaviour (Valo__ShowMoreBehaviour): Enables a basic show more feature. Click on a Show more link to see more content. &copy; 2022 Made with #ValoLove 495 Valo Intranet templates In order to use them, you have to specify them and provide the relevant parameters according to your template HTML. In the metadata JSON, add a new key uiBehaviours referencing a dictionary of behaviours. Each key will be one of the keys specified above. Each one must be an object having a parameters property which, in turn, will have any relevant properties for the current behaviour. The format of the UI behaviours configuration will look like: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <content id="metadata" type="x-handlebars-metadata"> { ... "uiBehaviours": { "Valo__BehaviourKey": { "parameters": { "param1": "value of parameter 2", "param2": "value of parameter 2", "param3": "value of parameter 3" } } } ... } </content> 15 Here are usage examples for each of the available behaviours. All parameters are mandatory. If one parameter is missing or mispelled, the behaviour will not work. Expand/Collapse UI behaviour The key to use for this behaviour is Valo__ExpandCollapseBehaviour. It enables an expand/collapse feature on parts of your content. In the following example, a click on a button with class contentHeader will expand or collapse the content with class expandableContent in the same parent element. &copy; 2022 Made with #ValoLove 496 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 Valo Intranet templates <content id="metadata" type="x-handlebars-metadata"> { "uiBehaviours": { "Valo__ExpandCollapseBehaviour": { "parameters": { "toggleTriggerElementSelector": ".contentHeader", "expandableContentElementsSelector": ".expandableContent", "toggleIconSelector": ".toggleIcon", "toggleIconAddClassName": "ms-Icon--Add", "toggleIconRemoveClassName": "ms-Icon--Remove" } } } } </content> <content id="template" type="x-handlebars-template"> ... ... <!-- one expandable item --> <div> <!-- A header and expandable content must be contained in any HTML parent element <button class="contentHeader" type="button" aria-expanded="false"> Content 1 <i class="toggleIcon ms-Icon ms-Icon--Add"></i> </button> <div class="expandableContent"> More info about content 1 </div> </div> <!-- Another expandable item --> <div> <!-- A header and expandable content must be contained in any HTML parent element <button class="contentHeader" type="button" aria-expanded="false"> Content 2 <i class="toggleIcon ms-Icon ms-Icon--Add"></i> </button> <div class="expandableContent"> More info about content 2 </div> </div> ... ... </content> --> --> 42 43 44 Filter Content UI behaviour The key to use for this behaviour is Valo__FilterContentBehaviour. It enables a basic filtering feature (show/hide) on parts of your content. In the following example, a click on one of the links with CSS class filterLink will filter out all the <li> elements whose data-category attribute's value is not matching the Id of the link. The id all is a special one that will make all the elements visible. &copy; 2022 Made with #ValoLove 497 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 Valo Intranet templates <content id="metadata" type="x-handlebars-metadata"> { "uiBehaviours": { "Valo__FilterContentBehaviour": { "parameters": { "triggerElementsSelector": ".filterLink", "triggerElementFilterValueAttributeName": "id", "filterableElementsSelector": "[data-category]", "matchingFilterElementsSelector": "[data-category='{value}']", "displayType": "block" } } } } </content> <content id="template" type="x-handlebars-template"> ... <div> <!-- Filter links --> <ul> <li> <!-- all is a special filter to show all content --> <button class="filterLink" id="all" type="button">See all</button> </li> <li> <button class="filterLink" id="category1" type="button">See category 1</button> </li> <li> <button class="filterLink" id="category2" type="button">See category 2</button> </ul> <!-- Content --> <ul> <li data-category="category1">Some Content (category1)</li> <li data-category="category1">Some Content (category1)</li> <li data-category="category2">Some Content (category2)</li> <li data-category="category2">Some Content (category2)</li> </ul> </div> ... </content> 41 Flip toggle UI behaviour The key to use for this behaviour is Valo__FlipToggleBehaviour. It enables a basic flipping card feature. See both faces of card items in your content. In the following example, a click on the links with CSS class flipToggleFront or flipToggleBack will flip the card with Id flippingCard. &copy; 2022 Made with #ValoLove 498 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 Valo Intranet templates <content id="metadata" type="x-handlebars-metadata"> { "uiBehaviours": { "Valo__FlipToggleBehaviour": { "parameters": { "toggleOnElementsSelector": ".flipToggleFront", "toggleOffElementsSelector": ".flipToggleBack", "toggledLinksSelector": ".link", "dataContainerAttributeName": "data-container" } } } } </content> <content id="template" type="x-handlebars-template"> ... <div id="flippingCard"> <div> CARD FRONT <a href="javascript:;;" class="flipToggleFront" data-container="#flippingCard"> See back side of the card </a> </div> <div> CARD BACK <a href="javascript:;;" class="flipToggleBack" data-container="#flippingCard"> See front side of the card </a> <a class="link">Misc link 1</a> <a class="link">Misc link 2</a> </div> </div> ... </content> 34 35 Show More UI behaviour The key to use for this behaviour is Valo__ShowMoreBehaviour. It enables a basic show more feature. Click on a Show more link to see more content. In the following example, a click on a button with ID showMoreTrigger will display the content of the div with CSS class moreContent. &copy; 2022 Made with #ValoLove 499 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 Valo Intranet templates <content id="metadata" type="x-handlebars-metadata"> { ... "uiBehaviours": { "Valo__ShowMoreBehaviour": { "parameters": { "showMoreTriggerElementSelector": "#showMoreTrigger", "isVisibleCssClass": "is-visible", "elementsToShowSelector": ".moreContent", "textContainerSelector": "#showMoreTextContainer", "showMoreKey": "Key_ShowMore", // The localization key of the label to use for "Show more" "showLessKey": "Key_ShowLess", // The localization key of the label to use for "Show less" "sizeRefElementSelector": ".moreContentPanel", "linksToUpdateTabIndexSelector": ".linkInContent", "toggleIconSelector": ".showMoreIcon", "collapsedIconCssClass": ".ms-Icon--ChevronDown", "expandedIconCssClass": ".ms-Icon--ChevronUp" } } } ... } </content> <content id="template" type="x-handlebars-template"> ... <div class="moreContent"> <div class="moreContentPanel"> <h3>TITLE</h3> <a class="linkInContent" tabindex="-1">LINK</a> ... </div> </div> ... <button type="button" tabindex="0" id="showMoreTrigger"> <span id="showMoreTextContainer">Show More</span> <i class="ms-Icon ms-Icon--ChevronDown showMoreIcon"></i> </button> ... </content> 39 40 Template HTML The HTML that the template will use to render needs to be specified in the template content element. 1 2 3 <content id="template" type="x-handlebars-template"> <!-- The template HTML --> </content> More information about how to create templates can be found on the handlebars js website. Note You need to allow the execution of the javascript inside the template, read how to enable it in search web parts. &copy; 2022 Made with #ValoLove 500 Valo Intranet templates Helpers In the Search and Universal web parts we automatically include the handlebars helpers dependecy which provides you with more than 130 additional helpers for creating your templates. More information about this helpers dependency can be found here: handlebars-helpers. The current version added to our project is: 0.8.2. Valo Helpers Besides the default helpers and the helpers dependency we load. We added a couple of our own helpers that have some SharePoint understanding. Check out the following page with all Valo Helpers. Valo Web Components There are a few built-in web components that are used in the internal templates. It is possible to take advantage of them in custom templates. Check out the list of them and how to use them on the following page: Valo Web components. Custom Web Component (Experimental mode since Valo intranet version 1.6.0 and @valo/extensibility version 1.4.0) Custom web components allow you to gain more control over the elements that get rendered in your template. It will also allow you to make it easier to write and control async logic. More information about custom web components can be read here: Creating web components. Custom helpers When you are building your own templates, it might happen that you miss some functionality/helpers. In that case, you can add your own helpers. In order to do this, you will have to follow our custom helpers guide. Styling The templates can be treated as individual components by including the styling into the template itself. This approach makes it easier to take the template and move it to another environment. If you want to add you own styling, you will have to add the following style element to the template: 1 2 3 4 5 6 <style id="styling" type="x-handlebars-styling"> /* https://docs.microsoft.com/en-us/sharepoint/dev/spfx/use-theme-colors-in-your-customizations */ .valo-rss-feed__title .valo-rss-feed__link { color: "[theme: neutralPrimaryAlt, default: #3c3c3c]"; } </style> Information The template allows you to make use of the SharePoint theme tokens in the CSS. You can find more information about how to use it on how to use theme colors in your SharePoint Framework customizations. If you want to make the styling process easier, be sure to check out the Valo Template Generator. This allows you to make use of SASS and includes all these SharePoint tokens for you to make use of. Theme variants Since version 1.8, theme variants are also supported (i.e., adapting to section background colors). The support is provided in the form of CSS custom properties and as such does not work on IE11. The values of these custom properties are assigned at the top-level container of the web part and depend on the background of the section the web part is placed in. &copy; 2022 Made with #ValoLove 501 Valo Intranet templates To support theme variants in your templates you should introduce additional color assignment to your template styles. For example: 1 2 3 4 .valo-rss-feed__title .valo-rss-feed__link { color: "[theme: neutralPrimaryAlt, default: #3c3c3c]"; color: var(--bodyTextChecked, "[theme: neutralPrimaryAlt, default: #3c3c3c]"); } In the above example, the first color assignment is only used by browsers that do not support CSS custom properties (IE11). The second assignment contains the custom property name --bodyTextChecked followed by a fallback value that will be only used if the custom property cannot be applied (i.e., the property is not available or contains an invalid value). A full categorized list of available semantic slots can be found at the bottom of Microsoft's Fluent UI Theme Designer page. Placeholder HTML (optional) The placeholder content element can be used if you want to show something while your data is being fetched. This is optional. When it cannot be found in the template, nothing will be shown. 1 2 3 <content id="placeholder" type="x-handlebars-template"> <!-- The placeholder HTML --> </content> Note In the placeholder you can also make use of the helpers. Template ready? Time to upload Once your template is ready, it is time to upload it to your tenant. In Valo Intranet we use the Valo Templates site for this purpose. The default location of this site is: https://<tenant>.sharepoint.com/sites/valotemplates (if you changed the URL in Genesis, you will have to look it up in your configuration). When you navigate to the site, you will be presented with two options: WebPart Templates and Page & News Templates. Pick the WebPart Templates, which navigates you to the Templates gallery library. In this library, you can upload your template. Note &copy; 2022 Made with #ValoLove 502 Valo Intranet templates Once the template has been uploaded, be sure to specify its title in the TemplateTitle field. Once it has a title, the template will be ready to be used in the web part. If this is a template created for the Valo Universal web part, you can also specify the data source name in the DataSource field. This allows us to filter out the templates that are only applicable to a specific data source in the web part. The available data source values are: • AnalyticsDataSource • HttpDataSource • MicrosoftGraphDataSource • NewsDataSource • RssDataSource • SharePointDataSource • VideoDataSource Debugging template When you are creating a template and want to know which values you retrieve in your template, you can use the default debugging template. This template shows the raw object which is passed to your template. The debug template can be selected in the template dropdown: &copy; 2022 Made with #ValoLove 503 Valo Intranet templates Sample output: RSS Data Source / Template The RSS data source in the Universal Web Par allows you to visualize the RSS feed. When you have a custom RSS format, or you want to visualize custom fields. Since the Valo Intranet 1.5 release, we now include the raw RSS feed in the data source. You can check this by using the Debug/Test template in the universal web part. &copy; 2022 Made with #ValoLove 504 Valo Intranet templates Info: Highlighted in red is the raw feed data for each item. In order to make use of the raw data format, you will have to use a custom template. You can use the default RSS template, which can be found in the Genesis folder under: Samples\templates\rss\rss.html. You can use the contents of the raw object in the {{#each dsData.items}} loop as follows; 1 {{#each dsData.items}} <!-- Already in the template --> 2 3 4 5 <p>{{raw.objectName}}</p> <!-- This is what you need to implement --> {{/each}} <!-- Already in the template --> Organisation Chart web part Feature limitations While the Organisation Chart web part supports Handlebars templates, it offers only a subset of features that the Universal Web part has. The supported features are listed below. • Metadata (Only the fields array) • Helpers • Custom helpers Valo helpers There are currently two helpers that are included by Valo, which you can use in the Organisation Chart templates. Instead of having a separate page for them, they are listed below. userPicture Gets a site relative URL of the user profile photo in SharePoint. &copy; 2022 Made with #ValoLove 505 Valo Intranet templates Parameters 1. Email of the user Usage {{userPicture mail}} 1 Returns /_layouts/15/userphoto.aspx?size=L&accountname=firstname.lastname@contoso.com resourceLabel Returns the resource label for the current locale. Parameters 1. Locale key Usage 1 {{resourceLabel 'GeneralOffice'}} &copy; 2022 Made with #ValoLove 506 Creating your custom helpers Creating your custom helpers Last updated on 2020-01-16 • 1 min read Summary If you have a need to create your own custom helpers in the template, you will have to do it as follows: • Start by creating a new content element with the following contents 1 2 3 4 5 <content id="customHelpers" type="x-handlebars-helpers"> <script> </script> </content> • Once the new custom helpers content element has been added to the template, you can start adding your own helpers with the Handlebars.registerHelper method. Examples: 1 2 3 4 5 6 1 2 3 4 5 6 7 8 9 Handlebars.registerHelper("customLogger", function(value) { console.log("Custom Logger:", value); }); // Usage {{customLogger itemValue}} Handlebars.registerHelper("reverseString", function(value) { if (value) { value = value.split("").reverse().join("") } return value; }); // Usage {{reverseString itemValue}} Example of the template: &copy; 2022 Made with #ValoLove 507 Creating your custom helpers Information If you want to know more about custom Handlebars helpers, you can check out the official documentation: Handlebars helpers documentation. &copy; 2022 Made with #ValoLove 508 Valo helpers Valo helpers Last updated on 2022-02-04 • 5 min read Summary List of Valo helpers. andCond Checks if both parameters contains a value. Parameters 1. Parameter A 2. Parameter B Usage {{#if (andCond ValoCommentingTypeOWSCHCS ValoYammerThreadIdOWSTEXT)}} 1 2 {{/if}} 3 blogImageResolution Specifies the image resolution to be used with the getpreview.ashx end-point. Parameters 1. Image URL 2. Image width Usage {{blogImageResolution PictureThumbnailURL 600}} 1 dateAgoFormat Format date with to ... ago. Parameters 1. Date value Usage 1 {{dateAgoFormat FirstPublishedDate}} eachLimited Limit the each-loop to a maximum number of items. Parameters 1. Items array 2. Maximum number to limit the array &copy; 2022 Made with #ValoLove 509 Valo helpers Usage {{eachLimited array 5}} 1 fileIconName Returns the office ui fabric icon name associated with the given file extension. Parameters 1. File extension Usage {{fileIconName FileExtension}} 1 generateId Generate a unique ID. Usage {{generateId}} 1 groupBy Grouping an array of items by a specific field. This allows you to show items in a grouped view. Usage {{#groupBy dsData.items by="ListId"}} <h1>{{ value }}</h1> <!-- 'value' is the group header --> 1 2 3 <ul> {{#each items}} <li><a href={{Path}}>{{ Title }}</a></li> {{/each}} </ul> {{/groupBy}} 4 5 6 7 8 9 if_containsQueryString Checks if URL contains a query string. Parameters 1. URL Usage 1 {{#if_containsQueryString Path}} 2 3 {{/if}} imageResolution Specifies the image resolution retrieved by the getpreview.ashx end-point. &copy; 2022 Made with #ValoLove 510 Valo helpers Parameters 1. Image URL 2. Resolution value 3. Side ID (optional) 4. Web ID (optional) Resolution values are: • 0: 300px • 1: 480px • 2: 750px • 3: 1024px • 4: 1600px (default) • 5: 2560px • 6: 4928px – Original file size Usage 1 2 {{imageResolution BannerImageUrlOWSURLH 4}} 3 // The site ID and web ID can be used for image values coming back from events. These will updated to use the get {{imageResolution BannerUrlOWSURLH 1 SiteID WebID}} 4 localizedMonth Returns the short month label in the current locale language. Parameters 1. Date Usage {{localizedMonth EventDateOWSDATE}} 1 meetingTime Format the meeting time from an event. Parameters 1. Start date 2. End date 3. Is an all day event Usage 1 {{meetingTime EventDateOWSDATE EndDateOWSDATE IsAllDayEvent}} profileProperty Returns the user profile property value. &copy; 2022 Made with #ValoLove 511 Valo helpers Parameters 1. Username 2. Name of the property Usage 1 {{profileProperty username 'Department'}} 2 3 {{profileProperty (splitSPUser AuthorOWSUSER 'email') 'Department'}} repeat Print the HTML content a X number of times. Parameters 1. Number of times to repeat the HTML contents Usage {{#repeat 5}} <div></div> {{/repeat}} 1 2 3 removeDuplicates Removes duplicates based on given field and returns an array which consists of only the given field. Parameters 1. Array 2. Field to be used to remove duplicates Usage {{#each (removeDuplicates items 'ValoFAQCategoryOWSCHCS')}} 1 2 {{/each}} 3 resolveAccountName Helper to resolve loginName from accountName exposed via search. Parameters 1. Account name Usage 1 {{resolveAccountName AccountName}} splitDisplayNames SharePoint helper to split the displaynames of for example the Author field (user1;user2...). &copy; 2022 Made with #ValoLove 512 Valo helpers Parameters 1. Users value Usage {{splitDisplayNames Author}} 1 splitTerms Splits a multi-value managed metadata property value and returns the labels. Parameters 1. Terms value Usage {{splitTerms TermsValue}} 1 splitSPUrl Split the SP URL field and return the requested property. Parameters 1. URL Value 2. Property to return (url or description) Usage 1 2 {{splitSPUrl urlProp 'url'}} 3 {{splitSPUrl urlProp 'description'}} splitUser This helper can be used to split a user managed property value (ex.: email|displayname|i:0#.f|membership|username) and return the wanted value (displayName or email). Parameters 1. User value 2. Property to return (displayName or email) Usage 1 {{splitSPUser AuthorOWSUSER 'displayName'}} 2 3 {{splitSPUser AuthorOWSUSER 'email'}} summary Formats the HitHighlightSummary returned by SharePoint. Parameters 1. Highlighted field value &copy; 2022 Made with #ValoLove 513 Valo helpers Usage {{summary HitHighlightedSummary}} 1 totalComments Get the number of comments for a modern page. Parameters 1. Site URL 2. List ID 3. Item ID 4. Unique page ID 5. Commenting type (optional - is used when using Yammer comments) 6. Yammer thread ID (optional - is used when using Yammer comments) Usage 1 2 {{totalComments SPWebUrl ListID ListItemID UniqueId} 3 {{totalComments SPWebUrl ListID ListItemID UniqueId ValoCommentingTypeOWSCHCS ValoYammerThreadIdOWSTEXT totalLikes Get the number of likes for a modern page. Parameters 1. Site URL 2. List ID 3. Item ID 4. Unique page ID 5. Commenting type (optional - is used when using Yammer comments) 6. Yammer thread ID (optional - is used when using Yammer comments) Usage 1 {{totalLikes SPWebUrl ListID ListItemID UniqueId} 2 3 {{totalLikes SPWebUrl ListID ListItemID UniqueId ValoCommentingTypeOWSCHCS ValoYammerThreadIdOWSTEXT toUtc Convert the date time back to UTC. Parameters 1. Date value 2. Format value Usage 1 {{toUtc EndDateOWSDATE "MMM DD"}} &copy; 2022 Made with #ValoLove 514 Valo helpers translateTerms Splits the term values and returns the label in the language of the current loaded UI language. Parameters 1. Terms value 2. Web URL Usage {{translateTerms ValoOfficeLocation SPWebUrl}} 1 typeof Return the type of from the object which is passed. Parameters 1. Value Usage 1 {{typeof this}} 2 3 {{typeof value}} userProfileUrl Returns the user profile URL for the specified email/createdById/modifiedById. Parameters 1. The user its email or ID Usage {{userProfileUrl ModifiedById}} 1 hours Returns hours for the current locale Parameters 1. The number of hours Usage 1 {{hours ValoJobPostingEmploymentHoursOWSNMBR}} doesEventSpansAcrossMultipleDays Convert the date time back to UTC Parameters 1. Start Date value as a string 2. End Date value as a string &copy; 2022 Made with #ValoLove 515 Valo helpers 3. IsAllDayEvent - boolean 4. preferRegionalSettingsOfWebToDisplayDates - boolean Usage {{doesEventSpansAcrossMultipleDays EventsRollUpStartDate EventsRollUpEndDate IsAllDayEvent @root.preferRegionalSe 1 isMidnightEvent If an event spans 2 days and its duration is less than 24 hours, then it is a midnight event. Parameters 1. Start Date value as a string 2. End Date value as a string 3. isAllDayEvent - boolean 4. preferRegionalSettingsOfWebToDisplayDates - boolean Usage {{isMidnightEvent EventsRollUpStartDate EventsRollUpEndDate IsAllDayEvent @root.preferRegionalSettingsOfWebToDisp 1 getFormattedEventDate Returns the event date in the format of the site's regional settings Parameters 1. Date value as a string 2. Date format value as a string 3. isAllDayEvent - boolean 4. preferRegionalSettingsOfWebToDisplayDates - boolean, specify if you want to use the regional settings in date display format Usage {{getFormattedEventDate EventsRollUpStartDate "DD" IsAllDayEvent @root.preferRegionalSettingsOfWebToDisplayDates 1 getFormattedEventTime Returns the formatted event time. Parameters 1. Start Date value as a string 2. End date value as a string 3. Date format value as a string 4. isAllDayEvent - boolean 5. preferRegionalSettingsOfWebToDisplayDates - boolean, specify if you want to use the regional settings in date display format Usage &copy; 2022 Made with #ValoLove 516 Valo helpers {{getFormattedEventTime EventsRollUpStartDate EventsRollUpEndDate "LT" IsAllDayEvent @root.preferRegionalSettings 1 adjustDateOnlyValueWithSiteTimeZone Provided UTC date is adjusted according to site collection TimeZone. This is due to the fact that SP stores Date only values with the time information. Parameters 1. UTC date value as a string 2. Url of the site collection Usage {{adjustDateOnlyValueWithSiteTimeZone ValoJobPostingApplyByOWSDATE SPWebUrl}} 1 isExpired Returns true if the date is less than the specified number of days Parameters 1. Date value as a string 2. Number of days Usage {{isExpired ModifiedOWSDATE 90}} 1 formatDateAsync Format date without changing it to UTC Parameters 1. Date value as a string 2. Date format value as a string Usage {{formatDateAsync ValoJobPostingApplyByOWSDATE "MMM DD YYYY"}} 1 wrapWithHtmlElementAsync Wraps content with declared tag. Accepts promise as an argument. Replaces value after the promise is resolved. Parameters 1. HTML tag name, like p, span, div 2. Promise string value 3. HTML Element Id - optional 4. HTML element class - optional Usage 1 {{wrapWithHtmlElementAsync 'span' (wrapAsyncValue (getProfilePropertyValue (splitSPUser AuthorOWSUSER &copy; 2022 Made with #ValoLove 517 Valo helpers wrapAsyncValue Wraps content with declared tag. Accepts promise as an argument. Replaces value after the promise is resolved. Parameters 1. Promise string value 2. Prefix - optional 3. Suffix - optional Usage {{(wrapAsyncValue (getProfilePropertyValue (splitSPUser AuthorOWSUSER 'email') 'Department') }} 1 prepareBatchPageImageInfoPromises Groups the requests to obtain the page image info. Parameters 1. Array of items, eg. list of pages that contains banner images. Usage {{prepareBatchPageImageInfoPromises dsData.items}} 1 getProfilePropertyValue Retrieves a User profile property value. 1. Name of the user 2. Profile property name Usage {{getProfilePropertyValue (splitSPUser EditorOWSUSER 'email') 'Department'}} 1 prepareBatchSocialInfoPromises Groups the requests to obtain the page social info. Parameters 1. Array of items, eg. list of pages from that you want to get like & comment count Usage {{prepareBatchSocialInfoPromises dsData.items}} 1 prepareBatchTermsPromises Groups the requests to obtain the page terms info like Valo Tags, Business area, Location. Parameters 1. Array of items, eg. list of pages from that you want to get Terms set information Usage &copy; 2022 Made with #ValoLove 518 Valo helpers {{prepareBatchTermsPromises dsData.items}} 1 getTermById Returns the Term value based on the id of the term Parameters 1. Term Id 2. Class name Usage {{getTermById dsData.ValoOfficeLocation.TermGuid 'ValoOfficeLocation'}} 1 append Appends a string to another string Parameters 1. string 2. string to append Usage {{append 'Hello ' 'World'}} 1 linkedInUrl Returns the Linked In embed URL. Parameters 1. Id of the LinkedIn Post Usage {{linkedInUrl parameters.LinkedInPostId}} 1 useIntersectionObserver Check if useImageLazyLoading is enabled on template and IntersectionObserver supported by the browser Parameters 1. Use lazy loading in the template, usually true or false string value Usage 1 {{useIntersectionObserver parameters.UseImageLazyLoading}} isDataSetIsEmpty Checks if dsData contains items. In case items.length >= 0 => returns true; otherwise false &copy; 2022 Made with #ValoLove 519 Valo helpers Parameters 1. Data set items Usage 1 2 3 {{#if (isDataSetIsEmpty dsData)}} {{"NoResultsFound"}} {{/if}} &copy; 2022 Made with #ValoLove 520 Valo Web components Valo Web components Last updated on 2021-05-20 • 5 min read Summary List of Valo Web Components. Image Focal Point (valo-image-focal-point) Render div element with source page's banner image as background with focal point support. Parameters Parameter Type Description css-names string CSS classes to include in the div element img-url string Url to the image item-id number List item id of the page in Site Pages library list-id string (guid) List id of the Site Pages library site-url string Url of the site where the page is located layout-content string Layout web parts content observer-support boolean Can intersection observer be used observer-margin Style definition for margin sizes string Usage 1 2 3 4 5 6 7 8 9 10 <valo-image-focal-point css-names="valo-news__item__banner__parallax parallax parallaxSlow" img-url="{{imageResolution BannerImageUrlOWSURLH 4 null null ../parameters.UseThumbnailImages}}" item-id="{{ListItemID}}" list-id="{{ListID}}" site-url="{{SPWebUrl}}" layout-content="{{LayoutWebpartsContentOWSHTML}}" observer-support="{{@root.canUseIntersectionObserver}}" observer-margin="0px 0px 0px -20px"> </valo-image-focal-point> Page comments (valo-page-comments) Shows comment count for the page and the comment icon Parameters Parameter Type Description item-id number List item id of the page in Site Pages library list-id string (guid) List id of the Site Pages library &copy; 2022 Made with #ValoLove 521 Valo Web components Parameter Type Description site-url string Url of the site where the page is located initial-commentscount number Number to show initially before API call for comment count is received Usage 1 2 3 4 5 6 <valo-page-comments item-id="{{ListItemID}}" list-id="{{ListID}}" site-url="{{SPWebUrl}}" initial-comments-count="{{CommentCountLifetime}}"> </valo-page-comments> Page likes (valo-page-likes) Shows like count for the page and the like icon/button. Parameters Parameter Type Description item-id number List item id of the page in Site Pages library list-id string (guid) List id of the Site Pages library site-url string Url of the site where the page is located initial-likecount number Number to show initially before API call for like count is received like-text string Overwrite aria-label attribute of the like button unlike-text string Overwrite aria-label attribute of the unlike button Usage 1 2 3 4 5 6 7 8 <valo-page-likes item-id="{{ListItemID}}" list-id="{{ListID}}" site-url="{{SPWebUrl}}" initial-like-count="{{LikesCount}}" like-text="{{@root.parameters.LikeText}}" unlike-text="{{@root.parameters.UnlikeText}}"> </valo-page-likes> Page social info (valo-page-social-info) Shows like and comment count for the page and the like icon/button and comment icon. &copy; 2022 Made with #ValoLove 522 Valo Web components Parameters Parameter Type Description item-id number List item id of the page in Site Pages library list-id string (guid) List id of the Site Pages library site-url string Url of the site where the page is located initial-like-count number Number to show initially before API call for like count is received like-text string Overwrite aria-label attribute of the like button unlike-text string Overwrite aria-label attribute of the unlike button initial-commentscount number Number to show initially before API call for comment count is received Usage 1 2 3 4 5 6 7 8 9 <valo-page-social-info item-id="{{ListItemID}}" list-id="{{ListID}}" site-url="{{SPWebUrl}}" initial-like-count="{{LikesCount}}" like-text="{{@root.parameters.LikeText}}" unlike-text="{{@root.parameters.UnlikeText}}" initial-comments-count="{{CommentCountLifetime}}"> </valo-page-social-info> Persona card (valo-persona-card) Shows user's profile with Fluent UI Persona component Parameters Parameter Type Description user-id number Site collection specific ID of the user. If this is used, it will get rest of the info from the profile. image-url string Url of the profile image text string Main text of the persona card, usually full name of the user. secondarytext string Text shown under the main text, for example job title. tertiary-text string Text shown under the secondary text, if persona-size is 14 or higher. persona-size number Size of the persona card Information &copy; 2022 Made with #ValoLove 523 Valo Web components Persona sizes comme directly from the Office UI Fabric enum: size28 = 7, size16 = 8, size10 = 9, (Tiny) size24 = 10, (Extra extra small) size32 = 11, (Extra small) size40 = 12, (Small) size48 = 13, (Regular) size72 = 14, (Large) size100 = 15 (Extra large) The sizes can be seen in action in the following link Persona control in Fluent UI. Usage 1 2 3 4 5 6 7 <valo-persona-card image-url="{{SPWebUrl}}/_layouts/15/userphoto.aspx?size=L&username={{splitSPUser EditorOWSUSER 'email'}}" text="{{splitSPUser EditorOWSUSER 'displayName'}}" secondary-text="" tertiary-text="{{splitSPUser EditorOWSUSER 'email'}}" persona-size="12" > </valo-persona-card> Poll (valo-poll) Renders Valo poll Parameters Parameter Type Description itemId number ID of the list item containing the selected poll. listId string (guid) ID of the list containing the selected poll. siteUrl string Url of the site where the poll list is located. allowUsersVote boolean Are users allowed to vote on the poll? hotSwap Is hot swapping in use? boolean Usage 1 2 3 4 5 6 7 <valo-poll itemId="{{ListItemID}}" listId="{{ListID}}" siteUrl="{{SPWebUrl}}" allowUsersVote="{{AllowUsersVote}}" hotSwap="{{HotSwap}}"> </valo-poll> Security Trimmed (valo-security-trimmed) Renders the inner content of the Web Component only if the current user has the specified permissions &copy; 2022 Made with #ValoLove 524 Valo Web components Parameters Parameter Type Description level string The level (or scope) of permission to check list-id string The Id of the list to check the permissions of list-item-id string remote-siteurl string permissions string A string containing a comma-separated list of permissions to check The Id of the list Item to check the permissions of (Only suitable if level is remoteListItem) The remote site to check the permissions of (if level is remoteWeb) or containing the list or item to check the permissions of Information The level is one of the following values: currentWeb, currentList, remoteWeb, remoteListOrLib, remoteListItem, hubSiteCreation, hubPageCreation Information The accepted values in permissions comma-separated list are one of the permissions described here Usage 1 2 3 4 5 6 7 <valo-security-trimmed level="currentWeb | currentList | remoteWeb | remoteListOrLib | remoteListItem | hubSiteCreation | hubPageCre list-item-id="{{ListItemID}}" list-id="{{ListID}}" remote-site-url="{{SPWebUrl}}" permissions="<comma-separated list of combined permissions>"> </valo-security-trimmed> Warning If the <valo-trigger/> web component is used and targets an element that is included in the security trimmed content, the trigger component should be nested in the security trimmed content as well. Such as in the following exhibit 1 2 3 4 5 6 7 8 9 10 11 12 <valo-security-trimmed level="remoteListItem" remote-site-url="{{SPWebUrl}}" list-id="{{ListID}}" list-item-id="{{ListItemID}}" permissions="editListItems"> <div class="valo-faq__editbutton_row"> <button class="valo-faq__editbutton valoFAQEditButton" id="{{@root.editButtonId}}" type="button" aria-expanded="false" aria-controls="answer-{{UniqueId}}-{{@index}}"> <i class="valo-faq__editbutton-icon valoFAQEditButtonIcon ms-Icon ms-Icon--Edit" aria-hidden="true"></i> </button> </div> <valo-trigger unique-id="{{@root.editButtonId}}" item-id="{{ListItemID}}" list-id="{{ListID}}" site-url="{{SPWebUrl}}" panel-title="{{Title}}" trigger-type="FAQPanel" action-type="edit" style="display: none;"></valo-trigger> </valo-security-trimmed> 13 &copy; 2022 Made with #ValoLove 525 Valo Web components Terms (valo-terms) Renders terms for list item Parameters Parameter Type Description term-value string Contents of the taxonomy field (usually ValoTags) web-url string Url of the site where the list item is located multilingual boolean Use multilingual terms? css-span string CSS classes to use in span element wrapping the tag css-icon string CSS classes to use in icon element title-span string Title attribute of the span element title-icon string Title attribute of the icon element css-more string CSS classes to use in span containing indication of more tags (+2 for example) show-moretag boolean Is the more tags span element shown Usage 1 2 3 4 5 6 7 <valo-terms term-value="{{owstaxIdValoTags}}" web-url="{{SPWebUrl}}" multilingual="{{@root.parameters.UseMultilingualTerms}}" css-span="valo-banner__item__social__tags__tag" css-icon="valo-banner__item__social-icon ms-Icon ms-Icon--Tag"> </valo-terms> Trigger (valo-trigger) Trigger allow you to communicate and invoke actions to the default Valo intranet components. For instance, it will enable you to open specific panels, like the page creation panel, from within your web parts or extensions. For more information, please check Triggers documentation. Parameters Parameter Type Description item-id string Id of the target List item of the action list-id string Id of the list where the list item is located site-url string The URL of the site where the list item is located unique-id string Unique ID of the HTML element to click to trigger the action &copy; 2022 Made with #ValoLove 526 Valo Web components Parameter Type Description The type of action to trigger. Accepted values are edit, action-type string content-type-name string The name of the content type of the target list item exclude-fields string array The list of fields to exclude from the opened panel panel-backgroundimage-url string The URL of the background image of the opened panel panel-title string The Title of the opened panel initial-panel-values JSON object The object of initial values to set (for creation panel) view or create Usage 1 2 3 4 5 6 7 8 9 10 11 12 <valo-trigger item-id="{{ListItemID}}" list-id="{{ListID}}" site-url="{{SPWebUrl}}" unique-id="{{UniqueId}}" trigger-type="EventsPanel|PagePanel|NewsPanel|..." action-type="edit|view|create" content-type-name="CTName" exclude-fields="[field1,field2,..]" panel-background-image-url="http://image-url" panel-title="Title of the panel" initial-panel-values='{"Title":"ValoLove", "Description":"#ValoHackaton", "EventDate":"2020-12-02T04:42: </valo-trigger> 13 &copy; 2022 Made with #ValoLove 527 Valo Extensibility Framework Valo Extensibility Framework Last updated on 2022-02-17 • 5 min read Summary Warning In the Valo Intranet 1.4 release, the extensibility framework was introduced as an experimental feature. Since 1.6, some of the extensibility features are now globally available. Other functions might still be under experimental mode available only. You can find more information on how to enable the experimental features here: enable experimental features With the Valo Extensibility Framework, you can make the Valo Intranet fit your needs or that of your client. It allows you to bind into or global navigation/footer experience, use some of our providers/services and add your custom data sources to be used in the Universal Web Part. You can find the extensibility framework published on npm here: @valo/extensibility. The following extension points are currently available globally (starting from @valo/extensibility@1.4.0): • Custom data sources that can be used in the Universal Web Part • Adding your custom React components to our global navigation/footer experience ◦ Navigation ▪ Left ▪ Right ▪ Top ▪ Bottom ◦ Footer • Using our providers/services ◦ Config ◦ UserProfile ◦ AzureAdToken ◦ Search ◦ StorageEntity ◦ ClientStorage • Triggering certain actions in our global navigation/footer experience ◦ OpenPageCreationPanel ◦ OpenNewsCreationPanel ◦ OpenEventCreationPanel ◦ OpenImportantMessageCreationPanel ◦ OpenMultilingualCreationPanel ◦ OpenSiteCreationPanel ◦ OpenSiteConfigurationPanel ◦ OpenPollCreationPanel ◦ OpenBlogCreationPanel (beta 1.7) • Custom web component support within the Handlebar templates Follow our getting started guide to start developing your own Valo Intranet extensions. &copy; 2022 Made with #ValoLove 528 Valo Extensibility Framework Custom data sources Custom data sources allow you to create your data providers and use them in the Universal Web Part. Custom data sources allow scenarios like fetching data from other external systems and integrating that into your intranet. Once you created a custom data source and it is loaded on the page, the Universal Web Part will allow you to select the in the available data source dropdown. Extension points The extensibility framework supports the following extension points: • Footer: allows you to override the default loaded footer • NavigationBottom: render your component underneath our navigation • NavigationLeft: render your component next to the hub site logo (IMPORTANT: for the best experience, keep the component dimensions small) &copy; 2022 Made with #ValoLove 529 Valo Extensibility Framework • NavigationRight: render your component next to the information messages icon (IMPORTANT: for the best experience, keep the component dimensions small) • NavigationTop: render your component on top of our navigation Currently, the following extension points are only available in experimental mode: • OverwriteNavigationGroupHeader: Allows you to overwrite the header element in the global navigation / mega menu • OverwriteNavigationItemLink: Allows you to overwrite the link element in the global navigation / mega menu. Example use could be to allow you to include an icon. • ToolboxAction: Allows you to add custom toolbox actions. • ToolboxPanelCreationAction: Allows you to add your custom toolbox actions in the content creation panel. • MegaMenuBeforeNavigationItems: Allows you to add navigation items before the navigation elements of the current hub site. This extension point can, for example, be used for a global/local hub site navigation. • MegaMenuAfterNavigationItems: Allows you to add navigation items after the navigation elements of the current hub site. This extension point can, for example, be used for a global/local hub site navigation. Here you can see all the extension points in action: Warning When adding your components to our global navigation/footer experience, we do not have any control over them. Because you get all control over them, it means you will have to take care of how they render on each device. For instance, the NavigationLeft and NavigationRight do not have a lot of space that can be used, so test it carefully if it fits appropriately. &copy; 2022 Made with #ValoLove 530 Valo Extensibility Framework Provider and services The purpose of the providers/services is not to extend, but more for you to leverage what we use. Currently, we support you to use the following providers/services: • Config: this provider returns the whole navigation/config object, which is used in our global navigation extension. • UserProfile: this provider allows you to use our user profile service, which can retrieve all user profile properties or a specific one. • AzureAdToken: service which can be used to retrieve an access token from Azure AD • Search: the search service which is used for our global navigation and universal web part • StorageEntity: retrieve values from storage entities • ClientStorage: service for retrieving/storing/deleting data in the local/session storage of the browser The following service will be available in beta: • Multilingual: This service allows you to retreive the current page, current multilingual page connections, site connections and all language terms. • MyTools (v1.7): This service allows you to asynchronously retrieve the Our Tools and My Tools links. • NavigationHierarchy (v1.7): This service allows provides you the whole navigation hierarchy. • NotificationProvider (v1.7): This service allows you to push/update/hide notification messages in the Information Messages panel. Triggers Triggers are extensions where you can invoke actions that will do something in the provided functionality from Valo. For example, you can use it to open the page creation panel, event creation panel, and more. Custom web components (Experimental only) In the external templates used for the Universal Web Part, you can add your scripts or custom helpers. One of the downsides is that it is hard to control async logic. Due to these limitations, we added Custom Web Components support. Web Components are a set of features that provide a standard component model for the web allowing for encapsulation and interoperability of individual HTML elements. The benefit for you is that you are in control of these web components, and you can perform async actions smoothly. For instructions on how to implement and use these web components, follow this guide: Implementing your web components. Changelog @valo/extensibility 1.8.0 • Added support to load multiple web component library projects • Handlebars TypeScript interfaces 1.7.0 • Added the MyToolsProvider service. • Added the NavigationHierarchy service. &copy; 2022 Made with #ValoLove 531 Valo Extensibility Framework • Added the NotificationProvider service. • Added the OpenBlogCreationPanel service. 1.6.0 • Fixed the provider and trigger services to correctly remove the unbinded providers. 1.5.1 • Removed the ApplicationCustomizerContext from the BaseDataSourceProvider. 1.5.0 • Added the new MultilingualProvider service 1.4.1 • Re-added the PageNavigation intranet trigger 1.4.0 • Custom data sources are now supported in GA • New providers and services added + GA • Extension points taken into GA + additional ones available in Experimental mode • Custom web components support in Experimental mode 1.3.0 • Internal optimizations 1.2.0 • Internal optimizations 1.1.0 • Included service versioning 1.0.0 • First version available for partners to test 0.0.1 • Alpha version of the extensibility framework for internal testing only &copy; 2022 Made with #ValoLove 532 Developing on top of Valo Intranet Developing on top of Valo Intranet Last updated on 2020-12-09 • 2 min read Summary So you want to start developing or extending the Valo Intranet experience. The extensibility framework offers a couple of capabilities to extend the current experience for your clients. Sample project The best way to learn and see the capabilities is by using the extensibility framework sample. The sample project is provided on GitHub, and you can find it here: https://github.com/ValoIntranet/valo-extensibility-sample. Extending the experience There are multiple options to start extending the experience. The best way is to start from a new SharePoint framework project. The component type depends on the functionality you want to add: Web Part: can be used for a custom data source and only want to use it on one specific page or a few pages. Application Customizer: you can use this to implement all functionalities. The advantage of this is that your extensibility will be globally available on the site and can be used on any page. Library: only for custom web components. More information can be found here: WebComponents. Steps to start: • Create a new SPFx application customizer or web part solution; • Once the project is created, and all SharePoint Framework dependencies are installed. You can go forward with installing the @valo/extensibility dependency. The install of the dependency can be done with the following command: npm i @valo/ extensibility -S -E. • The next steps depend on what you try to extend in Valo Intranet ◦ Data source creation ◦ Extension creation ◦ Provider/service usage ◦ Triggers ◦ WebComponents &copy; 2022 Made with #ValoLove 533 Creating a custom data source Creating a custom data source Last updated on 2021-06-11 • 2 min read Summary Info Custom data sources are GA-ed since version 1.6. To use it, be sure to use at least @valo/extensibility version 1.10.0-6030eb58d21176cd49cb6d2c4c27bc4b86e52a8a. Custom data sources allow you to fetch data from an external/internal end-point and get it rendered by the Valo Universal Web Part as we do not always know where data within your company is located and structured. This functionality allows you to overcome the limitation and need to develop an entirely new web part. Another advantage for you is that you can make use of the features already implemented in the Universal Web Part, like data visualization, caching, and more. Developing steps Follow the next steps in order to create a new custom data source: • In your application customizers class add a new dataSourceService property: 1 private dataSourceService: DataSourceService = null; • In your application customizers class constructor retrieve its instance: 1 this.dataSourceService = DataSourceService.getInstance(); • Create a new file for the data source, and add the following contents (more samples can be found in the sample project under: src\extensions\extendValoUi\datasource): 1 2 3 4 import { BaseDataSourceProvider } from "@valo/extensibility"; export class NoPagingDataSource extends BaseDataSourceProvider { private defaultArray: number[] = [1, 2, 3, 4, 5]; 5 public async getData(lastUpdated: string) { const newArray = this.defaultArray.map(i => `Item ${i}`); return { items: newArray }; } 6 7 8 9 10 11 12 } • Back in the application customizer class you can register your custom data source as follows: &copy; 2022 Made with #ValoLove 534 Creating a custom data source 1 2 3 4 5 6 const staticDs = new StaticDataSource(); this.dataSourceService.registerDataSource({ dataSource: staticDs, id: "StaticDataSource", name: "Custom static data source" }); Warning One issue if you are adding data sources this way, is that they can only be registered one time on a page. If you want to use your data source multiple times and with different settings on the same page, you will have to do the registration a bit differently. This new type of registration became available in version 1.4.0 of the extensibility framework. For registering your custom data source to be reused on the same page, register it as follows: 1 2 3 4 5 this.dataSourceService.registerDataSource({ dataSourcePrototype: StaticDataSource.prototype, id: "StaticDataSource", name: "Custom static data source" }); Info: Notice the difference here that the prototype reference of the function needs to be provided. Information For custom data sources, we support three types of paging: 1. None (default): no paging (you can find an example in the NoPagingDataSource) 2. Static: the whole array is provided, and paging will be created by providing the itemsCountPerPage property pane field (you can find an example in the StaticDataSource) 3. Dynamic: paging is controlled by your data source, on each page request, the data source needs to provide the items to display (you can find an example in the DynamicPagingDataSource) &copy; 2022 Made with #ValoLove 535 Creating a custom extension to render in the navigation/footer Creating a custom extension to render in the navigation/footer Last updated on 2021-06-11 • 3 min read Summary Info Extensions are GA-ed since version 1.6. To use them, be sure to use at least @valo/extensibility version 1.10.0-6030eb58d21176cd49cb6d2c4c27bc4b86e52a8a. New extensions points will get added over time and will first be available in experimental mode only before they are globally available. As the name suggests, extensions allow you to add custom components to specified locations in the Valo intranet UI. Warning When adding your components to our global navigation/footer experience, we do not have any control over them. This means you have full control over your components, and you will have to take care of how they render on each device. For instance, the NavigationLeft and NavigationRight do not have a lot of space that can be used, so test it carefully if it fits appropriately. Developing steps The following steps are required to add an extension to your intranet: • Create a new file called <extension-name>.tsx • Add the following contents: 1 2 export default class CustomExtensions { private extensionService: ExtensionService = null; 3 constructor() { this.extensionService = ExtensionService.getInstance(); } 4 5 6 7 public register(): void { 8 9 10 11 } } • In the main application customizer file, add the following lines to the onInit method: 1 2 const customExt = new CustomExtensions(); customExt.register(); • Once this is in place, it is time to create your first extension. Go back to your new <extension-name>.tsx file, and add the following in the register method: 1 2 3 4 5 this.extensionService.registerExtension({ id: "NavigationTop", // This name needs to be unique location: IntranetLocation.NavigationTop, // Specify where you want to render you component element: <div style={{textAlign: "center", height: "20px"}}> 01F 446 </div> }); &copy; 2022 Made with #ValoLove 536 Creating a custom extension to render in the navigation/footer Globally available extension points Information The available extension points will update over time. At the moment, we support the following locations: • Footer: allows you to override the default loaded footer • NavigationBottom: render your component underneath our navigation • NavigationLeft: render your component next to the hub site logo (IMPORTANT: for the best experience, keep the component dimensions small) • NavigationRight: render your component next to the information messages icon (IMPORTANT: for the best experience, keep the component dimensions small) • NavigationTop: render your component on top of our navigation Warning When you would use location footer, this will completely override the default footer behavior (normally, we render the footer.html file from the hub site its config library). This footer extension point allows you to gain complete control over the footer experience. Extension points only available in experimental mode Information In version 1.4.0 of the extensibility framework, the following extension points became available. Be aware that you can only use them as over version 1.6.0 of Valo intranet. • OverwriteNavigationGroupHeader: Allows you to overwrite the header element in the global navigation / mega menu • OverwriteNavigationItemLink: Allows you to overwrite the link element in the global navigation / mega menu. Example use could be to allow you to include an icon. • ToolboxAction: Allows you to add custom toolbox actions. • ToolboxPanelCreationAction: Allows you to add your custom toolbox actions in the content creation panel. • MegaMenuBeforeNavigationItems: Allows you to add navigation items before the navigation elements of the current hub site. This extension point can, for example, be used for a global/local hub site navigation. • MegaMenuAfterNavigationItems: Allows you to add navigation items after the navigation elements of the current hub site. This extension point can, for example, be used for a global/local hub site navigation. Info: Example of each of these extension points are provided in the sample project. &copy; 2022 Made with #ValoLove 537 Using Microsoft Graph Toolkit (MGT) Using Microsoft Graph Toolkit (MGT) Last updated on 2021-07-06 • 2 min read Summary Starting with 2.1 release, we have added support for Microsoft Graph toolkit (MGT) components. The MGT components are web components and make it very easy to fetch data from Graph and display it in your web parts. In release 2.1 we are providing these components in the Organization chart web part, but you will need to change to the MGT template manually in the web part settings as it is not set as the default. Note • We use the Valo tokens app for authentication to Graph, so for any permission granted to the app you will be able to fetch and display data. • So, if some of the components don't work in your tenant, please check the permissions of Valo Tokens Azure AD app in the Azure AD portal. As per our testing - Agenda, File, File-list , Person components are supported. • MGT's GET component is also supported depending on the endpoint that you are calling. How to use There are two ways to use MGT in Valo - Universal web part: 1. Using Graph Data source with API endpoint specified. ◦ Add Valo - Universal web part on a page. ◦ Select Graph data source, enter the endpoint URL and select the template containing MGT components. ◦ You should see the data from Graph. ◦ You can check the example templates which use this approach - GraphDsMGTPersonDetails.html and GraphDsMGT-MyEvents ◦ The Graph Data source will handle making the Graph calls, caching and paging for your web part. 2. Using Graph Data source without API endpoint specified. ◦ Add Valo - Universal web part on a page. ◦ Select Graph data source and then select the template containing MGT components. ◦ The MGT component used is <mgt-get>. ◦ This will ensure that MGT will handle the Graph calls, caching and pagination. ◦ You can check an example template that uses this approach - GraphDsMGTUsers.html Info We have chosen [[ and ]] as the expression binding syntax. This helps us differentiate from standard handler template which use {{ and }} syntax. We have added necessary samples in the Valo extensibility sample repository. &copy; 2022 Made with #ValoLove 538 Using Microsoft Graph Toolkit (MGT) To read more about Microsoft Graph Toolkit please visit the official docs site here. You can also check the MGT playground site to check what all components are available for use and how they can look like in the UI. &copy; 2022 Made with #ValoLove 539 Using Valo Intranet Providers/Services Using Valo Intranet Providers/Services Last updated on 2022-02-17 • 2 min read Summary One of the advantages of the extensibility framework is that it allows you to use the Providers/Services that the Valo Intranet code uses. These providers make sure that you do not have to reinvent the wheel each time, and that it speeds up the process of extending your intranet with custom logic. At this point, we provide the following providers/services: • Config provider: this provider returns the whole navigation/config object, which is used in our global navigation extension. • User profile service: this provider allows you to use our user profile service, which can retrieve all user profile properties or a specific one. • AzureAdToken: service which can be used to retrieve an access token from Azure AD • Search: the search service which is used for our global navigation and universal web part • StorageEntity: retrieve values from storage entities • ClientStorage: service for retrieving/storing/deleting data in the local/session storage of the browser The following service will be available in beta: • Multilingual (v1.6): This service allows you to retreive the current page, current multilingual page connections, site connections and all language terms. • MyTools (v1.7): This service allows you to asynchronously retrieve the Our Tools and My Tools links. • NavigationHierarchy (v1.7): This service allows provides you the whole navigation hierarchy. • NotificationProvider (v1.7): This service allows you to push/update/hide notification messages in the Information Messages panel. Using our providers/services in your code Follow the next steps if you want to use one of our providers/services in your code: • In your application customizers class add a new providerService property: 1 private providerService: ProviderService = null; • In your application customizers class constructor retrieve its instance: 1 this.providerService = ProviderService.getInstance(); • Once the previous lines are in place, you can start using the provider like this: &copy; 2022 Made with #ValoLove 540 Using Valo Intranet Providers/Services 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // Config provider example const configProvider = await this.providerService.getProvider<any>(IntranetProvider.Config); if (configProvider && configProvider.instance) { console.log(`Config retrieved: ${JSON.stringify(configProvider.instance)}`); } else { console.log(`Config not retrieved`); } // User profile provider example const userProfileProvider = await this.providerService.getProvider<IUserProfileProvider>(IntranetProvider if (userProfileProvider && userProfileProvider.instance) { console.log("Department:", await userProfileProvider.instance.getUserProperty("Department" console.log("All properties:", await userProfileProvider.instance.getUserProperties()); } // Client storage provider example const clientStorage = await this.providerService.getProvider<IClientStorageProvider>(IntranetProvider if (clientStorage && clientStorage.instance) { const csService = clientStorage.instance as IClientStorageProvider; const storageKey = "Client:Extensibility:Navigation"; // Get a key from the cache let navigationItems = csService.get<MegaMenuItem[]>(storageKey); // Store a key and data to the cache csService.put(storageKey, {}, StorageType.localStorage, crntDate); } &copy; 2022 Made with #ValoLove 541 Using Intranet extensibility triggers Using Intranet extensibility triggers Last updated on 2021-03-26 • 3 min read Summary Triggers allow you to communicate and invoke actions to the default Valo intranet components. For instance, it will enable you to open specific panels, like the page creation panel, from within your web parts or extensions. Supported triggers In version 1.8.0 we changed the way how the triggers are invoked. Now, extensibility framework supports all the panels (view/create/ edit). Currently supported list of triggers: • PagePanel • PageNavigation • NewsPanel • EventsPanel • ImportantMessagePanel • MultilingualPagePanel • SitePanel • PollPanel • BlogPanel • GenericPanel • IntranetSettingsPanel • HomeIntranetPanel • TopicsSubscriptionsPanel &copy; 2022 Made with #ValoLove 542 Using Intranet extensibility triggers • ImportantMessagesPanel • OurLinksPanel • LightsaberPanel • AddFeaturesPanel Deprecated triggers As of version 2.0.0 of Valo intranet, the following triggers are going to be deprecated: • OpenBlogCreationPanel • OpenPageCreationPanel • OpenNewsCreationPanel • OpenEventCreationPanel • OpenImportantMessageCreationPanel • OpenMultilingualCreationPanel • OpenPollCreationPalen • OpenSiteCreationPanel • OpenSiteConfigurationPanel We will still support existing solutions based on the deprecated triggers, but it is recommended to use supported ones, due to additional possibilities like opening 'Edit Panel' for page / item. Using triggers in your code • In your application, customizers class add a new triggerService property: 1 private triggerService: TriggerService = null; - In your application customizers class constructor retrieve its instance: 1 this.triggerService = TriggerService.getInstance(); - Once the previous line is in place. You can create your custom experience to invoke triggers to our components. Here is the example of the above screenshot: &copy; 2022 Made with #ValoLove 543 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Using Intranet extensibility triggers let buttonStyles = { 'textAlign': 'center', 'padding': '15px' }; this.extensionService.registerExtension({ id: "NavigationBottom", location: IntranetLocation.NavigationBottom, element: ( <div style={buttonStyles}> <PrimaryButton onClick={async () => { const trigger = await this.triggerService.registerTrigger(IntranetTrigger.OpenPageCreationPanel if (trigger) { trigger.invokeTrigger(); } }}>Open page creation</PrimaryButton> </div> ) }); 19 • In order to use new triggers, TriggerService handler requires additional information to be passed (check ContextData / CreateContextData / ViewContextData interfaces): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 this.extensionService.registerExtension({ id: "NavigationBottom", location: IntranetLocation.NavigationBottom, element: ( <div style={buttonStyles}> <PrimaryButton onClick={async () => { const trigger = await this.triggerService.registerTrigger(IntranetTrigger.GenericPanel if (trigger) { trigger.invokeTrigger({ itemId, listId, siteUrl, webUrl, panelTitle, // Title of the panel contextActionType, // Supported actions: view/edit/create excludeFields, // Array of fields to be excluded from the panel panelBackgroundImageUrl, // 1.8: Supported only by Pages/News, Events View Pane initialPanelValues // Supported only for Create panels. Allows to pass an }); } }}>Open page creation</PrimaryButton> </div> ) }); 24 Full specification of the supported interfaces passed as an argument to invokeTrigger method can be found in the extensibility framework documentation/package. Please note that the provided example shows how to open 'GenericPanel' which supports all the actions for non Valo lists. This functionality is enabled as beta and will work on the environments with 'experimental mode' flag set to true. It is recommended to use 'typed' types of panels (PagePanel, EventsPanel, ...) supported by Valo for getting full experience. Using triggers in your hbs templates In order to ease the panel behaviour, we have prepared a special web component that will ease the process of incorporation triggers into Valo Universal WebPart handlebars templates. Let's consider piece of code coming from events-compact.html template: &copy; 2022 Made with #ValoLove 544 1 Using Intranet extensibility triggers <!-- ... --> 2 3 4 5 6 7 8 9 10 {{setVariable "elementId" (generateId)}} <div class="valo-events__item ms-sm4 vm-Card showTransition" title="" id="{{@root.elementId}}"> <!-- Content t display --> </div> <!-ValoTrigger web component allows to easily bind the ExtensibilityTrigger behaviour to the HTML 'click' event. The only thing that is required is adding 'valo-trigger' component with required properties (like ListItemId, Li 13 Note: It is required that the element with specified ID is in the DOM before valo-trigger component is added. --> <valo-trigger unique-id="{{@root.elementId}}" item-id="{{ListItemID}}" list-id="{{ListID}}" site-url panel-title="{{Title}}" trigger-type="EventsPanel" action-type="view" style="display: none;"></valo-trigger 14 15 <!-- ... --> 11 12 16 &copy; 2022 Made with #ValoLove 545 Using custom Web Components in your external templates Using custom Web Components in your external templates Last updated on 2020-09-14 • 3 min read Summary In the external templates used for the Universal Web Part, you can add your scripts or custom helpers. One of the downsides is that it is hard to control async logic. Due to these limitations, we added Custom Web Components support. Web Components are a set of features that provide a standard component model for the web allowing for encapsulation and interoperability of individual HTML elements. Support for this kind of functionality will enable you to create your components and use them in an external template. The benefit for you is that you have more control over these components, and you can perform async actions smoothly. Prerequisites To make use of custom web components in your external templates, you can make use of the provided Valo Intranet Web Components project on GitHub. play_circle_filledImportant There can only be one library component with the same ID loaded on the page. If you want to split up your components in multiple projects, you will need to specify the library components' other IDs that need to be loaded. The default aa138b33-2075-4bf8-9154-613ed92f01cd library component ID will automatically be loaded if available. All others can be added as a ; separated value in the ExtensibilityWebComponentLibIds config property on the Valo Admin site. Be aware. This functionality is only supported as of version 1.8. Information You can find the web component which you need to use here: https://github.com/ValoIntranet/valo-intranet-webcomponents The reason why you need to make use of the project is because of the hardcoded reference for loading the library component. Create your custom web components A web component is a custom HTML element you can use in any of your external templates. We used them here as "wrappers" for React components to be able to use them with Handlebars. Follow the next steps to start and using your custom web components: • Clone the project: git clone https://github.com/ValoIntranet/valointranet-webcomponents • Open the project in your favorite code editor • In this project, you can find a sample web component • In the ./src/libraries/valoWebComponents/components folder, create a new folder with the name of the component you want to create. • Create a <your-component-name>.tsx file in the new folder with the following contents (adapt the contents to your needs): &copy; 2022 Made with #ValoLove 546 Using custom Web Components in your external templates 1 2 3 4 5 6 7 8 import * as React from 'react'; import * as ReactDOM from 'react-dom'; export interface ICustomComponentProps {} export interface ICustomComponenState {} export class CustomComponent extends React.Component<ICustomComponentProps, ICustomComponenState 9 10 public render() { return <h1>Hello Valo World!</h1>; } 11 12 } 13 • Create a <your-component-name>WebComponent.tsx file in the new folder with the following contents: 1 2 3 4 5 6 import import import import public constructor() { super(); } 8 9 10 11 public async connectedCallback() { 12 13 14 let props = this.resolveAttributes(); // You can use this._ctx here to access current Web Part context const customComponent = <CustomComponent {...props} />; ReactDOM.render(customComponent, this); 15 16 18 19 as React from 'react'; as ReactDOM from 'react-dom'; BaseWebComponent } from '@valo/extensibility'; CustomComponent } from '.'; export class CustomComponentWebComponent extends BaseWebComponent { 7 17 * * { { } } • Once your web component is ready, add its reference in the ValoWebComponentsLibrary.ts file within the getWebComponents method like this: 1 { name: 'custom-component', // Component name used in the Handlebars template class: CustomComponentWebComponent // Reference to the web component class 2 3 4 } • Bundle gulp bundle --ship and package your library gulp package-solution --ship and upload it either in the tenant or site app catalog. Using your web component in your template To use the new web component in your template, follow the next steps: • Create a new external template. More information can be found here: Handlebars templates. &copy; 2022 Made with #ValoLove 547 Using custom Web Components in your external templates • Add your custom web component to the HTML section as follows: <custom-component />. • If you want you can also pass properties as follows: <custom-component propone="Value" />. • You can use these properties in code as follows: this.props.propOne. &copy; 2022 Made with #ValoLove