├── .editorconfig ├── .github ├── dependabot.yml └── pull_request_template.md ├── .gitignore ├── .tool-versions ├── README.md ├── build └── .gitignore ├── dist ├── css │ ├── content.css │ ├── popup.css │ └── standup.css └── js │ ├── better-jira.js │ └── popup.js ├── icon_128.png ├── icon_16.png ├── icon_48.png ├── manifest.json ├── package.json ├── popup.html ├── src ├── js │ ├── better-jira.js │ ├── components │ │ ├── BetterJira.js │ │ ├── DetailResizer.js │ │ ├── Jira.js │ │ ├── OpenGithubInNewTab.js │ │ └── Standup.js │ └── popup.js └── sass │ ├── components │ ├── close.scss │ └── open.scss │ ├── content.scss │ ├── popup.scss │ └── standup.scss ├── webpack.mix.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | day: friday 8 | time: "11:00" 9 | open-pull-requests-limit: 10 10 | versioning-strategy: lockfile-only 11 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Checklist 2 | - [ ] Publish to Google Chrome Store 3 | - [ ] Publish to Firefox Addons 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules 3 | *.map 4 | /yarn-error.log 5 | /mix-manifest.json 6 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 10.9.0 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Better JIRA 2 | 3 | Ever wished that large Kanban boards could not be squished? Now you can set your own custom Column width for all of your cards on all of your boards. 4 | 5 | To install, visit this link: [Chrome Web Store](https://chrome.google.com/webstore/detail/better-jira/adjlkmhgnjccbagimdppnminndehkmgl). 6 | 7 | ## Planned features: 8 | 9 | - [x] Resizeable Detail view (via drag) 10 | - [x] Adding a standup view to give more space 11 | - [x] Adding a toggle to turn the extension off from within it’s menu 12 | - [ ] Adding an intuitive interface for inputing large numbers of tickets 13 | - [ ] Add a "Create and Open" button 14 | - [ ] Add a new Card design that allows hovering for more detail, bigger image, etc. (perhaps paired with standup mode) 15 | - [ ] Icon change when active/enabled 16 | - [ ] Add card overview when on a specific card in Standup Mode. 17 | - [x] Standup Variant (access to the filters and assignee drop downs) [add a visual element for displaying filters, remember status] 18 | - [x] Open Github Links in a New Tab 19 | - [x] Firefox Plugin 20 | - [ ] Safari Plugin 21 | 22 | ## Running the code locally 23 | 24 | > **NOTE**: You will need `node` and `yarn` set up on your computer. 25 | 26 | Type `yarn run` into your terminal from the root of this project. It will output the available commands. 27 | 28 | ### To build the code: 29 | 30 | You will need node version 10.9.0 and yarn installed. In the root of the project, run: 31 | 32 | ``` 33 | yarn 34 | yarn prod 35 | ``` 36 | 37 | The source code is in the `src` directory, and the distributed code is in the the `dist` directory. 38 | -------------------------------------------------------------------------------- /build/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /dist/css/content.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --viewport-width: 2000px; 3 | --detail-view-width: 32vw; 4 | } 5 | 6 | .BetterJira-instructions { 7 | position: relative; 8 | top: 0; 9 | right: 0; 10 | z-index: 2; 11 | background: rgba(9, 30, 66, 0.04) none repeat scroll 0% 0%; 12 | -webkit-transition: background 0.1s ease-out 0s, -webkit-box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s; 13 | transition: background 0.1s ease-out 0s, -webkit-box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s; 14 | transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s; 15 | transition: background 0.1s ease-out 0s, box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s, -webkit-box-shadow 0.15s cubic-bezier(0.47, 0.03, 0.49, 1.38) 0s; 16 | color: var(--ds-text, #42526E) !important; 17 | font-weight: 500; 18 | padding: 0px 10px; 19 | height: 2.28571em; 20 | line-height: 2.28571em; 21 | cursor: pointer; 22 | } 23 | 24 | .BetterJira-instructions .text { 25 | margin-right: 1.4rem; 26 | } 27 | 28 | .BetterJira-instructions:hover { 29 | background: rgba(9, 30, 66, 0.08); 30 | color: #42526e !important; 31 | -webkit-transition-duration: 0s, 0.15s; 32 | transition-duration: 0s, 0.15s; 33 | } 34 | 35 | .BetterJira-instructions .close { 36 | position: absolute; 37 | right: -2px; 38 | top: 0px; 39 | font-size: 1.7rem; 40 | font-family: verdana; 41 | -webkit-transform: rotate(-90deg); 42 | transform: rotate(-90deg); 43 | cursor: pointer; 44 | -webkit-user-select: none; 45 | -moz-user-select: none; 46 | -ms-user-select: none; 47 | user-select: none; 48 | color: #d04437; 49 | } 50 | 51 | .BetterJira-instructions .close:hover { 52 | color: #82271f; 53 | } 54 | 55 | .BetterJira-instructions .open { 56 | position: absolute; 57 | right: -2px; 58 | top: 0px; 59 | font-size: 1.7rem; 60 | font-family: verdana; 61 | -webkit-transform: rotate(90deg); 62 | transform: rotate(90deg); 63 | cursor: pointer; 64 | -webkit-user-select: none; 65 | -moz-user-select: none; 66 | -ms-user-select: none; 67 | user-select: none; 68 | color: #0052CC; 69 | } 70 | 71 | .BetterJira-instructions .open:hover { 72 | color: #002966; 73 | } 74 | 75 | body.better-jira { 76 | /* horizontal scroll on kanban boards */ 77 | /* horizontal scroll on board settings -> columns option */ 78 | /* story detail view coulmn */ 79 | /* Prevent column headers from overlapping when scrolling vertically */ 80 | } 81 | 82 | body.better-jira #ghx-column-headers .ghx-column { 83 | padding: 5px 17px !important; 84 | } 85 | 86 | body.better-jira #ghx-column-headers .ghx-column h2, 87 | body.better-jira #ghx-column-headers .ghx-column .ghx-qty, 88 | body.better-jira #ghx-column-headers .ghx-column .ghx-limits { 89 | font-size: 1em !important; 90 | font-weight: 700 !important; 91 | } 92 | 93 | body.better-jira #gh #ghx-work #ghx-pool-column.ghx-flexible-board .ghx-swimlane .ghx-swimlane-header { 94 | top: 30px !important; 95 | } 96 | 97 | body.better-jira #ghx-pool-column { 98 | overflow-y: auto; 99 | } 100 | 101 | body.better-jira #ghx-pool { 102 | width: auto; 103 | } 104 | 105 | body.better-jira #jira-board { 106 | width: var(--viewport-width); 107 | } 108 | 109 | body.better-jira #ghx-pool-wrapper { 110 | display: grid; 111 | } 112 | 113 | body.better-jira .ghx-page-panel-content-item { 114 | overflow-y: hidden; 115 | } 116 | 117 | body.better-jira #ghx-mapping { 118 | width: var(--viewport-width) !important; 119 | } 120 | 121 | body.better-jira #ghx-detail-view:not(.ui-resizable) { 122 | width: var(--detail-view-width) !important; 123 | position: relative; 124 | z-index: 3; 125 | } 126 | 127 | body.better-jira .aui-sidebar { 128 | z-index: 2; 129 | } 130 | 131 | body.better-jira #ghx-pool-column { 132 | display: block !important; 133 | overflow-x: scroll !important; 134 | } 135 | 136 | body.better-jira .better-resize { 137 | z-index: 90; 138 | width: 7px; 139 | position: absolute; 140 | top: 0; 141 | left: -2px; 142 | cursor: col-resize; 143 | height: 100%; 144 | } 145 | 146 | body.screenshot #js-work-quickfilters dd, 147 | body.screenshot .ghx-key-group, 148 | body.screenshot .ghx-group { 149 | -webkit-filter: blur(3px); 150 | filter: blur(3px); 151 | } 152 | 153 | body.screenshot #ghx-view-selector { 154 | -webkit-filter: blur(5px); 155 | filter: blur(5px); 156 | } 157 | 158 | body.screenshot .ghx-detail-summary, 159 | body.screenshot #js-detail-nav-content { 160 | -webkit-filter: blur(4px); 161 | filter: blur(4px); 162 | } 163 | 164 | body.screenshot .ghx-wrap-issue section { 165 | -webkit-filter: blur(4px); 166 | filter: blur(4px); 167 | } 168 | 169 | body.screenshot .ghx-wrap-issue .ghx-grabber { 170 | -webkit-filter: blur(3px); 171 | filter: blur(3px); 172 | } 173 | 174 | -------------------------------------------------------------------------------- /dist/css/popup.css: -------------------------------------------------------------------------------- 1 | html { 2 | background-color: #f5f6f7; 3 | overflow: hidden; 4 | } 5 | 6 | body { 7 | font-family: 'Raleway', Helvetica, sans-serif; 8 | font-size: 100%; 9 | width: 450px; 10 | margin: 0; 11 | } 12 | 13 | header, 14 | main { 15 | padding: 8px; 16 | } 17 | 18 | header { 19 | background-color: #fff; 20 | border-bottom: 1px solid #d1d4d7; 21 | -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 22 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 23 | position: relative; 24 | } 25 | 26 | .close { 27 | position: absolute; 28 | right: -2px; 29 | top: 0px; 30 | font-size: 1.7rem; 31 | font-family: verdana; 32 | -webkit-transform: rotate(-90deg); 33 | transform: rotate(-90deg); 34 | cursor: pointer; 35 | -webkit-user-select: none; 36 | -moz-user-select: none; 37 | -ms-user-select: none; 38 | user-select: none; 39 | color: #d04437; 40 | } 41 | 42 | .close:hover { 43 | color: #82271f; 44 | } 45 | 46 | h1 { 47 | margin: 0; 48 | font-family: 'Montserrat', Helvetica, sans-serif; 49 | display: inline-block; 50 | color: #1a5ca2; 51 | -webkit-user-select: none; 52 | -moz-user-select: none; 53 | -ms-user-select: none; 54 | user-select: none; 55 | cursor: default; 56 | } 57 | 58 | form { 59 | height: 100%; 60 | width: 100%; 61 | } 62 | 63 | form p { 64 | color: #808080; 65 | font-size: 0.9rem; 66 | margin: 0 0 0.5rem 0; 67 | } 68 | 69 | form label { 70 | -webkit-user-select: none; 71 | -moz-user-select: none; 72 | -ms-user-select: none; 73 | user-select: none; 74 | } 75 | 76 | form label.checkbox { 77 | display: block; 78 | cursor: pointer; 79 | font-size: 0.9rem; 80 | } 81 | 82 | form label.checkbox input { 83 | vertical-align: top; 84 | } 85 | 86 | form input[type='submit'] { 87 | background-color: #1cb330; 88 | color: white; 89 | font-size: 16px; 90 | font-family: 'Raleway', Helvetica, sans-serif; 91 | border: none; 92 | border-radius: 4px; 93 | padding: 0 36px; 94 | letter-spacing: 0.5px; 95 | cursor: pointer; 96 | outline: none; 97 | } 98 | 99 | form input[type='submit']:hover { 100 | background-color: #1dbc32; 101 | } 102 | 103 | form input[type='submit']:active { 104 | background-color: #1cb330; 105 | } 106 | 107 | form input[type='number'] { 108 | font-size: 16px; 109 | font-family: 'Montserrat', Helvetica, sans-serif; 110 | padding-left: 22px; 111 | padding-right: 0; 112 | width: 54px; 113 | outline: none; 114 | } 115 | 116 | form .form-element { 117 | padding: 6px; 118 | } 119 | 120 | form .form-element label { 121 | margin-right: 8px; 122 | } 123 | 124 | .card { 125 | background-color: white; 126 | border-radius: 4px; 127 | padding: 8px; 128 | border: 1px solid #dddddd; 129 | } 130 | 131 | .card .row { 132 | margin-bottom: 0; 133 | } 134 | 135 | .card.hover:hover:not(.selected) { 136 | background-color: rgba(222, 235, 255, 0.9); 137 | border-color: #0052CC; 138 | cursor: pointer; 139 | } 140 | 141 | .card.selected { 142 | background-color: #0052CC; 143 | border-color: #0052CC; 144 | color: white; 145 | } 146 | 147 | .row { 148 | margin-bottom: 0.5rem; 149 | display: -webkit-box; 150 | display: -ms-flexbox; 151 | display: flex; 152 | -webkit-box-pack: justify; 153 | -ms-flex-pack: justify; 154 | justify-content: space-between; 155 | } 156 | 157 | .row:last-child { 158 | margin-bottom: 0; 159 | } 160 | 161 | .col-3, 162 | .col-6 { 163 | margin-right: 0.5rem; 164 | -webkit-box-flex: 1; 165 | -ms-flex: 1; 166 | flex: 1; 167 | } 168 | 169 | .col-3:last-child, 170 | .col-6:last-child { 171 | margin-right: 0; 172 | } 173 | 174 | .text-center { 175 | text-align: center; 176 | } 177 | 178 | .padding-20 { 179 | padding: 20px; 180 | } 181 | 182 | -------------------------------------------------------------------------------- /dist/css/standup.css: -------------------------------------------------------------------------------- 1 | body.standup { 2 | /* 3 | |-------------------------------------------------------------------------- 4 | | New JIRA Experience 5 | |-------------------------------------------------------------------------- 6 | */ 7 | } 8 | 9 | body.standup #ghx-header, 10 | body.standup #header, 11 | body.standup .aui-sidebar { 12 | display: none; 13 | } 14 | 15 | body.standup #ghx-operations { 16 | padding-top: 1rem; 17 | } 18 | 19 | body.standup #gh { 20 | padding-left: 0; 21 | margin-left: 0; 22 | } 23 | 24 | body.standup #ghx-rabid { 25 | height: 100vh; 26 | } 27 | 28 | body.standup #ghx-work { 29 | height: calc(100vh - 71px) !important; 30 | } 31 | 32 | body.standup.adg3 { 33 | --topNavigationHeight: 0px; 34 | } 35 | 36 | body.standup.adg3 #navigation-app { 37 | display: none; 38 | } 39 | 40 | body.standup.adg3 #page-body > #content { 41 | border-top: 0px solid transparent; 42 | } 43 | 44 | body.standup.adg3 #content { 45 | margin-left: 1rem; 46 | } 47 | 48 | body.standup.adg3 #jira-frontend 49 | > div 50 | > div 51 | > div[class^='css']:nth-of-type(3) 52 | > div:first-child { 53 | display: none; 54 | } 55 | 56 | body.standup.adg3 div#ak-jira-navigation { 57 | display: none; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /dist/js/better-jira.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { 40 | /******/ configurable: false, 41 | /******/ enumerable: true, 42 | /******/ get: getter 43 | /******/ }); 44 | /******/ } 45 | /******/ }; 46 | /******/ 47 | /******/ // getDefaultExport function for compatibility with non-harmony modules 48 | /******/ __webpack_require__.n = function(module) { 49 | /******/ var getter = module && module.__esModule ? 50 | /******/ function getDefault() { return module['default']; } : 51 | /******/ function getModuleExports() { return module; }; 52 | /******/ __webpack_require__.d(getter, 'a', getter); 53 | /******/ return getter; 54 | /******/ }; 55 | /******/ 56 | /******/ // Object.prototype.hasOwnProperty.call 57 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 | /******/ 59 | /******/ // __webpack_public_path__ 60 | /******/ __webpack_require__.p = "/"; 61 | /******/ 62 | /******/ // Load entry module and return exports 63 | /******/ return __webpack_require__(__webpack_require__.s = 1); 64 | /******/ }) 65 | /************************************************************************/ 66 | /******/ ([ 67 | /* 0 */ 68 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 69 | 70 | "use strict"; 71 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 72 | 73 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 74 | 75 | var Jira = function () { 76 | function Jira() { 77 | _classCallCheck(this, Jira); 78 | 79 | this._isPresent = null; 80 | } 81 | 82 | _createClass(Jira, [{ 83 | key: 'isPresent', 84 | value: function isPresent() { 85 | if (this._isPresent !== null) { 86 | return this._isPresent; 87 | } 88 | 89 | try { 90 | var jira = document.querySelector('meta[name="application-name"]'); 91 | return this._isPresent = jira.content === 'JIRA'; 92 | } catch (e) { 93 | return this._isPresent = false; 94 | } 95 | } 96 | }, { 97 | key: 'isNotPresent', 98 | value: function isNotPresent() { 99 | return !this.isPresent(); 100 | } 101 | }, { 102 | key: 'hasLoadedSwimlanes', 103 | value: function hasLoadedSwimlanes() { 104 | return !!document.querySelector('.ghx-swimlane, #ghx-mapping, #jira-board > div > div'); 105 | } 106 | }, { 107 | key: 'hasNotLoadedSwimlanes', 108 | value: function hasNotLoadedSwimlanes() { 109 | return !this.hasLoadedSwimlanes(); 110 | } 111 | }, { 112 | key: 'columnsContainer', 113 | value: function columnsContainer() { 114 | return document.querySelector('.ghx-swimlane > .ghx-columns, #ghx-mapping, .aui-page-panel-content > #jira-board'); 115 | } 116 | }, { 117 | key: 'columns', 118 | value: function columns() { 119 | return this.columnsContainer().querySelectorAll('.ghx-column, .ghx-column-wrapper, [class*="hook__column"]'); 120 | } 121 | }, { 122 | key: 'content', 123 | value: function content() { 124 | return document.getElementById('content'); 125 | } 126 | }]); 127 | 128 | return Jira; 129 | }(); 130 | 131 | /* harmony default export */ __webpack_exports__["a"] = (new Jira()); 132 | 133 | /***/ }), 134 | /* 1 */ 135 | /***/ (function(module, exports, __webpack_require__) { 136 | 137 | __webpack_require__(2); 138 | __webpack_require__(7); 139 | __webpack_require__(8); 140 | module.exports = __webpack_require__(9); 141 | 142 | 143 | /***/ }), 144 | /* 2 */ 145 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 146 | 147 | "use strict"; 148 | Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); 149 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__components_DetailResizer__ = __webpack_require__(3); 150 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__components_BetterJira__ = __webpack_require__(4); 151 | 152 | 153 | 154 | var betterJira = __WEBPACK_IMPORTED_MODULE_1__components_BetterJira__["a" /* default */].initialize(); 155 | __WEBPACK_IMPORTED_MODULE_0__components_DetailResizer__["a" /* default */].run(); 156 | 157 | document.addEventListener('better-jira:updated', function (event) { 158 | console.log('🔧: ', event.detail); 159 | betterJira.update(event); 160 | }); 161 | 162 | /***/ }), 163 | /* 3 */ 164 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 165 | 166 | "use strict"; 167 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Jira__ = __webpack_require__(0); 168 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 169 | 170 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 171 | 172 | 173 | 174 | var DetailResizer = function () { 175 | function DetailResizer() { 176 | _classCallCheck(this, DetailResizer); 177 | 178 | this.id = 'ghx-detail-view'; 179 | this.Storage = chrome.storage.sync; 180 | this.listening = false; 181 | this.running = true; 182 | this.manageMouseListener = this.manageMouse.bind(this); 183 | } 184 | 185 | _createClass(DetailResizer, [{ 186 | key: 'run', 187 | value: function run() { 188 | var _this = this; 189 | 190 | if (__WEBPACK_IMPORTED_MODULE_0__Jira__["a" /* default */].isNotPresent()) { 191 | this.running = false; 192 | return; 193 | } 194 | 195 | var detailView = document.getElementById(this.id); 196 | if (!detailView) { 197 | this.running = false; 198 | return; 199 | } 200 | detailView.addEventListener('mouseenter', function () { 201 | if (detailView.querySelector('.better-resize') !== null) { 202 | return; 203 | } 204 | 205 | var resizer = document.createElement('div'); 206 | resizer.classList.add('better-resize'); 207 | detailView.appendChild(resizer); 208 | 209 | detailView.querySelector('.better-resize').addEventListener('mousedown', function (event) { 210 | event.preventDefault(); 211 | if (event.button === 2) { 212 | return; 213 | } 214 | 215 | document.addEventListener('mousemove', _this.manageMouseListener); 216 | _this.listening = true; 217 | }); 218 | 219 | document.addEventListener('mouseup', function (event) { 220 | if (!_this.listening) { 221 | return; 222 | } 223 | 224 | document.removeEventListener('mousemove', _this.manageMouseListener); 225 | _this.listening = false; 226 | 227 | _this.saveDetailViewWidth(); 228 | }); 229 | }); 230 | 231 | // detailView.addEventListener('mouseleave', () => { 232 | // console.log('You are now exiting'); 233 | // detailView.querySelector('.better-resize').remove(); 234 | // }); 235 | } 236 | }, { 237 | key: 'manageMouse', 238 | value: function manageMouse(event) { 239 | if (!this.running) { 240 | return; 241 | } 242 | 243 | var width = window.innerWidth - event.pageX + 2; 244 | 245 | document.documentElement.style.setProperty('--detail-view-width', width + 'px'); 246 | } 247 | }, { 248 | key: 'saveDetailViewWidth', 249 | value: function saveDetailViewWidth() { 250 | if (!this.running) { 251 | return; 252 | } 253 | 254 | console.log('🔧: Detail Width', document.documentElement.style.getPropertyValue('--detail-view-width')); 255 | this.Storage.set({ 256 | detailViewWidth: document.documentElement.style.getPropertyValue('--detail-view-width') 257 | }); 258 | } 259 | }]); 260 | 261 | return DetailResizer; 262 | }(); 263 | 264 | /* harmony default export */ __webpack_exports__["a"] = (new DetailResizer()); 265 | 266 | /***/ }), 267 | /* 4 */ 268 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 269 | 270 | "use strict"; 271 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Standup__ = __webpack_require__(5); 272 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Jira__ = __webpack_require__(0); 273 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__OpenGithubInNewTab__ = __webpack_require__(6); 274 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 275 | 276 | function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 277 | 278 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 279 | 280 | 281 | 282 | 283 | 284 | var BetterJira = function () { 285 | _createClass(BetterJira, null, [{ 286 | key: 'initialize', 287 | value: function initialize() { 288 | return new this(); 289 | } 290 | }]); 291 | 292 | function BetterJira() { 293 | var _this = this; 294 | 295 | _classCallCheck(this, BetterJira); 296 | 297 | this.data = {}; 298 | this.Storage = chrome.storage.sync; 299 | this.running = true; 300 | this.instructionsCssClass = 'BetterJira-instructions'; 301 | 302 | if (__WEBPACK_IMPORTED_MODULE_1__Jira__["a" /* default */].isNotPresent()) { 303 | this.running = false; 304 | return; 305 | } 306 | 307 | this._initialColumnResize(); 308 | this.Storage.get('standup', function (storage) { 309 | _this._initiateStandup(storage.standup); 310 | }); 311 | this._openGithubLinksInNewTabs(); 312 | } 313 | 314 | _createClass(BetterJira, [{ 315 | key: 'update', 316 | value: function update(event) { 317 | this._updateColumnWidths(event.detail); 318 | this._initiateStandup(event.detail.standup); 319 | } 320 | }, { 321 | key: '_updateColumnWidths', 322 | value: function _updateColumnWidths(detail) { 323 | if (!this.running) { 324 | return; 325 | } 326 | 327 | if (!detail.enabled) { 328 | document.body.classList.remove('better-jira'); 329 | document.getElementById('ghx-pool-wrapper').style.width = 'auto'; 330 | return; 331 | } 332 | document.body.classList.add('better-jira'); 333 | this._getPreferredWidth(detail); 334 | } 335 | }, { 336 | key: '_ifEnabled', 337 | value: function _ifEnabled(enabledCallback) { 338 | var disabledCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; 339 | 340 | if (!this.running) { 341 | return; 342 | } 343 | 344 | this.Storage.get('enabled', function (storage) { 345 | if (!storage.enabled) { 346 | disabledCallback(); 347 | return; 348 | } 349 | 350 | enabledCallback(); 351 | }); 352 | } 353 | }, { 354 | key: '_initialColumnResize', 355 | value: function _initialColumnResize() { 356 | var _this2 = this; 357 | 358 | if (!this.running) { 359 | return; 360 | } 361 | 362 | setTimeout(function () { 363 | if (__WEBPACK_IMPORTED_MODULE_1__Jira__["a" /* default */].hasNotLoadedSwimlanes()) { 364 | // console.log('🔧: Swimlanes not present, waiting 100ms.'); 365 | return _this2._initialColumnResize(); 366 | } 367 | // console.log('🔧: Swimlanes are present, resizing now.'); 368 | 369 | var enabled = function enabled() { 370 | document.body.classList.add('better-jira'); 371 | _this2.Storage.get('columnWidth', _this2._getPreferredWidth.bind(_this2)); 372 | _this2._protectAgainstReactBoardReloading(); 373 | }; 374 | 375 | //-- Disallow setting columns if the plugin is not enabled 376 | var disabled = function disabled() { 377 | document.body.classList.remove('better-jira'); 378 | document.getElementById('ghx-pool-wrapper').style.width = 'auto'; 379 | }; 380 | _this2._ifEnabled(enabled, disabled); 381 | }, 100); 382 | } 383 | }, { 384 | key: '_getPreferredWidth', 385 | value: function _getPreferredWidth(storage) { 386 | if (!this.running) { 387 | return; 388 | } 389 | 390 | this.data.columnWidth = storage.columnWidth; 391 | 392 | if (!this.data.columnWidth) { 393 | this.data.columnWidth = 'sm'; 394 | } 395 | 396 | this._setPreferredWidth(); 397 | } 398 | }, { 399 | key: '_setPreferredWidth', 400 | value: function _setPreferredWidth() { 401 | if (!this.running) { 402 | return; 403 | } 404 | 405 | var preferredWidth = void 0; 406 | 407 | preferredWidth = this.data.columnWidth; 408 | 409 | try { 410 | var items = { poolWidth: preferredWidth }; 411 | this.Storage.set(items); 412 | 413 | this._setPoolWidth(preferredWidth); 414 | } catch (e) { 415 | console.error(e); 416 | } 417 | } 418 | }, { 419 | key: '_setPoolWidth', 420 | value: function _setPoolWidth(width) { 421 | 422 | //-- Define sizes 423 | var columnWidths = { 424 | sm: 'auto', 425 | md: '150%', 426 | lg: '200%', 427 | xl: '250%' 428 | }; 429 | 430 | if (width === 'sm') { 431 | document.getElementById('ghx-pool-wrapper').style.width = 'auto'; 432 | } else { 433 | document.getElementById('ghx-pool-wrapper').style.width = 'var(--viewport-width)'; 434 | document.documentElement.style.setProperty('--viewport-width', '' + columnWidths[width]); 435 | } 436 | } 437 | }, { 438 | key: '_setDetailViewWidth', 439 | value: function _setDetailViewWidth(width) { 440 | document.documentElement.style.setProperty('--detail-view-width', width); 441 | } 442 | }, { 443 | key: '_initiateStandup', 444 | value: function _initiateStandup(config) { 445 | __WEBPACK_IMPORTED_MODULE_0__Standup__["a" /* default */].run(config); 446 | } 447 | }, { 448 | key: '_protectAgainstReactBoardReloading', 449 | value: function _protectAgainstReactBoardReloading() { 450 | var _this3 = this; 451 | 452 | var mutationObserver = new MutationObserver(function (mutations) { 453 | var contentHasBeenDeleted = mutations.find(function (mutation) { 454 | if (mutation.removedNodes < 1) { 455 | return false; 456 | } 457 | 458 | var removedNodes = [].concat(_toConsumableArray(mutation.removedNodes)); 459 | return removedNodes.find(function (node) { 460 | return node.id === 'ghx-pool-column'; 461 | }); 462 | }); 463 | 464 | if (contentHasBeenDeleted) { 465 | mutationObserver.disconnect(); 466 | _this3._initialColumnResize(); 467 | } 468 | }); 469 | mutationObserver.observe(__WEBPACK_IMPORTED_MODULE_1__Jira__["a" /* default */].content(), { 470 | childList: true, 471 | subtree: true 472 | }); 473 | } 474 | }, { 475 | key: '_openGithubLinksInNewTabs', 476 | value: function _openGithubLinksInNewTabs() { 477 | __WEBPACK_IMPORTED_MODULE_2__OpenGithubInNewTab__["a" /* default */].initialize(); 478 | } 479 | }]); 480 | 481 | return BetterJira; 482 | }(); 483 | 484 | /* harmony default export */ __webpack_exports__["a"] = (BetterJira); 485 | 486 | /***/ }), 487 | /* 5 */ 488 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 489 | 490 | "use strict"; 491 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Jira__ = __webpack_require__(0); 492 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 493 | 494 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 495 | 496 | 497 | 498 | var Standup = function () { 499 | function Standup() { 500 | _classCallCheck(this, Standup); 501 | 502 | this.cssClass = 'standup'; 503 | this.instructionsCssClass = 'BetterJira-instructions'; 504 | this.data = {}; 505 | this.running = true; 506 | } 507 | 508 | _createClass(Standup, [{ 509 | key: 'run', 510 | value: function run(state) { 511 | var _this = this; 512 | 513 | if (__WEBPACK_IMPORTED_MODULE_0__Jira__["a" /* default */].isNotPresent()) { 514 | this.running = false; 515 | return; 516 | } 517 | 518 | // Open standup listener 519 | this._listener = function (click) { 520 | var standupButton = click.target.closest('[data-standup-open]'); 521 | if (!standupButton) { 522 | return; 523 | } 524 | 525 | chrome.storage.sync.set({ standup: true }, function () { 526 | _this.initializeStandup(true); 527 | }); 528 | }; 529 | document.addEventListener('click', this._listener); 530 | 531 | //-- Add open Standup Mode button element 532 | var openStandupModeBtn = document.createElement('div'); 533 | openStandupModeBtn.setAttribute('data-standup-open', ''); 534 | openStandupModeBtn.classList.add(this.instructionsCssClass); 535 | openStandupModeBtn.innerHTML = 'Standup Mode « '; 536 | openStandupModeBtn.style.display = 'none'; 537 | document.getElementById('ghx-operations').appendChild(openStandupModeBtn); 538 | 539 | // Close standup listener 540 | this._listener = function (click) { 541 | var closeButton = click.target.closest('[data-standup-close]'); 542 | if (!closeButton) { 543 | return; 544 | } 545 | 546 | chrome.storage.sync.set({ standup: false }, function () { 547 | _this._cleanupStandup(); 548 | }); 549 | }; 550 | document.addEventListener('click', this._listener); 551 | 552 | //-- Add close Standup Mode button element 553 | var closeStandupModeBtn = document.createElement('div'); 554 | closeStandupModeBtn.setAttribute('data-standup-close', ''); 555 | closeStandupModeBtn.classList.add(this.instructionsCssClass); 556 | closeStandupModeBtn.innerHTML = 'Standup Mode « '; 557 | closeStandupModeBtn.style.display = 'none'; 558 | document.getElementById('ghx-operations').appendChild(closeStandupModeBtn); 559 | 560 | if (!state) { 561 | this._cleanupStandup(); 562 | return; 563 | } 564 | 565 | this.initializeStandup(); 566 | } 567 | }, { 568 | key: 'initializeStandup', 569 | value: function initializeStandup() { 570 | if (!this.running) { 571 | return; 572 | } 573 | 574 | window.standup = true; 575 | 576 | //-- Add `standup` class to the body 577 | document.body.classList.add(this.cssClass); 578 | 579 | //-- Show close standup mode button 580 | document.querySelector('[data-standup-close]').style.display = 'block'; 581 | 582 | //-- Hide open standup mode button 583 | document.querySelector('[data-standup-open]').style.display = 'none'; 584 | 585 | //-- Hide breadcrumbs 586 | document.querySelector('[data-testid="rapidboard-breadcrumbs"]').style.display = 'none'; 587 | } 588 | }, { 589 | key: '_cleanupStandup', 590 | value: function _cleanupStandup() { 591 | 592 | //-- Remove standup class 593 | document.body.classList.remove(this.cssClass); 594 | 595 | //-- Turn off standup mode 596 | window.standup = false; 597 | 598 | //-- Hide close standup mode button 599 | document.querySelector('[data-standup-close]').style.display = 'none'; 600 | 601 | //-- Show open standup mode button 602 | document.querySelector('[data-standup-open]').style.display = 'block'; 603 | 604 | //-- Show breadcrumbs 605 | document.querySelector('[data-testid="rapidboard-breadcrumbs"]').style.display = 'block'; 606 | } 607 | }]); 608 | 609 | return Standup; 610 | }(); 611 | 612 | /* harmony default export */ __webpack_exports__["a"] = (new Standup()); 613 | 614 | /***/ }), 615 | /* 6 */ 616 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 617 | 618 | "use strict"; 619 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 620 | 621 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 622 | 623 | var OpenGithubInNewTab = function () { 624 | _createClass(OpenGithubInNewTab, null, [{ 625 | key: 'initialize', 626 | value: function initialize() { 627 | return new this(); 628 | } 629 | }]); 630 | 631 | function OpenGithubInNewTab() { 632 | _classCallCheck(this, OpenGithubInNewTab); 633 | 634 | document.addEventListener('click', function (click) { 635 | var githubLink = click.target.closest('.pullrequest-link, .repository-link, .branch-link, .create-pullrequest-link, .changesetid, .filename a, .filerow a.more-files-info'); 636 | if (!githubLink) { 637 | return; 638 | } 639 | 640 | click.preventDefault(); 641 | 642 | var newWindow = window.open(githubLink.href, '_blank'); 643 | newWindow.opener = null; 644 | }); 645 | } 646 | 647 | return OpenGithubInNewTab; 648 | }(); 649 | 650 | /* harmony default export */ __webpack_exports__["a"] = (OpenGithubInNewTab); 651 | 652 | /***/ }), 653 | /* 7 */ 654 | /***/ (function(module, exports) { 655 | 656 | // removed by extract-text-webpack-plugin 657 | 658 | /***/ }), 659 | /* 8 */ 660 | /***/ (function(module, exports) { 661 | 662 | // removed by extract-text-webpack-plugin 663 | 664 | /***/ }), 665 | /* 9 */ 666 | /***/ (function(module, exports) { 667 | 668 | // removed by extract-text-webpack-plugin 669 | 670 | /***/ }) 671 | /******/ ]); -------------------------------------------------------------------------------- /dist/js/popup.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { 40 | /******/ configurable: false, 41 | /******/ enumerable: true, 42 | /******/ get: getter 43 | /******/ }); 44 | /******/ } 45 | /******/ }; 46 | /******/ 47 | /******/ // getDefaultExport function for compatibility with non-harmony modules 48 | /******/ __webpack_require__.n = function(module) { 49 | /******/ var getter = module && module.__esModule ? 50 | /******/ function getDefault() { return module['default']; } : 51 | /******/ function getModuleExports() { return module; }; 52 | /******/ __webpack_require__.d(getter, 'a', getter); 53 | /******/ return getter; 54 | /******/ }; 55 | /******/ 56 | /******/ // Object.prototype.hasOwnProperty.call 57 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 58 | /******/ 59 | /******/ // __webpack_public_path__ 60 | /******/ __webpack_require__.p = "/"; 61 | /******/ 62 | /******/ // Load entry module and return exports 63 | /******/ return __webpack_require__(__webpack_require__.s = 10); 64 | /******/ }) 65 | /************************************************************************/ 66 | /******/ ({ 67 | 68 | /***/ 10: 69 | /***/ (function(module, exports, __webpack_require__) { 70 | 71 | module.exports = __webpack_require__(11); 72 | 73 | 74 | /***/ }), 75 | 76 | /***/ 11: 77 | /***/ (function(module, exports) { 78 | 79 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 80 | 81 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 82 | 83 | var Popup = function () { 84 | function Popup() { 85 | _classCallCheck(this, Popup); 86 | 87 | this.Storage = chrome.storage.sync; 88 | this.data = {}; 89 | this.defaults = { 90 | columnWidth: 200, 91 | enabled: true, 92 | standup: false, 93 | updatedEvent: 'better-jira:updated' 94 | }; 95 | 96 | this.loadListener = this.boot.bind(this); 97 | window.addEventListener('load', this.loadListener); 98 | } 99 | 100 | _createClass(Popup, [{ 101 | key: 'boot', 102 | value: function boot() { 103 | window.removeEventListener('load', this.loadListener); 104 | 105 | this.setDefaults(); 106 | this.handleFormEvents(); 107 | } 108 | }, { 109 | key: 'setDefaults', 110 | value: function setDefaults() { 111 | var _this = this; 112 | 113 | this.Storage.get('columnWidth', function (storage) { 114 | console.log('storage', storage); 115 | var value = storage.columnWidth; 116 | console.log('columnWidth from Storage', value); 117 | if (!value) { 118 | value = _this.defaults.columnWidth; 119 | _this.Storage.set({ columnWidth: value }); 120 | } 121 | _this.data.columnWidth = value; 122 | 123 | //-- Set size selection 124 | document.querySelectorAll('[data-column-width-selector]').forEach(function (columnWidthSelector) { 125 | columnWidthSelector.classList.remove('selected'); 126 | }); 127 | if (_this.data.columnWidth === 'sm') { 128 | document.querySelector('[data-column-width-sm]').classList.add('selected'); 129 | } else if (_this.data.columnWidth === 'md') { 130 | document.querySelector('[data-column-width-md]').classList.add('selected'); 131 | } else if (_this.data.columnWidth === 'lg') { 132 | document.querySelector('[data-column-width-lg]').classList.add('selected'); 133 | } else if (_this.data.columnWidth === 'xl') { 134 | document.querySelector('[data-column-width-xl]').classList.add('selected'); 135 | } 136 | }); 137 | 138 | this.Storage.get('enabled', function (storage) { 139 | var value = storage.enabled; 140 | if (value === undefined) { 141 | value = _this.defaults.enabled; 142 | _this.Storage.set({ enabled: value }); 143 | } 144 | 145 | _this.data.enabled = value; 146 | console.log('enabled storage', storage); 147 | 148 | document.getElementById('enabled').checked = !!value; 149 | }); 150 | 151 | this.Storage.get('standup', function (storage) { 152 | var value = storage.standup; 153 | if (value === undefined) { 154 | value = _this.defaults.standup; 155 | _this.Storage.set({ standup: value }); 156 | } 157 | 158 | _this.data.standup = value; 159 | console.log('standup storage', storage); 160 | }); 161 | } 162 | }, { 163 | key: 'handleFormEvents', 164 | value: function handleFormEvents() { 165 | var _this2 = this; 166 | 167 | //-- Trigger Update Column Width (as a 1-click event) 168 | document.querySelectorAll('[data-column-width-selector]').forEach(function (columnWidthSelector) { 169 | columnWidthSelector.addEventListener('click', function (event) { 170 | _this2.data.columnWidth = event.target.dataset.columnWidth; 171 | _this2.save(); 172 | }); 173 | }); 174 | 175 | //-- Trigger Enabled (as a 1-click event) 176 | var enabled = document.getElementById('enabled'); 177 | enabled.addEventListener('click', function (event) { 178 | _this2.data.enabled = enabled.checked; 179 | _this2.save(); 180 | }); 181 | } 182 | }, { 183 | key: 'save', 184 | value: function save() { 185 | var _this3 = this; 186 | 187 | this.Storage.set({ enabled: this.data.enabled }, function () { 188 | _this3.Storage.set({ columnWidth: _this3.data.columnWidth }, function () { 189 | _this3.setDefaults(); 190 | _this3.Storage.set({ standup: _this3.data.standup }, _this3.refresh.bind(_this3)); 191 | }); 192 | }); 193 | } 194 | }, { 195 | key: 'refresh', 196 | value: function refresh() { 197 | var code = ['(function()', '{', '\'use strict\';', 'let updateEvent = new CustomEvent(\'' + this.defaults.updatedEvent + '\', {', 'detail: {', 'columnWidth: \'' + this.data.columnWidth + '\',', 'enabled: ' + this.data.enabled + ',', 'standup: ' + this.data.standup + ',', '}', '});', 'document.dispatchEvent(updateEvent);', '})();']; 198 | 199 | chrome.tabs.executeScript({ 200 | code: code.join('') 201 | }); 202 | } 203 | }]); 204 | 205 | return Popup; 206 | }(); 207 | 208 | new Popup(); 209 | 210 | /***/ }) 211 | 212 | /******/ }); -------------------------------------------------------------------------------- /icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshwhatk/better-jira/11c7fa948fea6075acb76409424838b52c57a07b/icon_128.png -------------------------------------------------------------------------------- /icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshwhatk/better-jira/11c7fa948fea6075acb76409424838b52c57a07b/icon_16.png -------------------------------------------------------------------------------- /icon_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshwhatk/better-jira/11c7fa948fea6075acb76409424838b52c57a07b/icon_48.png -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "browser_action": { 3 | "default_icon": "icon_16.png", 4 | "default_popup": "popup.html" 5 | }, 6 | "content_scripts": [ 7 | { 8 | "css": ["dist/css/content.css", "dist/css/standup.css"], 9 | "js": ["dist/js/better-jira.js"], 10 | "matches": ["https://*/*"] 11 | } 12 | ], 13 | "icons": { 14 | "16": "icon_16.png", 15 | "48": "icon_48.png", 16 | "128": "icon_128.png" 17 | }, 18 | "description": "Much needed interface improvements for Jira", 19 | "manifest_version": 2, 20 | "name": "Better Jira", 21 | "permissions": ["https://*.atlassian.net/*", "storage"], 22 | "update_url": "https://clients2.google.com/service/update2/crx", 23 | "version": "1.5.3" 24 | } 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "hot": "NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 4 | "dev": "NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 5 | "watch": "NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "prod": "NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 7 | "build:chrome": "zip -r build/chrome-better-jira.zip . -x './node_modules/*' -x './.*' -x './build/*'", 8 | "build:firefox": "zip -r build/firefox-better-jira.zip . -x './node_modules/*' -x './.*' -x './build/*'" 9 | }, 10 | "devDependencies": { 11 | "laravel-mix": "^2.0.0" 12 | }, 13 | "prettier": { 14 | "singleQuote": true, 15 | "arrowParens": "always" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |