Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(platform): Cancel app data storage service #2797

Merged
merged 22 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
95cd091
feat(platform): Cancel app data storage service
Cosmin-Parvulescu Dec 5, 2023
ca11ddf
Add batch queue functionality and logging
Cosmin-Parvulescu Dec 6, 2023
1f3c8fa
Revert "Add batch queue functionality and logging"
Cosmin-Parvulescu Dec 11, 2023
a1d3a1e
Add storage form and buttons for enabling/disabling app data package
Cosmin-Parvulescu Dec 11, 2023
e32bd03
Refactor storage.ostrich.tsx to handle null values in appDetails.exte…
Cosmin-Parvulescu Dec 11, 2023
f0ca007
Upgrade wrangler
Cosmin-Parvulescu Dec 11, 2023
48eccc9
Add queue functionality for deleting app data
Cosmin-Parvulescu Dec 12, 2023
948a990
Refactor external app data package definition and cancellation
Cosmin-Parvulescu Dec 12, 2023
2f8f960
Add ExternalAppDataPackageStatus enum
Cosmin-Parvulescu Dec 12, 2023
b00fed1
Refactor authorization and starbase nodes, and update storage.ostrich…
Cosmin-Parvulescu Dec 22, 2023
27cd626
Update storage.ostrich.tsx with comments on package usage
Cosmin-Parvulescu Dec 22, 2023
4076f0b
Update limit constant value to 2000
Cosmin-Parvulescu Jan 10, 2024
8ce8d2a
Add sync queue configuration to dev environment
Cosmin-Parvulescu Jan 10, 2024
c77233b
Add script to generate test data for app authorizations
Cosmin-Parvulescu Jan 10, 2024
a69b6ad
Add script to generate nodes and edges for testing purposes
Cosmin-Parvulescu Jan 10, 2024
5c228ee
Cleanup
Cosmin-Parvulescu Jan 10, 2024
4d31a5f
Add Spinner component for service cancellation progress
Cosmin-Parvulescu Jan 10, 2024
984a21c
Added cancellation modal
Cosmin-Parvulescu Jan 10, 2024
70800cf
Update core-queue configuration
Cosmin-Parvulescu Jan 11, 2024
2e862ca
Refactor fetch function and remove console logs
Cosmin-Parvulescu Jan 11, 2024
2993c9f
Update kv_namespaces in wrangler.current.toml
Cosmin-Parvulescu Jan 11, 2024
a17bd39
Removed unnecessary try catch
Cosmin-Parvulescu Jan 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
298 changes: 240 additions & 58 deletions apps/console/app/routes/apps/$clientId/storage.ostrich.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { useOutletContext, useSubmit, useTransition } from '@remix-run/react'
import { Text } from '@proofzero/design-system'
import { Form, useOutletContext, useTransition } from '@remix-run/react'
import { Button, Text } from '@proofzero/design-system'
import { DocumentationBadge } from '~/components/DocumentationBadge'
import { ReadOnlyInput } from '@proofzero/design-system/src/atoms/form/ReadOnlyInput'
import { ToastType, toast } from '@proofzero/design-system/src/atoms/toast'
import { getRollupReqFunctionErrorWrapper } from '@proofzero/utils/errors'
import { ActionFunction } from '@remix-run/cloudflare'
import createCoreClient from '@proofzero/platform-clients/core'
import { generateTraceContextHeaders } from '@proofzero/platform-middleware/trace'
import { getAuthzHeaderConditionallyFromToken } from '@proofzero/utils'
import { requireJWT } from '~/utilities/session.server'
import { BadRequestError, InternalServerError } from '@proofzero/errors'
import { InputToggle } from '@proofzero/design-system/src/atoms/form/InputToggle'
import classNames from 'classnames'
import { appDetailsProps } from '~/types'
import { ExternalAppDataPackageType } from '@proofzero/types/billing'
import {
HiOutlineShoppingCart,
HiOutlineTrash,
HiOutlineX,
} from 'react-icons/hi'
import { ExternalAppDataPackageStatus } from '@proofzero/platform.starbase/src/jsonrpc/validators/externalAppDataPackageDefinition'
import { Spinner } from '@proofzero/design-system/src/atoms/spinner/Spinner'
import { useState } from 'react'
import { Modal } from '@proofzero/design-system/src/molecules/modal/Modal'
import dangerVector from '~/images/danger.svg'
import { Input } from '@proofzero/design-system/src/atoms/form/Input'

export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
async ({ request, context, params }) => {
Expand Down Expand Up @@ -54,72 +62,246 @@ export const action: ActionFunction = getRollupReqFunctionErrorWrapper(
}
)

export const ConfirmCancelModal = ({
isOpen,
setIsOpen,
}: {
isOpen: boolean
setIsOpen: (val: boolean) => void
}) => {
const [confirmationText, setConfirmationText] = useState('')
const transition = useTransition()

return (
<Modal isOpen={isOpen} handleClose={() => setIsOpen(false)}>
<div
className={`w-fit rounded-lg bg-white p-4
text-left transition-all sm:p-5 overflow-y-auto flex items-start space-x-4 max-w-[512px]`}
>
<img src={dangerVector} alt="danger" />

<div className="flex-1">
<div className="flex flex-row items-center justify-between w-full mb-2">
<Text size="lg" weight="medium" className="text-gray-900">
Cancel Service
</Text>
<button
className={`bg-white p-2 rounded-lg text-xl cursor-pointer
hover:bg-[#F3F4F6]`}
onClick={() => {
setIsOpen(false)
}}
>
<HiOutlineX />
</button>
</div>

<Form
method="post"
onSubmit={() => {
setConfirmationText('')
setIsOpen(false)
}}
>
<input type="hidden" name="op" value="disable" />
<section className="mb-4">
<Text size="sm" weight="normal" className="text-gray-500 my-3">
Are you sure you want to stop{' '}
<Text type="span" weight="semibold" size="sm">
App Data Storage?
</Text>
<br /> This action will permanently delete all data from the
service and any paid package used by the service will not be
renewed in next billing cycle.
</Text>

<Text size="sm" weight="normal" className="text-gray-500 my-3">
* Type CANCEL to confirm
</Text>

<Input
id="confirm_text"
placeholder="CANCEL"
value={confirmationText}
required
className="mb-12"
onChange={(e) => {
setConfirmationText(e.target.value)
}}
/>
</section>

<div className="flex justify-end items-center space-x-3">
<Button btnType="secondary-alt" onClick={() => setIsOpen(false)}>
Cancel
</Button>
<Button
disabled={
confirmationText !== 'CANCEL' || transition.state !== 'idle'
}
type="submit"
btnType="dangerous"
>
Delete
</Button>
</div>
</Form>
</div>
</div>
</Modal>
)
}

export default () => {
const { appDetails } = useOutletContext<{
appDetails: appDetailsProps
}>()

const trans = useTransition()
const submit = useSubmit()
const [isModalOpen, setIsModalOpen] = useState(false)

return (
<section className="flex flex-col space-y-5">
<div className="flex flex-row items-center space-x-3">
<Text size="2xl" weight="semibold" className="text-gray-900">
Storage
</Text>
<DocumentationBadge
url={'https://docs.rollup.id/platform/console/storage'}
/>
</div>
<>
{isModalOpen && (
<ConfirmCancelModal isOpen={isModalOpen} setIsOpen={setIsModalOpen} />
)}
<section className="flex flex-col space-y-5">
<div className="flex flex-row items-center space-x-3">
<Text size="2xl" weight="semibold" className="text-gray-900">
Storage
</Text>
<DocumentationBadge
url={'https://docs.rollup.id/platform/console/storage'}
/>
</div>

<section className="flex-1 bg-white border rounded-lg px-4 pt-3 pb-6">
<section className="flex flex-row justify-between items-center">
<div className="flex flex-row gap-2 items-center">
<Text size="lg" weight="semibold">
App Data Storage
{appDetails.externalAppDataPackageDefinition?.status ===
ExternalAppDataPackageStatus.Deleting && (
<section className="my-4 p-4 flex flex-row items-center gap-3 bg-orange-50">
<Spinner color="#F97316" size={20} margin="unset" weight="slim" />
<Text size="sm" weight="medium" className="text-orange-600">
Service cancellation in progress. Existing application data being
deleted...{' '}
</Text>
</section>
)}

<div
className={classNames('w-2 h-2 rounded-full', {
'bg-green-500': Boolean(
appDetails.externalAppDataPackageDefinition
),
'bg-gray-300': !Boolean(
appDetails.externalAppDataPackageDefinition
),
})}
></div>
</div>
<section className="flex-1 bg-white border rounded-lg px-4 pt-3 pb-6">
<section className="flex flex-row justify-between items-center">
<div className="flex flex-row gap-2 items-center">
<Text size="lg" weight="semibold">
App Data Storage
</Text>

<InputToggle
id="toggle_storage"
checked={Boolean(appDetails.externalAppDataPackageDefinition)}
onToggle={() => {
submit(
{
op: Boolean(appDetails.externalAppDataPackageDefinition)
? 'disable'
: 'enable',
},
{
method: 'post',
}
)
}}
disabled={trans.state !== 'idle'}
/>
</section>
{appDetails.externalAppDataPackageDefinition?.status ===
ExternalAppDataPackageStatus.Deleting ? (
<div className="w-2 h-2 rounded-full bg-orange-500"></div>
) : (
<div
className={classNames('w-2 h-2 rounded-full', {
'bg-green-500': Boolean(
appDetails.externalAppDataPackageDefinition
),
'bg-gray-300': !Boolean(
appDetails.externalAppDataPackageDefinition
),
})}
></div>
)}
</div>

<section className="mt-2">
<Text size="sm" className="text-gray-600">
App Data Storage service provides a hassle-free way to store and
retrieve per-user data for your application. Once activated, the
service can be accessed through our Galaxy API and it supports
storing data up to 128kb, per user.
</Text>
{appDetails.externalAppDataPackageDefinition?.status !==
ExternalAppDataPackageStatus.Deleting && (
<>
{!Boolean(appDetails.externalAppDataPackageDefinition) && (
<Form method="post">
<input type="hidden" name="op" value="enable" />
<Button
btnType="primary-alt"
className="flex flex-row items-center gap-3"
type="submit"
>
<HiOutlineShoppingCart className="w-3.5 h-3.5" />
<Text>Purchase Package</Text>
</Button>
</Form>
)}
{Boolean(appDetails.externalAppDataPackageDefinition) && (
<Button
btnType="dangerous-alt"
className="flex flex-row items-center gap-3"
type="submit"
onClick={() => {
setIsModalOpen(true)
}}
>
<HiOutlineTrash className="w-3.5 h-3.5" />
<Text>Cancel Service</Text>
</Button>
)}
</>
)}
</section>

<section className="mt-2">
<Text size="sm" className="text-gray-600">
App Data Storage service provides a hassle-free way to store and
retrieve per-user data for your application. <br /> Once
activated, the service can be accessed through our Galaxy API and
it supports storing data up to 128kb, per user.
</Text>
</section>
<section className="mt-4">
<div className="w-full h-px bg-gray-200"></div>
<div className="flex flex-row justify-between items-center py-2">
<Text size="sm" className="text-gray-800">
Current Package:
</Text>
<Text size="sm" className="text-gray-500">
{appDetails.externalAppDataPackageDefinition?.packageDetails
.title ?? 'No active package'}
</Text>
</div>
<div className="w-full h-px bg-gray-200"></div>
<div className="flex flex-row justify-between items-center py-2">
<Text size="sm" className="text-gray-800">
Reads:
</Text>
{Boolean(appDetails.externalAppDataPackageDefinition) ? (
<Text size="sm" className="text-gray-500">
{
appDetails.externalAppDataPackageDefinition?.packageDetails
.reads
}{' '}
/ month
</Text>
) : (
<Text size="sm" className="text-gray-500">
-
</Text>
)}
</div>
<div className="w-full h-px bg-gray-200"></div>
<div className="flex flex-row justify-between items-center pt-2">
<Text size="sm" className="text-gray-800">
Writes:
</Text>
{Boolean(appDetails.externalAppDataPackageDefinition) ? (
<Text size="sm" className="text-gray-500">
{
appDetails.externalAppDataPackageDefinition?.packageDetails
.writes
}{' '}
/ month
</Text>
) : (
<Text size="sm" className="text-gray-500">
-
</Text>
)}
</div>
</section>
</section>
</section>
</section>
</>
)
}
4 changes: 2 additions & 2 deletions apps/console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
},
"devDependencies": {
"@babel/core": "7.20.2",
"@cloudflare/workers-types": "4.20221111.1",
"@cloudflare/workers-types": "4.20231121.0",
"@mdx-js/react": "2.1.5",
"@playwright/test": "1.35.1",
"@proofzero/platform.starbase": "workspace:*",
Expand All @@ -79,7 +79,7 @@
"npm-run-all": "4.1.5",
"tailwindcss": "3.3.3",
"typescript": "5.0.4",
"wrangler": "3.2.0"
"wrangler": "3.18"
},
"engines": {
"node": ">=16.13"
Expand Down
4 changes: 2 additions & 2 deletions apps/passport/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
},
"devDependencies": {
"@babel/core": "^7.20.2",
"@cloudflare/workers-types": "4.20221111.1",
"@cloudflare/workers-types": "4.20231121.0",
"@mdx-js/react": "^1.6.22",
"@playwright/test": "1.35.1",
"@remix-run/dev": "1.14.0",
Expand Down Expand Up @@ -106,7 +106,7 @@
"tailwindcss": "3.3.3",
"typescript": "5.0.4",
"webpack": "5.75.0",
"wrangler": "3.2.0"
"wrangler": "3.18"
},
"engines": {
"node": ">=16.13"
Expand Down
4 changes: 2 additions & 2 deletions apps/profile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
},
"devDependencies": {
"@babel/core": "7.20.2",
"@cloudflare/workers-types": "4.20221111.1",
"@cloudflare/workers-types": "4.20231121.0",
"@mdx-js/react": "2.1.5",
"@playwright/test": "1.35.1",
"@remix-run/dev": "1.14.0",
Expand Down Expand Up @@ -111,7 +111,7 @@
"tailwindcss": "3.3.3",
"typescript": "5.0.4",
"webpack": "5.75.0",
"wrangler": "3.2.0"
"wrangler": "3.18"
},
"engines": {
"node": ">=16.13"
Expand Down
Loading
Loading