mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Differentiate archived project behavior by plan tier (#2549)
Prior to this, the projects page had two problems: 1. After submitting a downgrade request but still on a Pro plan before the end of the billing period, projects showed as archived 2. After downgraded, archived projects showed as read only and gave options to migrate data even though access to the archived projects were blocked. This PR clarifies the behavior for archived projects by: - showing projects as pending archive if downgraded but still on Pro - removing the read only tag for downgraded orgs - preventing opening projects for downgraded orgs since the user has no access - making the unarchive and migrate buttons disabled for downgraded orgs
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { Button, InputText } from '$lib/elements/forms';
|
||||
import { DropList, GridItem1, CardContainer, Modal } from '$lib/components';
|
||||
import { GridItem1, CardContainer, Modal } from '$lib/components';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import {
|
||||
Badge,
|
||||
Icon,
|
||||
Typography,
|
||||
Tag,
|
||||
Accordion,
|
||||
ActionMenu,
|
||||
Popover,
|
||||
@@ -20,7 +19,6 @@
|
||||
IconFlutter,
|
||||
IconReact,
|
||||
IconUnity,
|
||||
IconInfo,
|
||||
IconDotsHorizontal,
|
||||
IconInboxIn,
|
||||
IconSwitchHorizontal,
|
||||
@@ -29,7 +27,6 @@
|
||||
import { getPlatformInfo } from '$lib/helpers/platform';
|
||||
import { Status, type Models } from '@appwrite.io/console';
|
||||
import type { ComponentType } from 'svelte';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { goto } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
@@ -52,8 +49,9 @@
|
||||
|
||||
let { projectsToArchive, organization, currentPlan }: Props = $props();
|
||||
|
||||
// Track Read-only info droplist per archived project
|
||||
let readOnlyInfoOpen = $state<Record<string, boolean>>({});
|
||||
// Check if current plan order is less than Pro (order < 1 means FREE plan)
|
||||
let isPlanBelowPro = $derived(currentPlan?.order < 1);
|
||||
|
||||
let showUnarchiveModal = $state(false);
|
||||
let projectToUnarchive = $state<Models.Project | null>(null);
|
||||
let showDeleteModal = $state(false);
|
||||
@@ -97,7 +95,7 @@
|
||||
function isUnarchiveDisabled(): boolean {
|
||||
if (!organization || !currentPlan) return true;
|
||||
|
||||
if (organization.billingPlan === BillingPlan.FREE) {
|
||||
if (isPlanBelowPro) {
|
||||
const currentProjectCount = organization.projects?.length || 0;
|
||||
const projectLimit = currentPlan.projects || 0;
|
||||
|
||||
@@ -196,10 +194,15 @@
|
||||
|
||||
{#if projectsToArchive.length > 0}
|
||||
<div class="archive-projects-margin-top">
|
||||
<Accordion title="Archived projects" badge={`${projectsToArchive.length}`}>
|
||||
<Accordion
|
||||
title={isPlanBelowPro ? 'Archived projects' : 'Pending archive'}
|
||||
badge={`${projectsToArchive.length}`}>
|
||||
<Typography.Text tag="p" size="s">
|
||||
These projects have been archived and are read-only. You can view and migrate their
|
||||
data.
|
||||
{#if isPlanBelowPro}
|
||||
These projects are archived and require a plan upgrade to restore access.
|
||||
{:else}
|
||||
These projects will be archived at the end of your billing cycle.
|
||||
{/if}
|
||||
</Typography.Text>
|
||||
|
||||
<div class="archive-projects-margin">
|
||||
@@ -216,36 +219,6 @@
|
||||
<svelte:fragment slot="title">{formatted}</svelte:fragment>
|
||||
<svelte:fragment slot="status">
|
||||
<div class="status-container">
|
||||
<DropList
|
||||
bind:show={readOnlyInfoOpen[project.$id]}
|
||||
placement="bottom-start"
|
||||
noArrow>
|
||||
<Tag
|
||||
size="s"
|
||||
style="white-space: nowrap;"
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
readOnlyInfoOpen = {
|
||||
...readOnlyInfoOpen,
|
||||
[project.$id]: !readOnlyInfoOpen[project.$id]
|
||||
};
|
||||
}}>
|
||||
<Icon icon={IconInfo} size="s" />
|
||||
<span>Read only</span>
|
||||
</Tag>
|
||||
<svelte:fragment slot="list">
|
||||
<li
|
||||
class="drop-list-item u-width-250"
|
||||
style="padding: var(--space-5, 12px) var(--space-6, 16px)">
|
||||
<span class="u-block u-mb-8">
|
||||
Archived projects are read-only. You can view
|
||||
and migrate their data, but they no longer
|
||||
accept edits or requests.
|
||||
</span>
|
||||
</li>
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
<Popover let:toggle padding="none" placement="bottom-end">
|
||||
<Button
|
||||
text
|
||||
@@ -267,6 +240,7 @@
|
||||
>Unarchive project</ActionMenu.Item.Button>
|
||||
<ActionMenu.Item.Button
|
||||
leadingIcon={IconSwitchHorizontal}
|
||||
disabled={isUnarchiveDisabled()}
|
||||
on:click={() => handleMigrateProject(project)}
|
||||
>Migrate project</ActionMenu.Item.Button>
|
||||
<div class="action-menu-divider">
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
{#if activeProjects.length > 0}
|
||||
<CardContainer
|
||||
disableEmpty={!$canWriteProjects}
|
||||
total={data.projects.total}
|
||||
total={activeProjects.length}
|
||||
offset={data.offset}
|
||||
on:click={handleCreateProject}>
|
||||
{#each activeProjects as project}
|
||||
@@ -309,7 +309,7 @@
|
||||
name="Projects"
|
||||
limit={data.limit}
|
||||
offset={data.offset}
|
||||
total={data.projects.total} />
|
||||
total={activeProjects.length} />
|
||||
|
||||
<!-- Archived Projects Section -->
|
||||
<ArchiveProject
|
||||
|
||||
Reference in New Issue
Block a user