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

[RW-13480][risk=no] Workspace Banners for Initial Credits #8951

Open
wants to merge 47 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
40bdb61
Added basic tests.
evrii Nov 12, 2024
cc7918c
Add expiration date.
evrii Nov 12, 2024
dee730b
Update styling
evrii Nov 12, 2024
e76615e
Add checks for extension button.
evrii Nov 12, 2024
a5ff2f3
Add extension and info buttons.
evrii Nov 12, 2024
0adb7e4
Merge remote-tracking branch 'origin/main' into eric/RW-13481
evrii Nov 14, 2024
ad412f5
Merge remote-tracking branch 'origin/main' into eric/RW-13481
evrii Nov 15, 2024
c214129
Added extension field.
evrii Nov 18, 2024
cd7f7d3
First pass at banners
evrii Nov 18, 2024
bdd7f49
Simplified logic?
evrii Nov 18, 2024
a2dbc9d
Added config values.
evrii Nov 18, 2024
42b159c
[RW-13735][risk=no] Added modal to trigger initial credit extension. …
evrii Nov 19, 2024
f50fb7b
Merge remote-tracking branch 'origin/eric/RW-13481' into eric/RW-13480
evrii Nov 19, 2024
bd12bb9
Fix title and eligibility usage
evrii Nov 19, 2024
7b35bd6
Merge remote-tracking branch 'origin/main' into eric/RW-13480
evrii Nov 19, 2024
6480a2f
[risk=low][no ticket] [dependabot] Bump cross-spawn from 7.0.3 to 7.0…
dependabot[bot] Nov 19, 2024
7881475
laucn multi-zone (#8956)
yonghaoy Nov 19, 2024
92a2784
remove getUploadResult in verifyAndLog (#8955)
Qi77Qi Nov 19, 2024
0abe313
Merge remote-tracking branch 'origin/main' into eric/RW-13480
evrii Nov 19, 2024
0f0326e
Update banner
evrii Nov 19, 2024
8092dba
Cleaner banner?
evrii Nov 19, 2024
e507305
Merge remote-tracking branch 'origin/main' into eric/RW-13480
evrii Nov 20, 2024
d7ec332
Cleanup
evrii Nov 20, 2024
34957ec
Add expiring soon banners.
evrii Nov 20, 2024
d1b1f87
Add expired but eligible tests
evrii Nov 20, 2024
f463eec
Add expired and ineligible tests
evrii Nov 20, 2024
73378ea
Hide banner if not appropriate
evrii Nov 20, 2024
3c286c7
Cleanup
evrii Nov 22, 2024
cbca190
Cleanup
evrii Nov 22, 2024
cd304ee
Updated language
evrii Nov 22, 2024
300240f
Updated spacing
evrii Nov 22, 2024
3c6ec5e
Updated test email.
evrii Nov 22, 2024
d6364e3
Merge main
evrii Dec 3, 2024
8f15eb8
Made variables explicit
evrii Dec 3, 2024
2e317b1
Cleanup
evrii Dec 3, 2024
b96ee0e
Changed directory
evrii Dec 3, 2024
6d30024
Swap function
evrii Dec 3, 2024
7b352b1
Fix link
evrii Dec 3, 2024
d66c840
Added missing extension logic
evrii Dec 3, 2024
62b3414
Cleanup
evrii Dec 3, 2024
df7e585
Merge main
evrii Dec 3, 2024
fa78083
Fix name of mapper
evrii Dec 3, 2024
db9d522
Add missing condition
evrii Dec 3, 2024
0954fd0
Cleanup
evrii Dec 3, 2024
ef63dde
Add comment
evrii Dec 3, 2024
db7a2ae
Removed unused enum
evrii Dec 3, 2024
2cc9dfa
Cleanup
evrii Dec 3, 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
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ public interface WorkspaceMapper {
target = "initialCredits.expirationEpochMillis",
source = "dbWorkspace.creator",
qualifiedByName = "getInitialCreditsExpiration")
@Mapping(
target = "initialCredits.extensionEpochMillis",
source = "dbWorkspace.creator",
qualifiedByName = "getInitialCreditsExpiration")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this sets extension to the same value as expiration. Is this intentional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, nope. I corrected it. Thank you for pointing it out.

@Mapping(target = "cdrVersionId", source = "dbWorkspace.cdrVersion")
@Mapping(target = "accessTierShortName", source = "dbWorkspace.cdrVersion.accessTier.shortName")
@Mapping(target = "googleProject", source = "dbWorkspace.googleProject")
Expand Down Expand Up @@ -128,6 +132,10 @@ default List<WorkspaceResponse> toApiWorkspaceResponseList(
target = "initialCredits.expirationEpochMillis",
source = "creator",
qualifiedByName = "getInitialCreditsExpiration")
@Mapping(
target = "initialCredits.extensionEpochMillis",
source = "creator",
qualifiedByName = "getInitialCreditsExpiration")
@Mapping(target = "initialCredits.exhausted", source = "dbWorkspace.initialCreditsExhausted")
@Mapping(target = "etag", source = "version", qualifiedByName = "versionToEtag")
@Mapping(
Expand Down
3 changes: 3 additions & 0 deletions api/src/main/resources/workbench-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13047,6 +13047,9 @@ components:
expirationEpochMillis:
type: integer
format: int64
extensionEpochMillis:
type: integer
format: int64
parameters:
userId:
name: userId
Expand Down
125 changes: 112 additions & 13 deletions ui/src/app/pages/workspace/invalid-billing-banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import * as fp from 'lodash';
import { Profile } from 'generated/fetch';

import { Button, LinkButton } from 'app/components/buttons';
import { AoU } from 'app/components/text-wrappers';
import { ToastBanner, ToastType } from 'app/components/toast-banner';
import { withCurrentWorkspace, withUserProfile } from 'app/utils';
import { plusDays } from 'app/utils/dates';
import { NavigationProps } from 'app/utils/navigation';
import { withNavigation } from 'app/utils/with-navigation-hoc';
import { WorkspaceData } from 'app/utils/workspace-data';
Expand All @@ -19,23 +21,119 @@ interface Props extends NavigationProps {
onClose: Function;
}

const InitialCreditsArticleLink = () => (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these 2 links have different text but the same URL. that does not seem right.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you :-)

<>
"
<LinkButton
onClick={() => window.open(supportUrls.createBillingAccount, '_blank')}
>
Using <AoU /> Initial Credits
</LinkButton>
"
</>
);

const BillingAccountArticleLink = () => (
<>
"
<LinkButton
onClick={() => window.open(supportUrls.createBillingAccount, '_blank')}
>
Paying for Your Research
</LinkButton>
"
</>
);

export const InvalidBillingBanner = fp.flow(
withCurrentWorkspace(),
withUserProfile(),
withNavigation
)(({ onClose, navigate, workspace }: Props) => {
const message = (
<div>
The initial credits for the creator of this workspace have run out. Please
provide a valid billing account.
<LinkButton
onClick={() => window.open(supportUrls.createBillingAccount, '_blank')}
>
Learn how to link a billing account.
</LinkButton>
</div>
);
const footer = (
)(({ onClose, navigate, workspace, profileState }: Props) => {
const { profile } = profileState;
const isCreator =
workspace && profile && profile.username === workspace.creator;
const isEligibleForExtension = workspace && !workspace.extensionEpochMillis;
const isExpired =
workspace && workspace.initialCredits.expirationEpochMillis < Date.now();
const isExpiringSoon =
workspace &&
!isExpired &&
plusDays(workspace.initialCredits.expirationEpochMillis, 5) < Date.now();
let message;
let title;
if (isExpiringSoon && isEligibleForExtension) {
evrii marked this conversation as resolved.
Show resolved Hide resolved
title = 'Workspace credits are expiring soon';
if (isCreator) {
// Banner 1 in spec
message = (
<div>
Your initial credits are expiring soon. You can request an extension
here. For more information, read the <InitialCreditsArticleLink />{' '}
article on the User Support Hub.
</div>
);
} else {
// Banner 2 in spec
message = (
<div>
This workspace creator’s initial credits are expiring soon. This
workspace was created by FIRST NAME LAST NAME. For more information,
read the <InitialCreditsArticleLink /> article on the User Support
Hub.
</div>
);
}
} else if (isExpired) {
if (isEligibleForExtension) {
title = 'Workspace credits have expired';
if (isCreator) {
// Banner 3 in spec (changed to trigger modal from here instead of on Profile page)
message = (
<div>
Your initial credits have expired. You can request an extension
here. For more information, read the <InitialCreditsArticleLink />{' '}
article on the User Support Hub.
</div>
);
} else {
// Banner 4 in spec
message = (
<div>
This workspace creator’s initial credits have expired. This
workspace was created by FIRST NAME LAST NAME. For more information,
read the <InitialCreditsArticleLink /> article on the User Support
Hub.
</div>
);
}
} else {
title = 'This workspace is out of initial credits';
if (isCreator) {
// Banner 5 in spec
message = (
<div>
Your initial credits have run out. To use the workspace, a valid
billing account needs to be provided. To learn more about
establishing a billing account, read the{' '}
<BillingAccountArticleLink /> article on the User Support Hub.
</div>
);
} else {
// Banner 6 in spec
message = (
<div>
This workspace creator’s initial credits have run out. This
workspace was created by FIRST NAME LAST NAME. To use the workspace,
a valid billing account needs to be provided. To learn more about
establishing a billing account, read the{' '}
<BillingAccountArticleLink /> article on the User Support Hub.
</div>
);
}
}
}
const footer = isCreator && (
<Button
style={{ height: '38px', width: '70%', fontWeight: 400 }}
onClick={() => {
Expand All @@ -53,6 +151,7 @@ export const InvalidBillingBanner = fp.flow(
Edit Workspace
</Button>
);

return (
<ToastBanner
{...{ message, footer, onClose }}
Expand Down