{"id":445,"date":"2023-04-19T11:18:34","date_gmt":"2023-04-19T09:18:34","guid":{"rendered":"https:\/\/www.paalolav.no\/?p=445"},"modified":"2023-04-19T14:17:29","modified_gmt":"2023-04-19T12:17:29","slug":"related-news-in-sharepoint","status":"publish","type":"post","link":"https:\/\/www.paalolav.no\/?p=445","title":{"rendered":"Related news in SharePoint"},"content":{"rendered":"\n<p>Quite a few customers have asked me for a solution for automatic linking of related articles on their modern SharePoint intranet. I&#8217;ve drummed together a solution using PnP Modern Search and Term store. This solution requires that each news article (or page) is tagged with a single metadata column.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/www.paalolav.no\/wp-content\/uploads\/2023\/04\/RelatedNews.png\"><img loading=\"lazy\" decoding=\"async\" width=\"658\" height=\"1024\" src=\"https:\/\/www.paalolav.no\/wp-content\/uploads\/2023\/04\/RelatedNews-658x1024.png\" alt=\"\" class=\"wp-image-446\" srcset=\"https:\/\/www.paalolav.no\/wp-content\/uploads\/2023\/04\/RelatedNews-658x1024.png 658w, https:\/\/www.paalolav.no\/wp-content\/uploads\/2023\/04\/RelatedNews-193x300.png 193w, https:\/\/www.paalolav.no\/wp-content\/uploads\/2023\/04\/RelatedNews.png 730w\" sizes=\"(max-width: 658px) 100vw, 658px\" \/><\/a><\/figure>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The template in Modern PnP Search:\n<ul class=\"wp-block-list\">\n<li><\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\" style=\"font-size:12px\"><code>&lt;content id=\"data-content\"&gt;\n\n    &lt;style&gt;\n        .template--card {\n            flex-grow: 1;\n            flex-shrink: 1;\n            min-width: 206px; \/* Min width of the Office UI Fabric document card *\/\n            flex-basis: {{@root.properties.layoutProperties.columnSizePercentage}}%;\n            margin: 0px -10px 0px -8px;\n        }\n        .template--header{\n            display:none;\n        }\n        .ms-DocumentCardPreview{\n            max-height:76px;\n            border-radius: 5px;\n            border:1px solid rgb(93, 141, 169);\n        }\n        .ms-Image{\n            max-height:75px;\n            margin: -1px 0 0 0;\n        }\n        .ms-DocumentCard--compact {\n            height:75px!important;\n            box-shadow: none;\n            border-radius: 5px;\n            }\n        .ms-DocumentCardTitle {\n            font-size: 14px;\n            font-weight: 400;\n        }\n    &lt;\/style&gt;\n\n    &lt;div class=\"template\"&gt;\n       \n        &lt;div class=\"template--header\"&gt;\n            {{#if @root.properties.showResultsCount}}\n                &lt;div class=\"template--resultCount\"&gt;\n                    &lt;label class=\"ms-fontWeight-semibold\"&gt;{{getCountMessage @root.data.totalItemsCount @root.inputQueryText}}&lt;\/label&gt;\n                &lt;\/div&gt;\n            {{\/if}}\n\n            &lt;div class=\"template--sort\"&gt;\n                &lt;pnp-sortfield \n                    data-fields=\"{{JSONstringify @root.properties.dataSourceProperties.sortList}}\" \n                    data-default-selected-field=\"{{sort.selectedSortFieldName}}\" \n                    data-default-direction=\"{{sort.selectedSortDirection}}\"\n                    data-theme-variant=\"{{JSONstringify @root.theme}}\"&gt;\n                &lt;\/pnp-sortfield&gt;    \n            &lt;\/div&gt;\n        &lt;\/div&gt;\n\n        &lt;div class=\"template--cardContainer\"&gt;\n            {{#each data.items as |item|}}    \n            \n                {{#&gt; resultTypes item=item}}\n                    &lt;pnp-documentcard class=\"template--card\" \n                        data-ui-test-id=\"resultCard\" \n                        data-item=\"{{JSONstringify item}}\" \n                        data-enable-preview=\"false\" \n                        data-show-file-icon=\"false\" \n                        data-is-compact=\"true\" \n                        data-context=\"{{JSONstringify @root}}\"\n                        data-instance-id=\"{{@root.instanceId}}\"\n                        data-theme-variant=\"{{JSONstringify @root.theme}}\"\n                        data-allow-item-selection=\"{{@root.properties.itemSelectionProps.allowItemSelection}}\"\n                        data-item-key=\"{{@root.paging.currentPageNumber}}{{@index}}\"                     \n                        data-selected-keys=\"{{JSONstringify @root.selectedKeys}}\"\n                        data-index=\"{{@index}}\"\n                        data-title=\"{{slot item @root.slots.Title}}\"\n                        data-preview-image=\"{{slot item @root.slots.PreviewImageUrl}}\" \n                        data-preview-url=\"{{slot item @root.slots.PreviewUrl}}\" \n                        data-href=\"{{slot item @root.slots.Path}}\" \n                        &gt;\n                    &lt;\/pnp-documentcard&gt;\n                {{\/resultTypes}}\n\n            {{\/each}}\n\n            &lt;!-- Generate fake items to correctly align cards on rows using flexbox --&gt;\n            {{#times @root.properties.layoutProperties.preferedCardNumberPerRow}}\n                &lt;pnp-documentcard \n                    class=\"template--card\" \n                    data-ui-test-id=\"fakeCard\"\n                    data-theme-variant=\"{{JSONstringify @root.theme}}\"\n                    style=\"visibility:hidden;height: 0;padding: 0\"&gt;\n                &lt;\/pnp-documentcard&gt;\n            {{\/times}}\n        &lt;\/div&gt;\n\n        {{#if @root.properties.paging.showPaging}}\n\n            {{#gt @root.data.totalItemsCount @root.properties.paging.itemsCountPerPage}}\n                &lt;pnp-pagination \n                    data-total-items=\"{{@root.data.totalItemsCount}}\" \n                    data-hide-first-last-pages=\"{{@root.properties.paging.hideFirstLastPages}}\"\n                    data-hide-disabled=\"{{@root.properties.paging.hideDisabled}}\"\n                    data-hide-navigation=\"{{@root.properties.paging.hideNavigation}}\"\n                    data-range=\"{{@root.properties.paging.pagingRange}}\" \n                    data-items-count-per-page=\"{{@root.properties.paging.itemsCountPerPage}}\" \n                    data-current-page-number=\"{{@root.paging.currentPageNumber}}\"\n                    data-theme-variant=\"{{JSONstringify @root.theme}}\"\n                &gt;\n                &lt;\/pnp-pagination&gt;\n            {{\/gt}}\n            \n        {{\/if}}\n\n    &lt;\/div&gt;\n\n&lt;\/content&gt;\n\n&lt;content id=\"placeholder-content\"&gt;   \n\n        &lt;style&gt;\n            \/* Assign the correct size % ratio according to the number of wanted cards on a single row. We use flexbox instead of static grid to deal with SharePoint canvas sections*\/\n            .template--card {\n                flex-grow: 1;\n                flex-shrink: 1;\n                min-width: 206px; \/* Min width of the Office UI Fabric document card *\/\n                flex-basis: {{@root.properties.layoutProperties.columnSizePercentage}}%;\n            }    \n        &lt;\/style&gt;\n\n    &lt;div class=\"placeholder\"&gt;\n\n        {{!-- #if showResultsCount --}}\n        &lt;div class=\"template--resultCount\"&gt;\n            &lt;span class=\"placeholder--shimmer placeholder--line\" style=\"width: 20%\"&gt;&lt;\/span&gt;\n        &lt;\/div&gt;\n        {{!-- \/if --}}\n        &lt;div class=\"template--cardContainer\"&gt;\n\n            {{#times @root.properties.paging.itemsCountPerPage}}\n                &lt;pnp-documentcardshimmers class=\"template--card\" \n                    data-ui-test-id=\"fakeCard\"\n                    data-theme-variant=\"{{JSONstringify @root.theme}}\"\n                    data-is-compact=\"true\"&gt;\n                &lt;\/pnp-documentcardshimmers&gt;\n            {{\/times}}\n\n            &lt;!-- Generate fake items to correctly align cards on rows using flexbox --&gt;\n            {{#times @root.properties.layoutProperties.preferedCardNumberPerRow}}\n                &lt;pnp-documentcard class=\"template--card\" \n                    data-ui-test-id=\"fakeCard\"\n                    data-theme-variant=\"{{JSONstringify @root.theme}}\"\n                    style=\"visibility:hidden;height: 0;padding: 0\"&gt;\n                &lt;\/pnp-documentcard&gt;\n            {{\/times}}\n        &lt;\/div&gt;\n\n    &lt;\/div&gt;\n&lt;\/content&gt;<\/code><\/pre>\n\n\n\n<p>2. The search query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DepartmentId:{{Hub.HubSiteId}} AND\nPromotedState:2 AND\n{|owstaxidCategories:{Page.Categories.TermID}} \n-Path:{Page}<\/code><\/pre>\n\n\n\n<p>3. Create a Term set for page categories and connect this to a column (multi choice) on the SitePages library on your news site(s). If you need to use this on several sites, consider creating an Azure Automation for this or a site template. This example uses a site column, called &#8216;Categories&#8217;.<\/p>\n\n\n\n<p>4. Add PnP Modern Search with the template and query on your news templates. Remember to limit the results and sort by firstpublisheddate. I&#8217;d also like to recommend to sync templates on all sites that hosts news stories on your intranet. Logic app or Power Automate to the rescue&#8230;<\/p>\n\n\n\n<p>5. Each news post will now display other posts that are relevant.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Quite a few customers have asked me for a solution for automatic linking of related articles on their modern SharePoint intranet. I&#8217;ve drummed together a solution using PnP Modern Search and Term store. This solution requires that each news article (or page) is tagged with a single metadata column. 2. The search query: 3. Create [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":459,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[70,67,76],"tags":[],"class_list":["post-445","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-intranet","category-sharepoint","category-search"],"_links":{"self":[{"href":"https:\/\/www.paalolav.no\/index.php?rest_route=\/wp\/v2\/posts\/445"}],"collection":[{"href":"https:\/\/www.paalolav.no\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.paalolav.no\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.paalolav.no\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.paalolav.no\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=445"}],"version-history":[{"count":3,"href":"https:\/\/www.paalolav.no\/index.php?rest_route=\/wp\/v2\/posts\/445\/revisions"}],"predecessor-version":[{"id":450,"href":"https:\/\/www.paalolav.no\/index.php?rest_route=\/wp\/v2\/posts\/445\/revisions\/450"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.paalolav.no\/index.php?rest_route=\/wp\/v2\/media\/459"}],"wp:attachment":[{"href":"https:\/\/www.paalolav.no\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=445"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.paalolav.no\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=445"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.paalolav.no\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=445"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}