Skip to content

Commit

Permalink
fix: quick action improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
voicis committed Sep 20, 2024
1 parent 5212bd8 commit 61bee66
Show file tree
Hide file tree
Showing 31 changed files with 303 additions and 161 deletions.
6 changes: 2 additions & 4 deletions packages/control-property-editor-common/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,7 @@ export const save = createExternalAction<void>('save');
export const quickActionListChanged = createExternalAction<QuickActionGroup[]>('quick-action-list-changed');
export const updateQuickAction = createExternalAction<QuickAction>('update-quick-action');
export const executeQuickAction = createExternalAction<QuickActionExecutionPayload>('execute-quick-action');
export const numberOfChangesRequiringReloadChanged = createExternalAction<number>(
'number-of-changes-requiring-reload-changed'
);
export const setApplicationRequiresReload = createExternalAction<boolean>('set-application-requires-reload');

export type ExternalAction =
| ReturnType<typeof iconsLoaded>
Expand All @@ -325,6 +323,6 @@ export type ExternalAction =
| ReturnType<typeof save>
| ReturnType<typeof appLoaded>
| ReturnType<typeof quickActionListChanged>
| ReturnType<typeof numberOfChangesRequiringReloadChanged>
| ReturnType<typeof setApplicationRequiresReload>
| ReturnType<typeof updateQuickAction>
| ReturnType<typeof executeQuickAction>;
12 changes: 6 additions & 6 deletions packages/control-property-editor/src/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
ShowMessage
} from '@sap-ux-private/control-property-editor-common';
import {
numberOfChangesRequiringReloadChanged,
setApplicationRequiresReload,
changeStackModified,
controlSelected,
iconsLoaded,
Expand Down Expand Up @@ -61,7 +61,7 @@ interface SliceState {
canRedo: boolean;
};
canSave: boolean;
pendingChangesRequiresSaveAndReload: boolean;
applicationRequiresReload: boolean;
isAppLoading: boolean;
quickActions: QuickActionGroup[];
}
Expand Down Expand Up @@ -149,7 +149,7 @@ export const initialState: SliceState = {
canRedo: false
},
canSave: false,
pendingChangesRequiresSaveAndReload: false,
applicationRequiresReload: false,
isAppLoading: true,
quickActions: []
};
Expand Down Expand Up @@ -324,9 +324,9 @@ const slice = createSlice<SliceState, SliceCaseReducers<SliceState>, string>({
state.isAppLoading = false;
})
.addMatcher(
numberOfChangesRequiringReloadChanged.match,
(state, action: ReturnType<typeof numberOfChangesRequiringReloadChanged>): void => {
state.pendingChangesRequiresSaveAndReload = action.payload > 0;
setApplicationRequiresReload.match,
(state, action: ReturnType<typeof setApplicationRequiresReload>): void => {
state.applicationRequiresReload = action.payload;
}
)
.addMatcher(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@ export function UndoRedoSaveActions(): ReactElement {
const canSave = useSelector<RootState, boolean>((state) => state.canSave);
const isLoading = useSelector<RootState, boolean>((state) => state.isAppLoading);
const fileChanges = useSelector<RootState, string[] | undefined>((state) => state.fileChanges) ?? [];
const pendingChangesRequiresSaveAndReload = useSelector<RootState, boolean>(
(state) => state.pendingChangesRequiresSaveAndReload
);
const applicationRequiresReload = useSelector<RootState, boolean>((state) => state.applicationRequiresReload);
const { pending } = useSelector<RootState, ChangesSlice>((state) => state.changes);
const saveAndReload = (fileChanges.length > 0 && pending.length > 0) || pendingChangesRequiresSaveAndReload;
const saveAndReload = (fileChanges.length > 0 && pending.length > 0) || applicationRequiresReload;
return (
<>
<UIIconButton
Expand Down
12 changes: 6 additions & 6 deletions packages/control-property-editor/test/unit/slice.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
changeStackModified,
iconsLoaded,
numberOfChangesRequiringReloadChanged,
setApplicationRequiresReload,
propertyChanged,
propertyChangeFailed,
quickActionListChanged,
Expand Down Expand Up @@ -297,19 +297,19 @@ describe('main redux slice', () => {
deviceType: DeviceType.Desktop
});
});
describe('numberOfChangesRequiringReloadChanged', () => {
describe('setApplicationRequiresReload', () => {
test('one change requires reload', () => {
expect(
reducer({ pendingChangesRequiresSaveAndReload: false } as any, numberOfChangesRequiringReloadChanged(1))
reducer({ applicationRequiresReload: false } as any, setApplicationRequiresReload(true))
).toStrictEqual({
pendingChangesRequiresSaveAndReload: true
applicationRequiresReload: true
});
});
test('no changes require reload', () => {
expect(
reducer({ pendingChangesRequiresSaveAndReload: true } as any, numberOfChangesRequiringReloadChanged(0))
reducer({ setApplicationRequiresReload: true } as any, setApplicationRequiresReload(false))
).toStrictEqual({
pendingChangesRequiresSaveAndReload: false
applicationRequiresReload: false
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
redo,
save,
undo,
numberOfChangesRequiringReloadChanged,
setApplicationRequiresReload,
reloadApplication
} from '@sap-ux-private/control-property-editor-common';

Expand Down Expand Up @@ -54,7 +54,7 @@ describe('toolbar', () => {
// update state
store.dispatch(setUndoRedoEnablement({ canRedo: true, canUndo: true }));
store.dispatch(setSaveEnablement(true));
store.dispatch(numberOfChangesRequiringReloadChanged(5));
store.dispatch(setApplicationRequiresReload(true));
store.dispatch(appLoaded());

dispatch.mockClear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ import OverlayRegistry from 'sap/ui/dt/OverlayRegistry';
import type ElementOverlay from 'sap/ui/dt/ElementOverlay';

/** sap.ui.fl */
import {type AddFragmentChangeContentType} from 'sap/ui/fl/Change';
import { type AddFragmentChangeContentType } from 'sap/ui/fl/Change';

import { setApplicationRequiresReload } from '@sap-ux-private/control-property-editor-common';

import { getResourceModel } from '../../i18n';
import { CommunicationService } from '../../cpe/communication-service';

import ControlUtils from '../control-utils';
import CommandExecutor from '../command-executor';
Expand All @@ -38,20 +43,30 @@ interface CreateFragmentProps {
const radix = 10;

type AddFragmentModel = JSONModel & {
getProperty(sPath: '/title'): string;
getProperty(sPath: '/completeView'): boolean;
getProperty(sPath: '/newFragmentName'): string;
getProperty(sPath: '/selectedIndex'): number;
getProperty(sPath: '/selectedAggregation/value'): string;
};

export interface AddFragmentOptions {
title: string;
aggregation?: string;
}

/**
* @namespace open.ux.preview.client.adp.controllers
*/
export default class AddFragment extends BaseDialog<AddFragmentModel> {
constructor(name: string, overlays: UI5Element, rta: RuntimeAuthoring, private aggregation?: string) {
constructor(name: string, overlays: UI5Element, rta: RuntimeAuthoring, private options: AddFragmentOptions) {
super(name);
this.rta = rta;
this.overlays = overlays;
this.model = new JSONModel();
this.model = new JSONModel({
title: options.title,
completeView: options.aggregation === undefined
});
this.ui5Version = sap.ui.version;
this.commandExecutor = new CommandExecutor(this.rta);
}
Expand All @@ -67,7 +82,9 @@ export default class AddFragment extends BaseDialog<AddFragmentModel> {
this.setEscapeHandler();

await this.buildDialogData();
const resourceModel = await getResourceModel('open.ux.preview.client');

this.dialog.setModel(resourceModel, 'i18n');
this.dialog.setModel(this.model);

this.dialog.open();
Expand Down Expand Up @@ -184,7 +201,7 @@ export default class AddFragment extends BaseDialog<AddFragmentModel> {
}
return false;
});
const defaultAggregation = this.aggregation ?? controlMetadata.getDefaultAggregationName();
const defaultAggregation = this.options.aggregation ?? controlMetadata.getDefaultAggregationName();
const selectedControlName = controlMetadata.getName();

let selectedControlChildren: string[] | number[] = Object.keys(
Expand Down Expand Up @@ -290,6 +307,7 @@ export default class AddFragment extends BaseDialog<AddFragmentModel> {
const preparedChange = command.getPreparedChange();
const content = preparedChange.getContent();
preparedChange.setContent({ ...content, templateName });
CommunicationService.sendAction(setApplicationRequiresReload(true));
}
await this.commandExecutor.pushAndExecuteCommand(command);
}
Expand Down
7 changes: 3 additions & 4 deletions packages/preview-middleware-client/src/adp/extension-point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ExternalAction, addExtensionPoint } from '@sap-ux-private/control-prope

import { Deferred, createDeferred } from './utils';

import { SubscribeFunction } from '../cpe/types';
import { CommunicationService } from '../cpe/communication-service';
import { DialogNames, handler } from './init-dialogs';

type ActionService = {
Expand Down Expand Up @@ -50,11 +50,10 @@ export default class ExtensionPointService {
/**
* Initializes communication with CPE, and the extension point plugin.
*
* @param subscribe Handles actions from CPE
*/
public init(subscribe: SubscribeFunction) {
public init() {
this.initPlugin();
subscribe(async (action: ExternalAction): Promise<void> => {
CommunicationService.subscribe(async (action: ExternalAction): Promise<void> => {
if (addExtensionPoint.match(action)) {
try {
const { controlId, name } = action.payload;
Expand Down
18 changes: 9 additions & 9 deletions packages/preview-middleware-client/src/adp/init-dialogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ import FlUtils from 'sap/ui/fl/Utils';
/** sap.ui.dt */
import type ElementOverlay from 'sap/ui/dt/ElementOverlay';

import AddFragment from './controllers/AddFragment.controller';
import AddFragment, { AddFragmentOptions } from './controllers/AddFragment.controller';
import ControllerExtension from './controllers/ControllerExtension.controller';
import { ExtensionPointData } from './extension-point';
import ExtensionPoint from './controllers/ExtensionPoint.controller';
import ManagedObject from 'sap/ui/base/ManagedObject';
import { isReuseComponent } from '../cpe/utils';
import { Ui5VersionInfo } from '../utils/version';
import { getTextBundle } from '../i18n';

export const enum DialogNames {
ADD_FRAGMENT = 'AddFragment',
Expand Down Expand Up @@ -118,25 +119,24 @@ export const getAddFragmentItemText = (overlay: ElementOverlay) => {
* @param rta Runtime Authoring
* @param dialogName Dialog name
* @param extensionPointData Control ID
* @param aggregation Name of aggregation that should be selected when dialog is opened
* @param options Dialog options
*/
export async function handler(
overlay: UI5Element,
rta: RuntimeAuthoring,
dialogName: DialogNames,
extensionPointData?: ExtensionPointData,
aggregation?: string
options: Partial<AddFragmentOptions> = {}
): Promise<void> {
let controller: Controller;
const resources = await getTextBundle();

switch (dialogName) {
case DialogNames.ADD_FRAGMENT:
controller = new AddFragment(
`open.ux.preview.client.adp.controllers.${dialogName}`,
overlay,
rta,
aggregation
);
controller = new AddFragment(`open.ux.preview.client.adp.controllers.${dialogName}`, overlay, rta, {
aggregation: options.aggregation,
title: resources.getText(options.title ?? 'ADP_ADD_FRAGMENT_DIALOG_TITLE')
});
break;
case DialogNames.CONTROLLER_EXTENSION:
controller = new ControllerExtension(`open.ux.preview.client.adp.controllers.${dialogName}`, overlay, rta);
Expand Down
38 changes: 7 additions & 31 deletions packages/preview-middleware-client/src/adp/init.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import log from 'sap/base/Log';
import type RuntimeAuthoring from 'sap/ui/rta/RuntimeAuthoring';

import {
ExternalAction,
showMessage,
startPostMessageCommunication,
enableTelemetry
} from '@sap-ux-private/control-property-editor-common';
import { showMessage, enableTelemetry } from '@sap-ux-private/control-property-editor-common';

import { ActionHandler } from '../cpe/types';
import { getError } from '../utils/error';
import { getUi5Version, getUI5VersionValidationMessage, isLowerThanMinimalUi5Version } from '../utils/version';

import { CommunicationService } from '../cpe/communication-service';
import init from '../cpe/init';
import { getApplicationType } from '../utils/application';
import { getTextBundle } from '../i18n';
Expand All @@ -25,27 +19,7 @@ export default async function (rta: RuntimeAuthoring) {
if (flexSettings.telemetry === true) {
enableTelemetry();
}
const actionHandlers: ActionHandler[] = [];
/**
*
* @param handler action handler
*/
function subscribe(handler: ActionHandler): void {
actionHandlers.push(handler);
}

const { sendAction } = startPostMessageCommunication<ExternalAction>(
window.parent,
async function onAction(action: ExternalAction) {
for (const handler of actionHandlers) {
try {
await handler(action);
} catch (error) {
log.error('Handler Failed: ', getError(error));
}
}
}
);

const ui5VersionInfo = await getUi5Version();
const syncViewsIds = await getAllSyncViewsIds(ui5VersionInfo);
Expand All @@ -54,7 +28,7 @@ export default async function (rta: RuntimeAuthoring) {
if (!isLowerThanMinimalUi5Version(ui5VersionInfo, { major: 1, minor: 78 })) {
const ExtensionPointService = (await import('open/ux/preview/client/adp/extension-point')).default;
const extPointService = new ExtensionPointService(rta);
extPointService.init(subscribe);
extPointService.init();
}

const applicationType = getApplicationType(rta.getRootControlInstance().getManifest());
Expand All @@ -63,13 +37,15 @@ export default async function (rta: RuntimeAuthoring) {
await init(rta, quickActionRegistries);

if (isLowerThanMinimalUi5Version(ui5VersionInfo)) {
sendAction(showMessage({ message: getUI5VersionValidationMessage(ui5VersionInfo), shouldHideIframe: true }));
CommunicationService.sendAction(
showMessage({ message: getUI5VersionValidationMessage(ui5VersionInfo), shouldHideIframe: true })
);
return;
}

if (syncViewsIds.length > 0) {
const bundle = await getTextBundle();
sendAction(
CommunicationService.sendAction(
showMessage({
message: bundle.getText('ADP_SYNC_VIEWS_MESSAGE'),
shouldHideIframe: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ export class AddCustomSectionQuickAction
)[0] as ObjectPageLayout;

const overlay = OverlayRegistry.getOverlay(objectPageLayout) || [];
await handler(overlay, this.context.rta, DialogNames.ADD_FRAGMENT, undefined, 'sections');
await handler(overlay, this.context.rta, DialogNames.ADD_FRAGMENT, undefined, {
aggregation: 'sections',
title: 'QUICK_ACTION_OP_ADD_CUSTOM_SECTION'
});
return [];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ export class AddHeaderFieldQuickAction extends SimpleQuickActionDefinitionBase i
// check if only flex box exist in the headerContent.
if (headerContent.length === 1 && isA<FlexBox>('sap.m.FlexBox', headerContent[0])) {
const overlay = OverlayRegistry.getOverlay(headerContent[0]) || [];
await handler(overlay, this.context.rta, DialogNames.ADD_FRAGMENT, undefined, 'items');
await handler(overlay, this.context.rta, DialogNames.ADD_FRAGMENT, undefined, {
aggregation: 'items',
title: 'QUICK_ACTION_OP_ADD_HEADER_FIELD'
});
} else if (this.control) {
const overlay = OverlayRegistry.getOverlay(this.control) || [];
await handler(overlay, this.context.rta, DialogNames.ADD_FRAGMENT, undefined, 'headerContent');
await handler(overlay, this.context.rta, DialogNames.ADD_FRAGMENT, undefined, {
aggregation: 'headerContent',
title: 'QUICK_ACTION_OP_ADD_HEADER_FIELD'
});
}
return [];
}
Expand Down
Loading

0 comments on commit 61bee66

Please sign in to comment.