diff --git a/README.md b/README.md index d8d4616..1bf1b87 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ -# Red Labels for Pivotal Tracker +# Simbi Labels for Pivotal Tracker -This Chrome extension for SystemSeed workflow tweaks in Pivotal Tracker. +This Chrome extension for Simbi workflow tweaks in Pivotal Tracker. ## Taxonomy Any of these labels on stories will turn blue: -- paused -- on hold -- blocked -- to +- planner +- estimate Any of these labels on stories will turn red: -- urgent priority -- high priority +- blocked +- needs- +- urgent + +Any of these labels on stories will turn gray: +- goal- diff --git a/css/content.css b/css/content.css index 14005b5..163dde8 100644 --- a/css/content.css +++ b/css/content.css @@ -6,31 +6,18 @@ white-space: nowrap; } -.preview a.label.ss.workflow-state { +.preview a.label.ss.blue { background: #203e64; } -.preview a.label.ss.workflow-state:hover { +.preview a.label.ss.blue:hover { background: #11213e; } -.preview a.label.ss.important { +.preview a.label.ss.red { background-color: hsl(349, 69%, 46%); } -.preview a.label.ss.missing-tags { - background-color: #f39300; -} - -.preview .time-overrun { - background: #a71f39; - color: white; - font-size: 8px; - padding: 0 5px; - border-radius: 20px; - position: absolute; - top: 25px; - line-height: 11px; - left: 22px; - font-weight: bold; +.preview a.label.ss.gray { + background-color: #b7b7b7; } diff --git a/manifest.json b/manifest.json index 0b87ade..134c2e4 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ { - "name": "SystemSeed PT", - "version": "1.7", + "name": "Simbi PT", + "version": "1.0", "manifest_version": 2, - "author": "Ev Maslovskiy", - "description": "Provides integration between SystemSeed workflow and Pivotal Tracker.", - "homepage_url": "https://github.com/spleshka/SystemSeed-PT", + "author": "Carlos Arguello", + "description": "Provides integration between Simbi's workflow and Pivotal Tracker.", + "homepage_url": "https://github.com/cjarguello/simbi-labels-for-pivotal-tracker", "icons": { "16": "icons/icon16.png", "32": "icons/icon32.png", @@ -15,7 +15,7 @@ "*://www.pivotaltracker.com/*" ], "browser_action": { - "default_title": "SystemSeed PT", + "default_title": "Simbi PT", "default_icon": "icons/icon16.png" }, "content_scripts": [ diff --git a/src/content.js b/src/content.js index cd536ab..3779d84 100644 --- a/src/content.js +++ b/src/content.js @@ -19,29 +19,28 @@ chrome.extension.sendMessage({}, function(response) { * Add observer handler. */ observer.observe(document, config); + var handleMutationEvents = function handleMutationEvents(mutation) { Array.prototype.forEach.call(mutation.addedNodes, processStories); processStories(mutation.target); }; - /** * Main entry point to loop through all stories and to process them. */ var processStories = function processStories(node) { - if (typeof node.querySelectorAll == 'undefined') { + if (typeof node.querySelectorAll == 'undefined') return; - } // Loop through every collapsed story. var collapsedStories = node.querySelectorAll('header.preview'); + if (collapsedStories.length) { Array.prototype.forEach.call(collapsedStories, function (story) { var storySelector = story.parentNode; - highlightWorkflowStates(storySelector); + highlightPlannerTags(storySelector); highlightImportantTags(storySelector); - detectMergeDeployTags(storySelector); - detectTimeIssues(storySelector); + highlightGoalTags(storySelector); }); } @@ -51,14 +50,13 @@ chrome.extension.sendMessage({}, function(response) { /** - * Highlights tags which contain workflow states. + * Highlights planner stories that need estimate. */ - function highlightWorkflowStates(story) { + function highlightPlannerTags(story) { var labels = story.querySelectorAll('a.label'); Array.prototype.forEach.call(labels, function(label) { - if (label.textContent.match(/\b(?:on hold|questions|awaiting|^to)\b/)) { - label.classList.add('ss', 'workflow-state'); - } + if (label.textContent.match(/\b(?:planner|estimate)\b/)) + label.classList.add('ss', 'blue'); }); } @@ -74,126 +72,28 @@ chrome.extension.sendMessage({}, function(response) { if (!storyAccepted) { var labels = story.querySelectorAll('a.label'); Array.prototype.forEach.call(labels, function(label) { - if (label.textContent.match(/\b(?:blocked|hot lead|blocker|high priority|urgent priority)\b/)) { - label.classList.add('ss', 'important'); - } + if (label.textContent.match(/\b(?:blocked|needs|needs-|urgent)\b/)) + label.classList.add('ss', 'red'); }); } } - /** - * Finds stories where logged time higher than estimate. + * Highlights tags which contain goal-based labels. + * productivity, analytics, etc. */ - function detectTimeIssues(story) { - var estimation = story.querySelector('.meta'); - var spentTime = story.querySelector('.everhour-stat'); - if (estimation !== null && spentTime !== null) { - var pts = estimation.textContent; - if (pts >= 0) { - var time = spentTime.textContent.split(' '); - var minutes = 0; - var hours = 0; - - // If time has only 1 param, means that it has only minutes. - // Otherwise - hours and minutes. - if (time.length == 1) { - minutes = parseInt(time[0]); - } - else { - hours = parseInt(time[0]); - minutes = parseInt(time[1]); - } - - // Care only about huge overruns. - var estimated = pts * 6 * 60 + 60; - var current = hours * 60 + minutes; - if (estimated < current) { - if (story.querySelector('.time-overrun') === null) { - story.insertAdjacentHTML('beforeend', 'overrun'); - } - } - } - } - } + function highlightGoalTags(story) { - - /** - * Checks for merging / deployment workflow. - */ - function detectMergeDeployTags(story) { - // We care about merging only when story is accepted. + // We care about important tags as long as it is not accepted. var storyAccepted = story.classList.contains('accepted'); - var storyHasBody = story.querySelector('.name') !== null; - if (!storyAccepted || !storyHasBody) { - return; - } - - // Make sure that the story has the right section and we haven't - // already processed it. - var bodySection = story.querySelector('.name'); - var hasMissingTags = bodySection.querySelector('.missing-tags') !== null; - if (hasMissingTags) { - return; - } - - var hasBranch = false; - var hasToMergeTag = false; - var hasMergedTag = false; - var hasToDeployTag = false; - var hasDeployedTag = false; - - // Loop through all labels of this story. - var labels = story.querySelectorAll('a.label'); - Array.prototype.forEach.call(labels, function (label) { - - // Check if the label is in format "b:branchname". - var regexp = new RegExp('^b:', 'i'); - if (label.textContent.match(regexp)) { - hasBranch = true; - } - - // Check if the label is "to merge". - regexp = new RegExp('^(to merge)', 'i'); - if (label.textContent.match(regexp)) { - hasToMergeTag = true; - } - - // Check if the label is "merged". - regexp = new RegExp('^(merged)', 'i'); - if (label.textContent.match(regexp)) { - hasMergedTag = true; - } - - // Check if the label is "to deploy". - regexp = new RegExp('^(to deploy)', 'i'); - if (label.textContent.match(regexp)) { - hasToDeployTag = true; - } - - // Check if the label is "deployed". - regexp = new RegExp('^(deployed)', 'i'); - if (label.textContent.match(regexp)) { - hasDeployedTag = true; - } - }); - - var warnings = []; - - if (hasBranch) { - if (!hasToMergeTag && !hasMergedTag) { - warnings.push('merge'); - } - - if (!hasToDeployTag && !hasDeployedTag) { - warnings.push('deploy'); - } - } - - if (warnings.length) { - bodySection.insertAdjacentHTML('beforeend', 'notice: missing ' + warnings.join(', ') + ' tags'); + if (!storyAccepted) { + var labels = story.querySelectorAll('a.label'); + Array.prototype.forEach.call(labels, function(label) { + if (label.textContent.match(/goal-b/)) + label.classList.add('ss', 'gray'); + }) } } } - }, 10); + }, 100); }); diff --git a/src/inject.js b/src/inject.js index d64deee..dfd02be 100644 --- a/src/inject.js +++ b/src/inject.js @@ -30,18 +30,8 @@ function injectTemplateButton(node) { function generateTasks(e) { var tasks = [ - '**===== TECHNICAL CONCEPT =====**', + '**===== CHECKLIST FOR ACCEPTANCE =====**', '- TDB', - '**===== DEFINITION OF DONE =====**', - '- Acceptance criteria is confirmed by the client', - '- Story meets acceptance criteria', - '- Story includes post deploy steps (where applicable)', - '- Story includes testing steps', - '- Code passes automated tests / code checks (where applicable)', - '- Story is tested and peer reviewed (where applicable)', - '- Story has test coverage (where applicable)', - '- Story is documented', - '- Story is accepted by the client', '**===== TESTING STEPS =====**', '- **Test 1:** TBD' ];