zowe / zowe-explorer-vscode

Visual Studio Code Extension for Zowe, which lets users interact with z/OS Data Sets, Unix System Services, and Jobs on a remote mainframe instance. Powered by Zowe SDKs.
Eclipse Public License 2.0
173 stars 92 forks source link

expose Profiles methods: createZoweSession, createZoweSchema, editZoweConfigFile #3229

Open sosadchuk opened 1 month ago

sosadchuk commented 1 month ago

Hi,

We're developing a vscode extension that is extending Zowe Explorer if it's available (no hard dependency on the extension is set).

However in both cases we want to provide an aligned experience to our users in terms of initializing & editing the Zowe Team config, meaning the same Add Profile button, quick picks, confirmations, notifications and so on:

image

image

image

image

Profiles class extends ProfilesCache with some useful methods like:

Is it possible to move them to the base class by removing view-specific processing?

I believe we reuse almost all of them with minimal changes (commented out trace calls to keep a minimal amount of reused code).

The main entry point that we have is createZoweSession, the difference is in the view specific code that is commented out:

    public async createZoweSession(): Promise<void> {
        // ZoweLogger.trace("Profiles.createZoweSession called.");
        // let profileNamesList: string[] = [];
        // const treeType = zoweFileProvider.getTreeType();
        // let allProfiles: imperative.IProfileLoaded[];
        // try {
        //     allProfiles = Profiles.getInstance().allProfiles;
        //     if (allProfiles) {
        //         // Get all profiles and filter to list of the APIs available for current tree explorer
        //         profileNamesList = allProfiles
        //             .map((profile) => profile.name)
        //             .filter((profileName) => {
        //                 const profile = Profiles.getInstance().loadNamedProfile(profileName);
        //                 const notInSessionNodes = !zoweFileProvider.mSessionNodes?.find(
        //                     (sessionNode) => sessionNode.getProfileName() === profileName
        //                 );
        //                 if (profile) {
        //                     if (zoweFileProvider.getTreeType() === PersistenceSchemaEnum.USS) {
        //                         const ussProfileTypes = ZoweExplorerApiRegister.getInstance().registeredUssApiTypes();
        //                         return ussProfileTypes.includes(profile.type) && notInSessionNodes;
        //                     }
        //                     if (zoweFileProvider.getTreeType() === PersistenceSchemaEnum.Dataset) {
        //                         const mvsProfileTypes = ZoweExplorerApiRegister.getInstance().registeredMvsApiTypes();
        //                         return mvsProfileTypes.includes(profile.type) && notInSessionNodes;
        //                     }
        //                     if (zoweFileProvider.getTreeType() === PersistenceSchemaEnum.Job) {
        //                         const jesProfileTypes = ZoweExplorerApiRegister.getInstance().registeredJesApiTypes();
        //                         return jesProfileTypes.includes(profile.type) && notInSessionNodes;
        //                     }
        //                 }

        //                 return false;
        //             });
        //     }
        // } catch (err) {
        //     ZoweLogger.warn(err);
        // }
        // // Set Options according to profile management in use

        const createNewConfig = "Create a New Team Configuration File";
        const editConfig = "Edit Team Configuration File";

        const configPick = new FilterDescriptor("\uFF0B " + createNewConfig);
        const configEdit = new FilterDescriptor("\u270F " + editConfig);
        // const items: vscode.QuickPickItem[] = [];
        let mProfileInfo: imperative.ProfileInfo;
        try {
            mProfileInfo = await this.getProfileInfo();
        } catch (err) {
            // ZoweLogger.error(err);
            assertError(err);   <- our custom method that asserts unknown to Error
            ZoweExplorerExtender.showZoweConfigError(err.message);
            return;
        }
        // const profAllAttrs = mProfileInfo.getAllProfiles();
        // for (const pName of profileNamesList) {
        //     const osLocInfo = mProfileInfo.getOsLocInfo(profAllAttrs.find((p) => p.profName === pName));
        //     items.push(new FilterItem({ text: pName, icon: this.getProfileIcon(osLocInfo)[0] }));
        // }

        const quickpick = Gui.createQuickPick();
        // let addProfilePlaceholder = "";
        // switch (zoweFileProvider.getTreeType()) {
        //     case PersistenceSchemaEnum.Dataset:
        //         addProfilePlaceholder = vscode.l10n.t(`Choose "Create new..." to define or select a profile to add to the DATA SETS Explorer`);
        //         break;
        //     case PersistenceSchemaEnum.Job:
        //         addProfilePlaceholder = vscode.l10n.t(`Choose "Create new..." to define or select a profile to add to the JOBS Explorer`);
        //         break;
        //     default:
        //         // Use USS View as default for placeholder text
        //         addProfilePlaceholder = vscode.l10n.t(`Choose "Create new..." to define or select a profile to add to the USS Explorer`);
        // }

        if (mProfileInfo && mProfileInfo.getAllProfiles().length > 0) {
            quickpick.items = [configPick, configEdit];
            quickpick.placeholder = "Choose to create or edit a Team Configuration File";
        } else {
            quickpick.items = [configPick];
            quickpick.placeholder = "Create a new Team Configuration File";
        }

        // quickpick.placeholder = addProfilePlaceholder;
        quickpick.ignoreFocusOut = true;
        quickpick.show();

        const choice = await Gui.resolveQuickPick(quickpick);
        quickpick.hide();
        const debugMsg = vscode.l10n.t(`Profile selection has been cancelled.`);

        if (!choice) {
            // ZoweLogger.debug(debugMsg);
            Gui.showMessage(debugMsg);
            return;
        }
        if (choice === configPick) {
            if (ZoweVsCodeExtension.getZoweExplorerApi(ZOWE_EXPLORER_API_VERSION)) await vscode.commands.executeCommand("zowe.all.config.init");
            else await this.createZoweSchema();

            return;
        }
        if (choice === configEdit) {
            await this.editZoweConfigFile();
            return;
        }

        // let chosenProfile: string = "";
        // if (choice instanceof FilterDescriptor) {
        //     chosenProfile = "";
        // } else {
        //     // remove any icons from the label
        //     chosenProfile = choice.label.replace(/\$\(.*\)\s/g, "");
        // }
        // if (chosenProfile === "") {
        //     let config: imperative.ProfileInfo;
        //     try {
        //         config = await this.getProfileInfo();
        //     } catch (error) {
        //         ZoweLogger.error(error);
        //         ZoweExplorerExtender.showZoweConfigError(error.message);
        //         return;
        //     }
        //     const profiles = config.getAllProfiles();
        //     const currentProfile = await this.getProfileFromConfig(profiles[0].profName);
        //     const filePath = currentProfile.profLoc.osLoc[0];
        //     await this.openConfigFile(filePath);
        // } else if (chosenProfile) {
        //     ZoweLogger.info(
        //         vscode.l10n.t({
        //             message: `The profile {0} has been added to the {1} tree.`,
        //             args: [chosenProfile, treeType],
        //             comment: ["chosen profile", "tree type"],
        //         }),
        //     );
        //     await zoweFileProvider.addSession({
        //         sessionName: chosenProfile,
        //         addToAllTrees: await Profiles.handleChangeForAllTrees(chosenProfile, true),
        //     });
        // } else {
        //     ZoweLogger.debug(debugMsg);
        // }
    }

Of course some of other module methods are imported too, so the final list of files we reuse looks like the following:

│  │     └─ zowe-explorer/
│  │        ├─ l10n/
│  │        │  └─ bundle.l10n.json [56.32 KB]
│  │        └─ src/
│  │           ├─ configuration/
│  │           │  ├─ Constants.js [8.99 KB]
│  │           │  ├─ Profiles.js [10.29 KB]
│  │           │  └─ SettingsConfig.js [0.43 KB]
│  │           ├─ extending/
│  │           │  └─ ZoweExplorerExtender.js [2.72 KB]
│  │           └─ management/
│  │              └─ FilterManagement.js [0.42 KB]
import { ProfileConstants } from "@zowe/core-for-zowe-sdk";
import {
    FileManagement,
    Gui,
    imperative,
    ProfilesCache,
    Validation,
    ZoweVsCodeExtension,
} from "@zowe/zowe-explorer-api";
import * as path from "path";
import * as vscode from "vscode";
import { Constants } from "./Constants";
import { SettingsConfig } from "./SettingsConfig";
import { ZoweExplorerExtender } from "../extending/ZoweExplorerExtender";
import { FilterDescriptor } from "../management/FilterManagement";

P.S. Currently we have to store your project as a subtree, making it not very simple to merge every time we want to sync up, and keeping our update cadence low.

Thanks, Sergei.

github-actions[bot] commented 1 month ago

Thank you for raising this enhancement request. The community has 90 days to vote on it. If the enhancement receives at least 10 upvotes, it is added to our development backlog. If it receives fewer votes, the issue is closed.

sosadchuk commented 1 month ago

Alternatively, we could also benefit from having a registered command for the Edit Team Config File option, same as you have for the init (zowe.all.config.init).

sosadchuk commented 1 month ago

Found similar request #3088 (didn't pop up when I created this one).