From 8f430114916645255ba049e255476d5522e9fba8 Mon Sep 17 00:00:00 2001 From: Kevin Hahn Date: Tue, 4 Feb 2025 16:02:24 +0700 Subject: [PATCH] Show loading server status (#1442) * avoid race condition by overwriting the cache rather than removing and adding in during a refresh * move homeView into a home folder * refactor home view and pull the server list out into it's own component * move server into it's own component outside the server list * display a skeleton when servers are loading * show loading items status when the remote projects are still loading but the server status has loaded --- .../FwLite/LcmCrdt/CurrentProjectService.cs | 12 +- frontend/viewer/src/App.svelte | 2 +- .../viewer/src/{ => home}/HomeView.svelte | 155 ++---------------- frontend/viewer/src/home/Server.svelte | 111 +++++++++++++ frontend/viewer/src/home/ServersList.svelte | 89 ++++++++++ 5 files changed, 217 insertions(+), 152 deletions(-) rename frontend/viewer/src/{ => home}/HomeView.svelte (53%) create mode 100644 frontend/viewer/src/home/Server.svelte create mode 100644 frontend/viewer/src/home/ServersList.svelte diff --git a/backend/FwLite/LcmCrdt/CurrentProjectService.cs b/backend/FwLite/LcmCrdt/CurrentProjectService.cs index 79281f8fc..2adbafdab 100644 --- a/backend/FwLite/LcmCrdt/CurrentProjectService.cs +++ b/backend/FwLite/LcmCrdt/CurrentProjectService.cs @@ -15,10 +15,10 @@ public class CurrentProjectService(IServiceProvider services, IMemoryCache memor //only works because PopulateProjectDataCache is called first in the request pipeline public ProjectData ProjectData => memoryCache.Get(CacheKey(Project)) ?? throw new InvalidOperationException("Project data not found, call PopulateProjectDataCache first or use GetProjectData"); - public async ValueTask GetProjectData() + public async ValueTask GetProjectData(bool forceRefresh = false) { var key = CacheKey(Project); - if (!memoryCache.TryGetValue(key, out object? result)) + if (!memoryCache.TryGetValue(key, out object? result) || forceRefresh) { result = await DbContext.ProjectData.AsNoTracking().FirstAsync(); memoryCache.Set(key, result); @@ -81,16 +81,10 @@ public async ValueTask SetupProjectContext(string projectName) public async ValueTask RefreshProjectData() { - RemoveProjectDataCache(); - var projectData = await GetProjectData(); + var projectData = await GetProjectData(true); return projectData; } - private void RemoveProjectDataCache() - { - memoryCache.Remove(CacheKey(Project)); - } - public async Task SetProjectSyncOrigin(Uri? domain, Guid? id) { var originDomain = ProjectData.GetOriginDomain(domain); diff --git a/frontend/viewer/src/App.svelte b/frontend/viewer/src/App.svelte index 41fbb38cd..2879e45aa 100644 --- a/frontend/viewer/src/App.svelte +++ b/frontend/viewer/src/App.svelte @@ -12,7 +12,7 @@ @@ -212,71 +146,7 @@ {/if} - {#each serversStatus as status} - {@const server = status.server} - {@const serverProjects = remoteProjects[server.id]?.filter(p => p.crdt) ?? []} -
-
-

- {server.displayName} Server -

-
- {#if status.loggedIn} -
-
- {#if !serverProjects.length} -

- {#if status.loggedIn} - No projects - {:else} - refreshProjectsAndServers()}/> - {/if} -

- {/if} - {#if loadingServerProjects === server.id} -

- - Loading... -

- {:else} - {#each serverProjects as project} - {@const localProject = matchesProject(projects, project)} - {#if localProject?.crdt} - - -
- -
-
-
- {:else} - void downloadCrdtProject(project, server)} - loading={downloading === project.name}> -
- -
-
- {/if} - {/each} - {/if} -
-
- {/each} - + {#if projects.some(p => p.fwdata)}

Classic FieldWorks Projects

@@ -324,9 +194,10 @@ @apply max-md:!rounded-none; @apply contrast-[0.95]; } - } - .sub-title { - @apply m-2; - @apply text-surface-content/50 text-sm; + + :global(.sub-title) { + @apply m-2; + @apply text-surface-content/50 text-sm; + } } diff --git a/frontend/viewer/src/home/Server.svelte b/frontend/viewer/src/home/Server.svelte new file mode 100644 index 000000000..6f7348333 --- /dev/null +++ b/frontend/viewer/src/home/Server.svelte @@ -0,0 +1,111 @@ + +
+
+

+ {#if server} + {server.displayName} Server + {:else} +

+ {/if} +

+
+ {#if status?.loggedIn} +
+
+ {#if !status || loading} + + + +
+
+
+
+
+
+
+ {:else if !projects.length} +

+ {#if status.loggedIn} + No projects + {:else} + dispatch('refreshAll')}/> + {/if} +

+ {:else} + {#each projects as project} + {@const localProject = matchesProject(localProjects, project)} + {#if localProject?.crdt} + + +
+ +
+
+
+ {:else} + void downloadCrdtProject(project, server)} + loading={downloading === project.name}> +
+ +
+
+ {/if} + {/each} + {/if} +
+
diff --git a/frontend/viewer/src/home/ServersList.svelte b/frontend/viewer/src/home/ServersList.svelte new file mode 100644 index 000000000..41dfca2d0 --- /dev/null +++ b/frontend/viewer/src/home/ServersList.svelte @@ -0,0 +1,89 @@ + + +{#await serversPromise} + +{:then serversStatus} + {#each serversStatus as status} + {@const server = status.server} + {@const serverProjects = remoteProjects[server.id]?.filter(p => p.crdt) ?? []} + refreshServerProjects(server, true)} + on:refreshAll={() => refreshProjectsAndServers()}/> + {/each} +{/await}