WRMCB=function(e){var c=console;if(c&&c.log&&c.error){c.log('Error running batched script.');c.error(e);}} ; try { /* module-key = 'com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend', location = 'lib/jquery.viewport.js' */ /* * Viewport - jQuery selectors for finding elements in viewport * * Copyright (c) 2008-2009 Mika Tuupola * * Licensed under the MIT license: * http://www.opensource.org/licenses/mit-license.php * * Project home: * http://www.appelsiini.net/projects/viewport * */ (function ($) { $.belowthefold = function (element, settings) { var fold = $(window).height() + $(window).scrollTop(); return fold <= $(element).offset().top - settings.threshold; }; $.abovethetop = function (element, settings) { var top = $(window).scrollTop(); return top >= $(element).offset().top + $(element).height() - settings.threshold; }; $.rightofscreen = function (element, settings) { var fold = $(window).width() + $(window).scrollLeft(); return (fold <= $(element).offset().left - settings.threshold) || $(element).offset().left < 0; }; $.leftofscreen = function (element, settings) { var left = $(window).scrollLeft(); return left >= $(element).offset().left + $(element).width() - settings.threshold; }; $.inviewport = function (element, settings) { return !$.rightofscreen(element, settings) && !$.leftofscreen(element, settings) && !$.belowthefold(element, settings) && !$.abovethetop(element, settings); }; $.extend($.expr[':'], { "below-the-fold": function (a, i, m) { return $.belowthefold(a, {threshold: 0}); }, "above-the-top": function (a, i, m) { return $.abovethetop(a, {threshold: 0}); }, "left-of-screen": function (a, i, m) { return $.leftofscreen(a, {threshold: 0}); }, "right-of-screen": function (a, i, m) { return $.rightofscreen(a, {threshold: 0}); }, "in-viewport": function (a, i, m) { return $.inviewport(a, {threshold: 0}); } }); })(jQuery); }catch(e){WRMCB(e)}; ; try { /* module-key = 'com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend', location = 'lib/jquery.ellipsis.min.js' */ /*! jQuery ellipsis - v1.1.1 - 2014-02-23 * https://github.com/STAR-ZERO/jquery-ellipsis * Copyright (c) 2014 Kenji Abe; Licensed MIT */ !function(a){a.fn.ellipsis=function(b){var c={row:1,onlyFullWords:!1,"char":"...",callback:function(){},position:"tail"};return b=a.extend(c,b),this.each(function(){var c=a(this),d=c.text(),e=d,f=e.length,g=c.height();c.text("a");var h=parseFloat(c.css("lineHeight"),10),i=c.height(),j=h>i?h-i:0,k=j*(b.row-1)+i*b.row;if(k>=g)return c.text(d),void b.callback.call(this);var l=1,m=0,n=d.length;if("tail"===b.position){for(;n>l;)m=Math.ceil((l+n)/2),c.text(d.slice(0,m)+b["char"]),c.height()<=k?l=m:n=m-1;d=d.slice(0,l),b.onlyFullWords&&(d=d.replace(/[\u00AD\w\uac00-\ud7af]+$/,"")),d+=b["char"]}else if("middle"===b.position){for(var o=0;n>l;)m=Math.ceil((l+n)/2),o=Math.max(f-m,0),c.text(e.slice(0,Math.floor((f-o)/2))+b["char"]+e.slice(Math.floor((f+o)/2),f)),c.height()<=k?l=m:n=m-1;o=Math.max(f-l,0);var p=e.slice(0,Math.floor((f-o)/2)),q=e.slice(Math.floor((f+o)/2),f);b.onlyFullWords&&(p=p.replace(/[\u00AD\w\uac00-\ud7af]+$/,"")),d=p+b["char"]+q}c.text(d),b.callback.call(this)}),this}}(jQuery); }catch(e){WRMCB(e)}; ; try { /* module-key = 'com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend', location = 'editor/roadmap-editor.js' */ AJS.toInit(function ($) { // @@roadmap var roadmapPopupTemplate, $roadmapPopup, $roadmapEditorPopup, roadmapEditorView, isCreateNew, saveInterval; var PAGE_LINK_DELIMITER = "~~~~~"; var tinymce = window.tinymce; AJS.MacroBrowser.setMacroJsOverride('roadmap', { opener: function (macro) { var updatePageLinksFromParams = function (roadmap, pagelinks, maplinks, callback) { var mapLinkArray = maplinks ? maplinks.split(PAGE_LINK_DELIMITER) : []; var pageLinkArray = pagelinks ? pagelinks.split(PAGE_LINK_DELIMITER) : []; if (!_.isEmpty(mapLinkArray)) { $.ajax({ type: 'POST', contentType: "application/json", url: AJS.contextPath() + '/rest/roadmap/1.0/extractPageLinks', data: JSON.stringify({ 'wikiLinks': _.object(mapLinkArray, pageLinkArray), 'roadmapSpace': AJS.Meta.get('space-key') }), success: function (result) { _.each(roadmap.lanes, function (lane) { _.chain(lane.bars) .filter(function (bar) { return _.contains(mapLinkArray, bar.id); }) .each(function (bar) { if (result[bar.id]) { bar.pageLink = result[bar.id]; } }); }) callback && callback(); }, error: function (error) { AJS.log(error); callback && callback(); } }); } else { callback && callback(); } }, preparePageLinkParams = function(roadmapData) { var pageLinks = []; var mapLinks = []; roadmapData.lanes.forEach(function (lane) { lane.bars.forEach(function (bar) { if (!_.isEmpty(bar.pageLink)) { var wikiLink = bar.pageLink.wikiLink.replace(/[\][]/g, ""); //remove "[ ]" pageLinks.push(_.escape(wikiLink)); mapLinks.push(bar.id); } }); }); return { pageLinks: pageLinks.join(PAGE_LINK_DELIMITER), mapLinks: mapLinks.join(PAGE_LINK_DELIMITER), }; } // Prevent user from editing an old roadmap // When user try to add a new roadmap, macro.params value is undefined if (macro.params && macro.params.timeline !== 'true') { var dialogId = 'roadmap-deprecation-dialog'; var $dialogEl = $(Confluence.Templates.Roadmap.deprecationDialog({ id: dialogId })); AJS.dialog2($dialogEl).on('hide', function () { $('#' + dialogId).remove(); }).on('show', function () { $("#dialog-close-button", $dialogEl).click(function (e) { e.preventDefault(); AJS.dialog2('#' + dialogId).hide(); }); }).show(); return false; // Return to exit this function. } // Setting up to show the Roadmap Editor Dialog var roadmapData; var isInTinyMceEditor = tinymce && !!tinymce.activeEditor; // We should autosave the roadmap planner macro when we're in fabric // editor and the feature flag is enabled. var roadmapShouldAutoSave = !isInTinyMceEditor; var constructRoadmapDialog = function () { var roadmapDialogId = 'confluence-roadmap-dialog'; var roadmapPopupPanelId = 'roadmap-popup-panel'; var roadmapDialog; var disableInsertButton = function () { $roadmapPopup.find("#roadmapInsertBtn").attr('disabled', 'disabled'); $roadmapPopup.find("#roadmapCancelBtn").attr('disabled', 'disabled'); if(roadmapShouldAutoSave){ removeIntermittentSaving(); } }; var enableInsertButton = function () { $roadmapPopup.find("#roadmapInsertBtn").removeAttr('disabled'); $roadmapPopup.find("#roadmapCancelBtn").removeAttr('disabled'); }; window.addEventListener('offline', disableInsertButton); window.addEventListener('online', enableInsertButton); var removeConnectionListener = function () { window.removeEventListener('online', enableInsertButton); window.removeEventListener('offline', disableInsertButton); }; function initializeIntermittentSaving() { if(saveInterval){ clearInterval(saveInterval); } saveInterval = setInterval(function () { saveRoadmap(); }, 15000); } function removeIntermittentSaving() { clearInterval(saveInterval); } // https://stackoverflow.com/a/48161723 function sha256(message) { // encode as UTF-8 var msgBuffer = new TextEncoder().encode(message); // hash the message return crypto.subtle.digest('SHA-256', msgBuffer).then(function(hashBuffer) { // convert ArrayBuffer to Array var hashArray = Array.from(new Uint8Array(hashBuffer)); // convert bytes to hex string return hashArray.map(function(b) { return b.toString(16).padStart(2, '0'); }).join(''); }); } function saveRoadmap() { var roadmapData = roadmapEditorView.model.toMacroData(); var source = encodeURIComponent(JSON.stringify(roadmapData)); sha256(source).then(function(hash) { var pageLinkRoadmap = preparePageLinkParams(roadmapData); var macroData = { timeline: "true", source: source, hash: hash, title: encodeURIComponent(roadmapData.title), pagelinks: pageLinkRoadmap.pageLinks, maplinks: pageLinkRoadmap.mapLinks, }; var macroBrowserFacade = require("confluence-macro-browser/macro-browser-facade"); macroBrowserFacade.saveMacro({ name: "roadmap", params: macroData }); }); } if (typeof roadmapPopupTemplate == "undefined") { roadmapPopupTemplate = aui.dialog.dialog2({ id: roadmapDialogId, size: "xlarge", titleText: "Insert Roadmap Planner", content: Confluence.Templates.Roadmap.roadmapPopupPanel({roadmapPopupPanelId: roadmapPopupPanelId}), footerActionContent: Confluence.Templates.Roadmap.footerActionContent({roadmapShouldAutoSave: roadmapShouldAutoSave}), /* this option prevents dialog2 from closing when a dropdown2 is going to show */ modal: true }); $roadmapPopup = $(roadmapPopupTemplate).appendTo($("body")); $roadmapPopup.find("#roadmapInsertBtn").on("click", function (e) { roadmapEditorView.removeDialog(); var roadmapData = roadmapEditorView.model.toMacroData(); var source = encodeURIComponent(JSON.stringify(roadmapData)); sha256(source).then(function(hash) { var pageLinkRoadmap = preparePageLinkParams(roadmapData); var macroData = { timeline: "true", source: source, hash: hash, title: encodeURIComponent(roadmapData.title), pagelinks: pageLinkRoadmap.pageLinks, maplinks: pageLinkRoadmap.mapLinks, }; var macroBrowserFacade = require("confluence-macro-browser/macro-browser-facade"); macroBrowserFacade.insert({ name: "roadmap", params: macroData }); roadmapEditorView.remove(); roadmapDialog.hide(); if (isCreateNew) { Confluence.Roadmap.Analytics.createRoadmap(roadmapData); } else { Confluence.Roadmap.Analytics.editRoadmap(roadmapData); } if(roadmapShouldAutoSave){ removeIntermittentSaving(); } removeConnectionListener(); }); }); if(roadmapShouldAutoSave){ $roadmapPopup.find("#roadmapCloseBtn").on("click", function (e) { roadmapEditorView.removeDialog(); roadmapEditorView.remove(); roadmapDialog.hide(); removeConnectionListener(); removeIntermittentSaving(); }); } else { $roadmapPopup.find("#roadmapCancelBtn").on("click", function (e) { roadmapEditorView.removeDialog(); roadmapEditorView.remove(); roadmapDialog.hide(); removeConnectionListener(); }); } $roadmapEditorPopup = $roadmapPopup.find('.roadmap-editor-popup'); } roadmapDialog = AJS.dialog2("#" + roadmapDialogId).show(); // Each time we call 'roadmapEditorView.remove()', it will remove roadmapPopupPanel. // To avoid this, we create a new container for roadmap-view. var $popupPanel = $('#' + roadmapPopupPanelId); var $roadmapViewEl = $popupPanel.find('.roadmap-view'); if (!$roadmapViewEl.length) { $roadmapViewEl = $('
'); $popupPanel.append($roadmapViewEl); } var roadmap = new Roadmap.Roadmap(roadmapData, {parse: true}); roadmapEditorView = new Roadmap.RoadmapEditorView({ model: roadmap, dialogId: roadmapDialogId, el: $roadmapViewEl, roadmapEditorPopup: $roadmapEditorPopup }); roadmapEditorView.render(); if(roadmapShouldAutoSave){ // start regularly inserting the roadmap planner macro initializeIntermittentSaving() } resizePopupPanel(); }; if (macro.params && macro.params.source) { // edit roadmap isCreateNew = false; roadmapData = JSON.parse(decodeURIComponent(macro.params.source)); updatePageLinksFromParams(roadmapData, macro.params.pagelinks, macro.params.maplinks, constructRoadmapDialog); } else { // create roadmap from macro browser or macro suggestion isCreateNew = true; Confluence.Roadmap.Analytics.insertRoadmap(); // insert new roadmap into editor constructRoadmapDialog(); } } }); function resizePopupPanel() { setTimeout(function () { if ($roadmapPopup && $roadmapPopup.is(":visible")) { var $popupHeight = $roadmapPopup.height(), $titleHeight = $roadmapPopup .find(".aui-dialog2-header") .outerHeight(), $buttonsHeight = $roadmapPopup .find(".aui-dialog2-footer") .outerHeight(), $toolbarHeight = $roadmapPopup .find("#roadmap-editor-toolbar") .outerHeight(), $roadmapEditorPopup = $roadmapPopup.find(".roadmap-editor-popup"); $roadmapEditorPopup.css( "height", $popupHeight - $titleHeight - $buttonsHeight - $toolbarHeight ); } }, 0); } $(window).resize(function () { resizePopupPanel(); roadmapEditorView && roadmapEditorView.resize(); }) })(AJS.$); }catch(e){WRMCB(e)}; ; try { /* module-key = 'com.atlassian.confluence.plugins.confluence-roadmap-plugin:roadmap-editor-resources-conf-frontend', location = 'editor/roadmap-editor-config.js' */ /* * z-index management * - Main popup 3004 * - Timeline options: 4010 * - Roadmap dialog: 4011 * - Color picker: 4012 * $Tips: element one should be smaller than 4010 to avoid overriding others */ (function () { window.Roadmap = window.Roadmap || {}; /** There is three kind of color * lane: use this color for lane title, border of bar and background of progress * bar: background of bar * text: title of bar */ Roadmap.COLORS = [ /* !important: CCECO-1290 When updating these colors, please also modify their rgb matching styles and light/dark mode CSS overrides in timeline-planner-view.vm and roadmap-editor.css Thank you! */ { lane: '#f6c342', bar: '#f6c342', text: '#594300' }, { lane: '#3b7fc4', bar: '#3b7fc4', text: '#ffffff' }, { lane: '#d04437', bar: '#d04437', text: '#ffffff' }, { lane: '#8eb021', bar: '#8eb021', text: '#ffffff' }, { lane: '#ea632b', bar: '#ea632b', text: '#ffffff' }, { lane: '#654982', bar: '#654982', text: '#ffffff' }, { lane: '#f15c75', bar: '#f15c75', text: '#ffffff' }, { lane: '#227D9B', bar: '#227D9B', text: '#ffffff' } ]; Roadmap.TIMELINE_DISPLAY_OPTION = { MONTH: 'MONTH', WEEK: 'WEEK' }; Roadmap.SHORT_DATE_FORMAT = 'YYYY-MM-DD'; //date format from aui date picker Roadmap.TWO_YY_SHORT_DATE_FORMAT = 'YY-MM-DD'; Roadmap.DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss'; // format in title of timeline. Roadmap.WEEK_FORMAT = 'DD-MMM'; Roadmap.MONTH_FORMAT = 'MMM'; Roadmap.TIMELINE_YEARS_LIMIT = 5; Roadmap.LANE_TITLE_WIDTH = 45; Roadmap.MARKER_HEIGHT_PADDING = 10; Roadmap.MARKER_TITLE_LINE = 2; Roadmap.LANE_PADDING = 11; Roadmap.BAR_PADDING = 8; Roadmap.BAR_MARGIN = 1; Roadmap.BAR_BORDER = 1; Roadmap.MONTH_WIDTH = 101; Roadmap.WEEK_WIDTH = 101; Roadmap.EXTRA_SPACE_AROUND = Roadmap.BAR_PADDING * 2 + Roadmap.BAR_BORDER * 2; Roadmap.MONTH_BAR_MIN_WIDTH = Roadmap.MONTH_WIDTH / 4 - Roadmap.EXTRA_SPACE_AROUND; Roadmap.WEEK_BAR_MIN_WIDTH = Roadmap.WEEK_WIDTH - Roadmap.EXTRA_SPACE_AROUND; Roadmap.barMinWidth = Roadmap.MONTH_BAR_MIN_WIDTH; /* This object is used to create an empty lane when reorder lanes, the aim is create a lane's structure only */ Roadmap.TRANSPARENT_LANE = { title: '', color: {lane: '#ffffff', bar: '#ffffff', text: '#ffffff'} }; // This is a namespace for all DragDrop configuration. Roadmap.DragDrop = {}; // Config for Bar's details dialog Roadmap.BarDialog = { MAX_LENGTH_TITLE: 100, MAX_LENGTH_DESCRIPTION: 150 }; Roadmap.getDefaultRoadmapData = function () { // As default the duration is one year from current date var startDate = moment(new Date()).hours(0).minutes(0).seconds(0).milliseconds(0).toDate(); var endDate = moment(startDate).add(11, 'months').toDate(); return { title: "Roadmap Planner", timeline: { startDate: new Date(startDate), endDate: endDate, displayOption: Roadmap.TIMELINE_DISPLAY_OPTION.MONTH }, lanes: [ { title: "Lane 1", color: Roadmap.COLORS[0], bars: [ { title: "Bar 1", description: "This is the first bar.", startDate: new Date(startDate.setDate(1)), duration: 2, rowIndex: 0 }, { title: "Bar 2", description: "This is the second bar.", startDate: new Date(startDate), duration: 1, rowIndex: 1 } ] }, { title: "Lane 2", color: Roadmap.COLORS[1], bars: [ { title: "Bar 3", description: "This is the third bar.", startDate: startDate, duration: 2.5, rowIndex: 0 } ] } ], markers: [ { title: "Marker 1", markerDate: moment(startDate).date(15).toDate() } ] } }; })(); }catch(e){WRMCB(e)};