@peers-app/peers-ui 0.7.35 → 0.7.40
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/dist/command-palette/command-palette-ui.js +190 -35
- package/dist/command-palette/command-palette.js +0 -121
- package/dist/mention-configs.js +1 -1
- package/dist/screens/console-logs/console-logs-list.js +45 -47
- package/dist/screens/search/global-search.js +110 -36
- package/package.json +3 -3
- package/src/command-palette/command-palette-ui.tsx +245 -12
- package/src/command-palette/command-palette.ts +0 -121
- package/src/mention-configs.ts +1 -1
- package/src/screens/console-logs/console-logs-list.tsx +47 -56
- package/src/screens/search/global-search.tsx +126 -7
|
@@ -38,10 +38,16 @@ const react_1 = __importStar(require("react"));
|
|
|
38
38
|
const hooks_1 = require("../hooks");
|
|
39
39
|
const color_mode_dropdown_1 = require("../screens/settings/color-mode-dropdown");
|
|
40
40
|
const command_palette_1 = require("./command-palette");
|
|
41
|
+
const routes_loader_1 = require("../ui-router/routes-loader");
|
|
42
|
+
const system_apps_1 = require("../system-apps");
|
|
43
|
+
const tabs_state_1 = require("../tabs-layout/tabs-state");
|
|
44
|
+
const peers_sdk_1 = require("@peers-app/peers-sdk");
|
|
45
|
+
const globals_1 = require("../globals");
|
|
41
46
|
function CommandPaletteOverlay() {
|
|
42
47
|
const [isOpen] = (0, hooks_1.useObservable)(command_palette_1.isCommandPaletteOpen);
|
|
43
48
|
const [_persistedQuery] = (0, hooks_1.useObservable)(command_palette_1.commandSearchQuery);
|
|
44
49
|
const [_colorMode] = (0, hooks_1.useObservable)(color_mode_dropdown_1.colorMode);
|
|
50
|
+
const [packages] = (0, hooks_1.useObservable)(routes_loader_1.allPackages);
|
|
45
51
|
const [selectedIndex, setSelectedIndex] = (0, react_1.useState)(0);
|
|
46
52
|
const inputRef = (0, react_1.useRef)(null);
|
|
47
53
|
// Local state for query input to avoid locking up on fast typing
|
|
@@ -75,7 +81,70 @@ function CommandPaletteOverlay() {
|
|
|
75
81
|
}, []);
|
|
76
82
|
const searchQuery = localQuery;
|
|
77
83
|
const filteredCommands = (0, command_palette_1.searchCommands)(searchQuery);
|
|
84
|
+
// Get all apps (system and user)
|
|
85
|
+
const getAllApps = () => {
|
|
86
|
+
const allPackages_ = [...packages, system_apps_1.systemPackage];
|
|
87
|
+
return allPackages_
|
|
88
|
+
.filter(p => !p.disabled && p.appNavs && p.appNavs.length > 0)
|
|
89
|
+
.flatMap(pkg => pkg.appNavs.map(navItem => {
|
|
90
|
+
// Construct path - use direct path for system apps, package-nav for others
|
|
91
|
+
let path;
|
|
92
|
+
if (pkg.packageId === 'system-apps') {
|
|
93
|
+
path = navItem.navigationPath ?? navItem.name.replace(/\s/g, '-').toLowerCase();
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
path = `package-nav/${pkg.packageId}/${(navItem.navigationPath ?? navItem.name).replace(/[^a-zA-Z0-9]/g, '-').toLowerCase()}`;
|
|
97
|
+
while (path.includes('//')) {
|
|
98
|
+
path = path.replace('//', '/');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
packageId: pkg.packageId,
|
|
103
|
+
packageName: pkg.name,
|
|
104
|
+
navItem,
|
|
105
|
+
path,
|
|
106
|
+
name: navItem.name,
|
|
107
|
+
displayName: navItem.displayName || navItem.name,
|
|
108
|
+
iconClassName: navItem.iconClassName || 'bi-box-seam'
|
|
109
|
+
};
|
|
110
|
+
}));
|
|
111
|
+
};
|
|
112
|
+
// Search apps
|
|
113
|
+
const searchApps = (query) => {
|
|
114
|
+
if (!query.trim())
|
|
115
|
+
return [];
|
|
116
|
+
const allApps = getAllApps();
|
|
117
|
+
const lowerQuery = query.toLowerCase();
|
|
118
|
+
return allApps.filter(app => app.name.toLowerCase().includes(lowerQuery) ||
|
|
119
|
+
app.displayName.toLowerCase().includes(lowerQuery) ||
|
|
120
|
+
app.packageName.toLowerCase().includes(lowerQuery));
|
|
121
|
+
};
|
|
122
|
+
const filteredApps = searchApps(searchQuery);
|
|
123
|
+
// Function to create a new thread from search query
|
|
124
|
+
const createNewThreadFromQuery = async (query) => {
|
|
125
|
+
try {
|
|
126
|
+
const currentUser = await (0, peers_sdk_1.getMe)();
|
|
127
|
+
const threadMessage = await (0, peers_sdk_1.Messages)().insert({
|
|
128
|
+
messageId: (0, peers_sdk_1.newid)(),
|
|
129
|
+
userId: currentUser.userId,
|
|
130
|
+
channelId: currentUser.userId,
|
|
131
|
+
message: query.trim(),
|
|
132
|
+
createdAt: new Date(),
|
|
133
|
+
});
|
|
134
|
+
await (0, globals_1.openThreadInTab)(threadMessage);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
console.error('Failed to create new thread:', error);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
78
140
|
// Create a flattened list that matches the visual rendering order
|
|
141
|
+
// Apps first, then commands
|
|
142
|
+
const allItems = [];
|
|
143
|
+
// Add apps first
|
|
144
|
+
filteredApps.forEach((app) => {
|
|
145
|
+
allItems.push({ type: 'app', app, id: `app-${app.packageId}-${app.path}` });
|
|
146
|
+
});
|
|
147
|
+
// Then add commands
|
|
79
148
|
const visualOrderCommands = Object.entries(filteredCommands.reduce((acc, cmd) => {
|
|
80
149
|
const category = cmd.category || 'Other';
|
|
81
150
|
if (!acc[category])
|
|
@@ -83,6 +152,9 @@ function CommandPaletteOverlay() {
|
|
|
83
152
|
acc[category].push(cmd);
|
|
84
153
|
return acc;
|
|
85
154
|
}, {})).flatMap(([, commands]) => commands);
|
|
155
|
+
visualOrderCommands.forEach((cmd) => {
|
|
156
|
+
allItems.push({ type: 'command', command: cmd, id: `command-${cmd.id}` });
|
|
157
|
+
});
|
|
86
158
|
// Focus input when opened
|
|
87
159
|
(0, react_1.useEffect)(() => {
|
|
88
160
|
if (isOpen && inputRef.current) {
|
|
@@ -100,7 +172,9 @@ function CommandPaletteOverlay() {
|
|
|
100
172
|
const handleKeyDown = (e) => {
|
|
101
173
|
if (e.key === 'ArrowDown') {
|
|
102
174
|
e.preventDefault();
|
|
103
|
-
|
|
175
|
+
// Allow selection to go one past the end if there's a search query (for new thread option)
|
|
176
|
+
const maxIndex = searchQuery.trim() ? allItems.length : allItems.length - 1;
|
|
177
|
+
setSelectedIndex(prev => Math.min(prev + 1, maxIndex));
|
|
104
178
|
}
|
|
105
179
|
else if (e.key === 'ArrowUp') {
|
|
106
180
|
e.preventDefault();
|
|
@@ -108,14 +182,34 @@ function CommandPaletteOverlay() {
|
|
|
108
182
|
}
|
|
109
183
|
else if (e.key === 'Enter') {
|
|
110
184
|
e.preventDefault();
|
|
111
|
-
if (
|
|
112
|
-
|
|
185
|
+
// Check if the new thread option is selected (selectedIndex >= allItems.length)
|
|
186
|
+
if (selectedIndex >= allItems.length && searchQuery.trim()) {
|
|
187
|
+
(0, command_palette_1.closeCommandPalette)();
|
|
188
|
+
createNewThreadFromQuery(searchQuery);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
const selectedItem = allItems[selectedIndex];
|
|
192
|
+
if (selectedItem) {
|
|
193
|
+
if (selectedItem.type === 'app' && selectedItem.app) {
|
|
194
|
+
(0, command_palette_1.closeCommandPalette)();
|
|
195
|
+
(0, tabs_state_1.goToTabPath)(selectedItem.app.path);
|
|
196
|
+
}
|
|
197
|
+
else if (selectedItem.type === 'command' && selectedItem.command) {
|
|
198
|
+
(0, command_palette_1.executeCommand)(selectedItem.command.id);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else if (searchQuery.trim()) {
|
|
202
|
+
// Fallback: Create a new thread with the search query as the message
|
|
203
|
+
// This happens when no item is selected (selectedIndex is out of bounds or -1)
|
|
204
|
+
(0, command_palette_1.closeCommandPalette)();
|
|
205
|
+
createNewThreadFromQuery(searchQuery);
|
|
206
|
+
}
|
|
113
207
|
}
|
|
114
208
|
}
|
|
115
209
|
};
|
|
116
210
|
document.addEventListener('keydown', handleKeyDown);
|
|
117
211
|
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
118
|
-
}, [isOpen,
|
|
212
|
+
}, [isOpen, allItems, selectedIndex]);
|
|
119
213
|
if (!isOpen)
|
|
120
214
|
return null;
|
|
121
215
|
const isDark = _colorMode === 'dark';
|
|
@@ -152,7 +246,7 @@ function CommandPaletteOverlay() {
|
|
|
152
246
|
color: '#6c757d',
|
|
153
247
|
zIndex: 1
|
|
154
248
|
} }),
|
|
155
|
-
react_1.default.createElement("input", { ref: inputRef, type: "text", className: `form-control ${isDark ? 'bg-dark text-light border-secondary' : ''}`, placeholder: "
|
|
249
|
+
react_1.default.createElement("input", { ref: inputRef, type: "text", className: `form-control ${isDark ? 'bg-dark text-light border-secondary' : ''}`, placeholder: "Search apps, commands, or navigate...", value: searchQuery, onChange: (e) => {
|
|
156
250
|
const newQuery = e.target.value;
|
|
157
251
|
setLocalQuery(newQuery);
|
|
158
252
|
updatePersistedQuery(newQuery);
|
|
@@ -174,41 +268,101 @@ function CommandPaletteOverlay() {
|
|
|
174
268
|
react_1.default.createElement("div", { style: {
|
|
175
269
|
maxHeight: '400px',
|
|
176
270
|
overflowY: 'auto'
|
|
177
|
-
} },
|
|
271
|
+
} }, allItems.length === 0 && !searchQuery.trim() ? (react_1.default.createElement("div", { className: "p-4 text-center text-muted" },
|
|
178
272
|
react_1.default.createElement("i", { className: "bi-search mb-2 d-block", style: { fontSize: '24px' } }),
|
|
179
|
-
"No
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
273
|
+
"No results found")) : (react_1.default.createElement("div", { className: "py-2" },
|
|
274
|
+
allItems.length === 0 && searchQuery.trim() && (react_1.default.createElement("div", { className: "px-3 py-2 text-muted small text-center" }, "No matching results")),
|
|
275
|
+
filteredApps.length > 0 && (react_1.default.createElement("div", null,
|
|
276
|
+
react_1.default.createElement("div", { className: "px-3 py-1 small text-muted fw-bold text-uppercase", style: { fontSize: '11px', letterSpacing: '0.5px' } }, "Apps"),
|
|
277
|
+
filteredApps.map((app) => {
|
|
278
|
+
const appId = `app-${app.packageId}-${app.path}`;
|
|
279
|
+
const globalIndex = allItems.findIndex(item => item.id === appId);
|
|
280
|
+
const isSelected = globalIndex === selectedIndex;
|
|
281
|
+
return (react_1.default.createElement("div", { key: `${app.packageId}-${app.path}`, className: `px-3 py-2 d-flex align-items-center justify-content-between ${isSelected
|
|
282
|
+
? (isDark ? 'bg-primary bg-opacity-25' : 'bg-primary bg-opacity-10')
|
|
283
|
+
: ''}`, style: {
|
|
284
|
+
cursor: 'pointer',
|
|
285
|
+
transition: 'background-color 0.1s ease'
|
|
286
|
+
}, onClick: () => {
|
|
287
|
+
(0, command_palette_1.closeCommandPalette)();
|
|
288
|
+
(0, tabs_state_1.goToTabPath)(app.path);
|
|
289
|
+
}, onMouseEnter: () => setSelectedIndex(globalIndex) },
|
|
290
|
+
react_1.default.createElement("div", { className: "d-flex align-items-center" },
|
|
291
|
+
react_1.default.createElement("i", { className: `${app.iconClassName} me-3`, style: {
|
|
292
|
+
fontSize: '16px',
|
|
293
|
+
color: isSelected ? (isDark ? '#ffffff' : '#0d6efd') : '#6c757d',
|
|
294
|
+
minWidth: '16px'
|
|
295
|
+
} }),
|
|
296
|
+
react_1.default.createElement("div", null,
|
|
297
|
+
react_1.default.createElement("div", { className: "fw-medium" }, app.displayName),
|
|
298
|
+
react_1.default.createElement("div", { className: "small text-muted", style: { fontSize: '12px' } }, app.packageId === 'system-apps' ? 'System App' : app.packageName)))));
|
|
299
|
+
}))),
|
|
300
|
+
filteredCommands.length > 0 && Object.entries(filteredCommands.reduce((acc, cmd) => {
|
|
301
|
+
const category = cmd.category || 'Other';
|
|
302
|
+
if (!acc[category])
|
|
303
|
+
acc[category] = [];
|
|
304
|
+
acc[category].push(cmd);
|
|
305
|
+
return acc;
|
|
306
|
+
}, {})).map(([category, commands]) => (react_1.default.createElement("div", { key: category },
|
|
307
|
+
react_1.default.createElement("div", { className: "px-3 py-1 small text-muted fw-bold text-uppercase", style: { fontSize: '11px', letterSpacing: '0.5px' } }, category),
|
|
308
|
+
commands.map((command) => {
|
|
309
|
+
const commandId = `command-${command.id}`;
|
|
310
|
+
const globalIndex = allItems.findIndex(item => item.id === commandId);
|
|
311
|
+
const isSelected = globalIndex === selectedIndex;
|
|
312
|
+
return (react_1.default.createElement("div", { key: command.id, className: `px-3 py-2 d-flex align-items-center justify-content-between ${isSelected
|
|
313
|
+
? (isDark ? 'bg-primary bg-opacity-25' : 'bg-primary bg-opacity-10')
|
|
314
|
+
: ''}`, style: {
|
|
315
|
+
cursor: 'pointer',
|
|
316
|
+
transition: 'background-color 0.1s ease'
|
|
317
|
+
}, onClick: () => (0, command_palette_1.executeCommand)(command.id), onMouseEnter: () => setSelectedIndex(globalIndex) },
|
|
318
|
+
react_1.default.createElement("div", { className: "d-flex align-items-center" },
|
|
319
|
+
command.iconClassName && (react_1.default.createElement("i", { className: `${command.iconClassName} me-3`, style: {
|
|
320
|
+
fontSize: '16px',
|
|
321
|
+
color: isSelected ? (isDark ? '#ffffff' : '#0d6efd') : '#6c757d',
|
|
322
|
+
minWidth: '16px'
|
|
323
|
+
} })),
|
|
324
|
+
react_1.default.createElement("div", null,
|
|
325
|
+
react_1.default.createElement("div", { className: "fw-medium" }, command.label),
|
|
326
|
+
command.description && (react_1.default.createElement("div", { className: "small text-muted", style: { fontSize: '12px' } }, command.description)))),
|
|
327
|
+
command.shortcut && (react_1.default.createElement("div", { className: `small px-2 py-1 rounded ${isDark ? 'bg-secondary bg-opacity-50' : 'bg-light'}`, style: {
|
|
328
|
+
fontSize: '11px',
|
|
329
|
+
fontFamily: 'monospace',
|
|
330
|
+
color: isDark ? '#adb5bd' : '#6c757d',
|
|
331
|
+
border: isDark ? '1px solid #495057' : '1px solid #dee2e6'
|
|
332
|
+
} }, command.shortcut))));
|
|
333
|
+
})))),
|
|
334
|
+
searchQuery.trim() && (react_1.default.createElement("div", null,
|
|
335
|
+
react_1.default.createElement("div", { className: "px-3 py-1 small text-muted fw-bold text-uppercase", style: { fontSize: '11px', letterSpacing: '0.5px' } }, "Actions"),
|
|
336
|
+
react_1.default.createElement("div", { className: `px-3 py-2 d-flex align-items-center ${(allItems.length === 0 || selectedIndex >= allItems.length) && searchQuery.trim()
|
|
191
337
|
? (isDark ? 'bg-primary bg-opacity-25' : 'bg-primary bg-opacity-10')
|
|
192
338
|
: ''}`, style: {
|
|
193
339
|
cursor: 'pointer',
|
|
194
|
-
transition: 'background-color 0.1s ease'
|
|
195
|
-
|
|
340
|
+
transition: 'background-color 0.1s ease',
|
|
341
|
+
borderTop: allItems.length > 0 ? `1px solid ${isDark ? '#495057' : '#dee2e6'}` : 'none',
|
|
342
|
+
marginTop: allItems.length > 0 ? '8px' : '0',
|
|
343
|
+
paddingTop: allItems.length > 0 ? '12px' : '8px'
|
|
344
|
+
}, onClick: () => {
|
|
345
|
+
(0, command_palette_1.closeCommandPalette)();
|
|
346
|
+
createNewThreadFromQuery(searchQuery);
|
|
347
|
+
}, onMouseEnter: () => {
|
|
348
|
+
// Set selected index beyond the list to indicate this item is selected
|
|
349
|
+
setSelectedIndex(allItems.length);
|
|
350
|
+
} },
|
|
196
351
|
react_1.default.createElement("div", { className: "d-flex align-items-center" },
|
|
197
|
-
|
|
352
|
+
react_1.default.createElement("i", { className: "bi-chat-dots me-3", style: {
|
|
198
353
|
fontSize: '16px',
|
|
199
|
-
color:
|
|
354
|
+
color: (allItems.length === 0 || selectedIndex >= allItems.length) && searchQuery.trim()
|
|
355
|
+
? (isDark ? '#ffffff' : '#0d6efd')
|
|
356
|
+
: '#6c757d',
|
|
200
357
|
minWidth: '16px'
|
|
201
|
-
} })
|
|
358
|
+
} }),
|
|
202
359
|
react_1.default.createElement("div", null,
|
|
203
|
-
react_1.default.createElement("div", { className: "fw-medium" },
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
border: isDark ? '1px solid #495057' : '1px solid #dee2e6'
|
|
210
|
-
} }, command.shortcut))));
|
|
211
|
-
}))))))),
|
|
360
|
+
react_1.default.createElement("div", { className: "fw-medium" },
|
|
361
|
+
"Start new thread: ",
|
|
362
|
+
react_1.default.createElement("span", { className: "text-muted" },
|
|
363
|
+
searchQuery.trim().slice(0, 50),
|
|
364
|
+
searchQuery.trim().length > 50 ? '...' : '')),
|
|
365
|
+
react_1.default.createElement("div", { className: "small text-muted", style: { fontSize: '12px' } }, "Press Enter to create"))))))))),
|
|
212
366
|
react_1.default.createElement("div", { className: `px-3 py-2 small text-muted border-top d-flex align-items-center justify-content-between`, style: {
|
|
213
367
|
borderTopColor: isDark ? '#495057' : '#dee2e6',
|
|
214
368
|
fontSize: '11px'
|
|
@@ -224,7 +378,8 @@ function CommandPaletteOverlay() {
|
|
|
224
378
|
react_1.default.createElement("kbd", { className: "small" }, "esc"),
|
|
225
379
|
" to close")),
|
|
226
380
|
react_1.default.createElement("div", null,
|
|
227
|
-
|
|
228
|
-
"
|
|
229
|
-
|
|
381
|
+
allItems.length,
|
|
382
|
+
" result",
|
|
383
|
+
allItems.length !== 1 ? 's' : '',
|
|
384
|
+
searchQuery.trim() && allItems.length === 0 && ' • Start thread')))));
|
|
230
385
|
}
|
|
@@ -129,127 +129,6 @@ const coreCommands = [
|
|
|
129
129
|
closeCommandPalette();
|
|
130
130
|
(0, tabs_state_1.goToTabPath)('threads');
|
|
131
131
|
}
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
id: 'go-settings',
|
|
135
|
-
label: 'Open Settings',
|
|
136
|
-
description: 'Open application settings',
|
|
137
|
-
iconClassName: 'bi-gear-fill',
|
|
138
|
-
category: 'Navigation',
|
|
139
|
-
action: () => {
|
|
140
|
-
closeCommandPalette();
|
|
141
|
-
(0, tabs_state_1.goToTabPath)('settings');
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
id: 'go-assistants',
|
|
146
|
-
label: 'Go to Assistants',
|
|
147
|
-
description: 'View and manage assistants',
|
|
148
|
-
iconClassName: 'bi-person-fill-gear',
|
|
149
|
-
category: 'Navigation',
|
|
150
|
-
action: () => {
|
|
151
|
-
closeCommandPalette();
|
|
152
|
-
(0, tabs_state_1.goToTabPath)('assistants');
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
id: 'go-workflows',
|
|
157
|
-
label: 'Go to Workflows',
|
|
158
|
-
description: 'View and manage workflows',
|
|
159
|
-
iconClassName: 'bi-database-fill-gear',
|
|
160
|
-
category: 'Navigation',
|
|
161
|
-
action: () => {
|
|
162
|
-
closeCommandPalette();
|
|
163
|
-
(0, tabs_state_1.goToTabPath)('workflows');
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
id: 'go-tools',
|
|
168
|
-
label: 'Go to Tools',
|
|
169
|
-
description: 'View and manage tools',
|
|
170
|
-
iconClassName: 'bi-tools',
|
|
171
|
-
category: 'Navigation',
|
|
172
|
-
action: () => {
|
|
173
|
-
closeCommandPalette();
|
|
174
|
-
(0, tabs_state_1.goToTabPath)('tools');
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
id: 'go-events',
|
|
179
|
-
label: 'Go to Events',
|
|
180
|
-
description: 'View and manage events',
|
|
181
|
-
iconClassName: 'bi-lightning-charge-fill',
|
|
182
|
-
category: 'Navigation',
|
|
183
|
-
action: () => {
|
|
184
|
-
closeCommandPalette();
|
|
185
|
-
(0, tabs_state_1.goToTabPath)('events');
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
id: 'go-predicates',
|
|
190
|
-
label: 'Go to Predicates',
|
|
191
|
-
description: 'View and manage predicates',
|
|
192
|
-
iconClassName: 'bi-node-plus-fill',
|
|
193
|
-
category: 'Navigation',
|
|
194
|
-
action: () => {
|
|
195
|
-
closeCommandPalette();
|
|
196
|
-
(0, tabs_state_1.goToTabPath)('predicates');
|
|
197
|
-
}
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
id: 'go-peer-types',
|
|
201
|
-
label: 'Go to Peer Types',
|
|
202
|
-
description: 'View and manage peer types',
|
|
203
|
-
iconClassName: 'bi-code-square',
|
|
204
|
-
category: 'Navigation',
|
|
205
|
-
action: () => {
|
|
206
|
-
closeCommandPalette();
|
|
207
|
-
(0, tabs_state_1.goToTabPath)('peer-types');
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
{
|
|
211
|
-
id: 'go-packages',
|
|
212
|
-
label: 'Go to Packages',
|
|
213
|
-
description: 'View and manage packages',
|
|
214
|
-
iconClassName: 'bi-box-fill',
|
|
215
|
-
category: 'Navigation',
|
|
216
|
-
action: () => {
|
|
217
|
-
closeCommandPalette();
|
|
218
|
-
(0, tabs_state_1.goToTabPath)('packages');
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
{
|
|
222
|
-
id: 'go-variables',
|
|
223
|
-
label: 'Go to Variables',
|
|
224
|
-
description: 'View and manage variables',
|
|
225
|
-
iconClassName: 'bi-braces',
|
|
226
|
-
category: 'Navigation',
|
|
227
|
-
action: () => {
|
|
228
|
-
closeCommandPalette();
|
|
229
|
-
(0, tabs_state_1.goToTabPath)('variables');
|
|
230
|
-
}
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
id: 'go-knowledge-values',
|
|
234
|
-
label: 'Go to Knowledge Values',
|
|
235
|
-
description: 'View and manage knowledge values',
|
|
236
|
-
iconClassName: 'bi-journal-bookmark-fill',
|
|
237
|
-
category: 'Navigation',
|
|
238
|
-
action: () => {
|
|
239
|
-
closeCommandPalette();
|
|
240
|
-
(0, tabs_state_1.goToTabPath)('knowledge-values');
|
|
241
|
-
}
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
id: 'go-knowledge-frames',
|
|
245
|
-
label: 'Go to Knowledge Frames',
|
|
246
|
-
description: 'View and manage knowledge frames',
|
|
247
|
-
iconClassName: 'bi-window-dock',
|
|
248
|
-
category: 'Navigation',
|
|
249
|
-
action: () => {
|
|
250
|
-
closeCommandPalette();
|
|
251
|
-
(0, tabs_state_1.goToTabPath)('knowledge-frames');
|
|
252
|
-
}
|
|
253
132
|
}
|
|
254
133
|
];
|
|
255
134
|
// Register core commands
|
package/dist/mention-configs.js
CHANGED
|
@@ -128,7 +128,7 @@ exports.valueTypeMentionConfig = {
|
|
|
128
128
|
name: item.name
|
|
129
129
|
}),
|
|
130
130
|
onClick(data) {
|
|
131
|
-
peers_sdk_1.rpcClientCalls.setClientPath(`
|
|
131
|
+
peers_sdk_1.rpcClientCalls.setClientPath(`peer-types/${data.id}`);
|
|
132
132
|
},
|
|
133
133
|
};
|
|
134
134
|
// Tasks().list({ title: { $matchWords: mentionString }, completeDT: { $exists: searchCompletedTasks } }, { pageSize: MAX_RESULTS })
|
|
@@ -59,9 +59,10 @@ const DEFAULT_COLUMNS = [
|
|
|
59
59
|
const ConsoleLogsList = () => {
|
|
60
60
|
const logs = (0, hooks_1.useObservableState)([]);
|
|
61
61
|
const [allLogsLoaded, setAllLogsLoaded] = (0, react_1.useState)(false);
|
|
62
|
+
const loadMoreId = (0, hooks_1.useObservableState)((0, peers_sdk_1.newid)(), true);
|
|
62
63
|
const [levelFilter, setLevelFilter] = (0, react_1.useState)('all');
|
|
63
64
|
const [processFilter, setProcessFilter] = (0, react_1.useState)('all');
|
|
64
|
-
const
|
|
65
|
+
const searchText = (0, hooks_1.useObservableState)('');
|
|
65
66
|
const [columns, setColumns] = (0, react_1.useState)(DEFAULT_COLUMNS);
|
|
66
67
|
const [totalLogCount, setTotalLogCount] = (0, react_1.useState)(0);
|
|
67
68
|
const [_colorMode] = (0, hooks_1.useObservable)(color_mode_dropdown_1.colorMode);
|
|
@@ -102,6 +103,9 @@ const ConsoleLogsList = () => {
|
|
|
102
103
|
if (processFilter !== 'all') {
|
|
103
104
|
filter.process = processFilter;
|
|
104
105
|
}
|
|
106
|
+
if (searchText()) {
|
|
107
|
+
filter.message = { $matchWords: searchText() };
|
|
108
|
+
}
|
|
105
109
|
return filter;
|
|
106
110
|
};
|
|
107
111
|
// Update total log count
|
|
@@ -109,11 +113,6 @@ const ConsoleLogsList = () => {
|
|
|
109
113
|
const table = await (0, peers_sdk_1.ConsoleLogs)();
|
|
110
114
|
const filter = buildFilter();
|
|
111
115
|
let count = await table.count(filter);
|
|
112
|
-
// If search text is applied, we need to count manually since it's client-side filtering
|
|
113
|
-
if (searchText) {
|
|
114
|
-
const allLogs = await table.list(filter);
|
|
115
|
-
count = allLogs.filter(log => log.message.toLowerCase().includes(searchText.toLowerCase())).length;
|
|
116
|
-
}
|
|
117
116
|
setTotalLogCount(count);
|
|
118
117
|
}
|
|
119
118
|
// Fetch logs using cursor-based pagination
|
|
@@ -123,54 +122,50 @@ const ConsoleLogsList = () => {
|
|
|
123
122
|
if (lastLog) {
|
|
124
123
|
filter.logId = { $lt: lastLog.logId };
|
|
125
124
|
}
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
});
|
|
129
|
-
const fetchedLogs = [];
|
|
130
|
-
for await (const log of cursor) {
|
|
131
|
-
// Apply text search filter (if search is implemented in cursor, this can be removed)
|
|
132
|
-
if (searchText && !log.message.toLowerCase().includes(searchText.toLowerCase())) {
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
fetchedLogs.push(log);
|
|
136
|
-
if (fetchedLogs.length >= batchSize) {
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return fetchedLogs;
|
|
125
|
+
const results = await table.list(filter, { pageSize: batchSize, sortBy: ['-timestamp', '-logId'] });
|
|
126
|
+
return results;
|
|
141
127
|
}
|
|
142
128
|
// Load older logs (prepend to list)
|
|
143
|
-
function
|
|
129
|
+
async function loadMoreLogs(startLoadId) {
|
|
130
|
+
if (startLoadId && startLoadId !== loadMoreId()) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
startLoadId ??= loadMoreId();
|
|
144
134
|
const oldestLog = logs()[0];
|
|
145
|
-
fetchLogs(oldestLog)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
135
|
+
const fetchedLogs = await fetchLogs(oldestLog);
|
|
136
|
+
if (loadMoreId() !== startLoadId) {
|
|
137
|
+
loadMoreLogs(loadMoreId());
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (fetchedLogs.length === 0) {
|
|
141
|
+
setAllLogsLoaded(true);
|
|
142
|
+
}
|
|
143
|
+
let _logs = (0, lodash_1.sortBy)([...logs(), ...fetchedLogs], 'timestamp');
|
|
144
|
+
_logs = (0, lodash_1.uniqBy)(_logs, l => l.logId);
|
|
145
|
+
logs(_logs);
|
|
156
146
|
}
|
|
157
147
|
// Initial load and ensure screen is filled
|
|
158
148
|
const minHeightOfLog = 30;
|
|
159
149
|
(0, react_1.useEffect)(() => {
|
|
160
150
|
if (!allLogsLoaded && (!logs.length || logs.length * minHeightOfLog < windowHeight())) {
|
|
161
|
-
|
|
151
|
+
loadMoreLogs();
|
|
162
152
|
}
|
|
163
|
-
}, [logs, levelFilter, processFilter, searchText]);
|
|
153
|
+
}, [logs, levelFilter, processFilter, searchText()]);
|
|
164
154
|
// Reset when filters change
|
|
165
155
|
(0, react_1.useEffect)(() => {
|
|
156
|
+
loadMoreId((0, peers_sdk_1.newid)());
|
|
166
157
|
logs([]);
|
|
167
|
-
setAllLogsLoaded(false);
|
|
168
158
|
updateLogCount();
|
|
169
|
-
|
|
159
|
+
if (allLogsLoaded) {
|
|
160
|
+
setAllLogsLoaded(false);
|
|
161
|
+
loadMoreLogs();
|
|
162
|
+
}
|
|
163
|
+
}, [levelFilter, processFilter, searchText()]);
|
|
170
164
|
// Subscribe to new logs
|
|
171
165
|
(0, react_1.useEffect)(() => {
|
|
166
|
+
let sub = undefined;
|
|
172
167
|
(0, peers_sdk_1.ConsoleLogs)().then(table => {
|
|
173
|
-
|
|
168
|
+
sub = table.dataChanged.subscribe(evt => {
|
|
174
169
|
// Update count whenever data changes
|
|
175
170
|
updateLogCount();
|
|
176
171
|
const log = evt.dataObject;
|
|
@@ -179,8 +174,12 @@ const ConsoleLogsList = () => {
|
|
|
179
174
|
return;
|
|
180
175
|
if (processFilter !== 'all' && log.process !== processFilter)
|
|
181
176
|
return;
|
|
182
|
-
if (searchText
|
|
183
|
-
|
|
177
|
+
if (searchText()) {
|
|
178
|
+
const logMessage = log.message.toLowerCase();
|
|
179
|
+
const filterOut = searchText().toLowerCase().split(' ').some(word => !logMessage.includes(word));
|
|
180
|
+
if (filterOut)
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
184
183
|
// Don't add we're only showing a limited batch and this is older
|
|
185
184
|
if (logs().length > batchSize && (0, lodash_1.min)(logs().map(l => l.timestamp)) > log.timestamp)
|
|
186
185
|
return;
|
|
@@ -191,11 +190,11 @@ const ConsoleLogsList = () => {
|
|
|
191
190
|
scrollToBottom('smooth');
|
|
192
191
|
}
|
|
193
192
|
});
|
|
194
|
-
return () => {
|
|
195
|
-
sub.unsubscribe();
|
|
196
|
-
};
|
|
197
193
|
});
|
|
198
|
-
|
|
194
|
+
return () => {
|
|
195
|
+
sub?.unsubscribe();
|
|
196
|
+
};
|
|
197
|
+
}, [levelFilter, processFilter]);
|
|
199
198
|
function scrollToBottom(behavior, delay = 100) {
|
|
200
199
|
setTimeout(() => {
|
|
201
200
|
logsEndRef.current?.scrollIntoView({ behavior });
|
|
@@ -207,7 +206,6 @@ const ConsoleLogsList = () => {
|
|
|
207
206
|
const table = await (0, peers_sdk_1.ConsoleLogs)();
|
|
208
207
|
await table.deleteOldLogs(Date.now());
|
|
209
208
|
logs([]);
|
|
210
|
-
setAllLogsLoaded(true);
|
|
211
209
|
setTotalLogCount(0);
|
|
212
210
|
}
|
|
213
211
|
catch (err) {
|
|
@@ -217,7 +215,7 @@ const ConsoleLogsList = () => {
|
|
|
217
215
|
}
|
|
218
216
|
const _logs = (0, lodash_1.uniqBy)(logs(), l => l.logId);
|
|
219
217
|
return (react_1.default.createElement("div", { className: "container-fluid", style: { height: 'calc(100vh - 100px)', display: 'flex', flexDirection: 'column' } },
|
|
220
|
-
react_1.default.createElement(log_filters_1.LogFilters, { levelFilter: levelFilter, setLevelFilter: setLevelFilter, processFilter: processFilter, setProcessFilter: setProcessFilter, searchText: searchText, setSearchText:
|
|
218
|
+
react_1.default.createElement(log_filters_1.LogFilters, { levelFilter: levelFilter, setLevelFilter: setLevelFilter, processFilter: processFilter, setProcessFilter: setProcessFilter, searchText: searchText(), setSearchText: searchText }),
|
|
221
219
|
react_1.default.createElement("div", { ref: containerRef, style: {
|
|
222
220
|
flex: 1,
|
|
223
221
|
display: 'flex',
|
|
@@ -234,7 +232,7 @@ const ConsoleLogsList = () => {
|
|
|
234
232
|
display: 'flex',
|
|
235
233
|
flexDirection: 'column-reverse',
|
|
236
234
|
} },
|
|
237
|
-
react_1.default.createElement(react_infinite_scroll_component_1.default, { dataLength: _logs.length, next:
|
|
235
|
+
react_1.default.createElement(react_infinite_scroll_component_1.default, { dataLength: _logs.length, next: loadMoreLogs, style: { display: 'flex', flexDirection: 'column-reverse', overflow: 'hidden' }, inverse: true, hasMore: !allLogsLoaded, loader: react_1.default.createElement(loading_indicator_1.LoadingIndicator, null), scrollableTarget: "scrollableLogsDiv", endMessage: react_1.default.createElement(react_1.Fragment, null,
|
|
238
236
|
react_1.default.createElement("div", { className: "d-flex justify-content-center p-3" },
|
|
239
237
|
react_1.default.createElement("div", { className: "text-muted" },
|
|
240
238
|
react_1.default.createElement("i", null, "beginning of logs")))) },
|