Skip to content

Commit

Permalink
use empty array for layouts if not yet loaded when changing layoutset (
Browse files Browse the repository at this point in the history
…#11340)

* Set layouts as empty array if not loaded yet

* Move selected layout set to global ux-editor context

* fix tests

* Add tests

* Move MapIformLayoutsToLayouts outside of comopnent

* Filter out eventlistener on window from useLocalStorage hook to separate useReactiveLocalStorage hook
  • Loading branch information
standeren authored and nkylstad committed Nov 5, 2023
1 parent 8b182f4 commit 190c235
Show file tree
Hide file tree
Showing 43 changed files with 268 additions and 215 deletions.
2 changes: 1 addition & 1 deletion backend/src/Designer/Controllers/PreviewController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ public IActionResult UpdateAttachmentWithTag(string org, string app, [FromQuery]
private string GetSelectedLayoutSetInEditorFromRefererHeader(string refererHeader)
{
Uri refererUri = new(refererHeader);
string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSetInEditor"];
string layoutSetName = HttpUtility.ParseQueryString(refererUri.Query)["selectedLayoutSet"];

return string.IsNullOrEmpty(layoutSetName) ? null : layoutSetName;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public async Task Delete_Attachment_Ok()
{
string dataPathWithData = $"{Org}/{App}/instances/{PartyId}/{InstanceGuId}/data/{AttachmentGuId}";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Delete, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -30,7 +30,7 @@ public async Task Delete_AttachmentForStateFulApp_Ok()
{
string dataPathWithData = $"{Org}/{StatefulApp}/instances/{PartyId}/{InstanceGuId}/data/{AttachmentGuId}";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Delete, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public async Task Get_FormData_Ok()

string dataPathWithData = $"{Org}/{App}/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -38,7 +38,7 @@ public async Task Get_FormDataForAppWithoutDatamodel_Ok()
{
string dataPathWithData = $"{Org}/empty-app/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -54,7 +54,7 @@ public async Task Get_FormDataForStatefulApp_Ok()

string dataPathWithData = $"{Org}/{StatefulApp}/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -68,7 +68,7 @@ public async Task Get_FormDataForStatefulAppForTaskWithoutDatamodel_Ok()
{
string dataPathWithData = $"{Org}/{StatefulApp}/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName2}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName2}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public async Task Get_InstanceForNextProcess_Ok()
{
string dataPathWithData = $"{Org}/{App}/instances/{PartyId}/{InstanceGuId}";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -39,7 +39,7 @@ public async Task Get_InstanceForNextTaskForStatefulApp_Ok_TaskIsIncreased()
{
string dataPathWithData = $"{Org}/{StatefulApp}/instances/{PartyId}/{InstanceGuId}";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public async Task Post_Instance_Ok()

string dataPathWithData = $"{Org}/{targetRepository}/instances?instanceOwnerPartyId=51001";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -46,7 +46,7 @@ public async Task Post_InstanceForStatefulApp_Ok()

string dataPathWithData = $"{Org}/{targetRepository}/instances?instanceOwnerPartyId=51001";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public async Task Post_Attachment_Ok()
{
string dataPathWithData = $"{Org}/{App}/instances/{PartyId}/{InstanceGuId}/data?dataType=FileUploadId";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
Expand All @@ -31,7 +31,7 @@ public async Task Post_AttachmentForStateFulApp_Ok()
{
string dataPathWithData = $"{Org}/{StatefulApp}/instances/{PartyId}/{InstanceGuId}/data?dataType=FileUploadId";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Post, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(StatusCodes.Status201Created, (int)response.StatusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public async Task Get_ProcessNext_Ok()
{
string dataPathWithData = $"{Org}/{App}/instances/{PartyId}/{InstanceGuId}/process/next";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -39,7 +39,7 @@ public async Task Get_ProcessNextForStatefulApp_Ok()
{
string dataPathWithData = $"{Org}/{StatefulApp}/instances/{PartyId}/{InstanceGuId}/process/next";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public async Task Get_Process_Ok()
{
string dataPathWithData = $"{Org}/{App}/instances/{PartyId}/{InstanceGuId}/process";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -39,7 +39,7 @@ public async Task Get_ProcessForStatefulApp_Ok()
{
string dataPathWithData = $"{Org}/{StatefulApp}/instances/{PartyId}/{InstanceGuId}/process";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Get, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public async Task Put_UpdateFormData_Ok()
{
string dataPathWithData = $"{Org}/{App}/instances/{PartyId}/{InstanceGuId}/data/test-datatask-id";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Put, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(StatusCodes.Status200OK, (int)response.StatusCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public async Task Put_ProcessNext_Ok()
{
string dataPathWithData = $"{Org}/{App}/instances/{PartyId}/{InstanceGuId}/process/next";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Put, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSetInEditor=");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={App}&selectedLayoutSet=");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand All @@ -36,7 +36,7 @@ public async Task Put_ProcessNextForStatefulAppForNonExistingTask_Ok()
{
string dataPathWithData = $"{Org}/{StatefulApp}/instances/{PartyId}/{InstanceGuId}/process/next";
using HttpRequestMessage httpRequestMessage = new(HttpMethod.Put, dataPathWithData);
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSetInEditor={LayoutSetName}");
httpRequestMessage.Headers.Referrer = new Uri($"{MockedReferrerUrl}?org={Org}&app={StatefulApp}&selectedLayoutSet={LayoutSetName}");

using HttpResponseMessage response = await HttpClient.SendAsync(httpRequestMessage);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Expand Down
10 changes: 4 additions & 6 deletions frontend/app-preview/src/views/LandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ export const LandingPage = ({ variant = 'preview' }: LandingPageProps) => {
const [openSaveChoiceInSession, setOpenShowSaveChoiceInSession] = useState<boolean>(false);
const showPreviewLimitationsInfoSession: boolean = typedSessionStorage.getItem('showPreviewLimitationsInfo');
const [showPreviewLimitationsInfo, setShowPreviewLimitationsInfo] = useState<boolean>(showPreviewLimitationsInfoSession ?? true);
const [selectedLayoutSetInEditor, setSelectedLayoutSetInEditor] = useLocalStorage<string>(
'layoutSet/' + app,
);
const [selectedLayoutSet, setSelectedLayoutSet] = useLocalStorage<string>('layoutSet/' + app, null);
const [previewViewSize, setPreviewViewSize] = useLocalStorage<PreviewAsViewSize>(
'viewSize',
'desktop',
Expand All @@ -49,7 +47,7 @@ export const LandingPage = ({ variant = 'preview' }: LandingPageProps) => {
input !== null && input.tagName === 'IFRAME';

const handleChangeLayoutSet = (layoutSet: string) => {
setSelectedLayoutSetInEditor(layoutSet);
setSelectedLayoutSet(layoutSet);
// might need to remove selected layout from local storage to make sure first page is selected
window.location.reload();
};
Expand Down Expand Up @@ -94,7 +92,7 @@ export const LandingPage = ({ variant = 'preview' }: LandingPageProps) => {
<AppPreviewSubMenu
setViewSize={setPreviewViewSize}
viewSize={previewViewSize}
selectedLayoutSet={selectedLayoutSetInEditor}
selectedLayoutSet={selectedLayoutSet}
handleChangeLayoutSet={handleChangeLayoutSet}
/>
}
Expand All @@ -121,7 +119,7 @@ export const LandingPage = ({ variant = 'preview' }: LandingPageProps) => {
<iframe
title={t('preview.iframe_title')}
id='app-frontend-react-iframe'
src={previewPage(org, app, selectedLayoutSetInEditor)}
src={previewPage(org, app, selectedLayoutSet)}
className={previewViewSize === 'desktop' ? classes.iframeDesktop : classes.iframeMobile}
/>
</div>
Expand Down
39 changes: 39 additions & 0 deletions frontend/packages/shared/src/hooks/useEventListener.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { renderHook } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { act } from 'react-dom/test-utils';

import { useEventListener } from './useEventListener';

const user = userEvent.setup();

const renderUseEventListener = (eventType: string, action: () => void) =>
renderHook(() => useEventListener(eventType, action), {
initialProps: { eventType, action },
});

describe('useEventListener', () => {
it('Calls action when given event happens', async () => {
const action = jest.fn();
renderUseEventListener('click', action);
await act(() => user.click(document.body));
expect(action).toHaveBeenCalledTimes(1);
});

it('Does not call action when another event is given', async () => {
const action = jest.fn();
renderUseEventListener('click', action);
await act(() => user.keyboard('{Enter}'));
expect(action).not.toHaveBeenCalled();
});

it('Removes event listener on unmount', () => {
const removeEventListenerSpy = jest.spyOn(
window,
'removeEventListener',
);
const { unmount } = renderUseEventListener('click', jest.fn());
expect(removeEventListenerSpy).not.toHaveBeenCalled();
unmount();
expect(removeEventListenerSpy).toHaveBeenCalledTimes(1);
});
});
16 changes: 16 additions & 0 deletions frontend/packages/shared/src/hooks/useEventListener.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useEffect } from 'react';

/**
* Adds an event listener to the given element or the document body if no element is given. The listener is removed on unmount.
* @param eventType The event type to listen for.
* @param action The action to perform when the event is triggered.
*/
export function useEventListener(
eventType: string,
action: () => void,
) {
useEffect(() => {
window.addEventListener(eventType, action);
return () => window.removeEventListener(eventType, action);
}, [eventType, action]);
}
4 changes: 2 additions & 2 deletions frontend/packages/shared/src/hooks/useLocalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ const useWebStorage = <T>(
* @description
* useLocalStorage is a hook that allows you to use local storage the same way you would with useState
*/
export const useLocalStorage = <T, K = string>(key: K, initialValue?: T) =>
useWebStorage<T>(typedLocalStorage, key as string, initialValue);
export const useLocalStorage = <T>(key: string, initialValue?: T) =>
useWebStorage<T>(typedLocalStorage, key, initialValue);
20 changes: 20 additions & 0 deletions frontend/packages/shared/src/hooks/useReactiveLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useCallback } from 'react';
import { typedLocalStorage } from 'app-shared/utils/webStorage';
import { useLocalStorage } from './useLocalStorage';
import { useEventListener } from './useEventListener';

export const useReactiveLocalStorage = <T>(
key: string,
initialValue?: T,
): [T, (newValue: T) => void, () => void] => {
const [value, setValue, removeValue] = useLocalStorage(key, initialValue);

const handleStorageChange = useCallback(() => {
const item = typedLocalStorage.getItem<T>(key);
setValue(item);
}, [key, setValue]);

useEventListener('storage', handleStorageChange);

return [value, setValue, removeValue];
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { createContext, ReactNode, useContext, useEffect, useState } from 'react';
import { previewSignalRHubSubPath } from 'app-shared/api/paths';
import { HubConnection, HubConnectionBuilder, LogLevel } from "@microsoft/signalr";
import { HubConnection, HubConnectionBuilder, LogLevel } from '@microsoft/signalr';

const PreviewConnectionContext = createContext<HubConnection>(null);

Expand Down
2 changes: 1 addition & 1 deletion frontend/packages/shared/src/utils/webStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type TypedStorage = {
removeItem: (key: string) => void;
};

type WebStorage = Pick<Storage, 'setItem' | 'getItem' | 'removeItem'>;
type WebStorage = Pick<Storage, 'setItem' | 'getItem' | 'removeItem' >;

const createWebStorage = (storage: WebStorage): TypedStorage => {
if (!storage) {
Expand Down
Loading

0 comments on commit 190c235

Please sign in to comment.