projax 3.3.66 → 3.3.67
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/prxi.js +58 -15
- package/dist/prxi.tsx +56 -13
- package/package.json +1 -1
package/dist/prxi.js
CHANGED
|
@@ -139,6 +139,7 @@ const HelpModal = ({ onClose }) => {
|
|
|
139
139
|
react_1.default.createElement(ink_1.Text, null, " u Show detected URLs"),
|
|
140
140
|
react_1.default.createElement(ink_1.Text, null, " s Scan project for tests"),
|
|
141
141
|
react_1.default.createElement(ink_1.Text, null, " p Scan ports for project"),
|
|
142
|
+
react_1.default.createElement(ink_1.Text, null, " Enter Run selected script (in details panel)"),
|
|
142
143
|
react_1.default.createElement(ink_1.Text, null, " r Run scripts (select from list)"),
|
|
143
144
|
react_1.default.createElement(ink_1.Text, null, " x Stop all scripts for project"),
|
|
144
145
|
react_1.default.createElement(ink_1.Text, null, " d Delete project (with confirmation)"),
|
|
@@ -336,12 +337,12 @@ const ScriptSelectionModal = ({ scripts, projectName, projectPath, onSelect, onC
|
|
|
336
337
|
}
|
|
337
338
|
if (key.return) {
|
|
338
339
|
const [scriptName] = scriptArray[selectedIndex];
|
|
339
|
-
onSelect(scriptName,
|
|
340
|
+
onSelect(scriptName, true);
|
|
340
341
|
return;
|
|
341
342
|
}
|
|
342
|
-
if (input === '
|
|
343
|
+
if (input === 'f') {
|
|
343
344
|
const [scriptName] = scriptArray[selectedIndex];
|
|
344
|
-
onSelect(scriptName,
|
|
345
|
+
onSelect(scriptName, false);
|
|
345
346
|
return;
|
|
346
347
|
}
|
|
347
348
|
});
|
|
@@ -359,7 +360,7 @@ const ScriptSelectionModal = ({ scripts, projectName, projectPath, onSelect, onC
|
|
|
359
360
|
react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, truncateText(script.command, 50))));
|
|
360
361
|
}),
|
|
361
362
|
react_1.default.createElement(ink_1.Text, null, " "),
|
|
362
|
-
react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, "\u2191\u2193/kj: Navigate | Enter: Run |
|
|
363
|
+
react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, "\u2191\u2193/kj: Navigate | Enter: Run (bg) | f: Foreground | Esc/q: Cancel")));
|
|
363
364
|
};
|
|
364
365
|
const ProjectListComponent = ({ projects, selectedIndex, runningProcesses, isFocused, height, scrollOffset, gitBranches, filterType, sortType, }) => {
|
|
365
366
|
const { focus } = (0, ink_1.useFocus)({ id: 'projectList' });
|
|
@@ -415,7 +416,7 @@ const ProjectListComponent = ({ projects, selectedIndex, runningProcesses, isFoc
|
|
|
415
416
|
projects.length - endIndex,
|
|
416
417
|
" more below")))))));
|
|
417
418
|
};
|
|
418
|
-
const ProjectDetailsComponent = ({ project, runningProcesses, isFocused, editingName, editingDescription, editingTags, editInput, allTags, onTagRemove, height, scrollOffset, gitBranch, }) => {
|
|
419
|
+
const ProjectDetailsComponent = ({ project, runningProcesses, isFocused, editingName, editingDescription, editingTags, editInput, allTags, onTagRemove, height, scrollOffset, gitBranch, selectedScriptIndex, }) => {
|
|
419
420
|
const { focus } = (0, ink_1.useFocus)({ id: 'projectDetails' });
|
|
420
421
|
const [scripts, setScripts] = (0, react_1.useState)(null);
|
|
421
422
|
const [ports, setPorts] = (0, react_1.useState)([]);
|
|
@@ -572,10 +573,11 @@ const ProjectDetailsComponent = ({ project, runningProcesses, isFocused, editing
|
|
|
572
573
|
"Available Scripts (",
|
|
573
574
|
react_1.default.createElement(ink_1.Text, { color: colors.accentCyan }, scripts.scripts.size),
|
|
574
575
|
"):"));
|
|
575
|
-
Array.from(scripts.scripts.entries()).forEach(([name, script]) => {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
576
|
+
Array.from(scripts.scripts.entries()).forEach(([name, script], idx) => {
|
|
577
|
+
const isScriptSelected = isFocused && idx === selectedScriptIndex;
|
|
578
|
+
contentLines.push(react_1.default.createElement(ink_1.Text, { key: `script-${name}`, bold: isScriptSelected },
|
|
579
|
+
isScriptSelected ? '▶ ' : ' ',
|
|
580
|
+
react_1.default.createElement(ink_1.Text, { color: isScriptSelected ? colors.accentCyan : colors.accentGreen }, name),
|
|
579
581
|
' - ',
|
|
580
582
|
react_1.default.createElement(ink_1.Text, { color: colors.textSecondary }, truncateText(script.command, 60))));
|
|
581
583
|
});
|
|
@@ -806,6 +808,7 @@ const App = () => {
|
|
|
806
808
|
// Script selection state
|
|
807
809
|
const [showScriptModal, setShowScriptModal] = (0, react_1.useState)(false);
|
|
808
810
|
const [scriptModalData, setScriptModalData] = (0, react_1.useState)(null);
|
|
811
|
+
const [detailSelectedScript, setDetailSelectedScript] = (0, react_1.useState)(0);
|
|
809
812
|
// Workspace state
|
|
810
813
|
const [workspaces, setWorkspaces] = (0, react_1.useState)([]);
|
|
811
814
|
const [selectedWorkspaceIndex, setSelectedWorkspaceIndex] = (0, react_1.useState)(0);
|
|
@@ -876,6 +879,7 @@ const App = () => {
|
|
|
876
879
|
setEditingTags(false);
|
|
877
880
|
setEditInput('');
|
|
878
881
|
setDetailsScrollOffset(0); // Reset scroll when switching projects
|
|
882
|
+
setDetailSelectedScript(0); // Reset selected script
|
|
879
883
|
}, [selectedIndex]);
|
|
880
884
|
// Load workspaces when switching to workspaces view
|
|
881
885
|
(0, react_1.useEffect)(() => {
|
|
@@ -1536,15 +1540,54 @@ const App = () => {
|
|
|
1536
1540
|
}
|
|
1537
1541
|
// Details panel actions
|
|
1538
1542
|
if (focusedPanel === 'details' && selectedProject) {
|
|
1539
|
-
//
|
|
1543
|
+
// Navigate scripts in details panel
|
|
1540
1544
|
if (key.upArrow || input === 'k') {
|
|
1541
|
-
|
|
1545
|
+
const projectScripts = (0, script_runner_1.getProjectScripts)(selectedProject.path);
|
|
1546
|
+
if (projectScripts.scripts.size > 0) {
|
|
1547
|
+
setDetailSelectedScript(prev => Math.max(0, prev - 1));
|
|
1548
|
+
}
|
|
1549
|
+
else {
|
|
1550
|
+
setDetailsScrollOffset(prev => Math.max(0, prev - 1));
|
|
1551
|
+
}
|
|
1542
1552
|
return;
|
|
1543
1553
|
}
|
|
1544
1554
|
if (key.downArrow || input === 'j') {
|
|
1545
|
-
const
|
|
1546
|
-
|
|
1547
|
-
|
|
1555
|
+
const projectScripts = (0, script_runner_1.getProjectScripts)(selectedProject.path);
|
|
1556
|
+
if (projectScripts.scripts.size > 0) {
|
|
1557
|
+
setDetailSelectedScript(prev => Math.min(projectScripts.scripts.size - 1, prev + 1));
|
|
1558
|
+
}
|
|
1559
|
+
else {
|
|
1560
|
+
setDetailsScrollOffset(prev => prev + 1);
|
|
1561
|
+
}
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
// Run selected script with Enter
|
|
1565
|
+
if (key.return) {
|
|
1566
|
+
try {
|
|
1567
|
+
const projectScripts = (0, script_runner_1.getProjectScripts)(selectedProject.path);
|
|
1568
|
+
if (projectScripts.scripts.size > 0) {
|
|
1569
|
+
const scriptArray = Array.from(projectScripts.scripts.keys());
|
|
1570
|
+
const scriptName = scriptArray[detailSelectedScript];
|
|
1571
|
+
if (scriptName) {
|
|
1572
|
+
setIsLoading(true);
|
|
1573
|
+
setLoadingMessage(`Running ${scriptName} in background...`);
|
|
1574
|
+
setTimeout(async () => {
|
|
1575
|
+
try {
|
|
1576
|
+
await (0, script_runner_1.runScriptInBackground)(selectedProject.path, selectedProject.name, scriptName, [], false);
|
|
1577
|
+
setIsLoading(false);
|
|
1578
|
+
await loadRunningProcesses();
|
|
1579
|
+
}
|
|
1580
|
+
catch (err) {
|
|
1581
|
+
setIsLoading(false);
|
|
1582
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
1583
|
+
}
|
|
1584
|
+
}, 100);
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
catch (err) {
|
|
1589
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
1590
|
+
}
|
|
1548
1591
|
return;
|
|
1549
1592
|
}
|
|
1550
1593
|
// Edit name
|
|
@@ -1744,7 +1787,7 @@ const App = () => {
|
|
|
1744
1787
|
const renderProjectsView = () => (react_1.default.createElement(ink_1.Box, { flexDirection: "row", height: availableHeight, flexGrow: 0, flexShrink: 0 },
|
|
1745
1788
|
react_1.default.createElement(ProjectListComponent, { projects: projects, selectedIndex: selectedIndex, runningProcesses: runningProcesses, isFocused: focusedPanel === 'list', height: availableHeight, scrollOffset: listScrollOffset, gitBranches: gitBranches, filterType: filterType, sortType: sortType }),
|
|
1746
1789
|
react_1.default.createElement(ink_1.Box, { width: 1 }),
|
|
1747
|
-
react_1.default.createElement(ProjectDetailsComponent, { project: selectedProject, runningProcesses: runningProcesses, isFocused: focusedPanel === 'details', editingName: editingName, editingDescription: editingDescription, editingTags: editingTags, editInput: editInput, allTags: allTags, onTagRemove: handleTagRemove, height: availableHeight, scrollOffset: detailsScrollOffset, gitBranch: selectedProject ? gitBranches.get(selectedProject.id) || null : null }),
|
|
1790
|
+
react_1.default.createElement(ProjectDetailsComponent, { project: selectedProject, runningProcesses: runningProcesses, isFocused: focusedPanel === 'details', editingName: editingName, editingDescription: editingDescription, editingTags: editingTags, editInput: editInput, allTags: allTags, onTagRemove: handleTagRemove, height: availableHeight, scrollOffset: detailsScrollOffset, gitBranch: selectedProject ? gitBranches.get(selectedProject.id) || null : null, selectedScriptIndex: detailSelectedScript }),
|
|
1748
1791
|
showTerminalPanel && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
1749
1792
|
react_1.default.createElement(ink_1.Box, { width: 1 }),
|
|
1750
1793
|
react_1.default.createElement(TerminalOutputPanel, { processes: runningProcesses, selectedPid: selectedProcessPid, height: availableHeight, onSelectProcess: (pid) => setSelectedProcessPid(pid) })))));
|
package/dist/prxi.tsx
CHANGED
|
@@ -162,6 +162,7 @@ const HelpModal: React.FC<HelpModalProps> = ({ onClose }) => {
|
|
|
162
162
|
<Text> u Show detected URLs</Text>
|
|
163
163
|
<Text> s Scan project for tests</Text>
|
|
164
164
|
<Text> p Scan ports for project</Text>
|
|
165
|
+
<Text> Enter Run selected script (in details panel)</Text>
|
|
165
166
|
<Text> r Run scripts (select from list)</Text>
|
|
166
167
|
<Text> x Stop all scripts for project</Text>
|
|
167
168
|
<Text> d Delete project (with confirmation)</Text>
|
|
@@ -470,13 +471,13 @@ const ScriptSelectionModal: React.FC<ScriptSelectionModalProps> = ({
|
|
|
470
471
|
|
|
471
472
|
if (key.return) {
|
|
472
473
|
const [scriptName] = scriptArray[selectedIndex];
|
|
473
|
-
onSelect(scriptName,
|
|
474
|
+
onSelect(scriptName, true);
|
|
474
475
|
return;
|
|
475
476
|
}
|
|
476
477
|
|
|
477
|
-
if (input === '
|
|
478
|
+
if (input === 'f') {
|
|
478
479
|
const [scriptName] = scriptArray[selectedIndex];
|
|
479
|
-
onSelect(scriptName,
|
|
480
|
+
onSelect(scriptName, false);
|
|
480
481
|
return;
|
|
481
482
|
}
|
|
482
483
|
});
|
|
@@ -505,7 +506,7 @@ const ScriptSelectionModal: React.FC<ScriptSelectionModalProps> = ({
|
|
|
505
506
|
);
|
|
506
507
|
})}
|
|
507
508
|
<Text> </Text>
|
|
508
|
-
<Text color={colors.textSecondary}>↑↓/kj: Navigate | Enter: Run |
|
|
509
|
+
<Text color={colors.textSecondary}>↑↓/kj: Navigate | Enter: Run (bg) | f: Foreground | Esc/q: Cancel</Text>
|
|
509
510
|
</Box>
|
|
510
511
|
);
|
|
511
512
|
};
|
|
@@ -631,6 +632,7 @@ interface ProjectDetailsProps {
|
|
|
631
632
|
height: number;
|
|
632
633
|
scrollOffset: number;
|
|
633
634
|
gitBranch: string | null;
|
|
635
|
+
selectedScriptIndex: number;
|
|
634
636
|
}
|
|
635
637
|
|
|
636
638
|
const ProjectDetailsComponent: React.FC<ProjectDetailsProps> = ({
|
|
@@ -646,6 +648,7 @@ const ProjectDetailsComponent: React.FC<ProjectDetailsProps> = ({
|
|
|
646
648
|
height,
|
|
647
649
|
scrollOffset,
|
|
648
650
|
gitBranch,
|
|
651
|
+
selectedScriptIndex,
|
|
649
652
|
}) => {
|
|
650
653
|
const { focus } = useFocus({ id: 'projectDetails' });
|
|
651
654
|
const [scripts, setScripts] = useState<any>(null);
|
|
@@ -858,11 +861,12 @@ const ProjectDetailsComponent: React.FC<ProjectDetailsProps> = ({
|
|
|
858
861
|
Available Scripts (<Text color={colors.accentCyan}>{scripts.scripts.size}</Text>):
|
|
859
862
|
</Text>
|
|
860
863
|
);
|
|
861
|
-
Array.from(scripts.scripts.entries() as IterableIterator<[string, any]>).forEach(([name, script]) => {
|
|
864
|
+
Array.from(scripts.scripts.entries() as IterableIterator<[string, any]>).forEach(([name, script], idx) => {
|
|
865
|
+
const isScriptSelected = isFocused && idx === selectedScriptIndex;
|
|
862
866
|
contentLines.push(
|
|
863
|
-
<Text key={`script-${name}`}>
|
|
864
|
-
{' '}
|
|
865
|
-
<Text color={colors.accentGreen}>{name}</Text>
|
|
867
|
+
<Text key={`script-${name}`} bold={isScriptSelected}>
|
|
868
|
+
{isScriptSelected ? '▶ ' : ' '}
|
|
869
|
+
<Text color={isScriptSelected ? colors.accentCyan : colors.accentGreen}>{name}</Text>
|
|
866
870
|
{' - '}
|
|
867
871
|
<Text color={colors.textSecondary}>{truncateText(script.command, 60)}</Text>
|
|
868
872
|
</Text>
|
|
@@ -1177,6 +1181,7 @@ const App: React.FC = () => {
|
|
|
1177
1181
|
// Script selection state
|
|
1178
1182
|
const [showScriptModal, setShowScriptModal] = useState(false);
|
|
1179
1183
|
const [scriptModalData, setScriptModalData] = useState<{ scripts: Map<string, any>; projectName: string; projectPath: string } | null>(null);
|
|
1184
|
+
const [detailSelectedScript, setDetailSelectedScript] = useState(0);
|
|
1180
1185
|
|
|
1181
1186
|
// Workspace state
|
|
1182
1187
|
const [workspaces, setWorkspaces] = useState<Workspace[]>([]);
|
|
@@ -1256,6 +1261,7 @@ const App: React.FC = () => {
|
|
|
1256
1261
|
setEditingTags(false);
|
|
1257
1262
|
setEditInput('');
|
|
1258
1263
|
setDetailsScrollOffset(0); // Reset scroll when switching projects
|
|
1264
|
+
setDetailSelectedScript(0); // Reset selected script
|
|
1259
1265
|
}, [selectedIndex]);
|
|
1260
1266
|
|
|
1261
1267
|
// Load workspaces when switching to workspaces view
|
|
@@ -1969,16 +1975,52 @@ const App: React.FC = () => {
|
|
|
1969
1975
|
|
|
1970
1976
|
// Details panel actions
|
|
1971
1977
|
if (focusedPanel === 'details' && selectedProject) {
|
|
1972
|
-
//
|
|
1978
|
+
// Navigate scripts in details panel
|
|
1973
1979
|
if (key.upArrow || input === 'k') {
|
|
1974
|
-
|
|
1980
|
+
const projectScripts = getProjectScripts(selectedProject.path);
|
|
1981
|
+
if (projectScripts.scripts.size > 0) {
|
|
1982
|
+
setDetailSelectedScript(prev => Math.max(0, prev - 1));
|
|
1983
|
+
} else {
|
|
1984
|
+
setDetailsScrollOffset(prev => Math.max(0, prev - 1));
|
|
1985
|
+
}
|
|
1975
1986
|
return;
|
|
1976
1987
|
}
|
|
1977
1988
|
|
|
1978
1989
|
if (key.downArrow || input === 'j') {
|
|
1979
|
-
const
|
|
1980
|
-
|
|
1981
|
-
|
|
1990
|
+
const projectScripts = getProjectScripts(selectedProject.path);
|
|
1991
|
+
if (projectScripts.scripts.size > 0) {
|
|
1992
|
+
setDetailSelectedScript(prev => Math.min(projectScripts.scripts.size - 1, prev + 1));
|
|
1993
|
+
} else {
|
|
1994
|
+
setDetailsScrollOffset(prev => prev + 1);
|
|
1995
|
+
}
|
|
1996
|
+
return;
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
// Run selected script with Enter
|
|
2000
|
+
if (key.return) {
|
|
2001
|
+
try {
|
|
2002
|
+
const projectScripts = getProjectScripts(selectedProject.path);
|
|
2003
|
+
if (projectScripts.scripts.size > 0) {
|
|
2004
|
+
const scriptArray = Array.from(projectScripts.scripts.keys());
|
|
2005
|
+
const scriptName = scriptArray[detailSelectedScript];
|
|
2006
|
+
if (scriptName) {
|
|
2007
|
+
setIsLoading(true);
|
|
2008
|
+
setLoadingMessage(`Running ${scriptName} in background...`);
|
|
2009
|
+
setTimeout(async () => {
|
|
2010
|
+
try {
|
|
2011
|
+
await runScriptInBackground(selectedProject.path, selectedProject.name, scriptName, [], false);
|
|
2012
|
+
setIsLoading(false);
|
|
2013
|
+
await loadRunningProcesses();
|
|
2014
|
+
} catch (err) {
|
|
2015
|
+
setIsLoading(false);
|
|
2016
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2017
|
+
}
|
|
2018
|
+
}, 100);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
} catch (err) {
|
|
2022
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
2023
|
+
}
|
|
1982
2024
|
return;
|
|
1983
2025
|
}
|
|
1984
2026
|
|
|
@@ -2283,6 +2325,7 @@ const App: React.FC = () => {
|
|
|
2283
2325
|
height={availableHeight}
|
|
2284
2326
|
scrollOffset={detailsScrollOffset}
|
|
2285
2327
|
gitBranch={selectedProject ? gitBranches.get(selectedProject.id) || null : null}
|
|
2328
|
+
selectedScriptIndex={detailSelectedScript}
|
|
2286
2329
|
/>
|
|
2287
2330
|
{showTerminalPanel && (
|
|
2288
2331
|
<>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projax",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.67",
|
|
4
4
|
"description": "Cross-platform project management dashboard for tracking local development projects. Features CLI, Terminal UI, Desktop app, REST API, and built-in tools for test detection, port management, and script execution.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|