diff --git a/examples/ui-prompting-examples/CHANGELOG.md b/examples/ui-prompting-examples/CHANGELOG.md index 07e97fe556..e73e117879 100644 --- a/examples/ui-prompting-examples/CHANGELOG.md +++ b/examples/ui-prompting-examples/CHANGELOG.md @@ -1,5 +1,29 @@ # @sap-ux-private/ui-prompting-examples +## 0.2.6 + +### Patch Changes + +- Updated dependencies [4c6f92c] + - @sap-ux/ui-components@1.18.9 + - @sap-ux/ui-prompting@0.2.6 + +## 0.2.5 + +### Patch Changes + +- Updated dependencies [b669796] + - @sap-ux/ui-components@1.18.8 + - @sap-ux/ui-prompting@0.2.5 + +## 0.2.4 + +### Patch Changes + +- Updated dependencies [e65bb7f] + - @sap-ux/ui-components@1.18.7 + - @sap-ux/ui-prompting@0.2.4 + ## 0.2.3 ### Patch Changes diff --git a/examples/ui-prompting-examples/package.json b/examples/ui-prompting-examples/package.json index ce57e71f64..0a9e2755f3 100644 --- a/examples/ui-prompting-examples/package.json +++ b/examples/ui-prompting-examples/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux-private/ui-prompting-examples", - "version": "0.2.3", + "version": "0.2.6", "description": "This project contains UI storybook stories with exampleS with prompt ui and FPM based building blocks.", "license": "Apache-2.0", "private": true, diff --git a/packages/abap-deploy-config-inquirer/CHANGELOG.md b/packages/abap-deploy-config-inquirer/CHANGELOG.md index 49102edad5..701bfb604e 100644 --- a/packages/abap-deploy-config-inquirer/CHANGELOG.md +++ b/packages/abap-deploy-config-inquirer/CHANGELOG.md @@ -1,5 +1,17 @@ # @sap-ux/abap-deploy-config-inquirer +## 1.0.1 + +### Patch Changes + +- 43988ca: bug fix + +## 1.0.0 + +### Major Changes + +- b3b1082: update prompt options for abap deploy config inquirer + ## 0.0.25 ### Patch Changes diff --git a/packages/abap-deploy-config-inquirer/package.json b/packages/abap-deploy-config-inquirer/package.json index e4e86eb6e8..128d1089fe 100644 --- a/packages/abap-deploy-config-inquirer/package.json +++ b/packages/abap-deploy-config-inquirer/package.json @@ -6,7 +6,7 @@ "url": "https://github.com/SAP/open-ux-tools.git", "directory": "packages/abap-deploy-config-inquirer" }, - "version": "0.0.25", + "version": "1.0.1", "license": "Apache-2.0", "main": "dist/index.js", "scripts": { diff --git a/packages/abap-deploy-config-inquirer/src/prompts/conditions.ts b/packages/abap-deploy-config-inquirer/src/prompts/conditions.ts index e1688d8ad6..acfa407989 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/conditions.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/conditions.ts @@ -143,13 +143,9 @@ export function showPasswordQuestion(): boolean { /** * Determines if the UI5 app deploy config question should be shown (UI5 Abap Repo name & Description). * - * @param hideUi5AbapRepoPrompt - option to hide the prompt if using a btp system * @returns boolean */ -export function showUi5AppDeployConfigQuestion(hideUi5AbapRepoPrompt?: boolean): boolean { - if (hideUi5AbapRepoPrompt) { - return false; - } +export function showUi5AppDeployConfigQuestion(): boolean { return !PromptState.transportAnswers.transportConfigNeedsCreds; } @@ -301,18 +297,6 @@ export function defaultOrShowManualTransportQuestion(transportInputChoice?: stri * @returns boolean */ export function showIndexQuestion(options: AbapDeployConfigPromptOptions): boolean { - const condition = Boolean(options.indexGenerationAllowed && !PromptState.abapDeployConfig.index); + const condition = Boolean(options.index?.indexGenerationAllowed && !PromptState.abapDeployConfig.index); return condition && !PromptState.transportAnswers.transportConfigError && options.backendTarget?.type !== 'library'; } - -/** - * Determines if the overwrite prompt should be shown. - * - * @param options - abap deploy config prompt options - * @returns boolean - */ -export function showOverwriteQuestion(options: AbapDeployConfigPromptOptions): boolean { - return Boolean( - options.showOverwriteQuestion && !!options.existingDeployTaskConfig && !PromptState.abapDeployConfig.overwrite - ); -} diff --git a/packages/abap-deploy-config-inquirer/src/prompts/helpers.ts b/packages/abap-deploy-config-inquirer/src/prompts/helpers.ts index 51c1b5a1c3..90fcd93035 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/helpers.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/helpers.ts @@ -93,8 +93,10 @@ async function getBackendTargetChoices( const systemChoices: AbapSystemChoice[] = Object.values(backendSystems) .sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, caseFirst: 'lower' })) .map((system) => { - if (!targetExists) { - targetExists = system.url === target?.url && (system.client ?? '') === (target?.client ?? ''); + if (!targetExists && target?.url) { + targetExists = + system.url.replace(/\/$/, '') === target.url.replace(/\/$/, '') && + (system.client ?? '') === (target?.client ?? ''); } return { name: targetExists diff --git a/packages/abap-deploy-config-inquirer/src/prompts/index.ts b/packages/abap-deploy-config-inquirer/src/prompts/index.ts index 60ff711c3c..77a8d3c370 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/index.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/index.ts @@ -21,19 +21,17 @@ export async function getAbapDeployConfigQuestions( const targetPrompts = await getAbapTargetPrompts(options); const authPrompts = getAuthPrompts(options); - const appConfigPrompts = getAppConfigPrompts(options); + const questions = [...targetPrompts, ...authPrompts]; + + if (options.ui5AbapRepo?.hide !== true) { + questions.push(...getAppConfigPrompts(options)); + } + const packagePrompts = getPackagePrompts(options); const transportRequestPrompts = getTransportRequestPrompts(options); const confirmPrompts = getConfirmPrompts(options); - const questions = [ - ...targetPrompts, - ...authPrompts, - ...appConfigPrompts, - ...packagePrompts, - ...transportRequestPrompts, - ...confirmPrompts - ]; + questions.push(...packagePrompts, ...transportRequestPrompts, ...confirmPrompts); return questions as AbapDeployConfigQuestion[]; } diff --git a/packages/abap-deploy-config-inquirer/src/prompts/questions/abap-target.ts b/packages/abap-deploy-config-inquirer/src/prompts/questions/abap-target.ts index 63150ea460..b3ebb04105 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/questions/abap-target.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/questions/abap-target.ts @@ -16,7 +16,7 @@ import { PromptState } from '../prompt-state'; import { Severity, type IMessageSeverity } from '@sap-devx/yeoman-ui-types'; import { isAppStudio, isOnPremiseDestination, type Destinations } from '@sap-ux/btp-utils'; import { - abapDeployConfigInternalPromptNames, + promptNames, ClientChoiceValue, type AbapDeployConfigAnswersInternal, type AbapDeployConfigPromptOptions, @@ -44,7 +44,7 @@ function getDestinationPrompt( { when: (): boolean => isAppStudio(), type: 'list', - name: abapDeployConfigInternalPromptNames.destination, + name: promptNames.destination, message: t('prompts.target.destination.message'), guiOptions: { mandatory: true, @@ -70,13 +70,13 @@ function getDestinationPrompt( if (isAppStudio() && !PromptState.isYUI) { prompts.push({ when: (answers: AbapDeployConfigAnswersInternal): boolean => { - const destination = answers[abapDeployConfigInternalPromptNames.destination]; + const destination = answers[promptNames.destination]; if (destination) { updateDestinationPromptState(destination, destinations); } return false; }, - name: abapDeployConfigInternalPromptNames.destinationCliSetter + name: promptNames.destinationCliSetter } as Question); } return prompts; @@ -95,7 +95,7 @@ function getTargetSystemPrompt( { when: (): boolean => !isAppStudio(), type: 'list', - name: abapDeployConfigInternalPromptNames.targetSystem, + name: promptNames.targetSystem, message: t('prompts.target.targetSystem.message'), guiOptions: { mandatory: true, @@ -110,13 +110,13 @@ function getTargetSystemPrompt( if (!isAppStudio() && !PromptState.isYUI) { prompts.push({ when: (answers: AbapDeployConfigAnswersInternal): boolean => { - const target = answers[abapDeployConfigInternalPromptNames.targetSystem]; + const target = answers[promptNames.targetSystem]; if (target) { validateTargetSystemUrlCli(target, choices); } return false; }, - name: abapDeployConfigInternalPromptNames.targetSystemCliSetter + name: promptNames.targetSystemCliSetter } as Question); } return prompts; @@ -140,7 +140,7 @@ function getUrlPrompt( return isValid; }, type: 'input', - name: abapDeployConfigInternalPromptNames.url, + name: promptNames.url, message: t('prompts.target.url.message'), guiOptions: { mandatory: true, @@ -163,7 +163,7 @@ function getScpPrompt(backendTarget?: BackendTarget): Question showScpQuestion(previousAnswers), type: 'confirm', - name: abapDeployConfigInternalPromptNames.scp, + name: promptNames.scp, message: t('prompts.target.scp.message'), guiOptions: { breadcrumb: t('prompts.target.scp.breadcrumb') @@ -174,15 +174,14 @@ function getScpPrompt(backendTarget?: BackendTarget): Question { - const scpChoice = answers[abapDeployConfigInternalPromptNames.scp]; - const targetChoice = answers[abapDeployConfigInternalPromptNames.targetSystem]; + const scpChoice = answers[promptNames.scp]; + const targetChoice = answers[promptNames.targetSystem]; // scpChoice by default is true so only update state if target system is a URL PromptState.abapDeployConfig.scp = !!(targetChoice === TargetSystemType.Url && scpChoice); return false; }, - name: abapDeployConfigInternalPromptNames.scpSetter + name: promptNames.scpSetter } as Question); - return prompts; } @@ -200,7 +199,7 @@ function getClientChoicePrompt( when: (previousAnswers: AbapDeployConfigAnswersInternal): boolean => showClientChoiceQuestion(previousAnswers, backendTarget?.abapTarget?.client), type: 'list', - name: abapDeployConfigInternalPromptNames.clientChoice, + name: promptNames.clientChoice, message: t('prompts.target.clientChoice.message'), guiOptions: { applyDefaultWhenDirty: true @@ -216,13 +215,13 @@ function getClientChoicePrompt( if (!PromptState.isYUI) { prompts.push({ when: (answers: AbapDeployConfigAnswersInternal): boolean => { - const clientChoice = answers[abapDeployConfigInternalPromptNames.clientChoice]; + const clientChoice = answers[promptNames.clientChoice]; if (clientChoice) { validateClientChoiceQuestion(clientChoice as ClientChoiceValue, backendTarget?.abapTarget?.client); } return false; }, - name: abapDeployConfigInternalPromptNames.clientChoiceCliSetter + name: promptNames.clientChoiceCliSetter } as Question); } return prompts; @@ -239,7 +238,7 @@ function getClientPrompt(): Question { return showClientQuestion(previousAnswers); }, type: 'input', - name: abapDeployConfigInternalPromptNames.client, + name: promptNames.client, message: t('prompts.target.client.message'), guiOptions: { breadcrumb: t('prompts.target.client.breadcrumb') diff --git a/packages/abap-deploy-config-inquirer/src/prompts/questions/auth.ts b/packages/abap-deploy-config-inquirer/src/prompts/questions/auth.ts index 6af0fbac24..f2f6ec7461 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/questions/auth.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/questions/auth.ts @@ -1,11 +1,7 @@ import { t } from '../../i18n'; import { showPasswordQuestion, showUsernameQuestion } from '../conditions'; import { validateCredentials } from '../validators'; -import { - abapDeployConfigInternalPromptNames, - type AbapDeployConfigAnswersInternal, - type AbapDeployConfigPromptOptions -} from '../../types'; +import { promptNames, type AbapDeployConfigAnswersInternal, type AbapDeployConfigPromptOptions } from '../../types'; import type { InputQuestion, PasswordQuestion, Question } from 'inquirer'; /** @@ -18,7 +14,7 @@ function getUsernamePrompt(options: AbapDeployConfigPromptOptions): Question => showUsernameQuestion(options.backendTarget), type: 'input', - name: abapDeployConfigInternalPromptNames.username, + name: promptNames.username, message: t('prompts.auth.username.message'), guiOptions: { mandatory: true @@ -36,7 +32,7 @@ function getPasswordPrompt(options: AbapDeployConfigPromptOptions): Question showPasswordQuestion(), type: 'password', - name: abapDeployConfigInternalPromptNames.password, + name: promptNames.password, message: t('prompts.auth.password.message'), mask: '*', guiOptions: { diff --git a/packages/abap-deploy-config-inquirer/src/prompts/questions/config/app.ts b/packages/abap-deploy-config-inquirer/src/prompts/questions/config/app.ts index 9030d37963..10d6843832 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/questions/config/app.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/questions/config/app.ts @@ -2,11 +2,7 @@ import { showUi5AppDeployConfigQuestion } from '../../conditions'; import { validateAppDescription, validateUi5AbapRepoName } from '../../validators'; import { PromptState } from '../../prompt-state'; import { t } from '../../../i18n'; -import { - abapDeployConfigInternalPromptNames, - type AbapDeployConfigAnswersInternal, - type AbapDeployConfigPromptOptions -} from '../../../types'; +import { promptNames, type AbapDeployConfigAnswersInternal, type AbapDeployConfigPromptOptions } from '../../../types'; import type { InputQuestion, Question } from 'inquirer'; /** @@ -17,9 +13,9 @@ import type { InputQuestion, Question } from 'inquirer'; */ function getUi5AbapRepoPrompt(options: AbapDeployConfigPromptOptions): Question { return { - when: (): boolean => showUi5AppDeployConfigQuestion(options.hideUi5AbapRepoPrompt), + when: (): boolean => showUi5AppDeployConfigQuestion(), type: 'input', - name: abapDeployConfigInternalPromptNames.ui5AbapRepo, + name: promptNames.ui5AbapRepo, message: (): string => { return PromptState.transportAnswers.transportConfig?.getApplicationPrefix() ? t('prompts.config.app.ui5AbapRepo.messageMaxLength', { @@ -33,7 +29,7 @@ function getUi5AbapRepoPrompt(options: AbapDeployConfigPromptOptions): Question< breadcrumb: t('prompts.config.app.ui5AbapRepo.message') }, default: (previousAnswers: AbapDeployConfigAnswersInternal) => - previousAnswers.ui5AbapRepo || options.existingDeployTaskConfig?.name, + previousAnswers.ui5AbapRepo || options.ui5AbapRepo?.default, validate: (input: string): string | boolean => validateUi5AbapRepoName(input), filter: (input: string): string | undefined => !PromptState.isYUI ? input?.trim()?.toUpperCase() : input?.trim() @@ -48,16 +44,16 @@ function getUi5AbapRepoPrompt(options: AbapDeployConfigPromptOptions): Question< */ function getDescriptionPrompt(options: AbapDeployConfigPromptOptions): Question { return { - when: (): boolean => showUi5AppDeployConfigQuestion(options.hideUi5AbapRepoPrompt), + when: (): boolean => showUi5AppDeployConfigQuestion(), type: 'input', - name: abapDeployConfigInternalPromptNames.description, + name: promptNames.description, message: t('prompts.config.app.description.message'), guiOptions: { hint: t('prompts.config.app.description.hint'), breadcrumb: true }, default: (previousAnswers: AbapDeployConfigAnswersInternal): string | undefined => - previousAnswers.description || options.existingDeployTaskConfig?.description, + previousAnswers.description || options.description?.default, filter: (input: string): string | undefined => input?.trim(), validate: (input: string): boolean | string => validateAppDescription(input) } as InputQuestion; diff --git a/packages/abap-deploy-config-inquirer/src/prompts/questions/config/package.ts b/packages/abap-deploy-config-inquirer/src/prompts/questions/config/package.ts index 13972f7dc5..8e75fdb6f6 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/questions/config/package.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/questions/config/package.ts @@ -9,7 +9,7 @@ import { getPackageChoices, getPackageInputChoices } from '../../helpers'; import { defaultPackage, defaultPackageChoice } from '../../defaults'; import { validatePackage, validatePackageChoiceInput, validatePackageChoiceInputForCli } from '../../validators'; import { - abapDeployConfigInternalPromptNames, + promptNames, type PackageInputChoices, type AbapDeployConfigAnswersInternal, type AbapDeployConfigPromptOptions @@ -30,9 +30,9 @@ export function getPackagePrompts(options: AbapDeployConfigPromptOptions): Quest const questions: Question[] = [ { - when: (): boolean => showPackageInputChoiceQuestion(options.useAutocomplete), + when: (): boolean => showPackageInputChoiceQuestion(options?.packageAutocomplete?.useAutocomplete), type: 'list', - name: abapDeployConfigInternalPromptNames.packageInputChoice, + name: promptNames.packageInputChoice, message: t('prompts.config.package.packageInputChoice.message'), guiOptions: { applyDefaultWhenDirty: true @@ -70,13 +70,16 @@ export function getPackagePrompts(options: AbapDeployConfigPromptOptions): Quest return false; }, type: 'input', - name: abapDeployConfigInternalPromptNames.packageCliExecution + name: promptNames.packageCliExecution } as InputQuestion, { when: (previousAnswers: AbapDeployConfigAnswersInternal): boolean => - defaultOrShowManualPackageQuestion(previousAnswers.packageInputChoice, options.useAutocomplete), + defaultOrShowManualPackageQuestion( + previousAnswers.packageInputChoice, + options?.packageAutocomplete?.useAutocomplete + ), type: 'input', - name: abapDeployConfigInternalPromptNames.packageManual, + name: promptNames.packageManual, message: t('prompts.config.package.packageManual.message'), guiOptions: { hint: t('prompts.config.package.packageManual.hint'), @@ -84,16 +87,19 @@ export function getPackagePrompts(options: AbapDeployConfigPromptOptions): Quest breadcrumb: true }, default: (previousAnswers: AbapDeployConfigAnswersInternal): string => - defaultPackage(previousAnswers.packageManual || options.existingDeployTaskConfig?.package), + defaultPackage(previousAnswers.packageManual || options.packageManual?.default), validate: async (input: string, answers: AbapDeployConfigAnswersInternal): Promise => await validatePackage(input, answers, options.backendTarget) } as InputQuestion, { when: (previousAnswers: AbapDeployConfigAnswersInternal): boolean => packageInputChoiceValid === true && - defaultOrShowSearchPackageQuestion(previousAnswers.packageInputChoice, options.useAutocomplete), + defaultOrShowSearchPackageQuestion( + previousAnswers.packageInputChoice, + options?.packageAutocomplete?.useAutocomplete + ), type: 'autocomplete', - name: abapDeployConfigInternalPromptNames.packageAutocomplete, + name: promptNames.packageAutocomplete, message: `${t('prompts.config.package.packageAutocomplete.message')}${ isCli ? t('prompts.config.package.packageAutocomplete.messageTypeFilter') : '' }`, diff --git a/packages/abap-deploy-config-inquirer/src/prompts/questions/config/transport.ts b/packages/abap-deploy-config-inquirer/src/prompts/questions/config/transport.ts index eca3d61f43..ba519fc16d 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/questions/config/transport.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/questions/config/transport.ts @@ -12,7 +12,7 @@ import { PromptState } from '../../prompt-state'; import { transportName } from '../../../service-provider-utils/transport-list'; import { defaultTransportListChoice, defaultTransportRequestChoice } from '../../defaults'; import { - abapDeployConfigInternalPromptNames, + promptNames, type AbapDeployConfigAnswersInternal, type AbapDeployConfigPromptOptions, type TransportChoices @@ -35,7 +35,7 @@ export function getTransportRequestPrompts( { when: (): boolean => showTransportInputChoice(), type: 'list', - name: abapDeployConfigInternalPromptNames.transportInputChoice, + name: promptNames.transportInputChoice, message: t('prompts.config.transport.transportInputChoice.message'), guiOptions: { applyDefaultWhenDirty: true @@ -44,7 +44,7 @@ export function getTransportRequestPrompts( default: (previousAnswers: AbapDeployConfigAnswersInternal): string => defaultTransportRequestChoice( previousAnswers.transportInputChoice, - useCreateTrDuringDeploy(options.existingDeployTaskConfig) + useCreateTrDuringDeploy(options.transportManual?.default) ), validate: async ( input: TransportChoices, @@ -74,12 +74,12 @@ export function getTransportRequestPrompts( return false; }, type: 'input', - name: abapDeployConfigInternalPromptNames.transportCliExecution + name: promptNames.transportCliExecution }, { when: (previousAnswers: AbapDeployConfigAnswersInternal): boolean => defaultOrShowTransportCreatedQuestion(previousAnswers.transportInputChoice), - name: abapDeployConfigInternalPromptNames.transportCreated, + name: promptNames.transportCreated, type: 'input', default: () => PromptState.transportAnswers.newTransportNumber, message: t('prompts.config.transport.transportCreated.message') @@ -88,7 +88,7 @@ export function getTransportRequestPrompts( when: (previousAnswers: AbapDeployConfigAnswersInternal): boolean => defaultOrShowTransportListQuestion(previousAnswers.transportInputChoice), type: 'list', - name: abapDeployConfigInternalPromptNames.transportFromList, + name: promptNames.transportFromList, message: t('prompts.config.transport.common.transportRequest'), guiOptions: { hint: t('prompts.config.transport.common.provideTransportRequest'), @@ -101,7 +101,7 @@ export function getTransportRequestPrompts( when: (previousAnswers: AbapDeployConfigAnswersInternal): boolean => defaultOrShowManualTransportQuestion(previousAnswers.transportInputChoice), type: 'input', - name: abapDeployConfigInternalPromptNames.transportManual, + name: promptNames.transportManual, message: () => PromptState.transportAnswers.transportRequired ? t('prompts.config.transport.common.transportRequestMandatory') @@ -111,7 +111,7 @@ export function getTransportRequestPrompts( breadcrumb: t('prompts.config.transport.common.transportRequest') }, default: (previousAnswers: AbapDeployConfigAnswersInternal) => - previousAnswers.transportManual || options.existingDeployTaskConfig?.transport, + previousAnswers.transportManual || options.transportManual?.default, validate: (input: string): boolean | string => validateTransportQuestion(input), filter: (input: string): string => input?.trim()?.toUpperCase() } as InputQuestion diff --git a/packages/abap-deploy-config-inquirer/src/prompts/questions/confirm.ts b/packages/abap-deploy-config-inquirer/src/prompts/questions/confirm.ts index 7d33f26fbe..a1a6d6b0a1 100644 --- a/packages/abap-deploy-config-inquirer/src/prompts/questions/confirm.ts +++ b/packages/abap-deploy-config-inquirer/src/prompts/questions/confirm.ts @@ -1,11 +1,7 @@ -import { showIndexQuestion, showOverwriteQuestion } from '../conditions'; +import { showIndexQuestion } from '../conditions'; import { validateConfirmQuestion } from '../validators'; import { t } from '../../i18n'; -import { - abapDeployConfigInternalPromptNames, - type AbapDeployConfigPromptOptions, - type AbapDeployConfigAnswersInternal -} from '../../types'; +import { promptNames, type AbapDeployConfigPromptOptions, type AbapDeployConfigAnswersInternal } from '../../types'; import type { ConfirmQuestion, Question } from 'inquirer'; /** @@ -17,7 +13,7 @@ import type { ConfirmQuestion, Question } from 'inquirer'; function getIndexPrompt(options: AbapDeployConfigPromptOptions): Question { return { when: (): boolean => showIndexQuestion(options), - name: abapDeployConfigInternalPromptNames.index, + name: promptNames.index, type: 'confirm', message: t('prompts.confirm.index.message'), guiOptions: { @@ -30,14 +26,11 @@ function getIndexPrompt(options: AbapDeployConfigPromptOptions): Question { +function getOverwritePrompt(): Question { return { - when: (): boolean => showOverwriteQuestion(options), - - name: abapDeployConfigInternalPromptNames.overwrite, + name: promptNames.overwrite, type: 'confirm', message: t('prompts.confirm.overwrite.message'), guiOptions: { @@ -55,5 +48,9 @@ function getOverwritePrompt(options: AbapDeployConfigPromptOptions): Question[] { - return [getIndexPrompt(options), getOverwritePrompt(options)]; + const questions = [getIndexPrompt(options)]; + if (options.overwrite?.hide !== true) { + questions.push(getOverwritePrompt()); + } + return questions; } diff --git a/packages/abap-deploy-config-inquirer/src/types.ts b/packages/abap-deploy-config-inquirer/src/types.ts index 6e4a318a29..91bedb525c 100644 --- a/packages/abap-deploy-config-inquirer/src/types.ts +++ b/packages/abap-deploy-config-inquirer/src/types.ts @@ -17,40 +17,28 @@ export interface Credentials { password?: string; } +/** + * The target system used during generation. + */ export interface BackendTarget { - systemName?: string; // name given for backend system + /** + * The name of the backend system. + */ + systemName?: string; + /** + * ABAP Target - can be either a URL Abap Target or a destination. + */ abapTarget: AbapTarget; + /** + * The connected service provider for the backend system. Passing this removes the need for re-authentication. + */ serviceProvider?: ServiceProvider; + /** + * The type of project that the deployment configuration is for. + */ type?: 'application' | 'library'; } -export interface DeployTaskConfig { - name?: string; - description?: string; - package?: string; - transport?: string; - [key: string]: unknown; -} - -/** - * AbapDeployConfigPromptOptions - * - * @param backendTarget - the backend target which may have been used to generate the application (useful for default values) - * @param existingDeployTaskConfig - the existing deploy task configuration, will be used to prefill certain prompt answers - * @param hideUi5AbapRepoPrompt - whether to hide the UI5 ABAP repository prompt - * @param showOverwriteQuestion - whether to show the overwrite question (this can be determined by the caller) - * @param indexGenerationAllowed - whether generating an index.html is allowed - * @param useAutocomplete - determines if the prompt(s) (currently only package prompt) should use auto completion - */ -export interface AbapDeployConfigPromptOptions { - backendTarget?: BackendTarget; - existingDeployTaskConfig?: DeployTaskConfig; - hideUi5AbapRepoPrompt?: boolean; - showOverwriteQuestion?: boolean; - indexGenerationAllowed?: boolean; - useAutocomplete?: boolean; -} - export interface AbapSystemChoice { name: string; value: string; @@ -62,9 +50,9 @@ export interface AbapSystemChoice { } /** - * Enumeration of internal prompt names used internally and not supported for modification using .... + * Enumeration of prompt names used by */ -export enum abapDeployConfigInternalPromptNames { +export enum promptNames { destination = 'destination', destinationCliSetter = 'destinationCliSetter', targetSystem = 'targetSystem', @@ -92,6 +80,85 @@ export enum abapDeployConfigInternalPromptNames { overwrite = 'overwrite' } +/** + * Options for the UI5 ABAP repository prompt. + * If `hide` is set to `true`, the prompt will not be shown, it is required to add a default value in this case. + */ +export type UI5AbapRepoPromptOptions = + | { + hide?: false; + default?: string; + } + | { + hide: true; + default: string; + }; + +export type DescriptionPromptOptions = { + /** + * Default description value. + */ + default?: string; +}; + +export type PackageManualPromptOptions = { + /** + * Default package value. + */ + default?: string; +}; + +export type TransportManualPromptOptions = { + /** + * Default transport value. + */ + default?: string; +}; + +export type OverwritePromptOptions = { + /** + * This option allows the prompt to be hidden and should be used when the overwrite prompt should not be shown. + * It should be set to false when existing configuration will be overwritten. + */ + hide?: boolean; +}; + +export type IndexPromptOptions = { + /** + * This option indicates if an generating an index.html is allowed. + */ + indexGenerationAllowed?: boolean; +}; + +export type PackageAutocompletePromptOptions = { + /** + * Determines if the package autocomplete prompt should use auto complete prompt for packages. + * Note that the auto-complete module must be registered with the inquirer instance to use this feature. + */ + useAutocomplete?: boolean; +}; + +type abapDeployConfigPromptOptions = Record & + Record & + Record & + Record & + Record & + Record & + Record; + +/** + * The options which are common for the abap deploy config inquirer. + */ +type AbapDeployConfigCommonInquirerOptions = { + backendTarget?: BackendTarget; +}; + +/** + * The options for the abap deploy config inquirer & the prompts. + */ +export type AbapDeployConfigPromptOptions = Partial & + AbapDeployConfigCommonInquirerOptions; + export interface TransportAnswers { transportRequired?: boolean; transportConfig?: TransportConfig; diff --git a/packages/abap-deploy-config-inquirer/src/utils.ts b/packages/abap-deploy-config-inquirer/src/utils.ts index c813d6bcdf..d4822b9388 100644 --- a/packages/abap-deploy-config-inquirer/src/utils.ts +++ b/packages/abap-deploy-config-inquirer/src/utils.ts @@ -10,7 +10,6 @@ import type { AbapDeployConfigAnswersInternal, BackendTarget, Credentials, - DeployTaskConfig, InitTransportConfigResult, SystemConfig } from './types'; @@ -197,14 +196,13 @@ function getTransportAnswer(previousAnswers?: AbapDeployConfigAnswersInternal): } /** - * If a deploy config already exists in the project, check if the config - * uses option to create transport request number during actual deploy process. + * Check if the transport matches placeholder used to create transport request number during actual deploy process. * - * @param existingDeployTaskConfig - existing deploy task config + * @param transport - existing transport * @returns true if transport setting is set to 'CreateDuringDeployChoice'. */ -export function useCreateTrDuringDeploy(existingDeployTaskConfig?: DeployTaskConfig): boolean { - return existingDeployTaskConfig?.transport === CREATE_TR_DURING_DEPLOY; +export function useCreateTrDuringDeploy(transport?: string): boolean { + return transport === CREATE_TR_DURING_DEPLOY; } /** diff --git a/packages/abap-deploy-config-inquirer/test/prompts/conditions.test.ts b/packages/abap-deploy-config-inquirer/test/prompts/conditions.test.ts index 1b43654157..c193b7c164 100644 --- a/packages/abap-deploy-config-inquirer/test/prompts/conditions.test.ts +++ b/packages/abap-deploy-config-inquirer/test/prompts/conditions.test.ts @@ -15,7 +15,6 @@ import { showClientChoiceQuestion, showClientQuestion, showIndexQuestion, - showOverwriteQuestion, showPackageInputChoiceQuestion, showPasswordQuestion, showScpQuestion, @@ -191,12 +190,7 @@ describe('Test abap deploy config inquirer conditions', () => { test('should show ui5 app deploy config questions', () => { PromptState.transportAnswers.transportConfigNeedsCreds = false; - expect(showUi5AppDeployConfigQuestion(undefined)).toBe(true); - }); - - test('should not show ui5 app deploy config questions', () => { - PromptState.abapDeployConfig.scp = true; - expect(showUi5AppDeployConfigQuestion(true)).toBe(false); + expect(showUi5AppDeployConfigQuestion()).toBe(true); }); test('should show package input choice question', () => { @@ -291,17 +285,7 @@ describe('Test abap deploy config inquirer conditions', () => { PromptState.abapDeployConfig.index = undefined; expect( showIndexQuestion({ - indexGenerationAllowed: true - }) - ).toBe(true); - }); - - test('should show overwrite question', () => { - PromptState.abapDeployConfig.overwrite = undefined; - expect( - showOverwriteQuestion({ - showOverwriteQuestion: true, - existingDeployTaskConfig: {} + index: { indexGenerationAllowed: true } }) ).toBe(true); }); diff --git a/packages/abap-deploy-config-inquirer/test/prompts/helpers.test.ts b/packages/abap-deploy-config-inquirer/test/prompts/helpers.test.ts index 6a2f84e070..b60d27a530 100644 --- a/packages/abap-deploy-config-inquirer/test/prompts/helpers.test.ts +++ b/packages/abap-deploy-config-inquirer/test/prompts/helpers.test.ts @@ -65,6 +65,34 @@ describe('helpers', () => { ] `); }); + + it('should return backend target choices (no backend target / default)', async () => { + const systemChoices = await getAbapSystemChoices(undefined, undefined, mockTargetSystems); + expect(systemChoices).toMatchInlineSnapshot(` + Array [ + Object { + "name": "Enter Target System URL", + "value": "Url", + }, + Object { + "client": "000", + "isDefault": false, + "isS4HC": false, + "name": "target1 [mockUser]", + "scp": false, + "value": "https://mock.url.target1.com", + }, + Object { + "client": "001", + "isDefault": false, + "isS4HC": true, + "name": "target2 (S4HC) [mockUser2]", + "scp": false, + "value": "https://mock.url.target2.com", + }, + ] + `); + }); }); describe('updatePromptStateUrl', () => { diff --git a/packages/abap-deploy-config-inquirer/test/prompts/questions/abap-target.test.ts b/packages/abap-deploy-config-inquirer/test/prompts/questions/abap-target.test.ts index 9ca84740c9..25d3540ea2 100644 --- a/packages/abap-deploy-config-inquirer/test/prompts/questions/abap-target.test.ts +++ b/packages/abap-deploy-config-inquirer/test/prompts/questions/abap-target.test.ts @@ -1,10 +1,5 @@ import { isAppStudio, isOnPremiseDestination } from '@sap-ux/btp-utils'; -import { - abapDeployConfigInternalPromptNames, - AbapDeployConfigPromptOptions, - ClientChoiceValue, - TargetSystemType -} from '../../../src/types'; +import { promptNames, AbapDeployConfigPromptOptions, ClientChoiceValue, TargetSystemType } from '../../../src/types'; import { getAbapTargetPrompts } from '../../../src/prompts/questions'; import { getAbapSystems } from '../../../src/utils'; import { mockDestinations } from '../../fixtures/destinations'; @@ -147,9 +142,7 @@ describe('getAbapTargetPrompts', () => { } as AbapDeployConfigPromptOptions; const abapTargetPrompts = await getAbapTargetPrompts(abapDeployConfigPromptOptions); - const destPrompt = abapTargetPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.destination - ); + const destPrompt = abapTargetPrompts.find((prompt) => prompt.name === promptNames.destination); if (destPrompt) { expect((destPrompt.when as Function)()).toBe(true); @@ -192,7 +185,7 @@ describe('getAbapTargetPrompts', () => { const updateDestinationPromptStateSpy = jest.spyOn(validators, 'updateDestinationPromptState'); const abapTargetPrompts = await getAbapTargetPrompts({}); const destinationCliSetterPrompt = abapTargetPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.destinationCliSetter + (prompt) => prompt.name === promptNames.destinationCliSetter ); if (destinationCliSetterPrompt) { @@ -216,9 +209,7 @@ describe('getAbapTargetPrompts', () => { jest.spyOn(validators, 'validateTargetSystem').mockReturnValueOnce(true); const abapTargetPrompts = await getAbapTargetPrompts({}); - const targetSystemPrompt = abapTargetPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.targetSystem - ); + const targetSystemPrompt = abapTargetPrompts.find((prompt) => prompt.name === promptNames.targetSystem); if (targetSystemPrompt) { expect((targetSystemPrompt.when as Function)()).toBe(true); @@ -264,7 +255,7 @@ describe('getAbapTargetPrompts', () => { const validateTargetSystemUrlCliSpy = jest.spyOn(validators, 'validateTargetSystemUrlCli'); const abapTargetPrompts = await getAbapTargetPrompts({}); const targetSystemCliSetterPrompt = abapTargetPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.targetSystemCliSetter + (prompt) => prompt.name === promptNames.targetSystemCliSetter ); if (targetSystemCliSetterPrompt) { @@ -288,7 +279,7 @@ describe('getAbapTargetPrompts', () => { jest.spyOn(validators, 'validateTargetSystemUrlCli').mockReturnValueOnce(); jest.spyOn(validators, 'validateUrl').mockReturnValueOnce(true); const abapTargetPrompts = await getAbapTargetPrompts({}); - const urlPrompt = abapTargetPrompts.find((prompt) => prompt.name === abapDeployConfigInternalPromptNames.url); + const urlPrompt = abapTargetPrompts.find((prompt) => prompt.name === promptNames.url); if (urlPrompt) { expect((urlPrompt.when as Function)({ targetSystem: TargetSystemType.Url })).toBe(true); @@ -310,11 +301,8 @@ describe('getAbapTargetPrompts', () => { const abapTargetPrompts = await getAbapTargetPrompts({ backendTarget: { abapTarget: { scp: true } as UrlAbapTarget } }); - const scpPrompt = abapTargetPrompts.find((prompt) => prompt.name === abapDeployConfigInternalPromptNames.scp); - const scpSetterPrompt = abapTargetPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.scpSetter - ); - + const scpPrompt = abapTargetPrompts.find((prompt) => prompt.name === promptNames.scp); + const scpSetterPrompt = abapTargetPrompts.find((prompt) => prompt.name === promptNames.scpSetter); if (scpPrompt) { expect( (scpPrompt.when as Function)({ @@ -370,9 +358,7 @@ describe('getAbapTargetPrompts', () => { jest.spyOn(conditions, 'showClientChoiceQuestion').mockReturnValueOnce(true); jest.spyOn(validators, 'validateClientChoiceQuestion').mockReturnValueOnce(true); const abapTargetPrompts = await getAbapTargetPrompts({}); - const clientChoicePrompt = abapTargetPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.clientChoice - ); + const clientChoicePrompt = abapTargetPrompts.find((prompt) => prompt.name === promptNames.clientChoice); if (clientChoicePrompt) { expect((clientChoicePrompt.when as Function)()).toBe(true); @@ -410,9 +396,7 @@ describe('getAbapTargetPrompts', () => { const abapTargetPrompts = await getAbapTargetPrompts({ backendTarget: { abapTarget: { client: '100' } as UrlAbapTarget } }); - const clientPrompt = abapTargetPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.client - ); + const clientPrompt = abapTargetPrompts.find((prompt) => prompt.name === promptNames.client); if (clientPrompt) { PromptState.abapDeployConfig.client = '100'; diff --git a/packages/abap-deploy-config-inquirer/test/prompts/questions/auth.test.ts b/packages/abap-deploy-config-inquirer/test/prompts/questions/auth.test.ts index 039e318be0..716ff9179d 100644 --- a/packages/abap-deploy-config-inquirer/test/prompts/questions/auth.test.ts +++ b/packages/abap-deploy-config-inquirer/test/prompts/questions/auth.test.ts @@ -2,7 +2,7 @@ import * as conditions from '../../../src/prompts/conditions'; import * as validators from '../../../src/prompts/validators'; import { initI18n, t } from '../../../src/i18n'; import { getAuthPrompts } from '../../../src/prompts/questions'; -import { abapDeployConfigInternalPromptNames } from '../../../src/types'; +import { promptNames } from '../../../src/types'; describe('getAuthPrompts', () => { beforeAll(async () => { @@ -41,9 +41,7 @@ describe('getAuthPrompts', () => { jest.spyOn(conditions, 'showUsernameQuestion').mockResolvedValueOnce(true); const authPrompts = getAuthPrompts({}); - const usernamePrompt = authPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.username - ); + const usernamePrompt = authPrompts.find((prompt) => prompt.name === promptNames.username); if (usernamePrompt) { expect(await (usernamePrompt.when as Function)()).toBe(true); @@ -56,9 +54,7 @@ describe('getAuthPrompts', () => { jest.spyOn(validators, 'validateCredentials').mockResolvedValueOnce(true); const authPrompts = getAuthPrompts({}); - const passwordPrompt = authPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.password - ); + const passwordPrompt = authPrompts.find((prompt) => prompt.name === promptNames.password); if (passwordPrompt) { expect((passwordPrompt.when as Function)()).toBe(true); diff --git a/packages/abap-deploy-config-inquirer/test/prompts/questions/config/app.test.ts b/packages/abap-deploy-config-inquirer/test/prompts/questions/config/app.test.ts index af9beaf212..3974bdeb60 100644 --- a/packages/abap-deploy-config-inquirer/test/prompts/questions/config/app.test.ts +++ b/packages/abap-deploy-config-inquirer/test/prompts/questions/config/app.test.ts @@ -2,7 +2,7 @@ import { initI18n, t } from '../../../../src/i18n'; import { getAppConfigPrompts } from '../../../../src/prompts/questions'; import * as conditions from '../../../../src/prompts/conditions'; import * as validators from '../../../../src/prompts/validators'; -import { abapDeployConfigInternalPromptNames, TransportConfig } from '../../../../src/types'; +import { promptNames, TransportConfig } from '../../../../src/types'; import { PromptState } from '../../../../src/prompts/prompt-state'; describe('getConfirmPrompts', () => { @@ -54,9 +54,7 @@ describe('getConfirmPrompts', () => { } as unknown as TransportConfig }; const appConfigPrompts = getAppConfigPrompts({}); - const ui5AbapRepoPrompt = appConfigPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.ui5AbapRepo - ); + const ui5AbapRepoPrompt = appConfigPrompts.find((prompt) => prompt.name === promptNames.ui5AbapRepo); if (ui5AbapRepoPrompt) { expect((ui5AbapRepoPrompt.when as Function)()).toBe(true); @@ -81,12 +79,8 @@ describe('getConfirmPrompts', () => { jest.spyOn(conditions, 'showUi5AppDeployConfigQuestion').mockReturnValue(true); jest.spyOn(validators, 'validateAppDescription').mockReturnValue(true); - const appConfigPrompts = getAppConfigPrompts({ - existingDeployTaskConfig: { description: 'Mock description' } - }); - const descriptionPrompt = appConfigPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.description - ); + const appConfigPrompts = getAppConfigPrompts({ description: { default: 'Mock description' } }); + const descriptionPrompt = appConfigPrompts.find((prompt) => prompt.name === promptNames.description); if (descriptionPrompt) { expect((descriptionPrompt.when as Function)()).toBe(true); diff --git a/packages/abap-deploy-config-inquirer/test/prompts/questions/config/package.test.ts b/packages/abap-deploy-config-inquirer/test/prompts/questions/config/package.test.ts index 06bd6bad4a..3ed0e25054 100644 --- a/packages/abap-deploy-config-inquirer/test/prompts/questions/config/package.test.ts +++ b/packages/abap-deploy-config-inquirer/test/prompts/questions/config/package.test.ts @@ -3,7 +3,7 @@ import { getPackagePrompts } from '../../../../src/prompts/questions'; import * as helpers from '../../../../src/prompts/helpers'; import * as conditions from '../../../../src/prompts/conditions'; import * as validators from '../../../../src/prompts/validators'; -import { abapDeployConfigInternalPromptNames, PackageInputChoices } from '../../../../src/types'; +import { promptNames, PackageInputChoices } from '../../../../src/types'; import { ListQuestion } from '@sap-ux/inquirer-common'; import type { AutocompleteQuestionOptions } from 'inquirer-autocomplete-prompt'; import { PromptState } from '../../../../src/prompts/prompt-state'; @@ -69,7 +69,7 @@ describe('getPackagePrompts', () => { const packagePrompts = getPackagePrompts({}); const packageInputChoicePrompt = packagePrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.packageInputChoice + (prompt) => prompt.name === promptNames.packageInputChoice ); if (packageInputChoicePrompt) { @@ -104,7 +104,7 @@ describe('getPackagePrompts', () => { PromptState.isYUI = false; const packagePromptsCli = getPackagePrompts({}); const packageCliExecutionPromptCli = packagePromptsCli.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.packageCliExecution + (prompt) => prompt.name === promptNames.packageCliExecution ); if (packageCliExecutionPromptCli) { @@ -116,7 +116,7 @@ describe('getPackagePrompts', () => { const packagePrompts = getPackagePrompts({}); const packageCliExecutionPrompt = packagePrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.packageCliExecution + (prompt) => prompt.name === promptNames.packageCliExecution ); if (packageCliExecutionPrompt) { @@ -131,9 +131,7 @@ describe('getPackagePrompts', () => { jest.spyOn(validators, 'validatePackage').mockResolvedValueOnce(true); const packagePrompts = getPackagePrompts({}); - const packageManualPrompt = packagePrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.packageManual - ); + const packageManualPrompt = packagePrompts.find((prompt) => prompt.name === promptNames.packageManual); if (packageManualPrompt) { expect((packageManualPrompt.when as Function)({ packageInputChoice: 'EnterManualChoice' })).toBe(true); @@ -159,14 +157,14 @@ describe('getPackagePrompts', () => { const packagePrompts = getPackagePrompts({}); const packageInputChoicePrompt = packagePrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.packageInputChoice + (prompt) => prompt.name === promptNames.packageInputChoice ); if (packageInputChoicePrompt) { await (packageInputChoicePrompt.validate as Function)(); } const packageAutocompletePrompt = packagePrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.packageAutocomplete + (prompt) => prompt.name === promptNames.packageAutocomplete ); if (packageAutocompletePrompt) { diff --git a/packages/abap-deploy-config-inquirer/test/prompts/questions/config/transport.test.ts b/packages/abap-deploy-config-inquirer/test/prompts/questions/config/transport.test.ts index 50666d3b07..31b1a66c7e 100644 --- a/packages/abap-deploy-config-inquirer/test/prompts/questions/config/transport.test.ts +++ b/packages/abap-deploy-config-inquirer/test/prompts/questions/config/transport.test.ts @@ -2,7 +2,7 @@ import { initI18n, t } from '../../../../src/i18n'; import { getTransportRequestPrompts } from '../../../../src/prompts/questions'; import * as conditions from '../../../../src/prompts/conditions'; import * as validators from '../../../../src/prompts/validators'; -import { abapDeployConfigInternalPromptNames, TransportChoices } from '../../../../src/types'; +import { promptNames, TransportChoices } from '../../../../src/types'; import { ListQuestion } from '@sap-ux/inquirer-common'; import { PromptState } from '../../../../src/prompts/prompt-state'; @@ -78,7 +78,7 @@ describe('getTransportRequestPrompts', () => { const transportPrompts = getTransportRequestPrompts({}); const transportInputChoicePrompt = transportPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.transportInputChoice + (prompt) => prompt.name === promptNames.transportInputChoice ); if (transportInputChoicePrompt) { @@ -116,7 +116,7 @@ describe('getTransportRequestPrompts', () => { PromptState.isYUI = false; const transportPrompts = getTransportRequestPrompts({}); const transportCliExecutionPrompt = transportPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.transportCliExecution + (prompt) => prompt.name === promptNames.transportCliExecution ); if (transportCliExecutionPrompt) { @@ -141,9 +141,7 @@ describe('getTransportRequestPrompts', () => { PromptState.transportAnswers.newTransportNumber = 'TR1234'; const transportPrompts = getTransportRequestPrompts({}); - const transportCreatedPrompt = transportPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.transportCreated - ); + const transportCreatedPrompt = transportPrompts.find((prompt) => prompt.name === promptNames.transportCreated); if (transportCreatedPrompt) { expect( @@ -164,7 +162,7 @@ describe('getTransportRequestPrompts', () => { const transportPrompts = getTransportRequestPrompts({}); const transportFromListPrompt = transportPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.transportFromList + (prompt) => prompt.name === promptNames.transportFromList ); if (transportFromListPrompt) { @@ -195,9 +193,7 @@ describe('getTransportRequestPrompts', () => { jest.spyOn(validators, 'validateTransportQuestion').mockReturnValueOnce(true); const transportPrompts = getTransportRequestPrompts({}); - const transportManualPrompt = transportPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.transportManual - ); + const transportManualPrompt = transportPrompts.find((prompt) => prompt.name === promptNames.transportManual); if (transportManualPrompt) { expect( diff --git a/packages/abap-deploy-config-inquirer/test/prompts/questions/confirm.test.ts b/packages/abap-deploy-config-inquirer/test/prompts/questions/confirm.test.ts index 44425a6c69..c3303a3dfc 100644 --- a/packages/abap-deploy-config-inquirer/test/prompts/questions/confirm.test.ts +++ b/packages/abap-deploy-config-inquirer/test/prompts/questions/confirm.test.ts @@ -2,7 +2,7 @@ import { initI18n, t } from '../../../src/i18n'; import { getConfirmPrompts } from '../../../src/prompts/questions'; import * as conditions from '../../../src/prompts/conditions'; import * as validators from '../../../src/prompts/validators'; -import { abapDeployConfigInternalPromptNames } from '../../../src/types'; +import { promptNames } from '../../../src/types'; describe('getConfirmPrompts', () => { beforeAll(async () => { @@ -31,7 +31,6 @@ describe('getConfirmPrompts', () => { "name": "overwrite", "type": "confirm", "validate": [Function], - "when": [Function], }, ] `); @@ -41,7 +40,7 @@ describe('getConfirmPrompts', () => { jest.spyOn(conditions, 'showIndexQuestion').mockReturnValueOnce(true); const confirmPrompts = getConfirmPrompts({}); - const indexPrompt = confirmPrompts.find((prompt) => prompt.name === abapDeployConfigInternalPromptNames.index); + const indexPrompt = confirmPrompts.find((prompt) => prompt.name === promptNames.index); if (indexPrompt) { expect((indexPrompt.when as Function)()).toBe(true); @@ -51,16 +50,12 @@ describe('getConfirmPrompts', () => { }); test('should return expected values from overwrite prompt methods', async () => { - jest.spyOn(conditions, 'showOverwriteQuestion').mockReturnValue(true); jest.spyOn(validators, 'validateConfirmQuestion').mockReturnValue(true); const confirmPrompts = getConfirmPrompts({}); - const overwritePrompt = confirmPrompts.find( - (prompt) => prompt.name === abapDeployConfigInternalPromptNames.overwrite - ); + const overwritePrompt = confirmPrompts.find((prompt) => prompt.name === promptNames.overwrite); if (overwritePrompt) { - expect((overwritePrompt.when as Function)()).toBe(true); expect(overwritePrompt.message).toBe(t('prompts.confirm.overwrite.message')); expect(overwritePrompt.default).toBe(true); expect((overwritePrompt.validate as Function)()).toBe(true); diff --git a/packages/abap-deploy-config-inquirer/test/utils.test.ts b/packages/abap-deploy-config-inquirer/test/utils.test.ts index 405da2c874..f4fedcd0da 100644 --- a/packages/abap-deploy-config-inquirer/test/utils.test.ts +++ b/packages/abap-deploy-config-inquirer/test/utils.test.ts @@ -195,10 +195,8 @@ describe('Test utils', () => { }); it('should return true when exisintg deploy task configuration has CREATE_TR_DURING_DEPLOY value', () => { - const existingDeployTaskConfig = { - transport: CREATE_TR_DURING_DEPLOY - }; - expect(useCreateTrDuringDeploy(existingDeployTaskConfig)).toBe(true); + const transport = CREATE_TR_DURING_DEPLOY; + expect(useCreateTrDuringDeploy(transport)).toBe(true); }); it('should return reconciled answers for destination', () => { diff --git a/packages/control-property-editor/CHANGELOG.md b/packages/control-property-editor/CHANGELOG.md index 1afa7d0b08..d2b549db93 100644 --- a/packages/control-property-editor/CHANGELOG.md +++ b/packages/control-property-editor/CHANGELOG.md @@ -1,5 +1,11 @@ # @sap-ux/control-property-editor +## 0.5.17 + +### Patch Changes + +- e65bb7f: Update popup styling and add more space between labels and icons + ## 0.5.16 ### Patch Changes diff --git a/packages/control-property-editor/package.json b/packages/control-property-editor/package.json index 6c1e81ee32..4387835604 100644 --- a/packages/control-property-editor/package.json +++ b/packages/control-property-editor/package.json @@ -3,7 +3,7 @@ "displayName": "Control Property Editor", "description": "Control Property Editor", "license": "Apache-2.0", - "version": "0.5.16", + "version": "0.5.17", "main": "dist/app.js", "repository": { "type": "git", diff --git a/packages/control-property-editor/src/Workarounds.scss b/packages/control-property-editor/src/Workarounds.scss index 6a2794278e..f9ff0798e6 100644 --- a/packages/control-property-editor/src/Workarounds.scss +++ b/packages/control-property-editor/src/Workarounds.scss @@ -91,7 +91,6 @@ } .ms-Callout { - border: 1px solid var(--vscode-widget-border); .ms-Callout-beak { display: none; } diff --git a/packages/control-property-editor/src/panels/properties/InputTypeWrapper.tsx b/packages/control-property-editor/src/panels/properties/InputTypeWrapper.tsx index 6e7d8b587a..2e944486f8 100644 --- a/packages/control-property-editor/src/panels/properties/InputTypeWrapper.tsx +++ b/packages/control-property-editor/src/panels/properties/InputTypeWrapper.tsx @@ -230,7 +230,8 @@ export function InputTypeWrapper(props: InputTypeWrapperProps): ReactElement { textOverflow: 'ellipsis', whiteSpace: 'nowrap', overflowX: 'hidden', - marginTop: 2 + marginTop: 2, + marginBottom: 3 }}> {property.readableName} diff --git a/packages/create/CHANGELOG.md b/packages/create/CHANGELOG.md index 8ffcf20340..ce427f3e54 100644 --- a/packages/create/CHANGELOG.md +++ b/packages/create/CHANGELOG.md @@ -1,5 +1,20 @@ # @sap-ux/create +## 0.8.40 + +### Patch Changes + +- Updated dependencies [43988ca] + - @sap-ux/abap-deploy-config-inquirer@1.0.1 + +## 0.8.39 + +### Patch Changes + +- b3b1082: update prompt options for abap deploy config inquirer +- Updated dependencies [b3b1082] + - @sap-ux/abap-deploy-config-inquirer@1.0.0 + ## 0.8.38 ### Patch Changes diff --git a/packages/create/package.json b/packages/create/package.json index 42bae1da66..a429eaabf2 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,7 +1,7 @@ { "name": "@sap-ux/create", "description": "SAP Fiori tools module to add or remove features", - "version": "0.8.38", + "version": "0.8.40", "repository": { "type": "git", "url": "https://github.com/SAP/open-ux-tools.git", diff --git a/packages/create/src/cli/add/deploy-config.ts b/packages/create/src/cli/add/deploy-config.ts index f70fb5b5b1..8ec74fcd8e 100644 --- a/packages/create/src/cli/add/deploy-config.ts +++ b/packages/create/src/cli/add/deploy-config.ts @@ -93,7 +93,7 @@ async function addDeployConfig( await validateBasePath(basePath); const { prompts: abapPrompts, answers: abapAnswers } = await getAbapDeployConfigPrompts( - { useAutocomplete: true }, + { packageAutocomplete: { useAutocomplete: true } }, logger, false ); diff --git a/packages/ui-components/CHANGELOG.md b/packages/ui-components/CHANGELOG.md index 986fbe4300..7781c4f83b 100644 --- a/packages/ui-components/CHANGELOG.md +++ b/packages/ui-components/CHANGELOG.md @@ -1,5 +1,23 @@ # @sap-ux/ui-components +## 1.18.9 + +### Patch Changes + +- 4c6f92c: feat(ui-c): add UIsetIconOptions and UIunregisterIcons + +## 1.18.8 + +### Patch Changes + +- b669796: UIComboBox and UIDropdown support custom renderers for dropdown items via the `onRenderOption` and `onRenderItem` properties + +## 1.18.7 + +### Patch Changes + +- e65bb7f: Update style for UICallout + ## 1.18.6 ### Patch Changes diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json index 388076971c..34a0c4d2a1 100644 --- a/packages/ui-components/package.json +++ b/packages/ui-components/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/ui-components", - "version": "1.18.6", + "version": "1.18.9", "license": "Apache-2.0", "description": "SAP UI Components Library", "repository": { diff --git a/packages/ui-components/src/components/Icons.tsx b/packages/ui-components/src/components/Icons.tsx index c1fb5dc07a..4f50fe4bf4 100644 --- a/packages/ui-components/src/components/Icons.tsx +++ b/packages/ui-components/src/components/Icons.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { registerIcons, initializeIcons } from '@fluentui/react'; +import { registerIcons, unregisterIcons, initializeIcons, setIconOptions } from '@fluentui/react'; const COLORS = { 'default': 'var(--vscode-icon-foreground, var(--vscode-foreground))', @@ -2237,4 +2237,6 @@ export function initIcons(): void { } export { registerIcons as UIregisterIcons }; +export { unregisterIcons as UIunregisterIcons }; export { initializeIcons as UIinitializeIcons }; +export { setIconOptions as UIsetIconOptions }; diff --git a/packages/ui-components/src/components/UICallout/UICallout.tsx b/packages/ui-components/src/components/UICallout/UICallout.tsx index e9869d6623..f2ea61aea5 100644 --- a/packages/ui-components/src/components/UICallout/UICallout.tsx +++ b/packages/ui-components/src/components/UICallout/UICallout.tsx @@ -18,11 +18,12 @@ export interface UICalloutProps extends ICalloutProps { import '../../styles/_shadows.scss'; export const CALLOUT_STYLES = { - background: 'var(--vscode-editorSuggestWidget-background)', + background: 'var(--vscode-editorWidget-background)', boxShadow: 'var(--ui-box-shadow-small)', - text: 'var(--vscode-editorSuggestWidget-foreground)', + borderColor: 'var(--vscode-editorWidget-border)', + text: 'var(--vscode-editorWidget-foreground)', font: 'var(--vscode-font-family)', - borderRadius: 4 + borderRadius: 2 }; export enum UICalloutContentPadding { @@ -54,8 +55,9 @@ export const getCalloutStyle = (props: UICalloutProps): ICalloutContentStyles => return { root: { boxShadow: CALLOUT_STYLES.boxShadow, - backgroundColor: 'transparent', + backgroundColor: CALLOUT_STYLES.background, borderRadius: CALLOUT_STYLES.borderRadius, + border: `1px solid ${CALLOUT_STYLES.borderColor}`, ...extractRawStyles(props.styles, 'root') }, beak: { @@ -69,7 +71,7 @@ export const getCalloutStyle = (props: UICalloutProps): ICalloutContentStyles => ...extractRawStyles(props.styles, 'beakCurtain') }, calloutMain: { - backgroundColor: CALLOUT_STYLES.background, + backgroundColor: 'transparent', color: CALLOUT_STYLES.text, fontFamily: CALLOUT_STYLES.font, borderRadius: CALLOUT_STYLES.borderRadius, diff --git a/packages/ui-components/src/components/UIComboBox/UIComboBox.tsx b/packages/ui-components/src/components/UIComboBox/UIComboBox.tsx index 864b38b9d1..76762bc9ff 100644 --- a/packages/ui-components/src/components/UIComboBox/UIComboBox.tsx +++ b/packages/ui-components/src/components/UIComboBox/UIComboBox.tsx @@ -287,14 +287,14 @@ export class UIComboBox extends React.Component JSX.Element | null ): JSX.Element | null => { @@ -319,6 +319,24 @@ export class UIComboBox extends React.Component JSX.Element | null + ): JSX.Element | null => { + if (this.props.onRenderItem) { + return this.props.onRenderItem(props, this._onRenderItem.bind(this, props, defaultRender)); + } + return this._onRenderItem(props, defaultRender); + }; + /** * Method to get current selected index. * @@ -350,14 +368,14 @@ export class UIComboBox extends React.Component JSX.Element | null ): JSX.Element | null => { @@ -367,6 +385,24 @@ export class UIComboBox extends React.Component JSX.Element | null + ): JSX.Element | null => { + if (this.props.onRenderOption) { + return this.props.onRenderOption(props, this._onRenderOption.bind(this, props, defaultRender)); + } + return this._onRenderOption(props, defaultRender); + }; + /** * Method which determines what is next visible item - it is used to fix bug in fluentui sources.. * diff --git a/packages/ui-components/src/components/UIDropdown/UIDropdown.tsx b/packages/ui-components/src/components/UIDropdown/UIDropdown.tsx index 1abf7d916a..5a1a127a87 100644 --- a/packages/ui-components/src/components/UIDropdown/UIDropdown.tsx +++ b/packages/ui-components/src/components/UIDropdown/UIDropdown.tsx @@ -136,7 +136,7 @@ export class UIDropdown extends React.Component JSX.Element | null} [defaultRender] Default option renderer. * @returns {JSX.Element | null} Returns dropdown option element. */ - private readonly onRenderOption = ( + private readonly _onRenderOption = ( props?: IDropdownOption, defaultRender?: (props?: IDropdownOption) => JSX.Element | null ): JSX.Element | null => { @@ -154,6 +154,23 @@ export class UIDropdown extends React.Component JSX.Element | null} [defaultRender] Default option renderer. + * @returns {JSX.Element | null} Returns dropdown option element. + */ + private readonly onRenderOption = ( + props?: IDropdownOption, + defaultRender?: (props?: IDropdownOption) => JSX.Element | null + ): JSX.Element | null => { + if (this.props.onRenderOption) { + return this.props.onRenderOption(props, this._onRenderOption.bind(this, props, defaultRender)); + } + return this._onRenderOption(props, defaultRender); + }; + /** * Method called on combobox item render. * We should pass query to it and avoid rendering if it is hidden. @@ -162,7 +179,7 @@ export class UIDropdown extends React.Component JSX.Element | null ): JSX.Element | null => { @@ -177,6 +194,23 @@ export class UIDropdown extends React.Component JSX.Element | null + ): JSX.Element | null => { + if (this.props.onRenderItem) { + return this.props.onRenderItem(props, this._onRenderItem.bind(this, props, defaultRender)); + } + return this._onRenderItem(props, defaultRender); + }; + /** * Method returns styles for callout to support property 'useDropdownAsMenuMinWidth'. * States: @@ -296,13 +330,13 @@ export class UIDropdown extends React.Component { ); }; + +const editableEntries = ['AR', 'BR', 'DK']; + +const tempData = data.map((item) => { + if (editableEntries.includes(item.key)) { + return { + ...item, + editable: true + }; + } + return item; +}); + +export const customRender = () => { + return ( + JSX.Element | null + ) => { + if ('editable' in (props ?? {})) { + return ( + { + const target = event.target as HTMLElement; + target.focus(); + }} + onClick={(event) => { + event.nativeEvent.preventDefault(); + event.nativeEvent.stopPropagation(); + event.preventDefault(); + event.stopPropagation(); + }} + /> + ); + } + return defaultRender?.(props) ?? null; + }} + onRenderItem={( + props?: UIComboBoxOption, + defaultRender?: (props?: UIComboBoxOption) => JSX.Element | null + ) => { + return defaultRender?.(props) ?? null; + }} + /> + ); +}; diff --git a/packages/ui-components/stories/UIDropdown.story.tsx b/packages/ui-components/stories/UIDropdown.story.tsx index ea707d4eed..5ba60d228d 100644 --- a/packages/ui-components/stories/UIDropdown.story.tsx +++ b/packages/ui-components/stories/UIDropdown.story.tsx @@ -1,7 +1,14 @@ import React from 'react'; import { Stack } from '@fluentui/react'; import type { IDropdownOption } from '@fluentui/react'; -import { UISelectableOptionMenuItemType, UICheckbox, UIDropdown, initIcons } from '../src/components'; +import { + UISelectableOptionMenuItemType, + UICheckbox, + UIDropdown, + initIcons, + UISelectableOption, + UITextInput +} from '../src/components'; import { data, shortData, groupsData } from '../test/__mock__/select-data'; initIcons(); @@ -210,3 +217,51 @@ export const groupsAndSeparators = () => { ); }; + +const editableEntries = ['AR', 'BR', 'DK']; + +const tempData = data.map((item) => { + if (editableEntries.includes(item.key)) { + return { + ...item, + editable: true + }; + } + return item; +}); + +export const customRender = () => { + return ( + JSX.Element | null + ) => { + if ('editable' in (props ?? {})) { + return ( + { + const target = event.target as HTMLElement; + target.focus(); + }} + onClick={(event) => { + event.nativeEvent.preventDefault(); + event.nativeEvent.stopPropagation(); + event.preventDefault(); + event.stopPropagation(); + }} + /> + ); + } + return defaultRender?.(props) ?? null; + }} + onRenderItem={( + props?: UISelectableOption, + defaultRender?: (props?: UISelectableOption) => JSX.Element | null + ) => { + return defaultRender?.(props) ?? null; + }} + /> + ); +}; diff --git a/packages/ui-components/stories/UITranslationInput.story.tsx b/packages/ui-components/stories/UITranslationInput.story.tsx index 28ba41a85a..747b541306 100644 --- a/packages/ui-components/stories/UITranslationInput.story.tsx +++ b/packages/ui-components/stories/UITranslationInput.story.tsx @@ -28,7 +28,7 @@ interface CustomTranslationEntry extends TranslationEntry { initIcons(); -const stackTokens: IStackTokens = { childrenGap: 40 }; +const stackTokens: IStackTokens = { childrenGap: 60 }; const I18N_BUNDLE_KEY = 'ui-components-i18n-bundle'; const getI18nBundle = (): I18nBundle => { diff --git a/packages/ui-components/test/unit/components/UICallout.test.tsx b/packages/ui-components/test/unit/components/UICallout.test.tsx index d046994cb8..5f44efb749 100644 --- a/packages/ui-components/test/unit/components/UICallout.test.tsx +++ b/packages/ui-components/test/unit/components/UICallout.test.tsx @@ -28,9 +28,9 @@ describe('', () => { it('Should render a UITooltip component', () => { expect(wrapper.find('.ms-Callout').length).toEqual(1); const style = getCalloutStyles(); - expect(style.root?.['borderRadius']).toEqual(4); - expect(style.beakCurtain?.['borderRadius']).toEqual(4); - expect(style.calloutMain?.['borderRadius']).toEqual(4); + expect(style.root?.['borderRadius']).toEqual(2); + expect(style.beakCurtain?.['borderRadius']).toEqual(2); + expect(style.calloutMain?.['borderRadius']).toEqual(2); expect(style.root?.['boxShadow']).toEqual('var(--ui-box-shadow-small)'); }); diff --git a/packages/ui-components/test/unit/components/UICombobox.test.tsx b/packages/ui-components/test/unit/components/UICombobox.test.tsx index 3512256bbe..1afaa8755a 100644 --- a/packages/ui-components/test/unit/components/UICombobox.test.tsx +++ b/packages/ui-components/test/unit/components/UICombobox.test.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import * as Enzyme from 'enzyme'; -import type { UIComboBoxProps, UIComboBoxState } from '../../../src/components/UIComboBox'; +import type { UIComboBoxOption, UIComboBoxProps, UIComboBoxState } from '../../../src/components/UIComboBox'; import { UIComboBox, UIComboBoxLoaderType } from '../../../src/components/UIComboBox'; import { data as originalData, groupsData as originalGroupsData } from '../../__mock__/select-data'; import { initIcons } from '../../../src/components/Icons'; @@ -831,4 +831,36 @@ describe('', () => { expect(wrapper.find('.ms-ComboBox UILoader').length).toEqual(expectLoaderInInput ? 1 : 0); }); }); + + it('Custom renderers for "onRenderOption"', () => { + wrapper.setProps({ + highlight: true, + onRenderOption: ( + props?: UIComboBoxOption, + defaultRender?: (props?: UIComboBoxOption) => JSX.Element | null + ) => { + return
{defaultRender?.(props)}
; + } + }); + openDropdown(); + expect(wrapper.find('.custom-render-option').length).toBeGreaterThan(0); + expect(wrapper.find(highlightItemSelector).length).toBeGreaterThan(0); + }); + + it('Custom renderers for "onRenderItem"', () => { + wrapper.setProps({ + options: JSON.parse(JSON.stringify(originalData)), + highlight: true, + selectedKey: 'AR', + onRenderItem: ( + props?: UIComboBoxOption, + defaultRender?: (props?: UIComboBoxOption) => JSX.Element | null + ) => { + return
{defaultRender?.(props)}
; + } + }); + openDropdown(); + expect(wrapper.find('.custom-render-item').length).toBeGreaterThan(0); + expect(wrapper.find('.ts-ComboBox--selected').length).toBeGreaterThan(0); + }); }); diff --git a/packages/ui-components/test/unit/components/UIDropdown.test.tsx b/packages/ui-components/test/unit/components/UIDropdown.test.tsx index 40afe012b6..ae0cd93447 100644 --- a/packages/ui-components/test/unit/components/UIDropdown.test.tsx +++ b/packages/ui-components/test/unit/components/UIDropdown.test.tsx @@ -7,6 +7,7 @@ import { Dropdown, ResponsiveMode } from '@fluentui/react'; import { data as originalData, groupsData as originalGroupsData } from '../../__mock__/select-data'; import { initIcons } from '../../../src/components/Icons'; import { CalloutCollisionTransform } from '../../../src/components'; +import type { UISelectableOption } from '../../../src/components'; const data = JSON.parse(JSON.stringify(originalData)); const groupsData = JSON.parse(JSON.stringify(originalGroupsData)); @@ -367,6 +368,33 @@ describe('', () => { }); } }); + + it('Custom renderers for "onRenderOption"', () => { + wrapper.setProps({ + onRenderOption: ( + props?: UISelectableOption, + defaultRender?: (props?: UISelectableOption) => JSX.Element | null + ) => { + return
{defaultRender?.(props)}
; + } + }); + openDropdown(); + expect(wrapper.find('.custom-render-option').length).toBeGreaterThan(0); + expect(wrapper.find('.ts-dropdown-item-blocker').length).toBeGreaterThan(0); + }); + + it('Custom renderers for "onRenderItem"', () => { + wrapper.setProps({ + onRenderItem: ( + props?: UISelectableOption, + defaultRender?: (props?: UISelectableOption) => JSX.Element | null + ) => { + return
{defaultRender?.(props)}
; + } + }); + openDropdown(); + expect(wrapper.find('.custom-render-item').length).toBeGreaterThan(0); + }); }); describe('Utils/getCalloutCollisionTransformationProps', () => { diff --git a/packages/ui-prompting/CHANGELOG.md b/packages/ui-prompting/CHANGELOG.md index 1af615873f..21a061819b 100644 --- a/packages/ui-prompting/CHANGELOG.md +++ b/packages/ui-prompting/CHANGELOG.md @@ -1,5 +1,26 @@ # @sap-ux/ui-prompting +## 0.2.6 + +### Patch Changes + +- Updated dependencies [4c6f92c] + - @sap-ux/ui-components@1.18.9 + +## 0.2.5 + +### Patch Changes + +- Updated dependencies [b669796] + - @sap-ux/ui-components@1.18.8 + +## 0.2.4 + +### Patch Changes + +- Updated dependencies [e65bb7f] + - @sap-ux/ui-components@1.18.7 + ## 0.2.3 ### Patch Changes diff --git a/packages/ui-prompting/package.json b/packages/ui-prompting/package.json index 81b61800e7..2d644f1f04 100644 --- a/packages/ui-prompting/package.json +++ b/packages/ui-prompting/package.json @@ -1,6 +1,6 @@ { "name": "@sap-ux/ui-prompting", - "version": "0.2.3", + "version": "0.2.6", "license": "Apache-2.0", "description": "SAP UI Components Library", "repository": {