From 4b74118fd9b5e94360a94e68a9c750fd98fab178 Mon Sep 17 00:00:00 2001 From: Jake Turner Date: Thu, 15 Jan 2026 19:03:05 +0000 Subject: [PATCH] feat: easy setup wizard --- .../components/InstallActivityFeed.tsx | 2 +- admin/inertia/hooks/useInternetStatus.ts | 2 +- admin/inertia/pages/easy-setup/index.tsx | 52 +++++++------------ .../pages/settings/zim/remote-explorer.tsx | 1 + 4 files changed, 22 insertions(+), 35 deletions(-) diff --git a/admin/inertia/components/InstallActivityFeed.tsx b/admin/inertia/components/InstallActivityFeed.tsx index ab7a9da..d686e64 100644 --- a/admin/inertia/components/InstallActivityFeed.tsx +++ b/admin/inertia/components/InstallActivityFeed.tsx @@ -27,7 +27,7 @@ const InstallActivityFeed: React.FC = ({ activity, cla return (
{withHeader &&

Installation Activity

} -
    +
      {activity.map((activityItem, activityItemIdx) => (
    • { - const [isOnline, setIsOnline] = useState(false); + const [isOnline, setIsOnline] = useState(true); // Initialize true to avoid "offline" flicker on load const { data } = useQuery({ queryKey: ['internetStatus'], queryFn: async () => (await api.getInternetStatus()) ?? false, diff --git a/admin/inertia/pages/easy-setup/index.tsx b/admin/inertia/pages/easy-setup/index.tsx index f420b76..d6f1ce0 100644 --- a/admin/inertia/pages/easy-setup/index.tsx +++ b/admin/inertia/pages/easy-setup/index.tsx @@ -1,6 +1,6 @@ import { Head, router } from '@inertiajs/react' import { useQuery } from '@tanstack/react-query' -import { useState, useMemo } from 'react' +import { useState } from 'react' import AppLayout from '~/layouts/AppLayout' import StyledButton from '~/components/StyledButton' import api from '~/lib/api' @@ -42,9 +42,9 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim refetchOnWindowFocus: false, }) - const availableServices = useMemo(() => { - return props.system.services.filter((service) => !service.installed) - }, [props.system.services]) + const availableServices = props.system.services.filter( + (service) => !service.installed && service.installation_status !== 'installing' + ) const toggleServiceSelection = (serviceName: string) => { setSelectedServices((prev) => @@ -97,26 +97,23 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim try { // All of these ops don't actually wait for completion, they just kick off the process, so we can run them in parallel without awaiting each one sequentially - // const installPromises = selectedServices.map((serviceName) => api.installService(serviceName)) + const installPromises = selectedServices.map((serviceName) => api.installService(serviceName)) - // await Promise.all(installPromises) + await Promise.all(installPromises) - // const downloadPromises = [ - // ...selectedMapCollections.map((slug) => api.downloadMapCollection(slug)), - // ...selectedZimCollections.map((slug) => api.downloadZimCollection(slug)), - // ] + const downloadPromises = [ + ...selectedMapCollections.map((slug) => api.downloadMapCollection(slug)), + ...selectedZimCollections.map((slug) => api.downloadZimCollection(slug)), + ] - // await Promise.all(downloadPromises) + await Promise.all(downloadPromises) addNotification({ type: 'success', message: 'Setup wizard completed! Your selections are being processed.', }) - // Wait a moment then redirect to completion page to show progress - setTimeout(() => { - router.visit('/easy-setup/complete') - }, 2000) + router.visit('/easy-setup/complete') } catch (error) { console.error('Error during setup:', error) addNotification({ @@ -226,26 +223,17 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim ) : (
      {availableServices.map((service) => { - const selectedOrInstalled = - selectedServices.includes(service.service_name) || - service.installed || - service.installation_status === 'installing' - - const installedOrInstalling = - service.installed || service.installation_status === 'installing' + const selected = selectedServices.includes(service.service_name) return (
      - !installedOrInstalling && toggleServiceSelection(service.service_name) - } + onClick={() => toggleServiceSelection(service.service_name)} className={classNames( 'p-6 rounded-lg border-2 cursor-pointer transition-all', - selectedOrInstalled + selected ? 'border-desert-green bg-desert-green bg-opacity-10 shadow-md text-white' - : 'border-desert-stone-light bg-white hover:border-desert-green hover:shadow-sm', - installedOrInstalling ? 'opacity-50 cursor-not-allowed' : '' + : 'border-desert-stone-light bg-white hover:border-desert-green hover:shadow-sm' )} >
      @@ -256,7 +244,7 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim

      {service.description} @@ -265,12 +253,10 @@ export default function EasySetupWizard(props: { system: { services: ServiceSlim

      - {selectedOrInstalled ? ( + {selected ? ( ) : (
      diff --git a/admin/inertia/pages/settings/zim/remote-explorer.tsx b/admin/inertia/pages/settings/zim/remote-explorer.tsx index 20cd1d4..5c66b6c 100644 --- a/admin/inertia/pages/settings/zim/remote-explorer.tsx +++ b/admin/inertia/pages/settings/zim/remote-explorer.tsx @@ -230,6 +230,7 @@ export default function ZimRemoteExplorer() { key={collection.slug} collection={collection} onClick={(collection) => confirmDownload(collection)} + size='large' /> ))}