From 02fd4906e78bc430e1a06a71d217569c920d4c01 Mon Sep 17 00:00:00 2001 From: Petr Kadlec <67226666+kapetr@users.noreply.github.com> Date: Tue, 21 Jan 2025 13:21:49 +0100 Subject: [PATCH] feat(app-builder): app loading update (#188) - fixes: visible app with error until the source code is fully loaded - updates: loading animation style according to the design Signed-off-by: Petr Kadlec --- src/modules/api-keys/api/useApiKeys.ts | 16 +++++++++ src/modules/api-keys/api/useCreateApiKey.ts | 16 +++++++++ .../builder/ArtifactSharedIframe.module.scss | 35 +++++++++++++++++++ .../apps/builder/ArtifactSharedIframe.tsx | 13 ++++++- 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/modules/api-keys/api/useApiKeys.ts b/src/modules/api-keys/api/useApiKeys.ts index 0287e08..043a95d 100644 --- a/src/modules/api-keys/api/useApiKeys.ts +++ b/src/modules/api-keys/api/useApiKeys.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2025 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { ApiKeysListQuery } from '@/app/api/api-keys/types'; import { useQuery } from '@tanstack/react-query'; import { useApiKeysQueries } from './queries'; diff --git a/src/modules/api-keys/api/useCreateApiKey.ts b/src/modules/api-keys/api/useCreateApiKey.ts index 1946626..27a633c 100644 --- a/src/modules/api-keys/api/useCreateApiKey.ts +++ b/src/modules/api-keys/api/useCreateApiKey.ts @@ -1,3 +1,19 @@ +/** + * Copyright 2025 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { createApiKey } from '@/app/api/api-keys'; import { ApiKey, ApiKeysCreateBody } from '@/app/api/api-keys/types'; import { useAppContext } from '@/layout/providers/AppProvider'; diff --git a/src/modules/apps/builder/ArtifactSharedIframe.module.scss b/src/modules/apps/builder/ArtifactSharedIframe.module.scss index 3486d72..8b9cac7 100644 --- a/src/modules/apps/builder/ArtifactSharedIframe.module.scss +++ b/src/modules/apps/builder/ArtifactSharedIframe.module.scss @@ -16,6 +16,8 @@ @use 'styles/common' as *; +$loading-size: rem(170px); + .root { position: relative; background-color: $layer-02; @@ -24,9 +26,42 @@ justify-content: center; align-items: center; z-index: 1; +} +.loading { + position: absolute; + inset: 0; + &.empty { + background-color: $layer-02; + } :global(.#{$prefix}--loading-overlay) { position: absolute; + + :global(.#{$prefix}--loading) { + block-size: $loading-size; + inline-size: $loading-size; + + &::after { + content: ''; + display: block; + position: absolute; + inset: 0; + z-index: -1; + block-size: $loading-size; + inline-size: $loading-size; + border-radius: 50%; + border: 19px solid $background-active; + } + + svg { + circle { + stroke-width: 11; + stroke-dasharray: 150, 260; + stroke-dashoffset: 40; + r: 44; + } + } + } } } .app { diff --git a/src/modules/apps/builder/ArtifactSharedIframe.tsx b/src/modules/apps/builder/ArtifactSharedIframe.tsx index 8691e1e..d2a2259 100644 --- a/src/modules/apps/builder/ArtifactSharedIframe.tsx +++ b/src/modules/apps/builder/ArtifactSharedIframe.tsx @@ -43,6 +43,7 @@ export function ArtifactSharedIframe({ }: Props) { const iframeRef = useRef(null); const [state, setState] = useState(State.LOADING); + const appliedCodeRef = useRef(null); const { appliedTheme: theme } = useTheme(); const { project, organization } = useAppContext(); const [iframeLoadCount, setIframeLoadCount] = useState(0); @@ -61,6 +62,8 @@ export function ArtifactSharedIframe({ useEffect(() => { if (isPending) return; + appliedCodeRef.current = sourceCode; + postMessage({ type: PostMessageType.UPDATE_STATE, stateChange: { @@ -166,7 +169,15 @@ export function ArtifactSharedIframe({ ) : ( - (state === State.LOADING || isPending) && + (state === State.LOADING || isPending) && ( +
+ +
+ ) )} );