customerio-gist-web 0.0.0-test-oidc
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/.github/workflows/eslint.yml +26 -0
- package/.github/workflows/release.yml +46 -0
- package/.github/workflows/release_hotfix.yml +41 -0
- package/.github/workflows/release_version.yml +57 -0
- package/.mise/config.toml +2 -0
- package/CODEOWNERS +2 -0
- package/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/gist.min.js +1 -0
- package/eslint.config.mjs +10 -0
- package/examples/index.html +126 -0
- package/examples/styles.css +55 -0
- package/index.d.ts +1 -0
- package/index.js +2 -0
- package/package.json +49 -0
- package/src/gist.js +128 -0
- package/src/index.js +2 -0
- package/src/managers/custom-attribute-manager.js +82 -0
- package/src/managers/gist-properties-manager.js +36 -0
- package/src/managers/locale-manager.js +16 -0
- package/src/managers/message-broadcast-manager.js +107 -0
- package/src/managers/message-component-manager.js +192 -0
- package/src/managers/message-manager.js +314 -0
- package/src/managers/message-user-queue-manager.js +80 -0
- package/src/managers/page-component-manager.js +19 -0
- package/src/managers/queue-manager.js +216 -0
- package/src/managers/user-manager.js +88 -0
- package/src/services/log-service.js +19 -0
- package/src/services/network.js +81 -0
- package/src/services/queue-service.js +75 -0
- package/src/services/settings.js +65 -0
- package/src/templates/embed.js +69 -0
- package/src/templates/message.js +57 -0
- package/src/utilities/event-emitter.js +12 -0
- package/src/utilities/local-storage.js +86 -0
- package/src/utilities/log.js +7 -0
- package/src/utilities/preview-mode.js +20 -0
- package/test.sh +4 -0
- package/webpack.config.js +11 -0
package/src/gist.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import EventEmitter from "./utilities/event-emitter";
|
|
2
|
+
import { log } from "./utilities/log";
|
|
3
|
+
import { clearExpiredFromLocalStore } from "./utilities/local-storage";
|
|
4
|
+
import { startQueueListener, checkMessageQueue, stopSSEListener } from "./managers/queue-manager";
|
|
5
|
+
import { setUserToken, clearUserToken, useGuestSession } from "./managers/user-manager";
|
|
6
|
+
import { showMessage, embedMessage, hideMessage, removePersistentMessage, fetchMessageByInstanceId, logBroadcastDismissedLocally } from "./managers/message-manager";
|
|
7
|
+
import { setUserLocale } from "./managers/locale-manager";
|
|
8
|
+
import { setCustomAttribute, clearCustomAttributes, removeCustomAttribute } from "./managers/custom-attribute-manager";
|
|
9
|
+
import { setupPreview } from "./utilities/preview-mode";
|
|
10
|
+
|
|
11
|
+
export default class {
|
|
12
|
+
static async setup(config) {
|
|
13
|
+
this.events = new EventEmitter();
|
|
14
|
+
this.config = {
|
|
15
|
+
useAnonymousSession: config.useAnonymousSession === undefined ? false : config.useAnonymousSession,
|
|
16
|
+
siteId: config.siteId,
|
|
17
|
+
dataCenter: config.dataCenter,
|
|
18
|
+
env: config.env === undefined ? "prod" : config.env,
|
|
19
|
+
logging: config.logging === undefined ? false : config.logging,
|
|
20
|
+
experiments: config.experiments === undefined ? false : config.experiments
|
|
21
|
+
}
|
|
22
|
+
this.currentMessages = [];
|
|
23
|
+
this.overlayInstanceId = null;
|
|
24
|
+
this.currentRoute = null;
|
|
25
|
+
this.isDocumentVisible = true;
|
|
26
|
+
this.config.isPreviewSession = setupPreview();
|
|
27
|
+
clearExpiredFromLocalStore();
|
|
28
|
+
|
|
29
|
+
log(`Setup complete on ${this.config.env} environment.`);
|
|
30
|
+
|
|
31
|
+
if (!this.config.isPreviewSession && this.config.useAnonymousSession) {
|
|
32
|
+
useGuestSession();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
await startQueueListener();
|
|
36
|
+
|
|
37
|
+
document.addEventListener("visibilitychange", async () => {
|
|
38
|
+
if (document.visibilityState === "hidden") {
|
|
39
|
+
this.isDocumentVisible = false;
|
|
40
|
+
} else {
|
|
41
|
+
this.isDocumentVisible = true;
|
|
42
|
+
await checkMessageQueue();
|
|
43
|
+
}
|
|
44
|
+
}, false);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static async setCurrentRoute(route) {
|
|
48
|
+
this.currentRoute = route;
|
|
49
|
+
log(`Current route set to: ${route}`);
|
|
50
|
+
await checkMessageQueue();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static async setUserToken(userToken, expiryDate) {
|
|
54
|
+
if (this.config.isPreviewSession) return;
|
|
55
|
+
setUserToken(userToken, expiryDate);
|
|
56
|
+
stopSSEListener(true);
|
|
57
|
+
await startQueueListener();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static setUserLocale(userLocale) {
|
|
61
|
+
setUserLocale(userLocale);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static setCustomAttribute(key, value) {
|
|
65
|
+
return setCustomAttribute(key, value);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static clearCustomAttributes() {
|
|
69
|
+
clearCustomAttributes();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static removeCustomAttribute(key) {
|
|
73
|
+
return removeCustomAttribute(key);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static async clearUserToken() {
|
|
77
|
+
if (this.config.isPreviewSession) return;
|
|
78
|
+
clearUserToken();
|
|
79
|
+
if (this.config.useAnonymousSession) {
|
|
80
|
+
useGuestSession();
|
|
81
|
+
}
|
|
82
|
+
stopSSEListener(true);
|
|
83
|
+
await startQueueListener();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static async dismissMessage(instanceId) {
|
|
87
|
+
var message = fetchMessageByInstanceId(instanceId);
|
|
88
|
+
await hideMessage(message);
|
|
89
|
+
await removePersistentMessage(message);
|
|
90
|
+
await logBroadcastDismissedLocally(message);
|
|
91
|
+
await checkMessageQueue();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static async embedMessage(message, elementId) {
|
|
95
|
+
var messageResponse = await embedMessage(message, elementId);
|
|
96
|
+
return messageResponse ? messageResponse.instanceId : null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static async showMessage(message) {
|
|
100
|
+
var messageResponse = await showMessage(message);
|
|
101
|
+
return messageResponse ? messageResponse.instanceId : null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Actions
|
|
105
|
+
|
|
106
|
+
static messageShown(message) {
|
|
107
|
+
log(`Message shown: ${message.messageId}`);
|
|
108
|
+
this.events.dispatch('messageShown', message);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static messageDismissed(message) {
|
|
112
|
+
if (message !== null) {
|
|
113
|
+
log(`Message dismissed: ${message.messageId}`);
|
|
114
|
+
this.events.dispatch('messageDismissed', message);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static messageError(message) {
|
|
119
|
+
log(`Message error: ${message.messageId}`);
|
|
120
|
+
this.events.dispatch('messageError', message);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static messageAction(message, action, name) {
|
|
124
|
+
log(`Message action: ${message.currentRoute}, ${action} with name ${name} on ${message.instanceId}`);
|
|
125
|
+
this.events.dispatch('messageAction', {message: message, action: action, name: name});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { log } from '../utilities/log';
|
|
2
|
+
import { setKeyToLocalStore, getKeyFromLocalStore, clearKeyFromLocalStore } from '../utilities/local-storage';
|
|
3
|
+
|
|
4
|
+
const customAttributesLocalStoreName = "gist.web.customAttributes";
|
|
5
|
+
const defaultExpiryInDays = 30;
|
|
6
|
+
|
|
7
|
+
// Internal map to store custom attributes in memory
|
|
8
|
+
let customAttributesMap = new Map();
|
|
9
|
+
|
|
10
|
+
function loadCustomAttributesFromStorage() {
|
|
11
|
+
const storedAttributes = getKeyFromLocalStore(customAttributesLocalStoreName);
|
|
12
|
+
if (storedAttributes) {
|
|
13
|
+
try {
|
|
14
|
+
customAttributesMap = new Map(storedAttributes);
|
|
15
|
+
} catch {
|
|
16
|
+
customAttributesMap = new Map();
|
|
17
|
+
}
|
|
18
|
+
} else {
|
|
19
|
+
customAttributesMap = new Map();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function saveCustomAttributesToStorage() {
|
|
24
|
+
const attributesArray = Array.from(customAttributesMap.entries());
|
|
25
|
+
const expiryDate = new Date();
|
|
26
|
+
expiryDate.setDate(expiryDate.getDate() + defaultExpiryInDays);
|
|
27
|
+
|
|
28
|
+
setKeyToLocalStore(customAttributesLocalStoreName, attributesArray, expiryDate);
|
|
29
|
+
log(`Saved ${customAttributesMap.size} custom attributes to storage with TTL of ${defaultExpiryInDays} days`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
loadCustomAttributesFromStorage();
|
|
33
|
+
|
|
34
|
+
export function setCustomAttribute(key, value) {
|
|
35
|
+
if (!key || typeof key !== 'string') {
|
|
36
|
+
log(`Invalid key for custom attribute: ${key}`);
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
customAttributesMap.set(key, value);
|
|
41
|
+
saveCustomAttributesToStorage();
|
|
42
|
+
log(`Set custom attribute "${key}" to "${value}"`);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function getCustomAttribute(key) {
|
|
47
|
+
if (!key || typeof key !== 'string') {
|
|
48
|
+
log(`Invalid key for custom attribute: ${key}`);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return customAttributesMap.get(key) || null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getAllCustomAttributes() {
|
|
56
|
+
return new Map(customAttributesMap);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function clearCustomAttributes() {
|
|
60
|
+
customAttributesMap.clear();
|
|
61
|
+
clearKeyFromLocalStore(customAttributesLocalStoreName);
|
|
62
|
+
log(`Cleared all custom attributes`);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function removeCustomAttribute(key) {
|
|
66
|
+
if (!key || typeof key !== 'string') {
|
|
67
|
+
log(`Invalid key for custom attribute: ${key}`);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const existed = customAttributesMap.has(key);
|
|
72
|
+
customAttributesMap.delete(key);
|
|
73
|
+
|
|
74
|
+
if (customAttributesMap.size > 0) {
|
|
75
|
+
saveCustomAttributesToStorage();
|
|
76
|
+
} else {
|
|
77
|
+
clearKeyFromLocalStore(customAttributesLocalStoreName);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
log(`Removed custom attribute "${key}"`);
|
|
81
|
+
return existed;
|
|
82
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function resolveMessageProperties(message) {
|
|
2
|
+
const defaults = {
|
|
3
|
+
isEmbedded: false,
|
|
4
|
+
elementId: "",
|
|
5
|
+
hasRouteRule: false,
|
|
6
|
+
routeRule: "",
|
|
7
|
+
position: "",
|
|
8
|
+
hasPosition: false,
|
|
9
|
+
shouldScale: false,
|
|
10
|
+
campaignId: null,
|
|
11
|
+
messageWidth: 414,
|
|
12
|
+
overlayColor: "#00000033",
|
|
13
|
+
persistent: false,
|
|
14
|
+
exitClick: false,
|
|
15
|
+
hasCustomWidth: false
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const gist = message?.properties?.gist;
|
|
19
|
+
if (!gist) return defaults;
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
isEmbedded: !!gist.elementId,
|
|
23
|
+
elementId: gist.elementId || "",
|
|
24
|
+
hasRouteRule: !!gist.routeRuleWeb,
|
|
25
|
+
routeRule: gist.routeRuleWeb || "",
|
|
26
|
+
position: gist.position || "",
|
|
27
|
+
hasPosition: !!gist.position,
|
|
28
|
+
shouldScale: !!gist.scale,
|
|
29
|
+
campaignId: gist.campaignId ?? null,
|
|
30
|
+
messageWidth: gist.messageWidth > 0 ? gist.messageWidth : defaults.messageWidth,
|
|
31
|
+
hasCustomWidth: gist.messageWidth > 0,
|
|
32
|
+
overlayColor: gist.overlayColor || defaults.overlayColor,
|
|
33
|
+
persistent: !!gist.persistent,
|
|
34
|
+
exitClick: !!gist.exitClick
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { log } from '../utilities/log';
|
|
2
|
+
import { setKeyToLocalStore, getKeyFromLocalStore } from '../utilities/local-storage';
|
|
3
|
+
const userLocaleLocalStoreName = "gist.web.userLocale";
|
|
4
|
+
|
|
5
|
+
export function getUserLocale() {
|
|
6
|
+
if (getKeyFromLocalStore(userLocaleLocalStoreName) !== null) {
|
|
7
|
+
return getKeyFromLocalStore(userLocaleLocalStoreName);
|
|
8
|
+
} else {
|
|
9
|
+
return navigator.language;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function setUserLocale(locale) {
|
|
14
|
+
setKeyToLocalStore(userLocaleLocalStoreName, locale);
|
|
15
|
+
log(`Set user locate to "${locale}"`);
|
|
16
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { log } from '../utilities/log';
|
|
2
|
+
import { setKeyToLocalStore, getKeyFromLocalStore } from '../utilities/local-storage';
|
|
3
|
+
import { getHashedUserToken } from './user-manager';
|
|
4
|
+
|
|
5
|
+
const broadcastsLocalStoreName = "gist.web.message.broadcasts";
|
|
6
|
+
const broadcastsExpiryInMinutes = 60;
|
|
7
|
+
|
|
8
|
+
export async function updateBroadcastsLocalStore(messages) {
|
|
9
|
+
const messageBroadcastLocalStoreName = await getMessageBroadcastLocalStoreName();
|
|
10
|
+
if (!messageBroadcastLocalStoreName) return;
|
|
11
|
+
|
|
12
|
+
const expiryDate = new Date();
|
|
13
|
+
expiryDate.setMinutes(expiryDate.getMinutes() + broadcastsExpiryInMinutes);
|
|
14
|
+
|
|
15
|
+
const messagesWithBroadcast = messages.filter(isMessageBroadcast);
|
|
16
|
+
setKeyToLocalStore(messageBroadcastLocalStoreName, messagesWithBroadcast, expiryDate);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function getEligibleBroadcasts() {
|
|
20
|
+
const messageBroadcastLocalStoreName = await getMessageBroadcastLocalStoreName();
|
|
21
|
+
if (!messageBroadcastLocalStoreName) return [];
|
|
22
|
+
|
|
23
|
+
const broadcasts = getKeyFromLocalStore(messageBroadcastLocalStoreName) ?? [];
|
|
24
|
+
return broadcasts.filter(broadcast => {
|
|
25
|
+
const { broadcast: broadcastDetails } = broadcast.properties.gist;
|
|
26
|
+
const shouldShow = getKeyFromLocalStore(getBroadcastShouldShowLocalStoreName(messageBroadcastLocalStoreName, broadcast.queueId)) ?? true;
|
|
27
|
+
const numberOfTimesShown = getKeyFromLocalStore(getNumberOfTimesShownLocalStoreName(messageBroadcastLocalStoreName, broadcast.queueId)) || 0;
|
|
28
|
+
const isFrequencyUnlimited = broadcastDetails.frequency.count === 0;
|
|
29
|
+
return shouldShow && (isFrequencyUnlimited || numberOfTimesShown < broadcastDetails.frequency.count);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function markBroadcastAsSeen(broadcastId) {
|
|
34
|
+
log(`Marking broadcast ${broadcastId} as seen.`);
|
|
35
|
+
const messageBroadcastLocalStoreName = await getMessageBroadcastLocalStoreName();
|
|
36
|
+
if (!messageBroadcastLocalStoreName) return;
|
|
37
|
+
|
|
38
|
+
const broadcast = await fetchMessageBroadcast(messageBroadcastLocalStoreName, broadcastId);
|
|
39
|
+
if (!broadcast) return;
|
|
40
|
+
|
|
41
|
+
const { broadcast: broadcastDetails } = broadcast.properties.gist;
|
|
42
|
+
const numberOfTimesShownLocalStoreName = getNumberOfTimesShownLocalStoreName(messageBroadcastLocalStoreName, broadcastId);
|
|
43
|
+
const broadcastShouldShowLocalStoreName = getBroadcastShouldShowLocalStoreName(messageBroadcastLocalStoreName, broadcastId);
|
|
44
|
+
let numberOfTimesShown = getKeyFromLocalStore(numberOfTimesShownLocalStoreName) || 0;
|
|
45
|
+
setKeyToLocalStore(numberOfTimesShownLocalStoreName, numberOfTimesShown + 1);
|
|
46
|
+
|
|
47
|
+
if (broadcastDetails.frequency.count === 1) {
|
|
48
|
+
setKeyToLocalStore(broadcastShouldShowLocalStoreName, false);
|
|
49
|
+
log(`Marked broadcast ${broadcastId} as seen.`);
|
|
50
|
+
} else {
|
|
51
|
+
let showShowDate = new Date();
|
|
52
|
+
showShowDate.setSeconds(showShowDate.getSeconds() + broadcastDetails.frequency.delay);
|
|
53
|
+
setKeyToLocalStore(broadcastShouldShowLocalStoreName, false, showShowDate);
|
|
54
|
+
log(`Marked broadcast ${broadcastId} as seen, broadcast was seen ${numberOfTimesShown + 1} times, next show date is ${showShowDate}.`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function markBroadcastAsDismissed(broadcastId) {
|
|
59
|
+
log(`Marking broadcast ${broadcastId} as dismissed.`);
|
|
60
|
+
const messageBroadcastLocalStoreName = await getMessageBroadcastLocalStoreName();
|
|
61
|
+
if (!messageBroadcastLocalStoreName) return;
|
|
62
|
+
|
|
63
|
+
const broadcast = await fetchMessageBroadcast(messageBroadcastLocalStoreName, broadcastId);
|
|
64
|
+
if (!broadcast) return;
|
|
65
|
+
|
|
66
|
+
const { broadcast: broadcastDetails } = broadcast.properties.gist;
|
|
67
|
+
const ignoreDismiss = broadcastDetails.frequency.ignoreDismiss;
|
|
68
|
+
|
|
69
|
+
if (ignoreDismiss === true) {
|
|
70
|
+
log(`Broadcast ${broadcastId} is set to ignore dismiss.`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// default to not showing the broadcast again
|
|
75
|
+
const broadcastShouldShowLocalStoreName = getBroadcastShouldShowLocalStoreName(messageBroadcastLocalStoreName, broadcastId);
|
|
76
|
+
setKeyToLocalStore(broadcastShouldShowLocalStoreName, false);
|
|
77
|
+
log(`Marked broadcast ${broadcastId} as dismissed and will not show again.`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async function fetchMessageBroadcast(messageBroadcastLocalStoreName, broadcastId) {
|
|
81
|
+
const broadcasts = getKeyFromLocalStore(messageBroadcastLocalStoreName);
|
|
82
|
+
return broadcasts.find(message => message.queueId === broadcastId);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function isMessageBroadcast(message) {
|
|
86
|
+
return message.properties && message.properties.gist && message.properties.gist.broadcast;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function isShowAlwaysBroadcast(message) {
|
|
90
|
+
if (!isMessageBroadcast(message)) return false;
|
|
91
|
+
const { broadcast: broadcastDetails } = message.properties.gist;
|
|
92
|
+
return broadcastDetails.frequency.delay === 0 && broadcastDetails.frequency.count === 0;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function getMessageBroadcastLocalStoreName() {
|
|
96
|
+
const userToken = await getHashedUserToken();
|
|
97
|
+
if (!userToken) return null;
|
|
98
|
+
return `${broadcastsLocalStoreName}.${userToken}`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function getNumberOfTimesShownLocalStoreName(messageBroadcastLocalStoreName, broadcastId) {
|
|
102
|
+
return `${messageBroadcastLocalStoreName}.${broadcastId}.numberOfTimesShown`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function getBroadcastShouldShowLocalStoreName(messageBroadcastLocalStoreName, broadcastId) {
|
|
106
|
+
return `${messageBroadcastLocalStoreName}.${broadcastId}.shouldShow`;
|
|
107
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import Gist from '../gist';
|
|
2
|
+
import { log } from "../utilities/log";
|
|
3
|
+
import { resolveMessageProperties } from "./gist-properties-manager";
|
|
4
|
+
import { embedHTMLTemplate } from "../templates/embed";
|
|
5
|
+
import { messageHTMLTemplate } from "../templates/message";
|
|
6
|
+
import { positions } from "./page-component-manager";
|
|
7
|
+
|
|
8
|
+
const delay = ms => new Promise(res => setTimeout(res, ms));
|
|
9
|
+
const wideOverlayPositions = ["x-gist-top", "x-gist-bottom", "x-gist-floating-top", "x-gist-floating-bottom"];
|
|
10
|
+
|
|
11
|
+
export function isElementLoaded(elementId) {
|
|
12
|
+
var element = safelyFetchElement(elementId);
|
|
13
|
+
if (element && element.classList.contains("gist-visible")) {
|
|
14
|
+
return true;
|
|
15
|
+
} else {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function loadEmbedComponent(elementId, url, message, options) {
|
|
21
|
+
var element = safelyFetchElement(elementId);
|
|
22
|
+
if (element) {
|
|
23
|
+
var messageElementId = getMessageElementId(message.instanceId);
|
|
24
|
+
element.classList.add(messageElementId);
|
|
25
|
+
var messageProperties = resolveMessageProperties(message);
|
|
26
|
+
var messageWidth = messageProperties.messageWidth + "px";
|
|
27
|
+
if (wideOverlayPositions.includes(elementId) && !messageProperties.hasCustomWidth) {
|
|
28
|
+
messageWidth = "100%";
|
|
29
|
+
}
|
|
30
|
+
// Only set the width if it's a position offered by the SDK
|
|
31
|
+
if (positions.includes(elementId)) {
|
|
32
|
+
element.style.width = messageWidth;
|
|
33
|
+
}
|
|
34
|
+
if (!elementHasHeight(elementId)) {
|
|
35
|
+
element.style.height = "0px";
|
|
36
|
+
}
|
|
37
|
+
element.innerHTML = embed(url, message, messageProperties);
|
|
38
|
+
attachIframeLoadEvent(messageElementId, options);
|
|
39
|
+
} else {
|
|
40
|
+
log(`Message could not be embedded, elementId ${elementId} not found.`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function showEmbedComponent(elementId) {
|
|
45
|
+
var element = safelyFetchElement(elementId);
|
|
46
|
+
if (element) {
|
|
47
|
+
element.classList.add("gist-visible");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function hideEmbedComponent(elementId) {
|
|
52
|
+
var element = safelyFetchElement(elementId);
|
|
53
|
+
if (element) {
|
|
54
|
+
element.classList.remove("gist-visible");
|
|
55
|
+
element.style.removeProperty("height");
|
|
56
|
+
element.innerHTML = "";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function elementHasHeight(elementId) {
|
|
61
|
+
var element = safelyFetchElement(elementId);
|
|
62
|
+
if (element) {
|
|
63
|
+
return element.style && element.style.height && element.style.height != "0px";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function resizeComponent(message, size) {
|
|
68
|
+
var elementId = message.elementId ? message.elementId : getMessageElementId(message.instanceId);
|
|
69
|
+
var element = safelyFetchElement(elementId);
|
|
70
|
+
if (element) {
|
|
71
|
+
var style = element.style;
|
|
72
|
+
if (size.height > 0) {
|
|
73
|
+
if (size.height > window.innerHeight) {
|
|
74
|
+
var heightScale = 1 - ((size.height / window.innerHeight) - 1);
|
|
75
|
+
if (message.shouldScale && heightScale >= 0.4) {
|
|
76
|
+
style.height = `${size.height}px`;
|
|
77
|
+
style.transform = `translateX(-50%) translateY(-50%) scale(${heightScale})`;
|
|
78
|
+
} else {
|
|
79
|
+
style.height = `${window.innerHeight}px`;
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
style.height = `${size.height}px`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function loadOverlayComponent(url, message, options) {
|
|
89
|
+
document.body.insertAdjacentHTML('afterbegin', component(url, message));
|
|
90
|
+
attachIframeLoadEvent(getMessageElementId(message.instanceId), options);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function attachIframeLoadEvent(elementId, options) {
|
|
94
|
+
const iframe = document.getElementById(elementId);
|
|
95
|
+
if (iframe) {
|
|
96
|
+
iframe.onload = function() {
|
|
97
|
+
sendOptionsToIframe(elementId, options); // Send the options when iframe loads
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function sendOptionsToIframe(iframeId, options) {
|
|
103
|
+
const iframe = document.getElementById(iframeId);
|
|
104
|
+
if (iframe && iframe.contentWindow) {
|
|
105
|
+
iframe.contentWindow.postMessage({ options: options }, '*');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function showOverlayComponent(message) {
|
|
110
|
+
var messageProperties = resolveMessageProperties(message);
|
|
111
|
+
var mainMessageElement = document.querySelector("#gist-overlay");
|
|
112
|
+
if (mainMessageElement) {
|
|
113
|
+
mainMessageElement.classList.add("gist-visible");
|
|
114
|
+
var messageElement = document.querySelector(".gist-message");
|
|
115
|
+
if (message.position) {
|
|
116
|
+
messageElement.classList.add("gist-" + message.position);
|
|
117
|
+
} else {
|
|
118
|
+
messageElement.classList.add("gist-center");
|
|
119
|
+
}
|
|
120
|
+
setTimeout(showMessage, 100);
|
|
121
|
+
// If exitClick is set to true, we add a dismiss listener after a 1-second delay to prevent accidental dismissals.
|
|
122
|
+
if (messageProperties.exitClick) { setTimeout(() => addDismissListener(message.instanceId), 1000); }
|
|
123
|
+
} else {
|
|
124
|
+
removeOverlayComponent();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function addDismissListener(instanceId) {
|
|
129
|
+
// We check if the overlay is still active before adding the dismiss listener
|
|
130
|
+
var mainMessageElement = document.querySelector("#gist-overlay");
|
|
131
|
+
if (mainMessageElement) {
|
|
132
|
+
mainMessageElement.addEventListener("click", function() {
|
|
133
|
+
Gist.dismissMessage(instanceId);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function hideOverlayComponent() {
|
|
139
|
+
var message = document.querySelector(".gist-message");
|
|
140
|
+
if (message) {
|
|
141
|
+
message.classList.remove("gist-visible");
|
|
142
|
+
await delay(300);
|
|
143
|
+
}
|
|
144
|
+
removeOverlayComponent();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function removeOverlayComponent() {
|
|
148
|
+
var mainMessageElement = document.querySelector("#gist-embed-message");
|
|
149
|
+
if (mainMessageElement) {
|
|
150
|
+
mainMessageElement.parentNode.removeChild(mainMessageElement);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function changeOverlayTitle(instanceId, title) {
|
|
155
|
+
var element = safelyFetchElement(getMessageElementId(instanceId));
|
|
156
|
+
if (element) {
|
|
157
|
+
element.title = title;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function getMessageElementId(instanceId) {
|
|
162
|
+
return `gist-${instanceId}`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function showMessage() {
|
|
166
|
+
var messageElement = document.querySelector(".gist-message");
|
|
167
|
+
if (messageElement) messageElement.classList.add("gist-visible");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function embed(url, message, messageProperties) {
|
|
171
|
+
var template = embedHTMLTemplate(getMessageElementId(message.instanceId), messageProperties, url);
|
|
172
|
+
return template;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function component(url, message) {
|
|
176
|
+
var messageProperties = resolveMessageProperties(message);
|
|
177
|
+
var template = messageHTMLTemplate(getMessageElementId(message.instanceId), messageProperties, url);
|
|
178
|
+
return template;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function safelyFetchElement(elementId) {
|
|
182
|
+
try {
|
|
183
|
+
var element = document.querySelector(`#${elementId}`);
|
|
184
|
+
if (element) {
|
|
185
|
+
return element;
|
|
186
|
+
} else {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
} catch {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
}
|