diff --git a/src/react/next-architecture/adaptors/metrics/IMetricsAdaptor.ts b/src/react/next-architecture/adaptors/metrics/IMetricsAdaptor.ts new file mode 100644 index 000000000..b4862f307 --- /dev/null +++ b/src/react/next-architecture/adaptors/metrics/IMetricsAdaptor.ts @@ -0,0 +1,27 @@ +import { Bucket } from 'aws-sdk/clients/s3'; +import { LatestUsedCapacity } from '../../domain/entities/metrics'; + +export type BucketLatestUsedCapacity = { + bucketName: string; +} & LatestUsedCapacity; +export type AccountLatestUsedCapacity = { + accountId: string; +} & LatestUsedCapacity; +export type LocationLatestUsedCapacity = { + locationId: string; +} & LatestUsedCapacity; + +export interface IMetricsAdaptor { + listBucketsLatestUsedCapacity( + buckets: Bucket[], + ): Promise; + listLocationsLatestUsedCapacity( + locationIds: string[], + ): Promise; + listAccountLocationsLatestUsedCapacity( + accountId: string, + ): Promise; + listAccountsLatestUsedCapacity( + accountIds: string[], + ): Promise; +} diff --git a/src/react/next-architecture/adaptors/metrics/PensieveMetricsAdaptor.ts b/src/react/next-architecture/adaptors/metrics/PensieveMetricsAdaptor.ts new file mode 100644 index 000000000..e096ebaf4 --- /dev/null +++ b/src/react/next-architecture/adaptors/metrics/PensieveMetricsAdaptor.ts @@ -0,0 +1,30 @@ +import { Bucket } from 'aws-sdk/clients/s3'; +import { + AccountLatestUsedCapacity, + BucketLatestUsedCapacity, + LocationLatestUsedCapacity, + IMetricsAdaptor, +} from './IMetricsAdaptor'; + +export class PensieveMetricsAdaptor implements IMetricsAdaptor { + listAccountLocationsLatestUsedCapacity( + accountId: string, + ): Promise { + throw new Error('Method not implemented.'); + } + async listAccountsLatestUsedCapacity( + accountIds: string[], + ): Promise { + throw new Error('Method not implemented.'); + } + async listBucketsLatestUsedCapacity( + buckets: Bucket[], + ): Promise { + throw new Error('Method not implemented.'); + } + async listLocationsLatestUsedCapacity( + locationIds: string[], + ): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/src/react/next-architecture/domain/business/accounts.ts b/src/react/next-architecture/domain/business/accounts.ts new file mode 100644 index 000000000..00dc1f91c --- /dev/null +++ b/src/react/next-architecture/domain/business/accounts.ts @@ -0,0 +1,29 @@ +import { IMetricsAdaptor } from '../../adaptors/metrics/IMetricsAdaptor'; +import { AccountsPromiseResult } from '../entities/account'; + +/** + * The hook returns all the accounts and the storage metric for the first 20 accounts. + * @param metricsAdaptor + */ +export const useListAccounts = ({ + metricsAdaptor, +}: { + metricsAdaptor: IMetricsAdaptor; +}): AccountsPromiseResult => { + throw new Error('Method not implemented.'); +}; + +/** + * The hook returns the latest used capacity for a specific account. + * @param metricsAdaptor + * @param accountId + */ +export const useAccountLatestUsedCapacity = ({ + metricsAdaptor, + accountId, +}: { + metricsAdaptor: IMetricsAdaptor; + accountId: string; +}): AccountsPromiseResult => { + throw new Error('Method not implemented.'); +}; diff --git a/src/react/next-architecture/domain/business/buckets.ts b/src/react/next-architecture/domain/business/buckets.ts new file mode 100644 index 000000000..88d375b59 --- /dev/null +++ b/src/react/next-architecture/domain/business/buckets.ts @@ -0,0 +1,44 @@ +import { IMetricsAdaptor } from '../../adaptors/metrics/IMetricsAdaptor'; +import { + BucketLatestUsedCapacityPromiseResult, + BucketLocationConstraintPromiseResult, + BucketsPromiseResult, +} from '../entities/bucket'; + +/** + * The hook returns the full list of buckets plus the locations and metrcis of the first 20 buckets. + */ +export const useListBucketsForCurrentAccount = ({ + metricsAdaptor, +}: { + metricsAdaptor: IMetricsAdaptor; +}): BucketsPromiseResult => { + throw new Error('Method not implemented.'); +}; + +/** + * The hook returns the location constraint for a specific bucket. + * It will be called within the Table Cell on demande. + * @param bucketName name of the bucket + */ +export const useBucketLocationConstraint = ({ + bucketName, +}: { + bucketName: string; +}): BucketLocationConstraintPromiseResult => { + throw new Error('Method not implemented.'); +}; + +/** + * The hook returns the latest used capacity for a specific bucket. + * @param bucketName name of the bucket + */ +export const useBucketLatestUsedCapacity = ({ + metricsAdaptor, + bucketName, +}: { + metricsAdaptor: IMetricsAdaptor; + bucketName: string; +}): BucketLatestUsedCapacityPromiseResult => { + throw new Error('Method not implemented.'); +}; diff --git a/src/react/next-architecture/domain/business/locations.ts b/src/react/next-architecture/domain/business/locations.ts new file mode 100644 index 000000000..8e50da6fd --- /dev/null +++ b/src/react/next-architecture/domain/business/locations.ts @@ -0,0 +1,22 @@ +import { IMetricsAdaptor } from '../../adaptors/metrics/IMetricsAdaptor'; +import { LocationsPromiseResult } from '../entities/location'; + +/** + * The hook returns all the locations and it's metrics + * @param metricsAdaptor + */ +export const useListLocations = ({ + metricsAdaptor, +}: { + metricsAdaptor: IMetricsAdaptor; +}): LocationsPromiseResult => { + throw new Error('Method not implemented.'); +}; + +export const useListLocationsForCurrentAccount = ({ + metricsAdaptor, +}: { + metricsAdaptor: IMetricsAdaptor; +}): LocationsPromiseResult => { + throw new Error('Method not implemented.'); +}; diff --git a/src/react/next-architecture/domain/entities/account.ts b/src/react/next-architecture/domain/entities/account.ts new file mode 100644 index 000000000..43e59b4ab --- /dev/null +++ b/src/react/next-architecture/domain/entities/account.ts @@ -0,0 +1,16 @@ +import { LatestUsedCapacity } from './metrics'; +import { PromiseResult } from './promise'; + +export type AccountLatestUsedCapacityPromiseResult = { + usedCapacity: PromiseResult; +}; + +type Account = { + id: string; + accountName: string; + creationDate: Date; +} & AccountLatestUsedCapacityPromiseResult; + +export type AccountsPromiseResult = { + accounts: PromiseResult; +}; diff --git a/src/react/next-architecture/domain/entities/bucket.ts b/src/react/next-architecture/domain/entities/bucket.ts new file mode 100644 index 000000000..b327b6c2d --- /dev/null +++ b/src/react/next-architecture/domain/entities/bucket.ts @@ -0,0 +1,20 @@ +import { LatestUsedCapacity } from './metrics'; +import { PromiseResult } from './promise'; + +export type BucketLocationConstraintPromiseResult = { + locationConstraint: PromiseResult; +}; + +export type BucketLatestUsedCapacityPromiseResult = { + usedCapacity: PromiseResult; +}; + +type Bucket = BucketLocationConstraintPromiseResult & { + bucketName: string; + creationDate: Date; + usedCapacity: PromiseResult; +}; + +export type BucketsPromiseResult = { + buckets: PromiseResult; +}; diff --git a/src/react/next-architecture/domain/entities/location.ts b/src/react/next-architecture/domain/entities/location.ts new file mode 100644 index 000000000..daa6a91fc --- /dev/null +++ b/src/react/next-architecture/domain/entities/location.ts @@ -0,0 +1,14 @@ +import { LatestUsedCapacity } from './metrics'; +import { PromiseResult } from './promise'; + +type Location = { + id: string; + name: string; + type: string; + usedCapacity: PromiseResult; + targetBucket?: string; +}; + +export type LocationsPromiseResult = { + locations: PromiseResult; +}; diff --git a/src/react/next-architecture/domain/entities/metrics.ts b/src/react/next-architecture/domain/entities/metrics.ts new file mode 100644 index 000000000..1e06e3e16 --- /dev/null +++ b/src/react/next-architecture/domain/entities/metrics.ts @@ -0,0 +1,12 @@ +export type LatestUsedCapacity = + | { + type: 'noMetrics'; + } + | { + type: 'hasMetrics'; + usedCapacity: { + current: number; + nonCurrent: number; + }; + measuredOn: Date; + }; diff --git a/src/react/next-architecture/domain/entities/promise.ts b/src/react/next-architecture/domain/entities/promise.ts new file mode 100644 index 000000000..2fb2787c6 --- /dev/null +++ b/src/react/next-architecture/domain/entities/promise.ts @@ -0,0 +1,27 @@ +type Idle = 'idle'; +type Loading = 'loading'; +type NotResolved = Idle | Loading; +type Success = 'success'; +type Error = 'error'; + +export type PromiseStatus = NotResolved | Success | Error; + +interface PromiseSucceedResult { + status: Success; + value: T; +} + +interface PromiseRejectedResult { + status: Error; + title: string; + reason: string; +} + +interface PromiseNotResolved { + status: NotResolved; +} + +export type PromiseResult = + | PromiseNotResolved + | PromiseSucceedResult + | PromiseRejectedResult; diff --git a/src/react/next-architecture/ui/MetricsAdaptorProvider.tsx b/src/react/next-architecture/ui/MetricsAdaptorProvider.tsx new file mode 100644 index 000000000..34d0ee967 --- /dev/null +++ b/src/react/next-architecture/ui/MetricsAdaptorProvider.tsx @@ -0,0 +1,30 @@ +import { createContext, useContext } from 'react'; +import { PensieveMetricsAdaptor } from '../adaptors/metrics/PensieveMetricsAdaptor'; +import { IMetricsAdaptor } from '../adaptors/metrics/IMetricsAdaptor'; + +const _MetricsAdaptorContext = createContext(null); + +export const useMetricsAdaptor = (): IMetricsAdaptor => { + const context = useContext(_MetricsAdaptorContext); + + if (!context) { + throw new Error( + 'The useMetricsAdaptor hook can only be used within MetricsAdaptorProvider.', + ); + } + + return context.metricsAdaptor; +}; + +const MetricsAdaptorProvider = ({ children }: { children: JSX.Element }) => { + // We only need to change to SCUBA Adaptor later on. + const metricsAdaptor = new PensieveMetricsAdaptor(); + return ( + <_MetricsAdaptorContext.Provider value={{ metricsAdaptor }}> + {children} + + ); +}; +export default MetricsAdaptorProvider;