@underpostnet/underpost 2.97.0 → 2.97.5
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/README.md +2 -2
- package/baremetal/commission-workflows.json +33 -3
- package/bin/deploy.js +1 -1
- package/cli.md +7 -2
- package/conf.js +3 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
- package/package.json +1 -1
- package/packer/scripts/fuse-tar-root +3 -3
- package/scripts/disk-clean.sh +23 -23
- package/scripts/gpu-diag.sh +2 -2
- package/scripts/ip-info.sh +11 -11
- package/scripts/maas-upload-boot-resource.sh +1 -1
- package/scripts/nvim.sh +1 -1
- package/scripts/packer-setup.sh +13 -13
- package/scripts/rocky-setup.sh +2 -2
- package/scripts/rpmfusion-ffmpeg-setup.sh +4 -4
- package/scripts/ssl.sh +7 -7
- package/src/api/core/core.service.js +0 -5
- package/src/api/default/default.service.js +7 -5
- package/src/api/document/document.model.js +30 -1
- package/src/api/document/document.router.js +6 -0
- package/src/api/document/document.service.js +423 -51
- package/src/api/file/file.model.js +112 -4
- package/src/api/file/file.ref.json +42 -0
- package/src/api/file/file.service.js +380 -32
- package/src/api/user/user.model.js +38 -1
- package/src/api/user/user.router.js +96 -63
- package/src/api/user/user.service.js +81 -48
- package/src/cli/baremetal.js +689 -329
- package/src/cli/cluster.js +50 -52
- package/src/cli/db.js +424 -166
- package/src/cli/deploy.js +1 -1
- package/src/cli/index.js +12 -1
- package/src/cli/lxd.js +3 -3
- package/src/cli/repository.js +1 -1
- package/src/cli/run.js +2 -1
- package/src/cli/ssh.js +10 -10
- package/src/client/components/core/Account.js +327 -36
- package/src/client/components/core/AgGrid.js +3 -0
- package/src/client/components/core/Auth.js +9 -3
- package/src/client/components/core/Chat.js +2 -2
- package/src/client/components/core/Content.js +159 -78
- package/src/client/components/core/Css.js +16 -2
- package/src/client/components/core/CssCore.js +16 -12
- package/src/client/components/core/FileExplorer.js +115 -8
- package/src/client/components/core/Input.js +204 -11
- package/src/client/components/core/LogIn.js +42 -20
- package/src/client/components/core/Modal.js +257 -177
- package/src/client/components/core/Panel.js +324 -27
- package/src/client/components/core/PanelForm.js +280 -73
- package/src/client/components/core/PublicProfile.js +888 -0
- package/src/client/components/core/Router.js +117 -15
- package/src/client/components/core/SearchBox.js +1117 -0
- package/src/client/components/core/SignUp.js +26 -7
- package/src/client/components/core/SocketIo.js +6 -3
- package/src/client/components/core/Translate.js +98 -0
- package/src/client/components/core/Validator.js +15 -0
- package/src/client/components/core/windowGetDimensions.js +6 -6
- package/src/client/components/default/MenuDefault.js +59 -12
- package/src/client/components/default/RoutesDefault.js +1 -0
- package/src/client/services/core/core.service.js +163 -1
- package/src/client/services/default/default.management.js +451 -64
- package/src/client/services/default/default.service.js +13 -6
- package/src/client/services/document/document.service.js +23 -0
- package/src/client/services/file/file.service.js +43 -16
- package/src/client/services/user/user.service.js +13 -9
- package/src/db/DataBaseProvider.js +1 -1
- package/src/db/mongo/MongooseDB.js +1 -1
- package/src/index.js +1 -1
- package/src/mailer/MailerProvider.js +4 -4
- package/src/runtime/express/Express.js +2 -1
- package/src/runtime/lampp/Lampp.js +2 -2
- package/src/server/auth.js +3 -6
- package/src/server/data-query.js +449 -0
- package/src/server/dns.js +4 -4
- package/src/server/object-layer.js +0 -3
- package/src/ws/IoInterface.js +2 -2
|
@@ -34,6 +34,7 @@ import { Badge } from './Badge.js';
|
|
|
34
34
|
import { Worker } from './Worker.js';
|
|
35
35
|
import { Scroll } from './Scroll.js';
|
|
36
36
|
import { windowGetH, windowGetW } from './windowGetDimensions.js';
|
|
37
|
+
import { SearchBox } from './SearchBox.js';
|
|
37
38
|
|
|
38
39
|
const logger = loggerFactory(import.meta, { trace: true });
|
|
39
40
|
|
|
@@ -73,7 +74,7 @@ const Modal = {
|
|
|
73
74
|
const minWidth = width;
|
|
74
75
|
const heightDefaultTopBar = 50;
|
|
75
76
|
const heightDefaultBottomBar = 0;
|
|
76
|
-
const idModal = options
|
|
77
|
+
const idModal = options.id ? options.id : getId(this.Data, 'modal-');
|
|
77
78
|
this.Data[idModal] = {
|
|
78
79
|
options,
|
|
79
80
|
onCloseListener: {},
|
|
@@ -549,6 +550,9 @@ const Modal = {
|
|
|
549
550
|
const inputInfoNode = s(`.input-info-${inputSearchBoxId}`).cloneNode(true);
|
|
550
551
|
s(`.input-info-${inputSearchBoxId}`).remove();
|
|
551
552
|
{
|
|
553
|
+
// Inject SearchBox base styles
|
|
554
|
+
SearchBox.injectStyles();
|
|
555
|
+
|
|
552
556
|
const id = 'search-box-history';
|
|
553
557
|
const searchBoxHistoryId = id;
|
|
554
558
|
const formDataInfoNode = [
|
|
@@ -568,7 +572,6 @@ const Modal = {
|
|
|
568
572
|
});
|
|
569
573
|
let currentKeyBoardSearchBoxIndex = 0;
|
|
570
574
|
let results = [];
|
|
571
|
-
let historySearchBox = [];
|
|
572
575
|
|
|
573
576
|
const checkHistoryBoxTitleStatus = () => {
|
|
574
577
|
if (s(`.search-box-result-title`) && s(`.search-box-result-title`).classList) {
|
|
@@ -589,8 +592,28 @@ const Modal = {
|
|
|
589
592
|
} else s(`.key-shortcut-container-info`).classList.add('hide');
|
|
590
593
|
};
|
|
591
594
|
|
|
592
|
-
const renderSearchResult = async (results) => {
|
|
595
|
+
const renderSearchResult = async (results, isRecentHistory = false) => {
|
|
596
|
+
// Check if the search history modal still exists before rendering
|
|
597
|
+
if (!s(`.html-${searchBoxHistoryId}`)) return;
|
|
598
|
+
|
|
593
599
|
htmls(`.html-${searchBoxHistoryId}`, '');
|
|
600
|
+
|
|
601
|
+
// Show/hide clear-all button based on whether showing recent history
|
|
602
|
+
// Use setTimeout to ensure the button is in the DOM after modal renders
|
|
603
|
+
const updateClearAllBtn = () => {
|
|
604
|
+
const clearAllBtn = s(`.btn-search-history-clear-all`);
|
|
605
|
+
if (clearAllBtn) {
|
|
606
|
+
if (isRecentHistory && results.length > 0) {
|
|
607
|
+
clearAllBtn.style.display = 'flex';
|
|
608
|
+
} else {
|
|
609
|
+
clearAllBtn.style.display = 'none';
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
// Try immediately and also with a delay to handle timing
|
|
614
|
+
updateClearAllBtn();
|
|
615
|
+
setTimeout(updateClearAllBtn, 50);
|
|
616
|
+
|
|
594
617
|
if (results.length === 0) {
|
|
595
618
|
append(
|
|
596
619
|
`.html-${searchBoxHistoryId}`,
|
|
@@ -609,108 +632,63 @@ const Modal = {
|
|
|
609
632
|
}),
|
|
610
633
|
}),
|
|
611
634
|
);
|
|
635
|
+
return;
|
|
612
636
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
/>`
|
|
629
|
-
: ''
|
|
630
|
-
} ${Translate.Render(result.routerId)}`,
|
|
631
|
-
class: `wfa search-result-btn-${result.routerId} ${
|
|
632
|
-
indexResult === currentKeyBoardSearchBoxIndex ? 'main-btn-menu-active' : ''
|
|
633
|
-
} search-result-btn-${indexResult}`,
|
|
634
|
-
style: renderCssAttr({
|
|
635
|
-
style: { padding: '3px', margin: '2px', 'text-align': 'left' },
|
|
636
|
-
}),
|
|
637
|
-
}),
|
|
638
|
-
);
|
|
639
|
-
s(`.search-result-btn-${result.routerId}`).onclick = () => {
|
|
640
|
-
if (!s(`.html-${searchBoxHistoryId}`) || !s(`.html-${searchBoxHistoryId}`).hasChildNodes()) return;
|
|
641
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList.remove(
|
|
642
|
-
`main-btn-menu-active`,
|
|
643
|
-
);
|
|
644
|
-
currentKeyBoardSearchBoxIndex = indexRender;
|
|
645
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList.add(
|
|
646
|
-
`main-btn-menu-active`,
|
|
647
|
-
);
|
|
648
|
-
setSearchValue(`.search-result-btn-${result.routerId}`);
|
|
649
|
-
};
|
|
650
|
-
}
|
|
637
|
+
|
|
638
|
+
// Use SearchBox component for rendering results
|
|
639
|
+
const searchContext = {
|
|
640
|
+
RouterInstance: Worker.RouterInstance,
|
|
641
|
+
options: options,
|
|
642
|
+
isRecentHistory: isRecentHistory, // Flag for delete button visibility
|
|
643
|
+
onResultClick: () => {
|
|
644
|
+
// Dismiss search box on result click
|
|
645
|
+
if (s(`.${searchBoxHistoryId}`)) {
|
|
646
|
+
Modal.removeModal(searchBoxHistoryId);
|
|
647
|
+
}
|
|
648
|
+
},
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
SearchBox.renderResults(results, `html-${searchBoxHistoryId}`, searchContext);
|
|
651
652
|
};
|
|
652
653
|
|
|
653
|
-
const getResultSearchBox = (validatorData) => {
|
|
654
|
-
if (!s(`.html-${searchBoxHistoryId}`)
|
|
654
|
+
const getResultSearchBox = async (validatorData) => {
|
|
655
|
+
if (!s(`.html-${searchBoxHistoryId}`)) return;
|
|
655
656
|
const { model, id } = validatorData;
|
|
657
|
+
|
|
656
658
|
switch (model) {
|
|
657
659
|
case 'search-box':
|
|
658
660
|
{
|
|
659
|
-
if (
|
|
660
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex] &&
|
|
661
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList
|
|
662
|
-
)
|
|
663
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList.remove(
|
|
664
|
-
`main-btn-menu-active`,
|
|
665
|
-
);
|
|
666
661
|
currentKeyBoardSearchBoxIndex = 0;
|
|
667
|
-
if (
|
|
668
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex] &&
|
|
669
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList
|
|
670
|
-
)
|
|
671
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList.add(
|
|
672
|
-
`main-btn-menu-active`,
|
|
673
|
-
);
|
|
674
662
|
results = [];
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
) {
|
|
689
|
-
const fontAwesomeIcon = getAllChildNodes(s(`.main-btn-${routerId}`)).find((e) => {
|
|
690
|
-
return (
|
|
691
|
-
e.classList &&
|
|
692
|
-
Array.from(e.classList).find((e) => e.match('fa-') && !e.match('fa-grip-vertical'))
|
|
693
|
-
);
|
|
694
|
-
});
|
|
695
|
-
const imgElement = getAllChildNodes(s(`.main-btn-${routerId}`)).find((e) => {
|
|
696
|
-
return (
|
|
697
|
-
e.classList &&
|
|
698
|
-
Array.from(e.classList).find((e) =>
|
|
699
|
-
options.searchCustomImgClass
|
|
700
|
-
? e.match(options.searchCustomImgClass)
|
|
701
|
-
: e.match('img-btn-square-menu'),
|
|
702
|
-
)
|
|
703
|
-
);
|
|
704
|
-
});
|
|
705
|
-
if (imgElement || fontAwesomeIcon) {
|
|
706
|
-
results.push({
|
|
707
|
-
routerId,
|
|
708
|
-
fontAwesomeIcon: fontAwesomeIcon,
|
|
709
|
-
imgElement,
|
|
710
|
-
});
|
|
711
|
-
}
|
|
663
|
+
|
|
664
|
+
const query = s(`.${id}`) ? s(`.${id}`).value : '';
|
|
665
|
+
const trimmedQuery = query.trim();
|
|
666
|
+
|
|
667
|
+
// Use SearchBox component for extensible search
|
|
668
|
+
const searchContext = {
|
|
669
|
+
RouterInstance: Worker.RouterInstance,
|
|
670
|
+
options: options,
|
|
671
|
+
minQueryLength: options?.minSearchQueryLength || 1, // Allow single character search by default
|
|
672
|
+
onResultClick: () => {
|
|
673
|
+
// Dismiss search box on result click
|
|
674
|
+
if (s(`.${searchBoxHistoryId}`)) {
|
|
675
|
+
Modal.removeModal(searchBoxHistoryId);
|
|
712
676
|
}
|
|
713
|
-
}
|
|
677
|
+
},
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
// Check minimum query length (default: 1 character)
|
|
681
|
+
const minLength = searchContext.minQueryLength;
|
|
682
|
+
if (trimmedQuery.length >= minLength) {
|
|
683
|
+
results = await SearchBox.search(trimmedQuery, searchContext);
|
|
684
|
+
renderSearchResult(results, false); // Search results - no delete buttons
|
|
685
|
+
} else if (trimmedQuery.length === 0) {
|
|
686
|
+
// Show recent results from persistent history when query is empty
|
|
687
|
+
const recentResults = SearchBox.RecentResults.getAll();
|
|
688
|
+
renderSearchResult(recentResults, true); // Recent history - show delete buttons
|
|
689
|
+
} else {
|
|
690
|
+
// Query is too short - show nothing or a hint
|
|
691
|
+
renderSearchResult([], false);
|
|
714
692
|
}
|
|
715
693
|
}
|
|
716
694
|
break;
|
|
@@ -718,8 +696,6 @@ const Modal = {
|
|
|
718
696
|
default:
|
|
719
697
|
break;
|
|
720
698
|
}
|
|
721
|
-
if (s(`.${inputSearchBoxId}`).value.trim()) renderSearchResult(results);
|
|
722
|
-
else renderSearchResult(historySearchBox);
|
|
723
699
|
};
|
|
724
700
|
|
|
725
701
|
const searchBoxCallBack = async (validatorData) => {
|
|
@@ -742,28 +718,20 @@ const Modal = {
|
|
|
742
718
|
});
|
|
743
719
|
};
|
|
744
720
|
|
|
745
|
-
const getDefaultSearchBoxSelector = () => `.search-result-btn-${currentKeyBoardSearchBoxIndex}`;
|
|
746
|
-
|
|
747
721
|
const updateSearchBoxValue = (selector) => {
|
|
748
|
-
if (!selector)
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
s(selector).childNodes[s(selector).childNodes.length - 2] &&
|
|
762
|
-
s(selector).childNodes[s(selector).childNodes.length - 2].outerText &&
|
|
763
|
-
s(selector).childNodes[s(selector).childNodes.length - 2].outerText.trim()
|
|
764
|
-
) {
|
|
765
|
-
s(`.${inputSearchBoxId}`).value =
|
|
766
|
-
s(selector).childNodes[s(selector).childNodes.length - 2].outerText.trim();
|
|
722
|
+
if (!selector) {
|
|
723
|
+
// Get the currently active search result item
|
|
724
|
+
const activeItem = s(`.html-${searchBoxHistoryId} .search-result-item.active-search-result`);
|
|
725
|
+
if (activeItem) {
|
|
726
|
+
const titleEl = activeItem.querySelector('.search-result-title');
|
|
727
|
+
if (titleEl && titleEl.textContent) {
|
|
728
|
+
s(`.${inputSearchBoxId}`).value = titleEl.textContent.trim();
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
} else if (s(selector)) {
|
|
732
|
+
const titleEl = s(selector).querySelector('.search-result-title');
|
|
733
|
+
if (titleEl && titleEl.textContent) {
|
|
734
|
+
s(`.${inputSearchBoxId}`).value = titleEl.textContent.trim();
|
|
767
735
|
}
|
|
768
736
|
}
|
|
769
737
|
checkHistoryBoxTitleStatus();
|
|
@@ -771,17 +739,32 @@ const Modal = {
|
|
|
771
739
|
};
|
|
772
740
|
|
|
773
741
|
const setSearchValue = (selector) => {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
);
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
742
|
+
// Get all search result items
|
|
743
|
+
const allItems = sa(`.html-${searchBoxHistoryId} .search-result-item`);
|
|
744
|
+
if (!allItems || allItems.length === 0) return;
|
|
745
|
+
|
|
746
|
+
const activeItem = allItems[currentKeyBoardSearchBoxIndex];
|
|
747
|
+
if (!activeItem) return;
|
|
748
|
+
|
|
749
|
+
const resultId = activeItem.getAttribute('data-result-id');
|
|
750
|
+
const resultType = activeItem.getAttribute('data-result-type');
|
|
751
|
+
|
|
752
|
+
if (resultType === 'route' && results[currentKeyBoardSearchBoxIndex]) {
|
|
753
|
+
const result = results[currentKeyBoardSearchBoxIndex];
|
|
754
|
+
// Track in persistent history
|
|
755
|
+
SearchBox.RecentResults.add(result);
|
|
756
|
+
updateSearchBoxValue();
|
|
757
|
+
if (s(`.main-btn-${resultId}`)) {
|
|
758
|
+
s(`.main-btn-${resultId}`).click();
|
|
759
|
+
}
|
|
760
|
+
} else {
|
|
761
|
+
// Track custom provider result in persistent history
|
|
762
|
+
if (results[currentKeyBoardSearchBoxIndex]) {
|
|
763
|
+
SearchBox.RecentResults.add(results[currentKeyBoardSearchBoxIndex]);
|
|
764
|
+
}
|
|
765
|
+
// Trigger click on custom result
|
|
766
|
+
activeItem.click();
|
|
767
|
+
}
|
|
785
768
|
Modal.removeModal(searchBoxHistoryId);
|
|
786
769
|
};
|
|
787
770
|
let boxHistoryDelayRender = 0;
|
|
@@ -799,21 +782,28 @@ const Modal = {
|
|
|
799
782
|
barConfig.buttons.restore.disabled = true;
|
|
800
783
|
barConfig.buttons.menu.disabled = true;
|
|
801
784
|
barConfig.buttons.close.disabled = false;
|
|
785
|
+
|
|
802
786
|
await Modal.Render({
|
|
803
787
|
id: searchBoxHistoryId,
|
|
804
788
|
barConfig,
|
|
805
|
-
title: html`<div
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
789
|
+
title: html`<div
|
|
790
|
+
style="display: flex; align-items: center; justify-content: space-between; width: 100%;"
|
|
791
|
+
>
|
|
792
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
793
|
+
<div class="search-box-recent-title">
|
|
794
|
+
${renderViewTitle({
|
|
795
|
+
icon: html`<i class="fas fa-history mini-title"></i>`,
|
|
796
|
+
text: Translate.Render('recent'),
|
|
797
|
+
})}
|
|
798
|
+
</div>
|
|
799
|
+
<div class="search-box-result-title hide">
|
|
800
|
+
${renderViewTitle({
|
|
801
|
+
icon: html`<i class="far fa-list-alt mini-title"></i>`,
|
|
802
|
+
text: Translate.Render('results'),
|
|
803
|
+
})}
|
|
804
|
+
</div>
|
|
810
805
|
</div>
|
|
811
|
-
|
|
812
|
-
${renderViewTitle({
|
|
813
|
-
icon: html`<i class="far fa-list-alt mini-title"></i>`,
|
|
814
|
-
text: Translate.Render('results'),
|
|
815
|
-
})}
|
|
816
|
-
</div>`,
|
|
806
|
+
</div>`,
|
|
817
807
|
html: () => html``,
|
|
818
808
|
titleClass: 'mini-title',
|
|
819
809
|
style: {
|
|
@@ -825,6 +815,7 @@ const Modal = {
|
|
|
825
815
|
: '300px !important',
|
|
826
816
|
'z-index': 7,
|
|
827
817
|
},
|
|
818
|
+
class: 'search-history-modal',
|
|
828
819
|
dragDisabled: true,
|
|
829
820
|
maximize: true,
|
|
830
821
|
barMode: options.barMode,
|
|
@@ -842,6 +833,63 @@ const Modal = {
|
|
|
842
833
|
|
|
843
834
|
Modal.MoveTitleToBar(id);
|
|
844
835
|
|
|
836
|
+
// Add styles for inline button layout in the search history modal bar
|
|
837
|
+
const styleId = 'search-history-modal-bar-styles';
|
|
838
|
+
if (!s(`#${styleId}`)) {
|
|
839
|
+
const styleTag = document.createElement('style');
|
|
840
|
+
styleTag.id = styleId;
|
|
841
|
+
styleTag.textContent = `
|
|
842
|
+
.search-history-modal .btn-bar-modal-container .bar-default-modal {
|
|
843
|
+
display: flex;
|
|
844
|
+
flex-direction: row-reverse;
|
|
845
|
+
align-items: center;
|
|
846
|
+
}
|
|
847
|
+
.search-history-modal .btn-bar-modal-container .btn-modal-default {
|
|
848
|
+
display: inline-flex;
|
|
849
|
+
align-items: center;
|
|
850
|
+
justify-content: center;
|
|
851
|
+
float: none;
|
|
852
|
+
}
|
|
853
|
+
.search-history-modal .html-${searchBoxHistoryId} {
|
|
854
|
+
overflow-x: hidden;
|
|
855
|
+
box-sizing: border-box;
|
|
856
|
+
}
|
|
857
|
+
.search-history-modal .html-${searchBoxHistoryId} .search-result-item,
|
|
858
|
+
.search-history-modal .html-${searchBoxHistoryId} .search-result-history-item {
|
|
859
|
+
box-sizing: border-box;
|
|
860
|
+
max-width: 100%;
|
|
861
|
+
}
|
|
862
|
+
`;
|
|
863
|
+
document.head.appendChild(styleTag);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// Add clear all button to the bar area, before the close button
|
|
867
|
+
const clearAllBtnHtml = await BtnIcon.Render({
|
|
868
|
+
class: `btn-search-history-clear-all btn-modal-default btn-modal-default-${searchBoxHistoryId}`,
|
|
869
|
+
label: html`<i class="fas fa-trash-alt"></i>`,
|
|
870
|
+
attrs: `title="Clear all recent items"`,
|
|
871
|
+
style: 'padding: 4px 8px; font-size: 12px; display: none;',
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
// Insert before close button in the bar (with flex row-reverse, inserting after close button places our button to its left visually)
|
|
875
|
+
const closeBtn = s(`.btn-close-${searchBoxHistoryId}`);
|
|
876
|
+
if (closeBtn) {
|
|
877
|
+
closeBtn.insertAdjacentHTML('afterend', clearAllBtnHtml);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// Add click handler for clear all history button
|
|
881
|
+
const clearAllBtn = s(`.btn-search-history-clear-all`);
|
|
882
|
+
if (clearAllBtn) {
|
|
883
|
+
clearAllBtn.onclick = (e) => {
|
|
884
|
+
e.preventDefault();
|
|
885
|
+
e.stopPropagation();
|
|
886
|
+
// Clear all history from persistent storage
|
|
887
|
+
SearchBox.RecentResults.clear();
|
|
888
|
+
// Re-render to show empty history (with isRecentHistory true to hide button)
|
|
889
|
+
renderSearchResult([], true);
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
|
|
845
893
|
prepend(`.btn-bar-modal-container-${id}`, html`<div class="hide">${inputInfoNode.outerHTML}</div>`);
|
|
846
894
|
}
|
|
847
895
|
};
|
|
@@ -879,27 +927,29 @@ const Modal = {
|
|
|
879
927
|
keys: ['ArrowUp'],
|
|
880
928
|
eventCallBack: () => {
|
|
881
929
|
if (s(`.${id}`)) {
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
930
|
+
const allItems = sa(`.html-${searchBoxHistoryId} .search-result-item`);
|
|
931
|
+
if (!allItems || allItems.length === 0) return;
|
|
932
|
+
|
|
933
|
+
// Remove active class from current
|
|
934
|
+
if (allItems[currentKeyBoardSearchBoxIndex]) {
|
|
935
|
+
allItems[currentKeyBoardSearchBoxIndex].classList.remove('active-search-result');
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Navigate up
|
|
939
|
+
if (currentKeyBoardSearchBoxIndex > 0) {
|
|
889
940
|
currentKeyBoardSearchBoxIndex--;
|
|
890
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList.add(
|
|
891
|
-
`main-btn-menu-active`,
|
|
892
|
-
);
|
|
893
941
|
} else {
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
942
|
+
currentKeyBoardSearchBoxIndex = allItems.length - 1;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// Add active class to new and ensure visibility
|
|
946
|
+
if (allItems[currentKeyBoardSearchBoxIndex]) {
|
|
947
|
+
allItems[currentKeyBoardSearchBoxIndex].classList.add('active-search-result');
|
|
948
|
+
// Use optimized scroll method to ensure item is always visible
|
|
949
|
+
const container = s(`.html-${searchBoxHistoryId}`);
|
|
950
|
+
if (container) {
|
|
951
|
+
SearchBox.scrollIntoViewIfNeeded(allItems[currentKeyBoardSearchBoxIndex], container);
|
|
952
|
+
}
|
|
903
953
|
}
|
|
904
954
|
updateSearchBoxValue();
|
|
905
955
|
}
|
|
@@ -912,27 +962,29 @@ const Modal = {
|
|
|
912
962
|
keys: ['ArrowDown'],
|
|
913
963
|
eventCallBack: () => {
|
|
914
964
|
if (s(`.${id}`)) {
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
965
|
+
const allItems = sa(`.html-${searchBoxHistoryId} .search-result-item`);
|
|
966
|
+
if (!allItems || allItems.length === 0) return;
|
|
967
|
+
|
|
968
|
+
// Remove active class from current
|
|
969
|
+
if (allItems[currentKeyBoardSearchBoxIndex]) {
|
|
970
|
+
allItems[currentKeyBoardSearchBoxIndex].classList.remove('active-search-result');
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// Navigate down
|
|
974
|
+
if (currentKeyBoardSearchBoxIndex < allItems.length - 1) {
|
|
922
975
|
currentKeyBoardSearchBoxIndex++;
|
|
923
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList.add(
|
|
924
|
-
`main-btn-menu-active`,
|
|
925
|
-
);
|
|
926
976
|
} else {
|
|
927
|
-
if (s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex])
|
|
928
|
-
s(`.html-${searchBoxHistoryId}`).childNodes[currentKeyBoardSearchBoxIndex].classList.remove(
|
|
929
|
-
`main-btn-menu-active`,
|
|
930
|
-
);
|
|
931
977
|
currentKeyBoardSearchBoxIndex = 0;
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
// Add active class to new and ensure visibility
|
|
981
|
+
if (allItems[currentKeyBoardSearchBoxIndex]) {
|
|
982
|
+
allItems[currentKeyBoardSearchBoxIndex].classList.add('active-search-result');
|
|
983
|
+
// Use optimized scroll method to ensure item is always visible
|
|
984
|
+
const container = s(`.html-${searchBoxHistoryId}`);
|
|
985
|
+
if (container) {
|
|
986
|
+
SearchBox.scrollIntoViewIfNeeded(allItems[currentKeyBoardSearchBoxIndex], container);
|
|
987
|
+
}
|
|
936
988
|
}
|
|
937
989
|
updateSearchBoxValue();
|
|
938
990
|
}
|
|
@@ -2054,6 +2106,34 @@ const Modal = {
|
|
|
2054
2106
|
},
|
|
2055
2107
|
mobileModal: () => windowGetW() < 600 || windowGetH() < 600,
|
|
2056
2108
|
writeHTML: ({ idModal, html }) => htmls(`.html-${idModal}`, html),
|
|
2109
|
+
updateModal: async function ({ idModal, html, title }) {
|
|
2110
|
+
if (!this.Data[idModal] || !s(`.${idModal}`)) {
|
|
2111
|
+
console.warn(`Modal ${idModal} not found for update`);
|
|
2112
|
+
return false;
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
// Update modal content
|
|
2116
|
+
if (html) {
|
|
2117
|
+
this.writeHTML({ idModal, html });
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
// Update modal title if provided
|
|
2121
|
+
if (title) {
|
|
2122
|
+
const titleElement = s(`.${idModal} .modal-title`);
|
|
2123
|
+
if (titleElement) {
|
|
2124
|
+
titleElement.innerHTML = title;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
// Trigger reload listeners
|
|
2129
|
+
if (this.Data[idModal].onReloadModalListener) {
|
|
2130
|
+
for (const event of Object.keys(this.Data[idModal].onReloadModalListener)) {
|
|
2131
|
+
await this.Data[idModal].onReloadModalListener[event]();
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
return true;
|
|
2136
|
+
},
|
|
2057
2137
|
viewModalOpen: function () {
|
|
2058
2138
|
return Object.keys(this.Data).find((idModal) => s(`.${idModal}`) && this.Data[idModal].options.mode === 'view');
|
|
2059
2139
|
},
|