- 0 minutes to read

Templates

New 7.11

Standardize how a category of Article begins. A Template copies its content, content type, tags, and Custom Metadata into every new Article created from it — so a runbook, a design document, or an onboarding guide always starts from the same shape instead of a blank page. A Template can also use a Document Profile, and then supplies the starter text for each of the profile's sections.

  • ✅ Start new Articles from a consistent, pre-approved shape
  • ✅ Pair a Template with a Document Profile: the profile sets the structure, the Template fills in the starter text
  • ✅ Keep reusable macro placeholders in the Template body
  • ✅ Resolve Resource and C4 node macros from context when available
  • ✅ Trace every Article back to the Template it came from

Understanding Templates

A Template is a starting point for new Articles — its content, content type, tags, and Custom Metadata are copied into every Article created from it. Unlike a Snippet, a Template's content isn't included by reference: it's copied once, at creation, and the new Article is then free to diverge from it.

graph TD Template[fa:fa-clone Template: Incident Runbook] ArticleA[fa:fa-newspaper Article: DB Outage Runbook] ArticleB[fa:fa-newspaper Article: API Outage Runbook] Template -- Create From Template --> ArticleA Template -- Create From Template --> ArticleB ArticleA -- Based On Template --> Template ArticleB -- Based On Template --> Template

Two Articles created from the same Template. Each copy is independent after creation, but both remember their Source Template.

Concept Behavior
Copied at creation Content, content type, tags, and Custom Metadata — plus the Document Profile and the text of each Content Part, when the Template uses a profile
Independent afterward Editing the Template does not change Articles already created from it
Source Template Recorded on the new Article; visible in the reader and relationship views

Profile-Based Templates

New 7.11

A Template can use a Document Profile, just like an Article. The three document types then share the work:

graph LR Profile[fa:fa-list-check Document Profile - structure] Template[fa:fa-clone Template - starter text per section] Article[fa:fa-newspaper Article - the instance] Profile -- Structures --> Template Profile -- Structures --> Article Template -- Create From Template --> Article style Profile fill:#2678BD style Template fill:#E47528 style Article fill:#93d16d

The Document Profile (blue) owns the structure, the Template (orange) owns the starter text for each Content Part, and the Article (green) is the instance a user writes.

Owns
Document Profile The structure: Snippet Parts and Content Part slots
Template Starter text for each Content Part, plus tags and Custom Metadata
Article Its own text, written from that starting point
  • Editing the Template — choose a Document Profile in the Template editor, and the Template is shown in the same composite workspace as an Article: Snippet Parts locked, and one editor per Content Part for its starter text. The Template's reader shows the composed document.
  • Creating an Article from it — the new Article starts profile-based: the Template's Document Profile is preselected, and the Main Body and every other Content Part start with the Template's text. Template variables found in any Content Part are listed to fill in, as for the Main Body.
  • A Template without a profile — works as before: one body, copied into the new Article.

Seeded Example Template

On a new installation, Nodinite seeds the Standard Technical Base Template, which uses the seeded Standard Technical Article Document Profile. It supplies starter text for the profile's two Content Parts — Describe purpose and scope. for the Overview Main Body, and Describe implementation details and operational context. for Details — while the profile supplies the header, Next Step, Related Topics, footer, and copyright Snippet Parts.

Note

An upgraded installation keeps the seeded Template it already has: a single body with its own headings and Snippet include tokens, and no Document Profile.

Macros in Template-Based Articles

Templates can contain the same macros as regular Articles. Macro placeholders are kept in the content and resolved when the Article is displayed.

Macro group Example Resolution behavior
Date and time {{ today }}, {{ now.utc }} Resolved at display time
Article {{ article.title }}, {{ article.url }} Resolved from the current Article
Environment {{ environmentname }} Resolved from the active environment
Resource / C4 node {{ resource.name }}, {{ node.name }} Resolved when the Article is opened in the matching context

The editor's Template Guidance card summarizes how template content, Source Template tracking, and macro behavior work together, and that a Template may use a Document Profile whose Content Parts become the starter text of new Articles.

Template Guidance card in the article editor (7.11)
Example of the Template Guidance card shown in the editor.

Create an Article From a Template

  1. Start creating a new Article
  2. Choose Create From Template
  3. Pick a Template from the list
  4. The Article's content, content type, tags, and Custom Metadata are copied in; for a profile-based Template, the Document Profile is preselected and each Content Part starts with the Template's text

You can also start from a Template in one click: the Add Article dropdown's From Template…, the Create Article From Template row action on the Templates overview, and the Create Article from this Template button on a Template's editor and reader pages. See Ways to Create an Article for every entry point and the templateId deep link. When a link carries both templateId and profileId, a profile-based Template's own Document Profile wins.

Create From Template picker shown when creating a new Article (7.11)
Example of choosing a Template while creating a new Article.

Macro Resolution Context

Some macros need context from where the Article is opened:

  • Opening the Article from a Resource provides resource.* values
  • Opening the Article from a C4 diagram node provides node.* values

If that context is missing, those macros remain unresolved until the Article is viewed in a matching context.

An Article created from a Template remembers it. The reader and relationship views show Based On Template, linking back to the Template it came from — even after the Article's own content has since changed completely.

Copy an Article as a Template

New 7.11

Your best Article is often the best starting point for the next one. Copy as Template turns an existing Article into a new Template, and leaves the Article itself untouched.

  1. Choose Copy as Template, either from the Article's row Action menu on the Articles overview, or from the Clone dropdown in the Article editor's header
  2. The Duplicate dialog suggests the title (Template)</em>; change it if you like</li> <li>Confirm — the new Template is created, and it opens in the browser</li> </ol> <p><a href="Integration%20Manager/Documentation/Repository%20Model/Knowledge%20base%20Articles/Features/%7Bndm%7D/Documentation%20Pictures/IM/WebClient/Repository/Articles/CloneSplitButtonCopyAsTemplate.png" class="img-fluid" data-title="Clone split button in the Article editor header, with Copy as Template in the dropdown (7.11)" data-toggle="lightbox" data-type="image" data-gallery="docpage"><img src="Integration%20Manager/Documentation/Repository%20Model/Knowledge%20base%20Articles/Features/%7Bndm%7D/Documentation%20Pictures/IM/WebClient/Repository/Articles/CloneSplitButtonCopyAsTemplate.png" alt="Clone split button in the Article editor header, with Copy as Template in the dropdown (7.11)" /></a><br /> <em>Example of Copy as Template in the Article editor's Clone dropdown.</em></p> <table class="table"> <thead> <tr> <th>What happens</th> <th>Behavior</th> </tr> </thead> <tbody> <tr> <td>Copied</td> <td>Title (as entered in the dialog), content, content type, tags, Custom Metadata, and the Document Profile when the Article uses one</td> </tr> <tr> <td>Not copied</td> <td>Resource, Application, and Category links, because a Template has none of them</td> </tr> <tr> <td>Profile-based Article</td> <td>The Template keeps the Article's Document Profile: the Main Body becomes the Template's body, and every other Content Part keeps its text as starter text. The Snippet Parts still come from the profile, so they aren't copied into the Template</td> </tr> <tr> <td>Plain Article</td> <td>The Template gets the Article's single body, as is</td> </tr> <tr> <td>Relationship</td> <td>The Template's <strong>Clone Source</strong> points at the original Article, so the <a href="/Documentation/RepositoryModel?doc=/Knowledge%20base%20Articles/Features/%7Bndr%7D/Repository%20Model/Knowledge%20base%20Articles/Features/Reading%20Articles">relationship views</a> show where it came from. It has no Source Template</td> </tr> <tr> <td>Original Article</td> <td>Not modified. There's no in-place conversion: a document's kind never changes after it's created</td> </tr> <tr> <td>Permission</td> <td><strong>Create Article</strong> (<code>Repository_Article_Create</code>), the same as Add and Clone</td> </tr> </tbody> </table> <p>Copy as Template is available for Articles only. To go the other way, create an Article from the Template as described above.</p> <h3 id="fa-code-web-api"><i class="fal fa-code"></i> Web API <a title="Go to headline" class="x-hidden-focus" href="#fa-code-web-api"><i class="fal fa-link"></i></a></h3> <p>Copy as Template uses the existing duplicate endpoint with a new optional query parameter, <code>targetDocumentType</code>:</p> <pre class="line-numbers"><code class="language-http">POST api/Articles/{id}/Duplicate?targetDocumentType=Template Content-Type: application/json { "Name": "Incident Runbook (Template)" } </code></pre> <table class="table"> <thead> <tr> <th><code>targetDocumentType</code></th> <th>Result</th> </tr> </thead> <tbody> <tr> <td>Omitted</td> <td>A copy of the same kind, as before</td> </tr> <tr> <td><code>Template</code> (or <code>2</code>), with an Article as the source</td> <td>The copy is written as a Template, following the rules above</td> </tr> <tr> <td>Any other value that changes the kind</td> <td><code>400 Bad Request</code>, with an input error on <code>TargetDocumentType</code></td> </tr> </tbody> </table> <p>The request body is unchanged, and the response is the created document with <code>201 Created</code>.</p> <h2 id="fa-hand-point-right-next-step"><i class="fal fa-hand-point-right"></i> Next Step <a title="Go to headline" class="x-hidden-focus" href="#fa-hand-point-right-next-step"><i class="fal fa-link"></i></a></h2> <ul> <li><i class="fal fa-code"></i> <a href="/Documentation/RepositoryModel?doc=/Knowledge%20base%20Articles/Features/%7Bndr%7D/Repository%20Model/Knowledge%20base%20Articles/Features/Macros%20Reference">Macros Reference</a></li> <li><i class="fal fa-list-check"></i> <a href="/Documentation/RepositoryModel?doc=/Knowledge%20base%20Articles/Features/%7Bndr%7D/Repository%20Model/Knowledge%20base%20Articles/Features/Document%20Profiles">Document Profiles</a></li> </ul> <h2 id="fa-link-horizontal-related-topics"><i class="fal fa-link-horizontal"></i> Related Topics <a title="Go to headline" class="x-hidden-focus" href="#fa-link-horizontal-related-topics"><i class="fal fa-link"></i></a></h2> <ul> <li><i class="fal fa-newspaper"></i> <a href="/Documentation/RepositoryModel?doc=/Knowledge%20base%20Articles/Features/%7Bndr%7D/Repository%20Model/Knowledge%20base%20Articles/Overview">Knowledge base Articles</a></li> <li><i class="fal fa-puzzle-piece"></i> <a href="/Documentation/RepositoryModel?doc=/Knowledge%20base%20Articles/Features/%7Bndr%7D/Repository%20Model/Knowledge%20base%20Articles/Features/Snippets">Snippets</a></li> <li><i class="fal fa-book-open"></i> <a href="/Documentation/RepositoryModel?doc=/Knowledge%20base%20Articles/Features/%7Bndr%7D/Repository%20Model/Knowledge%20base%20Articles/Features/Reading%20Articles">Reading Articles</a></li> </ul> </div> </main> <div class="no-print d-none d-xl-block col-xl-3"> <div class="doc-toc sticky"> <p><b>Table of content</b></p> <nav id="toc"></nav> <div class="webinar-banner-container webinar-banner-docpage" style="gap:0.25rem;"> </div> </div> </div> </div> </div> </div> </div> <footer class="footer"> <div class="flex-column"> <div class="row"> <div class="col-lg-5 col-12 flex-column flex-gap-small newsletter-font mb-lg-0 mb-4"> <h1 class="footer-heading">Sign up to our Newsletter!</h1> <p>Get the latest news about Nodinite’s new features and product updates. No spam. Ever.</p> <script charset="utf-8" type="text/javascript" src="//js-eu1.hsforms.net/forms/shell.js"></script> <script> hbspt.forms.create({ region: "eu1", portalId: "25126156", formId: "d32f2d0e-f3f8-4c99-8f9f-3ee12f755dbc" }); </script> </div> <div class="col-lg-2 col-sm-4 col-12 flex-column flex-gap-small mb-4 mb-sm-0"> <h2 class="footer-heading">Company <i class="glyphicon fa-external-link-alt fas" aria-hidden="true"></i></h2> <a href="https://nodinite.com/about-us/">About us</a> <a href="https://nodinite.com/privacy-policy/">Privacy policy</a> <a href="https://nodinite.com/news/">News & Articles</a> <a href="https://nodinite.com/contact-us/">Contact</a> </div> <div class="col-lg-2 col-sm-4 col-12 flex-column flex-gap-small mb-4 mb-sm-0"> <h2 class="footer-heading"><a href="https://nodinite.com">Nodinite.com <i class="glyphicon fa-external-link-alt fas" aria-hidden="true"></i></a></h2> <a href="https://nodinite.com/features/">Features</a> <a href="https://nodinite.com/pricing/">Pricing</a> <a href="https://nodinite.com/resources/">Resources</a> <a href="https://nodinite.com/partners/">Partners</a> </div> <div class="col-lg-3 col-sm-4 col-12 flex-column flex-gap-small"> <h2 class="footer-heading">Contact</a></h2> <div>info(at)nodinite.com</div> <div>support(at)nodinite.com</div> <a class="btn btn-outline-light" href="https://nodinite.com/request-quote/">Request quote</a> </div> </div> <div class="flex-row flex-space-between"> <img src="https://nodinite.com/wp-content/uploads/2022/02/nodinite-logo-neg-payoff.png" /> <div class="flex-row flex-gap-small footer-icons"> <a href="https://www.facebook.com/nodinite/" title="Facebook"><i class="fab fa-facebook-square"></i></a> <a href="https://twitter.com/nodinite" title="Twitter"><i class="fab fa-twitter-square"></i></a> <a href="https://www.youtube.com/channel/UCwyKPt2EgxjHpS_dl1-QfnQ" title="YouTube"><i class="fab fa-youtube-square"></i></a> <a href="https://www.linkedin.com/company/nodinite/" title="LinkedIn"><i class="fab fa-linkedin"></i></a> </div> </div> <div class="flex-row flex-end"> <small class="copyright"> © 2026 <a href="https://nodinite.com/" target="_blank">Nodinite</a>. All rights reserved </small> </div><!--//container--> </div> </footer><!--//footer--> <script src="/js/jquery-3.6.4.min.js"></script> <script src="/js/bootstrap.bundle.min.js"></script> <script src="/fontawesome/all.min.js"></script> <script src="/js/bootstrap-toc.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/prism.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-csharp.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-javascript.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-json.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-sql.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-bash.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-python.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/components/prism-powershell.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/plugins/line-numbers/prism-line-numbers.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/plugins/toolbar/prism-toolbar.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.15.0/plugins/show-language/prism-show-language.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/goodshare.js/6.1.5/goodshare.min.js" integrity="sha512-fwnD6EKphZnxk0R6Q9X88dfBcQPS9IkHEQNwfo3ion9kpXg94aOkqV3bFUP8vIOvff+lKh88BVGdKzvurDG7Lw==" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.min.js" integrity="sha512-Y2IiVZeaBwXG1wSV7f13plqlmFOx8MdjuHyYFVoYzhyRr3nH/NMDjTBSswijzADdNzMyWNetbLMfOpIPl6Cv9g==" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.4/clipboard.min.js"></script> <script src="/js/moment.min.js"></script> <!-- put jquery extensions here... --> <script src="/js/site.min.js?v=oMI_64QVTJL5CWfhZGikYNuoxcIC_01zZnukexynk_g"></script> <script type="text/javascript"> function ReadableDateTime(time) { return moment(time).fromNow(); }; $('.tree-toggle').click(function () { $(this).parent().children('ul.tree').toggleClass("active"); $(this).toggleClass("active"); }); $('.doc-toc ul li a').click(function () { $('.doc-toc ul li a.active').removeClass("active"); $(this).addClass("active"); }); $(function () { var scope = $('#doccontent'), navSelector = '#toc'; Toc.init({ $nav: $(navSelector), $scope: $('#doccontent') }); $('body').scrollspy({ target: navSelector, offset: 80 }); $('[data-toggle="tooltip"]').tooltip() var isPreview = false; setTimeout(function() { mermaid.init(undefined, scope.find(".mermaid")); },isPreview ? 500 : 0); }); </script> <div class="modal release-notes-modal" tabindex="-1"> <div class="modal-dialog modal-xl"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title release-notes-title">...</h5> </div> <div class="modal-header"> <div> <span class="modal-title vertical-align-middle"> Version: <div class="dropdown d-inline-block release-notes-version-dropdown vertical-align-middle"> <button class="btn btn-light btn-light2 p-1 mb-1 small dropdown-toggle" type="button" style="line-height:0.5;" id="versionSelectButton" data-toggle="dropdown" aria-expanded="false"> <span class="release-notes-selected-version"></span> <span class="release-notes-selected-version-icons"></span> </button> <div class="dropdown-menu release-notes-version-list" aria-labelledby="versionSelectButton"></div> </div> </span> <div class="realign-checkbox custom-control custom-checkbox d-inline-block vertical-align-middle"> <input class="custom-control-input" type="checkbox" id="includePreRelease" name="includePreRelease" value="1" /> <label class="custom-control-label m-0 ml-1 d-inline" for="includePreRelease"> <span class="d-none d-md-inline" title="Include preview versions">Incl. preview</span> <span class="d-inline d-md-none" title="Include preview versions"><i class="fas fa-eye"></i></span> </label> </div> <div class="small text-black-50" style="font-family:Montserrat, Verdana, serif;"> Release date: <strong class="release-notes-date"></strong> </div> </div> <div> <div class="w-100 d-flex flex-wrap" style="justify-content:flex-end;"> <div class="input-group w-auto flex-nowrap"> <div class="input-group-prepend"> <strong class="input-group-text small release-notes-size"> N/A MB </strong> </div> <button type="button" disabled class="btn btn-danger text-nowrap release-notes-download-unavailable" title="Download Unavailable"> <i class="fas fa-exclamation-triangle"></i> <span class="d-none d-lg-inline d-xl-inline">Download Unavailable</span> <span class="d-none d-md-inline d-lg-none d-xl-none">Unavailable</span> </button> <div class="input-group-append"> <a class="btn btn-primary hidden text-nowrap release-notes-download-btn"> <i class="fas fa-download"></i> <span class="d-none d-lg-inline d-xl-inline">Download Package</span> <span class="d-none d-md-inline d-lg-none d-xl-none">Download</span> </a> </div> </div> </div> </div> </div> <div class="modal-body release-notes-body-loading"> <i class="far fa-fw fa-spin fa-code-commit"></i> Loading... </div> <div class="modal-body release-notes-body"> </div> <div class="modal-body release-notes-body-not-found"> <div class="alert alert-warning mb-0"><i class="fa fa-exclamation-triangle"></i> No versions found. Try enabling the Include Preview Versions filter.</div> </div> <div class="modal-footer"> <a class="ng-cloak small text-black-50 mt-1 release-notes-portal-link" target="_blank"> <i class="far fa-fw fa-portal-enter"></i> Portal - Release Notes <sup><i class="fa fa-external-link"></i></sup> </a> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </div> </div> </div> </div> <style> .release-notes-body img { max-width: 100%; } .release-notes-version-select { width: auto; min-width: 300px; max-width: calc(100% - 290px); } .release-notes-package-icons svg { margin-left: 1px; margin-right: 1px; } .link-pointer { cursor: pointer; } .modal-xl { max-width:1140px; } .vertical-align-middle { vertical-align: middle; } .realign-checkbox.custom-checkbox.custom-control .custom-control-label::before, .realign-checkbox.custom-checkbox.custom-control .custom-control-label::after { top:0.05rem !important; } .btn-light2 { background-color: #edece9; border-color: #f8f9fa } .btn-light2:hover { background-color: #e2e6ea; border-color: #dae0e5; } </style> <script type="text/javascript"> $(function() { var parentSlug = ""; var slug = ""; var selectedVersion = ""; var versionList = []; var elements = { versionList: $(".release-notes-version-list"), selectedVersion: $(".release-notes-selected-version"), selectedVersionIcons: $(".release-notes-selected-version-icons"), body: $(".release-notes-body"), bodyNotFound: $(".release-notes-body-not-found"), bodyLoading: $(".release-notes-body-loading"), downloadUnavailable: $(".release-notes-download-unavailable"), download: $(".release-notes-download-btn"), size: $(".release-notes-size"), date: $(".release-notes-date"), portalLink: $(".release-notes-portal-link"), includePreRelease: $("#includePreRelease"), title: $(".release-notes-title") } function niceSize(n, maxacc) { if (n <= 1024) return n + " B"; var digits = Math.min(Math.floor(Math.log10(n) / 3), maxacc || 4); // "B" is never used here but we need to fill the slot in the array, or do -1 everywhere var sizes = ["B", "KB", "MB", "GB"]; return Math.floor(n / Math.pow(1024, digits) * 10) / 10 + " " + sizes[digits]; } function niceDate(d) { return (new moment(d)).format("YYYY-MM-DD"); } function getIcons(version) { var icons = []; if (version.isPreRelease) { icons.push($("<i>").addClass("fas fa-info-circle text-info ml-2").attr("title","This is a preview version.")); } return icons; } function reset(resetLite) { if (!resetLite) { parentSlug = ""; slug = ""; } selectedVersion = ""; versionList = []; elements.versionList.empty(); elements.selectedVersion.empty(); elements.selectedVersionIcons.empty(); elements.body.empty().hide(); setLoadingStatus(LOADING); elements.download.hide(); elements.size.text("N/A MB"); elements.date.text("N/A"); } function selectVersion(version) { selectedVersion = version; getReleaseNotes(); elements.selectedVersion.text(selectedVersion.version); elements.selectedVersionIcons.empty().append(getIcons(selectedVersion)); elements.date.text(niceDate(selectedVersion.changed)); if (version.downloadLink && version.downloadLink != "") { elements.download.attr("href", version.downloadLink).show(); elements.downloadUnavailable.hide(); } else { elements.downloadUnavailable.show(); elements.download.hide(); } } // 0 = loading // 1 = finished // 2 = not found var LOADING = 0; var FINISHED = 1; var NOTFOUND = 2; function setLoadingStatus(status) { var elems = [elements.bodyLoading, elements.body, elements.bodyNotFound]; elements.bodyLoading.hide(); elements.body.hide(); elements.bodyNotFound.hide(); elems[status].show(); } function updateSelectedVersionReleaseNotes(ifNotFoundShowLoading) { if (selectedVersion.releaseNotes && selectedVersion.releaseNotes != "") { elements.body.empty().append(selectedVersion.releaseNotes); setLoadingStatus(FINISHED); } else if (ifNotFoundShowLoading) { setLoadingStatus(LOADING); } else { setLoadingStatus(NOTFOUND); } if (selectedVersion.size && selectedVersion.size != 0) { elements.size .text(niceSize(selectedVersion.size)) .attr("title", niceSize(selectedVersion.size,1)); } else { elements.size.text("N/A MB").attr("title","File size unavailable"); } } function getAgentInformation() { elements.title.text("..."); var includePreRelease = elements.includePreRelease.is(":checked") ? 'true' : 'false'; $.get(`https://api.nodinite.com/api/Agents/?slug=${slug}&includePreRelease=${includePreRelease}`,function(data) { try { elements.title.empty().append([ $("<span class='text-muted'>").text(data.Collection.Items[0].Data.parentAgents[0].name + "/"), $("<span>").text(data.Collection.Items[0].Data.name) ]); } catch(e) { elements.title.text("N/A"); } }).fail(function() { elements.title.text("N/A"); }); } function getVersionList(page) { if (!page) { reset(true); page = 1; } var includePreRelease = elements.includePreRelease.is(":checked") ? 'true' : 'false'; $.get(`https://api.nodinite.com/api/ReleaseNotes/List/?slug=${slug}&numberOfItems=10&page=${page}&includePreRelease=${includePreRelease}`, function(data) { var items = data.Collection.Items; if (items != null && items.length > 0) { for(let k in items) { let version = items[k].Data; versionList.push(version); let opt = $("<a>").addClass("dropdown-item link-pointer").click(() => selectVersion(version)); opt.text(version.version); opt.append(getIcons(version)) elements.versionList.append(opt); if (versionList.length < data.Collection.Pagination.TotalNumberOfItemsAvailable) { let loadMoreElem = $(".release-notes-load-more",elements.versionList); if (loadMoreElem.length == 0) { loadMoreElem = $("<a>").addClass("dropdown-item link-pointer").click(() => getVersionList(page+1)); loadMoreElem.text("+ " + (data.Collection.Pagination.TotalNumberOfItemsAvailable-versionList.length) + " older versions"); } else { loadMoreElem.detach().appendTo(elements.versionList); } } else { $(".release-notes-load-more",elements.versionList).remove(); } } if (selectedVersion == "" && versionList.length > 0) { selectVersion(versionList[0]); } } else { setLoadingStatus(NOTFOUND); } }).fail(function() { setLoadingStatus(NOTFOUND); }); } function getReleaseNotes() { setLoadingStatus(LOADING); var includePreRelease = elements.includePreRelease.is(":checked") ? 'true' : 'false'; $.get(`https://api.nodinite.com/api/ReleaseNotes/?slug=${slug}&versions=${selectedVersion.version}&includePreRelease=${includePreRelease}&numberOfItems=1&page=1`, function(data) { if (data.Collection && data.Collection.Items.length > 0) { var item = data.Collection.Items[0].Data; selectedVersion.releaseNotes = item.releaseNotes; selectedVersion.size = item.size; updateSelectedVersionReleaseNotes(); } else { setLoadingStatus(NOTFOUND); } }).fail(function() { setLoadingStatus(NOTFOUND); }) } function onClick(event) { var href = $(this).attr("href"); if (!href) {href = $(this).attr("data-url");} if (!href) {return;} $(".release-notes-modal").modal("show"); reset(); // for debug //var href = "https://portal.nodinite.com/marketplace/nodiniteInstallationFiles/nodiniteUpdate"; var hrefSplit = href.split("/"); slug = hrefSplit.pop(); parentSlug = hrefSplit.pop(); getAgentInformation(); getVersionList(1); elements.portalLink.attr("href", href); event.preventDefault(); event.stopPropagation(); return true; } function setupReleaseNotesLinks(parent) { // for debug //$("a:contains('Release Notes')").click(function(event) { $("a:contains('Release Notes')[href^='https://portal.nodinite.com/marketplace/']", parent).click(onClick); $("div.release-notes-btn[data-url]",parent).click(onClick); } setupReleaseNotesLinks($("body")); window.setupReleaseNotesLinks = setupReleaseNotesLinks; elements.includePreRelease.change(() => getVersionList()); }); </script> <script type="text/javascript"> $(document).on('click', '[data-toggle="lightbox"]', function (event) { event.preventDefault(); $(this).ekkoLightbox({ delay: { "show": 500, "hide": 100 }, showArrows: true }); }); </script> </body> </html>