├── .gitignore ├── assets ├── settings │ ├── id.png │ ├── label.png │ ├── compact.png │ ├── numberOfCards.png │ └── hideAddNewList.png ├── logos │ ├── logo_128.png │ ├── logo_16.png │ ├── logo_19.png │ ├── logo_256.png │ ├── logo_32.png │ ├── logo_38.png │ ├── logo_64.png │ └── logo.svg └── page-action │ ├── download-16.svg │ ├── page-action-16.svg │ ├── page-action-19.svg │ ├── page-action-32.svg │ └── page-action-38.svg ├── Privacy_Policy.md ├── translate.js ├── page-action ├── main.js └── index.html ├── package.json ├── LICENSE ├── settings ├── options.js └── options.html ├── manifest.json ├── README.md ├── inject ├── enhancedStyles.css └── inject.js ├── _locales ├── es │ └── messages.json ├── fr │ └── messages.json ├── en │ └── messages.json └── de │ └── messages.json ├── CONTRIBUTING.md ├── background.js └── papaparse.min.js /.gitignore: -------------------------------------------------------------------------------- 1 | web-ext-artifacts 2 | node_modules 3 | -------------------------------------------------------------------------------- /assets/settings/id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/settings/id.png -------------------------------------------------------------------------------- /assets/logos/logo_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/logos/logo_128.png -------------------------------------------------------------------------------- /assets/logos/logo_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/logos/logo_16.png -------------------------------------------------------------------------------- /assets/logos/logo_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/logos/logo_19.png -------------------------------------------------------------------------------- /assets/logos/logo_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/logos/logo_256.png -------------------------------------------------------------------------------- /assets/logos/logo_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/logos/logo_32.png -------------------------------------------------------------------------------- /assets/logos/logo_38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/logos/logo_38.png -------------------------------------------------------------------------------- /assets/logos/logo_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/logos/logo_64.png -------------------------------------------------------------------------------- /assets/settings/label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/settings/label.png -------------------------------------------------------------------------------- /assets/settings/compact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/settings/compact.png -------------------------------------------------------------------------------- /assets/settings/numberOfCards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/settings/numberOfCards.png -------------------------------------------------------------------------------- /assets/settings/hideAddNewList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christiankaindl/trello-super-powers/HEAD/assets/settings/hideAddNewList.png -------------------------------------------------------------------------------- /assets/page-action/download-16.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Privacy_Policy.md: -------------------------------------------------------------------------------- 1 | # Trello Super Powers Privacy Policy 2 | 3 | Trello Super Powers does not collect any user information/data. Trello Super Powers only saves users preferences, nothing is ever synchronized to Trello Super Powers servers. Preferences may be synchronized with Firefox/Mozilla servers when the user uses Firefox Sync. 4 | 5 | Trello Super Powers also does not collect any information from your Trello boards. 6 | -------------------------------------------------------------------------------- /translate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Translate an HTML page with the i18n API 3 | * 4 | * @param {string} property Name of the HTML attribute used for localization 5 | */ 6 | function translate(property = 'data-translate') { 7 | let translateables = document.querySelectorAll(`[${property}]`); 8 | 9 | for (let i = 0; i < translateables.length; i++) { 10 | let string = translateables[i].getAttribute(property); 11 | translateables[i].textContent = browser.i18n.getMessage(string); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /page-action/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Handle form submit. Gather input values and send them to the Background Script. 3 | */ 4 | async function handleSubmit() { 5 | console.log("I AM HERE"); 6 | let data; 7 | 8 | data = { 9 | filename: `${document.getElementById("file-name").value}.csv`, 10 | delimiter: document.querySelector('input[name="delimiter"]:checked').value, 11 | includeArchived: document.getElementById("include-archived").checked 12 | }; 13 | 14 | exportButton.setAttribute("disabled", "disabled"); 15 | await browser.runtime.sendMessage({ type: "exportCSV", data: data }); 16 | exportButton.removeAttribute("disabled"); 17 | } 18 | 19 | let form = document.getElementById('csv-export'), 20 | exportButton = document.getElementById("export-button"); 21 | 22 | form.addEventListener('submit', handleSubmit); 23 | 24 | // exportButton.addEventListener("click", handleSubmit); 25 | translate(); 26 | -------------------------------------------------------------------------------- /assets/page-action/page-action-16.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "trello-super-powers", 3 | "description": "Firefox add-on to enhance your Trello (trello.com) experience. Get it here -> [https://addons.mozilla.org/en-US/firefox/addon/trello-super-powers/](https://addons.mozilla.org/en-US/firefox/addon/trello-super-powers/)", 4 | "version": "1.0.0", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1", 7 | "start:firefox": "web-ext run --source-dir ./", 8 | "build": "web-ext build", 9 | "lint": "web-ext lint" 10 | }, 11 | "keywords": [ 12 | "add-on", 13 | "web-extension", 14 | "trello" 15 | ], 16 | "author": "Christian Kaindl", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/christiankaindl/trello-super-powers/issues" 20 | }, 21 | "homepage": "https://github.com/christiankaindl/trello-super-powers#readme", 22 | "devDependencies": { 23 | "web-ext": "^6.5.0" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/christiankaindl/trello-super-powers.git" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Christian Kaindl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /settings/options.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Update storage with changed settings 5 | * 6 | * @param {object} e 'onchange' event object 7 | */ 8 | async function updateStorage (e) { 9 | var setting = e.target.getAttribute('name'), 10 | value = e.target.checked 11 | await browser.storage.local.set({ [setting]: value }) 12 | 13 | browser.notifications.create({ 14 | type: 'basic', 15 | title: browser.i18n.getMessage('settingsSavedNotificationTitle'), 16 | message: browser.i18n.getMessage('settingsSavedNotificationBody'), 17 | iconUrl: '../assets/logo.svg' 18 | }) 19 | } 20 | 21 | /** 22 | * Initialize settings page. Apply saved settings from storage and add evnt listener to the input elements. 23 | */ 24 | async function initialize () { 25 | var settings = await browser.storage.local.get(), 26 | inputs = document.getElementsByTagName('input'), 27 | translateables = document.querySelectorAll('[data-translate]') 28 | 29 | // Apply settings 30 | for (let i = 0; i < inputs.length; i++) { 31 | inputs[i].checked = settings[inputs[i].getAttribute('name')] 32 | inputs[i].addEventListener('change', updateStorage) 33 | } 34 | 35 | // Apply localized/translated strings 36 | translate() 37 | } 38 | 39 | initialize() 40 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "__MSG_extensionName__", 4 | "version": "0.13.3", 5 | 6 | "description": "__MSG_extensionDescription__", 7 | "homepage_url": "https://github.com/christiankaindl/trello-super-powers", 8 | "icons": { 9 | "16": "assets/logos/logo_16.png", 10 | "32": "assets/logos/logo_32.png", 11 | "64": "assets/logos/logo_64.png", 12 | "128": "assets/logos/logo_128.png", 13 | "256": "assets/logos/logo_256.png" 14 | }, 15 | "permissions": [ 16 | "tabs", "storage", "https://trello.com/b/*/", "notifications", "downloads" 17 | ], 18 | "background": { 19 | "scripts": ["background.js"] 20 | }, 21 | "page_action": { 22 | "browser_style": true, 23 | "default_icon": { 24 | "16": "assets/logos/logo_16.png", 25 | "19": "assets/logos/logo_19.png", 26 | "32": "assets/logos/logo_32.png", 27 | "38": "assets/logos/logo_38.png", 28 | "64": "assets/logos/logo_64.png", 29 | "128": "assets/logos/logo_128.png", 30 | "256": "assets/logos/logo_256.png" 31 | }, 32 | "default_title": "Export Trello board as CSV", 33 | "default_popup": "/page-action/index.html" 34 | }, 35 | 36 | "options_ui": { 37 | "page": "settings/options.html", 38 | "browser_style": true 39 | }, 40 | 41 | "applications": { 42 | "gecko": { 43 | "id": "{e8a71c3b-3deb-4ab3-834a-5c0aee943847}", 44 | "strict_min_version": "52.0" 45 | } 46 | }, 47 | "default_locale": "en" 48 | } 49 | -------------------------------------------------------------------------------- /assets/page-action/page-action-19.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/page-action/page-action-32.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/page-action/page-action-38.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Trello Super Powers 2 | 3 | Firefox add-on to enhance your Trello (trello.com) experience. Get it here -> [https://addons.mozilla.org/en-US/firefox/addon/trello-super-powers/](https://addons.mozilla.org/en-US/firefox/addon/trello-super-powers/) 4 | 5 | --- 6 | 7 | ## Features 8 | 9 | Trello Super Powers implements some small yet useful enhancements into your everyday Trello usage. 10 | 11 | - Visible label text 12 | - Clickable IDs on hover (+ they get copied to your clipboard when clicked) 13 | - Compact Mode: Removes all clutter if you want to focus 14 | - Resizable lists: Click and drag to adjust the size of your Trello lists 15 | - See at a glance how many cards are in each list 16 | - Option to hide "Add new List"-Element 17 | 18 | Also you can find explanation of these features and a way to turn them off in the settings of the Add-on ('about:addons' in your address bar or 'Add-Ons' in the hamburger menu). 19 | 20 | 21 | There are plenty of features waiting to be implemented, most notably Account integration, which would allow for blazing fast access to your boards and notification integration which would give you the newest from the newest directly from the Firefox toolbar. 22 | 23 | # Contribute 24 | 25 | If you want to contribute to this project, that is awesome! I tried to comment the code as good as I can and optimize it for readability. Hints and tricks to get you started can be found in the [CONTRIBUTING.md](https://github.com/christiankaindl/trello-super-powers/blob/master/CONTRIBUTING.md) file. 26 | 27 | If you have something on your mind or need help, hop to the [issues](https://github.com/christiankaindl/trello-super-powers/issues) tab and ask your question. There are lots of friendly people who will gladly help you out. 28 | 29 | Quick jump to... 30 | 31 | - **[Translation help](https://github.com/christiankaindl/trello-super-powers/blob/master/CONTRIBUTING.md#translations)** 32 | - **[Coding help](https://github.com/christiankaindl/trello-super-powers/blob/master/CONTRIBUTING.md#coding)** 33 | 34 | # Development 35 | - Clone repository: `git clone https://github.com/christiankaindl/trello-super-powers.git` 36 | - Install npm dependencies: 37 | - Start local dev environment: `npm run start` (starts a fresh Firefox instance with Trello Super Powers pre-loaded) 38 | 39 | # License 40 | 41 | This project, Trello Super Powers, is licensed under MIT. For details, please refer to the [LICENSE file](https://github.com/christiankaindl/trello-super-powers/blob/master/LICENSE) 42 | -------------------------------------------------------------------------------- /inject/enhancedStyles.css: -------------------------------------------------------------------------------- 1 | /*==== LABEL TEXT ====*/ 2 | /* Label text is already there by default in Trello, it is just hidden */ 3 | .TSP-label-enabled .list-card-labels .card-label { 4 | border-radius: 4px; 5 | font-size: 0.8em; 6 | height: auto; 7 | line-height: 10px; 8 | padding: 4px 6px; 9 | text-shadow: none; 10 | width: auto; 11 | min-width: 16px; 12 | max-width: 100%; 13 | } 14 | .TSP-label-enabled .list-card-labels .card-label > span { 15 | display: inline; 16 | } 17 | 18 | /*==== CARD ID ====*/ 19 | .TSP-id-enabled .card-short-id { 20 | display: inline; 21 | margin-right: 5px; 22 | color: #333; 23 | font-weight: bold; 24 | } 25 | 26 | .TSP-id-enabled .card-short-id:hover { 27 | color: grey; 28 | } 29 | 30 | .TSP-id-enabled.onlyShowOnHover .card-short-id { 31 | display: none; 32 | } 33 | .TSP-id-enabled.onlyShowOnHover .active-card .card-short-id { 34 | display: inline; 35 | } 36 | 37 | /*==== CARDS PER LIST ====*/ 38 | /* This is already there by default in Trello, it is just hidden */ 39 | .TSP-numberOfCards-enabled .list-header-num-cards.hide { 40 | display: block; 41 | } 42 | 43 | /*==== COMPACT MODE ====*/ 44 | .compact-mode-button { 45 | padding-left: 8px; 46 | margin-left: 4px; 47 | } 48 | .TSP-compact-enabled.compact-mode div.board-header-btns.mod-left a.board-header-btn.compact-mode-button { 49 | background-color: rgba(0, 0, 0, 0.14); 50 | } 51 | .TSP-compact-enabled.compact-mode .list-card-cover, 52 | .TSP-compact-enabled.compact-mode .list-card-details .badges, 53 | .TSP-compact-enabled.compact-mode .list-card-members, 54 | .TSP-compact-enabled.compact-mode .list-card-stickers-area, 55 | .TSP-compact-enabled.compact-mode .list-card-labels { 56 | display: none; 57 | } 58 | .TSP-compact-enabled.compact-mode .list-card.is-stickered .list-card-details { 59 | margin-top: 0; 60 | } 61 | 62 | /*==== RESIZABLE LISTS ====*/ 63 | .resize-element { 64 | height: 100%; 65 | width: 8px; 66 | cursor: col-resize; 67 | margin: 0px -4px; 68 | border-radius: 99px; 69 | 70 | /* borrowed from Trellos .list-wrapper*/ 71 | box-sizing: border-box; 72 | display: inline-block; 73 | vertical-align: top; 74 | white-space: nowrap; 75 | } 76 | .resize-element:hover { 77 | background-color: rgba(170, 170, 170, 0.25); 78 | } 79 | .resize-element:active { 80 | background-color: rgba(170, 170, 170, 0.5); 81 | } 82 | .list-card { 83 | max-width: none; 84 | min-width: none; 85 | } 86 | 87 | /*==== HIDE ELEMENT ====*/ 88 | .hide-element { 89 | display: none; 90 | } -------------------------------------------------------------------------------- /page-action/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Export Trello board as CSV 6 | 67 | 68 | 69 | 70 |
71 |

Export Trello Board as CSV

72 |
73 | 74 |
75 | 78 |
79 | 80 | .csv 81 |
82 | 83 |
84 | 85 |
Delimiter:
86 | 90 | 94 | 95 |
96 | 97 | 101 |
102 | 103 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /_locales/es/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionName": { 3 | "message": "Trello Super Powers", 4 | "description": "Name of the extension." 5 | }, 6 | "extensionDescription": { 7 | "message": "Añade superpoderes a tu tablero de Trello. Redimensiona listas, visualiza etiquetas de texto, añade un modo compacto y mucho más...", 8 | "description": "Description of the extension." 9 | }, 10 | "settingsHeading": { 11 | "message": "Ajustes", 12 | "description": "Settings heading." 13 | }, 14 | "settingsSavedNotificationTitle": { 15 | "message": "Ajustes salvados", 16 | "description": "Notification title when settings are updated." 17 | }, 18 | "settingsSavedNotificationBody": { 19 | "message": "Recarga tu tablero de Trello para que los cambios tengan efecto", 20 | "description": "Instuctions for the user in order for the changes to take effect." 21 | }, 22 | "settingsCompactTitle": { 23 | "message": "Modo compacto", 24 | "description": "Name of the Compact Mode feature." 25 | }, 26 | "settingsCompactDescription": { 27 | "message": "Añade un botón que rápidamente cambie al modo compacto. En este modo, las etiquetas, tags y demás elementos estarán ocultos, así te enfocarás solo en tus tareas.", 28 | "description": "Description of the Compact Mode feature." 29 | }, 30 | "settingsLabelTitle": { 31 | "message": "Etiquetas de texto visibles", 32 | "description": "Name of the visible label text feature." 33 | }, 34 | "settingsLabelDescription": { 35 | "message": "Muestra los textos de las etiquetas por defecto. Nota: Aunque Trello soporta este comportamiento, no está establecido por defecto y no se muestra tan bien con los estilos que tenemos en Trello Super Powers.", 36 | "description": "Description of the visible label text feature." 37 | }, 38 | "settingsIdTitle": { 39 | "message": "IDs de las tarjetas al colocar el ratón por encima", 40 | "description": "Name of the Card IDs on hover feature." 41 | }, 42 | "settingsIdDescription": { 43 | "message": "¡Haz click en los IDs para copiarlos! Entonces podrás pegarlos en un comentario y Trello mostrará automáticamente la correspondiente tarjeta.", 44 | "description": "Description of the card IDs on hover feature." 45 | }, 46 | "settingsNumberListTitle": { 47 | "message": "Número de tarjetas por lista", 48 | "description": "Name of the Number of cards per list feature." 49 | }, 50 | "settingsNumberListDescription": { 51 | "message": "Muestra un pequeño indicador en cada lista con el número de tarjeta que hay.", 52 | "description": "Description of the cards per list feature." 53 | }, 54 | "injectIdNotificationBody": { 55 | "message": "ID de la tarjeta se copia a tu clipboard.", 56 | "description": "Message body when a user clicks on a card ID." 57 | }, 58 | 59 | "pageAction_exportToCSV_title": { 60 | "message": "Exporta el tablero de Trello como CSV", 61 | "description": "Action of the Page Action (popup)." 62 | }, 63 | "pageAction_exportToCSV_optionFileName_title": { 64 | "message": "Nombre de archivo", 65 | "description": "Name of the option to choose a file name." 66 | }, 67 | "pageAction_exportToCSV_optionDelimiter_title": { 68 | "message": "Delimitador", 69 | "description": "Name of the option to choose a delimiter (seperator)." 70 | }, 71 | "pageAction_exportToCSV_optionDelimiter_comma": { 72 | "message": "(Coma)", 73 | "description": "Hint for the name of the character ','" 74 | }, 75 | "pageAction_exportToCSV_optionDelimiter_semicolon": { 76 | "message": "(Punto y coma)", 77 | "description": "Hint for the name of the character ';'" 78 | }, 79 | "pageAction_exportToCSV_optionIncludeArchived_title": { 80 | "message": "Incluir tarjetas archivadas", 81 | "description": "Name of the option to optionally inlcude also arcived cards." 82 | }, 83 | "pageAction_exportToCSV_genericExport_title": { 84 | "message": "Exportar", 85 | "description": "Action to output something." 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /_locales/fr/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionName": { 3 | "message": "Trello Super Powers", 4 | "description": "Name of the extension." 5 | }, 6 | "extensionDescription": { 7 | "message": "Donnez des super pouvoirs à vos tableaux. Listes ajustables, affichage du titre des étiquettes, mode compact, et bien plus encore...", 8 | "description": "Description of the extension." 9 | }, 10 | "settingsHeading": { 11 | "message": "Préférences", 12 | "description": "Settings heading." 13 | }, 14 | "settingsSavedNotificationTitle": { 15 | "message": "Préférences enregistrées", 16 | "description": "Notification title when settings are updated." 17 | }, 18 | "settingsSavedNotificationBody": { 19 | "message": "Rechargez vos tableaux pour activer les nouveaux pouvoirs", 20 | "description": "Instuctions for the user in order for the changes to take effect." 21 | }, 22 | "settingsCompactTitle": { 23 | "message": "Mode Compact", 24 | "description": "Name of the Compact Mode feature." 25 | }, 26 | "settingsCompactDescription": { 27 | "message": "Ajoute un bouton qui vous permet de passer rapidement en mode compact. En mode compact, les étiquettes, assignations, pièces jointes and autres éléments sont cachés pour mettre en évidence le titre de chaque carte.", 28 | "description": "Description of the Compact Mode feature." 29 | }, 30 | "settingsLabelTitle": { 31 | "message": "Affichage du texte des étiquettes", 32 | "description": "Name of the visible label text feature." 33 | }, 34 | "settingsLabelDescription": { 35 | "message": "Affiche le text des étiquettes par défaut. Note: Bien que Trello propose désormais cette fonction, elle n’est pas activée par défaut et n’est pas aussi élégante qu’avec Trello Super Powers.", 36 | "description": "Description of the visible label text feature." 37 | }, 38 | "settingsIdTitle": { 39 | "message": "Numéro des cartes au survol", 40 | "description": "Name of the Card IDs on hover feature." 41 | }, 42 | "settingsIdDescription": { 43 | "message": "Cliquez sur ces numéros pour les copier dans votre presse-papier! Collez-les dans un commentaire pour afficher automatiquement la carte correspondante.", 44 | "description": "Description of the card IDs on hover feature." 45 | }, 46 | "settingsNumberListTitle": { 47 | "message": "Nombre de carte par liste", 48 | "description": "Name of the Number of cards per list feature." 49 | }, 50 | "settingsNumberListDescription": { 51 | "message": "Affiche un petit indicateur dans chaque liste avec le nombre de cartes qu’elle contient.", 52 | "description": "Description of the cards per list feature." 53 | }, 54 | "injectIdNotificationBody": { 55 | "message": "Carte copiée dans ton presse-papier", 56 | "description": "Message body when a user clicks on a card ID." 57 | }, 58 | 59 | "pageAction_exportToCSV_title": { 60 | "message": "Export Trello Board as CSV", 61 | "description": "Action of the Page Action (popup)." 62 | }, 63 | "pageAction_exportToCSV_optionFileName_title": { 64 | "message": "File Name", 65 | "description": "Name of the option to choose a file name." 66 | }, 67 | "pageAction_exportToCSV_optionDelimiter_title": { 68 | "message": "Delimiter", 69 | "description": "Name of the option to choose a delimiter (seperator)." 70 | }, 71 | "pageAction_exportToCSV_optionDelimiter_comma": { 72 | "message": "(Comma)", 73 | "description": "Hint for the name of the character ','" 74 | }, 75 | "pageAction_exportToCSV_optionDelimiter_semicolon": { 76 | "message": "(Semicolon)", 77 | "description": "Hint for the name of the character ';'" 78 | }, 79 | "pageAction_exportToCSV_optionIncludeArchived_title": { 80 | "message": "Include Archived Cards", 81 | "description": "Name of the option to optionally inlcude also arcived cards." 82 | }, 83 | "pageAction_exportToCSV_genericExport_title": { 84 | "message": "Export", 85 | "description": "Action to output something." 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Hello 2 | 3 | Thanks for considering supporting the development of Trello Super Powers! 4 | 5 | There are **2** ways to contribute to Trello Super Powers: 6 | 7 | - [Translations](#translations) 8 | - [Code](#coding) 9 | 10 | If at any time you need help you can always open an Issue on the GitHub page and someone will help you to get started. 11 | 12 | Also, if you have found an error or bug, please create an issue on GitHub. This is the fastest way to get it fixed and helps greatly to improve Trello Super Powers for everyone. Lot's of misbehavior are caused by simple mistakes and can be fixed easily, but only once they are known to exist. 13 | 14 | \> [GitHub main page](https://github.com/christiankaindl/trello-super-powers/) 15 | \> [GitHub issues page](https://github.com/christiankaindl/trello-super-powers/issues) 16 | 17 | # Translations 18 | 19 | If you want to help translate Trello Super Powers into your language, that's awesome. The simplest way to get translations in is to create a [GitHub issue](https://github.com/christiankaindl/trello-super-powers/issues) and suggest your translations. 20 | 21 | Alternatively, you can also download the Trello Super Powers repository and add your translations to the source files, and then make a pull request. For this approach, here a some notes to guide you: 22 | 23 | First, all translations are in the folder called _`_locales`_. For each language there is a separate directory that contains the a file called _`messages.json`_. This file contains all translations for a given language. 24 | 25 | If the language you want to contribute to already exists, but some translations are missing or you think something could be translated better, open the _`messages.json`_ for you language and look for the string(s) that you want to modify/add and replace the existing string in its `message` field. 26 | 27 | If you want to contribute in a language that is currently not present at all, this is possible too. First, create a folder with the appropriate language abbreviation in the same folder as the other language folders are in. If you are not sure what the abbreviation for your language is, they can be [found here](http://www.abbreviations.com/acronyms/LANGUAGES2L). Then create a file called `messages.json` in the newly created folder. In it copy and paste all existing translated strings from the `messages.json` (preferably) from the English (called `en`) language folder's `message.json` file. *You can also copy from a different language if you are more familiar it*. 28 | 29 | From there you can start replacing the existing strings in the `"message: "` fields. 30 | 31 | --- 32 | 33 | # Coding 34 | 35 | If you want to contribute a feature or other things such as code organization, here is what to look out for: 36 | 37 | ## Structure 38 | 39 | The most complex parts of the Add-on is the Background Script (`background.js`) and the Content Script (`inject/inject.js`). 40 | 41 | **background.js** 42 | This file has **3** functions. 43 | - `urlCheck()` 44 | - `checkSettings()` 45 | - `handleMessage()` 46 | 47 | `urlCheck()` is called every time the url/page state changes. This is done so TSP knows when to insert the `inject.js` script. 48 | 49 | `checkSettings()` is called when the Add-on starts and when the Add-on is installed. It checks the integrity of the settings and defaults them if necessary. 50 | 51 | `handleMessage()` gets either called from the Content Script (`inject/inject.js`) or from the Page Action script (`page-action/main.js`). The Content Script uses the uses it to display notifications to the user (otherwise not possible in a Content Script). The Page Action uses it for its CSV export. 52 | 53 | ## Translating UI elements 54 | 55 | If you've wondered how we apply the translations that are located in the `_locales` directory to the actual pages, here's how you can do it as well: 56 | 57 | Each HTML element that is translatable (and thus should be translated) has a `data-translate` attribute on it. The value of this attribute is the name of the `messages.json` key for that string. E.g. `` Trello Super Powers pulls the string from from that key's `"message"` property. So if you had a JSON file like this for your language 58 | ```json 59 | { 60 | "notificationTitle": { 61 | "message": "Awesome Notification", 62 | "description": "Title for an awesome notification." 63 | } 64 | } 65 | ``` 66 | TSP would pull the string `Awesome Notification` from it. 67 | -------------------------------------------------------------------------------- /_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionName": { 3 | "message": "Trello Super Powers", 4 | "description": "Name of the extension." 5 | }, 6 | "extensionDescription": { 7 | "message": "Add Superpowers to your Trello board. Resizable lists, visible label text, compact mode and much more...", 8 | "description": "Description of the extension." 9 | }, 10 | "settingsHeading": { 11 | "message": "Settings", 12 | "description": "Settings heading." 13 | }, 14 | "settingsSavedNotificationTitle": { 15 | "message": "Settings saved", 16 | "description": "Notification title when settings are updated." 17 | }, 18 | "settingsSavedNotificationBody": { 19 | "message": "Reload your Trello boards for changes to take effect.", 20 | "description": "Instuctions for the user in order for the changes to take effect." 21 | }, 22 | "settingsCompactTitle": { 23 | "message": "Compact Mode", 24 | "description": "Name of the Compact Mode feature." 25 | }, 26 | "settingsCompactDescription": { 27 | "message": "Adds a button that lets you quickly toggle Compact Mode. When in Compact Mode, tags, assignations, attachments and more are hidden, so you can focus on your tasks.", 28 | "description": "Description of the Compact Mode feature." 29 | }, 30 | "settingsHideAddNewListTitle": { 31 | "message": "Hide 'Add another list'", 32 | "description": "Name of the 'Hide Add New List' feature." 33 | }, 34 | "settingsHideAddNewListDescription": { 35 | "message": "This hides the additional column with the 'Add another list' button and saves horizontal space. You can still create new lists by double clicking on an empty area on the board.", 36 | "description": "Description of the 'Hide Add New List' feature." 37 | }, 38 | "settingsLabelTitle": { 39 | "message": "Visible label text", 40 | "description": "Name of the visible label text feature." 41 | }, 42 | "settingsLabelDescription": { 43 | "message": "Shows the text of labels by default. Note: Although Trello now supports this feature, it is not enabled by default and does not look as good as the styles provided by Trello Super Powers.", 44 | "description": "Description of the visible label text feature." 45 | }, 46 | "settingsIdTitle": { 47 | "message": "Show card IDs", 48 | "description": "Name of the Show Card IDs feature." 49 | }, 50 | "settingsIdTitleHover": { 51 | "message": "Show only on hover", 52 | "description": "Name of the Card IDs on hover feature." 53 | }, 54 | "settingsIdDescription": { 55 | "message": "Click on IDs to save them to your clipboard! Paste them in a comment and Trello will automatically show the corresponding card.", 56 | "description": "Description of the card IDs on hover feature." 57 | }, 58 | "settingsNumberListTitle": { 59 | "message": "Number of cards per list", 60 | "description": "Name of the Number of cards per list feature." 61 | }, 62 | "settingsNumberListDescription": { 63 | "message": "Shows a small indicator in each list with the number of cards in it.", 64 | "description": "Description of the cards per list feature." 65 | }, 66 | "injectIdNotificationBody": { 67 | "message": "Card ID saved to your clipboard.", 68 | "description": "Message body when a user clicks on a card ID." 69 | }, 70 | 71 | "pageAction_exportToCSV_title": { 72 | "message": "Export Trello Board as CSV", 73 | "description": "Action of the Page Action (popup)." 74 | }, 75 | "pageAction_exportToCSV_optionFileName_title": { 76 | "message": "File Name", 77 | "description": "Name of the option to choose a file name." 78 | }, 79 | "pageAction_exportToCSV_optionDelimiter_title": { 80 | "message": "Delimiter", 81 | "description": "Name of the option to choose a delimiter (seperator)." 82 | }, 83 | "pageAction_exportToCSV_optionDelimiter_comma": { 84 | "message": "(Comma)", 85 | "description": "Hint for the name of the character ','" 86 | }, 87 | "pageAction_exportToCSV_optionDelimiter_semicolon": { 88 | "message": "(Semicolon)", 89 | "description": "Hint for the name of the character ';'" 90 | }, 91 | "pageAction_exportToCSV_optionIncludeArchived_title": { 92 | "message": "Include Archived Cards", 93 | "description": "Name of the option to optionally inlcude also arcived cards." 94 | }, 95 | "pageAction_exportToCSV_genericExport_title": { 96 | "message": "Export", 97 | "description": "Action to output something." 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /_locales/de/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extensionName": { 3 | "message": "Trello Super Powers", 4 | "description": "Name of the extension." 5 | }, 6 | "extensionDescription": { 7 | "message": "Gib deinen Trello-Boards Superkräfte. Kompakt-Modus, sichtbare Labels, größenverstellbare Listen und noch viel mehr...", 8 | "description": "Description of the extension." 9 | }, 10 | "settingsHeading": { 11 | "message": "Einstellungen", 12 | "description": "Settings heading." 13 | }, 14 | "settingsSavedNotificationTitle": { 15 | "message": "Einstellungen gespeichert", 16 | "description": "Notification title when settings are updated." 17 | }, 18 | "settingsSavedNotificationBody": { 19 | "message": "Trello-Boards neu laden, damit die Veränderungen wirksam werden.", 20 | "description": "Instuctions for the user in order for the changes to take effect." 21 | }, 22 | "settingsCompactTitle": { 23 | "message": "Kompakt-Modus", 24 | "description": "Name of the Compact Mode feature." 25 | }, 26 | "settingsCompactDescription": { 27 | "message": "Fügt einen Button hinzu, der dich bequem den Kompakt-Modus aktivieren/deaktivieren lässt. Wenn aktiv, werden Tags, zugewiesene Menschen, Anhänge und mehr ausgeblendet. so kannst Du dich auf das konzentrieren, was wirklich wichtig ist.", 28 | "description": "Description of the Compact Mode feature." 29 | }, 30 | "settingsHideAddNewListTitle": { 31 | "message": "Verstecke \"Eine weitere Liste hinzufügen\"", 32 | "description": "Name of the 'Hide Add New List' feature." 33 | }, 34 | "settingsHideAddNewListDescription": { 35 | "message": "Versteckt die Spalte mit dem \"Eine weitere Liste hinzufügen\"-Button und spart dadurch Platz. Du kannst weiterhin neue Listen hinzufügen, indem du einen Doppelklick auf eine freie Fläche machst.", 36 | "description": "Description of the 'Hide Add New List' feature." 37 | }, 38 | "settingsLabelTitle": { 39 | "message": "Sichtbarer Label-Text", 40 | "description": "Name of the visible label text feature." 41 | }, 42 | "settingsLabelDescription": { 43 | "message": "Macht den Text von Labels sichtbar. Anmerkung: Trello hat diese Funktion mittlerweile eingebaut, jedoch ist sie standardmäßig nicht aktiviert und schaut nicht so gut aus wie das Styling von Trello Super Powers.", 44 | "description": "Description of the visible label text feature." 45 | }, 46 | "settingsIdTitle": { 47 | "message": "Karten-IDs", 48 | "description": "Name of the Card IDs on hover feature." 49 | }, 50 | "settingsIdDescription": { 51 | "message": "Fahre mit der Maus über Karten, um ihre ID zu sehen. Mit einem Klick werden sie automatisch in deine Zwischenablage kopiert! Die ID kannst Du z.B. in Kommentaren verwenden um schnelle Verweise zu machen (Trello ersetzt die IDs mit Links zu den tatsächlichen Karten).", 52 | "description": "Description of the card IDs on hover feature." 53 | }, 54 | "settingsNumberListTitle": { 55 | "message": "Anzahl der Karten in Listen", 56 | "description": "Name of the Number of cards per list feature." 57 | }, 58 | "settingsNumberListDescription": { 59 | "message": "Fügt einen kleinen Indikator hinzu, der die Anzahl der enthaltenen Karten in jeder Liste anzeigt.", 60 | "description": "Description of the cards per list feature." 61 | }, 62 | "injectIdNotificationBody": { 63 | "message": "Karten-ID in die Zwischenablage gespeichert.", 64 | "description": "Message body when a user clicks on a card ID." 65 | }, 66 | 67 | "pageAction_exportToCSV_title": { 68 | "message": "Trello Board als CSV Exportieren", 69 | "description": "Action of the Page Action (popup)." 70 | }, 71 | "pageAction_exportToCSV_optionFileName_title": { 72 | "message": "Dateiname", 73 | "description": "Name of the option to choose a file name." 74 | }, 75 | "pageAction_exportToCSV_optionDelimiter_title": { 76 | "message": "Seperator", 77 | "description": "Name of the option to choose a delimiter (seperator)." 78 | }, 79 | "pageAction_exportToCSV_optionDelimiter_comma": { 80 | "message": "(Komma)", 81 | "description": "Hint for the name of the character ','" 82 | }, 83 | "pageAction_exportToCSV_optionDelimiter_semicolon": { 84 | "message": "(Semikolon)", 85 | "description": "Hint for the name of the character ';'" 86 | }, 87 | "pageAction_exportToCSV_optionIncludeArchived_title": { 88 | "message": "Archivierte Karten Inkludieren", 89 | "description": "Name of the option to optionally inlcude also arcived cards." 90 | }, 91 | "pageAction_exportToCSV_genericExport_title": { 92 | "message": "Exportieren", 93 | "description": "Action to output something." 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /settings/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Trello Super Powers - Preferences 6 | 7 | 43 | 44 |
45 |
46 |
47 | 48 | 49 |
50 | 51 | 52 |
53 |

Click on IDs to save them to your clipboard! Paste them in a comment and Trello will automatically show the corresponding card.

54 |
55 | 56 |
57 |
58 |
59 | 60 | 61 |

Shows the text of labels by default. Note: Although Trello now supports this feature, it is not enabled by default and does not look as good as the styles provided by Trello Super Powers.

62 |
63 | Visible label text feature 64 |
65 |
66 |
67 | 68 | 69 |
70 | 71 | 72 |
73 |

Adds a button that lets you quickly toggle Compact Mode. When in Compact Mode, tags, assignations, attachments and more are hidden, so you can focus on your tasks.

74 |
75 | Compact Mode feature 76 |
77 |
78 |
79 | 80 | 81 |

Shows a small indicator in each list with the number of cards in it.

82 |
83 | Number of cards feature 84 |
85 |
86 |
87 | 88 | 89 |

This hides the additional column with the 'Add another list' button and saves horizontal space. You can still create new lists by double clicking on an empty area on the board.

90 |
91 | 'Hide add another list' feature 92 |
93 |
94 | 95 |

Found an error? Help getting it fixed by reporting an issue.

96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | console.clear() 3 | 4 | const trelloBoardURL = /\S+:\/\/\S*\.?trello\.com\/b\/\S+/ 5 | var injectStatus = undefined 6 | 7 | /** 8 | * Checks whether or not a given url is a Trello board url. 9 | * 10 | * @param {number} id id of the tab the url is From 11 | * @param {string} updateReason Reason why the function was called 12 | * @param {object} state Properties of the tab 13 | */ 14 | async function urlCheck (id, updateReason, state) { 15 | if (!state.url.match(trelloBoardURL)) return 16 | if (injectStatus === 'pending') return 17 | 18 | injectStatus = 'pending' 19 | 20 | try { 21 | await browser.tabs.insertCSS({ file: 'inject/enhancedStyles.css' }) 22 | await browser.tabs.executeScript({ file: 'inject/inject.js' }) 23 | 24 | browser.pageAction.show(id) 25 | 26 | injectStatus = 'fullfilled' 27 | console.info(`[Trello Super Powers] Successfully injected 'inject.js' into ${state.url}`) 28 | } catch (e) { 29 | injectStatus = 'rejected' 30 | console.error( 31 | `[Trello Super Powers] Error: Could not inject 'inject.js' into ${state.url}: `, 32 | e 33 | ) 34 | } 35 | } 36 | 37 | /** 38 | * Checks current settings and defaults them as necessary 39 | */ 40 | async function checkSettings () { 41 | var settings = await browser.storage.local.get() 42 | 43 | if (settings['compactMode'] === undefined) { 44 | browser.storage.local.set({ compactMode: true }) 45 | } 46 | if (settings['compactModeByDefault'] === undefined) { 47 | browser.storage.local.set({ compactModeByDefault: false }) 48 | } 49 | if (settings['numberOfCards'] === undefined) { 50 | browser.storage.local.set({ numberOfCards: true }) 51 | } 52 | if (settings['labelText'] === undefined) { 53 | browser.storage.local.set({ labelText: true }) 54 | } 55 | if (settings['copyId'] === undefined) { 56 | browser.storage.local.set({ copyId: true }) 57 | } 58 | if (settings['copyId_onlyShowOnHover'] === undefined) { 59 | browser.storage.local.set({ copyId_onlyShowOnHover: true }) 60 | } 61 | if (settings['list'] === undefined) { 62 | browser.storage.local.set({ list: { width: 270 } }) 63 | } 64 | if (settings['hideAddNewList'] === undefined) { 65 | browser.storage.local.set({ hideAddNewList: false }) 66 | } 67 | } 68 | 69 | browser.runtime.onMessage.addListener(handleMessage) 70 | 71 | /** 72 | * Message handler for incomming messages 73 | * 74 | * @param {object} message Message from a Script, containing a 'type' property. 75 | */ 76 | async function handleMessage (message) { 77 | if (message.type === 'notification') { 78 | browser.notifications.create({ 79 | type: 'basic', 80 | title: 'Trello Super Powers', 81 | message: message.message, 82 | iconUrl: '/assets/logo.svg' 83 | }) 84 | } 85 | 86 | if (message.type === 'exportCSV') { 87 | if (!navigator.onLine) { 88 | browser.notifications.create({ 89 | type: 'basic', 90 | title: 'You are offline', 91 | message: 92 | 'Trello Super Powers could not connect to the internet. Please check your connection and try again.' 93 | }) 94 | 95 | return 96 | } 97 | 98 | let tabId, tabUrl, csvBlob, downloadUrl 99 | let { 100 | filename = 'CSV-export.csv', 101 | delimiter = ',', 102 | includeArchived = false 103 | } = message.data; 104 | 105 | [{ id: tabId, url: tabUrl }] = await browser.tabs.query({ 106 | active: true, 107 | currentWindow: true 108 | }) 109 | 110 | await browser.tabs.executeScript(tabId, { file: 'papaparse.min.js' }) 111 | 112 | // TODO: Don't use a content script for this operation. Do everything in the 113 | // background script 114 | csvBlob = await browser.tabs.sendMessage(tabId, { 115 | type: 'fetch', 116 | tabUrl, 117 | delimiter, 118 | includeArchived 119 | }) 120 | 121 | // Create a file URL so we can download it 122 | downloadUrl = URL.createObjectURL(csvBlob) 123 | 124 | try { // Try downloading the CSV file 125 | browser.downloads.download({ 126 | url: downloadUrl, 127 | filename: filename 128 | }) 129 | } catch (e) { 130 | console.error('[Trello Super Powers] Error: ', e) 131 | 132 | browser.notifications.create({ 133 | type: 'basic', 134 | title: 'Export failed', 135 | message: `Trello Super Powers could export your board. We're sorry. Error message: ${e}` 136 | }) 137 | } 138 | 139 | browser.notifications.create({ 140 | type: 'basic', 141 | title: 'Board exported', 142 | message: 'Successfully downloaded your board as CSV.' 143 | }) 144 | } 145 | } 146 | 147 | /* Trello uses AJAX loading and because of this when a board is loaded from 148 | within the UI (not from URL) 'inject.js' won't be fired. To overcome this we 149 | listen for URL changes initTrelloBoardand fire inizializations manually */ 150 | browser.tabs.onUpdated.addListener(urlCheck) 151 | 152 | browser.runtime.onStartup.addListener(checkSettings) 153 | browser.runtime.onInstalled.addListener(checkSettings) 154 | 155 | console.info('Trello Super Powers WebExtension started successfully.') 156 | -------------------------------------------------------------------------------- /assets/logos/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 21 | 23 | 24 | 26 | image/svg+xml 27 | 29 | 30 | 31 | 32 | 33 | 35 | 38 | 42 | 46 | 50 | 51 | 62 | 70 | 74 | 75 | 83 | 87 | 88 | 89 | 115 | 121 | 127 | 133 | 139 | 144 | 149 | 155 | 161 | 167 | 173 | 174 | -------------------------------------------------------------------------------- /inject/inject.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /* 4 | Inizialize Trello Super Powers features 5 | - copy card id on click 6 | - compact mode 7 | - resizable lists 8 | - label text 9 | - number of cards per list 10 | */ 11 | 12 | function gracefullyInject (feature, args) { 13 | /** Takes a funtion and injects it 14 | * TODO: add error handling logic 15 | */ 16 | feature(args) 17 | } 18 | 19 | /** 20 | * Wrapper for `browser.storage.local.get()`. 21 | * 22 | * @returns {object} An object with current settings. 23 | */ 24 | async function getSettings () { 25 | return browser.storage.local.get() 26 | } 27 | 28 | // NOTE: Ideally in the future, each feature has its own module 29 | var features = { 30 | /** 31 | * Initializes ID feature. 32 | * 33 | * @returns {promise} 34 | */ 35 | id (onlyShowOnHover) { 36 | return new Promise(function (resolve, reject) { 37 | const input = document.createElement('input') 38 | 39 | // Add dummy element so we can use the clipboard functionality 40 | input.setAttribute('style', 'height: 0px;padding: 0px; margin: 0px; border: none;') 41 | document.getElementsByTagName('body')[0].appendChild(input) 42 | 43 | document.addEventListener('click', copyCardURL, true) 44 | function copyCardURL (e) { 45 | // Don't move on if the element clicked is not an ID 46 | if (!e.target.classList.contains('card-short-id')) return 47 | 48 | let elem 49 | 50 | e.stopImmediatePropagation() 51 | e.preventDefault() 52 | 53 | elem = e.target 54 | // Traverse up the DOM to find the anchor element with the URL we want to copy. 55 | while (true) { 56 | elem = elem.parentNode 57 | 58 | if (elem.tagName !== 'A') continue 59 | 60 | input.value = elem.href 61 | input.select() 62 | document.execCommand('copy') 63 | break 64 | } 65 | 66 | // NOTE: Content Scripts do not have access to the notifications API. If a notification should be sent, we have to communicate with the background script using the messaging API 67 | browser.runtime.sendMessage({ 68 | type: 'notification', 69 | message: browser.i18n.getMessage('injectIdNotificationBody') 70 | }) 71 | } 72 | 73 | console.info('[Trello Super Powers] Injected feature: "Show card IDs"') 74 | board.classList.add('TSP-id-enabled') 75 | if (onlyShowOnHover) { 76 | board.classList.add('onlyShowOnHover') 77 | } 78 | resolve() 79 | }) 80 | }, 81 | /** 82 | * Initializes Compact Mode feature 83 | * 84 | * @returns {promise} 85 | */ 86 | compact (byDefault) { 87 | return new Promise(async function (resolve, reject) { 88 | function createCompactModeButton () { 89 | const parent = document.createElement('a') 90 | parent.setAttribute('class', 'board-header-btn compact-mode-button') 91 | // TODO: Internationalize this string! 92 | parent.setAttribute('title', 'Toggle Compact Mode') 93 | 94 | const child = document.createElement('span') 95 | child.setAttribute('class', 'board-header-btn-text') // The `board-header-btn-text` class is provided by Trello itself 96 | child.textContent = browser.i18n.getMessage('settingsCompactTitle') 97 | 98 | parent.appendChild(child) 99 | 100 | return parent 101 | } 102 | 103 | function toggleCompactMode () { 104 | // Apply Compact Mode CSS 105 | board.classList.toggle('compact-mode') 106 | } 107 | 108 | const compactModeButton = createCompactModeButton() 109 | 110 | compactModeButton.addEventListener('click', toggleCompactMode) 111 | 112 | // Inject into page 113 | document 114 | .getElementById('permission-level') 115 | .parentElement.appendChild(compactModeButton) 116 | 117 | console.info('[Trello Super Powers] Injected feature "Compact Modew"') 118 | board.classList.add('TSP-compact-enabled') 119 | 120 | byDefault && compactModeButton.click() 121 | resolve() 122 | }) 123 | }, 124 | /** 125 | * Initializes "Hide 'Add new List'-Button" feature 126 | * 127 | * @returns {promise} 128 | */ 129 | hideAddNewList () { 130 | return new Promise(function (resolve, reject) { 131 | const addNewListElement = document.getElementsByClassName('js-add-list')[0] 132 | addNewListElement.classList.toggle('hide-element') 133 | 134 | console.info('[Trello Super Powers] Injected feature: "Hide \'Add new List\'"') 135 | 136 | resolve() 137 | }) 138 | }, 139 | /** 140 | * Initializes Resizable Lists feature 141 | * 142 | * @returns {promise} 143 | */ 144 | resize () { 145 | return new Promise(async function (resolve, reject) { 146 | function createResizeElem () { 147 | function attachListeners () { 148 | document.addEventListener('mousemove', adjustSize) 149 | document.addEventListener('mouseup', setSize) 150 | } 151 | 152 | function adjustSize (e) { 153 | const styleId = document.getElementById('inserted-tsp-styles') 154 | const currentWidth = 155 | listWidth + e.movementX / 3 < 500 && 156 | listWidth + e.movementX / 3 > 150 157 | ? (listWidth = listWidth + e.movementX / 3) 158 | : listWidth 159 | 160 | styleId.textContent = `.list-wrapper {width: ${currentWidth}px}` 161 | } 162 | 163 | function setSize (e) { 164 | document.removeEventListener('mousemove', adjustSize) 165 | document.removeEventListener('mouseup', setSize) 166 | 167 | browser.storage.local.set({ list: { width: listWidth } }).catch(e => { 168 | console.error( 169 | "[Trello Super Powers] Could not save 'listWidth' to browser sync storage.", 170 | e 171 | ) 172 | }) 173 | } 174 | 175 | const resizeElem = document.createElement('div') 176 | 177 | resizeElem.setAttribute('class', 'resize-element') 178 | // Listen for mouse down 179 | resizeElem.addEventListener('mousedown', attachListeners) 180 | 181 | return resizeElem 182 | } 183 | 184 | var listWidth 185 | var lists = [] 186 | 187 | try { 188 | listWidth = (await browser.storage.local.get()).list.width 189 | } catch (e) { 190 | console.error('[Trello Super Powers] Error: Could not get local storage', e) 191 | listWidth = 270 192 | } 193 | 194 | // Insert a