underpost 2.8.87 → 2.8.88
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/.env.development +35 -3
- package/.env.production +39 -4
- package/.env.test +35 -3
- package/.github/workflows/ghpkg.ci.yml +1 -1
- package/.github/workflows/npmpkg.ci.yml +1 -1
- package/.github/workflows/pwa-microservices-template-page.cd.yml +6 -5
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/.github/workflows/release.cd.yml +3 -3
- package/README.md +56 -2
- package/bin/build.js +4 -0
- package/bin/deploy.js +62 -8
- package/bin/file.js +3 -2
- package/cli.md +8 -2
- package/conf.js +30 -4
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +174 -0
- package/manifests/deployment/dd-test-development/proxy.yaml +51 -0
- package/package.json +6 -5
- package/src/api/core/core.router.js +2 -1
- package/src/api/default/default.controller.js +6 -1
- package/src/api/default/default.router.js +6 -2
- package/src/api/default/default.service.js +10 -1
- package/src/api/document/document.controller.js +66 -0
- package/src/api/document/document.model.js +51 -0
- package/src/api/document/document.router.js +24 -0
- package/src/api/document/document.service.js +125 -0
- package/src/api/file/file.controller.js +15 -1
- package/src/api/file/file.router.js +2 -1
- package/src/api/test/test.router.js +1 -1
- package/src/api/user/postman_collection.json +216 -0
- package/src/api/user/user.controller.js +25 -60
- package/src/api/user/user.model.js +29 -7
- package/src/api/user/user.router.js +9 -3
- package/src/api/user/user.service.js +84 -32
- package/src/cli/baremetal.js +33 -3
- package/src/cli/cloud-init.js +11 -0
- package/src/cli/cron.js +0 -1
- package/src/cli/deploy.js +46 -23
- package/src/cli/index.js +5 -0
- package/src/cli/lxd.js +7 -0
- package/src/cli/repository.js +42 -6
- package/src/cli/run.js +45 -13
- package/src/cli/ssh.js +20 -6
- package/src/client/Default.index.js +42 -1
- package/src/client/components/core/Account.js +10 -2
- package/src/client/components/core/AgGrid.js +30 -8
- package/src/client/components/core/Auth.js +99 -56
- package/src/client/components/core/BtnIcon.js +3 -2
- package/src/client/components/core/CalendarCore.js +2 -3
- package/src/client/components/core/CommonJs.js +1 -2
- package/src/client/components/core/Content.js +15 -12
- package/src/client/components/core/Css.js +2 -1
- package/src/client/components/core/CssCore.js +6 -1
- package/src/client/components/core/Docs.js +5 -5
- package/src/client/components/core/FileExplorer.js +3 -3
- package/src/client/components/core/Input.js +22 -17
- package/src/client/components/core/JoyStick.js +2 -2
- package/src/client/components/core/LoadingAnimation.js +2 -2
- package/src/client/components/core/LogIn.js +16 -23
- package/src/client/components/core/LogOut.js +5 -1
- package/src/client/components/core/Logger.js +4 -1
- package/src/client/components/core/Modal.js +82 -53
- package/src/client/components/core/ObjectLayerEngineModal.js +2 -1
- package/src/client/components/core/Pagination.js +207 -0
- package/src/client/components/core/Panel.js +10 -10
- package/src/client/components/core/PanelForm.js +130 -33
- package/src/client/components/core/Recover.js +2 -2
- package/src/client/components/core/Router.js +210 -34
- package/src/client/components/core/SignUp.js +1 -2
- package/src/client/components/core/Stream.js +1 -1
- package/src/client/components/core/VanillaJs.js +3 -84
- package/src/client/components/core/Worker.js +2 -2
- package/src/client/components/default/LogInDefault.js +0 -6
- package/src/client/components/default/LogOutDefault.js +0 -16
- package/src/client/components/default/MenuDefault.js +97 -44
- package/src/client/components/default/RoutesDefault.js +5 -2
- package/src/client/services/core/core.service.js +8 -20
- package/src/client/services/default/default.management.js +115 -18
- package/src/client/services/default/default.service.js +13 -4
- package/src/client/services/document/document.service.js +97 -0
- package/src/client/services/file/file.service.js +2 -0
- package/src/client/services/test/test.service.js +3 -0
- package/src/client/services/user/user.management.js +6 -0
- package/src/client/services/user/user.service.js +15 -4
- package/src/client/ssr/Render.js +1 -1
- package/src/client/ssr/head/DefaultScripts.js +3 -0
- package/src/client/ssr/head/Seo.js +1 -0
- package/src/index.js +24 -2
- package/src/runtime/lampp/Lampp.js +89 -2
- package/src/runtime/xampp/Xampp.js +48 -1
- package/src/server/auth.js +519 -155
- package/src/server/backup.js +2 -2
- package/src/server/conf.js +66 -8
- package/src/server/process.js +2 -1
- package/src/server/runtime.js +135 -286
- package/src/server/ssl.js +1 -2
- package/src/server/ssr.js +85 -0
- package/src/server/start.js +2 -2
- package/src/server/valkey.js +2 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { getQueryParams, setQueryParams } from './Router.js';
|
|
2
|
+
|
|
3
|
+
class AgPagination extends HTMLElement {
|
|
4
|
+
constructor() {
|
|
5
|
+
super();
|
|
6
|
+
this.attachShadow({ mode: 'open' });
|
|
7
|
+
this._gridId = null;
|
|
8
|
+
const queryParams = getQueryParams();
|
|
9
|
+
this._currentPage = parseInt(queryParams.page, 10) || 1;
|
|
10
|
+
this._limit = parseInt(queryParams.limit, 10) || 10;
|
|
11
|
+
this._totalPages = 1;
|
|
12
|
+
this._totalItems = 0;
|
|
13
|
+
this.handlePageChange = this.handlePageChange.bind(this);
|
|
14
|
+
this.handleLimitChange = this.handleLimitChange.bind(this);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static get observedAttributes() {
|
|
18
|
+
return ['grid-id', 'current-page', 'total-pages', 'total-items', 'limit'];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
22
|
+
switch (name) {
|
|
23
|
+
case 'grid-id':
|
|
24
|
+
this._gridId = newValue;
|
|
25
|
+
break;
|
|
26
|
+
case 'current-page':
|
|
27
|
+
this._currentPage = parseInt(newValue, 10) || this._currentPage;
|
|
28
|
+
break;
|
|
29
|
+
case 'total-pages':
|
|
30
|
+
this._totalPages = parseInt(newValue, 10) || 1;
|
|
31
|
+
break;
|
|
32
|
+
case 'total-items':
|
|
33
|
+
this._totalItems = parseInt(newValue, 10) || 0;
|
|
34
|
+
break;
|
|
35
|
+
case 'limit':
|
|
36
|
+
this._limit = parseInt(newValue, 10) || this._limit;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
this.update();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
connectedCallback() {
|
|
43
|
+
this.render();
|
|
44
|
+
this.addEventListeners();
|
|
45
|
+
this.update();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
disconnectedCallback() {
|
|
49
|
+
// Event listeners on shadow DOM are garbage collected with the component
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
handlePageChange(newPage) {
|
|
53
|
+
if (newPage < 1 || newPage > this._totalPages || newPage === this._currentPage) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this._currentPage = newPage;
|
|
57
|
+
setQueryParams({ page: newPage, limit: this._limit });
|
|
58
|
+
this.dispatchEvent(new CustomEvent('page-change', { detail: { page: newPage } }));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
handleLimitChange(event) {
|
|
62
|
+
const newLimit = parseInt(event.target.value, 10);
|
|
63
|
+
if (newLimit === this._limit) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this._limit = newLimit;
|
|
67
|
+
this._currentPage = 1; // Reset to first page on limit change
|
|
68
|
+
setQueryParams({ page: 1, limit: newLimit });
|
|
69
|
+
this.dispatchEvent(new CustomEvent('limit-change', { detail: { limit: newLimit } }));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
update() {
|
|
73
|
+
if (!this.shadowRoot.querySelector('#page-info')) return;
|
|
74
|
+
|
|
75
|
+
const isFirstPage = this._currentPage === 1;
|
|
76
|
+
const isLastPage = this._currentPage === this._totalPages;
|
|
77
|
+
|
|
78
|
+
this.shadowRoot.querySelector('#first-page').disabled = isFirstPage;
|
|
79
|
+
this.shadowRoot.querySelector('#prev-page').disabled = isFirstPage;
|
|
80
|
+
this.shadowRoot.querySelector('#next-page').disabled = isLastPage;
|
|
81
|
+
this.shadowRoot.querySelector('#last-page').disabled = isLastPage;
|
|
82
|
+
|
|
83
|
+
const startItem = this._totalItems > 0 ? (this._currentPage - 1) * this._limit + 1 : 0;
|
|
84
|
+
const endItem = Math.min(this._currentPage * this._limit, this._totalItems);
|
|
85
|
+
|
|
86
|
+
this.shadowRoot.querySelector('#summary-info').textContent = `${startItem} - ${endItem} of ${this._totalItems}`;
|
|
87
|
+
this.shadowRoot.querySelector('#page-info').textContent = `Page ${this._currentPage} of ${this._totalPages}`;
|
|
88
|
+
|
|
89
|
+
const limitSelector = this.shadowRoot.querySelector('#limit-selector');
|
|
90
|
+
if (limitSelector.value != this._limit) {
|
|
91
|
+
limitSelector.value = this._limit;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
this.renderPageButtons();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
renderPageButtons() {
|
|
98
|
+
const pageButtonsContainer = this.shadowRoot.querySelector('#page-buttons');
|
|
99
|
+
pageButtonsContainer.innerHTML = '';
|
|
100
|
+
|
|
101
|
+
const maxButtons = 5;
|
|
102
|
+
let startPage = Math.max(1, this._currentPage - Math.floor(maxButtons / 2));
|
|
103
|
+
let endPage = Math.min(this._totalPages, startPage + maxButtons - 1);
|
|
104
|
+
|
|
105
|
+
if (endPage - startPage + 1 < maxButtons) {
|
|
106
|
+
startPage = Math.max(1, endPage - maxButtons + 1);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (let i = startPage; i <= endPage; i++) {
|
|
110
|
+
const button = document.createElement('button');
|
|
111
|
+
button.textContent = i;
|
|
112
|
+
button.disabled = i === this._currentPage;
|
|
113
|
+
if (i === this._currentPage) {
|
|
114
|
+
button.classList.add('active');
|
|
115
|
+
}
|
|
116
|
+
button.addEventListener('click', () => this.handlePageChange(i));
|
|
117
|
+
pageButtonsContainer.appendChild(button);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
addEventListeners() {
|
|
122
|
+
this.shadowRoot.querySelector('#first-page').addEventListener('click', () => this.handlePageChange(1));
|
|
123
|
+
this.shadowRoot
|
|
124
|
+
.querySelector('#prev-page')
|
|
125
|
+
.addEventListener('click', () => this.handlePageChange(this._currentPage - 1));
|
|
126
|
+
this.shadowRoot
|
|
127
|
+
.querySelector('#next-page')
|
|
128
|
+
.addEventListener('click', () => this.handlePageChange(this._currentPage + 1));
|
|
129
|
+
this.shadowRoot
|
|
130
|
+
.querySelector('#last-page')
|
|
131
|
+
.addEventListener('click', () => this.handlePageChange(this._totalPages));
|
|
132
|
+
this.shadowRoot.querySelector('#limit-selector').addEventListener('change', this.handleLimitChange);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
render() {
|
|
136
|
+
this.shadowRoot.innerHTML = html`
|
|
137
|
+
<style>
|
|
138
|
+
:host {
|
|
139
|
+
display: flex;
|
|
140
|
+
align-items: center;
|
|
141
|
+
justify-content: center;
|
|
142
|
+
padding: 8px;
|
|
143
|
+
font-family: sans-serif;
|
|
144
|
+
font-size: 14px;
|
|
145
|
+
gap: 8px;
|
|
146
|
+
}
|
|
147
|
+
button {
|
|
148
|
+
border: 1px solid #ccc;
|
|
149
|
+
background-color: #f0f0f0;
|
|
150
|
+
padding: 6px 12px;
|
|
151
|
+
cursor: pointer;
|
|
152
|
+
border-radius: 4px;
|
|
153
|
+
}
|
|
154
|
+
button:disabled {
|
|
155
|
+
cursor: not-allowed;
|
|
156
|
+
opacity: 0.5;
|
|
157
|
+
}
|
|
158
|
+
button.active {
|
|
159
|
+
border-color: #007bff;
|
|
160
|
+
background-color: #007bff;
|
|
161
|
+
color: white;
|
|
162
|
+
}
|
|
163
|
+
#page-info {
|
|
164
|
+
min-width: 80px;
|
|
165
|
+
text-align: center;
|
|
166
|
+
}
|
|
167
|
+
#page-buttons {
|
|
168
|
+
display: flex;
|
|
169
|
+
gap: 4px;
|
|
170
|
+
}
|
|
171
|
+
.summary-panel,
|
|
172
|
+
.page-summary-panel {
|
|
173
|
+
display: flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
gap: 8px;
|
|
176
|
+
}
|
|
177
|
+
#limit-selector {
|
|
178
|
+
border: 1px solid #ccc;
|
|
179
|
+
background-color: #f0f0f0;
|
|
180
|
+
padding: 6px 12px;
|
|
181
|
+
border-radius: 4px;
|
|
182
|
+
}
|
|
183
|
+
</style>
|
|
184
|
+
<div class="summary-panel">
|
|
185
|
+
<span id="summary-info"></span>
|
|
186
|
+
</div>
|
|
187
|
+
<button id="first-page">First</button>
|
|
188
|
+
<button id="prev-page">Previous</button>
|
|
189
|
+
<div class="page-summary-panel">
|
|
190
|
+
<div id="page-buttons"></div>
|
|
191
|
+
<span id="page-info"></span>
|
|
192
|
+
</div>
|
|
193
|
+
<button id="next-page">Next</button>
|
|
194
|
+
<button id="last-page">Last</button>
|
|
195
|
+
<select id="limit-selector">
|
|
196
|
+
<option value="10">10</option>
|
|
197
|
+
<option value="20">20</option>
|
|
198
|
+
<option value="50">50</option>
|
|
199
|
+
<option value="100">100</option>
|
|
200
|
+
</select>
|
|
201
|
+
`;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
customElements.define('ag-pagination', AgPagination);
|
|
206
|
+
|
|
207
|
+
export { AgPagination };
|
|
@@ -2,17 +2,14 @@ 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 { Responsive } from '../core/Responsive.js';
|
|
6
5
|
import { darkTheme, ThemeEvents } from './Css.js';
|
|
7
|
-
import { append, getDataFromInputFile,
|
|
6
|
+
import { append, getDataFromInputFile, htmls, s } from './VanillaJs.js';
|
|
8
7
|
import { BtnIcon } from './BtnIcon.js';
|
|
9
8
|
import { Translate } from './Translate.js';
|
|
10
9
|
import { DropDown } from './DropDown.js';
|
|
11
|
-
import { dynamicCol
|
|
10
|
+
import { dynamicCol } from './Css.js';
|
|
12
11
|
import { EventsUI } from './EventsUI.js';
|
|
13
12
|
import { ToggleSwitch } from './ToggleSwitch.js';
|
|
14
|
-
import { Modal } from './Modal.js';
|
|
15
|
-
import { RouterEvents } from './Router.js';
|
|
16
13
|
import { RichText } from './RichText.js';
|
|
17
14
|
import { loggerFactory } from './Logger.js';
|
|
18
15
|
import { Badge } from './Badge.js';
|
|
@@ -117,6 +114,7 @@ const Panel = {
|
|
|
117
114
|
options.originData().find((d) => d._id === obj._id || d.id === obj.id),
|
|
118
115
|
options.filesData().find((d) => d._id === obj._id || d.id === obj.id),
|
|
119
116
|
);
|
|
117
|
+
if (options.on.initEdit) await options.on.initEdit({ data: obj });
|
|
120
118
|
});
|
|
121
119
|
s(`.a-${payload._id}`).onclick = async (e) => {
|
|
122
120
|
e.preventDefault();
|
|
@@ -470,11 +468,9 @@ const Panel = {
|
|
|
470
468
|
s(`.${btnSelector}`).classList.remove('hide');
|
|
471
469
|
}
|
|
472
470
|
}
|
|
473
|
-
|
|
474
|
-
s(`.${idPanel}-form-body`).classList.add('hide');
|
|
475
|
-
});
|
|
471
|
+
s(`.${idPanel}-form-body`).classList.add('hide');
|
|
476
472
|
};
|
|
477
|
-
s(`.btn-${idPanel}-add`).onclick = (e) => {
|
|
473
|
+
s(`.btn-${idPanel}-add`).onclick = async (e) => {
|
|
478
474
|
e.preventDefault();
|
|
479
475
|
// s(`.btn-${idPanel}-clean`).click();
|
|
480
476
|
Panel.Tokens[idPanel].editId = undefined;
|
|
@@ -483,16 +479,20 @@ const Panel = {
|
|
|
483
479
|
s(`.${scrollClassContainer}`).scrollTop = 0;
|
|
484
480
|
|
|
485
481
|
openPanelForm();
|
|
482
|
+
if (options.on.initAdd) await options.on.initAdd();
|
|
486
483
|
};
|
|
487
484
|
if (s(`.${scrollClassContainer}`)) s(`.${scrollClassContainer}`).style.overflow = 'auto';
|
|
488
485
|
});
|
|
489
486
|
|
|
490
487
|
if (data.length > 0) for (const obj of data) render += await renderPanel(obj);
|
|
491
|
-
else
|
|
488
|
+
else {
|
|
492
489
|
render += html`<div class="in" style="min-height: 200px">
|
|
493
490
|
<div class="abs center"><i class="fas fa-exclamation-circle"></i> ${Translate.Render(`no-result-found`)}</div>
|
|
494
491
|
</div>`;
|
|
495
492
|
|
|
493
|
+
if (options.on.noResultFound) setTimeout(options.on.noResultFound);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
496
|
this.Tokens[idPanel] = { idPanel, scrollClassContainer, formData, data, titleKey, subTitleKey, renderPanel };
|
|
497
497
|
|
|
498
498
|
let customButtonsRender = '';
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import { getCapVariableName, newInstance, random, range, uniqueArray } from './CommonJs.js';
|
|
1
|
+
import { getCapVariableName, newInstance, random, range, timer, uniqueArray } from './CommonJs.js';
|
|
2
2
|
import { marked } from 'marked';
|
|
3
|
-
import {
|
|
4
|
-
getBlobFromUint8ArrayFile,
|
|
5
|
-
getDataFromInputFile,
|
|
6
|
-
getQueryParams,
|
|
7
|
-
getRawContentFile,
|
|
8
|
-
htmls,
|
|
9
|
-
} from './VanillaJs.js';
|
|
3
|
+
import { append, getBlobFromUint8ArrayFile, getDataFromInputFile, getRawContentFile, htmls, s } from './VanillaJs.js';
|
|
10
4
|
import { Panel } from './Panel.js';
|
|
11
5
|
import { NotificationManager } from './NotificationManager.js';
|
|
12
6
|
import { DocumentService } from '../../services/document/document.service.js';
|
|
@@ -15,7 +9,9 @@ import { getSrcFromFileData } from './Input.js';
|
|
|
15
9
|
import { imageShimmer, renderCssAttr } from './Css.js';
|
|
16
10
|
import { Translate } from './Translate.js';
|
|
17
11
|
import { Modal } from './Modal.js';
|
|
18
|
-
import { closeModalRouteChangeEvents, listenQueryPathInstance, setQueryPath } from './Router.js';
|
|
12
|
+
import { closeModalRouteChangeEvents, listenQueryPathInstance, setQueryPath, getQueryParams } from './Router.js';
|
|
13
|
+
import { Scroll } from './Scroll.js';
|
|
14
|
+
import { LoadingAnimation } from './LoadingAnimation.js';
|
|
19
15
|
|
|
20
16
|
const PanelForm = {
|
|
21
17
|
Data: {},
|
|
@@ -39,6 +35,10 @@ const PanelForm = {
|
|
|
39
35
|
originData: [],
|
|
40
36
|
data: [],
|
|
41
37
|
filesData: [],
|
|
38
|
+
skip: 0,
|
|
39
|
+
limit: 3, // Load 5 items per page
|
|
40
|
+
hasMore: true,
|
|
41
|
+
loading: false,
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
const formData = [
|
|
@@ -138,7 +138,7 @@ const PanelForm = {
|
|
|
138
138
|
`,
|
|
139
139
|
});
|
|
140
140
|
return await options.fileRender({
|
|
141
|
-
file: PanelForm.Data[idPanel].filesData.find((f) => f._id === options.data._id)
|
|
141
|
+
file: PanelForm.Data[idPanel].filesData.find((f) => f._id === options.data._id)?.fileId?.fileBlob,
|
|
142
142
|
style: {
|
|
143
143
|
overflow: 'auto',
|
|
144
144
|
width: '100%',
|
|
@@ -178,6 +178,15 @@ const PanelForm = {
|
|
|
178
178
|
}
|
|
179
179
|
return { status: 'error' };
|
|
180
180
|
},
|
|
181
|
+
initAdd: async function () {
|
|
182
|
+
s(`.modal-${options.route}`).scrollTo({ top: 0, behavior: 'smooth' });
|
|
183
|
+
},
|
|
184
|
+
initEdit: async function ({ data }) {
|
|
185
|
+
s(`.modal-${options.route}`).scrollTo({ top: 0, behavior: 'smooth' });
|
|
186
|
+
},
|
|
187
|
+
noResultFound: async function () {
|
|
188
|
+
LoadingAnimation.spinner.stop(`.panel-placeholder-bottom-${idPanel}`);
|
|
189
|
+
},
|
|
181
190
|
add: async function ({ data, editId }) {
|
|
182
191
|
let mdFileId;
|
|
183
192
|
const mdFileName = `${getCapVariableName(data.title)}.md`;
|
|
@@ -318,19 +327,36 @@ const PanelForm = {
|
|
|
318
327
|
},
|
|
319
328
|
});
|
|
320
329
|
|
|
321
|
-
const getPanelData = async () => {
|
|
330
|
+
const getPanelData = async (isLoadMore = false) => {
|
|
331
|
+
const panelData = PanelForm.Data[idPanel];
|
|
332
|
+
if (panelData.loading || !panelData.hasMore) return;
|
|
333
|
+
panelData.loading = true;
|
|
334
|
+
|
|
335
|
+
if (!isLoadMore) {
|
|
336
|
+
// Reset for a fresh load
|
|
337
|
+
panelData.skip = 0;
|
|
338
|
+
panelData.hasMore = true;
|
|
339
|
+
}
|
|
340
|
+
|
|
322
341
|
const result = await DocumentService.get({
|
|
323
|
-
|
|
342
|
+
params: {
|
|
343
|
+
tags: prefixTags.join(','),
|
|
344
|
+
...(getQueryParams().cid && { cid: getQueryParams().cid }),
|
|
345
|
+
skip: panelData.skip,
|
|
346
|
+
limit: panelData.limit,
|
|
347
|
+
},
|
|
348
|
+
id: 'public/',
|
|
324
349
|
});
|
|
325
350
|
|
|
326
|
-
NotificationManager.Push({
|
|
327
|
-
html: result.status === 'success' ? Translate.Render('success-get-posts') : result.message,
|
|
328
|
-
status: result.status,
|
|
329
|
-
});
|
|
330
351
|
if (result.status === 'success') {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
352
|
+
if (!isLoadMore) {
|
|
353
|
+
panelData.originData = [];
|
|
354
|
+
panelData.filesData = [];
|
|
355
|
+
panelData.data = [];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
panelData.originData.push(...newInstance(result.data));
|
|
359
|
+
|
|
334
360
|
for (const documentObject of result.data) {
|
|
335
361
|
let mdFileId, fileId;
|
|
336
362
|
let mdBlob, fileBlob;
|
|
@@ -339,7 +365,6 @@ const PanelForm = {
|
|
|
339
365
|
{
|
|
340
366
|
const {
|
|
341
367
|
data: [file],
|
|
342
|
-
status,
|
|
343
368
|
} = await FileService.get({ id: documentObject.mdFileId });
|
|
344
369
|
|
|
345
370
|
// const ext = file.name.split('.')[file.name.split('.').length - 1];
|
|
@@ -350,7 +375,6 @@ const PanelForm = {
|
|
|
350
375
|
if (documentObject.fileId) {
|
|
351
376
|
const {
|
|
352
377
|
data: [file],
|
|
353
|
-
status,
|
|
354
378
|
} = await FileService.get({ id: documentObject.fileId._id });
|
|
355
379
|
|
|
356
380
|
// const ext = file.name.split('.')[file.name.split('.').length - 1];
|
|
@@ -359,14 +383,14 @@ const PanelForm = {
|
|
|
359
383
|
fileId = getSrcFromFileData(file);
|
|
360
384
|
}
|
|
361
385
|
|
|
362
|
-
|
|
386
|
+
panelData.filesData.push({
|
|
363
387
|
id: documentObject._id,
|
|
364
388
|
_id: documentObject._id,
|
|
365
389
|
mdFileId: { mdBlob, mdPlain },
|
|
366
390
|
fileId: { fileBlob, filePlain },
|
|
367
391
|
});
|
|
368
392
|
|
|
369
|
-
|
|
393
|
+
panelData.data.push({
|
|
370
394
|
id: documentObject._id,
|
|
371
395
|
title: documentObject.title,
|
|
372
396
|
createdAt: documentObject.createdAt,
|
|
@@ -378,7 +402,23 @@ const PanelForm = {
|
|
|
378
402
|
_id: documentObject._id,
|
|
379
403
|
});
|
|
380
404
|
}
|
|
405
|
+
|
|
406
|
+
panelData.skip += result.data.length;
|
|
407
|
+
panelData.hasMore = result.data.length === panelData.limit;
|
|
408
|
+
if (result.data.length < panelData.limit) {
|
|
409
|
+
LoadingAnimation.spinner.stop(`.panel-placeholder-bottom-${idPanel}`);
|
|
410
|
+
}
|
|
411
|
+
} else {
|
|
412
|
+
NotificationManager.Push({
|
|
413
|
+
html: result.message,
|
|
414
|
+
status: result.status,
|
|
415
|
+
});
|
|
416
|
+
panelData.hasMore = false;
|
|
381
417
|
}
|
|
418
|
+
|
|
419
|
+
await timer(250);
|
|
420
|
+
|
|
421
|
+
panelData.loading = false;
|
|
382
422
|
};
|
|
383
423
|
const renderSrrPanelData = async () =>
|
|
384
424
|
await panelRender({
|
|
@@ -426,10 +466,10 @@ const PanelForm = {
|
|
|
426
466
|
let firsUpdateEvent = false;
|
|
427
467
|
let lastCid;
|
|
428
468
|
let lastUserId;
|
|
429
|
-
closeModalRouteChangeEvents[idPanel] = (
|
|
430
|
-
|
|
469
|
+
closeModalRouteChangeEvents[idPanel] = () => {
|
|
470
|
+
setTimeout(() => {
|
|
431
471
|
this.Data[idPanel].updatePanel();
|
|
432
|
-
}
|
|
472
|
+
});
|
|
433
473
|
};
|
|
434
474
|
this.Data[idPanel].updatePanel = async () => {
|
|
435
475
|
const cid = getQueryParams().cid ? getQueryParams().cid : '';
|
|
@@ -437,13 +477,60 @@ const PanelForm = {
|
|
|
437
477
|
if (lastCid === cid && !forceUpdate) return;
|
|
438
478
|
lastUserId = newInstance(Elements.Data.user.main.model.user._id);
|
|
439
479
|
lastCid = cid;
|
|
440
|
-
|
|
441
|
-
|
|
480
|
+
|
|
481
|
+
if (cid) {
|
|
482
|
+
this.Data[idPanel] = {
|
|
483
|
+
...this.Data[idPanel],
|
|
484
|
+
originData: [],
|
|
485
|
+
data: [],
|
|
486
|
+
filesData: [],
|
|
487
|
+
skip: 0,
|
|
488
|
+
limit: 3, // Load 5 items per page
|
|
489
|
+
hasMore: true,
|
|
490
|
+
loading: false,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const containerSelector = `.${options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body'}`;
|
|
495
|
+
htmls(containerSelector, await renderSrrPanelData());
|
|
496
|
+
|
|
442
497
|
await getPanelData();
|
|
498
|
+
|
|
443
499
|
htmls(
|
|
444
|
-
|
|
445
|
-
|
|
500
|
+
containerSelector,
|
|
501
|
+
html`
|
|
502
|
+
<div class="in">${await panelRender({ data: this.Data[idPanel].data })}</div>
|
|
503
|
+
<div class="in panel-placeholder-bottom panel-placeholder-bottom-${idPanel}"></div>
|
|
504
|
+
`,
|
|
446
505
|
);
|
|
506
|
+
|
|
507
|
+
LoadingAnimation.spinner.play(`.panel-placeholder-bottom-${idPanel}`, 'dual-ring-mini');
|
|
508
|
+
|
|
509
|
+
const scrollContainerSelector = `.modal-${options.route}`;
|
|
510
|
+
|
|
511
|
+
if (cid) {
|
|
512
|
+
LoadingAnimation.spinner.stop(`.panel-placeholder-bottom-${idPanel}`);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (this.Data[idPanel].removeScrollEvent) {
|
|
516
|
+
this.Data[idPanel].removeScrollEvent();
|
|
517
|
+
}
|
|
518
|
+
const { removeEvent } = Scroll.setEvent(scrollContainerSelector, async (payload) => {
|
|
519
|
+
const panelData = PanelForm.Data[idPanel];
|
|
520
|
+
if (!panelData) return;
|
|
521
|
+
|
|
522
|
+
// Infinite scroll: load more items at bottom
|
|
523
|
+
if (payload.atBottom && panelData.hasMore && !panelData.loading) {
|
|
524
|
+
const oldDataCount = panelData.data.length;
|
|
525
|
+
await getPanelData(true); // isLoadMore = true
|
|
526
|
+
const newItems = panelData.data.slice(oldDataCount);
|
|
527
|
+
if (newItems.length > 0) {
|
|
528
|
+
for (const item of newItems) append(`.${idPanel}-render`, await Panel.Tokens[idPanel].renderPanel(item));
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
this.Data[idPanel].removeScrollEvent = removeEvent;
|
|
533
|
+
|
|
447
534
|
if (!firsUpdateEvent && options.firsUpdateEvent) {
|
|
448
535
|
firsUpdateEvent = true;
|
|
449
536
|
await options.firsUpdateEvent();
|
|
@@ -454,15 +541,25 @@ const PanelForm = {
|
|
|
454
541
|
id: options.parentIdModal ? 'html-' + options.parentIdModal : 'main-body',
|
|
455
542
|
routeId: options.route,
|
|
456
543
|
event: async (path) => {
|
|
457
|
-
|
|
544
|
+
PanelForm.Data[idPanel] = {
|
|
545
|
+
...PanelForm.Data[idPanel],
|
|
546
|
+
originData: [],
|
|
547
|
+
data: [],
|
|
548
|
+
filesData: [],
|
|
549
|
+
// skip: 0,
|
|
550
|
+
limit: 3, // Load 5 items per page
|
|
551
|
+
hasMore: true,
|
|
552
|
+
loading: false,
|
|
553
|
+
};
|
|
554
|
+
await PanelForm.Data[idPanel].updatePanel();
|
|
458
555
|
},
|
|
459
556
|
});
|
|
460
557
|
if (!options.parentIdModal)
|
|
461
558
|
Modal.Data['modal-menu'].onHome[idPanel] = async () => {
|
|
462
559
|
lastCid = undefined;
|
|
463
560
|
lastUserId = undefined;
|
|
464
|
-
setQueryPath({ path: options.route, queryPath: '' });
|
|
465
|
-
await
|
|
561
|
+
setQueryPath({ path: options.route, queryPath: options.route === 'home' ? '?' : '' });
|
|
562
|
+
await PanelForm.Data[idPanel].updatePanel();
|
|
466
563
|
};
|
|
467
564
|
}
|
|
468
565
|
|
|
@@ -3,11 +3,11 @@ import { Auth } from './Auth.js';
|
|
|
3
3
|
import { BtnIcon } from './BtnIcon.js';
|
|
4
4
|
import { EventsUI } from './EventsUI.js';
|
|
5
5
|
import { Input } from './Input.js';
|
|
6
|
-
import { LogIn } from './LogIn.js';
|
|
7
6
|
import { NotificationManager } from './NotificationManager.js';
|
|
8
7
|
import { Translate } from './Translate.js';
|
|
9
8
|
import { Validator } from './Validator.js';
|
|
10
|
-
import {
|
|
9
|
+
import { s } from './VanillaJs.js';
|
|
10
|
+
import { getProxyPath, getQueryParams } from './Router.js';
|
|
11
11
|
|
|
12
12
|
const Recover = {
|
|
13
13
|
Event: {},
|