AUI 8 Temprary File upload AJS.InlineAttach replacement

I am trying to update plugin compatibility from Jira 7.0.11 to 8.5.0 . I am getting issues with temporary file upload. Unable to find AJS.InlineAttach class and getting this error on frontend Uncaught TypeError: Cannot read property ‘AjaxPresenter’ of undefined.

File is not being received to the backend upon form submission and receiving null pointer exception .Also tried to load file explicitly by copying into webresource / including directly through script tag but did not work.

May I know how we can achieve this in AUI 8 ?

<link rel="stylesheet" type="text/css" 
  href="https://unpkg.com/@atlassian/aui@8.5.0/dist/aui/aui-prototyping.css" />
  <script src="http://code.jquery.com/jquery-2.2.4.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/1.15.4/sinon.js"> 
  </script>
  <script src="https://unpkg.com/@atlassian/aui@8.5.0/dist/aui/aui-prototyping.js"> 
</script>

 <script type="text/javascript">
// replace the generic JIRA hook to the REST API for uploading temporary files
var defaultJiraAjaxPresenterHook = AJS.InlineAttach.AjaxPresenter.DEFAULT_URL
var defaultJiraPresenterHook = AJS.InlineAttach.Presenter.DEFAULT_URL
var defaultJiraFormPresenterHook = AJS.InlineAttach.FormPresenter.DEFAULT_URL
AJS.InlineAttach.AjaxPresenter.DEFAULT_URL = "/rest/fileupload/1.0/customfile";
AJS.InlineAttach.Presenter.DEFAULT_URL = "/rest/fileupload/1.0/customfile";
AJS.InlineAttach.FormPresenter.DEFAULT_URL = "/rest/fileupload/1.0/customfile";
  </script>

<section id="static-dialog" class="aui-dialog2 aui-dialog2-medium" role="dialog">

<div id="upload-file-dialog">
	<header class="aui-dialog2-header">
		<h2 class="aui-dialog2-header-main">
			Import ${fileType} File<span style="display:none" class="header-separator">:&nbsp;</span>
			<a class="header-issue-key" style="display:none" title="" href=""></a>
		</h2>
	</header>
		<div class="aui-dialog2-content">
			<div class="dialog-title hidden">Import ${fileType} File</div>
			<form action="Import!${formAction}.jspa" class="aui" id="load-file-form" method="post">
				<div class="form-body" style="max-height: 404px; ">
					<div class="hidden">
						<input name="id" type="hidden" value="10400">
					</div>
					<fieldset class="group ">
						<legend><span>File selection <span class="aui-icon icon-required"></span></span></legend>
						<div class="field-group file-input-list">
							<div class="field-group ">
								<input class="upfile " name="tempFilename" type="file" id="tf" multiple="none">
								<div id="attach-max-size" class="hidden">10485760</div>
							</div>
							<div class="description">The maximum file upload size is 10.00 MB.</div>
						</div>

					</fieldset> <!-- // .group -->

					<div class="security-level">
						<fieldset class="hidden parameters">
							<input type="hidden" title="securityLevelViewableByAll" value="Viewable by All Users">
							<input type="hidden" title="securityLevelViewableRestrictedTo"
								value="Restricted to &lt;span class='redText'&gt;{0}&lt;/span&gt;">
						</fieldset>

						<div class="select-menu" id="commentLevel-multi-select"></div>
					</div>

				</div>

				<div class="buttons-container form-footer">
					<div class="buttons"><span class="icon throbber"></span>
						<input accesskey="s" class="button" id="attach-file-submit" name="Upload"
							title="Press Alt+s to submit this form" type="submit" value="Upload">
						<a accesskey="`" class="cancel" href="" id="attach-file-cancel"
							title="Press Alt+` to cancel">Cancel</a>

					</div>
				</div>
			</form> <!-- // .aui #upload-file -->
		</div>
</div>
</section>

<script type="text/javascript">

var timer = setInterval(function () {

	AJS.$('#normalized_tsv_import_link-dialog').css("top", "30%");
	AJS.$('#normalized_tsv_import_link-dialog').css("height", "390px");
	AJS.$('#normalized_tsv_import_link-dialog').css("margin-top", "-10px");

	AJS.$('#normalized_xml_import_link-dialog').css("top", "30%");
	AJS.$('#normalized_xml_import_link-dialog').css("height", "390px");
	AJS.$('#normalized_xml_import_link-dialog').css("margin-top", "-10px");

	if (AJS.$("#attach-file-submit").length > 0) {
		AJS.$("#attach-file-submit").click(function (ev) {
			isOk = true;
			AJS.InlineAttach.AjaxPresenter.DEFAULT_URL = defaultJiraAjaxPresenterHook;
			AJS.InlineAttach.Presenter.DEFAULT_URL = defaultJiraPresenterHook;
			AJS.InlineAttach.FormPresenter.DEFAULT_URL = defaultJiraFormPresenterHook;
			if (!isOk) {
				ev.preventDefault();
			}
			else {
				ev.currentTarget.allowDefault = true;
			}
			return isOk;
		})
		AJS.$("#attach-file-cancel").click(function (ev) {
			AJS.InlineAttach.AjaxPresenter.DEFAULT_URL = defaultJiraAjaxPresenterHook;
			AJS.InlineAttach.Presenter.DEFAULT_URL = defaultJiraPresenterHook;
			AJS.InlineAttach.FormPresenter.DEFAULT_URL = defaultJiraFormPresenterHook;
		})

		clearInterval(timer);
	}
}, 200);


</script>

Hi @rpatil,
InlineAttach comes from Jira codebase, not AUI, so it’s not related to AUI per se.
First, you need to add an explicit dependency on the following web-resource in your atlassian-plugin.xml file to be sure that the code you’re relying on will be provided to the browser:

<dependency>jira.webresources:inline-attach</dependency>

Then, it’s preferred to use AMD modules over global variables. You can find InlineAttach exposed as jira/attachment/inline-attach.

An example of requiring AMD module:

define('your-prefix/your/amd/module-name', [
    'some-amd-module-name-as-a-dependency',
    'jira/attachment/inline-attach',
], function(someAmd, InlineAttach) {
  // here you can use InlineAttach
});

or directly

const InlineAttach = require('jira/attachment/inline-attach');

Let me know if it helped you.

Best,
Jira Team

1 Like

Thank you. I tried adding dependency to the webresource but it wasnt being loaded to the page. So I tried to add inline-attach.js file with script tag

<script src="https://infocentral.infoway-inforoute.ca/inline-attach.js"></script>

And used this before URL definitions
const InlineAttach = require(‘jira/attachment/inline-attach’);

Inline-attach.js starts with this.

define('jira/attachment/inline-attach', [
   'jira/lib/class',
   'jira/xsrf',
   'jira/util/navigator',
   'jquery'
], function(
 Class,
 XSRF,
 Navigator,
 jQuery
) { ....

I am getting two errors on browser console here.
Uncaught ReferenceError: define is not defined
at inline-attach.js:1 (at the start of js file)
and
Uncaught ReferenceError: require is not defined
at Import!showNormalizedTsvImport.jspa:12 where const InlineAttach = require(‘jira/attachment/inline-attach’); is defined

I’m afraid I don’t have a context what you’re building and in which environment.
Can you shed a light on this?

Given you wanted to use Jira modules, I assumed you’re writing an app (P2 plugin) for Jira.
In this context, you shouldn’t write your on script tags, just put explicit dependencies and other entires in your atlassian-plugin.xml (unless you’re using webpack along with Bitbucket then you don’t need to write those entires on your own)
and required assets will be included on the page (strictly speaking, a product makes calls to WRM which generates script and link tags which are put on the page).

Can you tell me more about this line ? I am not able to understnad what is your-prefix/your in this context

 define ( 'your-prefix/your/amd/module-name'

I tried adding web resource in atlassian-plugin.xml

<web-resource name="Showloadwebresourse" i18n-name-key="showloadwebresourse.name" key="showloadwebresourse"> 
 <description key="showloadwebresourse.description">The Showloadwebresourse Plugin</description>
 <dependency>com.atlassian.auiplugin:ajs</dependency>
 <dependency>jira.webresources:inline-attach</dependency>
 <context>atl.general</context>
</web-resource>

Then in the front end

$webResourceManager.requireResource("ca.chi.jira.chi-addons:showloadwebresourse")
$webResourceManager.requireResource("jira.webresources:inline-attach")

<link rel="stylesheet" type="text/css" href="https://unpkg.com/@atlassian/aui@8.5.0/dist/aui/aui-prototyping.css" />
<script src="http://code.jquery.com/jquery-2.2.4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sinon.js/1.15.4/sinon.js"></script>
<script src="https://unpkg.com/@atlassian/aui@8.5.0/dist/aui/aui-prototyping.js"></script>


<script type="text/javascript">
// replace the generic JIRA hook to the REST API for uploading temporary files
define([ "jquery", 'jira/attachment/inline-attach'],
function (jquery, InlineAttach) {
    var defaultJiraAjaxPresenterHook = AJS.InlineAttach.AjaxPresenter.DEFAULT_URL
    var defaultJiraPresenterHook = AJS.InlineAttach.Presenter.DEFAULT_URL
    var defaultJiraFormPresenterHook = AJS.InlineAttach.FormPresenter.DEFAULT_URL
    var defaultTimeout = AJS["$"].ajaxSettings.timeout;
    AJS.InlineAttach.AjaxPresenter.DEFAULT_URL = "/rest/fileupload/1.0/customfile";
    AJS.InlineAttach.Presenter.DEFAULT_URL = "/rest/fileupload/1.0/customfile";
    AJS.InlineAttach.FormPresenter.DEFAULT_URL = "/rest/fileupload/1.0/customfile";
    AJS["$"].ajaxSettings.timeout=7200000;
});
</script>

Getting define is not defined error at define([ “jquery”, ‘jira/attachment/inline-attach’],

When I tried to search for inlineattach in target folder, then I found it on this path.

Hi @rpatil,

The define function is a part of the AMD runtime that you can use to share the code and then require it using the require function.

The your-prefix/your/amd/module-name is an example of the module name that later you can require .e.g.:

define('your-prefix/your/amd/module-name', [], function() {
   return function someFunction() {
      console.log('Hello there!');
   };
});

var someFunction = require('your-prefix/your/amd/module-name');
someFunction() // prints "Hello there!" in the browser console

Here is a link to the AMD module docs:

From the description of your post, it looks like you are trying to inject the JavaScript code without using Web Resouce Manager (WRM).

The define function is part of the server/dc browser runtime, but it’s not registered in the runtime yet when you call it. Try moving all of your inline JS code from <script> tags to the `web-resource you can require later.

You can either use the webpack and atlassian-webresource-webpack-plugin webpack plugin, or you can define the web-resources manually in the atlassian-plugin.xml file.

Docs links:

You can also check this guide if you want to set up the plugin using the webpack and atlassian-webresource-webpack-plugin .

Thanks,
Maciej Adamczak
Atlassian Developer

Hi , I think problem here is I am unable to load webResource to the template. I removed js imported from tags and tried to check if AJS and other dependency js are being loaded to the page, But they are not loading. I do not see AMD modules like require and define being loaded while trying to search from console. Resulting in define / require not found errors.

Do we have any method to validate how we can check If dependency from webresource is being loaded or not ? It seems like WRM is not working here.

I created this web resource in atlassian-plugin.xml

<web-resource name="Showloadwebresourse" i18n-name-key="showloadwebresourse.name" key="showloadwebresourse"> 
  <description key="showloadwebresourse.description">The Showloadwebresourse Plugin</description>
 <dependency>com.atlassian.auiplugin:ajs</dependency>
 <dependency>jira.webresources:inline-attach</dependency>
 <dependency>com.atlassian.plugins.atlassian-plugins-webresource-rest:web-resource-manager</dependency>
 <context>atl.general</context>
</web-resource>

And added this to the template

$webResourceManager.requireResource("ca.chi.jira.chi-addons:showloadwebresourse")
$webResourceManager.requireResource("jira.webresources:inline-attach")

Hi,
in general the code you posted looks OK.

  1. Using <context>atl.general</context> is good for testing, as the resources from that web-resource are going to be present on every page, however it’s not suitable the production, because every page will be affected.
    In the current shape, those resources (ajs, inline-attach) will be present on every page (not sure about admin pages, there may be another context such as atl.admin, good for testing too).
    Hence, even without the later requireResource you should be able to see those assets loaded on the page.
  • are there any errors in the console log?
  • can you share a screenshot?
  • are you sure the app and its module are installed and enabled? (you can check that in the Manage apps, finding your app, and expanding modules)
  • are you able to share more of the source code (can be on a private repo or so) or a jar, so that we’d see a bigger picture what’s happening there?
  1. for the production, you can change the atl.general context to some unique name for your feature, and do the following in the template:
    $webResourceManager.requireResourcesForContext('your.context.name')