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

Classes hub #410

Merged
merged 43 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
48461f0
stachign code
Jul 24, 2023
68a4c4f
adding cards
Jul 25, 2023
4068b3d
adding more card content
Jul 25, 2023
48699f9
more card updates
Jul 27, 2023
fb0dc1e
more styles
Jul 28, 2023
1675bd2
finishing design
Jul 29, 2023
bd586c8
fixing padding
Jul 29, 2023
e335e2a
more plan id's
Jul 31, 2023
7aefa07
simplifying bar
Jul 31, 2023
f290ced
fixing free card
Jul 31, 2023
cb6a551
clean up
Aug 1, 2023
92d8fd5
adding version tracker
Aug 1, 2023
6ed5f97
pr callouts
Aug 2, 2023
ab552b4
adding lilypad 2.0 (#401)
nickgrato Aug 2, 2023
548afcc
loading section
Aug 2, 2023
e044912
merge main
Aug 2, 2023
33602cb
merge main
Aug 2, 2023
ee2216a
more marketing page designs and new utility classes
Aug 3, 2023
635775e
adding legacy section and breaking up the form component in the email…
Aug 4, 2023
a308060
making the grid section
Aug 4, 2023
a2ad8b8
adding slider
Aug 7, 2023
00f990a
adding assets
Aug 7, 2023
f79bf8e
finishing touches
Aug 7, 2023
83d1e01
fixing chf price
Aug 7, 2023
ed8c8ee
fixing build
Aug 7, 2023
477911c
merging base
Aug 8, 2023
7a14c0b
pr clean up
Aug 8, 2023
114d360
new pages:
Aug 8, 2023
e5be748
staching code
Aug 8, 2023
fd01d4a
more styles.
Aug 14, 2023
207121a
pr callouts
Aug 14, 2023
e1e855a
adding hub class
Aug 15, 2023
d1f1a65
staching code
Aug 15, 2023
27e832c
staching code
Aug 16, 2023
d1e65b1
fixing merge conflicts
Sep 5, 2023
d320ae5
organizing dependancies
Sep 5, 2023
58c94b8
fixing file name
Sep 5, 2023
31c62a8
merging main
Sep 6, 2023
484c393
merging blog
Sep 6, 2023
b20dc7b
refining more of the components to use the Hub class, this has taken …
Sep 6, 2023
5ae4c57
updating TierT
Sep 14, 2023
3a1ee1e
spelling and error consoles.
Sep 14, 2023
850c700
small clean up
Sep 18, 2023
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
127 changes: 127 additions & 0 deletions client/classes/Hub.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { TierT, HubT, StorageStateE, StatusE, LastErrorE } from 'types/General';
import {
validateHubSubdomain as validateSubdomain,
validationResponseT,
updateHub,
} from 'services/hub.service';

export const loadingHub: HubT = {
ccuLimit: 0,
currentCcu: 0,
currentStorageMb: 0,
domain: '',
hubId: '',
name: 'Untitled Hub',
status: StatusE.CREATING,
lastError: null,
storageLimitMb: 0,
subdomain: '',
tier: 'p0',
};

export default class Hub {
ccuLimit: number;
currentCcu: number | null;
currentStorageMb: number | null;
hubId: string;
name: string;
status: StatusE;
lastError: LastErrorE | null;
storageLimitMb: number;
subdomain: string;
domain: string;
fullDomain: string;
tier: TierT;

constructor({
ccuLimit,
currentCcu,
currentStorageMb,
hubId,
name,
status,
lastError,
storageLimitMb,
subdomain,
domain,
tier,
}: HubT) {
this.ccuLimit = ccuLimit;
this.currentCcu = currentCcu;
this.currentStorageMb = currentStorageMb;
this.hubId = hubId;
this.name = name;
this.status = status;
this.lastError = lastError;
this.storageLimitMb = storageLimitMb;
this.subdomain = subdomain;
this.domain = domain;
this.fullDomain = `https://${subdomain}.${domain}`;
this.tier = tier;
}

/**
* Round Storage MB
* @returns string
*/
roundedCurrentStorageMb(): string {
if (this.currentStorageMb == null) return 'Configuring';
// TODO - In the future, I guess we'd use i18n routing and useRouter to get the current
// locale, but for now default to "en-US".
return new Intl.NumberFormat('en-US', {
maximumFractionDigits: 2,
}).format(this.currentStorageMb);
}

/**
* Storage Percentage
* @returns number
*/
getStoragePercent(): number {
if (this.currentStorageMb === 0 || this.currentStorageMb === null) return 0;
return Math.min(100, this.currentStorageMb / this.storageLimitMb) * 100;
}

/**
* Storage State
* @returns StorageStateE
*/
getStorageState(): StorageStateE {
const storagePercent = this.getStoragePercent();
const warningThreshold = 75;
const criticalThreshold = 100;
let status = StorageStateE.DEFAULT;

storagePercent > warningThreshold && (status = StorageStateE.WARNING);
storagePercent >= criticalThreshold && (status = StorageStateE.CRITICAL);

return status;
}

/**
* Validate subdomain for bad words or already in use
* @param value
* @returns Promise<validationResponseT>
*/
async validateHubSubdomain(value: string): Promise<validationResponseT> {
return await validateSubdomain(this.hubId, value);
}

/**
* Update Hub Subdomain
* @param value
* @returns response status
*/
async updateSubdomain(
value: string
): Promise<{ status: number | undefined }> {
const response = await updateHub(this.hubId, {
...this,
subdomain: value,
});

return {
status: response?.status,
};
}
}
105 changes: 34 additions & 71 deletions client/components/modules/hubs/HubCard/HubCard.tsx
Original file line number Diff line number Diff line change
@@ -1,116 +1,81 @@
import { useContext, useMemo, useState } from 'react';
import { useContext, useState, useMemo } from 'react';
import styles from './HubCard.module.scss';
import { HubT, UpdateHubT, LastErrorE, StatusE } from 'types/General';
import { HubT, LastErrorE, StatusE } from 'types/General';
import { Message } from './Message';
import { StoreContext } from 'contexts/StoreProvider';
import { updateHub } from 'services/hub.service';
import ErrorBox from './ErrorBox';
import HubLink from './HubLink';
import HubLoading from './HubLoading';
import HubCardHeader from './HubCardHeader';
import HubCardFooter from './HubCardFooter';
import Hub from 'classes/Hub';

type HubCardPropsT = {
hub: HubT;
refreshHubData?: Function;
classProp?: string;
};

const HubCard = ({ hub, refreshHubData, classProp = '' }: HubCardPropsT) => {
const HubCard = ({ hub: _hub, refreshHubData, classProp }: HubCardPropsT) => {
const storeContext = useContext(StoreContext);
const { domain, hubId, status, subdomain, lastError } = hub;
const hub = useMemo(() => new Hub(_hub), [_hub]);
const [showRevertError, setShowRevertError] = useState<boolean>(
lastError === LastErrorE.SUBDOMAIN_REVERTED
hub.lastError === LastErrorE.SUBDOMAIN_REVERTED
);

/**
* Submit Update Hub
* @param updatedHub
* @param callback
* Updating Hub has failed - try again
*/
const submit = async (updatedHub: UpdateHubT, callback: Function) => {
const onTryReupdate = async () => {
/**
* Note: use session data 'storeContext.lastSubmittedSubdomain' and
* try and updates the Hub again.
*/
try {
const resp = await updateHub(hub.hubId, updatedHub);
const resp = await hub.updateSubdomain(
storeContext.lastSubmittedSubdomain.subdomain
);
// Refresh data after update.
if (resp?.status === 200) {
callback();
() => refreshHubData && refreshHubData();
} else {
handleError();
console.error('Sorry, there was an error updating this Hub.');
}
} catch (error) {
console.error(error);
}
};

/**
* Updating Hub has failed - try again
*/
const onTryReupdate = () => {
/**
* Note: use session data 'storeContext.lastSubmittedSubdomain' and
* try and updates the Hub again.
*/
const updatedHub: UpdateHubT = {
...hub,
subdomain: storeContext.lastSubmittedSubdomain.subdomain,
};

submit(updatedHub, () => refreshHubData && refreshHubData());
};

/**
* Submit hub no longer needs to be in reverted state.
*/
const handleOnCloseError = () => {
// patch the hub with lastError = '' to clear out the error.
const updatedHub: UpdateHubT = {
...hub,
lastError: '',
};
submit(updatedHub, () => setShowRevertError(false));
};

const handleError = () => {
console.error('Sorry, there was an error updating this Hub.');
};

/**
* Check if session data is still holding last submitted domain
* to display 'try again button'
* @returns Boolean
*/
const canTryAgain = (): boolean => {
const { subdomain: _subdomain, hubId: _hubId } =
storeContext.lastSubmittedSubdomain;
if (_subdomain === '' || _hubId !== hubId) return false;
const { subdomain, hubId } = storeContext.lastSubmittedSubdomain;
if (subdomain === '' || hubId !== hub.hubId) return false;

return true;
};

/**
* Hide / Show Card Footer
*/
const footerVisible = useMemo(() => {
return status === StatusE.READY;
}, [status]);

/**
* Hide / Show Loader
*/
const loadingVisible = useMemo(() => {
return status === StatusE.CREATING || status === StatusE.UPDATING;
}, [status]);
const loadingVisible = () => {
return hub.status === StatusE.CREATING || hub.status === StatusE.UPDATING;
};

return (
<div className={`${styles.card_wrapper} ${classProp}`}>
<div className={styles.card_container}>
{/* HEADER */}
<HubCardHeader status={status} hubId={hubId} />
<HubCardHeader status={hub.status} hubId={hub.hubId} />

{/* BODY */}
<div className={styles.card_body}>
{/* TODO - figure out if a name is applied to a hub off the bat before we put "untitled hub"
here statically, might be able to just pull w/e through */}
<div className={`${styles.card_name} ${styles[status]}`}>Hub</div>
<div className={`${styles.card_name} ${styles[hub.status]}`}>Hub</div>

{/* Did Revert Error */}
{showRevertError && (
Expand All @@ -119,56 +84,54 @@ const HubCard = ({ hub, refreshHubData, classProp = '' }: HubCardPropsT) => {
message={Message.updateSubdomainErrorMessage}
onTryAgainClick={onTryReupdate}
canTryAgain={canTryAgain()}
onClose={handleOnCloseError}
onClose={() => setShowRevertError(false)}
/>
)}

{/* Critical Error
The user can not try aagin on critical error
have the only contact button.
*/}
{lastError === LastErrorE.SUBDOMAIN_ERROR && (
{hub.lastError === LastErrorE.SUBDOMAIN_ERROR && (
<ErrorBox message={Message.criticalFailMessage} />
)}

{/* Create Error
This error takes place when the hub first tries to build
and fails to do so.
*/}
{lastError === LastErrorE.CREATING_ERROR && (
{hub.lastError === LastErrorE.CREATING_ERROR && (
<ErrorBox message={Message.createFailMessage} />
)}

{/* Default Error
This error takes place if the communication with the server fails (http server error)
and we need a "catch all" error status to show the user.
*/}
{lastError === LastErrorE.ERROR && (
{hub.lastError === LastErrorE.ERROR && (
<ErrorBox message={Message.errorMessage} />
)}

{/* Loading Subdomain Updates */}
{loadingVisible && (
{loadingVisible() && (
<HubLoading
loadingMessage={
status === StatusE.CREATING
hub.status === StatusE.CREATING
? Message.creatingMessage
: Message.updatingMessage
}
/>
)}

{/* Subdomain is ready and available */}
{status === StatusE.READY && (
<HubLink domain={domain} subdomain={subdomain} />
)}
{hub.status === StatusE.READY && <HubLink url={hub.fullDomain} />}
</div>

{/* FOOTER */}
{footerVisible && (
{hub.status === StatusE.READY && (
<>
<hr className={styles.card_hr} />
<HubCardFooter hub={hub} />
<HubCardFooter hub={_hub} />
</>
)}
</div>
Expand Down
Loading