Skip to content

Commit 097afb1

Browse files
committed
Encahnce pickDocument and use it to select superclass
1 parent 60db6b1 commit 097afb1

File tree

3 files changed

+35
-165
lines changed

3 files changed

+35
-165
lines changed

src/commands/newFile.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { DocumentContentProvider } from "../providers/DocumentContentProvider";
66
import { replaceFile, getWsFolder, handleError, displayableUri } from "../utils";
77
import { getFileName } from "./export";
88
import { getUrisForDocument } from "../utils/documentIndex";
9-
import { pickClass } from "./project";
9+
import { pickDocument } from "../utils/documentPicker";
1010

1111
interface InputStepItem extends vscode.QuickPickItem {
1212
value?: string;
@@ -112,7 +112,7 @@ async function multiStepInput(steps: InputStepOptions[]): Promise<string[] | und
112112
// Optional step: escape = skip (store ""), back = go back one step, pick = store class name
113113
let picked: string | undefined;
114114
if (stepOptions.api) {
115-
picked = await pickClass(stepOptions.api, stepOptions.title, step > 0);
115+
picked = await pickDocument(stepOptions.api, stepOptions.title, "cls", step + 1, steps.length);
116116
} else {
117117
// Fallback InputBox when there's no server connection
118118
picked = await new Promise<string | undefined>((resolve) => {
@@ -150,11 +150,16 @@ async function multiStepInput(steps: InputStepOptions[]): Promise<string[] | und
150150
inputBox.show();
151151
});
152152
}
153-
if (picked === undefined) {
153+
if (picked === "") {
154154
// Back button was pressed: go back one step
155155
step--;
156156
} else {
157-
// "" = skipped, or a class name was entered/picked
157+
// undefined = skipped, or a class name was entered/picked
158+
if (typeof picked == "undefined") {
159+
picked = "";
160+
} else if (picked.slice(-4) == ".cls") {
161+
picked = picked.slice(0, -4);
162+
}
158163
results[step] = picked;
159164
step++;
160165
}
@@ -999,7 +1004,7 @@ Parameter ENSPURGE As BOOLEAN = 1;
9991004
// Add the superclass picker as the third step
10001005
inputSteps.push({
10011006
type: "classPick",
1002-
title: "Pick an optional superclass. Press 'Escape' to skip.",
1007+
title: "Pick an optional superclass or press 'Escape' for none",
10031008
api: api,
10041009
});
10051010

src/commands/project.ts

Lines changed: 0 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -650,160 +650,6 @@ async function pickAdditions(
650650
});
651651
}
652652

653-
/**
654-
* Show an expandable QuickPick to let the user pick a single class from the server.
655-
* Packages can be expanded to reveal their classes. Only leaf class items can be accepted.
656-
* - Returns the class name (without the `.cls` extension) when a class is picked.
657-
* - Returns `""` when the user presses Escape (skip this optional step).
658-
* - Returns `undefined` when the user presses the Back button (only when `canGoBack` is `true`).
659-
*/
660-
export async function pickClass(api: AtelierAPI, title: string, canGoBack = false): Promise<string | undefined> {
661-
const query = "SELECT Name, Type FROM %Library.RoutineMgr_StudioOpenDialog(?,1,1,?,0,0,?)";
662-
let sys: "0" | "1" = "0";
663-
let gen: "0" | "1" = "0";
664-
665-
return new Promise<string | undefined>((resolve) => {
666-
// Use a settled flag so that onDidHide (which always fires) never double-resolves.
667-
let settled = false;
668-
const settle = (value: string | undefined) => {
669-
if (!settled) {
670-
settled = true;
671-
resolve(value);
672-
}
673-
};
674-
675-
const quickPick = vscode.window.createQuickPick<PickAdditionsItem>();
676-
quickPick.title = title;
677-
quickPick.ignoreFocusOut = true;
678-
quickPick.keepScrollPosition = true;
679-
quickPick.matchOnDescription = true;
680-
quickPick.buttons = [
681-
...(canGoBack ? [vscode.QuickInputButtons.Back] : []),
682-
{
683-
iconPath: new vscode.ThemeIcon("library"),
684-
tooltip: "System",
685-
location: vscode.QuickInputButtonLocation.Input,
686-
toggle: { checked: false },
687-
},
688-
{
689-
iconPath: new vscode.ThemeIcon("server-process"),
690-
tooltip: "Generated",
691-
location: vscode.QuickInputButtonLocation.Input,
692-
toggle: { checked: false },
693-
},
694-
];
695-
696-
const getRootItems = (): Promise<void> => {
697-
return api
698-
.actionQuery(query, ["*.cls", sys, gen])
699-
.then((data) => {
700-
quickPick.items = data.result.content.map((i) => sodItemToPickAdditionsItem(i));
701-
quickPick.busy = false;
702-
})
703-
.catch((error) => {
704-
quickPick.hide();
705-
handleError(error, "Failed to get namespace contents.");
706-
});
707-
};
708-
709-
const expandItem = (itemIdx: number): Promise<void> => {
710-
const item = quickPick.items[itemIdx];
711-
// Switch the expand button to a collapse button
712-
const newItems = [...quickPick.items];
713-
newItems[itemIdx] = {
714-
...item,
715-
buttons: [{ iconPath: new vscode.ThemeIcon("chevron-down"), tooltip: "Collapse" }],
716-
};
717-
quickPick.items = newItems;
718-
return api
719-
.actionQuery(query, [item.fullName + "/*.cls", sys, gen])
720-
.then((data) => {
721-
const insertItems: PickAdditionsItem[] = data.result.content.map((i) =>
722-
sodItemToPickAdditionsItem(i, item.fullName, item.label.search(/\S/))
723-
);
724-
const updatedItems = [...quickPick.items];
725-
updatedItems.splice(itemIdx + 1, 0, ...insertItems);
726-
quickPick.items = updatedItems;
727-
quickPick.busy = false;
728-
})
729-
.catch((error) => {
730-
quickPick.hide();
731-
handleError(error, "Failed to get namespace contents.");
732-
});
733-
};
734-
735-
quickPick.onDidTriggerButton((button) => {
736-
if (button === vscode.QuickInputButtons.Back) {
737-
settle(undefined); // signal "go back" to the caller
738-
quickPick.hide();
739-
} else {
740-
quickPick.busy = true;
741-
if (button.tooltip == "System") {
742-
sys = button.toggle.checked ? "1" : "0";
743-
} else {
744-
gen = button.toggle.checked ? "1" : "0";
745-
}
746-
getRootItems();
747-
}
748-
});
749-
750-
quickPick.onDidTriggerItemButton((event) => {
751-
quickPick.busy = true;
752-
const itemIdx = quickPick.items.findIndex((i) => i.fullName === event.item.fullName);
753-
if (event.button.tooltip.charAt(0) == "E") {
754-
expandItem(itemIdx);
755-
} else {
756-
// Collapse: remove the button and all descendants
757-
const newItems = [...quickPick.items];
758-
newItems[itemIdx] = {
759-
...newItems[itemIdx],
760-
buttons: [{ iconPath: new vscode.ThemeIcon("chevron-right"), tooltip: "Expand" }],
761-
};
762-
quickPick.items = newItems.filter(
763-
(i, idx) => idx <= itemIdx || !i.fullName.startsWith(event.item.fullName + ".")
764-
);
765-
quickPick.busy = false;
766-
}
767-
});
768-
769-
quickPick.onDidChangeValue((filter: string) => {
770-
// Auto-expand a package when the user types its name followed by a dot
771-
if (filter.endsWith(".")) {
772-
const itemIdx = quickPick.items.findIndex(
773-
(i) => i.fullName.toLowerCase() === filter.slice(0, -1).toLowerCase()
774-
);
775-
if (
776-
itemIdx != -1 &&
777-
quickPick.items[itemIdx].buttons?.length &&
778-
quickPick.items[itemIdx].buttons[0].tooltip.charAt(0) == "E"
779-
) {
780-
quickPick.busy = true;
781-
expandItem(itemIdx);
782-
}
783-
}
784-
});
785-
786-
quickPick.onDidAccept(() => {
787-
const selected = quickPick.activeItems[0];
788-
if (selected && !selected.buttons?.length) {
789-
// Leaf class item (no expand button): strip the .cls extension and resolve
790-
const name = selected.fullName.endsWith(".cls") ? selected.fullName.slice(0, -4) : selected.fullName;
791-
settle(name);
792-
quickPick.hide();
793-
}
794-
});
795-
796-
quickPick.onDidHide(() => {
797-
settle(""); // Escape pressed: resolve with "" to signal "skip this optional step"
798-
quickPick.dispose();
799-
});
800-
801-
quickPick.busy = true;
802-
quickPick.show();
803-
getRootItems();
804-
});
805-
}
806-
807653
export async function modifyProject(
808654
nodeOrUri: NodeBase | vscode.Uri | undefined,
809655
type: "add" | "remove"

src/utils/documentPicker.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,14 +285,23 @@ export async function pickDocuments(api: AtelierAPI, prompt?: string): Promise<s
285285

286286
/**
287287
* Prompts the user to select a single document in server-namespace `api`
288-
* using a custom QuickPick. An optional prompt will customize the title.
288+
* using a custom QuickPick. An optional `prompt` will customize the title.
289+
* `typeSuffix` can be provided to filter for specific types of documents (e.g. "cls").
290+
* If `step` is provided and greater than 1, a back button will be included that resolves to an empty string when pressed.
291+
* If `numberOfSteps` is provided, the title will be suffixed with the current step and total number of steps (e.g. "(2/4)") instead of the namespace and server information.
289292
*/
290-
export async function pickDocument(api: AtelierAPI, prompt?: string): Promise<string> {
293+
export async function pickDocument(
294+
api: AtelierAPI,
295+
prompt?: string,
296+
typeSuffix?: string,
297+
step?: number,
298+
numberOfSteps?: number
299+
): Promise<string> {
291300
let sys: "0" | "1" = "0";
292301
let gen: "0" | "1" = "0";
293302
let map: "0" | "1" = "1";
294303
const query = "SELECT Name, Type FROM %Library.RoutineMgr_StudioOpenDialog(?,1,1,?,0,0,?,,0,?)";
295-
const webApps = cspAppsForApi(api);
304+
const webApps = (typeSuffix ?? "csp") == "csp" ? cspAppsForApi(api) : [];
296305
const webAppRootItems = webApps.map((app: string) => {
297306
return {
298307
label: app,
@@ -302,9 +311,10 @@ export async function pickDocument(api: AtelierAPI, prompt?: string): Promise<st
302311

303312
return new Promise<string>((resolve) => {
304313
const quickPick = vscode.window.createQuickPick<DocumentPickerItem>();
305-
quickPick.title = `${prompt ? prompt : "Select a document"} in namespace '${api.ns}' on server '${api.serverId}'`;
314+
quickPick.title = `${prompt ? prompt : "Select a document"} ${numberOfSteps ? `(${step}/${numberOfSteps})` : `in namespace '${api.ns}' on server '${api.serverId}'`}`;
306315
quickPick.ignoreFocusOut = true;
307316
quickPick.buttons = [
317+
...((step ?? 0) > 1 ? [vscode.QuickInputButtons.Back] : []),
308318
{
309319
iconPath: new vscode.ThemeIcon("library"),
310320
tooltip: "System",
@@ -327,7 +337,12 @@ export async function pickDocument(api: AtelierAPI, prompt?: string): Promise<st
327337

328338
const getRootItems = (): Promise<void> => {
329339
return api
330-
.actionQuery(`${query} WHERE Type != 5 AND Type != 10`, ["*,'*.prj", sys, gen, map])
340+
.actionQuery(`${query} WHERE Type != 5 AND Type != 10`, [
341+
typeSuffix ? `*.${typeSuffix}` : "*,'*.prj",
342+
sys,
343+
gen,
344+
map,
345+
])
331346
.then((data) => {
332347
const rootitems: DocumentPickerItem[] = data.result.content.map((i) => createSingleSelectItem(i));
333348
const findLastIndex = (): number => {
@@ -356,6 +371,10 @@ export async function pickDocument(api: AtelierAPI, prompt?: string): Promise<st
356371
quickPick.onDidTriggerButton((button) => {
357372
quickPick.busy = true;
358373
quickPick.enabled = false;
374+
if (button === vscode.QuickInputButtons.Back) {
375+
resolve(""); // signal "go back" to the caller
376+
quickPick.hide();
377+
}
359378
if (button.tooltip == "System") {
360379
sys = button.toggle.checked ? "1" : "0";
361380
} else if (button.tooltip == "Generated") {
@@ -409,7 +428,7 @@ export async function pickDocument(api: AtelierAPI, prompt?: string): Promise<st
409428
getRootItems();
410429
} else {
411430
api
412-
.actionQuery(query, [`${item.fullName}/*`, sys, gen, map])
431+
.actionQuery(query, [`${item.fullName}/*${typeSuffix ? `.${typeSuffix}` : ""}`, sys, gen, map])
413432
.then((data) => {
414433
const delim = item.fullName.includes("/") ? "/" : ".";
415434
const newItems: DocumentPickerItem[] = data.result.content.map((i) =>

0 commit comments

Comments
 (0)