mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-27 02:42:25 +08:00
feat: add storage panel in setting (#4069)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
export { SettingModal, type SettingModalProps } from './modal';
|
||||
export { SettingHeader } from './setting-header';
|
||||
export { SettingRow } from './setting-row';
|
||||
export * from './storage-progess';
|
||||
export * from './workspace-detail-skeleton';
|
||||
export * from './workspace-list-skeleton';
|
||||
export { SettingWrapper } from './wrapper';
|
||||
|
||||
@@ -92,3 +92,55 @@ globalStyle(`${settingRow} .right-col`, {
|
||||
paddingLeft: '15px',
|
||||
flexShrink: 0,
|
||||
});
|
||||
|
||||
export const storageProgressContainer = style({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
export const storageProgressWrapper = style({
|
||||
flexGrow: 1,
|
||||
marginRight: '20px',
|
||||
});
|
||||
|
||||
globalStyle(`${storageProgressWrapper} .storage-progress-desc`, {
|
||||
fontSize: 'var(--affine-font-xs)',
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
height: '20px',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 2,
|
||||
});
|
||||
globalStyle(`${storageProgressWrapper} .storage-progress-bar-wrapper`, {
|
||||
height: '8px',
|
||||
borderRadius: '4px',
|
||||
backgroundColor: 'var(--affine-pure-black-10)',
|
||||
overflow: 'hidden',
|
||||
});
|
||||
export const storageProgressBar = style({
|
||||
height: '100%',
|
||||
backgroundColor: 'var(--affine-processing-color)',
|
||||
selectors: {
|
||||
'&.warning': {
|
||||
// Wait for design
|
||||
backgroundColor: '#FF7C09',
|
||||
},
|
||||
'&.danger': {
|
||||
backgroundColor: 'var(--affine-error-color)',
|
||||
},
|
||||
},
|
||||
});
|
||||
export const storageExtendHint = style({
|
||||
borderRadius: '4px',
|
||||
padding: '4px 8px',
|
||||
backgroundColor: 'var(--affine-background-secondary-color)',
|
||||
color: 'var(--affine-text-secondary-color)',
|
||||
fontSize: 'var(--affine-font-xs)',
|
||||
lineHeight: '20px',
|
||||
marginTop: 8,
|
||||
});
|
||||
globalStyle(`${storageExtendHint} a`, {
|
||||
color: 'var(--affine-link-color)',
|
||||
});
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { Button } from '@toeverything/components/button';
|
||||
import { Tooltip } from '@toeverything/components/tooltip';
|
||||
import clsx from 'clsx';
|
||||
import { useMemo, useRef } from 'react';
|
||||
|
||||
import * as styles from './share.css';
|
||||
|
||||
export interface StorageProgressProgress {
|
||||
max: number;
|
||||
value: number;
|
||||
onUpgrade: () => void;
|
||||
}
|
||||
|
||||
const transformBytesToMB = (bytes: number) => {
|
||||
return (bytes / 1024 / 1024).toFixed(2);
|
||||
};
|
||||
|
||||
const transformBytesToGB = (bytes: number) => {
|
||||
return (bytes / 1024 / 1024 / 1024).toFixed(2);
|
||||
};
|
||||
|
||||
export const StorageProgress = ({
|
||||
max: upperLimit,
|
||||
value,
|
||||
onUpgrade,
|
||||
}: StorageProgressProgress) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const ref = useRef(null);
|
||||
const percent = useMemo(
|
||||
() => Math.round((value / upperLimit) * 100),
|
||||
[upperLimit, value]
|
||||
);
|
||||
|
||||
const used = useMemo(() => transformBytesToMB(value), [value]);
|
||||
const max = useMemo(() => transformBytesToGB(upperLimit), [upperLimit]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.storageProgressContainer}>
|
||||
<div className={styles.storageProgressWrapper}>
|
||||
<div className="storage-progress-desc">
|
||||
<span>{t['com.affine.storage.used.hint']()}</span>
|
||||
<span>
|
||||
{used}MB/{max}GB
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="storage-progress-bar-wrapper">
|
||||
<div
|
||||
className={clsx(styles.storageProgressBar, {
|
||||
warning: percent > 80,
|
||||
danger: percent > 99,
|
||||
})}
|
||||
style={{ width: `${percent}%` }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Tooltip
|
||||
content={t['com.affine.storage.disabled.hint']()}
|
||||
portalOptions={{
|
||||
container: ref.current,
|
||||
}}
|
||||
>
|
||||
<div ref={ref}>
|
||||
<Button disabled onClick={onUpgrade}>
|
||||
{t['com.affine.storage.upgrade']()}
|
||||
</Button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{percent > 80 ? (
|
||||
<div className={styles.storageExtendHint}>
|
||||
{t['com.affine.storage.extend.hint']()}
|
||||
<a
|
||||
href="https://community.affine.pro/c/insider-general/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t['com.affine.storage.extend.link']()}
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
5
packages/graphql/src/graphql/blobs-size.gql
Normal file
5
packages/graphql/src/graphql/blobs-size.gql
Normal file
@@ -0,0 +1,5 @@
|
||||
query allBlobSizes {
|
||||
collectAllBlobSizes {
|
||||
size
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,19 @@ query blobSizes($workspaceId: String!) {
|
||||
}`,
|
||||
};
|
||||
|
||||
export const allBlobSizesQuery = {
|
||||
id: 'allBlobSizesQuery' as const,
|
||||
operationName: 'allBlobSizes',
|
||||
definitionName: 'collectAllBlobSizes',
|
||||
containsFile: false,
|
||||
query: `
|
||||
query allBlobSizes {
|
||||
collectAllBlobSizes {
|
||||
size
|
||||
}
|
||||
}`,
|
||||
};
|
||||
|
||||
export const changeEmailMutation = {
|
||||
id: 'changeEmailMutation' as const,
|
||||
operationName: 'changeEmail',
|
||||
|
||||
@@ -82,6 +82,13 @@ export type BlobSizesQuery = {
|
||||
collectBlobSizes: { __typename?: 'WorkspaceBlobSizes'; size: number };
|
||||
};
|
||||
|
||||
export type AllBlobSizesQueryVariables = Exact<{ [key: string]: never }>;
|
||||
|
||||
export type AllBlobSizesQuery = {
|
||||
__typename?: 'Query';
|
||||
collectAllBlobSizes: { __typename?: 'WorkspaceBlobSizes'; size: number };
|
||||
};
|
||||
|
||||
export type ChangeEmailMutationVariables = Exact<{
|
||||
id: Scalars['String']['input'];
|
||||
newEmail: Scalars['String']['input'];
|
||||
@@ -448,6 +455,11 @@ export type Queries =
|
||||
variables: BlobSizesQueryVariables;
|
||||
response: BlobSizesQuery;
|
||||
}
|
||||
| {
|
||||
name: 'allBlobSizesQuery';
|
||||
variables: AllBlobSizesQueryVariables;
|
||||
response: AllBlobSizesQuery;
|
||||
}
|
||||
| {
|
||||
name: 'getCurrentUserQuery';
|
||||
variables: GetCurrentUserQueryVariables;
|
||||
|
||||
@@ -530,5 +530,11 @@
|
||||
"com.affine.share-menu.ShareViaExportDescription": "Download a static copy of your page to share with others.",
|
||||
"com.affine.share-menu.ShareWithLink": "Share with link",
|
||||
"com.affine.share-menu.ShareWithLinkDescription": "Create a link you can easily share with anyone. The visitors will open your page in the form od a document",
|
||||
"com.affine.share-menu.ShareMode": "Share mode"
|
||||
"com.affine.share-menu.ShareMode": "Share mode",
|
||||
"com.affine.storage.title": "AFFiNE Cloud Storage",
|
||||
"com.affine.storage.upgrade": "Upgrade to Pro",
|
||||
"com.affine.storage.disabled.hint": "AFFiNE Cloud is currently in early access phase and is not supported for upgrading, please be patient and wait for our pricing plan.",
|
||||
"com.affine.storage.used.hint": "Space used",
|
||||
"com.affine.storage.extend.hint": "The usage has reached its maximum capacity, AFFiNE Cloud is currently in early access phase and is not supported for upgrading, please be patient and wait for our pricing plan. ",
|
||||
"com.affine.storage.extend.link": "To get more information click here."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user