@underpostnet/underpost 2.96.1 → 2.97.1
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/.dockerignore +1 -2
- package/.env.development +0 -3
- package/.env.production +0 -3
- package/.env.test +0 -3
- package/.prettierignore +1 -2
- package/README.md +31 -31
- package/baremetal/commission-workflows.json +94 -17
- package/bin/deploy.js +1 -1
- package/cli.md +75 -41
- package/conf.js +1 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +4 -4
- package/package.json +3 -2
- package/packer/scripts/fuse-tar-root +3 -3
- package/scripts/disk-clean.sh +128 -187
- package/scripts/gpu-diag.sh +2 -2
- package/scripts/ip-info.sh +11 -11
- package/scripts/ipxe-setup.sh +197 -0
- package/scripts/maas-upload-boot-resource.sh +1 -1
- package/scripts/nvim.sh +1 -1
- package/scripts/packer-setup.sh +13 -13
- package/scripts/ports-ls.sh +31 -0
- package/scripts/quick-tftp.sh +19 -0
- package/scripts/rocky-setup.sh +2 -2
- package/scripts/rpmfusion-ffmpeg-setup.sh +4 -4
- package/scripts/ssl.sh +7 -7
- package/src/api/document/document.controller.js +15 -0
- package/src/api/document/document.model.js +44 -1
- package/src/api/document/document.router.js +2 -0
- package/src/api/document/document.service.js +398 -26
- package/src/cli/baremetal.js +2001 -463
- package/src/cli/cloud-init.js +354 -231
- package/src/cli/cluster.js +51 -53
- package/src/cli/db.js +22 -0
- package/src/cli/deploy.js +7 -3
- package/src/cli/image.js +1 -0
- package/src/cli/index.js +40 -37
- package/src/cli/lxd.js +3 -3
- package/src/cli/run.js +78 -12
- package/src/cli/ssh.js +1 -1
- package/src/client/components/core/Css.js +16 -2
- package/src/client/components/core/Input.js +3 -1
- package/src/client/components/core/Modal.js +125 -159
- package/src/client/components/core/Panel.js +436 -31
- package/src/client/components/core/PanelForm.js +222 -37
- package/src/client/components/core/SearchBox.js +801 -0
- package/src/client/components/core/Translate.js +11 -0
- package/src/client/services/document/document.service.js +42 -0
- package/src/index.js +1 -1
- package/src/server/dns.js +12 -6
- package/src/server/start.js +14 -6
|
@@ -2,8 +2,8 @@ import { getId, isValidDate, newInstance } from './CommonJs.js';
|
|
|
2
2
|
import { LoadingAnimation } from '../core/LoadingAnimation.js';
|
|
3
3
|
import { Validator } from '../core/Validator.js';
|
|
4
4
|
import { Input } from '../core/Input.js';
|
|
5
|
-
import { darkTheme, ThemeEvents } from './Css.js';
|
|
6
|
-
import { append, getDataFromInputFile, htmls, s } from './VanillaJs.js';
|
|
5
|
+
import { darkTheme, ThemeEvents, subThemeManager, lightenHex, darkenHex } from './Css.js';
|
|
6
|
+
import { append, copyData, getDataFromInputFile, htmls, s, sa } from './VanillaJs.js';
|
|
7
7
|
import { BtnIcon } from './BtnIcon.js';
|
|
8
8
|
import { Translate } from './Translate.js';
|
|
9
9
|
import { DropDown } from './DropDown.js';
|
|
@@ -14,6 +14,9 @@ import { RichText } from './RichText.js';
|
|
|
14
14
|
import { loggerFactory } from './Logger.js';
|
|
15
15
|
import { Badge } from './Badge.js';
|
|
16
16
|
import { Content } from './Content.js';
|
|
17
|
+
import { DocumentService } from '../../services/document/document.service.js';
|
|
18
|
+
import { NotificationManager } from './NotificationManager.js';
|
|
19
|
+
import { getApiBaseUrl } from '../../services/core/core.service.js';
|
|
17
20
|
|
|
18
21
|
const logger = loggerFactory(import.meta);
|
|
19
22
|
|
|
@@ -30,6 +33,10 @@ const Panel = {
|
|
|
30
33
|
originData: () => [],
|
|
31
34
|
filesData: () => [],
|
|
32
35
|
onClick: () => {},
|
|
36
|
+
share: {
|
|
37
|
+
copyLink: false,
|
|
38
|
+
},
|
|
39
|
+
showCreatorProfile: false,
|
|
33
40
|
},
|
|
34
41
|
) {
|
|
35
42
|
const idPanel = options?.idPanel ? options.idPanel : getId(this.Tokens, `${idPanel}-`);
|
|
@@ -87,6 +94,62 @@ const Panel = {
|
|
|
87
94
|
htmls(`.${idPanel}-cell-col-a-${id}`, render);
|
|
88
95
|
},
|
|
89
96
|
});
|
|
97
|
+
if (options.share && options.share.copyLink) {
|
|
98
|
+
EventsUI.onClick(
|
|
99
|
+
`.${idPanel}-btn-copy-share-${id}`,
|
|
100
|
+
async (e) => {
|
|
101
|
+
try {
|
|
102
|
+
const shareUrl = `${window.location.origin}${window.location.pathname}?cid=${obj._id}`;
|
|
103
|
+
await copyData(shareUrl);
|
|
104
|
+
await NotificationManager.Push({
|
|
105
|
+
status: 'success',
|
|
106
|
+
html: html`<div>${Translate.Render('link-copied')}</div>`,
|
|
107
|
+
});
|
|
108
|
+
// Track the copy share link event
|
|
109
|
+
await DocumentService.patch({ id: obj._id, action: 'copy-share-link' });
|
|
110
|
+
// Update the count in the UI - read current value from span first
|
|
111
|
+
const countSpan = s(`.${idPanel}-share-count-${id}`);
|
|
112
|
+
if (countSpan) {
|
|
113
|
+
const currentCount = parseInt(countSpan.textContent) || 0;
|
|
114
|
+
const newCount = currentCount + 1;
|
|
115
|
+
htmls(`.${idPanel}-share-count-${id}`, newCount);
|
|
116
|
+
} else {
|
|
117
|
+
// Create count badge if it didn't exist before (was 0)
|
|
118
|
+
const btn = s(`.${idPanel}-btn-copy-share-${id}`);
|
|
119
|
+
if (btn) {
|
|
120
|
+
const countBadge = document.createElement('span');
|
|
121
|
+
countBadge.className = `${idPanel}-share-count-${id}`;
|
|
122
|
+
countBadge.style.cssText =
|
|
123
|
+
'position: absolute; top: -4px; right: -4px; background: #666; color: white; border-radius: 10px; padding: 1px 5px; font-size: 10px; font-weight: bold; min-width: 16px; text-align: center;';
|
|
124
|
+
countBadge.textContent = '1';
|
|
125
|
+
btn.appendChild(countBadge);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} catch (error) {
|
|
129
|
+
logger.error('Error copying share link:', error);
|
|
130
|
+
await NotificationManager.Push({
|
|
131
|
+
status: 'error',
|
|
132
|
+
html: html`<div>${Translate.Render('error-copying-link')}</div>`,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{ context: 'modal' },
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// Add tooltip hover effect
|
|
140
|
+
setTimeout(() => {
|
|
141
|
+
const btn = s(`.${idPanel}-btn-copy-share-${id}`);
|
|
142
|
+
const tooltip = s(`.${idPanel}-share-tooltip-${id}`);
|
|
143
|
+
if (btn && tooltip) {
|
|
144
|
+
btn.addEventListener('mouseenter', () => {
|
|
145
|
+
tooltip.style.opacity = '1';
|
|
146
|
+
});
|
|
147
|
+
btn.addEventListener('mouseleave', () => {
|
|
148
|
+
tooltip.style.opacity = '0';
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
90
153
|
EventsUI.onClick(
|
|
91
154
|
`.${idPanel}-btn-delete-${id}`,
|
|
92
155
|
async (e) => {
|
|
@@ -99,6 +162,8 @@ const Panel = {
|
|
|
99
162
|
);
|
|
100
163
|
EventsUI.onClick(`.${idPanel}-btn-edit-${id}`, async () => {
|
|
101
164
|
logger.warn('edit', obj);
|
|
165
|
+
const searchId = String(obj._id || obj.id);
|
|
166
|
+
|
|
102
167
|
if (obj._id) Panel.Tokens[idPanel].editId = obj._id;
|
|
103
168
|
else if (obj.id) Panel.Tokens[idPanel].editId = obj.id;
|
|
104
169
|
|
|
@@ -106,14 +171,11 @@ const Panel = {
|
|
|
106
171
|
s(`.btn-${idPanel}-label-add`).classList.add('hide');
|
|
107
172
|
|
|
108
173
|
openPanelForm();
|
|
109
|
-
// s(
|
|
110
|
-
s(`.${scrollClassContainer}`).scrollTop = 0;
|
|
111
|
-
|
|
174
|
+
// s(`.${scrollClassContainer}`).scrollTop = 0;
|
|
112
175
|
const originData = options.originData();
|
|
113
176
|
const filesData = options.filesData();
|
|
114
177
|
|
|
115
178
|
// Convert IDs to strings for comparison to handle ObjectId vs string issues
|
|
116
|
-
const searchId = String(obj._id || obj.id);
|
|
117
179
|
const foundOrigin = originData.find((d) => String(d._id || d.id) === searchId);
|
|
118
180
|
const foundFiles = filesData.find((d) => String(d._id || d.id) === searchId);
|
|
119
181
|
|
|
@@ -133,6 +195,8 @@ const Panel = {
|
|
|
133
195
|
);
|
|
134
196
|
}
|
|
135
197
|
|
|
198
|
+
// Clear previous form values then populate with the current item's data
|
|
199
|
+
Input.cleanValues(formData);
|
|
136
200
|
Input.setValues(formData, obj, foundOrigin, foundFiles);
|
|
137
201
|
if (options.on.initEdit) await options.on.initEdit({ data: obj });
|
|
138
202
|
});
|
|
@@ -144,34 +208,120 @@ const Panel = {
|
|
|
144
208
|
e.preventDefault();
|
|
145
209
|
// if (options.onClick) await options.onClick({ payload });
|
|
146
210
|
};
|
|
211
|
+
|
|
212
|
+
// Add theme change handler for creator profile header
|
|
213
|
+
if (options.showCreatorProfile && obj.userInfo) {
|
|
214
|
+
const updateCreatorProfileTheme = () => {
|
|
215
|
+
const profileHeader = s(`.creator-profile-header-${id}`);
|
|
216
|
+
if (profileHeader) {
|
|
217
|
+
profileHeader.style.borderBottom = `1px solid ${darkTheme ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.08)'}`;
|
|
218
|
+
profileHeader.style.background = `${darkTheme ? 'rgba(255,255,255,0.02)' : 'rgba(0,0,0,0.02)'}`;
|
|
219
|
+
|
|
220
|
+
// Update avatar border if it's an image
|
|
221
|
+
const avatarImg = profileHeader.querySelector('.creator-avatar');
|
|
222
|
+
if (avatarImg && avatarImg.tagName === 'IMG') {
|
|
223
|
+
avatarImg.style.border = `2px solid ${darkTheme ? 'rgba(102, 126, 234, 0.5)' : 'rgba(102, 126, 234, 0.3)'}`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Update username color
|
|
227
|
+
const username = profileHeader.querySelector('.creator-username');
|
|
228
|
+
if (username) {
|
|
229
|
+
username.style.color = `${darkTheme ? 'rgba(255,255,255,0.9)' : 'rgba(0,0,0,0.85)'}`;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Update "Creator" label color
|
|
233
|
+
const creatorLabel = username?.nextElementSibling;
|
|
234
|
+
if (creatorLabel) {
|
|
235
|
+
creatorLabel.style.color = `${darkTheme ? 'rgba(255,255,255,0.5)' : 'rgba(0,0,0,0.45)'}`;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// Register theme change handler
|
|
241
|
+
const profileThemeHandlerId = `${id}-creator-profile-theme`;
|
|
242
|
+
ThemeEvents[profileThemeHandlerId] = updateCreatorProfileTheme;
|
|
243
|
+
}
|
|
147
244
|
});
|
|
148
245
|
if (s(`.${idPanel}-${id}`)) s(`.${idPanel}-${id}`).remove();
|
|
149
|
-
|
|
246
|
+
|
|
247
|
+
// Check if document is public (from obj.isPublic field)
|
|
248
|
+
const isPublic = obj.isPublic === true;
|
|
249
|
+
// Visibility icon: globe for public, padlock for private
|
|
250
|
+
const visibilityIcon = isPublic
|
|
251
|
+
? '<i class="fas fa-globe" title="Public document"></i>'
|
|
252
|
+
: '<i class="fas fa-lock" title="Private document"></i>';
|
|
253
|
+
|
|
254
|
+
return html` <div class="in box-shadow ${idPanel} ${idPanel}-${id}" style="position: relative;">
|
|
150
255
|
<div class="fl ${idPanel}-tools session-fl-log-in ${obj.tools ? '' : 'hide'}">
|
|
151
256
|
${await BtnIcon.Render({
|
|
152
|
-
class: `in flr main-btn-menu action-bar-box ${idPanel}-btn-tool ${idPanel}-btn-
|
|
153
|
-
label: html`<div class="abs center"><i class="fas fa-
|
|
257
|
+
class: `in flr main-btn-menu action-bar-box ${idPanel}-btn-tool ${idPanel}-btn-delete-${id}`,
|
|
258
|
+
label: html`<div class="abs center"><i class="fas fa-trash"></i></div>`,
|
|
154
259
|
useVisibilityHover: true,
|
|
155
260
|
tooltipHtml: await Badge.Render({
|
|
156
261
|
id: `tooltip-${idPanel}-${id}`,
|
|
157
|
-
text: `${Translate.Render(`
|
|
262
|
+
text: `${Translate.Render(`delete`)}`,
|
|
158
263
|
classList: '',
|
|
159
|
-
style: { top: `-22px`, left: '-
|
|
264
|
+
style: { top: `-22px`, left: '-13px' },
|
|
160
265
|
}),
|
|
161
266
|
})}
|
|
162
267
|
${await BtnIcon.Render({
|
|
163
|
-
class: `in flr main-btn-menu action-bar-box ${idPanel}-btn-tool ${idPanel}-btn-
|
|
164
|
-
label: html`<div class="abs center"><i class="fas fa-
|
|
268
|
+
class: `in flr main-btn-menu action-bar-box ${idPanel}-btn-tool ${idPanel}-btn-edit-${id}`,
|
|
269
|
+
label: html`<div class="abs center"><i class="fas fa-edit"></i></div>`,
|
|
165
270
|
useVisibilityHover: true,
|
|
166
271
|
tooltipHtml: await Badge.Render({
|
|
167
272
|
id: `tooltip-${idPanel}-${id}`,
|
|
168
|
-
text: `${Translate.Render(`
|
|
273
|
+
text: `${Translate.Render(`edit`)}`,
|
|
169
274
|
classList: '',
|
|
170
|
-
style: { top: `-22px`, left: '-
|
|
275
|
+
style: { top: `-22px`, left: '-5px' },
|
|
171
276
|
}),
|
|
172
277
|
})}
|
|
173
278
|
</div>
|
|
174
279
|
<div class="in container-${idPanel}-${id}">
|
|
280
|
+
<div class="panel-visibility-icon">${visibilityIcon}</div>
|
|
281
|
+
${options.showCreatorProfile && obj.userInfo
|
|
282
|
+
? html`<div
|
|
283
|
+
class="creator-profile-header creator-profile-header-${id}"
|
|
284
|
+
style="padding: 10px 12px; margin-bottom: 10px; border-bottom: 1px solid ${darkTheme
|
|
285
|
+
? 'rgba(255,255,255,0.1)'
|
|
286
|
+
: 'rgba(0,0,0,0.08)'}; display: flex; align-items: center; gap: 10px; background: ${darkTheme
|
|
287
|
+
? 'rgba(255,255,255,0.02)'
|
|
288
|
+
: 'rgba(0,0,0,0.02)'}; border-radius: 4px 4px 0 0;"
|
|
289
|
+
>
|
|
290
|
+
${obj.userInfo.profileImageId && obj.userInfo.profileImageId._id
|
|
291
|
+
? html`<img
|
|
292
|
+
class="creator-avatar"
|
|
293
|
+
src="${getApiBaseUrl({ id: obj.userInfo.profileImageId._id, endpoint: 'file/blob' })}"
|
|
294
|
+
alt="${obj.userInfo.username || obj.userInfo.email}"
|
|
295
|
+
style="width: 36px; height: 36px; border-radius: 50%; object-fit: cover; border: 2px solid ${darkTheme
|
|
296
|
+
? 'rgba(102, 126, 234, 0.5)'
|
|
297
|
+
: 'rgba(102, 126, 234, 0.3)'}; flex-shrink: 0; box-shadow: 0 2px 8px rgba(0,0,0,0.15);"
|
|
298
|
+
title="${obj.userInfo.email || obj.userInfo.username}"
|
|
299
|
+
/>`
|
|
300
|
+
: html`<div
|
|
301
|
+
class="creator-avatar"
|
|
302
|
+
style="width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 16px; flex-shrink: 0; box-shadow: 0 2px 8px rgba(0,0,0,0.15);"
|
|
303
|
+
title="${obj.userInfo.email || obj.userInfo.username}"
|
|
304
|
+
>
|
|
305
|
+
${(obj.userInfo.username || obj.userInfo.email || 'U').charAt(0).toUpperCase()}
|
|
306
|
+
</div>`}
|
|
307
|
+
<div style="display: flex; flex-direction: column; min-width: 0; flex: 1;">
|
|
308
|
+
<span
|
|
309
|
+
class="creator-username"
|
|
310
|
+
style="font-size: 14px; font-weight: 600; color: ${darkTheme
|
|
311
|
+
? 'rgba(255,255,255,0.9)'
|
|
312
|
+
: 'rgba(0,0,0,0.85)'}; line-height: 1.4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"
|
|
313
|
+
>
|
|
314
|
+
${obj.userInfo.username || obj.userInfo.email || 'Unknown'}
|
|
315
|
+
</span>
|
|
316
|
+
<span
|
|
317
|
+
style="font-size: 11px; color: ${darkTheme
|
|
318
|
+
? 'rgba(255,255,255,0.5)'
|
|
319
|
+
: 'rgba(0,0,0,0.45)'}; line-height: 1.3; text-transform: uppercase; letter-spacing: 0.5px; font-weight: 500;"
|
|
320
|
+
>Creator</span
|
|
321
|
+
>
|
|
322
|
+
</div>
|
|
323
|
+
</div>`
|
|
324
|
+
: ''}
|
|
175
325
|
<div class="in ${idPanel}-head">
|
|
176
326
|
<div class="in ${idPanel}-title">
|
|
177
327
|
${options.titleIcon}
|
|
@@ -201,18 +351,79 @@ const Panel = {
|
|
|
201
351
|
}
|
|
202
352
|
|
|
203
353
|
if (formData.find((f) => f.model === infoKey && f.panel && f.panel.type === 'tags')) {
|
|
204
|
-
|
|
354
|
+
// Function to render tags with current theme
|
|
355
|
+
const renderTags = async () => {
|
|
205
356
|
let tagRender = html``;
|
|
206
357
|
for (const tag of obj[infoKey]) {
|
|
358
|
+
// Use subThemeManager colors for consistent theming
|
|
359
|
+
const themeColor = darkTheme ? subThemeManager.darkColor : subThemeManager.lightColor;
|
|
360
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
361
|
+
|
|
362
|
+
let tagBg, tagColor;
|
|
363
|
+
if (darkTheme) {
|
|
364
|
+
tagBg = hasThemeColor ? darkenHex(themeColor, 0.6) : '#4a4a4a';
|
|
365
|
+
tagColor = hasThemeColor ? lightenHex(themeColor, 0.7) : '#ffffff';
|
|
366
|
+
} else {
|
|
367
|
+
tagBg = hasThemeColor ? lightenHex(themeColor, 0.7) : '#a2a2a2';
|
|
368
|
+
tagColor = hasThemeColor ? darkenHex(themeColor, 0.5) : '#ffffff';
|
|
369
|
+
}
|
|
370
|
+
|
|
207
371
|
tagRender += await Badge.Render({
|
|
208
372
|
text: tag,
|
|
209
|
-
style: { color:
|
|
210
|
-
classList: 'inl',
|
|
211
|
-
style: {
|
|
373
|
+
style: { color: tagColor },
|
|
374
|
+
classList: 'inl panel-tag-clickable',
|
|
375
|
+
style: {
|
|
376
|
+
margin: '3px',
|
|
377
|
+
background: tagBg,
|
|
378
|
+
color: tagColor,
|
|
379
|
+
cursor: 'pointer',
|
|
380
|
+
transition: 'all 0.2s ease',
|
|
381
|
+
},
|
|
212
382
|
});
|
|
213
383
|
}
|
|
214
|
-
if (s(`.tag-render-${id}`))
|
|
215
|
-
|
|
384
|
+
if (s(`.tag-render-${id}`)) {
|
|
385
|
+
htmls(`.tag-render-${id}`, tagRender);
|
|
386
|
+
|
|
387
|
+
// Add click handlers to tags for search integration
|
|
388
|
+
setTimeout(() => {
|
|
389
|
+
const tagElements = sa(`.tag-render-${id} .panel-tag-clickable`);
|
|
390
|
+
tagElements.forEach((tagEl) => {
|
|
391
|
+
tagEl.onclick = (e) => {
|
|
392
|
+
e.stopPropagation();
|
|
393
|
+
const tagText = tagEl.textContent.trim();
|
|
394
|
+
|
|
395
|
+
// Open search bar if closed
|
|
396
|
+
if (
|
|
397
|
+
!s('.main-body-btn-ui-bar-custom-open').classList.contains('hide') ||
|
|
398
|
+
!s(`.main-body-btn-ui-open`).classList.contains('hide')
|
|
399
|
+
)
|
|
400
|
+
s('.main-body-btn-bar-custom').click();
|
|
401
|
+
|
|
402
|
+
// Find and populate search box if it exists
|
|
403
|
+
const searchBox = s('.top-bar-search-box');
|
|
404
|
+
if (searchBox) {
|
|
405
|
+
searchBox.value = tagText;
|
|
406
|
+
searchBox.focus();
|
|
407
|
+
|
|
408
|
+
// Trigger input event to start search
|
|
409
|
+
const inputEvent = new Event('input', { bubbles: true });
|
|
410
|
+
searchBox.dispatchEvent(inputEvent);
|
|
411
|
+
|
|
412
|
+
logger.info(`Tag clicked: ${tagText} - search triggered`);
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
});
|
|
416
|
+
}, 100);
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
// Initial render
|
|
421
|
+
setTimeout(renderTags);
|
|
422
|
+
|
|
423
|
+
// Add theme change handler for this tag set
|
|
424
|
+
const tagThemeHandlerId = `${id}-tags-${infoKey}-theme`;
|
|
425
|
+
ThemeEvents[tagThemeHandlerId] = renderTags;
|
|
426
|
+
|
|
216
427
|
return html``;
|
|
217
428
|
}
|
|
218
429
|
{
|
|
@@ -266,6 +477,32 @@ const Panel = {
|
|
|
266
477
|
</div>
|
|
267
478
|
</div>
|
|
268
479
|
</div>
|
|
480
|
+
${options.share && options.share.copyLink
|
|
481
|
+
? html`<div
|
|
482
|
+
class="${idPanel}-share-btn-container ${idPanel}-share-btn-container-${id}"
|
|
483
|
+
style="position: absolute; bottom: 8px; right: 8px; z-index: 2;"
|
|
484
|
+
>
|
|
485
|
+
<button
|
|
486
|
+
class="btn-icon ${idPanel}-btn-copy-share-${id}"
|
|
487
|
+
style="background: transparent; color: #888; border: none; border-radius: 50%; width: 40px; height: 40px; cursor: pointer; display: flex; align-items: center; justify-content: center; position: relative; transition: all 0.3s ease;"
|
|
488
|
+
>
|
|
489
|
+
<i class="fas fa-link" style="font-size: 20px;"></i>
|
|
490
|
+
${obj.totalCopyShareLinkCount && obj.totalCopyShareLinkCount > 0
|
|
491
|
+
? html`<span
|
|
492
|
+
class="${idPanel}-share-count-${id}"
|
|
493
|
+
style="position: absolute; top: -4px; right: -4px; background: #666; color: white; border-radius: 10px; padding: 1px 5px; font-size: 10px; font-weight: bold; min-width: 16px; text-align: center;"
|
|
494
|
+
>${obj.totalCopyShareLinkCount}</span
|
|
495
|
+
>`
|
|
496
|
+
: ''}
|
|
497
|
+
</button>
|
|
498
|
+
<div
|
|
499
|
+
class="${idPanel}-share-tooltip-${id}"
|
|
500
|
+
style="position: absolute; bottom: 50px; right: 0; background: rgba(0,0,0,0.8); color: white; padding: 6px 10px; border-radius: 4px; font-size: 12px; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.3s ease;"
|
|
501
|
+
>
|
|
502
|
+
${Translate.Render('copy-share-link')}
|
|
503
|
+
</div>
|
|
504
|
+
</div>`
|
|
505
|
+
: ''}
|
|
269
506
|
</div>`;
|
|
270
507
|
};
|
|
271
508
|
|
|
@@ -410,6 +647,11 @@ const Panel = {
|
|
|
410
647
|
</div>`,
|
|
411
648
|
// disabled: true,
|
|
412
649
|
// disabledEye: true,
|
|
650
|
+
})}
|
|
651
|
+
${await BtnIcon.Render({
|
|
652
|
+
class: `inl section-mp btn-custom btn-${idPanel}-clean-file`,
|
|
653
|
+
label: html`<i class="fa-solid fa-file-circle-xmark"></i> ${Translate.Render('clear-file')}`,
|
|
654
|
+
type: 'button',
|
|
413
655
|
})}`;
|
|
414
656
|
break;
|
|
415
657
|
default:
|
|
@@ -476,6 +718,15 @@ const Panel = {
|
|
|
476
718
|
s(`.btn-${idPanel}-clean`).onclick = () => {
|
|
477
719
|
Input.cleanValues(formData);
|
|
478
720
|
};
|
|
721
|
+
s(`.btn-${idPanel}-clean-file`).onclick = () => {
|
|
722
|
+
// Clear file input specifically
|
|
723
|
+
const fileFormData = formData.find((f) => f.inputType === 'file');
|
|
724
|
+
if (fileFormData && s(`.${fileFormData.id}`)) {
|
|
725
|
+
s(`.${fileFormData.id}`).value = '';
|
|
726
|
+
s(`.${fileFormData.id}`).inputFiles = null;
|
|
727
|
+
htmls(`.file-name-render-${fileFormData.id}`, `${fileNameInputExtDefaultContent}`);
|
|
728
|
+
}
|
|
729
|
+
};
|
|
479
730
|
s(`.btn-${idPanel}-close`).onclick = (e) => {
|
|
480
731
|
e.preventDefault();
|
|
481
732
|
s(`.${idPanel}-form-body`).style.opacity = 0;
|
|
@@ -494,10 +745,26 @@ const Panel = {
|
|
|
494
745
|
};
|
|
495
746
|
s(`.btn-${idPanel}-add`).onclick = async (e) => {
|
|
496
747
|
e.preventDefault();
|
|
497
|
-
|
|
748
|
+
|
|
749
|
+
// Clean all form inputs and reset data scope
|
|
750
|
+
Input.cleanValues(formData);
|
|
751
|
+
|
|
752
|
+
// Clean file input specifically
|
|
753
|
+
const fileFormData = formData.find((f) => f.inputType === 'file');
|
|
754
|
+
if (fileFormData && s(`.${fileFormData.id}`)) {
|
|
755
|
+
s(`.${fileFormData.id}`).value = '';
|
|
756
|
+
s(`.${fileFormData.id}`).inputFiles = null;
|
|
757
|
+
htmls(`.file-name-render-${fileFormData.id}`, `${fileNameInputExtDefaultContent}`);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// Reset edit ID to ensure we're in "add" mode
|
|
498
761
|
Panel.Tokens[idPanel].editId = undefined;
|
|
762
|
+
|
|
763
|
+
// Update button labels
|
|
499
764
|
s(`.btn-${idPanel}-label-add`).classList.remove('hide');
|
|
500
765
|
s(`.btn-${idPanel}-label-edit`).classList.add('hide');
|
|
766
|
+
|
|
767
|
+
// Scroll to top
|
|
501
768
|
s(`.${scrollClassContainer}`).scrollTop = 0;
|
|
502
769
|
|
|
503
770
|
openPanelForm();
|
|
@@ -544,6 +811,29 @@ const Panel = {
|
|
|
544
811
|
? getDarkStyles(idPanel, scrollClassContainer)
|
|
545
812
|
: getLightStyles(idPanel, scrollClassContainer);
|
|
546
813
|
}
|
|
814
|
+
|
|
815
|
+
// Update tag hover styles
|
|
816
|
+
const tagStyleElement = s(`.${idPanel}-tag-styles`);
|
|
817
|
+
if (tagStyleElement) {
|
|
818
|
+
const themeColor = darkTheme ? subThemeManager.darkColor : subThemeManager.lightColor;
|
|
819
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
820
|
+
let hoverBg;
|
|
821
|
+
if (darkTheme) {
|
|
822
|
+
hoverBg = hasThemeColor ? darkenHex(themeColor, 0.5) : '#5a5a5a';
|
|
823
|
+
} else {
|
|
824
|
+
hoverBg = hasThemeColor ? lightenHex(themeColor, 0.6) : '#8a8a8a';
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
tagStyleElement.textContent = css`
|
|
828
|
+
.panel-tag-clickable:hover {
|
|
829
|
+
background: ${hoverBg} !important;
|
|
830
|
+
transform: scale(1.05);
|
|
831
|
+
}
|
|
832
|
+
.panel-tag-clickable:active {
|
|
833
|
+
transform: scale(0.98);
|
|
834
|
+
}
|
|
835
|
+
`;
|
|
836
|
+
}
|
|
547
837
|
};
|
|
548
838
|
|
|
549
839
|
// Add theme change listener
|
|
@@ -562,15 +852,39 @@ const Panel = {
|
|
|
562
852
|
width: 100%;
|
|
563
853
|
}
|
|
564
854
|
.${idPanel}-title {
|
|
565
|
-
color:
|
|
855
|
+
color: ${(() => {
|
|
856
|
+
const themeColor = darkTheme ? subThemeManager.darkColor : subThemeManager.lightColor;
|
|
857
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
858
|
+
if (hasThemeColor) {
|
|
859
|
+
return darkTheme ? lightenHex(themeColor, 0.3) : darkenHex(themeColor, 0.2);
|
|
860
|
+
} else {
|
|
861
|
+
return darkTheme ? '#8a85ff' : 'rgba(109, 104, 255, 1)';
|
|
862
|
+
}
|
|
863
|
+
})()};
|
|
566
864
|
font-size: 24px;
|
|
567
865
|
padding: 5px;
|
|
568
866
|
}
|
|
569
867
|
.a-title-${idPanel} {
|
|
570
|
-
color:
|
|
868
|
+
color: ${(() => {
|
|
869
|
+
const themeColor = darkTheme ? subThemeManager.darkColor : subThemeManager.lightColor;
|
|
870
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
871
|
+
if (hasThemeColor) {
|
|
872
|
+
return darkTheme ? lightenHex(themeColor, 0.3) : darkenHex(themeColor, 0.2);
|
|
873
|
+
} else {
|
|
874
|
+
return darkTheme ? '#8a85ff' : 'rgba(109, 104, 255, 1)';
|
|
875
|
+
}
|
|
876
|
+
})()};
|
|
571
877
|
}
|
|
572
878
|
.a-title-${idPanel}:hover {
|
|
573
|
-
color:
|
|
879
|
+
color: ${(() => {
|
|
880
|
+
const themeColor = darkTheme ? subThemeManager.darkColor : subThemeManager.lightColor;
|
|
881
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
882
|
+
if (hasThemeColor) {
|
|
883
|
+
return darkTheme ? lightenHex(themeColor, 0.5) : lightenHex(themeColor, 0.3);
|
|
884
|
+
} else {
|
|
885
|
+
return darkTheme ? '#ffb74d' : '#e89f4c';
|
|
886
|
+
}
|
|
887
|
+
})()};
|
|
574
888
|
}
|
|
575
889
|
.${idPanel}-row {
|
|
576
890
|
padding: 5px;
|
|
@@ -587,6 +901,7 @@ const Panel = {
|
|
|
587
901
|
margin-left: 10px;
|
|
588
902
|
top: -7px;
|
|
589
903
|
}
|
|
904
|
+
|
|
590
905
|
.${idPanel}-row-key {
|
|
591
906
|
}
|
|
592
907
|
.${idPanel}-row-value {
|
|
@@ -617,8 +932,53 @@ const Panel = {
|
|
|
617
932
|
color: #000000 !important;
|
|
618
933
|
font-size: 17px !important;
|
|
619
934
|
}
|
|
935
|
+
.${idPanel}-share-btn-container button:hover {
|
|
936
|
+
background: transparent !important;
|
|
937
|
+
transform: scale(1.1);
|
|
938
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4) !important;
|
|
939
|
+
}
|
|
940
|
+
.${idPanel}-share-btn-container button:focus {
|
|
941
|
+
outline: none;
|
|
942
|
+
background: transparent !important;
|
|
943
|
+
}
|
|
944
|
+
.${idPanel}-share-btn-container button:focus {
|
|
945
|
+
outline: none;
|
|
946
|
+
background: transparent !important;
|
|
947
|
+
}
|
|
948
|
+
.${idPanel}-share-btn-container button:active {
|
|
949
|
+
transform: scale(0.95);
|
|
950
|
+
}
|
|
951
|
+
.${idPanel}-share-btn-container span[class*='share-count'] {
|
|
952
|
+
animation: ${idPanel}-share-pulse 2s infinite;
|
|
953
|
+
}
|
|
954
|
+
@keyframes ${idPanel}-share-pulse {
|
|
955
|
+
0%,
|
|
956
|
+
100% {
|
|
957
|
+
transform: scale(1);
|
|
958
|
+
}
|
|
959
|
+
50% {
|
|
960
|
+
transform: scale(1.1);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
620
963
|
</style>
|
|
621
964
|
<style class="${idPanel}-styles"></style>
|
|
965
|
+
<style class="${idPanel}-tag-styles">
|
|
966
|
+
.panel-tag-clickable:hover {
|
|
967
|
+
background: ${(() => {
|
|
968
|
+
const themeColor = darkTheme ? subThemeManager.darkColor : subThemeManager.lightColor;
|
|
969
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
970
|
+
if (darkTheme) {
|
|
971
|
+
return hasThemeColor ? darkenHex(themeColor, 0.5) : '#5a5a5a';
|
|
972
|
+
} else {
|
|
973
|
+
return hasThemeColor ? lightenHex(themeColor, 0.6) : '#8a8a8a';
|
|
974
|
+
}
|
|
975
|
+
})()} !important;
|
|
976
|
+
transform: scale(1.05);
|
|
977
|
+
}
|
|
978
|
+
.panel-tag-clickable:active {
|
|
979
|
+
transform: scale(0.98);
|
|
980
|
+
}
|
|
981
|
+
</style>
|
|
622
982
|
<div class="${idPanel}-container">
|
|
623
983
|
<div class="in modal ${idPanel}-form-container ${options.formContainerClass ? options.formContainerClass : ''}">
|
|
624
984
|
<div class="in ${idPanel}-form-header">
|
|
@@ -710,6 +1070,19 @@ function getBaseStyles(idPanel, scrollClassContainer) {
|
|
|
710
1070
|
.${idPanel}-dropdown {
|
|
711
1071
|
min-height: 100px;
|
|
712
1072
|
}
|
|
1073
|
+
.panel-visibility-icon {
|
|
1074
|
+
position: absolute;
|
|
1075
|
+
top: 34px;
|
|
1076
|
+
left: 0px;
|
|
1077
|
+
font-size: 14px;
|
|
1078
|
+
opacity: 0.7;
|
|
1079
|
+
transition: opacity 0.2s ease;
|
|
1080
|
+
pointer-events: none;
|
|
1081
|
+
z-index: 10;
|
|
1082
|
+
}
|
|
1083
|
+
.${idPanel}:hover .panel-visibility-icon {
|
|
1084
|
+
opacity: 1;
|
|
1085
|
+
}
|
|
713
1086
|
`;
|
|
714
1087
|
}
|
|
715
1088
|
|
|
@@ -726,15 +1099,27 @@ function getLightStyles(idPanel, scrollClassContainer) {
|
|
|
726
1099
|
background: #ffffff;
|
|
727
1100
|
}
|
|
728
1101
|
.${idPanel}-title {
|
|
729
|
-
color:
|
|
1102
|
+
color: ${(() => {
|
|
1103
|
+
const themeColor = subThemeManager.lightColor;
|
|
1104
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
1105
|
+
return hasThemeColor ? darkenHex(themeColor, 0.2) : 'rgba(109, 104, 255, 1)';
|
|
1106
|
+
})()};
|
|
730
1107
|
font-size: 24px;
|
|
731
1108
|
padding: 5px;
|
|
732
1109
|
}
|
|
733
1110
|
.a-title-${idPanel} {
|
|
734
|
-
color:
|
|
1111
|
+
color: ${(() => {
|
|
1112
|
+
const themeColor = subThemeManager.lightColor;
|
|
1113
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
1114
|
+
return hasThemeColor ? darkenHex(themeColor, 0.2) : 'rgba(109, 104, 255, 1)';
|
|
1115
|
+
})()};
|
|
735
1116
|
}
|
|
736
1117
|
.a-title-${idPanel}:hover {
|
|
737
|
-
color:
|
|
1118
|
+
color: ${(() => {
|
|
1119
|
+
const themeColor = subThemeManager.lightColor;
|
|
1120
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
1121
|
+
return hasThemeColor ? lightenHex(themeColor, 0.3) : '#e89f4c';
|
|
1122
|
+
})()};
|
|
738
1123
|
}
|
|
739
1124
|
.${idPanel}-row-pin-value {
|
|
740
1125
|
font-size: 20px;
|
|
@@ -748,6 +1133,10 @@ function getLightStyles(idPanel, scrollClassContainer) {
|
|
|
748
1133
|
color: #000000 !important;
|
|
749
1134
|
font-size: 17px !important;
|
|
750
1135
|
}
|
|
1136
|
+
.panel-visibility-icon .fa-globe,
|
|
1137
|
+
.panel-visibility-icon .fa-lock {
|
|
1138
|
+
color: #666;
|
|
1139
|
+
}
|
|
751
1140
|
`;
|
|
752
1141
|
}
|
|
753
1142
|
|
|
@@ -764,15 +1153,27 @@ function getDarkStyles(idPanel, scrollClassContainer) {
|
|
|
764
1153
|
background: #3a3a3a;
|
|
765
1154
|
}
|
|
766
1155
|
.${idPanel}-title {
|
|
767
|
-
color:
|
|
1156
|
+
color: ${(() => {
|
|
1157
|
+
const themeColor = subThemeManager.darkColor;
|
|
1158
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
1159
|
+
return hasThemeColor ? lightenHex(themeColor, 0.3) : '#8a85ff';
|
|
1160
|
+
})()};
|
|
768
1161
|
font-size: 24px;
|
|
769
1162
|
padding: 5px;
|
|
770
1163
|
}
|
|
771
1164
|
.a-title-${idPanel} {
|
|
772
|
-
color:
|
|
1165
|
+
color: ${(() => {
|
|
1166
|
+
const themeColor = subThemeManager.darkColor;
|
|
1167
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
1168
|
+
return hasThemeColor ? lightenHex(themeColor, 0.3) : '#8a85ff';
|
|
1169
|
+
})()};
|
|
773
1170
|
}
|
|
774
1171
|
.a-title-${idPanel}:hover {
|
|
775
|
-
color:
|
|
1172
|
+
color: ${(() => {
|
|
1173
|
+
const themeColor = subThemeManager.darkColor;
|
|
1174
|
+
const hasThemeColor = themeColor && themeColor !== null;
|
|
1175
|
+
return hasThemeColor ? lightenHex(themeColor, 0.5) : '#ffb74d';
|
|
1176
|
+
})()};
|
|
776
1177
|
}
|
|
777
1178
|
.${idPanel}-row-pin-value {
|
|
778
1179
|
font-size: 20px;
|
|
@@ -786,6 +1187,10 @@ function getDarkStyles(idPanel, scrollClassContainer) {
|
|
|
786
1187
|
color: #ffffff !important;
|
|
787
1188
|
font-size: 17px !important;
|
|
788
1189
|
}
|
|
1190
|
+
.panel-visibility-icon .fa-globe,
|
|
1191
|
+
.panel-visibility-icon .fa-lock {
|
|
1192
|
+
color: #999;
|
|
1193
|
+
}
|
|
789
1194
|
`;
|
|
790
1195
|
}
|
|
791
1196
|
|