ultimate-jekyll-manager 0.0.116 → 0.0.118

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.
@@ -1,4 +1,4 @@
1
- import fetch from 'wonderful-fetch';
1
+ import authorizedFetch from '__main_assets__/js/libs/authorized-fetch.js';
2
2
 
3
3
  // Auth Module
4
4
  export default function (Manager, options) {
@@ -166,9 +166,6 @@ function setAnalyticsUserId(user) {
166
166
  // Send user metadata to server (affiliate, UTM params, etc.)
167
167
  async function sendUserSignupMetadata(user, webManager) {
168
168
  try {
169
- // Get the auth token
170
- const token = await webManager.auth().getIdToken();
171
-
172
169
  // Get affiliate data from storage
173
170
  const affiliateData = webManager.storage().get('marketing.affiliate', null);
174
171
  const utmData = webManager.storage().get('marketing.utm', null);
@@ -193,11 +190,10 @@ async function sendUserSignupMetadata(user, webManager) {
193
190
  // Get server API URL
194
191
  const serverApiURL = webManager.getApiUrl() + '/backend-manager';
195
192
 
196
- // Make API call to reset API key
197
- const response = await fetch(serverApiURL, {
193
+ // Make API call to send signup metadata
194
+ const response = await authorizedFetch(serverApiURL, {
198
195
  method: 'POST',
199
196
  body: {
200
- authenticationToken: token,
201
197
  command: 'user:sign-up',
202
198
  payload: payload
203
199
  }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Prerendered Icons Library
3
+ * Retrieves pre-rendered icon HTML from the frontmatter icon system
4
+ */
5
+
6
+ /**
7
+ * Get pre-rendered icon by name from frontmatter icon system
8
+ * @param {string} iconName - Name of the icon to retrieve (matches data-icon attribute)
9
+ * @returns {string} Icon HTML or empty string if not found
10
+ *
11
+ * @example
12
+ * import { getPrerenderedIcon } from '__main_assets__/js/libs/prerendered-icons.js';
13
+ *
14
+ * // Get an icon
15
+ * const appleIcon = getPrerenderedIcon('apple');
16
+ */
17
+ export function getPrerenderedIcon(iconName) {
18
+ // Query the global prerendered icons container
19
+ const $iconTemplate = document.querySelector(`#prerendered-icons [data-icon="${iconName}"]`);
20
+
21
+ if ($iconTemplate) {
22
+ return $iconTemplate.innerHTML;
23
+ }
24
+
25
+ // Return empty string if not found
26
+ return '';
27
+ }
@@ -82,7 +82,7 @@ async function initializeAccount() {
82
82
  {
83
83
  // Check for test subscription parameter
84
84
  const urlParams = new URLSearchParams(window.location.search);
85
- const testSubscription = urlParams.get('_test_subscription');
85
+ const testSubscription = urlParams.get('_dev_subscription');
86
86
 
87
87
  if (testSubscription && webManager.isDevelopment()) {
88
88
  try {
@@ -1,6 +1,6 @@
1
1
  // API Keys section module
2
2
  import { FormManager } from '__main_assets__/js/libs/form-manager.js';
3
- import fetch from 'wonderful-fetch';
3
+ import authorizedFetch from '__main_assets__/js/libs/authorized-fetch.js';
4
4
 
5
5
  let webManager = null;
6
6
  let resetApiKeyFormManager = null;
@@ -113,20 +113,16 @@ async function handleCopyApiKey() {
113
113
 
114
114
  // Handle reset API key form submission
115
115
  async function handleResetApiKeySubmit() {
116
- // Get authentication token
117
- const token = await webManager.auth().getIdToken();
118
-
119
116
  // Get server API URL
120
117
  const serverApiURL = webManager.getApiUrl() + '/backend-manager';
121
118
 
122
119
  // Make API call to reset API key
123
- const response = await fetch(serverApiURL, {
120
+ const response = await authorizedFetch(serverApiURL, {
124
121
  method: 'POST',
125
122
  timeout: 30000,
126
123
  response: 'json',
127
124
  tries: 2,
128
125
  body: {
129
- authenticationToken: token,
130
126
  command: 'user:regenerate-api-keys',
131
127
  },
132
128
  });
@@ -1,6 +1,6 @@
1
1
  // Connections section module for OAuth account linking
2
2
  import { FormManager } from '__main_assets__/js/libs/form-manager.js';
3
- import fetch from 'wonderful-fetch';
3
+ import authorizedFetch from '__main_assets__/js/libs/authorized-fetch.js';;
4
4
 
5
5
  let webManager = null;
6
6
  let appData = null;
@@ -32,6 +32,8 @@ export async function loadData(account, sharedAppData) {
32
32
 
33
33
  // Display available and connected OAuth providers
34
34
  function displayConnections() {
35
+ console.log('[DEBUG] displayConnections() called');
36
+
35
37
  // Hide loading state
36
38
  const $loading = document.getElementById('connections-loading');
37
39
  if ($loading) {
@@ -40,6 +42,7 @@ function displayConnections() {
40
42
 
41
43
  // Check if appData is loaded
42
44
  if (!appData) {
45
+ console.log('[DEBUG] No appData, showing loading state');
43
46
  // Show loading if no app data yet
44
47
  if ($loading) {
45
48
  $loading.classList.remove('d-none');
@@ -51,33 +54,51 @@ function displayConnections() {
51
54
  const availableProviders = appData?.oauth2 || {};
52
55
  const userConnections = accountData?.oauth2 || {};
53
56
 
54
- console.log('Available OAuth providers:', availableProviders);
55
- console.log('User connections:', userConnections);
57
+ console.log('[DEBUG] Available OAuth providers:', availableProviders);
58
+ console.log('[DEBUG] User connections:', userConnections);
56
59
 
57
60
  // Check if any providers are configured
58
61
  let hasEnabledProviders = false;
59
62
 
60
63
  // Process each supported provider
61
64
  supportedProviders.forEach(providerId => {
65
+ console.log(`[DEBUG] Processing provider: ${providerId}`);
66
+
62
67
  const providerSettings = availableProviders[providerId];
63
68
  const $providerElement = document.getElementById(`connection-${providerId}`);
64
69
 
65
- if (!$providerElement) return;
70
+ console.log(`[DEBUG] ${providerId} - providerSettings:`, providerSettings);
71
+ console.log(`[DEBUG] ${providerId} - providerSettings.enabled:`, providerSettings?.enabled);
72
+ console.log(`[DEBUG] ${providerId} - $providerElement exists:`, !!$providerElement);
73
+
74
+ if (!$providerElement) {
75
+ console.warn(`[DEBUG] ${providerId} - Provider element not found in DOM`);
76
+ return;
77
+ }
66
78
 
67
79
  // Check if provider is enabled
68
- if (providerSettings && providerSettings.enabled !== false) {
80
+ const isEnabled = providerSettings && providerSettings.enabled !== false;
81
+ console.log(`[DEBUG] ${providerId} - isEnabled:`, isEnabled);
82
+
83
+ if (isEnabled) {
69
84
  hasEnabledProviders = true;
70
85
 
71
- // Show the provider element
86
+ // Show the provider element first
87
+ console.log(`[DEBUG] ${providerId} - Removing d-none class`);
72
88
  $providerElement.classList.remove('d-none');
73
89
 
74
- // Update provider status based on user connection
75
- updateProviderStatus(providerId, userConnections[providerId], providerSettings);
76
-
77
- // Initialize FormManager for this provider
90
+ // Initialize FormManager for this provider before updating status
91
+ console.log(`[DEBUG] ${providerId} - About to initialize FormManager`);
78
92
  initializeProviderForm(providerId);
93
+
94
+ // Update provider status based on user connection
95
+ const userConnection = userConnections[providerId];
96
+ console.log(`[DEBUG] ${providerId} - userConnection:`, userConnection);
97
+ console.log(`[DEBUG] ${providerId} - About to update provider status`);
98
+ updateProviderStatus(providerId, userConnection, providerSettings);
79
99
  } else {
80
100
  // Hide disabled providers
101
+ console.log(`[DEBUG] ${providerId} - Provider disabled, adding d-none class`);
81
102
  $providerElement.classList.add('d-none');
82
103
  }
83
104
  });
@@ -95,14 +116,28 @@ function displayConnections() {
95
116
 
96
117
  // Update provider status display
97
118
  function updateProviderStatus(providerId, userConnection, providerSettings) {
119
+ console.log(`[DEBUG] updateProviderStatus() called for ${providerId}`);
120
+ console.log(`[DEBUG] ${providerId} - userConnection:`, userConnection);
121
+ console.log(`[DEBUG] ${providerId} - userConnection truthy:`, !!userConnection);
122
+ console.log(`[DEBUG] ${providerId} - userConnection.identity:`, userConnection?.identity);
123
+ console.log(`[DEBUG] ${providerId} - providerSettings:`, providerSettings);
124
+
98
125
  const $status = document.getElementById(`${providerId}-connection-status`);
99
126
  const $description = document.getElementById(`${providerId}-connection-description`);
100
127
  const $form = document.getElementById(`connection-form-${providerId}`);
101
- const $button = $form?.querySelector('button[type="submit"]');
102
- const $buttonText = $button?.querySelector('.button-text');
103
- const $action = $form?.querySelector('input[name="action"]');
128
+ const $connectButton = $form?.querySelector('button[data-action="connect"]');
129
+ const $disconnectButton = $form?.querySelector('button[data-action="disconnect"]');
130
+
131
+ console.log(`[DEBUG] ${providerId} - DOM elements found:`, {
132
+ $status: !!$status,
133
+ $description: !!$description,
134
+ $form: !!$form,
135
+ $connectButton: !!$connectButton,
136
+ $disconnectButton: !!$disconnectButton
137
+ });
104
138
 
105
139
  const isConnected = userConnection && userConnection.identity;
140
+ console.log(`[DEBUG] ${providerId} - isConnected:`, isConnected);
106
141
 
107
142
  // Always show description on the left
108
143
  if ($description) {
@@ -113,7 +148,7 @@ function updateProviderStatus(providerId, userConnection, providerSettings) {
113
148
  twitter: 'Share updates and connect with Twitter',
114
149
  facebook: 'Connect your Facebook account for social features'
115
150
  };
116
-
151
+
117
152
  // Use provider description or fallback to default
118
153
  const descriptionText = providerSettings?.description || defaultDescriptions[providerId] || `Connect your ${providerId.charAt(0).toUpperCase() + providerId.slice(1)} account`;
119
154
  $description.textContent = descriptionText;
@@ -140,45 +175,28 @@ function updateProviderStatus(providerId, userConnection, providerSettings) {
140
175
  $status.textContent = statusText;
141
176
  $status.classList.remove('d-none');
142
177
  } else {
143
- // Not connected - hide status under button
178
+ // Not connected - hide status text
144
179
  $status.textContent = '';
145
180
  $status.classList.add('d-none');
146
181
  }
147
182
  }
148
183
 
149
- if ($button && $buttonText && $action) {
184
+ // Show/hide appropriate button
185
+ if ($connectButton && $disconnectButton) {
186
+ console.log(`[DEBUG] ${providerId} - Updating buttons. isConnected:`, isConnected);
187
+
150
188
  if (isConnected) {
151
- // Update to disconnect state
152
- $button.classList.remove('btn-primary');
153
- $button.classList.add('btn-outline-danger');
154
- $buttonText.textContent = 'Disconnect';
155
- $action.value = 'disconnect';
156
-
157
- // Replace icon - need to update the button's first icon element
158
- const $icon = $button.querySelector('.fa-icon');
159
- if ($icon) {
160
- // Change icon classes from link to unlink
161
- $icon.classList.remove('fa-link');
162
- $icon.classList.add('fa-unlink');
163
- }
189
+ // Hide connect button, show disconnect button
190
+ $connectButton.classList.add('d-none');
191
+ $disconnectButton.classList.remove('d-none');
192
+ console.log(`[DEBUG] ${providerId} - Showing disconnect button`);
164
193
  } else {
165
- // Update to connect state
166
- $button.classList.remove('btn-outline-danger');
167
- $button.classList.add('btn-primary');
168
- $buttonText.textContent = 'Connect';
169
- $action.value = 'connect';
170
-
171
- // Replace icon
172
- const $icon = $button.querySelector('.fa-icon');
173
- if ($icon) {
174
- // Change icon classes from unlink to link
175
- $icon.classList.remove('fa-unlink');
176
- $icon.classList.add('fa-link');
177
- }
194
+ // Show connect button, hide disconnect button
195
+ $connectButton.classList.remove('d-none');
196
+ $disconnectButton.classList.add('d-none');
197
+ console.log(`[DEBUG] ${providerId} - Showing connect button`);
178
198
  }
179
199
  }
180
-
181
- // The updated section has been removed from HTML, no longer needed
182
200
  }
183
201
 
184
202
  // Get display name for connection
@@ -199,13 +217,19 @@ function initializeProviderForm(providerId) {
199
217
  const formId = `connection-form-${providerId}`;
200
218
  const form = document.getElementById(formId);
201
219
 
202
- if (!form) return;
220
+ if (!form) {
221
+ console.warn(`Form not found for provider: ${providerId}`);
222
+ return;
223
+ }
203
224
 
204
225
  // Skip if already initialized
205
226
  if (connectionForms.has(providerId)) {
227
+ console.log(`FormManager already initialized for ${providerId}`);
206
228
  return;
207
229
  }
208
230
 
231
+ console.log(`Initializing FormManager for ${providerId}`);
232
+
209
233
  // Create new FormManager
210
234
  const formManager = new FormManager(`#${formId}`, {
211
235
  autoDisable: true,
@@ -215,14 +239,32 @@ function initializeProviderForm(providerId) {
215
239
  // Store the FormManager instance
216
240
  connectionForms.set(providerId, formManager);
217
241
 
242
+ // Listen for state changes to update button after FormManager is ready
243
+ formManager.addEventListener('statechange', (event) => {
244
+ const { status } = event.detail;
245
+ console.log(`[DEBUG] ${providerId} - FormManager state changed to:`, status);
246
+
247
+ // When FormManager transitions to ready, update the button status
248
+ if (status === 'ready') {
249
+ console.log(`[DEBUG] ${providerId} - FormManager is ready, updating button status`);
250
+ const userConnection = accountData?.oauth2?.[providerId];
251
+ const providerSettings = appData?.oauth2?.[providerId];
252
+ updateProviderStatus(providerId, userConnection, providerSettings);
253
+ }
254
+ });
255
+
218
256
  // Handle form submission
219
257
  formManager.addEventListener('submit', async (event) => {
220
258
  event.preventDefault();
221
259
 
222
- const { data } = event.detail;
223
- const action = data.action;
260
+ const { data, submitButton } = event.detail;
224
261
  const provider = data.provider;
225
262
 
263
+ // Determine action from the clicked button's data-action attribute
264
+ const action = submitButton?.getAttribute('data-action');
265
+
266
+ console.log(`[DEBUG] ${providerId} - Form submitted. Action:`, action, 'Provider:', provider);
267
+
226
268
  try {
227
269
  if (action === 'connect') {
228
270
  await handleConnect(provider);
@@ -253,19 +295,15 @@ async function handleConnect(providerId) {
253
295
  throw new Error('This connection service is not available.');
254
296
  }
255
297
 
256
- // Get user token
257
- const token = await webManager.auth().getIdToken();
258
-
259
298
  // Get scope from provider settings (pass as array)
260
299
  const scope = provider.scope || [];
261
300
 
262
- const response = await fetch(getApiUrl(), {
301
+ const response = await authorizedFetch(getApiUrl(), {
263
302
  method: 'POST',
264
303
  timeout: 30000,
265
304
  response: 'json',
266
305
  tries: 2,
267
306
  body: {
268
- authenticationToken: token,
269
307
  command: 'user:oauth2',
270
308
  payload: {
271
309
  redirect: false,
@@ -299,20 +337,16 @@ async function handleDisconnect(providerId) {
299
337
  throw new Error('Disconnection cancelled');
300
338
  }
301
339
 
302
- // Get user token
303
- const token = await webManager.auth().getIdToken();
304
-
305
340
  // Get provider settings for scope (pass as array)
306
341
  const provider = appData?.oauth2?.[providerId] || {};
307
342
  const scope = provider.scope || [];
308
343
 
309
- const response = await fetch(getApiUrl(), {
344
+ const response = await authorizedFetch(getApiUrl(), {
310
345
  method: 'POST',
311
346
  timeout: 30000,
312
347
  response: 'json',
313
348
  tries: 2,
314
349
  body: {
315
- authenticationToken: token,
316
350
  command: 'user:oauth2',
317
351
  payload: {
318
352
  redirect: false,
@@ -11,10 +11,10 @@ export function init(wm) {
11
11
  // Load referrals data
12
12
  export function loadData(account) {
13
13
  if (!account) return;
14
-
14
+
15
15
  // Update referral code (real code only)
16
16
  updateReferralCode(account.affiliate?.code);
17
-
17
+
18
18
  // Update referrals list
19
19
  updateReferralsList(account.affiliate?.referrals);
20
20
  }
@@ -22,7 +22,7 @@ export function loadData(account) {
22
22
  // Update referral code display
23
23
  function updateReferralCode(code) {
24
24
  const $codeInput = document.getElementById('referral-code-input');
25
-
25
+
26
26
  if ($codeInput) {
27
27
  if (code) {
28
28
  const baseUrl = window.location.origin;
@@ -39,19 +39,19 @@ function updateReferralsList(referrals) {
39
39
  const $recentReferrals = document.getElementById('recent-referrals');
40
40
  const $referralsBadge = document.getElementById('referrals-badge');
41
41
  const $referralsList = document.getElementById('referrals-list');
42
-
42
+
43
43
  // Initialize referrals array
44
44
  let referralData = referrals || [];
45
-
46
- // Add fake data if _test_prefill=true is in query string
45
+
46
+ // Add fake data if _dev_prefill=true is in query string
47
47
  const urlParams = new URLSearchParams(window.location.search);
48
- if (urlParams.get('_test_prefill') === 'true') {
48
+ if (urlParams.get('_dev_prefill') === 'true') {
49
49
  console.log('Adding fake referral data for testing');
50
50
  const fakeReferrals = generateFakeReferrals();
51
51
  // Add fake referrals to existing data
52
52
  referralData = [...referralData, ...fakeReferrals];
53
53
  }
54
-
54
+
55
55
  // Handle empty state
56
56
  if (!referralData || !Array.isArray(referralData) || referralData.length === 0) {
57
57
  // No referrals - show empty state
@@ -67,7 +67,7 @@ function updateReferralsList(referrals) {
67
67
  }
68
68
  return;
69
69
  }
70
-
70
+
71
71
  // Calculate stats
72
72
  const totalCount = referralData.length;
73
73
  const now = new Date();
@@ -76,19 +76,19 @@ function updateReferralsList(referrals) {
76
76
  const timestamp = ref.timestamp || ref.timestampUNIX * 1000;
77
77
  return timestamp >= thisMonth;
78
78
  }).length;
79
-
79
+
80
80
  // Update stats
81
81
  if ($totalReferrals) $totalReferrals.textContent = totalCount.toString();
82
82
  if ($recentReferrals) $recentReferrals.textContent = recentCount.toString();
83
83
  if ($referralsBadge) $referralsBadge.textContent = totalCount.toString();
84
-
84
+
85
85
  // Sort referrals by timestamp in reverse order (newest first)
86
86
  const sortedReferrals = [...referralData].sort((a, b) => {
87
87
  const timeA = a.timestamp || (a.timestampUNIX * 1000) || 0;
88
88
  const timeB = b.timestamp || (b.timestampUNIX * 1000) || 0;
89
89
  return timeB - timeA; // Reverse order
90
90
  });
91
-
91
+
92
92
  // Generate referral list HTML
93
93
  if ($referralsList) {
94
94
  if (sortedReferrals.length === 0) {
@@ -103,7 +103,7 @@ function updateReferralsList(referrals) {
103
103
  const date = timestamp ? new Date(timestamp) : null;
104
104
  const dateStr = date ? formatDate(date) : 'Unknown date';
105
105
  const timeStr = date ? formatTime(date) : '';
106
-
106
+
107
107
  return `
108
108
  <div class="list-group-item px-0">
109
109
  <div class="d-flex justify-content-between align-items-center">
@@ -123,7 +123,7 @@ function updateReferralsList(referrals) {
123
123
  </div>
124
124
  `;
125
125
  }).join('');
126
-
126
+
127
127
  $referralsList.innerHTML = referralHTML;
128
128
  }
129
129
  }
@@ -149,45 +149,45 @@ function formatTime(date) {
149
149
  // Get time since string
150
150
  function getTimeSince(timestamp) {
151
151
  if (!timestamp) return '<small class="text-muted">Unknown</small>';
152
-
152
+
153
153
  const now = Date.now();
154
154
  const diff = now - timestamp;
155
-
155
+
156
156
  // Less than 1 minute
157
157
  if (diff < 60000) {
158
158
  return '<small class="text-success">Just now</small>';
159
159
  }
160
-
160
+
161
161
  // Less than 1 hour
162
162
  if (diff < 3600000) {
163
163
  const minutes = Math.floor(diff / 60000);
164
164
  return `<small class="text-muted">${minutes} min${minutes > 1 ? 's' : ''} ago</small>`;
165
165
  }
166
-
166
+
167
167
  // Less than 24 hours
168
168
  if (diff < 86400000) {
169
169
  const hours = Math.floor(diff / 3600000);
170
170
  return `<small class="text-muted">${hours} hour${hours > 1 ? 's' : ''} ago</small>`;
171
171
  }
172
-
172
+
173
173
  // Less than 7 days
174
174
  if (diff < 604800000) {
175
175
  const days = Math.floor(diff / 86400000);
176
176
  return `<small class="text-muted">${days} day${days > 1 ? 's' : ''} ago</small>`;
177
177
  }
178
-
178
+
179
179
  // Less than 30 days
180
180
  if (diff < 2592000000) {
181
181
  const weeks = Math.floor(diff / 604800000);
182
182
  return `<small class="text-muted">${weeks} week${weeks > 1 ? 's' : ''} ago</small>`;
183
183
  }
184
-
184
+
185
185
  // More than 30 days
186
186
  const months = Math.floor(diff / 2592000000);
187
187
  if (months < 12) {
188
188
  return `<small class="text-muted">${months} month${months > 1 ? 's' : ''} ago</small>`;
189
189
  }
190
-
190
+
191
191
  const years = Math.floor(months / 12);
192
192
  return `<small class="text-muted">${years} year${years > 1 ? 's' : ''} ago</small>`;
193
193
  }
@@ -205,31 +205,31 @@ function setupButtons() {
205
205
  async function handleCopyReferralCode() {
206
206
  const $codeInput = document.getElementById('referral-code-input');
207
207
  const $copyBtn = document.getElementById('copy-referral-code-btn');
208
-
208
+
209
209
  if (!$codeInput || !$codeInput.value || $codeInput.value === 'No referral link available') {
210
210
  webManager.utilities().showNotification('No referral link to copy', 'warning');
211
211
  return;
212
212
  }
213
-
213
+
214
214
  try {
215
215
  // Copy the full URL directly from the input (it now contains the full URL)
216
216
  await webManager.utilities().clipboardCopy($codeInput);
217
-
217
+
218
218
  // Update button text temporarily
219
219
  const $text = $copyBtn.querySelector('.button-text');
220
220
  const originalText = $text.textContent;
221
-
221
+
222
222
  $text.textContent = 'Copied!';
223
223
  $copyBtn.classList.remove('btn-primary');
224
224
  $copyBtn.classList.add('btn-success');
225
-
225
+
226
226
  // Reset after 2 seconds
227
227
  setTimeout(() => {
228
228
  $text.textContent = originalText;
229
229
  $copyBtn.classList.remove('btn-success');
230
230
  $copyBtn.classList.add('btn-primary');
231
231
  }, 2000);
232
-
232
+
233
233
  } catch (err) {
234
234
  console.error('Failed to copy referral link:', err);
235
235
  webManager.utilities().showNotification('Failed to copy referral link', 'danger');
@@ -240,7 +240,7 @@ async function handleCopyReferralCode() {
240
240
  function generateFakeReferrals() {
241
241
  const now = Date.now();
242
242
  const oneDay = 24 * 60 * 60 * 1000;
243
-
243
+
244
244
  return [
245
245
  {
246
246
  uid: 'user_k9m2n8p4q1r7',