From 693a371d61fa7f7e1543f58e809511cf7a2d507f Mon Sep 17 00:00:00 2001 From: Truman Gao <106889354+tdgao@users.noreply.github.com> Date: Sun, 12 Apr 2026 15:38:08 -0600 Subject: [PATCH] feat: server management in app (#5628) * start new server settings tabs * update properties tab to match design * better stying in general tab * feat: add suffix input for hostname field * implement tables for allocations and DNS records * add tags for dns record type * small gap adjustment * polish advanced page * adjust properties page hierarchy * fix searching properties, empty state and projection radius appearing * pnpm prepr * update copy to match designs * fix suffix input component * style fixes and match heading size * small fix * fix search allocations placeholder * adjust table styles * move all installation settings helper text to below input * update icon to use overflow menu buttons * fix modal to be consistent * open advanced properties when search * remove other and custom properties, and update styles * remove hide/show all java versions * handle mc 26 * refactor: move server settings pages into /ui and add app ServerSettingsModal * hook up server pages for app * add server page header to app * hook up server settings modal * use large size * fix card box shadow style * fix hostname input for app * fix app/website card containers * implement external tabs for billing and admin billing * fix save banner fixed to parent instead of page body * remove unused prop to FriendsList causing warning in app * fix client-only not available for app * fix bottom cut off * wire node auth * implement full copy buttons * dedup copy button tailwind styles * fix hover class not working in @apply * fix spacing * fix error validation styles * apply consistent styles and spacing * feat: update hosting server card (#5609) * fix type errors * fix some stylesheets not imported for storybook * add server listing stories * add fix for frontend stylesheet imports * remove props. * convert copy code to use tailwind * update server listing component styles * update server info label styles * start status/player count info label, more style updates and fixes * add new server card buttons * hook up server cards and implement updated styles * hook up on download button * fix tauri throwing error when api returns 204 No Content * hook up purchase server modal in app * fix upgrading state loading icon * pnpm prepr * filter out servers past 30 days after cancellation * do not apply opacity on lock or spiner icons * fix disabled server icon background * update pending change stage * handle known suspension states * refactor: reduce code duplication for server listing * update disabled state text color * fix loading icon color * clean up copy * fix disabled opacity for server card * update server listing files kept to be countdown * implement resubscribe modal * implement proper provisioning state for resubscribe * fix duplicate attribute and pnpm prepr * feat: add shared UI package auth DI * feat: update purchase server flow (#5714) * implement server list empty state component * fix stories and adjust spacing * implement select plan design refresh * implement auth for empty server list * use refs instead of reactive * pnpm prepr * fix auth usage for empty servers list * move app auth provider setup to src/providers/setup * pnpm prepr * fix max height * style fix * fix getCreds no auth is blocking api client * implement servers guest plan modal and signin which redirects back to modal's next step * refactor guest plan select logic into provider * implement sign in or create account popup * remove force empty serverList * add download button for suspended mod and generic * add handling for when user logs out * QA pass style fixes * more consistent page styles * fix duplicate export * refactor: remove all fallback stuff from resubscribe modal * implement shared download latest backup util * i18n pass * pnpm prepr * fix region being selected if ping failed * pnpm prepr * feat: servers in app finalization (#5744) * feat: start on shared console implementation into logs and overview pages * fix: terminal gap issues * feat: swap word wrap for full screen * fix: stats cards alignment * fix: stats * feat: fix console clear + remove copy * fix: lint * fix: use reset not clear * feat: shared server header & overview page for app and website (#5736) * feat: implement shared server header for app and website * feat: implement wrapped overview page with shared composable and hook it up * pnpm prepr * fix: bugs * qa: cleanup * feat: root.vue shared layout * feat: delete old options pages + fix discovery frontend * fix: discovery * fix: misc style/layout issues * fix page padding * fix: modal height jankiness * feat: implement server install content in app and server setup modal with DI * fix: spacing * remove servers in app feature flag * Revert "remove servers in app feature flag" This reverts commit 86e284c4bdd6fa42c3c8fbaf1efbec41f4d1c6d2. * fix: qa * feat: remove legacy components from apps/frontend/src/components/ui/servers --------- Co-authored-by: Calum H. (IMB11) * qa pass (#5738) * fix: qa * feat: qa * fix: server icon fetch fails due to global node auth race condition overriding each other * fix: lint * fix: server icon upload/sync and centralize logic * fix: server settings modal not closing for server reset * fix: better server sorting * feat: copy address in server listing card * fix: notification panel in modal and when overlapping with action bar * fix: empty server list empty state flashing when refresh, fixed by adding isReady auth flag * feat: use floating action bar for save banner * fix: saving state in save bar * fix: edit server icon styling * fix: confirm modal to have consistent buttons * feat: loading animation for server panel + caching improvements for app * pnpm prepr * feat: search page deduplication (#5754) * fix: action bar behind modal * fix: remove warning modal for stopping * fix: server cards states * we hate webkit we hate webkit * fix: update allocation creation to not use modal * fix: properties tab spacing and styles * feat: add files tab copy * fix: advanced properties icon * fix: remove back to all servers link * feat: add files tab link in copy * fix: server header styles to be consistent with instance * fix: add header icons back * feat: update instance settings icon to be consistent * fix: icon container * feat: upload state persistence across tabs * fix: server labels text wrapping * fix: use surface-5 border * fix: loading spinner showing with onboarding below * feat: new server button shows purchase modal in website * fix: billing page not showing quarterly interval * fix: server downgrade not showing updated subscription notification * fix: server settings invalidate saved state and remove server context provider since its already provided in the page * pnpm prepr * add stripe publishable key to app build * feat: console highlighting * fix: rename servers title to modrinth hosting * feat: search fix * fix: qa/styles * fix: ip click active and remove power dont ask again * fix: qa * feat: highlighting fix console * fix: disable conflicts action * fix: error dismiss bug * feat: modal clarification * fix: files perms issue * fix: lint * feat: modal fix * enable show uptime * fix: add loading state to edit server icon * fix: notification panel take in has sidebar from settings * fix: consistency pass on app settings * fix: consistency pass on instance settings * pnpm prepr * fix: nagivate to billing button in app to go to website * fix: stripe return url in app causing app to open modrinth.com in tauri * refactor: better show polling UI code * fix: new server polling comparison to use server ids instead of length * fix: buttonstyled story * fix: button styling * fix: content.vue regression * feat: project url redirects * fix: breadcrumbs * fix: purchase with newly added card * fix: console ordering problems * fix: app-frontend missing env config and staging environment * fix: log syncing for instances and server panel accidentally * fix: QA issues * fix: server page loading state * fix: stats card logic * fix: lint * fix: qa * fix: console height padding * fix: terminal padding + loading indicator * feat: update medal server listing styling * fix: no upgrade button for medal server listing in app * fix: go to overview instead of content tab after onboarding * fix: qa * fix: teleport modals to body * fix: logs tab + qa * fix: local storage for user preferences * fix: qa loading indic * feat: considitonal debug and trace * fix: jump to top on install bug * feat: swap out server hard drive icon to server stack icon * feat: servers in app feature flag default true * fix: highlight row ufll * fix: webkit thing onto a tag * fix: input field * fix: clear fix * fix: lint * fix: fmt * feat: improve share modal and bring it back for sharing log * pnpm prepr * fix: menu overflowing * feat: remove servers in app feature flag * fix: server stat charts no longer showing color * fix: library nav no primary state * fix: better modal height and width * fix: highlighting bugs * fix: empty states * fix: delay import to fix overview page slow load on MacOS * fix: medal server listing too bright on light mode * fix: admon analysis + fix logs * fix: bug * fix: clear purchase intent from sign-in after closing modal * performance: improve server manage stats loading by splitting reactivity * fix: deploy + admon + disable highlighting * fix: clippy --------- Co-authored-by: tdgao Co-authored-by: Truman Gao <106889354+tdgao@users.noreply.github.com> * feat: temp wrangler * fix: lint * fix: logs upload * fix: console empty state and admon regressions * fix: fields * feat: log deleting + prefetch for Logs.vue * feat: move delete before share * feat: clear endpoint * feat: we ball! --------- Co-authored-by: Calum H. Co-authored-by: Calum H. (IMB11) --- .github/workflows/theseus-build.yml | 3 + .vscode/settings.json | 4 +- apps/app-frontend/src/App.vue | 85 +- .../src/assets/stylesheets/global.scss | 75 +- .../src/components/ui/NavButton.vue | 1 + .../src/components/ui/SearchCard.vue | 142 -- .../src/components/ui/URLConfirmModal.vue | 33 +- .../ui/instance_settings/GeneralSettings.vue | 201 +- .../ui/instance_settings/HooksSettings.vue | 34 +- .../ui/instance_settings/JavaSettings.vue | 14 +- .../ui/instance_settings/WindowSettings.vue | 20 +- .../components/ui/modal/AppSettingsModal.vue | 2 +- .../ui/settings/AppearanceSettings.vue | 32 +- .../ui/settings/DefaultInstanceSettings.vue | 222 +-- .../ui/settings/FeatureFlagSettings.vue | 42 +- .../components/ui/settings/JavaSettings.vue | 26 +- .../ui/settings/LanguageSettings.vue | 2 +- .../ui/settings/PrivacySettings.vue | 12 +- .../settings/ResourceManagementSettings.vue | 132 +- .../src/composables/useInstanceConsole.ts | 92 + apps/app-frontend/src/config.ts | 18 + apps/app-frontend/src/helpers/events.js | 20 + apps/app-frontend/src/helpers/logs.js | 10 + apps/app-frontend/src/pages/Browse.vue | 1141 +++++------- apps/app-frontend/src/pages/Servers.vue | 26 + .../src/pages/hosting/manage/Backups.vue | 9 + .../src/pages/hosting/manage/Content.vue | 7 + .../src/pages/hosting/manage/Files.vue | 7 + .../src/pages/hosting/manage/Index.vue | 113 ++ .../src/pages/hosting/manage/Overview.vue | 7 + .../src/pages/hosting/manage/index.js | 7 + apps/app-frontend/src/pages/index.js | 3 +- .../app-frontend/src/pages/instance/Index.vue | 17 +- apps/app-frontend/src/pages/instance/Logs.vue | 642 ++----- .../src/pages/instance/Worlds.vue | 33 +- apps/app-frontend/src/providers/setup/auth.ts | 4 +- .../providers/setup/server-install-content.ts | 393 ++++ apps/app-frontend/src/routes.js | 53 +- apps/app-frontend/src/store/theme.ts | 1 - apps/app-frontend/tsconfig.app.json | 4 +- apps/app-frontend/vite.config.ts | 20 +- apps/app/build.rs | 2 + apps/app/capabilities/plugins.json | 7 +- apps/app/src/api/logs.rs | 17 + apps/app/src/main.rs | 3 + apps/app/tauri.conf.json | 6 +- .../src/assets/styles/components.scss | 17 + apps/frontend/src/assets/styles/global.scss | 6 +- .../servers => brand}/ModrinthServersIcon.vue | 0 .../notice => admin}/AssignNoticeModal.vue | 0 .../components/ui/servers/LoaderSelector.vue | 96 - .../ui/servers/LoaderSelectorCard.vue | 68 - .../src/components/ui/servers/LogLine.vue | 91 - .../ui/servers/PanelServerActionButton.vue | 276 --- .../ui/servers/PanelServerStatus.vue | 75 - .../components/ui/servers/PanelSpinner.vue | 22 - .../components/ui/servers/PanelTerminal.vue | 1414 --------------- .../PlatformChangeModpackVersionModal.vue | 163 -- .../ui/servers/PlatformVersionSelectModal.vue | 538 ------ .../src/components/ui/servers/SaveBanner.vue | 90 - .../components/ui/servers/ServerSidebar.vue | 52 - .../src/components/ui/servers/ServerStats.vue | 256 --- .../ui/servers/TeleportOverflowMenu.vue | 438 ----- .../ui/servers/icons/ChevronDownIcon.vue | 16 - .../ui/servers/icons/ChevronUpIcon.vue | 16 - .../ui/servers/icons/CodeFileIcon.vue | 18 - .../ui/servers/icons/CogFolderIcon.vue | 26 - .../components/ui/servers/icons/EarthIcon.vue | 20 - .../ui/servers/icons/FullscreenIcon.vue | 19 - .../ui/servers/icons/ImageFileIcon.vue | 18 - .../ui/servers/icons/LoaderIcon.vue | 15 - .../ui/servers/icons/LoadingIcon.vue | 9 - .../ui/servers/icons/MinimizeIcon.vue.vue | 19 - .../ui/servers/icons/PanelErrorIcon.vue | 16 - .../components/ui/servers/icons/SlashIcon.vue | 10 - .../ui/servers/icons/TextFileIcon.vue | 20 - .../src/components/ui/servers/icons/Timer.vue | 17 - .../ui/servers/notice/NoticeDashboardItem.vue | 127 -- .../src/components/ui/thread/ThreadView.vue | 3 +- .../composables/servers/use-server-image.ts | 131 -- apps/frontend/src/error.vue | 1 + apps/frontend/src/layouts/default.vue | 7 +- apps/frontend/src/locales/en-US/index.json | 74 +- .../frontend/src/pages/admin/billing/[id].vue | 4 +- .../src/pages/admin/servers/notices.vue | 2 +- apps/frontend/src/pages/discover.vue | 1 - .../src/pages/discover/[type]/index.vue | 1151 +++--------- apps/frontend/src/pages/hosting/index.vue | 2 +- .../src/pages/hosting/manage/[id].vue | 1612 +---------------- .../src/pages/hosting/manage/[id]/index.vue | 729 +------- .../src/pages/hosting/manage/[id]/options.vue | 69 - .../hosting/manage/[id]/options/billing.vue | 12 - .../hosting/manage/[id]/options/index.vue | 335 ---- .../hosting/manage/[id]/options/info.vue | 154 -- .../hosting/manage/[id]/options/network.vue | 507 ------ .../manage/[id]/options/preferences.vue | 113 -- .../manage/[id]/options/properties.vue | 292 --- .../hosting/manage/[id]/options/startup.vue | 287 --- .../src/pages/hosting/manage/index.vue | 3 +- .../src/pages/settings/billing/index.vue | 149 +- apps/frontend/src/providers/setup/auth.ts | 1 + .../src/providers/setup/page-context.ts | 1 + apps/frontend/src/store/console.ts | 165 +- apps/frontend/wrangler.jsonc | 4 +- packages/api-client/CLAUDE.md | 16 + .../api-client/src/core/abstract-client.ts | 4 + .../api-client/src/features/panel-version.ts | 4 +- .../api-client/src/modules/archon/types.ts | 11 + packages/api-client/src/modules/index.ts | 6 + .../api-client/src/modules/kyros/files/v0.ts | 77 + .../api-client/src/modules/kyros/logs/v1.ts | 17 + .../src/modules/mclogs/insights/v1.ts | 19 + .../api-client/src/modules/mclogs/logs/v1.ts | 19 + .../api-client/src/modules/mclogs/types.ts | 63 + packages/api-client/src/modules/types.ts | 1 + packages/api-client/src/platform/tauri.ts | 34 +- packages/app-lib/.env.prod | 1 + .../app-lib/.env.prod-with-staging-archon | 12 + packages/app-lib/.env.staging | 1 + packages/app-lib/src/api/logs.rs | 20 + packages/app-lib/src/event/mod.rs | 23 + packages/app-lib/src/state/process.rs | 335 ++-- packages/assets/generated-icons.ts | 8 +- packages/assets/icons/server-stack.svg | 18 + packages/assets/icons/server.svg | 19 +- packages/assets/icons/wrap-text.svg | 7 + packages/assets/styles/classes.scss | 2 - packages/ui/.storybook/preview.ts | 72 +- packages/ui/CLAUDE.md | 14 + packages/ui/package.json | 5 +- .../ui/src/components/base/BaseTerminal.vue | 221 ++- .../ui/src/components/base/ButtonStyled.vue | 7 +- .../components/base/CollapsibleAdmonition.vue | 196 ++ .../src/components/base/ContentPageHeader.vue | 46 +- packages/ui/src/components/base/CopyCode.vue | 45 +- .../ui/src/components/base/FilterPills.vue | 53 + .../src/components/base/FloatingActionBar.vue | 2 +- packages/ui/src/components/base/NavTabs.vue | 2 +- packages/ui/src/components/base/Table.vue | 10 +- .../components/base/TeleportOverflowMenu.vue | 6 +- packages/ui/src/components/base/index.ts | 4 + .../billing/ModalBasedServerPlan.vue | 149 -- .../billing/ModrinthServersPurchaseModal.vue | 54 +- .../components/billing/ResubscribeModal.vue | 287 +++ .../billing/ServersGuestPlanModal.vue | 169 ++ .../billing/ServersPurchase0Plan.vue | 327 +++- .../billing/ServersPurchase1Region.vue | 13 +- .../billing/ServersPurchase3Review.vue | 11 +- .../billing/ServersUpgradeModalWrapper.vue | 40 +- packages/ui/src/components/billing/index.ts | 2 + .../ui/src/components/modal/ConfirmModal.vue | 16 +- .../ui/src/components/modal/ShareModal.vue | 171 +- .../ui/src/components/modal/TabbedModal.vue | 38 +- .../components/modal/UploadProgressModal.vue | 50 + packages/ui/src/components/modal/index.ts | 1 + .../src/components/nav/NotificationPanel.vue | 12 +- .../components/project/card/ProjectCard.vue | 3 +- .../components/search/SearchFilterControl.vue | 8 +- .../ui/src/components/servers/SaveBanner.vue | 68 + .../src/components/servers/ServerListing.vue | 594 ++++-- .../servers/ServerSettingsModal.vue | 232 +++ .../components/servers/ServerSetupModal.vue | 63 +- .../edit-server-icon/EditServerIcon.vue | 264 +++ .../components/servers/icons/ServerIcon.vue | 21 +- packages/ui/src/components/servers/index.ts | 7 +- .../components/servers/labels/Separator.vue | 3 + .../servers/labels/ServerGameLabel.vue | 37 +- .../servers/labels/ServerInfoLabels.vue | 16 +- .../servers/labels/ServerLoaderLabel.vue | 31 +- .../servers/labels/ServerPlayerCount.vue | 17 + .../servers/labels/ServerSubdomainLabel.vue | 22 +- .../servers/labels/ServerUptimeLabel.vue | 10 +- .../marketing/MedalServerCountdown.vue | 34 +- .../servers/marketing/MedalServerListing.vue | 302 +-- .../src/components/servers/marketing/index.ts | 1 + .../server-header/PanelServerActionButton.vue | 64 + .../server-header/PanelServerOverflowMenu.vue | 85 + .../server-header/ServerManageHeader.vue | 179 ++ .../components/servers/server-header/index.ts | 3 + .../server-header/use-server-power-action.ts | 80 + .../server-list-empty/ServerListEmpty.vue | 313 ++++ .../grid-images/aircraft.png | Bin 0 -> 21840 bytes .../server-list-empty/grid-images/alex's.png | Bin 0 -> 19570 bytes .../grid-images/artifacts.png | Bin 0 -> 704 bytes .../server-list-empty/grid-images/biomes.png | Bin 0 -> 1167 bytes .../server-list-empty/grid-images/catac.png | Bin 0 -> 12710 bytes .../server-list-empty/grid-images/cobble.png | Bin 0 -> 17701 bytes .../grid-images/comforts.png | Bin 0 -> 990 bytes .../server-list-empty/grid-images/create.png | Bin 0 -> 22270 bytes .../server-list-empty/grid-images/create1.png | Bin 0 -> 20019 bytes .../server-list-empty/grid-images/create2.png | Bin 0 -> 20355 bytes .../server-list-empty/grid-images/create3.png | Bin 0 -> 21715 bytes .../server-list-empty/grid-images/creeper.png | Bin 0 -> 36105 bytes .../server-list-empty/grid-images/friends.png | Bin 0 -> 18513 bytes .../server-list-empty/grid-images/geo.png | Bin 0 -> 18242 bytes .../grid-images/naturalist.png | Bin 0 -> 22716 bytes .../server-list-empty/grid-images/seasons.png | Bin 0 -> 16140 bytes .../grid-images/travellers.png | Bin 0 -> 20052 bytes .../server-list-empty/grid-images/tree.png | Bin 0 -> 23739 bytes .../server-list-empty/grid-images/yum1.png | Bin 0 -> 14167 bytes .../server-list-empty/grid-images/yum2.png | Bin 0 -> 15751 bytes .../server-list-empty/grid-images/yum3.png | Bin 0 -> 13945 bytes .../server-list-empty/grid-images/yung.png | Bin 0 -> 15455 bytes .../components/settings/LanguageSelector.vue | 4 +- packages/ui/src/composables/index.ts | 5 + packages/ui/src/composables/modal-stack.ts | 17 +- packages/ui/src/composables/server-backup.ts | 54 + packages/ui/src/composables/server-console.ts | 351 ++++ .../composables/server-manage-core-runtime.ts | 443 +++++ packages/ui/src/composables/stripe.ts | 51 +- packages/ui/src/composables/terminal.ts | 24 +- .../ui/src/composables/use-server-image.ts | 134 ++ .../ui/src/composables}/use-server-project.ts | 9 +- packages/ui/src/layouts/index.ts | 3 + .../shared/browse-tab/composables/index.ts | 1 + .../composables/use-browse-search.ts | 311 ++++ .../src/layouts/shared/browse-tab/header.vue | 63 + .../ui/src/layouts/shared/browse-tab/index.ts | 6 + .../src/layouts/shared/browse-tab/layout.vue | 262 +++ .../browse-tab/providers/browse-manager.ts | 106 ++ .../shared/browse-tab/providers/index.ts | 1 + .../src/layouts/shared/browse-tab/sidebar.vue | 177 ++ .../ui/src/layouts/shared/browse-tab/types.ts | 46 + .../components/ConsoleActionButtons.vue | 70 + .../console/components/ConsoleFilterPills.vue | 60 + .../console/composables/console-filtering.ts | 97 + .../shared/console/composables/index.ts | 9 + .../composables/log-highlight-addon.ts | 242 +++ .../shared/console/composables/log-level.ts | 14 + .../ui/src/layouts/shared/console/index.ts | 3 + .../ui/src/layouts/shared/console/layout.vue | 357 ++++ .../console/providers/console-manager.ts | 36 + .../layouts/shared/console/providers/index.ts | 1 + .../ui/src/layouts/shared/console/types.ts | 21 + .../modals/ConfirmModpackUpdateModal.vue | 14 +- .../src/layouts/shared/content-tab/layout.vue | 6 +- .../components/FileOperationAdmonitions.vue | 79 +- .../components/editor/FileEditor.vue | 18 +- .../src/layouts/shared/files-tab/layout.vue | 2 - .../composables/use-installation-form.ts | 26 +- .../shared/installation-settings/layout.vue | 243 +-- .../providers/installation-settings.ts | 11 +- .../layouts/shared/server-settings/index.ts | 3 + .../shared/server-settings/pages/advanced.vue | 391 ++++ .../shared/server-settings/pages/general.vue | 288 +++ .../shared/server-settings/pages/index.ts | 5 + .../server-settings/pages/installation.vue | 138 +- .../shared/server-settings/pages/network.vue | 411 +++++ .../server-settings/pages/properties.vue | 560 ++++++ .../shared/server-settings/providers/index.ts | 1 + .../providers/server-settings.ts | 22 + .../layouts/shared/server-settings/tabs.ts | 82 + .../hosting/manage/[id]/onboarding.vue | 28 +- .../manage/components/ServerManageStats.vue | 262 +++ .../wrapped/hosting/manage/content.vue | 167 +- .../layouts/wrapped/hosting/manage/files.vue | 64 +- .../layouts/wrapped/hosting/manage/index.vue | 804 +++++++- .../wrapped/hosting/manage/overview.vue | 123 ++ .../layouts/wrapped/hosting/manage/root.vue | 1580 ++++++++++++++++ packages/ui/src/layouts/wrapped/index.ts | 2 + packages/ui/src/locales/en-US/index.json | 383 +++- packages/ui/src/providers/auth.ts | 2 + .../src/providers/hosting-purchase-intent.ts | 189 ++ packages/ui/src/providers/index.ts | 2 + packages/ui/src/providers/page-context.ts | 1 + packages/ui/src/providers/server-context.ts | 16 +- .../ui/src/providers/server-settings-modal.ts | 17 + .../src/stories/base/ButtonStyled.stories.ts | 210 ++- .../src/stories/modal/ShareModal.stories.ts | 67 + .../modal/UploadProgressModal.stories.ts | 95 + .../stories/servers/EditServerIcon.stories.ts | 94 + .../servers/MedalServerListing.stories.ts | 85 + .../src/stories/servers/SaveBanner.stories.ts | 37 + .../servers/ServerListEmpty.stories.ts | 16 + .../stories/servers/ServerListing.stories.ts | 158 ++ packages/ui/src/utils/common-messages.ts | 3 +- pnpm-lock.yaml | 172 +- turbo.jsonc | 9 +- 278 files changed, 15974 insertions(+), 12608 deletions(-) delete mode 100644 apps/app-frontend/src/components/ui/SearchCard.vue create mode 100644 apps/app-frontend/src/composables/useInstanceConsole.ts create mode 100644 apps/app-frontend/src/config.ts create mode 100644 apps/app-frontend/src/pages/Servers.vue create mode 100644 apps/app-frontend/src/pages/hosting/manage/Backups.vue create mode 100644 apps/app-frontend/src/pages/hosting/manage/Content.vue create mode 100644 apps/app-frontend/src/pages/hosting/manage/Files.vue create mode 100644 apps/app-frontend/src/pages/hosting/manage/Index.vue create mode 100644 apps/app-frontend/src/pages/hosting/manage/Overview.vue create mode 100644 apps/app-frontend/src/pages/hosting/manage/index.js create mode 100644 apps/app-frontend/src/providers/setup/server-install-content.ts rename apps/frontend/src/components/{ui/servers => brand}/ModrinthServersIcon.vue (100%) rename apps/frontend/src/components/ui/{servers/notice => admin}/AssignNoticeModal.vue (100%) delete mode 100644 apps/frontend/src/components/ui/servers/LoaderSelector.vue delete mode 100644 apps/frontend/src/components/ui/servers/LoaderSelectorCard.vue delete mode 100644 apps/frontend/src/components/ui/servers/LogLine.vue delete mode 100644 apps/frontend/src/components/ui/servers/PanelServerActionButton.vue delete mode 100644 apps/frontend/src/components/ui/servers/PanelServerStatus.vue delete mode 100644 apps/frontend/src/components/ui/servers/PanelSpinner.vue delete mode 100644 apps/frontend/src/components/ui/servers/PanelTerminal.vue delete mode 100644 apps/frontend/src/components/ui/servers/PlatformChangeModpackVersionModal.vue delete mode 100644 apps/frontend/src/components/ui/servers/PlatformVersionSelectModal.vue delete mode 100644 apps/frontend/src/components/ui/servers/SaveBanner.vue delete mode 100644 apps/frontend/src/components/ui/servers/ServerSidebar.vue delete mode 100644 apps/frontend/src/components/ui/servers/ServerStats.vue delete mode 100644 apps/frontend/src/components/ui/servers/TeleportOverflowMenu.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/ChevronDownIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/ChevronUpIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/CodeFileIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/CogFolderIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/EarthIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/FullscreenIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/ImageFileIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/LoaderIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/LoadingIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/MinimizeIcon.vue.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/PanelErrorIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/SlashIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/TextFileIcon.vue delete mode 100644 apps/frontend/src/components/ui/servers/icons/Timer.vue delete mode 100644 apps/frontend/src/components/ui/servers/notice/NoticeDashboardItem.vue delete mode 100644 apps/frontend/src/composables/servers/use-server-image.ts delete mode 100644 apps/frontend/src/pages/hosting/manage/[id]/options.vue delete mode 100644 apps/frontend/src/pages/hosting/manage/[id]/options/billing.vue delete mode 100644 apps/frontend/src/pages/hosting/manage/[id]/options/index.vue delete mode 100644 apps/frontend/src/pages/hosting/manage/[id]/options/info.vue delete mode 100644 apps/frontend/src/pages/hosting/manage/[id]/options/network.vue delete mode 100644 apps/frontend/src/pages/hosting/manage/[id]/options/preferences.vue delete mode 100644 apps/frontend/src/pages/hosting/manage/[id]/options/properties.vue delete mode 100644 apps/frontend/src/pages/hosting/manage/[id]/options/startup.vue create mode 100644 packages/api-client/src/modules/kyros/logs/v1.ts create mode 100644 packages/api-client/src/modules/mclogs/insights/v1.ts create mode 100644 packages/api-client/src/modules/mclogs/logs/v1.ts create mode 100644 packages/api-client/src/modules/mclogs/types.ts create mode 100644 packages/app-lib/.env.prod-with-staging-archon create mode 100644 packages/assets/icons/server-stack.svg create mode 100644 packages/assets/icons/wrap-text.svg create mode 100644 packages/ui/src/components/base/CollapsibleAdmonition.vue create mode 100644 packages/ui/src/components/base/FilterPills.vue delete mode 100644 packages/ui/src/components/billing/ModalBasedServerPlan.vue create mode 100644 packages/ui/src/components/billing/ResubscribeModal.vue create mode 100644 packages/ui/src/components/billing/ServersGuestPlanModal.vue create mode 100644 packages/ui/src/components/modal/UploadProgressModal.vue create mode 100644 packages/ui/src/components/servers/SaveBanner.vue create mode 100644 packages/ui/src/components/servers/ServerSettingsModal.vue create mode 100644 packages/ui/src/components/servers/edit-server-icon/EditServerIcon.vue create mode 100644 packages/ui/src/components/servers/labels/Separator.vue create mode 100644 packages/ui/src/components/servers/labels/ServerPlayerCount.vue rename {apps/frontend/src/components/ui => packages/ui/src/components}/servers/marketing/MedalServerCountdown.vue (80%) create mode 100644 packages/ui/src/components/servers/server-header/PanelServerActionButton.vue create mode 100644 packages/ui/src/components/servers/server-header/PanelServerOverflowMenu.vue create mode 100644 packages/ui/src/components/servers/server-header/ServerManageHeader.vue create mode 100644 packages/ui/src/components/servers/server-header/index.ts create mode 100644 packages/ui/src/components/servers/server-header/use-server-power-action.ts create mode 100644 packages/ui/src/components/servers/server-list-empty/ServerListEmpty.vue create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/aircraft.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/alex's.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/artifacts.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/biomes.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/catac.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/cobble.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/comforts.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/create.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/create1.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/create2.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/create3.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/creeper.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/friends.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/geo.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/naturalist.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/seasons.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/travellers.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/tree.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/yum1.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/yum2.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/yum3.png create mode 100644 packages/ui/src/components/servers/server-list-empty/grid-images/yung.png create mode 100644 packages/ui/src/composables/server-backup.ts create mode 100644 packages/ui/src/composables/server-console.ts create mode 100644 packages/ui/src/composables/server-manage-core-runtime.ts create mode 100644 packages/ui/src/composables/use-server-image.ts rename {apps/frontend/src/composables/servers => packages/ui/src/composables}/use-server-project.ts (70%) create mode 100644 packages/ui/src/layouts/shared/browse-tab/composables/index.ts create mode 100644 packages/ui/src/layouts/shared/browse-tab/composables/use-browse-search.ts create mode 100644 packages/ui/src/layouts/shared/browse-tab/header.vue create mode 100644 packages/ui/src/layouts/shared/browse-tab/index.ts create mode 100644 packages/ui/src/layouts/shared/browse-tab/layout.vue create mode 100644 packages/ui/src/layouts/shared/browse-tab/providers/browse-manager.ts create mode 100644 packages/ui/src/layouts/shared/browse-tab/providers/index.ts create mode 100644 packages/ui/src/layouts/shared/browse-tab/sidebar.vue create mode 100644 packages/ui/src/layouts/shared/browse-tab/types.ts create mode 100644 packages/ui/src/layouts/shared/console/components/ConsoleActionButtons.vue create mode 100644 packages/ui/src/layouts/shared/console/components/ConsoleFilterPills.vue create mode 100644 packages/ui/src/layouts/shared/console/composables/console-filtering.ts create mode 100644 packages/ui/src/layouts/shared/console/composables/index.ts create mode 100644 packages/ui/src/layouts/shared/console/composables/log-highlight-addon.ts create mode 100644 packages/ui/src/layouts/shared/console/composables/log-level.ts create mode 100644 packages/ui/src/layouts/shared/console/index.ts create mode 100644 packages/ui/src/layouts/shared/console/layout.vue create mode 100644 packages/ui/src/layouts/shared/console/providers/console-manager.ts create mode 100644 packages/ui/src/layouts/shared/console/providers/index.ts create mode 100644 packages/ui/src/layouts/shared/console/types.ts create mode 100644 packages/ui/src/layouts/shared/server-settings/index.ts create mode 100644 packages/ui/src/layouts/shared/server-settings/pages/advanced.vue create mode 100644 packages/ui/src/layouts/shared/server-settings/pages/general.vue create mode 100644 packages/ui/src/layouts/shared/server-settings/pages/index.ts rename apps/frontend/src/pages/hosting/manage/[id]/options/loader.vue => packages/ui/src/layouts/shared/server-settings/pages/installation.vue (87%) create mode 100644 packages/ui/src/layouts/shared/server-settings/pages/network.vue create mode 100644 packages/ui/src/layouts/shared/server-settings/pages/properties.vue create mode 100644 packages/ui/src/layouts/shared/server-settings/providers/index.ts create mode 100644 packages/ui/src/layouts/shared/server-settings/providers/server-settings.ts create mode 100644 packages/ui/src/layouts/shared/server-settings/tabs.ts create mode 100644 packages/ui/src/layouts/wrapped/hosting/manage/components/ServerManageStats.vue create mode 100644 packages/ui/src/layouts/wrapped/hosting/manage/overview.vue create mode 100644 packages/ui/src/layouts/wrapped/hosting/manage/root.vue create mode 100644 packages/ui/src/providers/hosting-purchase-intent.ts create mode 100644 packages/ui/src/providers/server-settings-modal.ts create mode 100644 packages/ui/src/stories/modal/ShareModal.stories.ts create mode 100644 packages/ui/src/stories/modal/UploadProgressModal.stories.ts create mode 100644 packages/ui/src/stories/servers/EditServerIcon.stories.ts create mode 100644 packages/ui/src/stories/servers/MedalServerListing.stories.ts create mode 100644 packages/ui/src/stories/servers/SaveBanner.stories.ts create mode 100644 packages/ui/src/stories/servers/ServerListEmpty.stories.ts create mode 100644 packages/ui/src/stories/servers/ServerListing.stories.ts diff --git a/.github/workflows/theseus-build.yml b/.github/workflows/theseus-build.yml index 46bb693b8..36547186e 100644 --- a/.github/workflows/theseus-build.yml +++ b/.github/workflows/theseus-build.yml @@ -27,12 +27,15 @@ on: options: - prod - staging + - prod-with-staging-archon default: prod required: false jobs: build: name: Build + env: + VITE_STRIPE_PUBLISHABLE_KEY: pk_live_51JbFxJJygY5LJFfKLVVldb10HlLt24p421OWRsTOWc5sXYFOnFUXWieSc6HD3PHo25ktx8db1WcHr36XGFvZFVUz00V9ixrCs5 strategy: fail-fast: false matrix: diff --git a/.vscode/settings.json b/.vscode/settings.json index d4d338f6d..752219881 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -29,5 +29,7 @@ }, "[rust]": { "editor.defaultFormatter": "rust-lang.rust-analyzer" - } + }, + "css.lint.unknownAtRules": "ignore", + "scss.lint.unknownAtRules": "ignore" } diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 6b1b964a1..d37b0b822 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -1,5 +1,12 @@ diff --git a/apps/app-frontend/src/components/ui/URLConfirmModal.vue b/apps/app-frontend/src/components/ui/URLConfirmModal.vue index aa7917a5d..0ec7cd0bc 100644 --- a/apps/app-frontend/src/components/ui/URLConfirmModal.vue +++ b/apps/app-frontend/src/components/ui/URLConfirmModal.vue @@ -1,11 +1,9 @@ diff --git a/apps/app-frontend/src/pages/instance/Worlds.vue b/apps/app-frontend/src/pages/instance/Worlds.vue index e8b79f438..861eba018 100644 --- a/apps/app-frontend/src/pages/instance/Worlds.vue +++ b/apps/app-frontend/src/pages/instance/Worlds.vue @@ -357,9 +357,7 @@ const MAX_LINUX_REFRESHES = 3 const isLinux = platform() === 'linux' const linuxRefreshCount = ref(0) -const protocolVersion = ref( - await get_profile_protocol_version(instance.value.path), -) +const protocolVersion = ref(null) const managedServerName = ref(null) const managedServerAddress = ref(null) @@ -424,22 +422,27 @@ watch( { immediate: true }, ) -const unlistenProfile = await profile_listener(async (e: ProfileEvent) => { - if (e.profile_path_id !== instance.value.path) return +const [unlistenProfile, , resolvedProtocolVersion, resolvedGameVersions] = await Promise.all([ + profile_listener(async (e: ProfileEvent) => { + if (e.profile_path_id !== instance.value.path) return - console.info(`Handling profile event '${e.event}' for profile: ${e.profile_path_id}`) + console.info(`Handling profile event '${e.event}' for profile: ${e.profile_path_id}`) - if (e.event === 'servers_updated') { - if (isLinux && linuxRefreshCount.value >= MAX_LINUX_REFRESHES) return - if (isLinux) linuxRefreshCount.value++ + if (e.event === 'servers_updated') { + if (isLinux && linuxRefreshCount.value >= MAX_LINUX_REFRESHES) return + if (isLinux) linuxRefreshCount.value++ - await refreshAllWorlds() - } + await refreshAllWorlds() + } - await handleDefaultProfileUpdateEvent(worlds.value, instance.value.path, e) -}) + await handleDefaultProfileUpdateEvent(worlds.value, instance.value.path, e) + }), + refreshAllWorlds(), + get_profile_protocol_version(instance.value.path).catch(() => null), + get_game_versions().catch(() => [] as GameVersion[]), +]) -await refreshAllWorlds() +protocolVersion.value = resolvedProtocolVersion async function refreshServer(address: string) { if (!serverData.value[address]) { @@ -589,7 +592,7 @@ function worldsMatch(world: World, other: World | undefined) { return false } -const gameVersions = ref(await get_game_versions().catch(() => [])) +const gameVersions = ref(resolvedGameVersions) const supportsServerQuickPlay = computed(() => hasServerQuickPlaySupport(gameVersions.value, instance.value.game_version), ) diff --git a/apps/app-frontend/src/providers/setup/auth.ts b/apps/app-frontend/src/providers/setup/auth.ts index bf522c59a..2de8c0acf 100644 --- a/apps/app-frontend/src/providers/setup/auth.ts +++ b/apps/app-frontend/src/providers/setup/auth.ts @@ -1,6 +1,6 @@ import type { Labrinth } from '@modrinth/api-client' import { type AuthProvider, provideAuth } from '@modrinth/ui' -import { type Ref, ref, watchEffect } from 'vue' +import { computed, type Ref, ref, watchEffect } from 'vue' type AppCredentials = { session?: string | null @@ -13,10 +13,12 @@ export function setupAuthProvider( ) { const sessionToken = ref(null) const user = ref(null) + const isReady = computed(() => credentials.value !== undefined) const authProvider: AuthProvider = { session_token: sessionToken, user, + isReady, requestSignIn, } diff --git a/apps/app-frontend/src/providers/setup/server-install-content.ts b/apps/app-frontend/src/providers/setup/server-install-content.ts new file mode 100644 index 000000000..35919d9d7 --- /dev/null +++ b/apps/app-frontend/src/providers/setup/server-install-content.ts @@ -0,0 +1,393 @@ +import type { Archon, Labrinth } from '@modrinth/api-client' +import { + createContext, + type CreationFlowContextValue, + injectModrinthClient, + injectNotificationManager, +} from '@modrinth/ui' +import { computed, type ComputedRef, nextTick, type Ref, ref, watch } from 'vue' +import { useRoute, useRouter } from 'vue-router' + +type ServerFlowFrom = 'onboarding' | 'reset-server' +type ServerInstallableType = 'modpack' | 'mod' | 'plugin' | 'datapack' + +type InstallableSearchResult = Labrinth.Search.v3.ResultSearchProject & { + installing?: boolean + installed?: boolean +} + +interface ServerModpackSelectionRequest { + projectId: string + versionId: string + name: string + iconUrl?: string +} + +interface ServerSetupModalHandle { + show: () => void | Promise + hide: () => void + ctx?: CreationFlowContextValue | null +} + +export interface ServerInstallContentContext { + serverIdQuery: ComputedRef + worldIdQuery: ComputedRef + browseFrom: ComputedRef + serverFlowFrom: ComputedRef + isFromWorlds: ComputedRef + isServerContext: ComputedRef + isSetupServerContext: ComputedRef + effectiveServerWorldId: ComputedRef + serverContextServerData: Ref + serverContentProjectIds: Ref> + serverBackUrl: ComputedRef + serverBackLabel: ComputedRef + serverBrowseHeading: ComputedRef + initServerContext: () => Promise + watchServerContextChanges: () => void + searchServerModpacks: ( + query: string, + limit?: number, + ) => Promise + getServerProjectVersions: (projectId: string) => Promise<{ id: string }[]> + enforceSetupModpackRoute: (currentProjectType: string | undefined) => void + installProjectToServer: (project: InstallableSearchResult) => Promise + onServerFlowBack: () => void + handleServerModpackFlowCreate: (config: CreationFlowContextValue) => Promise + markServerProjectInstalled: (id: string) => void +} + +export const [injectServerInstallContent, provideServerInstallContent] = + createContext('Browse', 'serverInstallContent') + +function readQueryString(value: unknown): string | null { + if (Array.isArray(value)) return value[0] ?? null + return typeof value === 'string' && value.length > 0 ? value : null +} + +export function createServerInstallContent(opts: { + serverSetupModalRef: Ref +}) { + const { serverSetupModalRef } = opts + const route = useRoute() + const router = useRouter() + const client = injectModrinthClient() + const { handleError } = injectNotificationManager() + + const serverIdQuery = computed(() => readQueryString(route.query.sid)) + const worldIdQuery = computed(() => readQueryString(route.query.wid)) + const browseFrom = computed(() => readQueryString(route.query.from)) + const serverFlowFrom = computed(() => + browseFrom.value === 'onboarding' || browseFrom.value === 'reset-server' + ? browseFrom.value + : null, + ) + + const isFromWorlds = computed(() => browseFrom.value === 'worlds') + const isServerContext = computed(() => !!serverIdQuery.value) + const isSetupServerContext = computed(() => !!serverIdQuery.value && !!serverFlowFrom.value) + + const serverContextWorldId = ref(worldIdQuery.value) + const serverContextServerData = ref(null) + const serverContentProjectIds = ref>(new Set()) + const effectiveServerWorldId = computed(() => worldIdQuery.value ?? serverContextWorldId.value) + + const serverBackUrl = computed(() => { + const sid = serverIdQuery.value + if (!sid) return '/hosting/manage' + if (serverFlowFrom.value === 'onboarding') { + return `/hosting/manage/${sid}?resumeModal=setup-type` + } + if (serverFlowFrom.value === 'reset-server') { + return `/hosting/manage/${sid}?openSettings=installation` + } + return `/hosting/manage/${sid}/content` + }) + const serverBackLabel = computed(() => { + if (serverFlowFrom.value === 'onboarding') return 'Back to setup' + if (serverFlowFrom.value === 'reset-server') return 'Cancel reset' + return 'Back to server' + }) + const serverBrowseHeading = computed(() => { + if (serverFlowFrom.value === 'reset-server') { + return 'Select modpack to install after reset' + } + return 'Install content to server' + }) + + async function resolveServerContextWorldId(serverId: string) { + try { + const server = await client.archon.servers_v1.get(serverId) + const activeWorld = server.worlds.find((world) => world.is_active) + return activeWorld?.id ?? server.worlds[0]?.id ?? null + } catch (err) { + handleError(err as Error) + return null + } + } + + async function refreshServerInstalledContent(serverId: string, worldId: string) { + try { + const content = await client.archon.content_v1.getAddons(serverId, worldId) + const ids = new Set( + (content.addons ?? []) + .map((addon) => addon.project_id) + .filter((projectId): projectId is string => !!projectId), + ) + serverContentProjectIds.value = ids + } catch (err) { + handleError(err as Error) + } + } + + async function initServerContext() { + const sid = serverIdQuery.value + if (!sid) return + + try { + serverContextServerData.value = await client.archon.servers_v0.get(sid) + } catch (err) { + handleError(err as Error) + } + + let resolvedWorldId = effectiveServerWorldId.value + if (!resolvedWorldId) { + resolvedWorldId = await resolveServerContextWorldId(sid) + if (resolvedWorldId) { + serverContextWorldId.value = resolvedWorldId + } + } + + if (resolvedWorldId) { + await refreshServerInstalledContent(sid, resolvedWorldId) + } + } + + function watchServerContextChanges() { + watch([serverIdQuery, effectiveServerWorldId], async ([sid, wid], [prevSid, prevWid]) => { + if (!sid) { + serverContextServerData.value = null + serverContentProjectIds.value = new Set() + return + } + + if (sid !== prevSid) { + serverContentProjectIds.value = new Set() + try { + serverContextServerData.value = await client.archon.servers_v0.get(sid) + } catch (err) { + handleError(err as Error) + } + } + + if (wid && (sid !== prevSid || wid !== prevWid)) { + await refreshServerInstalledContent(sid, wid) + } + }) + } + + function normalizeLoader(loader: string) { + return loader.toLowerCase().replaceAll('_', '').replaceAll('-', '').replaceAll(' ', '') + } + + function getCompatibleLoaders(loader: string) { + const normalized = normalizeLoader(loader) + if (!normalized) return new Set() + if (normalized === 'paper' || normalized === 'purpur' || normalized === 'spigot') { + return new Set(['paper', 'purpur', 'spigot', 'bukkit']) + } + if (normalized === 'neoforge' || normalized === 'neo') { + return new Set(['neoforge', 'neo']) + } + return new Set([normalized]) + } + + function enforceSetupModpackRoute(currentProjectType: string | undefined) { + if (!isSetupServerContext.value || currentProjectType === 'modpack') return + router.replace({ + path: '/browse/modpack', + query: route.query, + }) + } + + async function searchServerModpacks(query: string, limit: number = 10) { + return client.labrinth.projects_v2.search({ + query: query || undefined, + new_filters: + 'project_types = "modpack" AND (client_side = "optional" OR client_side = "required") AND server_side = "required"', + limit, + }) + } + + async function getServerProjectVersions(projectId: string) { + const versions = await client.labrinth.versions_v3.getProjectVersions(projectId) + return versions.map((version) => ({ id: version.id })) + } + + async function openServerModpackInstallFlow(request: ServerModpackSelectionRequest) { + if (!serverIdQuery.value || !effectiveServerWorldId.value) { + throw new Error('Missing server context') + } + + const modalInstance = serverSetupModalRef.value + if (!modalInstance) return + + modalInstance.show() + await nextTick() + + const ctx = modalInstance.ctx + if (!ctx) return + + ctx.setupType.value = 'modpack' + ctx.modpackSelection.value = { + projectId: request.projectId, + versionId: request.versionId, + name: request.name, + iconUrl: request.iconUrl, + } + ctx.modal.value?.setStage('final-config') + } + + function getCurrentServerInstallType(): ServerInstallableType { + const raw = Array.isArray(route.params.projectType) + ? route.params.projectType[0] + : route.params.projectType + if (raw === 'modpack' || raw === 'mod' || raw === 'plugin' || raw === 'datapack') { + return raw + } + throw new Error('This content type cannot be installed to a server from browse.') + } + + async function installProjectToServer(project: InstallableSearchResult) { + const contentType = getCurrentServerInstallType() + const sid = serverIdQuery.value + const wid = effectiveServerWorldId.value + if (!sid || !wid) { + throw new Error('No server world is available for install.') + } + + if (contentType === 'modpack') { + const versions = await client.labrinth.versions_v2.getProjectVersions(project.project_id, { + include_changelog: false, + }) + const versionId = versions[0]?.id ?? project.version_id + if (!versionId) { + throw new Error('No version found for this modpack') + } + + await openServerModpackInstallFlow({ + projectId: project.project_id, + versionId, + name: project.name, + iconUrl: project.icon_url ?? undefined, + }) + return false + } + + const versions = await client.labrinth.versions_v2.getProjectVersions(project.project_id, { + include_changelog: false, + }) + const serverLoader = (serverContextServerData.value?.loader ?? '').toLowerCase() + const serverGameVersion = (serverContextServerData.value?.mc_version ?? '').trim() + const compatibleLoaders = getCompatibleLoaders(serverLoader) + + const hasGameVersionMatch = (version: Labrinth.Versions.v2.Version) => + !serverGameVersion || version.game_versions.includes(serverGameVersion) + const hasLoaderMatch = (version: Labrinth.Versions.v2.Version) => { + if (contentType === 'datapack') return true + if (compatibleLoaders.size === 0) return true + return version.loaders.some((loader) => compatibleLoaders.has(normalizeLoader(loader))) + } + + let matchingVersion = versions.find( + (version) => hasGameVersionMatch(version) && hasLoaderMatch(version), + ) + if (!matchingVersion) { + matchingVersion = versions.find((version) => hasLoaderMatch(version)) + } + if (!matchingVersion) { + matchingVersion = versions.find((version) => hasGameVersionMatch(version)) + } + if (!matchingVersion) { + matchingVersion = versions[0] + } + if (!matchingVersion) { + throw new Error('No installable version was found for this project.') + } + + await client.archon.content_v1.addAddon(sid, wid, { + project_id: matchingVersion.project_id, + version_id: matchingVersion.id, + }) + + serverContentProjectIds.value = new Set([...serverContentProjectIds.value, project.project_id]) + return true + } + + function onServerFlowBack() { + serverSetupModalRef.value?.hide() + } + + async function handleServerModpackFlowCreate(config: CreationFlowContextValue) { + const sid = serverIdQuery.value + const wid = effectiveServerWorldId.value + if (!sid || !wid || !config.modpackSelection.value) { + config.loading.value = false + return + } + + try { + await client.archon.content_v1.installContent(sid, wid, { + content_variant: 'modpack', + spec: { + platform: 'modrinth', + project_id: config.modpackSelection.value.projectId, + version_id: config.modpackSelection.value.versionId, + }, + soft_override: false, + properties: config.buildProperties(), + } satisfies Archon.Content.v1.InstallWorldContent) + serverSetupModalRef.value?.hide() + + if (serverFlowFrom.value === 'onboarding') { + await client.archon.servers_v1.endIntro(sid) + await router.push(`/hosting/manage/${sid}/content`) + return + } + + await router.push(`/hosting/manage/${sid}?openSettings=installation`) + } catch (err) { + handleError(err as Error) + config.loading.value = false + } + } + + function markServerProjectInstalled(id: string) { + serverContentProjectIds.value = new Set([...serverContentProjectIds.value, id]) + } + + return { + serverIdQuery, + worldIdQuery, + browseFrom, + serverFlowFrom, + isFromWorlds, + isServerContext, + isSetupServerContext, + effectiveServerWorldId, + serverContextServerData, + serverContentProjectIds, + serverBackUrl, + serverBackLabel, + serverBrowseHeading, + initServerContext, + watchServerContextChanges, + searchServerModpacks, + getServerProjectVersions, + enforceSetupModpackRoute, + installProjectToServer, + onServerFlowBack, + handleServerModpackFlowCreate, + markServerProjectInstalled, + } +} diff --git a/apps/app-frontend/src/routes.js b/apps/app-frontend/src/routes.js index 18c6df173..b80137915 100644 --- a/apps/app-frontend/src/routes.js +++ b/apps/app-frontend/src/routes.js @@ -1,7 +1,7 @@ -import { ServersManagePageIndex } from '@modrinth/ui' import { createRouter, createWebHistory } from 'vue-router' import * as Pages from '@/pages' +import * as Hosting from '@/pages/hosting/manage' import * as Instance from '@/pages/instance' import * as Library from '@/pages/library' import * as Project from '@/pages/project' @@ -31,11 +31,50 @@ export default new createRouter({ { path: '/hosting/manage/', name: 'Servers', - component: ServersManagePageIndex, + component: Pages.Servers, meta: { breadcrumb: [{ name: 'Servers' }], }, }, + { + path: '/hosting/manage/:id', + name: 'ServerManage', + component: Hosting.Index, + children: [ + { + path: '', + name: 'ServerManageOverview', + component: Hosting.Overview, + meta: { + breadcrumb: [{ name: '?Server' }], + }, + }, + { + path: 'content', + name: 'ServerManageContent', + component: Hosting.Content, + meta: { + breadcrumb: [{ name: '?Server' }], + }, + }, + { + path: 'files', + name: 'ServerManageFiles', + component: Hosting.Files, + meta: { + breadcrumb: [{ name: '?Server' }], + }, + }, + { + path: 'backups', + name: 'ServerManageBackups', + component: Hosting.Backups, + meta: { + breadcrumb: [{ name: '?Server' }], + }, + }, + ], + }, { path: '/browse/:projectType', name: 'Discover content', @@ -88,6 +127,13 @@ export default new createRouter({ }, ], }, + { + path: '/:projectType(mod|plugin|datapack|resourcepack|shader|modpack)/:id/:rest(.*)*', + redirect: (to) => { + const rest = to.params.rest ? `/${[].concat(to.params.rest).join('/')}` : '' + return `/project/${to.params.id}${rest}${to.hash}` + }, + }, { path: '/project/:id', name: 'Project', @@ -202,7 +248,8 @@ export default new createRouter({ ], linkActiveClass: 'router-link-active', linkExactActiveClass: 'router-link-exact-active', - scrollBehavior() { + scrollBehavior(to, from) { + if (to.path === from.path) return // Sometimes Vue's scroll behavior is not working as expected, so we need to manually scroll to top (especially on Linux) document.querySelector('.app-viewport')?.scrollTo(0, 0) return { diff --git a/apps/app-frontend/src/store/theme.ts b/apps/app-frontend/src/store/theme.ts index 605596b11..dbdd5a119 100644 --- a/apps/app-frontend/src/store/theme.ts +++ b/apps/app-frontend/src/store/theme.ts @@ -5,7 +5,6 @@ export const DEFAULT_FEATURE_FLAGS = { page_path: false, worlds_tab: false, worlds_in_home: true, - servers_in_app: false, server_project_qa: false, i18n_debug: false, } diff --git a/apps/app-frontend/tsconfig.app.json b/apps/app-frontend/tsconfig.app.json index 8d5b455fe..504558d95 100644 --- a/apps/app-frontend/tsconfig.app.json +++ b/apps/app-frontend/tsconfig.app.json @@ -3,7 +3,7 @@ "target": "ES2020", "useDefineForClassFields": true, "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], + "lib": ["ES2021", "DOM", "DOM.Iterable"], "skipLibCheck": true, "moduleResolution": "bundler", @@ -16,6 +16,8 @@ "strict": true, + "types": ["vite/client"], + "paths": { "@/*": ["./src/*"] } diff --git a/apps/app-frontend/vite.config.ts b/apps/app-frontend/vite.config.ts index 618068cb2..f55d00c81 100644 --- a/apps/app-frontend/vite.config.ts +++ b/apps/app-frontend/vite.config.ts @@ -1,4 +1,5 @@ import vue from '@vitejs/plugin-vue' +import { existsSync, readFileSync } from 'fs' import { resolve } from 'path' import { defineConfig } from 'vite' import svgLoader from 'vite-svg-loader' @@ -6,6 +7,23 @@ import svgLoader from 'vite-svg-loader' import tauriConf from '../app/tauri.conf.json' const projectRootDir = resolve(__dirname) +const appLibEnvDir = resolve(projectRootDir, '../../packages/app-lib') + +// Load .env from app-lib manually instead of using Vite's envDir, which would auto-load .env.local and override values +const envFilePath = resolve(appLibEnvDir, '.env') +if (existsSync(envFilePath)) { + for (const line of readFileSync(envFilePath, 'utf-8').split('\n')) { + const trimmed = line.trim() + if (!trimmed || trimmed.startsWith('#')) continue + const eqIndex = trimmed.indexOf('=') + if (eqIndex === -1) continue + const key = trimmed.slice(0, eqIndex) + const value = trimmed.slice(eqIndex + 1) + if (!(key in process.env)) { + process.env[key] = value + } + } +} // https://vitejs.dev/config/ export default defineConfig({ @@ -68,7 +86,7 @@ export default defineConfig({ }, // to make use of `TAURI_ENV_DEBUG` and other env variables // https://v2.tauri.app/reference/environment-variables/#tauri-cli-hook-commands - envPrefix: ['VITE_', 'TAURI_'], + envPrefix: ['VITE_', 'TAURI_', 'MODRINTH_'], build: { rolldownOptions: { onwarn(warning, defaultHandler) { diff --git a/apps/app/build.rs b/apps/app/build.rs index 358975ed1..769d7db70 100644 --- a/apps/app/build.rs +++ b/apps/app/build.rs @@ -89,6 +89,8 @@ fn main() { "logs_delete_logs", "logs_delete_logs_by_filename", "logs_get_latest_log_cursor", + "logs_get_live_log_buffer", + "logs_clear_live_log_buffer", ]) .default_permission( DefaultPermissionRule::AllowAllCommands, diff --git a/apps/app/capabilities/plugins.json b/apps/app/capabilities/plugins.json index f1a45bf27..ac090260b 100644 --- a/apps/app/capabilities/plugins.json +++ b/apps/app/capabilities/plugins.json @@ -22,7 +22,12 @@ { "identifier": "http:default", - "allow": [{ "url": "https://modrinth.com/*" }, { "url": "https://*.modrinth.com/*" }] + "allow": [ + { "url": "https://modrinth.com/*" }, + { "url": "https://*.modrinth.com/*" }, + { "url": "https://*.nodes.modrinth.com/*" }, + { "url": "https://api.mclo.gs/*" } + ] }, "dialog:allow-save", diff --git a/apps/app/src/api/logs.rs b/apps/app/src/api/logs.rs index c5097a1c9..cf68519e1 100644 --- a/apps/app/src/api/logs.rs +++ b/apps/app/src/api/logs.rs @@ -21,6 +21,8 @@ pub fn init() -> tauri::plugin::TauriPlugin { logs_delete_logs, logs_delete_logs_by_filename, logs_get_latest_log_cursor, + logs_get_live_log_buffer, + logs_clear_live_log_buffer, ]) .build() } @@ -83,3 +85,18 @@ pub async fn logs_get_latest_log_cursor( ) -> Result { Ok(logs::get_latest_log_cursor(profile_path, cursor).await?) } + +/// Get all buffered live log lines for a profile +#[tauri::command] +pub async fn logs_get_live_log_buffer( + profile_path: &str, +) -> Result { + Ok(logs::get_live_log_buffer(profile_path).await?) +} + +/// Clear the live log buffer for a profile +#[tauri::command] +pub async fn logs_clear_live_log_buffer(profile_path: &str) -> Result<()> { + logs::clear_live_log_buffer(profile_path); + Ok(()) +} diff --git a/apps/app/src/main.rs b/apps/app/src/main.rs index 03a8227ac..a78c26010 100644 --- a/apps/app/src/main.rs +++ b/apps/app/src/main.rs @@ -7,6 +7,7 @@ use native_dialog::{DialogBuilder, MessageLevel}; use std::env; use tauri::{Listener, Manager}; +use tauri_plugin_fs::FsExt; use theseus::prelude::*; mod api; @@ -35,6 +36,8 @@ async fn initialize_state(app: tauri::AppHandle) -> api::Result<()> { .allow_directory(state.directories.caches_dir(), true)?; app.asset_protocol_scope() .allow_directory(state.directories.caches_dir().join("icons"), true)?; + app.fs_scope() + .allow_directory(state.directories.profiles_dir(), true)?; Ok(()) } diff --git a/apps/app/tauri.conf.json b/apps/app/tauri.conf.json index 986347dc3..06d1d350a 100644 --- a/apps/app/tauri.conf.json +++ b/apps/app/tauri.conf.json @@ -87,12 +87,12 @@ "capabilities": ["ads", "core", "plugins"], "csp": { "default-src": "'self' customprotocol: asset:", - "connect-src": "ipc: http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.posthog.com https://*.sentry.io https://api.mclo.gs http://textures.minecraft.net https://textures.minecraft.net 'self' data: blob:", + "connect-src": "ipc: http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.nodes.modrinth.com https://*.posthog.com https://posthog.modrinth.com https://*.sentry.io https://api.mclo.gs http://textures.minecraft.net https://textures.minecraft.net https://js.stripe.com https://*.stripe.com wss://*.stripe.com wss://*.nodes.modrinth.com wss://*.ts.net 'self' data: blob:", "font-src": ["https://cdn-raw.modrinth.com/fonts/"], "img-src": "https: 'unsafe-inline' 'self' asset: http://asset.localhost http://textures.minecraft.net blob: data:", "style-src": "'unsafe-inline' 'self'", - "script-src": "https://*.posthog.com https://tally.so/widgets/embed.js 'self'", - "frame-src": "https://www.youtube.com https://www.youtube-nocookie.com https://discord.com https://tally.so/popup/ 'self'", + "script-src": "https://*.posthog.com https://posthog.modrinth.com https://js.stripe.com https://tally.so/widgets/embed.js 'self'", + "frame-src": "https://www.youtube.com https://www.youtube-nocookie.com https://discord.com https://tally.so/popup/ https://js.stripe.com https://hooks.stripe.com 'self'", "media-src": "https://*.githubusercontent.com" } } diff --git a/apps/frontend/src/assets/styles/components.scss b/apps/frontend/src/assets/styles/components.scss index 9ac5ec5b9..b04291d4c 100644 --- a/apps/frontend/src/assets/styles/components.scss +++ b/apps/frontend/src/assets/styles/components.scss @@ -841,6 +841,23 @@ button { opacity: 0.5; box-shadow: none; flex-shrink: 0; + user-select: none; + } + + .text-input-wrapper__after { + display: flex; + color: var(--color-text); + padding: 0.5rem 1rem 0.5rem 0; + font-weight: var(--font-weight-medium); + min-height: 36px; + box-sizing: border-box; + width: fit-content; + align-items: center; + filter: grayscale(50%); + opacity: 0.5; + box-shadow: none; + flex-shrink: 0; + user-select: none; } input, diff --git a/apps/frontend/src/assets/styles/global.scss b/apps/frontend/src/assets/styles/global.scss index 305b14442..917240e78 100644 --- a/apps/frontend/src/assets/styles/global.scss +++ b/apps/frontend/src/assets/styles/global.scss @@ -456,9 +456,9 @@ kbd { font-size: 0.85em !important; } -@import '~/assets/styles/layout.scss'; -@import '~/assets/styles/utils.scss'; -@import '~/assets/styles/components.scss'; +@import './layout.scss'; +@import './utils.scss'; +@import './components.scss'; // OMORPHIA FIXES .card { diff --git a/apps/frontend/src/components/ui/servers/ModrinthServersIcon.vue b/apps/frontend/src/components/brand/ModrinthServersIcon.vue similarity index 100% rename from apps/frontend/src/components/ui/servers/ModrinthServersIcon.vue rename to apps/frontend/src/components/brand/ModrinthServersIcon.vue diff --git a/apps/frontend/src/components/ui/servers/notice/AssignNoticeModal.vue b/apps/frontend/src/components/ui/admin/AssignNoticeModal.vue similarity index 100% rename from apps/frontend/src/components/ui/servers/notice/AssignNoticeModal.vue rename to apps/frontend/src/components/ui/admin/AssignNoticeModal.vue diff --git a/apps/frontend/src/components/ui/servers/LoaderSelector.vue b/apps/frontend/src/components/ui/servers/LoaderSelector.vue deleted file mode 100644 index 0998a9ced..000000000 --- a/apps/frontend/src/components/ui/servers/LoaderSelector.vue +++ /dev/null @@ -1,96 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/LoaderSelectorCard.vue b/apps/frontend/src/components/ui/servers/LoaderSelectorCard.vue deleted file mode 100644 index 0017f1076..000000000 --- a/apps/frontend/src/components/ui/servers/LoaderSelectorCard.vue +++ /dev/null @@ -1,68 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/LogLine.vue b/apps/frontend/src/components/ui/servers/LogLine.vue deleted file mode 100644 index 07df871a3..000000000 --- a/apps/frontend/src/components/ui/servers/LogLine.vue +++ /dev/null @@ -1,91 +0,0 @@ - - - - - diff --git a/apps/frontend/src/components/ui/servers/PanelServerActionButton.vue b/apps/frontend/src/components/ui/servers/PanelServerActionButton.vue deleted file mode 100644 index 3022a7b06..000000000 --- a/apps/frontend/src/components/ui/servers/PanelServerActionButton.vue +++ /dev/null @@ -1,276 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/PanelServerStatus.vue b/apps/frontend/src/components/ui/servers/PanelServerStatus.vue deleted file mode 100644 index f5b42fa0e..000000000 --- a/apps/frontend/src/components/ui/servers/PanelServerStatus.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/PanelSpinner.vue b/apps/frontend/src/components/ui/servers/PanelSpinner.vue deleted file mode 100644 index c2c7f55ea..000000000 --- a/apps/frontend/src/components/ui/servers/PanelSpinner.vue +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/PanelTerminal.vue b/apps/frontend/src/components/ui/servers/PanelTerminal.vue deleted file mode 100644 index 950a2dc9e..000000000 --- a/apps/frontend/src/components/ui/servers/PanelTerminal.vue +++ /dev/null @@ -1,1414 +0,0 @@ - - - - - diff --git a/apps/frontend/src/components/ui/servers/PlatformChangeModpackVersionModal.vue b/apps/frontend/src/components/ui/servers/PlatformChangeModpackVersionModal.vue deleted file mode 100644 index e7b0c74ed..000000000 --- a/apps/frontend/src/components/ui/servers/PlatformChangeModpackVersionModal.vue +++ /dev/null @@ -1,163 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/PlatformVersionSelectModal.vue b/apps/frontend/src/components/ui/servers/PlatformVersionSelectModal.vue deleted file mode 100644 index f4ca68f7c..000000000 --- a/apps/frontend/src/components/ui/servers/PlatformVersionSelectModal.vue +++ /dev/null @@ -1,538 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/SaveBanner.vue b/apps/frontend/src/components/ui/servers/SaveBanner.vue deleted file mode 100644 index 092ca3b60..000000000 --- a/apps/frontend/src/components/ui/servers/SaveBanner.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - - - diff --git a/apps/frontend/src/components/ui/servers/ServerSidebar.vue b/apps/frontend/src/components/ui/servers/ServerSidebar.vue deleted file mode 100644 index 1b455df0c..000000000 --- a/apps/frontend/src/components/ui/servers/ServerSidebar.vue +++ /dev/null @@ -1,52 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/ServerStats.vue b/apps/frontend/src/components/ui/servers/ServerStats.vue deleted file mode 100644 index a16aa6322..000000000 --- a/apps/frontend/src/components/ui/servers/ServerStats.vue +++ /dev/null @@ -1,256 +0,0 @@ - - - - - diff --git a/apps/frontend/src/components/ui/servers/TeleportOverflowMenu.vue b/apps/frontend/src/components/ui/servers/TeleportOverflowMenu.vue deleted file mode 100644 index 4a8f77413..000000000 --- a/apps/frontend/src/components/ui/servers/TeleportOverflowMenu.vue +++ /dev/null @@ -1,438 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/icons/ChevronDownIcon.vue b/apps/frontend/src/components/ui/servers/icons/ChevronDownIcon.vue deleted file mode 100644 index 783d18a40..000000000 --- a/apps/frontend/src/components/ui/servers/icons/ChevronDownIcon.vue +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/ChevronUpIcon.vue b/apps/frontend/src/components/ui/servers/icons/ChevronUpIcon.vue deleted file mode 100644 index da6cf408a..000000000 --- a/apps/frontend/src/components/ui/servers/icons/ChevronUpIcon.vue +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/CodeFileIcon.vue b/apps/frontend/src/components/ui/servers/icons/CodeFileIcon.vue deleted file mode 100644 index 42022a33c..000000000 --- a/apps/frontend/src/components/ui/servers/icons/CodeFileIcon.vue +++ /dev/null @@ -1,18 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/CogFolderIcon.vue b/apps/frontend/src/components/ui/servers/icons/CogFolderIcon.vue deleted file mode 100644 index cc8fc1bc6..000000000 --- a/apps/frontend/src/components/ui/servers/icons/CogFolderIcon.vue +++ /dev/null @@ -1,26 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/EarthIcon.vue b/apps/frontend/src/components/ui/servers/icons/EarthIcon.vue deleted file mode 100644 index e96f944bc..000000000 --- a/apps/frontend/src/components/ui/servers/icons/EarthIcon.vue +++ /dev/null @@ -1,20 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/FullscreenIcon.vue b/apps/frontend/src/components/ui/servers/icons/FullscreenIcon.vue deleted file mode 100644 index 383912d2b..000000000 --- a/apps/frontend/src/components/ui/servers/icons/FullscreenIcon.vue +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/ImageFileIcon.vue b/apps/frontend/src/components/ui/servers/icons/ImageFileIcon.vue deleted file mode 100644 index 6aa81c277..000000000 --- a/apps/frontend/src/components/ui/servers/icons/ImageFileIcon.vue +++ /dev/null @@ -1,18 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/LoaderIcon.vue b/apps/frontend/src/components/ui/servers/icons/LoaderIcon.vue deleted file mode 100644 index 090bb945b..000000000 --- a/apps/frontend/src/components/ui/servers/icons/LoaderIcon.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/apps/frontend/src/components/ui/servers/icons/LoadingIcon.vue b/apps/frontend/src/components/ui/servers/icons/LoadingIcon.vue deleted file mode 100644 index 9e9a8ad3f..000000000 --- a/apps/frontend/src/components/ui/servers/icons/LoadingIcon.vue +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/MinimizeIcon.vue.vue b/apps/frontend/src/components/ui/servers/icons/MinimizeIcon.vue.vue deleted file mode 100644 index 27b0fcad2..000000000 --- a/apps/frontend/src/components/ui/servers/icons/MinimizeIcon.vue.vue +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/PanelErrorIcon.vue b/apps/frontend/src/components/ui/servers/icons/PanelErrorIcon.vue deleted file mode 100644 index 2ecad74dc..000000000 --- a/apps/frontend/src/components/ui/servers/icons/PanelErrorIcon.vue +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/SlashIcon.vue b/apps/frontend/src/components/ui/servers/icons/SlashIcon.vue deleted file mode 100644 index 7f6e62fca..000000000 --- a/apps/frontend/src/components/ui/servers/icons/SlashIcon.vue +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/TextFileIcon.vue b/apps/frontend/src/components/ui/servers/icons/TextFileIcon.vue deleted file mode 100644 index 99bcee1ac..000000000 --- a/apps/frontend/src/components/ui/servers/icons/TextFileIcon.vue +++ /dev/null @@ -1,20 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/icons/Timer.vue b/apps/frontend/src/components/ui/servers/icons/Timer.vue deleted file mode 100644 index e1ead004b..000000000 --- a/apps/frontend/src/components/ui/servers/icons/Timer.vue +++ /dev/null @@ -1,17 +0,0 @@ - diff --git a/apps/frontend/src/components/ui/servers/notice/NoticeDashboardItem.vue b/apps/frontend/src/components/ui/servers/notice/NoticeDashboardItem.vue deleted file mode 100644 index 220880845..000000000 --- a/apps/frontend/src/components/ui/servers/notice/NoticeDashboardItem.vue +++ /dev/null @@ -1,127 +0,0 @@ - - diff --git a/apps/frontend/src/components/ui/thread/ThreadView.vue b/apps/frontend/src/components/ui/thread/ThreadView.vue index 608f0f1f1..dc9bcaa6c 100644 --- a/apps/frontend/src/components/ui/thread/ThreadView.vue +++ b/apps/frontend/src/components/ui/thread/ThreadView.vue @@ -74,7 +74,7 @@ diff --git a/apps/frontend/src/pages/hosting/manage/[id]/index.vue b/apps/frontend/src/pages/hosting/manage/[id]/index.vue index 46e19ea11..9b4ae555c 100644 --- a/apps/frontend/src/pages/hosting/manage/[id]/index.vue +++ b/apps/frontend/src/pages/hosting/manage/[id]/index.vue @@ -1,728 +1,13 @@ - - + + diff --git a/apps/frontend/src/pages/hosting/manage/[id]/options.vue b/apps/frontend/src/pages/hosting/manage/[id]/options.vue deleted file mode 100644 index 9d4697de0..000000000 --- a/apps/frontend/src/pages/hosting/manage/[id]/options.vue +++ /dev/null @@ -1,69 +0,0 @@ - - diff --git a/apps/frontend/src/pages/hosting/manage/[id]/options/billing.vue b/apps/frontend/src/pages/hosting/manage/[id]/options/billing.vue deleted file mode 100644 index db707f8a1..000000000 --- a/apps/frontend/src/pages/hosting/manage/[id]/options/billing.vue +++ /dev/null @@ -1,12 +0,0 @@ - - - diff --git a/apps/frontend/src/pages/hosting/manage/[id]/options/index.vue b/apps/frontend/src/pages/hosting/manage/[id]/options/index.vue deleted file mode 100644 index 09d45c96b..000000000 --- a/apps/frontend/src/pages/hosting/manage/[id]/options/index.vue +++ /dev/null @@ -1,335 +0,0 @@ - - - diff --git a/apps/frontend/src/pages/hosting/manage/[id]/options/info.vue b/apps/frontend/src/pages/hosting/manage/[id]/options/info.vue deleted file mode 100644 index 35f89ad0b..000000000 --- a/apps/frontend/src/pages/hosting/manage/[id]/options/info.vue +++ /dev/null @@ -1,154 +0,0 @@ - - - diff --git a/apps/frontend/src/pages/hosting/manage/[id]/options/network.vue b/apps/frontend/src/pages/hosting/manage/[id]/options/network.vue deleted file mode 100644 index f9fd5f60e..000000000 --- a/apps/frontend/src/pages/hosting/manage/[id]/options/network.vue +++ /dev/null @@ -1,507 +0,0 @@ - - - diff --git a/apps/frontend/src/pages/hosting/manage/[id]/options/preferences.vue b/apps/frontend/src/pages/hosting/manage/[id]/options/preferences.vue deleted file mode 100644 index d3c84bf5b..000000000 --- a/apps/frontend/src/pages/hosting/manage/[id]/options/preferences.vue +++ /dev/null @@ -1,113 +0,0 @@ - - - diff --git a/apps/frontend/src/pages/hosting/manage/[id]/options/properties.vue b/apps/frontend/src/pages/hosting/manage/[id]/options/properties.vue deleted file mode 100644 index ae73daf96..000000000 --- a/apps/frontend/src/pages/hosting/manage/[id]/options/properties.vue +++ /dev/null @@ -1,292 +0,0 @@ - - - diff --git a/apps/frontend/src/pages/hosting/manage/[id]/options/startup.vue b/apps/frontend/src/pages/hosting/manage/[id]/options/startup.vue deleted file mode 100644 index d8fd8c985..000000000 --- a/apps/frontend/src/pages/hosting/manage/[id]/options/startup.vue +++ /dev/null @@ -1,287 +0,0 @@ - - - diff --git a/apps/frontend/src/pages/hosting/manage/index.vue b/apps/frontend/src/pages/hosting/manage/index.vue index 0767051ab..3ea3fb216 100644 --- a/apps/frontend/src/pages/hosting/manage/index.vue +++ b/apps/frontend/src/pages/hosting/manage/index.vue @@ -8,7 +8,7 @@ definePageMeta({ }) useHead({ - title: 'Servers - Modrinth', + title: 'Hosting - Modrinth', }) const config = useRuntimeConfig() @@ -20,5 +20,6 @@ const generatedState = useGeneratedState() :stripe-publishable-key="config.public.stripePublishableKey" :site-url="config.public.siteUrl" :products="generatedState.products || []" + class="max-w-[1280px] py-0" /> diff --git a/apps/frontend/src/pages/settings/billing/index.vue b/apps/frontend/src/pages/settings/billing/index.vue index 3c5578042..5a9cdd8db 100644 --- a/apps/frontend/src/pages/settings/billing/index.vue +++ b/apps/frontend/src/pages/settings/billing/index.vue @@ -1,5 +1,6 @@