- Created by Robert Reiner, last modified on 01. Oct 2020
projectdoc Toolbox
Enforces comments in a specific format when documents are edited.
- Tags
- Identifier
de.smartics.userscripts.confluence.force-comment
- Type
- Repository
- Since
- 1.0
The script checks in the Confluence page editor whether or not the comment adheres to the required format. If not the page cannot be saved.
If the change is either a feature or a fix, then the watchers of the page will be notified.
Code
The code of the script for reference.
/* * Copyright 2019-2024 Kronseder & Reiner GmbH, smartics * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ "use strict"; AJS.toInit(function () { const logToConsole = false; const commentPrefixes = ["change: ", "feat: ", "fix: ", "refactor: ", "style: ", "chore: "]; const notificationRequiredIndex = 2; if (logToConsole) { AJS.log("[force-comment] Force comment with: " + commentPrefixes); } const isValidComment = function (comment) { if (comment) { for (let i = 0; i < commentPrefixes.length; i++) { const commentPrefix = commentPrefixes[i]; if (comment.startsWith(commentPrefix) && comment.length > commentPrefix.length) { return true; } } } return false; }; const requiresNotification = function (comment) { if (comment) { for (let i = 0; i <= notificationRequiredIndex; i++) { const commentPrefix = commentPrefixes[i]; if (comment.startsWith(commentPrefix)) { return true; } } } return false; }; const updateNotification = function (comment) { const $notify = AJS.$('#notifyWatchers'); if (requiresNotification(comment)) { $notify.prop('checked', true); } else { $notify.prop('checked', false); } }; const monitorPublishButtonStatus = function () { const comment = AJS.$('#versionComment').val(); if (logToConsole) AJS.log("[force-comment] Checking comment: " + comment); const currentStatus = AJS.$('#rte-button-publish').prop('disabled'); if (!isValidComment(comment)) { if (logToConsole) AJS.log("[force-comment] Comment '" + comment + "' is not valid, therefore disabling publish button."); if (!currentStatus) { AJS.$('#rte-button-publish').prop('disabled', true); updateNotification(comment); } } else { if (logToConsole) AJS.log("[force-comment] Comment '" + comment + "' is valid, therefore enabling publish button."); if (currentStatus) { AJS.$('#rte-button-publish').prop('disabled', false); updateNotification(comment); } } }; const createHelpDialog = function ($element) { if (AJS.$("#userscripts-commitMessages-helpDialog-show-button").length) { return; } const button = AJS.$("<button id=\"userscripts-commitMessages-helpDialog-show-button\" class=\"aui-button toolbar-item\" style=\"margin-right: 10px;\"><span class=\"aui-icon aui-icon-small aui-iconfont-question-filled\">Help on Commit Message Format</span></button>\n"); $element.before(button); AJS.$("#userscripts-commitMessages-helpDialog-show-button").on('click', function (e) { e.preventDefault(); const dialog = AJS.$("<section\n" + " id=\"userscripts-commitMessages-helpDialog\"\n" + " class=\"aui-dialog2 aui-dialog2-medium aui-layer\"\n" + " role=\"dialog\"\n" + " tabindex=\"-1\"\n" + " data-aui-modal=\"false\"" + " data-aui-remove-on-hide=\"true\"" + " aria-labelledby=\"userscripts-commitMessages-helpDialog-show-button--heading\"\n" + " hidden\n" + ">\n" + " <header class=\"aui-dialog2-header\">\n" + " <h1 class=\"aui-dialog2-header-main\" id=\"userscripts-commitMessages-helpDialog-show-button--heading\">Help: Commit message format</h1>\n" + " </header>\n" + " <div class=\"aui-dialog2-content\">\n" + " <p>Use the following format for your commit messages.</p>\n" + "<table class=\"aui\">\n" + " <thead>\n" + " <tr>\n" + " <th id=\"type\">Type</th>\n" + " <th id=\"description\">Description</th>\n" + " <th id=\"notify\" style=\"text-align:center;\">Notify</th>\n" + " <th id=\"example\">Example</th>\n" + " </tr>\n" + " </thead>\n" + " <tbody>\n" + " <tr>\n" + " <td headers=\"type\" style=\"font-weight: bold;\">Change</td>\n" + " <td headers=\"description\">Alters or removes an existing feature.</td>\n" + " <td headers=\"notify\" style=\"text-align:center;\">\n<span class=\"aui-icon aui-icon-small aui-iconfont-approve\">Checks the 'Notify watchers' checkbox</span></td>\n" + " <td headers=\"example\">\n" + " <code>change: Replace response code format.</code>\n" + " </td>\n" + " </tr>\n" + " <tr>\n" + " <td headers=\"type\" style=\"font-weight: bold;\">Feature</td>\n" + " <td headers=\"description\">Adds essential new information.</td>\n" + " <td headers=\"notify\" style=\"text-align:center;\">\n<span class=\"aui-icon aui-icon-small aui-iconfont-approve\">Checks the 'Notify watchers' checkbox</span></td>\n" + " <td headers=\"example\">\n" + " <code>feat: Add section on error handling.</code>\n" + " </td>\n" + " </tr>\n" + " <tr>\n" + " <td headers=\"type\" style=\"font-weight: bold;\">Fix</td>\n" + " <td headers=\"description\">Fixes an issue or false information.</td>\n" + " <td headers=\"notify\" style=\"text-align:center;\">\n<span class=\"aui-icon aui-icon-small aui-iconfont-approve\">Checks the 'Notify watchers' checkbox</span></td>\n" + " <td headers=\"example\">\n" + " <code>fix: Clarify section on user administration which is misleading.</code>\n" + " </td>\n" + " </tr>\n" + " <tr>\n" + " <td headers=\"type\" style=\"font-weight: bold;\">Refactor</td>\n" + " <td headers=\"description\">Reorganize sections or rename elements.</td>\n" + " <td headers=\"notify\" style=\"text-align:center;\">\n<span class=\"aui-icon aui-icon-small aui-iconfont-cross-circle\">Unchecks the 'Notify watchers' checkbox</span></td>\n" + " <td headers=\"example\">\n" + " <code>refactor: Split administration section into three subsections.</code>\n" + " </td>\n" + " </tr>\n" + " <tr>\n" + " <td headers=\"type\" style=\"font-weight: bold;\">Style</td>\n" + " <td headers=\"description\">Change the wording, remove typos, or fix grammar.</td>\n" + " <td headers=\"notify\" style=\"text-align:center;\">\n<span class=\"aui-icon aui-icon-small aui-iconfont-cross-circle\">Unchecks the 'Notify watchers' checkbox</span></td>\n" + " <td headers=\"example\">\n" + " <code>style: Replace with active voice to address the reader.</code>\n" + " </td>\n" + " </tr>\n" + " <tr>\n" + " <td headers=\"type\" style=\"font-weight: bold;\">Chore</td>\n" + " <td headers=\"description\">Necessary adjustments without regards to content.</td>\n" + " <td headers=\"notify\" style=\"text-align:center;\">\n<span class=\"aui-icon aui-icon-small aui-iconfont-cross-circle\">Unchecks the 'Notify watchers' checkbox</span></td>\n" + " <td headers=\"example\">\n" + " <code>chore: Update icon to higher resolution.</code>\n" + " </td>\n" + " </tr>\n" + " </tbody>\n" + "</table>" + " </div>\n" + " <footer class=\"aui-dialog2-footer\">\n" + " <div class=\"aui-dialog2-footer-actions\">\n" + " <button id=\"userscripts-commitMessages-helpDialog-submit-button\" class=\"aui-button aui-button-primary\">Okay</button>\n" + " </div>\n" + " </footer>\n" + "</section>"); $element.before(dialog); AJS.$("#userscripts-commitMessages-helpDialog-submit-button").on('click', function (e) { e.preventDefault(); AJS.dialog2("#userscripts-commitMessages-helpDialog").hide(); }); AJS.dialog2("#userscripts-commitMessages-helpDialog").show(); }); }; AJS.$(function () { if (logToConsole) { AJS.log("[force-comment] Analysing page elements: " + commentPrefixes); } const $versionComment = AJS.$('#versionComment'); if ($versionComment.length) { createHelpDialog($versionComment); const $publishButton = AJS.$('#rte-button-publish'); const $notify = AJS.$('#notifyWatchers'); if ($publishButton.length && $notify.length) { $versionComment.bind("input change", function () { const comment = $versionComment.val(); if (isValidComment(comment)) { $publishButton.prop('disabled', false); updateNotification(comment); } else { $publishButton.prop('disabled', true); } }); USERSCRIPT4C_SYNC.monitorPage(monitorPublishButtonStatus, AJS.$("#savebar-container")); const comment = $versionComment.val(); if (!isValidComment(comment)) { $publishButton.prop('disabled', true); } } } }); });
Details
Describing the use case for this script. First the use case for the author then for the userscripts administrator.
Commenting Changes
When opening a page where this script enforces the format of a comment, the Save button will be deactivated per default.
Users who do not know how to work with comments, may click the Help button ().
Entering a valid comment will activate the Save button.
If the comment does not meet the constraints, then the page cannot be saved.
If the comment is indicating a new feature, then the checkbox for Notify watchers will be checked.
Configuration of Userscript
Typically there is no need to enforce specific comments for each and every change for a page on a Confluence server. Typically versioned documents are located in a specific space. To activate the script for spaces with versioned documents, the userscripts administrator may define a space category, like versioned
, to be set.
Configure the space category via the Space Tools.
Once the categories contain a category 'versioned
', as specified in the activation record via activation-space-categories
, the space will enforce the comment on every document.
Related Scripts
Name | Short Description |
---|---|
Create with Template | Removes the default create-page button and renames the create with template. |
Shortcuts for Focus | Sample script to register actions with a shortcut in Confluence. |