1. Mike Cannon-Brookes
  2. jira-attachment-improvements-extension

Commits

Mike Cannon-Brookes  committed afdacf8

Initial commit. Useful but not finished yet. Shows thumbnails for images and links for all attachments.

  • Participants
  • Branches default

Comments (0)

Files changed (3)

File pom.xml

View file
  • Ignore whitespace
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>com.atlassian.mike</groupId>
+    <artifactId>jira-attachment-improvements-extension</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <organization>
+        <name>Atlassian</name>
+        <url>http://www.atlassian.com/</url>
+    </organization>
+
+    <name>JIRA Attachment Improvements Extension</name>
+    <description>Improvements to attachment handling in change history. Links all attachments, shows thumbnails for non-deleted images and links deletion events to creation events and vice versa.</description>
+    <packaging>atlassian-plugin</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.6</version>
+            <scope>test</scope>
+        </dependency>
+          <dependency>
+	            <groupId>com.atlassian.confluence</groupId>
+	            <artifactId>confluence</artifactId>
+	            <version>${confluence.version}</version>
+	            <scope>provided</scope>
+	        </dependency>
+	        <dependency>
+	            <groupId>com.atlassian.confluence.plugin</groupId>
+	            <artifactId>func-test</artifactId>
+	            <version>2.3-beta1</version>
+	            <scope>test</scope>
+	        </dependency>
+	        <dependency>
+	            <groupId>net.sourceforge.jwebunit</groupId>
+	            <artifactId>jwebunit-htmlunit-plugin</artifactId>
+	            <version>2.2</version>
+	            <scope>test</scope>
+	        </dependency>
+	        <dependency>
+	            <groupId>net.sourceforge.nekohtml</groupId>
+	            <artifactId>nekohtml</artifactId>
+	            <version>1.9.12</version>
+	            <scope>test</scope>
+	        </dependency>
+    </dependencies>
+
+    <build>
+       <plugins>
+            <plugin>
+                <groupId>com.atlassian.maven.plugins</groupId>
+                <artifactId>maven-confluence-plugin</artifactId>
+                <version>3.3-m7</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <productVersion>${confluence.version}</productVersion>
+                    <productDataVersion>${confluence.data.version}</productDataVersion>
+                    <compressResources>false</compressResources>
+                    <pluginArtifacts>
+                        <pluginArtifact>
+                            <groupId>com.atlassian.labs</groupId>
+                            <artifactId>speakeasy-plugin</artifactId>
+                            <version>1.0-SNAPSHOT</version>
+                        </pluginArtifact>
+                    </pluginArtifacts>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.5</source>
+                    <target>1.5</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <properties>
+        <jira.version>4.2</jira.version>
+        <jira.data.version>4.2</jira.data.version>
+        <confluence.version>3.4</confluence.version>
+        <confluence.data.version>3.1</confluence.data.version>
+    </properties>
+
+</project>

File src/main/resources/atlassian-plugin.xml

View file
  • Ignore whitespace
+<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2">
+    <plugin-info>
+        <description>${project.description}</description>
+        <version>${project.version}</version>
+        <vendor name="${project.organization.name}" url="${project.organization.url}" />
+    </plugin-info>
+
+    <scoped-web-resource key="attachment-improvements">
+        <resource type="download" name="attachment-improvements.js" location="js/attachment-improvements.js">
+			<param name="batch" value="false"/>
+		</resource>
+        <!-- <context>issue</context> -->
+        <context>atl.general</context>
+    </scoped-web-resource>
+</atlassian-plugin>

File src/main/resources/js/attachment-improvements.js

View file
  • Ignore whitespace
+function Attachment(id, filename, cell){
+	this.id = id;
+	this.filename = filename;
+	this.isImage = (filename.match(/\.(gif|jpg|jpeg|png)$/i) ? true : false);
+	this.cell = cell;
+}
+
+(function() {
+    jQuery(document).ready(function() {
+		var removedAttachments = {};
+		var addedAttachments = {};
+		
+		// first, let's fine all the table cells containing activity names
+        jQuery("td.activity-name").each(function() {
+			var tdName = jQuery(this);
+			
+			// now filter only those which are Attachment actions by looking at the text
+			if (tdName.text().match(/Attachment/)) {
+				
+				// now we look to see if there's an old value by moving to the next table cell
+				var tdOldVal = tdName.next();
+				if (tdOldVal.text().trim() != '') {
+					var attachment = findAttachment(tdOldVal)
+					
+					if (attachment) {
+						removedAttachments[attachment.id] = attachment;
+					}
+				}
+				
+				// now move onto the new value and do the same
+				var tdNewVal = tdOldVal.next();
+				if (tdNewVal.text().trim() != '') {
+					var attachment = findAttachment(tdNewVal);
+					if (attachment) {
+						addedAttachments[attachment.id] = attachment;
+					}
+				}
+			}
+		 });
+		
+		jQuery.each(addedAttachments, function(id, attachment) { 
+			if (!removedAttachments[id]) {
+				attachment.cell.html('<a href="' + contextPath + '/secure/attachment/' + id + '/' + encodeURI(attachment.filename) + '">' + attachment.filename + '</a> [' + id + ']' + (attachment.isImage ? '<br/ ><img src="' + contextPath + '/secure/thumbnail/' + id + '/' + id + '">' : ''));
+			}
+			else {
+				attachment.cell.html('<a name="addAttachment' + id + '"></a><strike>' + attachment.filename + ' [' + id + ']</strike> (removed <a href="#removeAttachment' + id + '">later</a>)')
+			}
+		});
+		
+		jQuery.each(removedAttachments, function(id, attachment) { 
+			if (addedAttachments[id]) {
+				attachment.cell.html('<a name="removeAttachment' + id + '"></a>' + attachment.filename + ' [' + id + '] (added <a href="#addAttachment' + id + '">earlier</a>)')
+			}
+			else {
+				attachment.cell.html(attachment.filename + '</a> [' + id + '] (added on issue create)')
+			}
+		});
+    });
+})();
+
+function findAttachment(cell) {
+	// we've found an attachment! Let's get the filename and attachment ID
+	var matches = cell.text().match("^([^\\[]+)\\[([^\\]]+)\\]");
+	if (!matches)
+		return;
+	var filename = matches[1].trim();
+	var id = matches[2].trim();
+	
+	return new Attachment(id, filename, cell);
+}
+
+	// great - now let's rewrite the cell contents to what we want!
+//	cell.html('<a href="' + contextPath + '/secure/attachment/' + attachmentId + '/' + encodeURI(filename) + '">' + filename + '</a> [' + attachmentId + ']<br/ ><img src="' + contextPath + '/secure/thumbnail/' + attachmentId + '/' + attachmentId + '">');
+