Einführung in Asana-Bookmarklets

Erstellt von: @ShunS

Die Originalversion des Beitrags auf Englisch ist unter folgendem Link verfügbar: Introduction to Asana bookmarklets

Alle Aufgaben eines Projekts als erledigt/unerledigt markieren, alle Abschnitte eines Projekts ein-/ausblenden, alle Kommentare einer Aufgabe anzeigen – all diese Massenaktionen können mit nur einem Klick durchgeführt werden.

Screen Recording 2022-07-25 at 16.21.00 (1)

0. Was sind Bookmarklets?

Bookmarklets sind in JavaScript programmierte Snippets, die als Browser-Lesezeichen hinzugefügt und durch Anklicken ausgeführt werden. Man kann JavaScript-Snippets mit Lesezeichen versehen, indem man sie mit javascript:(function() { und })(); einschließt.

Das Frontend einer Website, darunter Asana, setzt sich hauptsächlich aus drei Sprachen zusammen: HTML (eine Markup-Sprache zur Markierung von Bestandteilen einer Seite), CSS (eine Programmiersprache zur Festlegung des Layouts und des Designs) und JavaScript (eine Programmiersprache).

Tag-Paare in HTML bilden strukturierte Einheiten (Knoten), die von JavaScript bedient werden können. Diese Interaktion nennt man DOM (Document Object Model).

1. Bookmarklets hinzufügen

Besuchen Sie Asana bookmarklets, und ziehen Sie die blauen Links in die Lesezeichenleiste des Browsers, um sie hinzuzufügen.

Ich empfehle, einen Ordner zu erstellen, damit die Bookmarklets nicht zu viel Platz in der Lesezeichenleiste einnehmen. Werden sie direkt in die Lesezeichenleiste eingefügt, empfiehlt es sich, den Namen zu bearbeiten und nur das Emoji beizubehalten.

Beim manuellen Hinzufügen der Bookmarklets gehen Sie wie folgt vor:

  1. Fügen Sie eine beliebige Webseite als Lesezeichen hinzu.

  2. Klicken Sie beim Hinzufügen auf „Mehr…“, wählen Sie den Ordner aus, und bearbeiten Sie anschließend den Namen und die URL.

  3. Geben Sie unter „Name“ die Titel der Bookmarklets und unter „URL“ den mit „javascript:“ beginnenden Code ein.

Wenn Sie in der Liste der Bookmarklets einen Abschnitt erstellen möchten, empfehle ich die Verwendung von Chrome Bookmarks Separator.

Durch Anklicken der gespeicherten Bookmarklets auf einem Asana-Tab können Sie die automatischen Aktionen ausführen.

2. Derzeitige Bookmarklets

Der Quellcode und die Beschreibung der Bookmarklets sind hier aufgeführt: Asana-Bookmarklets

2-1. Vorgänge für eine Aufgabe

2-1-1. :speech_balloon: Story-Bereinigung

Aktivieren Sie unten die Optionen „Kommentare ausklappen” und „Verknüpfte Arbeitslinks ausblenden”.

javascript:(function() {
	const expandLink = document.querySelector('.TaskStoryFeed-expandLink');
	if (expandLink && expandLink.textContent.match(/\d/)) expandLink.click();
	document.querySelectorAll('.TruncatedRichText-expand').forEach(link => link.click());
	document.querySelectorAll('.TaskStoryFeed-expandMiniStoriesLink').forEach(link => link.click());
	document.querySelectorAll('.BacklinkMiniStory').forEach(line => {line.parentNode.style.display = 'none';});
})();

2-1-2. :arrow_up_down: Kommentare ausklappen

In den Aufgaben-Storys auf „7 weitere Kommentare” klicken und „Mehr anzeigen”.

javascript:(function() {
	const expandLink = document.querySelector('.TaskStoryFeed-expandLink');
	if (expandLink && expandLink.textContent.match(/\d/)) expandLink.click();
	document.querySelectorAll('.TruncatedRichText-expand').forEach(link => link.click());
	document.querySelectorAll('.TaskStoryFeed-expandMiniStoriesLink').forEach(link => link.click());
})();

2-1-3. ↔ Verknüpfte Arbeitslinks ausblenden

Ausblenden aller “<user_name> hat diese Aufgabe in einer anderen Aufgabe erwähnt: <task_link>” in Aufgaben-Storys. Diese Option ist dann sinnvoll, wenn eine Aufgabe in zu vielen Aufgaben erwähnt wird, so dass andere Kommentare und Anhänge schwer zu finden sind.

javascript:(function() {
	document.querySelectorAll('.BacklinkMiniStory').forEach(line => {line.parentNode.style.display = 'none';});
})();

2-1-4. ⫚ Erledigte Aufgaben ausblenden

Alle erledigten Unteraufgaben im Aufgabenfenster rechts ausblenden. Durch erneutes Anklicken des Bookmarklets werden sie wieder angezeigt.

Bei vielen Unteraufgaben empfehle ich auch die Chrome-Erweiterung Asana Load More.

javascript:(function() {
	const completedSubtaskRows = document.querySelectorAll('.SubtaskTaskRow--completed');
	completedSubtaskRows.forEach(row => {
		row.parentNode.parentNode.style.display = row.parentNode.parentNode.style.display? '': 'none';
	});
})();

2-2. Vorgänge in einer Liste von Aufgaben (z. B. in einem Projekt)

:exclamation:**Hinweis: Wenn bei einer großen Anzahl von Aufgaben einige nicht im Fenster erscheinen, scrollen Sie einfach den Asana-Tab nach unten, um alle Aufgaben zu laden, bevor Sie diese Bookmarklets aufrufen. **

2-2-1. :arrow_forward:︎ Zwischen Abschnitten hin- und herwechseln

Umschalten zwischen Ein- und Ausblenden von Abschnitten in der Listenansicht.

javascript:(function() {
	const firstButtonIcon = document.querySelector('.TaskGroupHeader-toggleButton .Icon');
	if (!firstButtonIcon) return;
	const firstTriangleClassName = firstButtonIcon.classList.contains('DownTriangleIcon')? 'DownTriangleIcon': 'RightTriangleIcon';
	document.querySelectorAll(`.TaskGroupHeader-toggleButton .${firstTriangleClassName}`).forEach(buttonIcon => buttonIcon.parentNode.click());
})();

2-2-2. ▷ Unteraufgaben ein- und ausblenden

Aktivieren Sie das Ein- und Ausblenden von Unteraufgaben in der Listenansicht, indem Sie auf die kleinen :arrow_forward:-Symbole klicken, die auf vorhandene Unteraufgaben hinweisen. Bei vielen Unteraufgaben muss das Bookmarklet auf jeden Link „Weitere Unteraufgaben laden” klicken, was einige Zeit in Anspruch nimmt.

javascript:(function() {
	const firstSubtaskButton = document.querySelector('.ProjectSpreadsheetGridRow-subtaskToggleButton');
	const firstTriangleClassName = firstSubtaskButton.firstElementChild.classList.contains('DownTriangleIcon')? 'DownTriangleIcon': 'RightTriangleIcon';
 
	const taskPlaceholderHTMLCollection = document.getElementsByClassName('SpreadsheetTaskRowScrollPlaceholder');
	const taskGroup = document.querySelector('.TaskGroup');
	const buttonAtTheBottom = document.querySelector('.SpreadsheetPotGridContents-addSectionButton');
	setTimeout(function () {if (buttonAtTheBottom) buttonAtTheBottom.scrollIntoView();}, 30);
	setTimeout(function () {taskGroup.style.display = 'none';}, 60);
 
	let monitorTaskStructure = setInterval(() => {
		if (taskPlaceholderHTMLCollection.length == 0) {
			document.querySelectorAll('.ProjectSpreadsheetGridRow-subtaskToggleButton').forEach(function (buttonIcon) {
				if (buttonIcon.firstElementChild.classList.contains(firstTriangleClassName)) buttonIcon.click();
			});
			taskGroup.style.display = '';
			clearInterval(monitorTaskStructure);
			const loadMoreLinkHTMLCollection = document.getElementsByClassName('SpreadsheetTaskList-showMoreLink');
			setTimeout(() => {
				let clickingLoadMoreLinks = setInterval(function() {
					if (!loadMoreLinkHTMLCollection.length) {
						clearInterval(clickingLoadMoreLinks);
					} else {
						loadMoreLinkHTMLCollection[0].scrollIntoView();
						loadMoreLinkHTMLCollection[0].click();
					}
				}, 100);
			}, 200);
		}
	}, 100);
})();

2-2-3. :white_check_mark: Alle Aufgaben erledigen

Alle sichtbaren, nicht erledigten Aufgaben in der Listenansicht als erledigt kennzeichnen. Bei einer Vielzahl von Aufgaben blendet das Bookmarklet vorübergehend alle Aufgaben aus und klickt jeweils 50 Aufgaben auf einmal an.

javascript:(function() {
	const taskPlaceholderHTMLCollection = document.getElementsByClassName('SpreadsheetTaskRowScrollPlaceholder');
	if (!taskPlaceholderHTMLCollection.length) {
		document.querySelectorAll('.TaskRowCompletionStatus-taskCompletionIcon--incomplete').forEach(incompleteIcon => incompleteIcon.parentNode.click());
	} else {
		const taskGroup = document.querySelector('.TaskGroup');
		const buttonAtTheBottom = document.querySelector('.SpreadsheetPotGridContents-addSectionButton');
		setTimeout(function () {if (buttonAtTheBottom) buttonAtTheBottom.scrollIntoView();}, 30);
		setTimeout(function () {
			taskGroup.style.display = 'none';
			const progressIndicator = document.createElement('span');
			progressIndicator.setAttribute('id', 'progressIndicator');
			progressIndicator.textContent = 'Wird ausgeführt';
			taskGroup.parentNode.appendChild(progressIndicator);
		}, 60);
 
		let monitorTaskStructure = setInterval(() => {
			if (taskPlaceholderHTMLCollection.length == 0) {
				clearInterval(monitorTaskStructure);
				const progressIndicator = document.querySelector('#progressIndicator');
				const allTasks = Array.from(document.querySelectorAll('.TaskRowCompletionStatus-taskCompletionIcon--incomplete'));
				const numProcesses = Math.floor(allTasks.length / 50) + 1;
				let counter = 0;
				let loopTasks = setInterval(() => {				
					progressIndicator.textContent = `Wird ausgeführt (${counter}/${numProcesses})`;
 
					for (let i = 50 * counter; i < Math.min(allTasks.length, 50 * (counter + 1)); i++) {
						allTasks[i].parentNode.click();
						if (i == allTasks.length - 1) {
							clearInterval(loopTasks);
							progressIndicator.remove();
							taskGroup.style.display = '';
						}
					}
					counter += 1;
				}, 500);
			}
		}, 100);
	}
})();

2-2-4. :ballot_box_with_check: Alle Aufgaben als nicht erledigt kennzeichnen

Alle sichtbaren, erledigten Aufgaben in der Listenansicht wieder als nicht erledigt markieren. Bei einer großen Anzahl von Aufgaben blendet das Bookmarklet vorübergehend alle Aufgaben aus und klickt jeweils 50 Aufgaben auf einmal an.

javascript:(function() {
	const taskPlaceholderHTMLCollection = document.getElementsByClassName('SpreadsheetTaskRowScrollPlaceholder');
	if (!taskPlaceholderHTMLCollection.length) {
		document.querySelectorAll('.TaskRowCompletionStatus-taskCompletionIcon--complete').forEach(incompleteIcon => incompleteIcon.parentNode.click());
	} else {
		const taskGroup = document.querySelector('.TaskGroup');
		const buttonAtTheBottom = document.querySelector('.SpreadsheetPotGridContents-addSectionButton');
		setTimeout(function () {if (buttonAtTheBottom) buttonAtTheBottom.scrollIntoView();}, 30);
		setTimeout(function () {
			taskGroup.style.display = 'none';
			const progressIndicator = document.createElement('span');
			progressIndicator.setAttribute('id', 'progressIndicator');
			progressIndicator.textContent = 'Wird ausgeführt';
			taskGroup.parentNode.appendChild(progressIndicator);
		}, 60);
 
		let monitorTaskStructure = setInterval(() => {
			if (taskPlaceholderHTMLCollection.length == 0) {
				clearInterval(monitorTaskStructure);
				const progressIndicator = document.querySelector('#progressIndicator');
				const allTasks = Array.from(document.querySelectorAll('.TaskRowCompletionStatus-taskCompletionIcon--complete'));
				const numProcesses = Math.floor(allTasks.length / 50) + 1;
				let counter = 0;
				let loopTasks = setInterval(() => {				
					progressIndicator.textContent = `Wird ausgeführt (${counter}/${numProcesses})`;
					for (let i = 50 * counter; i < Math.min(allTasks.length, 50 * (counter + 1)); i++) {
						allTasks[i].parentNode.click();
						if (i == allTasks.length - 1) {
							clearInterval(loopTasks);
							progressIndicator.remove();
							taskGroup.style.display = '';
						}
					}
					counter += 1;
				}, 500);
			}
		}, 100);
	}
})();

2-3. Andere Vorgänge

2-3-1.☰ Größe der Seitenleiste verändern

Durch Verdoppeln der Breite der Seitenleiste auf 480 Pixel werden lange Projektnamen besser lesbar. Klicken Sie erneut auf das Bookmarklet, um zur Standardbreite zurückzukehren.

Dieser Beitrag entstand in Anlehnung an @Ian_Housers Bookmarklet auf https://forum.asana.com/t/sidebar-adjust-size-width/27297/14!

javascript:(function() {
	const widerWidth = '480px';
	const asanaSidebar = document.querySelector('.AsanaMain-sidebar');
	if (!asanaSidebar) return; 
 
	var newStyle = document.querySelector('#asanaSidebarBookmarkletStyle');
	if (!newStyle) {	
		newStyle = document.createElement('style');
		newStyle.id = 'asanaSidebarBookmarkletStyle';
		document.head.appendChild(newStyle);
	}
 
	if (asanaSidebar.style.width == widerWidth) {
		asanaSidebar.style.width = '240px';
		newStyle.innerText = '';
	} else {
		asanaSidebar.style.width = widerWidth;
		newStyle.innerText = `.AsanaMain-sidebar.AsanaMain-sidebar--isCollapsed {margin-left: -${widerWidth} !important}`;
	}
})();
 

3. Herausforderungen

3-1. Aufgaben mit Platzhaltern

Bei einem Projekt mit vielen Aufgaben wandelt Asana einige der Aufgaben, die sich weit außerhalb des Ansichtsbereichs befinden, in vereinfachte Platzhalter um. Diese enthalten lediglich Aufgabennamen, um Ressourcen zu sparen (z. B. Speicher und Energieverbrauch). Beim Scrollen in der Nähe der Platzhalter-Aufgaben werden die Daten erneut geladen.

Beispiel: Beim Scrollen vom unteren Ende des Projekts aus werden die Aufgaben in der Nähe des oberen Endes für kurze Zeit nur mit Namen angezeigt. Weniger als eine Sekunde später werden sie vollständig angezeigt.

Wenn man wie in Abschnitt 2-2 sämtliche Aufgaben anvisiert, blendet man vorübergehend alle Aufgaben aus, wodurch Asana den Eindruck hat, dass genügend Platz vorhanden ist, um alle Aufgaben anzuzeigen. Nachdem Asana alle Platzhalteraufgaben als vollständige Aufgaben wiederhergestellt hat, läuft die Automatisierung. Danach können Sie das Ausblenden wieder rückgängig machen.

3-2. Minderung von Ladezeiten

Wenn Sie zu viele Vorgänge auf einmal ausführen, belasten Sie den Asana-Server. Bei der Verwendung der Asana-API oder bei der Durchführung von Massenaktionen für mehrfach ausgewählte Aufgaben gibt es Grenzen von etwa 50 Aufgaben. Daher habe ich beschlossen, in den oben aufgeführten Bookmarklets „Alle Aufgaben als erledigt/unerledigt markieren” jeweils 50 Aufgaben auf einmal zu verarbeiten.

4. Vergleich mit anderen Verfahren

4-1. Vergleich mit anderen JavaScript-Methoden

Vergleichen wir nun verschiedene Methoden, um bestimmte Vorgänge mit Asana zu automatisieren. Die Methoden links sind komplizierter und leistungsfähiger, während die Methoden rechts einfacher sind. Ein Bookmarklet ist eine ziemlich einfache Methode, da wir im Vergleich zur Entwicklung einer Chrome-Erweiterung nur 1/100 oder 1/10 der Zeilen programmieren müssen. Allerdings müssen wir immer noch eine gewisse Länge an Programmcode schreiben, wenn wir die in Abschnitt 3 beschriebenen Herausforderungen berücksichtigen.

Methoden: OAuth Personal Access Token (PAT) Chrome-Erweiterungen Bookmarklets Browser-Adresszeile
Beispiele: Melden Sie sich bei Asana Academy mit Ihrem Asana-Konto an. Die offizielle Erweiterung von Asana Zu diesem Thema aufgeführt Abrufen der Liste der Arbeitsbereiche
Authentifizierung: Einrichten eines Servers PAT hartkodieren oder in Umgebungsvariablen speichern Browser-Cookie mit Benutzeranmeldung verwenden Cookie (ditto) Cookie (ditto)
Zugriff: Zugriff gewähren PAT verwenden Installieren von Chrome Web Store Zu Lesezeichen hinzufügen URL in Adressleiste eingeben
Kann Folgendes: Operationen über API Operationen über API Operationen über API+DOM Operationen über DOM GET-Operationen über API (Informationen abrufen)
Eignet sich gut für: Groß angelegte Tools Schreiben von Skripten für den persönlichen Gebrauch Verteilung Einfache Erstellung und Verteilung Einfachste Nutzung
Kann Folgendes nicht: Operationen durch DOM Operationen durch DOM (einige Dinge natürlich) Unsichtbare Aufgaben ausführen POST/PUT/DELETE-Operationen (Informationen bearbeiten)
Wie man große Daten verwaltet: Paginierung Paginierung Paginierung Platzhalteraufgaben Paginierung (nicht automatisierbar)

Example: Alle Aufgaben in einem Projekt erledigen

Ein Bookmarklet funktioniert einfacher und schneller.

  • Mit der API senden wir zunächst eine GET-Anforderung an den Endpunkt /projects/<project_gid>/tasks, um die Aufgaben im Projekt abzurufen. Dann durchlaufen wir die Aufgaben in einer Schleife und senden PUT-Anforderungen, um die jeweilige Aufgabe zu erledigen. Für den Abruf und die Aktualisierung von Informationen müssen wir zwei Runden von API-Aufrufen durchführen.

  • Bei Bookmarklets werden die angezeigten Aufgaben direkt durchlaufen und angeklickt.

4-2. Vergleich von JavaScript und CSS

Mit CSS lässt sich das Design von Asana anpassen. Die wesentlichen Unterschiede von CSS sind folgende:

  • Authentifizierung nicht erforderlich, da keine Interaktion mit API

  • Kann „immer” das Design von HTML-Elementen ändern

  • Kann nicht dynamisch reagieren, wenn bestimmte Änderungen eintreten oder der Nutzer einen bestimmten Vorgang ausführt

Vorgehensweise bei der CSS-Anpassung: Installieren Sie Chrome-Erweiterungen wie Stylish oder User CSS. Sie können entweder benutzerdefinierte CSS-Einstellungen verwenden, die von anderen Nutzern aus Bibliotheken wie userstyles.org erstellt wurden, oder eigene CSS-Regeln erstellen.

Example: Breite der Seitenleiste ändern

  • Beim Anklicken des unter 2-3-1 erwähnten Bookmarklets wird die Seitenleiste vergrößert/verkleinert

  • Soll die Breite der Seitenleiste „immer” geändert werden, dann ist es sinnvoller, CSS anzupassen

5. Betrachtungen

5-1. Reverse Engineering

Die API-Bedingungen von Asana untersagen Reverse Engineering. Die Identifizierung von DOM-Elementen durch Rechtsklick und Auswahl von „Inspect” ist jedoch generell möglich. Ich glaube nicht, dass jemand dadurch in irgendeiner Weise auf geschützte Daten von Asana zugreift.

5-2. Mögliche Designänderungen

Asana kann jederzeit IDs und Klassennamen ändern, die wir zur Identifizierung von HTML-Elementen im Asana-Tool einsetzen. Einige der oben genannten Bookmarklets funktionieren dann nicht mehr. Ich werde den Code aktualisieren, wenn ich die Änderungen bemerke. Ich wäre Ihnen jedoch dankbar, wenn Sie mir in einem Kommentar zu diesem Thema Bescheid geben würden.

5-3. Haftungsausschluss

Ich habe die Bookmarklets mit Sorgfalt entwickelt und getestet, hafte allerdings nicht für Probleme, die sich daraus ergeben.

6. Mein besonderer Dank

  • Ich bin auf die Idee gekommen, Bookmarklets zu verwenden, nachdem ich "COLLAPSE (or re-expand) ALL SECTIONS" button needed - #4 by Tony_Tsui gelesen hatte und dachte, dass es ein einfaches und gutes Werkzeug ist. "COLLAPSE (or re-expand) ALL SECTIONS" button needed - #47 by Skyler präsentiert Bookmarklets, die von einem anderen Nutzer zusammengestellt wurden.

  • Forum Leader @Bastien_Siebman und Ambassador @Itay_Kurgan halfen mir freundlicherweise, einen Teil des Codes in realen Umgebungen zu testen, und gaben mir wertvolle Einblicke, insbesondere in die in Abschnitt 3 genannten Herausforderungen.

  • Vielen Dank, dass Sie diesen Artikel gelesen haben. Bitte hinterlassen Sie einen Kommentar, wenn Sie weitere Funktionen wünschen. Außerdem empfehle ich Ihnen, selbst Bookmarklets zu programmieren, wenn Sie JavaScript beherrschen. :slight_smile:

Dieser Beitrag wurde ursprünglich auf Japanisch verfasst: Asanaブックマークレットのご紹介

3 Likes