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

add TTL to create cluster flow cached state #1404

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion www/src/components/account/billing/BillingPricingCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function ContactUs({ ...props }: ButtonProps) {
return (
<Button
as="a"
href="https://plural.sh/contact-sales"
href="https://www.plural.sh/contact"
target="_blank"
rel="noopener noreferer"
width="100%"
Expand Down
14 changes: 9 additions & 5 deletions www/src/components/create-cluster/CreateCluster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,32 @@ export const CUR_CREATE_CLUSTER_STEP_KEY = 'cur-create-cluster-step'
export const CLOUD_OPTION_KEY = 'cloud-option'
export const HOSTING_OPTION_KEY = 'hosting-option'
export const CUR_CONSOLE_INSTANCE_KEY = 'cur-console-instance-id'
const TTL_KEY = 'create-cluster-ttl'

export function CreateCluster() {
const theme = useTheme()
const navigate = useNavigate()
const [curStep, setCurStep] = usePersistedState<CreateClusterStepKey>(
CUR_CREATE_CLUSTER_STEP_KEY,
CreateClusterStepKey.ChooseCloud
CreateClusterStepKey.ChooseCloud,
{ key: TTL_KEY }
)
const [cloudOption, setCloudOption] = usePersistedState<CloudOption>(
CLOUD_OPTION_KEY,
'local'
'local',
{ key: TTL_KEY }
)
const [hostingOption, setHostingOption] =
usePersistedState<ConsoleInstanceType>(
HOSTING_OPTION_KEY,
ConsoleInstanceType.Shared
ConsoleInstanceType.Shared,
{ key: TTL_KEY }
)
const [finishEnabled, setFinishEnabled] = useState(false)
const [continueBtn, setContinueBtn] = useState<ReactElement | undefined>()
const [consoleInstanceId, setConsoleInstanceId] = usePersistedState<
Nullable<string>
>(CUR_CONSOLE_INSTANCE_KEY, null)
>(CUR_CONSOLE_INSTANCE_KEY, null, { key: TTL_KEY })

const steps = cloudOption === 'local' ? localSteps : cloudSteps
const curStepIndex = steps.findIndex((step) => step.key === curStep)
Expand Down Expand Up @@ -142,7 +146,7 @@ export function CreateCluster() {
secondary
startIcon={<SendMessageIcon />}
as="a"
href="https://plural.sh/contact-sales"
href="https://www.plural.sh/contact"
target="_blank"
rel="noopener noreferrer"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function ChooseCloudStep() {
</CalloutLinkButton>
<CalloutLinkButton
secondary
href="https://plural.sh/contact-sales"
href="https://www.plural.sh/contact"
>
Contact sales
</CalloutLinkButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function ChooseHostingOptionStep() {
>
If you would like to create a dedicated cloud instance, please
contact sales to inquire about upgrading to an Enterprise plan.
<CalloutLinkButton href="https://plural.sh/contact-sales">
<CalloutLinkButton href="https://www.plural.sh/contact">
Contact sales
</CalloutLinkButton>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function ClustersHelpSection(): ReactElement {
floating
startIcon={<SendMessageIcon />}
forwardedAs="a"
href="https://plural.sh/contact-sales"
href="https://www.plural.sh/contact"
target="_blank"
rel="noopener noreferrer"
>
Expand Down
34 changes: 27 additions & 7 deletions www/src/hooks/usePersistedState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,49 @@ import {

const identity = (x: any) => x

// 12 hours, but only used if TTL key explicitly provided
const DEFAULT_TTL_DURATION = 12 * 60 * 60 * 1000

type TTLConfig = {
key: string
duration?: number
}

// useState with localStorage persistence
function usePersistedState<T>(
key: string,
defaultValue: T,
ttl?: TTLConfig,
parser = identity
): [T, Dispatch<SetStateAction<T>>] {
const getLocalStorageValue = useCallback(() => {
const ttlKey = ttl ? `plural-${ttl.key}-timestamp` : ''
const itemKey = `plural-${key}`
const getInitialVal = useCallback(() => {
try {
const item = localStorage.getItem(`plural-${key}`)

// if TTL key provided, check if it's expired or not found
if (ttl) {
const timestamp = JSON.parse(localStorage.getItem(ttlKey) ?? 'null')
if (
!timestamp ||
Date.now() - timestamp > (ttl.duration ?? DEFAULT_TTL_DURATION)
)
return defaultValue
}
const item = localStorage.getItem(itemKey)
if (item) return parser(JSON.parse(item))
} catch (error) {
console.log('Error on localStorage.getItem of', key)
}

return defaultValue
}, [key, defaultValue, parser])
}, [key, defaultValue, parser, ttl])

const [state, setState] = useState<T>(getLocalStorageValue())
const [state, setState] = useState<T>(getInitialVal())

useEffect(() => {
localStorage.setItem(`plural-${key}`, JSON.stringify(state))
}, [key, state])
localStorage.setItem(itemKey, JSON.stringify(state))
if (ttlKey !== '') localStorage.setItem(ttlKey, JSON.stringify(Date.now()))
}, [key, state, ttlKey])

return [state, setState]
}
Expand Down
Loading