@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,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DO NOT INCLUDE ME IN THE PUBLIC DOCUMENTATION
|
|
3
|
+
* there is no AUI implementation of this
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import HostApi from '../host-api';
|
|
7
|
+
import util from '../util';
|
|
8
|
+
import EventDispatcher from '../dispatchers/event_dispatcher';
|
|
9
|
+
import EventActions from '../actions/event_actions';
|
|
10
|
+
import DropdownActions from '../actions/dropdown_actions';
|
|
11
|
+
|
|
12
|
+
var dropdownProvider;
|
|
13
|
+
|
|
14
|
+
function buildListItem(listItem) {
|
|
15
|
+
let finishedListItem = {};
|
|
16
|
+
if (typeof listItem === 'string') {
|
|
17
|
+
finishedListItem.content = listItem;
|
|
18
|
+
} else if (listItem.text && typeof listItem.text === 'string') {
|
|
19
|
+
finishedListItem.content = listItem.text;
|
|
20
|
+
if(typeof listItem.disabled === 'boolean') {
|
|
21
|
+
finishedListItem.disabled = listItem.disabled;
|
|
22
|
+
}
|
|
23
|
+
if(typeof listItem.itemId !== 'undefined') {
|
|
24
|
+
finishedListItem.itemId = listItem.itemId;
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
throw new Error('Unknown dropdown list item format.');
|
|
28
|
+
}
|
|
29
|
+
return finishedListItem;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function moduleListToApiList(list) {
|
|
33
|
+
return list.map((item) => {
|
|
34
|
+
if (item.list && Array.isArray(item.list)) {
|
|
35
|
+
let returnval = {
|
|
36
|
+
heading: item.heading
|
|
37
|
+
}
|
|
38
|
+
returnval.items = item.list.map((listitem) => {
|
|
39
|
+
return buildListItem(listitem);
|
|
40
|
+
});
|
|
41
|
+
return returnval;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @class DropdownItem
|
|
48
|
+
* A single item in a dropdown menu can be a string or an object
|
|
49
|
+
* @param {String} itemId The id of a single dropdown item
|
|
50
|
+
* @param {String} text The text to display in the dropdown item
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @module Dropdown
|
|
55
|
+
* @description Dropdown menu that can go outside the iframe bounds.
|
|
56
|
+
* @example
|
|
57
|
+
* // create a dropdown menu with 1 section and 2 items
|
|
58
|
+
* var mydropdown = {
|
|
59
|
+
* dropdownId: 'my-dropdown',
|
|
60
|
+
* list: [{
|
|
61
|
+
* heading: 'section heading',
|
|
62
|
+
* list: [
|
|
63
|
+
* {text: 'one'},
|
|
64
|
+
* {text: 'two'}
|
|
65
|
+
* ]
|
|
66
|
+
* }]
|
|
67
|
+
* };
|
|
68
|
+
*
|
|
69
|
+
* AP.events.on('dropdown-item-selected', (data) =>{
|
|
70
|
+
* console.log('dropdown item selected', data.dropdownId, data.item);
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* AP.dropdown.create(mydropdown);
|
|
74
|
+
* // button is an element in our document that triggered the dropdown
|
|
75
|
+
* let rect = document.querySelector('button').getBoundingClientRect();
|
|
76
|
+
* AP.dropdown.showAt('my-dropdown', rect.left, rect.top, rect.width);
|
|
77
|
+
*
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
export default {
|
|
81
|
+
/**
|
|
82
|
+
* @name create
|
|
83
|
+
* @method
|
|
84
|
+
* @description Creates a new dropdown.
|
|
85
|
+
* @param {Object} options Options of the dropdown.
|
|
86
|
+
* @param {String} options.dropdownId A unique identifier for the dropdown that will be referenced in events.
|
|
87
|
+
* @param {String} options.list An array containing dropdown items {Dropdown~DropdownItem}
|
|
88
|
+
* @example
|
|
89
|
+
* // create a dropdown menu with 1 section and 2 items
|
|
90
|
+
* var mydropdown = {
|
|
91
|
+
* dropdownId: 'my-dropdown',
|
|
92
|
+
* list: [{
|
|
93
|
+
* heading: 'section heading',
|
|
94
|
+
* list: [
|
|
95
|
+
* {text: 'one'},
|
|
96
|
+
* {text: 'two'}
|
|
97
|
+
* ]
|
|
98
|
+
* }]
|
|
99
|
+
* };
|
|
100
|
+
*
|
|
101
|
+
* AP.dropdown.create(mydropdown);
|
|
102
|
+
*/
|
|
103
|
+
create(options, callback) {
|
|
104
|
+
callback = util.last(arguments);
|
|
105
|
+
if (typeof options !== 'object') {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
109
|
+
const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
|
|
110
|
+
if (dropdownProvider) {
|
|
111
|
+
const dropdownGroups = moduleListToApiList(options.list);
|
|
112
|
+
const dropdownProviderOptions = {
|
|
113
|
+
dropdownId: options.dropdownId,
|
|
114
|
+
dropdownGroups: dropdownGroups,
|
|
115
|
+
dropdownItemNotifier: (data) => {
|
|
116
|
+
DropdownActions.itemSelected(data.dropdownId, data.item, callback._context.extension);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
dropdownProvider.create(dropdownProviderOptions, callback._context);
|
|
120
|
+
return dropdownProviderOptions;
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @name showAt
|
|
126
|
+
* @method
|
|
127
|
+
* @description Displays a created dropdown menu.
|
|
128
|
+
* @param {String} dropdownId Id used when creating the dropdown
|
|
129
|
+
* @param {String} x x position from the edge of your iframe to display
|
|
130
|
+
* @param {String} y y position from the edge of your iframe to display
|
|
131
|
+
* @param {String} width Optionally enforce a width for the dropdown menu
|
|
132
|
+
* @example
|
|
133
|
+
* // create a dropdown menu with 1 section and 2 items
|
|
134
|
+
* var mydropdown = {
|
|
135
|
+
* dropdownId: 'my-dropdown',
|
|
136
|
+
* list: [{
|
|
137
|
+
* list:['one', 'two']
|
|
138
|
+
* }]
|
|
139
|
+
* };
|
|
140
|
+
*
|
|
141
|
+
* AP.dropdown.create(mydropdown);
|
|
142
|
+
* // Get the button that activated the dropdown
|
|
143
|
+
* let rect = document.querySelector('button').getBoundingClientRect();
|
|
144
|
+
* AP.dropdown.showAt('my-dropdown', rect.left, rect.top, rect.width);
|
|
145
|
+
*/
|
|
146
|
+
showAt(dropdownId, x, y, width) {
|
|
147
|
+
let callback = util.last(arguments);
|
|
148
|
+
let rect = {left: 0, top: 0};
|
|
149
|
+
let iframe = document.getElementById(callback._context.extension_id);
|
|
150
|
+
if(iframe) {
|
|
151
|
+
rect = iframe.getBoundingClientRect();
|
|
152
|
+
} else {
|
|
153
|
+
console.error('ACJS: no iframe found for dropdown');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
157
|
+
const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
|
|
158
|
+
if (dropdownProvider) {
|
|
159
|
+
const dropdownProviderArgs = {
|
|
160
|
+
dropdownId: dropdownId,
|
|
161
|
+
x: x,
|
|
162
|
+
y: y,
|
|
163
|
+
width: width
|
|
164
|
+
};
|
|
165
|
+
dropdownProvider.showAt(dropdownProviderArgs, {
|
|
166
|
+
iframeDimensions: rect,
|
|
167
|
+
onItemSelection: (dropdownId, item) => {
|
|
168
|
+
DropdownActions.itemSelected(dropdownId, item, callback._context.extension);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
/**
|
|
174
|
+
* @name hide
|
|
175
|
+
* @method
|
|
176
|
+
* @description Hide a dropdown menu
|
|
177
|
+
* @param {String} dropdownId The id of the dropdown to hide
|
|
178
|
+
* @example
|
|
179
|
+
* AP.dropdown.create('my-dropdown');
|
|
180
|
+
* AP.dropdown.hide('my-dropdown');
|
|
181
|
+
*/
|
|
182
|
+
hide(id) {
|
|
183
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
184
|
+
const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
|
|
185
|
+
if (dropdownProvider) {
|
|
186
|
+
dropdownProvider.hide(id);
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @name itemDisable
|
|
192
|
+
* @method
|
|
193
|
+
* @description Disable an item in the dropdown menu
|
|
194
|
+
* @param {String} dropdownId The id of the dropdown
|
|
195
|
+
* @param {String} itemId The dropdown item to disable
|
|
196
|
+
* @example
|
|
197
|
+
* AP.dropdown.create('my-dropdown');
|
|
198
|
+
* AP.dropdown.itemDisable('my-dropdown', 'item-id');
|
|
199
|
+
*/
|
|
200
|
+
itemDisable(dropdownId, itemId) {
|
|
201
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
202
|
+
const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
|
|
203
|
+
if (dropdownProvider) {
|
|
204
|
+
dropdownProvider.itemDisable(dropdownId, itemId);
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @name itemEnable
|
|
210
|
+
* @method
|
|
211
|
+
* @description Hide a dropdown menu
|
|
212
|
+
* @param {String} dropdownId The id of the dropdown
|
|
213
|
+
* @param {String} itemId The id of the dropdown item to enable
|
|
214
|
+
* @example
|
|
215
|
+
* AP.dropdown.create('my-dropdown');
|
|
216
|
+
* AP.dropdown.itemEnable('my-dropdown', 'item-id');
|
|
217
|
+
*/
|
|
218
|
+
itemEnable(dropdownId, itemId) {
|
|
219
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
220
|
+
const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
|
|
221
|
+
if (dropdownProvider) {
|
|
222
|
+
dropdownProvider.itemEnable(dropdownId, itemId);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
EventDispatcher.register('dropdown-item-selected', (data) => {
|
|
230
|
+
EventActions.broadcast('dropdown-item-selected', {
|
|
231
|
+
addon_key: data.extension.addon_key,
|
|
232
|
+
key: data.extension.key
|
|
233
|
+
}, {
|
|
234
|
+
dropdownId: data.id,
|
|
235
|
+
item: data.item
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// friendly unload with connectHost.destroy
|
|
240
|
+
EventDispatcher.register('iframe-destroyed', (data) => {
|
|
241
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
242
|
+
const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
|
|
243
|
+
if (dropdownProvider) {
|
|
244
|
+
dropdownProvider.destroyByExtension(data.extension.extension_id);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// unfriendly unload by removing the iframe from the DOM
|
|
249
|
+
EventDispatcher.register('after:iframe-unload', (data) => {
|
|
250
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
251
|
+
const dropdownProvider = frameworkAdaptor.getProviderByModuleName('dropdown');
|
|
252
|
+
if (dropdownProvider) {
|
|
253
|
+
dropdownProvider.destroyByExtension(data.extension.extension_id);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import EnvActions from '../actions/env_actions';
|
|
2
|
+
import EventDispatcher from '../dispatchers/event_dispatcher';
|
|
3
|
+
import util from '../util';
|
|
4
|
+
import ModuleProviders from '../module-providers';
|
|
5
|
+
import {Flags} from '../utils/feature-flag';
|
|
6
|
+
|
|
7
|
+
var debounce = util.debounce;
|
|
8
|
+
var resizeFuncHolder = {};
|
|
9
|
+
// ignore resize events for iframes that use sizeToParent
|
|
10
|
+
var ignoreResizeForExtension = [];
|
|
11
|
+
var sizeToParentExtension = {};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Enables apps to resize their iframes.
|
|
15
|
+
* @exports iframe
|
|
16
|
+
*/
|
|
17
|
+
export default {
|
|
18
|
+
/**
|
|
19
|
+
* Get the location of the current page of the host product.
|
|
20
|
+
*
|
|
21
|
+
* @param {Function} callback function (location) {...} The callback to pass the location to.
|
|
22
|
+
* @example
|
|
23
|
+
* AP.getLocation(function(location){
|
|
24
|
+
* alert(location);
|
|
25
|
+
* });
|
|
26
|
+
*/
|
|
27
|
+
getLocation: function(callback) {
|
|
28
|
+
callback = util.last(arguments);
|
|
29
|
+
let pageLocationProvider = ModuleProviders.getProvider('get-location');
|
|
30
|
+
if (typeof pageLocationProvider === 'function') {
|
|
31
|
+
callback(pageLocationProvider());
|
|
32
|
+
} else {
|
|
33
|
+
callback(window.location.href);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
/**
|
|
37
|
+
* Resize the iframe to a width and height.
|
|
38
|
+
*
|
|
39
|
+
* Only content within an element with the class `ac-content` is resized automatically.
|
|
40
|
+
* Content without this identifier is sized according to the `body` element, and
|
|
41
|
+
* is *not* dynamically resized. The recommended DOM layout for your app is:
|
|
42
|
+
*
|
|
43
|
+
* ``` html
|
|
44
|
+
* <div class="ac-content">
|
|
45
|
+
* <p>Hello World</p>
|
|
46
|
+
* <div id="your-id-here">
|
|
47
|
+
* <p>App content goes here</p>
|
|
48
|
+
* </div>
|
|
49
|
+
*
|
|
50
|
+
* ...this area reserved for the resize sensor divs
|
|
51
|
+
* </div>
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* The resize sensor div is added on the iframe's [load event](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event).
|
|
55
|
+
* Removing the `ac-content` element after this, prevents resizing from working correctly.
|
|
56
|
+
*
|
|
57
|
+
* This method cannot be used in dialogs.
|
|
58
|
+
*
|
|
59
|
+
* @method
|
|
60
|
+
* @param {String} width The desired width in pixels or percentage.
|
|
61
|
+
* @param {String} height The desired height in pixels or percentage.
|
|
62
|
+
* @example
|
|
63
|
+
* AP.resize('400','400');
|
|
64
|
+
*/
|
|
65
|
+
resize: function(width, height, callback) {
|
|
66
|
+
callback = util.last(arguments);
|
|
67
|
+
let addon = ModuleProviders.getProvider('addon');
|
|
68
|
+
if (addon) {
|
|
69
|
+
addon.resize(width, height, callback._context);
|
|
70
|
+
} else {
|
|
71
|
+
var iframeId = callback._context.extension.id;
|
|
72
|
+
var options = callback._context.extension.options;
|
|
73
|
+
if (ignoreResizeForExtension.indexOf(iframeId) !== -1 || (options && options.isDialog)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!resizeFuncHolder[iframeId]) {
|
|
78
|
+
resizeFuncHolder[iframeId] = debounce(function(dwidth, dheight, dcallback) {
|
|
79
|
+
EnvActions.iframeResize(dwidth, dheight, dcallback._context);
|
|
80
|
+
}, 50);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
resizeFuncHolder[iframeId](width, height, callback);
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* Resize the iframe so that it takes up the entire page.
|
|
89
|
+
*
|
|
90
|
+
* This method is only available for general page modules.
|
|
91
|
+
*
|
|
92
|
+
* @method
|
|
93
|
+
* @example
|
|
94
|
+
* AP.sizeToParent();
|
|
95
|
+
*/
|
|
96
|
+
sizeToParent: debounce(function(hideFooter, callback) {
|
|
97
|
+
callback = util.last(arguments);
|
|
98
|
+
let addon = ModuleProviders.getProvider('addon');
|
|
99
|
+
if (addon) {
|
|
100
|
+
addon.sizeToParent(hideFooter, callback._context);
|
|
101
|
+
} else {
|
|
102
|
+
// sizeToParent is only available for general-pages
|
|
103
|
+
if (callback._context.extension.options.isFullPage) {
|
|
104
|
+
// This adds border between the iframe and the page footer as the connect addon has scrolling content and can't do this
|
|
105
|
+
util.getIframeByExtensionId(callback._context.extension_id).addClass('full-size-general-page');
|
|
106
|
+
util.getIframeByExtensionId(callback._context.extension_id).addClass('sized-to-parent');
|
|
107
|
+
EnvActions.sizeToParent(callback._context.extension_id, hideFooter);
|
|
108
|
+
sizeToParentExtension[callback._context.extension_id] = { hideFooter: hideFooter };
|
|
109
|
+
} else {
|
|
110
|
+
// This is only here to support integration testing
|
|
111
|
+
// see com.atlassian.plugin.connect.test.pageobjects.RemotePage#isNotFullSize()
|
|
112
|
+
util.getIframeByExtensionId(callback._context.extension_id).addClass('full-size-general-page-fail');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
/**
|
|
117
|
+
* Hide the footer.
|
|
118
|
+
*
|
|
119
|
+
* @method
|
|
120
|
+
* @param {boolean} hideFooter Whether the footer should be hidden.
|
|
121
|
+
* @ignore
|
|
122
|
+
*/
|
|
123
|
+
hideFooter: function(hideFooter) {
|
|
124
|
+
if (hideFooter) {
|
|
125
|
+
EnvActions.hideFooter(hideFooter);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const _removeIframeReferenceAfterUnloadAndDestroyed = (extensionId) => {
|
|
131
|
+
delete resizeFuncHolder[extensionId];
|
|
132
|
+
delete sizeToParentExtension[extensionId];
|
|
133
|
+
if (ignoreResizeForExtension.indexOf(extensionId) !== -1) {
|
|
134
|
+
ignoreResizeForExtension.splice(ignoreResizeForExtension.indexOf(extensionId), 1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
EventDispatcher.register('host-window-resize', data => {
|
|
139
|
+
Object.getOwnPropertyNames(sizeToParentExtension).forEach(extensionId => {
|
|
140
|
+
EnvActions.sizeToParent(extensionId, sizeToParentExtension[extensionId].hideFooter);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
EventDispatcher.register('after:iframe-unload', function(data) {
|
|
145
|
+
_removeIframeReferenceAfterUnloadAndDestroyed(data.extension.id);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
EventDispatcher.register('after:iframe-destroyed', function(data) {
|
|
149
|
+
_removeIframeReferenceAfterUnloadAndDestroyed(data.extension.extension.id);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
EventDispatcher.register('before:iframe-size-to-parent', function(data) {
|
|
153
|
+
if (ignoreResizeForExtension.indexOf(data.extensionId) === -1) {
|
|
154
|
+
ignoreResizeForExtension.push(data.extensionId);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import EventActions from '../actions/event_actions';
|
|
2
|
+
import Util from '../util';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
emit: function(name, ...args) {
|
|
6
|
+
var callback = Util.last(args);
|
|
7
|
+
args = Util.first(args, -1);
|
|
8
|
+
EventActions.broadcast(name, {
|
|
9
|
+
addon_key: callback._context.extension.addon_key
|
|
10
|
+
}, args);
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
emitPublic: function(name, ...args) {
|
|
14
|
+
var callback = Util.last(args);
|
|
15
|
+
var extension = callback._context.extension;
|
|
16
|
+
args = Util.first(args, -1);
|
|
17
|
+
EventActions.broadcastPublic(name, args, extension);
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
emitToDataProvider: function(...args) {
|
|
21
|
+
var callback = Util.last(args);
|
|
22
|
+
var extension = callback._context.extension;
|
|
23
|
+
args = Util.first(args, -1);
|
|
24
|
+
EventActions.broadcast('dataProviderEvent', {
|
|
25
|
+
addon_key: callback._context.extension.addon_key
|
|
26
|
+
}, args);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flags are the primary method for providing system feedback in the product user interface. Messages include notifications of various kinds: alerts, confirmations, notices, warnings, info and errors.
|
|
3
|
+
* @module Flag
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import HostApi from '../host-api';
|
|
7
|
+
import EventDispatcher from '../dispatchers/event_dispatcher';
|
|
8
|
+
import FlagActions from '../actions/flag_actions';
|
|
9
|
+
import FlagComponent from '../components/flag';
|
|
10
|
+
import util from '../util';
|
|
11
|
+
import EventActions from '../actions/event_actions';
|
|
12
|
+
import ModuleProviders from '../module-providers';
|
|
13
|
+
import getBooleanFeatureFlag from '../utils/feature-flag';
|
|
14
|
+
|
|
15
|
+
const _flags = {};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @class Flag~Flag
|
|
19
|
+
* @description A flag object created by the [AP.flag]{@link module:Flag} module.
|
|
20
|
+
* @example
|
|
21
|
+
* // complete flag API example:
|
|
22
|
+
* var outFlagId;
|
|
23
|
+
* var flag = AP.flag.create({
|
|
24
|
+
* title: 'Successfully created a flag.',
|
|
25
|
+
* body: 'This is a flag.',
|
|
26
|
+
* type: 'info',
|
|
27
|
+
* actions: {
|
|
28
|
+
* 'actionOne': 'action name'
|
|
29
|
+
* }
|
|
30
|
+
* }, function(identifier) {
|
|
31
|
+
* // Each flag will have a unique id. Save it for later.
|
|
32
|
+
* ourFlagId = identifier;
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // listen to flag events
|
|
36
|
+
* AP.events.on('flag.close', function(data) {
|
|
37
|
+
* // a flag was closed. data.flagIdentifier should match ourFlagId
|
|
38
|
+
* console.log('flag id: ', data.flagIdentifier);
|
|
39
|
+
* });
|
|
40
|
+
* AP.events.on('flag.action', function(data) {
|
|
41
|
+
* // a flag action was clicked. data.actionIdentifier will be 'actionOne'
|
|
42
|
+
* // data.flagIdentifier will equal ourFlagId
|
|
43
|
+
* console.log('flag id: ', data.flagIdentifier, 'flag action id', data.actionIdentifier);
|
|
44
|
+
* });
|
|
45
|
+
*/
|
|
46
|
+
class Flag {
|
|
47
|
+
constructor(options, callback) {
|
|
48
|
+
callback = util.last(arguments);
|
|
49
|
+
if(typeof options !== 'object') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const flagId = callback._id;
|
|
53
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
54
|
+
const flagProvider = frameworkAdaptor.getProviderByModuleName('flag');
|
|
55
|
+
if (flagProvider) {
|
|
56
|
+
let actions = [];
|
|
57
|
+
if (typeof options.actions === 'object') {
|
|
58
|
+
actions = Object.getOwnPropertyNames(options.actions).map(key => {
|
|
59
|
+
return {
|
|
60
|
+
actionKey: key,
|
|
61
|
+
actionText: options.actions[key],
|
|
62
|
+
executeAction: FlagActions.actionInvoked.bind(null, key, flagId)
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
let type = options.type || 'info';
|
|
67
|
+
let flagOptions = {
|
|
68
|
+
id: flagId,
|
|
69
|
+
title: options.title,
|
|
70
|
+
body: options.body,
|
|
71
|
+
actions: actions,
|
|
72
|
+
onClose: FlagActions.closed,
|
|
73
|
+
close: options.close,
|
|
74
|
+
type: type.toLowerCase()
|
|
75
|
+
};
|
|
76
|
+
this.flag = flagProvider.create(flagOptions);
|
|
77
|
+
let addonProvider = ModuleProviders.getProvider('addon');
|
|
78
|
+
if (addonProvider && addonProvider.registerUnmountCallback) {
|
|
79
|
+
addonProvider.registerUnmountCallback(this.close.bind(this), callback._context);
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
this.flag = FlagComponent.render({
|
|
83
|
+
type: options.type,
|
|
84
|
+
title: options.title,
|
|
85
|
+
body: AJS.escapeHtml(options.body),
|
|
86
|
+
actions: options.actions,
|
|
87
|
+
close: options.close,
|
|
88
|
+
id: flagId
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
FlagActions.open(this.flag.attr('id'));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.onTriggers= {};
|
|
95
|
+
this.extension = callback._context.extension;
|
|
96
|
+
_flags[callback._id] = this;
|
|
97
|
+
callback.call(null, callback._id);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @name close
|
|
102
|
+
* @memberof Flag~Flag
|
|
103
|
+
* @method
|
|
104
|
+
* @description Closes the Flag.
|
|
105
|
+
* @example
|
|
106
|
+
* // Display a nice green flag using the Flags JavaScript API.
|
|
107
|
+
* var flag = AP.flag.create({
|
|
108
|
+
* title: 'Successfully created a flag.',
|
|
109
|
+
* body: 'This is a flag.',
|
|
110
|
+
* type: 'info'
|
|
111
|
+
* });
|
|
112
|
+
*
|
|
113
|
+
* // Close the flag.
|
|
114
|
+
* flag.close()
|
|
115
|
+
*
|
|
116
|
+
*/
|
|
117
|
+
close() {
|
|
118
|
+
this.flag.close();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function invokeTrigger(id, eventName, data) {
|
|
123
|
+
if (_flags[id]) {
|
|
124
|
+
let extension = _flags[id].extension;
|
|
125
|
+
data = data || {};
|
|
126
|
+
data.flagIdentifier = id;
|
|
127
|
+
const targetSpec = { id: extension.id };
|
|
128
|
+
EventActions.broadcast(eventName, targetSpec, data);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
EventDispatcher.register('flag-closed', (data) => {
|
|
133
|
+
invokeTrigger(data.id, 'flag.close');
|
|
134
|
+
if (_flags[data.id]) {
|
|
135
|
+
delete _flags[data.id];
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
EventDispatcher.register('flag-action-invoked', (data) => {
|
|
140
|
+
invokeTrigger(data.id, 'flag.action', {actionIdentifier: data.actionId});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export default {
|
|
144
|
+
/**
|
|
145
|
+
* @name create
|
|
146
|
+
* @method
|
|
147
|
+
* @description Creates a new flag.
|
|
148
|
+
* @param {Object} options Options of the flag.
|
|
149
|
+
* @param {String} options.title The title text of the flag.
|
|
150
|
+
* @param {String} options.body The body text of the flag.
|
|
151
|
+
* @param {String} options.type=info Sets the type of the message. Valid options are "info", "success", "warning" and "error".
|
|
152
|
+
* @param {String} options.close The closing behaviour that this flag has. Valid options are "manual", and "auto".
|
|
153
|
+
* @param {Object} options.actions Map of {actionIdentifier: 'Action link text'} to add to the flag. The actionIdentifier will be passed to a 'flag.action' event if the link is clicked.
|
|
154
|
+
* @returns {Flag~Flag}
|
|
155
|
+
* @example
|
|
156
|
+
* // Display a nice green flag using the Flags JavaScript API.
|
|
157
|
+
* var flag = AP.flag.create({
|
|
158
|
+
* title: 'Successfully created a flag.',
|
|
159
|
+
* body: 'This is a flag.',
|
|
160
|
+
* type: 'success',
|
|
161
|
+
* actions: {
|
|
162
|
+
* 'actionkey': 'Click me'
|
|
163
|
+
* }
|
|
164
|
+
* });
|
|
165
|
+
*/
|
|
166
|
+
create: {
|
|
167
|
+
constructor: Flag,
|
|
168
|
+
close: Flag.prototype.close
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import deprecateHost from '../deprecate';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
This function could be used in Connect app for moving focus to Host app.
|
|
7
|
+
As Connect App - iframe app, it can get control. When it's happen - host app events such short-cuts
|
|
8
|
+
stop working. This function could help in this case.
|
|
9
|
+
*/
|
|
10
|
+
focus: () => {
|
|
11
|
+
window.document.querySelector('a').focus({preventScroll:true});
|
|
12
|
+
window.document.querySelector('a').blur();
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
getSelectedText: deprecateHost(function(callback) {
|
|
16
|
+
callback('');
|
|
17
|
+
return;
|
|
18
|
+
}, 'AP.host.getSelectedText()')
|
|
19
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inline dialog is a wrapper for secondary content/controls to be displayed on user request. Consider this component as displayed in context to the triggering control with the dialog overlaying the page content.
|
|
3
|
+
* An inline dialog should be preferred over a modal dialog when a connection between the action has a clear benefit versus having a lower user focus.
|
|
4
|
+
*
|
|
5
|
+
* Inline dialogs can be shown via a [web item target](../../modules/web-item/#target).
|
|
6
|
+
*
|
|
7
|
+
* For more information, read about the Atlassian User Interface [inline dialog component](https://docs.atlassian.com/aui/latest/docs/inline-dialog.html).
|
|
8
|
+
* @module Inline-dialog
|
|
9
|
+
*/
|
|
10
|
+
import HostApi from '../host-api';
|
|
11
|
+
import InlineDialogActions from '../actions/inline_dialog_actions';
|
|
12
|
+
import util from '../util';
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
/**
|
|
16
|
+
* Hide the inline dialog that contains the iframe where this method is called from.
|
|
17
|
+
* @memberOf module:Inline-dialog
|
|
18
|
+
* @method hide
|
|
19
|
+
* @noDemo
|
|
20
|
+
* @example
|
|
21
|
+
* AP.inlineDialog.hide();
|
|
22
|
+
*/
|
|
23
|
+
hide: function(callback) {
|
|
24
|
+
callback = util.last(arguments);
|
|
25
|
+
const frameworkAdaptor = HostApi.getFrameworkAdaptor();
|
|
26
|
+
const inlineDialogProvider = frameworkAdaptor.getProviderByModuleName('inlineDialog');
|
|
27
|
+
if (inlineDialogProvider) {
|
|
28
|
+
inlineDialogProvider.hide(callback._context);
|
|
29
|
+
} else {
|
|
30
|
+
InlineDialogActions.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|