@atlassian/atlassian-connect-js 5.3.190
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.depcheckrc.json +16 -0
- package/.editorconfig +9 -0
- package/.envrc +5 -0
- package/.eslintignore +12 -0
- package/.eslintrc +31 -0
- package/.husky/pre-commit +11 -0
- package/.lintstagedrc.js +6 -0
- package/.netrc +1 -0
- package/.npmrc-public +4 -0
- package/.nvmrc +1 -0
- package/LICENSE +3 -0
- package/README.md +281 -0
- package/bitbucket-pipelines.yml +33 -0
- package/build/bin/bin-helper.js +29 -0
- package/build/bin/npm-postinstall.js +9 -0
- package/build/configs/append-sourcemapping.js +13 -0
- package/build/configs/availabletasks.js +15 -0
- package/build/configs/clean.js +12 -0
- package/build/configs/concat.js +44 -0
- package/build/configs/copy.js +32 -0
- package/build/configs/index.js +19 -0
- package/build/configs/jshint.js +9 -0
- package/build/configs/karma.js +11 -0
- package/build/configs/replace.js +10 -0
- package/build/configs/requirejs.js +187 -0
- package/build/configs/saucelabs-launchers.js +30 -0
- package/build/configs/shell.js +24 -0
- package/build/configs/uglify.js +15 -0
- package/build/configs/watch.js +45 -0
- package/build/end.frag +13 -0
- package/build/start.frag +18 -0
- package/bundlesize.config.json +14 -0
- package/dist/connect-host.css +225 -0
- package/dist/connect-host.js +13908 -0
- package/dist/connect-host.min.css +1 -0
- package/dist/iframe-fedramp.js +13663 -0
- package/dist/iframe.js +13663 -0
- package/dist/legacy-text-colors.css +245 -0
- package/dist/surfaces.css +11 -0
- package/dist/themes/atlaskit-tokens_dark-future.css +6 -0
- package/dist/themes/atlaskit-tokens_dark.css +394 -0
- package/dist/themes/atlaskit-tokens_legacy-dark.css +394 -0
- package/dist/themes/atlaskit-tokens_legacy-light.css +394 -0
- package/dist/themes/atlaskit-tokens_light-future.css +6 -0
- package/dist/themes/atlaskit-tokens_light.css +394 -0
- package/dist/themes/atlaskit-tokens_shape.css +14 -0
- package/dist/themes/atlaskit-tokens_spacing.css +26 -0
- package/dist/themes/atlaskit-tokens_typography-adg3.css +25 -0
- package/dist/themes/atlaskit-tokens_typography-modernized.css +25 -0
- package/dist/themes/atlaskit-tokens_typography-refreshed.css +25 -0
- package/gulpfile.js +204 -0
- package/memleak-check/app.html +10 -0
- package/memleak-check/index.html +31 -0
- package/memleak-check/index.js +33 -0
- package/package.json +102 -0
- package/renovate.json +11 -0
- package/security-assistant.yml +2 -0
- package/spec/.eslintrc +10 -0
- package/spec/config/karma.base.conf.js +200 -0
- package/spec/config/karma.conf.js +20 -0
- package/spec/fixtures/base_dialog_component_tests.js +180 -0
- package/spec/mocks/mock_feature_flag.js +23 -0
- package/spec/tests/amd_spec.js +122 -0
- package/spec/tests/analytics_dispatcher_spec.js +429 -0
- package/spec/tests/analytics_performance_spec.js +41 -0
- package/spec/tests/button_spec.js +143 -0
- package/spec/tests/dialog_extension_spec.js +59 -0
- package/spec/tests/dialog_module_provider_spec.js +499 -0
- package/spec/tests/dialog_module_spec.js +395 -0
- package/spec/tests/dialog_spec.js +296 -0
- package/spec/tests/dialog_webitem_spec.js +183 -0
- package/spec/tests/dropdown_module_spec.js +77 -0
- package/spec/tests/env_module_spec.js +153 -0
- package/spec/tests/events_spec.js +77 -0
- package/spec/tests/extension_configuration_options_store_spec.js +25 -0
- package/spec/tests/flag_module_provider_spec.js +79 -0
- package/spec/tests/flag_module_spec.js +118 -0
- package/spec/tests/flag_spec.js +243 -0
- package/spec/tests/host-api_spec.js +220 -0
- package/spec/tests/iframe-create_spec.js +43 -0
- package/spec/tests/iframe_container_spec.js +19 -0
- package/spec/tests/iframe_spec.js +265 -0
- package/spec/tests/inline_dialog_spec.js +41 -0
- package/spec/tests/inline_dialog_webitem_spec.js +331 -0
- package/spec/tests/loading_indicator_spec.js +48 -0
- package/spec/tests/messages_module_spec.js +108 -0
- package/spec/tests/meta_spec.js +71 -0
- package/spec/tests/module_args_spec.js +52 -0
- package/spec/tests/observe_spec.js +73 -0
- package/spec/tests/public_events.spec.js +102 -0
- package/spec/tests/scroll_position_spec.js +109 -0
- package/spec/tests/theming_spec.js +594 -0
- package/spec/tests/util_spec.js +55 -0
- package/spec/tests/utils/base64_spec.js +20 -0
- package/spec/tests/utils/button_spec.js +11 -0
- package/spec/tests/utils/cookie_spec.js +19 -0
- package/spec/tests/utils/deprecate_spec.js +22 -0
- package/spec/tests/utils/dialog_spec.js +297 -0
- package/spec/tests/utils/host_util_spec.js +45 -0
- package/spec/tests/utils/iframe_spec.js +41 -0
- package/spec/tests/utils/jwt_spec.js +135 -0
- package/spec/tests/utils/url_spec.js +37 -0
- package/spec/tests/utils/waitUntilReadyNextTick.js +5 -0
- package/spec/tests/utils/webitem.js +219 -0
- package/spec/tests/webitem_spec.js +131 -0
- package/src/css/host/dialog.css +144 -0
- package/src/css/host/flags.css +5 -0
- package/src/css/host/host.css +64 -0
- package/src/css/host/messages.css +12 -0
- package/src/css/plugin/legacy-text-colors.less +55 -0
- package/src/css/plugin/surfaces.css +11 -0
- package/src/host/ACJSFrameworkAdaptor.js +44 -0
- package/src/host/actions/analytics_action.js +35 -0
- package/src/host/actions/button_actions.js +21 -0
- package/src/host/actions/dialog_actions.js +27 -0
- package/src/host/actions/dialog_extension_actions.js +25 -0
- package/src/host/actions/dom_event_actions.js +32 -0
- package/src/host/actions/dropdown_actions.js +12 -0
- package/src/host/actions/env_actions.js +57 -0
- package/src/host/actions/event_actions.js +33 -0
- package/src/host/actions/flag_actions.js +22 -0
- package/src/host/actions/iframe_actions.js +27 -0
- package/src/host/actions/inline_dialog_actions.js +26 -0
- package/src/host/actions/inline_dialog_webitem_actions.js +10 -0
- package/src/host/actions/jwt_actions.js +51 -0
- package/src/host/actions/loading_indicator_actions.js +10 -0
- package/src/host/actions/module_actions.js +14 -0
- package/src/host/actions/webitem_actions.js +29 -0
- package/src/host/components/button.js +112 -0
- package/src/host/components/dialog.js +447 -0
- package/src/host/components/dialog_extension.js +106 -0
- package/src/host/components/dialog_webitem.js +69 -0
- package/src/host/components/flag.js +102 -0
- package/src/host/components/iframe.js +130 -0
- package/src/host/components/iframe_container.js +38 -0
- package/src/host/components/inline_dialog.js +108 -0
- package/src/host/components/inline_dialog_webitem.js +157 -0
- package/src/host/components/loading_indicator.js +110 -0
- package/src/host/components/webitem.js +227 -0
- package/src/host/deprecate.js +20 -0
- package/src/host/dispatchers/analytics_dispatcher.js +512 -0
- package/src/host/dispatchers/event_dispatcher.js +46 -0
- package/src/host/dollar.js +8 -0
- package/src/host/host-api.js +325 -0
- package/src/host/iframe-create.js +7 -0
- package/src/host/index.js +108 -0
- package/src/host/module-providers.js +13 -0
- package/src/host/modules/_featureFlag.js +42 -0
- package/src/host/modules/_performance.js +54 -0
- package/src/host/modules/analytics.js +17 -0
- package/src/host/modules/dialog.js +496 -0
- package/src/host/modules/dropdown.js +255 -0
- package/src/host/modules/env.js +156 -0
- package/src/host/modules/events.js +28 -0
- package/src/host/modules/flag.js +170 -0
- package/src/host/modules/host.js +19 -0
- package/src/host/modules/inline-dialog.js +33 -0
- package/src/host/modules/messages.js +309 -0
- package/src/host/modules/page.js +29 -0
- package/src/host/modules/scroll-position.js +102 -0
- package/src/host/modules/theming.js +114 -0
- package/src/host/stores/extension_configuration_options_store.js +24 -0
- package/src/host/util.js +98 -0
- package/src/host/utils/access-narrowing-context.js +18 -0
- package/src/host/utils/base64.js +22 -0
- package/src/host/utils/button.js +10 -0
- package/src/host/utils/cookie.js +14 -0
- package/src/host/utils/dialog.js +239 -0
- package/src/host/utils/feature-flag.js +27 -0
- package/src/host/utils/iframe.js +23 -0
- package/src/host/utils/jwt.js +60 -0
- package/src/host/utils/observe.js +34 -0
- package/src/host/utils/removal-observer.js +30 -0
- package/src/host/utils/simplexdm.js +58 -0
- package/src/host/utils/url.js +23 -0
- package/src/host/utils/webitem.js +214 -0
- package/src/plugin/amd.js +115 -0
- package/src/plugin/analytics.js +84 -0
- package/src/plugin/deprecate.js +16 -0
- package/src/plugin/dialog.js +197 -0
- package/src/plugin/dollar.js +77 -0
- package/src/plugin/events-instance.js +2 -0
- package/src/plugin/events.js +246 -0
- package/src/plugin/extension_configuration_options_store.js +27 -0
- package/src/plugin/featureFlag.js +8 -0
- package/src/plugin/index.js +118 -0
- package/src/plugin/meta.js +14 -0
- package/src/plugin/public-events.js +73 -0
- package/src/plugin/theming.js +211 -0
- package/src/plugin/util.js +104 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messages are the primary method for providing system feedback in the product user interface.
|
|
3
|
+
* Messages include notifications of various kinds: alerts, confirmations, notices, warnings, info and errors.
|
|
4
|
+
* For visual examples of each kind please see the [Design guide](https://docs.atlassian.com/aui/latest/docs/messages.html).
|
|
5
|
+
* ### Example ###
|
|
6
|
+
* ```
|
|
7
|
+
* //create a message
|
|
8
|
+
* var message = AP.messages.info('plain text title', 'plain text body');
|
|
9
|
+
* ```
|
|
10
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
11
|
+
* @name Messages
|
|
12
|
+
* @module
|
|
13
|
+
* @ignore
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import $ from '../dollar';
|
|
17
|
+
import HostApi from '../host-api';
|
|
18
|
+
import util from '../util';
|
|
19
|
+
import AnalyticsAction from '../actions/analytics_action';
|
|
20
|
+
|
|
21
|
+
const MESSAGE_BAR_ID = 'ac-message-container';
|
|
22
|
+
const MESSAGE_TYPES = ['generic', 'error', 'warning', 'success', 'info', 'hint'];
|
|
23
|
+
const MSGID_PREFIX = 'ap-message-';
|
|
24
|
+
const MSGID_REGEXP = new RegExp(`^${MSGID_PREFIX}[0-9A-fa-f]+$`);
|
|
25
|
+
const _messages = {};
|
|
26
|
+
|
|
27
|
+
function validateMessageId(msgId) {
|
|
28
|
+
return MSGID_REGEXP.test(msgId);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getMessageBar() {
|
|
32
|
+
let $msgBar = $('#' + MESSAGE_BAR_ID);
|
|
33
|
+
|
|
34
|
+
if ($msgBar.length < 1) {
|
|
35
|
+
$msgBar = $('<div id="' + MESSAGE_BAR_ID + '" />').appendTo('body');
|
|
36
|
+
}
|
|
37
|
+
return $msgBar;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function filterMessageOptions(options) {
|
|
41
|
+
const copy = {};
|
|
42
|
+
const allowed = ['closeable', 'fadeout', 'delay', 'duration', 'id'];
|
|
43
|
+
if (typeof options === 'object') {
|
|
44
|
+
allowed.forEach(key => {
|
|
45
|
+
if (key in options) {
|
|
46
|
+
copy[key] = options[key];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return copy;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
var messageCloseListenerCreated = false;
|
|
54
|
+
|
|
55
|
+
function showMessage(name, title, body, options) {
|
|
56
|
+
if(!messageCloseListenerCreated) {
|
|
57
|
+
createMessageCloseListener();
|
|
58
|
+
messageCloseListenerCreated = true;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const $msgBar = getMessageBar();
|
|
62
|
+
options = filterMessageOptions(options);
|
|
63
|
+
$.extend(options, {
|
|
64
|
+
title: title,
|
|
65
|
+
body: AJS.escapeHtml(body)
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (MESSAGE_TYPES.indexOf(name) < 0) {
|
|
69
|
+
throw 'Invalid message type. Must be: ' + MESSAGE_TYPES.join(', ');
|
|
70
|
+
}
|
|
71
|
+
if (validateMessageId(options.id)) {
|
|
72
|
+
AJS.messages[name]($msgBar, options);
|
|
73
|
+
// Calculate the left offset based on the content width.
|
|
74
|
+
// This ensures the message always stays in the centre of the window.
|
|
75
|
+
$msgBar.css('margin-left', '-' + $msgBar.innerWidth() / 2 + 'px');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function deprecatedShowMessage(name, title, body, options, callback) {
|
|
80
|
+
const methodUsed = `AP.messages.${name}`;
|
|
81
|
+
console.warn(`DEPRECATED API - AP.messages.${name} has been deprecated since ACJS 5.0 and will be removed in a future release. Use AP.flag.create instead.`);
|
|
82
|
+
AnalyticsAction.trackDeprecatedMethodUsed(methodUsed, callback._context.extension);
|
|
83
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
84
|
+
const messageProvider = frameworkAdaptor.getProviderByModuleName('messages');
|
|
85
|
+
if (messageProvider) {
|
|
86
|
+
const messageType = name;
|
|
87
|
+
let createMessage = messageProvider[messageType];
|
|
88
|
+
if (!createMessage) {
|
|
89
|
+
messageProvider[messageType] = messageProvider.generic;
|
|
90
|
+
}
|
|
91
|
+
createMessage(title, body, options);
|
|
92
|
+
} else {
|
|
93
|
+
showMessage(name, title, body, options);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function createMessageCloseListener(){
|
|
98
|
+
$(document).on('aui-message-close', function(e, $msg) {
|
|
99
|
+
const _id = $msg.attr('id').replace(MSGID_PREFIX, '');
|
|
100
|
+
if (_messages[_id]) {
|
|
101
|
+
if ($.isFunction(_messages[_id].onCloseTrigger)) {
|
|
102
|
+
_messages[_id].onCloseTrigger();
|
|
103
|
+
}
|
|
104
|
+
_messages[_id]._destroy();
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
function messageModule(messageType) {
|
|
112
|
+
return {
|
|
113
|
+
constructor: function(title, body, options, callback) {
|
|
114
|
+
callback = util.last(arguments);
|
|
115
|
+
const _id = callback._id;
|
|
116
|
+
if (typeof title !== 'string') {
|
|
117
|
+
title = '';
|
|
118
|
+
}
|
|
119
|
+
if (typeof body !== 'string') {
|
|
120
|
+
body = '';
|
|
121
|
+
}
|
|
122
|
+
if (typeof options !== 'object') {
|
|
123
|
+
options = {};
|
|
124
|
+
}
|
|
125
|
+
options.id = MSGID_PREFIX + _id;
|
|
126
|
+
deprecatedShowMessage(messageType, title, body, options, callback);
|
|
127
|
+
_messages[_id] = this;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export default {
|
|
133
|
+
/**
|
|
134
|
+
* Close a message
|
|
135
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
136
|
+
* @name clear
|
|
137
|
+
* @method
|
|
138
|
+
* @memberof module:Messages#
|
|
139
|
+
* @param {String} id The id that was returned when the message was created.
|
|
140
|
+
* @example
|
|
141
|
+
* //create a message
|
|
142
|
+
* var message = AP.messages.info('title', 'body');
|
|
143
|
+
* setTimeout(function(){
|
|
144
|
+
* AP.messages.clear(message);
|
|
145
|
+
* }, 2000);
|
|
146
|
+
*/
|
|
147
|
+
clear: function(msg) {
|
|
148
|
+
const id = MSGID_PREFIX + msg._id;
|
|
149
|
+
if (validateMessageId(id)) {
|
|
150
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
151
|
+
const messageProvider = frameworkAdaptor.getProviderByModuleName('messages');
|
|
152
|
+
if (messageProvider) {
|
|
153
|
+
messageProvider.clear(id);
|
|
154
|
+
} else {
|
|
155
|
+
$('#' + id).closeMessage();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Trigger an event when a message is closed
|
|
162
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
163
|
+
* @name onClose
|
|
164
|
+
* @method
|
|
165
|
+
* @memberof module:Messages#
|
|
166
|
+
* @param {String} id The id that was returned when the message was created.
|
|
167
|
+
* @param {Function} callback The function that is run when the event is triggered
|
|
168
|
+
* @example
|
|
169
|
+
* //create a message
|
|
170
|
+
* var message = AP.messages.info('title', 'body');
|
|
171
|
+
* AP.messages.onClose(message, function() {
|
|
172
|
+
* console.log(message, ' has been closed!');
|
|
173
|
+
* });
|
|
174
|
+
*/
|
|
175
|
+
onClose: function(msg, callback) {
|
|
176
|
+
callback = util.last(arguments);
|
|
177
|
+
const id = msg._id;
|
|
178
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
179
|
+
const messageProvider = frameworkAdaptor.getProviderByModuleName('messages');
|
|
180
|
+
if (messageProvider) {
|
|
181
|
+
const fullId = MSGID_PREFIX + msg._id;
|
|
182
|
+
messageProvider.onClose(fullId, callback);
|
|
183
|
+
} else {
|
|
184
|
+
if (_messages[id]) {
|
|
185
|
+
_messages[id].onCloseTrigger = callback;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Show a generic message
|
|
192
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
193
|
+
* @name generic
|
|
194
|
+
* @method
|
|
195
|
+
* @memberof module:Messages#
|
|
196
|
+
* @param {String} title Sets the title text of the message.
|
|
197
|
+
* @param {String} body The main content of the message.
|
|
198
|
+
* @param {Object} options Message Options
|
|
199
|
+
* @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
|
|
200
|
+
* @param {Boolean} options.fadeout Toggles the fade away on the message
|
|
201
|
+
* @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
|
|
202
|
+
* @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
|
|
203
|
+
* @returns {String} The id to be used when clearing the message
|
|
204
|
+
* @example
|
|
205
|
+
* //create a message
|
|
206
|
+
* var message = AP.messages.generic('title', 'generic message example');
|
|
207
|
+
*/
|
|
208
|
+
generic: messageModule('generic'),
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Show an error message
|
|
212
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
213
|
+
* @name error
|
|
214
|
+
* @method
|
|
215
|
+
* @memberof module:Messages#
|
|
216
|
+
* @param {String} title Sets the title text of the message.
|
|
217
|
+
* @param {String} body The main content of the message.
|
|
218
|
+
* @param {Object} options Message Options
|
|
219
|
+
* @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
|
|
220
|
+
* @param {Boolean} options.fadeout Toggles the fade away on the message
|
|
221
|
+
* @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
|
|
222
|
+
* @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
|
|
223
|
+
* @returns {String} The id to be used when clearing the message
|
|
224
|
+
* @example
|
|
225
|
+
* //create a message
|
|
226
|
+
* var message = AP.messages.error('title', 'error message example');
|
|
227
|
+
*/
|
|
228
|
+
error: messageModule('error'),
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Show a warning message
|
|
232
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
233
|
+
* @name warning
|
|
234
|
+
* @method
|
|
235
|
+
* @memberof module:Messages#
|
|
236
|
+
* @param {String} title Sets the title text of the message.
|
|
237
|
+
* @param {String} body The main content of the message.
|
|
238
|
+
* @param {Object} options Message Options
|
|
239
|
+
* @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
|
|
240
|
+
* @param {Boolean} options.fadeout Toggles the fade away on the message
|
|
241
|
+
* @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
|
|
242
|
+
* @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
|
|
243
|
+
* @returns {String} The id to be used when clearing the message
|
|
244
|
+
* @example
|
|
245
|
+
* //create a message
|
|
246
|
+
* var message = AP.messages.warning('title', 'warning message example');
|
|
247
|
+
*/
|
|
248
|
+
warning: messageModule('warning'),
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Show a success message
|
|
252
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
253
|
+
* @name success
|
|
254
|
+
* @method
|
|
255
|
+
* @memberof module:Messages#
|
|
256
|
+
* @param {String} title Sets the title text of the message.
|
|
257
|
+
* @param {String} body The main content of the message.
|
|
258
|
+
* @param {Object} options Message Options
|
|
259
|
+
* @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
|
|
260
|
+
* @param {Boolean} options.fadeout Toggles the fade away on the message
|
|
261
|
+
* @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
|
|
262
|
+
* @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
|
|
263
|
+
* @returns {String} The id to be used when clearing the message
|
|
264
|
+
* @example
|
|
265
|
+
* //create a message
|
|
266
|
+
* var message = AP.messages.success('title', 'success message example');
|
|
267
|
+
*/
|
|
268
|
+
success: messageModule('success'),
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Show an info message
|
|
272
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
273
|
+
* @name info
|
|
274
|
+
* @method
|
|
275
|
+
* @memberof module:Messages#
|
|
276
|
+
* @param {String} title Sets the title text of the message.
|
|
277
|
+
* @param {String} body The main content of the message.
|
|
278
|
+
* @param {Object} options Message Options
|
|
279
|
+
* @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
|
|
280
|
+
* @param {Boolean} options.fadeout Toggles the fade away on the message
|
|
281
|
+
* @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
|
|
282
|
+
* @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
|
|
283
|
+
* @returns {String} The id to be used when clearing the message
|
|
284
|
+
* @example
|
|
285
|
+
* //create a message
|
|
286
|
+
* var message = AP.messages.info('title', 'info message example');
|
|
287
|
+
*/
|
|
288
|
+
info: messageModule('info'),
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Show a hint message
|
|
292
|
+
* @deprecated after August 2017 | Please use the Flag module instead.
|
|
293
|
+
* @name hint
|
|
294
|
+
* @method
|
|
295
|
+
* @memberof module:Messages#
|
|
296
|
+
* @param {String} title Sets the title text of the message.
|
|
297
|
+
* @param {String} body The main content of the message.
|
|
298
|
+
* @param {Object} options Message Options
|
|
299
|
+
* @param {Boolean} options.closeable Adds a control allowing the user to close the message, removing it from the page.
|
|
300
|
+
* @param {Boolean} options.fadeout Toggles the fade away on the message
|
|
301
|
+
* @param {Number} options.delay Time to wait (in ms) before starting fadeout animation (ignored if fadeout==false)
|
|
302
|
+
* @param {Number} options.duration Fadeout animation duration in milliseconds (ignored if fadeout==false)
|
|
303
|
+
* @returns {String} The id to be used when clearing the message
|
|
304
|
+
* @example
|
|
305
|
+
* //create a message
|
|
306
|
+
* var message = AP.messages.hint('title', 'hint message example');
|
|
307
|
+
*/
|
|
308
|
+
hint: messageModule('hint')
|
|
309
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A JavaScript module which provides functions for general page modules.
|
|
3
|
+
* @module Page
|
|
4
|
+
*/
|
|
5
|
+
import util from '../util';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
/**
|
|
9
|
+
* Sets the title of the document when a full page iframe is loaded.
|
|
10
|
+
* @memberOf module:Page
|
|
11
|
+
* @method setTitle
|
|
12
|
+
* @param {String} title the title of the document to be set.
|
|
13
|
+
* @example
|
|
14
|
+
* AP.page.setTitle(title)
|
|
15
|
+
*/
|
|
16
|
+
setTitle: function (title, callback) {
|
|
17
|
+
callback = util.last(arguments);
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
callback._context.extension.options &&
|
|
21
|
+
callback._context.extension.options.isFullPage
|
|
22
|
+
) {
|
|
23
|
+
const productSuffix =
|
|
24
|
+
' - ' + util.guessProductFromModuleDefined(window.connectHost);
|
|
25
|
+
|
|
26
|
+
document.title = title + productSuffix;
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import util from '../util';
|
|
2
|
+
import $ from '../dollar';
|
|
3
|
+
import EventDispatcher from '../dispatchers/event_dispatcher';
|
|
4
|
+
import EventActions from '../actions/event_actions';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const TRIGGER_PERCENTAGE = 10; //% before scroll events are fired
|
|
8
|
+
let activeGeneralPageAddon;
|
|
9
|
+
let lastScrollEventTriggered; //top or bottom
|
|
10
|
+
|
|
11
|
+
EventDispatcher.register('iframe-bridge-established', function(data) {
|
|
12
|
+
if(data.extension.options.isFullPage) {
|
|
13
|
+
window.addEventListener('scroll', scrollEventHandler);
|
|
14
|
+
activeGeneralPageAddon = data.extension.id;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
EventDispatcher.register('iframe-destroyed', function(extension) {
|
|
19
|
+
removeScrollEvent();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
EventDispatcher.register('iframe-unload', function(extension) {
|
|
23
|
+
removeScrollEvent();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
function removeScrollEvent(){
|
|
27
|
+
window.removeEventListener('scroll', scrollEventHandler);
|
|
28
|
+
activeGeneralPageAddon = undefined;
|
|
29
|
+
lastScrollEventTriggered = undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function scrollEventHandler(){
|
|
33
|
+
var documentHeight = document.documentElement.scrollHeight;
|
|
34
|
+
var windowHeight = window.innerHeight;
|
|
35
|
+
|
|
36
|
+
var boundary = documentHeight * (TRIGGER_PERCENTAGE/100);
|
|
37
|
+
if(window.pageYOffset <= boundary) {
|
|
38
|
+
triggerEvent('nearTop');
|
|
39
|
+
} else if((windowHeight + window.pageYOffset + boundary) >= documentHeight) {
|
|
40
|
+
triggerEvent('nearBottom');
|
|
41
|
+
} else {
|
|
42
|
+
lastScrollEventTriggered = undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function triggerEvent(type) {
|
|
47
|
+
if(lastScrollEventTriggered === type) {
|
|
48
|
+
return; // only once per scroll.
|
|
49
|
+
}
|
|
50
|
+
EventActions.broadcast('scroll.' + type, {id: activeGeneralPageAddon}, {});
|
|
51
|
+
lastScrollEventTriggered = type;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Enables apps to get and set the scroll position.
|
|
56
|
+
* @exports Scroll-position
|
|
57
|
+
*/
|
|
58
|
+
export default {
|
|
59
|
+
/**
|
|
60
|
+
* Gets the scroll position relative to the browser viewport
|
|
61
|
+
*
|
|
62
|
+
* @param callback {Function} callback to pass the scroll position
|
|
63
|
+
* @noDemo
|
|
64
|
+
* @example
|
|
65
|
+
* AP.scrollPosition.getPosition(function(obj) { console.log(obj); });
|
|
66
|
+
*/
|
|
67
|
+
getPosition: function (callback) {
|
|
68
|
+
callback = util.last(arguments);
|
|
69
|
+
// scrollPosition.getPosition is only available for general-pages
|
|
70
|
+
if (callback._context.extension.options.isFullPage) {
|
|
71
|
+
var $el = util.getIframeByExtensionId(callback._context.extension_id);
|
|
72
|
+
var offset = $el.offset();
|
|
73
|
+
var $window = $(window);
|
|
74
|
+
|
|
75
|
+
callback({
|
|
76
|
+
scrollY: $window.scrollTop() - offset.top,
|
|
77
|
+
scrollX: $window.scrollLeft() - offset.left,
|
|
78
|
+
width: window.innerWidth,
|
|
79
|
+
height: window.innerHeight
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Sets the vertical scroll position relative to the iframe
|
|
85
|
+
*
|
|
86
|
+
* @param y {Number} vertical offset position
|
|
87
|
+
* @param callback {Function} callback to pass the scroll position
|
|
88
|
+
* @noDemo
|
|
89
|
+
* @example
|
|
90
|
+
* AP.scrollPosition.setVerticalPosition(30, function(obj) { console.log(obj); });
|
|
91
|
+
*/
|
|
92
|
+
setVerticalPosition: function(y, callback) {
|
|
93
|
+
callback = util.last(arguments);
|
|
94
|
+
if (callback._context.extension.options && callback._context.extension.options.isFullPage) {
|
|
95
|
+
var $el = util.getIframeByExtensionId(callback._context.extension_id);
|
|
96
|
+
var offset = $el.offset();
|
|
97
|
+
if(typeof y === 'number') {
|
|
98
|
+
document.documentElement.scrollTop = offset.top + y;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import simpleXDM from 'simple-xdm/host';
|
|
2
|
+
import { getGlobalTheme, ThemeMutationObserver, CURRENT_SURFACE_CSS_VAR } from '@atlaskit/tokens';
|
|
3
|
+
|
|
4
|
+
import util from '../util';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const getPluginFeatureFlags = () => ({
|
|
8
|
+
// Add feature flags sent to the plugin on theming bootstrap here
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const getSurfaceValue = (extension_id) => {
|
|
12
|
+
const iframe = document.getElementById(extension_id);
|
|
13
|
+
if (!iframe) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const styles = getComputedStyle(iframe);
|
|
18
|
+
const currentSurface = styles.getPropertyValue(CURRENT_SURFACE_CSS_VAR);
|
|
19
|
+
const raised = styles.getPropertyValue('--ds-surface-raised');
|
|
20
|
+
const overlay = styles.getPropertyValue('--ds-surface-overlay');
|
|
21
|
+
|
|
22
|
+
if (currentSurface === raised) {
|
|
23
|
+
return 'raised';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (currentSurface === overlay) {
|
|
27
|
+
return 'overlay';
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Broadcasts the new theme to all plugins.
|
|
33
|
+
* @typedef {import("@atlaskit/tokens").ThemeState} ThemeState
|
|
34
|
+
* @param newTheme {ThemeState}
|
|
35
|
+
*/
|
|
36
|
+
function broadcastThemeChange(newTheme) {
|
|
37
|
+
const featureFlags = getPluginFeatureFlags();
|
|
38
|
+
if (ThemingModuleState.extensionIds.length) {
|
|
39
|
+
ThemingModuleState.extensionIds.forEach((id) => {
|
|
40
|
+
const surface = getSurfaceValue(id);
|
|
41
|
+
simpleXDM.broadcast(
|
|
42
|
+
'theme_changed',
|
|
43
|
+
{ id },
|
|
44
|
+
{ newTheme, featureFlags, surface }
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Exported only for testing
|
|
51
|
+
export const ThemingModuleState = {
|
|
52
|
+
/**
|
|
53
|
+
* An array containing extension ID's for each app that has enabled theming.
|
|
54
|
+
* Theme change events are only sent to apps listed in this array.
|
|
55
|
+
*/
|
|
56
|
+
extensionIds: [],
|
|
57
|
+
/**
|
|
58
|
+
* Observer that will only trigger on changes to data-theme on the root html element.
|
|
59
|
+
* Dispatches the new theme to all plugins when the theme changes.
|
|
60
|
+
*/
|
|
61
|
+
themeObserver: new ThemeMutationObserver((newTheme) => {
|
|
62
|
+
broadcastThemeChange(newTheme);
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Only functions that make up the public ACJS theming API should be exported on this object.
|
|
67
|
+
const ThemingModule = {
|
|
68
|
+
/**
|
|
69
|
+
* Starts observing theme changes and dispatches the `theme_initialized` event to the plugin.
|
|
70
|
+
* This event causes the plugin to react when the host's theme changes.
|
|
71
|
+
*/
|
|
72
|
+
initializeTheming() {
|
|
73
|
+
const callback = util.last(arguments);
|
|
74
|
+
const forceNoCleanup = arguments.length === 1 ? false : arguments[0];
|
|
75
|
+
|
|
76
|
+
if (!callback || !callback._context || !callback._context.extension_id) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const { _context: { extension_id } } = callback;
|
|
81
|
+
|
|
82
|
+
if (!extension_id) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const initialTheme = getGlobalTheme();
|
|
87
|
+
const surface = getSurfaceValue(extension_id);
|
|
88
|
+
const featureFlags = getPluginFeatureFlags();
|
|
89
|
+
|
|
90
|
+
// The theme_initialized event should be broadcast even if it has previously been initialized by the plugin.
|
|
91
|
+
// This is to ensure that theming works in multi-page apps after navigating to a different page.
|
|
92
|
+
// The reason is that isThemingInitialized on the plugin side starts as `false` when all.js is loaded.
|
|
93
|
+
// The theme_initialized event is needed to change it to `true` for any new page.
|
|
94
|
+
simpleXDM.broadcast(
|
|
95
|
+
'theme_initialized',
|
|
96
|
+
{ id: extension_id },
|
|
97
|
+
{ initialTheme, featureFlags, surface, forceNoCleanup }
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
if (!ThemingModuleState.extensionIds.includes(extension_id)) {
|
|
101
|
+
ThemingModuleState.extensionIds.push(extension_id);
|
|
102
|
+
ThemingModuleState.themeObserver.observe(document.documentElement);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
/**
|
|
106
|
+
* This has to be part of the API so the plugin can notify us when theme loading is finished.
|
|
107
|
+
* The underscore indicates it should not be called by apps directly.
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
_finishedInitTheming() {
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export default ThemingModule;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import util from '../util';
|
|
2
|
+
|
|
3
|
+
class ExtensionConfigurationOptionsStore {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.store = {};
|
|
6
|
+
}
|
|
7
|
+
set(obj, val) {
|
|
8
|
+
if(val) {
|
|
9
|
+
var toSet = {};
|
|
10
|
+
toSet[obj] = val;
|
|
11
|
+
} else {
|
|
12
|
+
toSet = obj;
|
|
13
|
+
}
|
|
14
|
+
util.extend(this.store, toSet);
|
|
15
|
+
}
|
|
16
|
+
get(key) {
|
|
17
|
+
if(key) {
|
|
18
|
+
return this.store[key];
|
|
19
|
+
}
|
|
20
|
+
return util.extend({}, this.store); //clone
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default new ExtensionConfigurationOptionsStore();
|
package/src/host/util.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import $ from './dollar';
|
|
2
|
+
|
|
3
|
+
function escapeSelector(s) {
|
|
4
|
+
if (!s) {
|
|
5
|
+
throw new Error('No selector to escape');
|
|
6
|
+
}
|
|
7
|
+
return s.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, '\\$&');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function stringToDimension(value) {
|
|
11
|
+
var percent = false;
|
|
12
|
+
var unit = 'px';
|
|
13
|
+
|
|
14
|
+
if(typeof value === 'string') {
|
|
15
|
+
percent = value.indexOf('%') === value.length - 1;
|
|
16
|
+
value = parseInt(value, 10);
|
|
17
|
+
if (percent) {
|
|
18
|
+
unit = '%';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if(!isNaN(value)) {
|
|
23
|
+
return value + unit;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getIframeByExtensionId(id) {
|
|
28
|
+
return $('iframe#' + escapeSelector(id));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function first(arr, numb){
|
|
32
|
+
if(numb) {
|
|
33
|
+
return arr.slice(0, numb);
|
|
34
|
+
}
|
|
35
|
+
return arr[0];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function last(arr){
|
|
39
|
+
return arr[arr.length - 1];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function pick(obj, keys) {
|
|
43
|
+
if(typeof obj !== 'object') {
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
return Object.keys(obj)
|
|
47
|
+
.filter((key) => keys.indexOf(key) >= 0)
|
|
48
|
+
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function debounce (fn, wait) {
|
|
52
|
+
var timeout;
|
|
53
|
+
return function () {
|
|
54
|
+
var ctx = this;
|
|
55
|
+
var args = [].slice.call(arguments);
|
|
56
|
+
function later() {
|
|
57
|
+
timeout = null;
|
|
58
|
+
fn.apply(ctx, args);
|
|
59
|
+
}
|
|
60
|
+
if (timeout) {
|
|
61
|
+
clearTimeout(timeout);
|
|
62
|
+
}
|
|
63
|
+
timeout = setTimeout(later, wait || 50);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function isSupported(domElem, attr, value, defaultValue) {
|
|
68
|
+
if (domElem && domElem[attr] && domElem[attr].supports) {
|
|
69
|
+
return domElem[attr].supports(value);
|
|
70
|
+
} else {
|
|
71
|
+
return defaultValue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function guessProductFromModuleDefined(connectHost) {
|
|
76
|
+
if (connectHost.isModuleDefined('jira')) {
|
|
77
|
+
return 'Jira';
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (connectHost.isModuleDefined('confluence')) {
|
|
81
|
+
return 'Confluence';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return '';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default {
|
|
88
|
+
escapeSelector,
|
|
89
|
+
stringToDimension,
|
|
90
|
+
getIframeByExtensionId,
|
|
91
|
+
first,
|
|
92
|
+
last,
|
|
93
|
+
pick,
|
|
94
|
+
debounce,
|
|
95
|
+
isSupported,
|
|
96
|
+
extend: Object.assign,
|
|
97
|
+
guessProductFromModuleDefined,
|
|
98
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function getAccessNarrowingSpaceContext(extension) {
|
|
2
|
+
if (extension?.options && AJS?.Meta?.get) {
|
|
3
|
+
const productContext = {
|
|
4
|
+
...(extension.options.productContext || {})
|
|
5
|
+
};
|
|
6
|
+
if (AJS.Meta.get('space-key')) {
|
|
7
|
+
productContext['an.spaceKey'] = AJS.Meta.get('space-key');
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
...extension,
|
|
11
|
+
options: {
|
|
12
|
+
...extension.options,
|
|
13
|
+
productContext,
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return extension;
|
|
18
|
+
}
|