|
1 | 1 | <script lang="ts">
|
2 | 2 | import { invalidate } from '$app/navigation';
|
3 | 3 | import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
4 |
| - import { CardGrid, Heading } from '$lib/components'; |
5 |
| - import { Dependencies } from '$lib/constants'; |
| 4 | + import { Alert, CardGrid, Heading } from '$lib/components'; |
| 5 | + import { BillingPlan, Dependencies } from '$lib/constants'; |
| 6 | + import { tierToPlan, upgradeURL } from '$lib/stores/billing'; |
6 | 7 | import { Button, Form, FormList, InputSelectSearch } from '$lib/elements/forms';
|
7 | 8 | import {
|
8 | 9 | Table,
|
|
15 | 16 | } from '$lib/elements/table';
|
16 | 17 | import { symmetricDifference } from '$lib/helpers/array';
|
17 | 18 | import { addNotification } from '$lib/stores/notifications';
|
18 |
| - import { organization } from '$lib/stores/organization'; |
| 19 | + import { currentPlan, organization } from '$lib/stores/organization'; |
19 | 20 | import { sdk } from '$lib/stores/sdk';
|
20 | 21 | import { onMount } from 'svelte';
|
21 | 22 |
|
|
39 | 40 | if (alerts.some((alert) => alert === selectedAlert)) {
|
40 | 41 | return;
|
41 | 42 | }
|
42 |
| - if (alerts.length <= 2) { |
| 43 | + if (alerts.length <= 3) { |
43 | 44 | alerts = [...alerts, selectedAlert ? selectedAlert : parseInt(search)];
|
44 | 45 | search = '';
|
45 | 46 | selectedAlert = null;
|
|
59 | 60 | addNotification({
|
60 | 61 | type: 'success',
|
61 | 62 | isHtml: true,
|
62 |
| - message: `<span>A budget alert has been added to <b>${$organization.name}</b></span>` |
| 63 | + message: `<span> ${alerts.length === 0 ? 'Budget alerts removed from' : alerts.length > 1 ? `Budget alerts added to` : 'A budget alert has been added to'} <b>${$organization.name}</b> </span>` |
63 | 64 | });
|
64 | 65 | trackEvent(Submit.BudgetAlertsUpdate, {
|
65 | 66 | alerts
|
|
78 | 79 |
|
79 | 80 | <Form onSubmit={updateBudget}>
|
80 | 81 | <CardGrid>
|
81 |
| - <Heading tag="h2" size="6">Budget alerts</Heading> |
| 82 | + <Heading tag="h2" size="6">Billing alerts</Heading> |
82 | 83 |
|
83 | 84 | <p class="text">
|
84 |
| - Get notified by email when your organization reaches or exceeds a percent of your |
85 |
| - specified budget cap. You can set a maximum of 3 alerts. |
| 85 | + {#if !$currentPlan.budgeting} |
| 86 | + Get notified by email when your organization meets a percentage of your budget cap. <b |
| 87 | + >{tierToPlan($organization.billingPlan).name} organizations will receive one notification |
| 88 | + at 75% resource usage.</b> |
| 89 | + {:else} |
| 90 | + Get notified by email when your organization meets or exceeds a percentage of your |
| 91 | + specified billing alert(s). |
| 92 | + {/if} |
86 | 93 | </p>
|
87 | 94 | <svelte:fragment slot="aside">
|
88 |
| - <FormList> |
89 |
| - <div class="u-flex u-gap-16"> |
90 |
| - <InputSelectSearch |
91 |
| - label="Percentage (%) of budget cap" |
92 |
| - placeholder="Select a percentage" |
93 |
| - id="alerts" |
94 |
| - {options} |
95 |
| - bind:search |
96 |
| - bind:value={selectedAlert} |
97 |
| - on:select={() => (search = selectedAlert.toString())} /> |
98 |
| - <div style="align-self: flex-end"> |
99 |
| - <Button |
100 |
| - secondary |
101 |
| - disabled={alerts.length > 2 || (!search && !selectedAlert)} |
102 |
| - on:click={addAlert}> |
103 |
| - Add alert |
104 |
| - </Button> |
| 95 | + {#if !$currentPlan.budgeting} |
| 96 | + <Alert type="info"> |
| 97 | + <svelte:fragment slot="title" |
| 98 | + >Billing alerts are a Pro plan feature |
| 99 | + </svelte:fragment> |
| 100 | + Upgrade to a Pro plan to manage when you receive billing alerts for your organization. |
| 101 | + </Alert> |
| 102 | + {:else} |
| 103 | + <FormList> |
| 104 | + <Alert type="info"> |
| 105 | + You can set a maximum of 4 billing alerts per organization. |
| 106 | + </Alert> |
| 107 | + |
| 108 | + <div class="u-flex u-gap-16"> |
| 109 | + <InputSelectSearch |
| 110 | + label="Percentage (%) of budget cap" |
| 111 | + placeholder="Select a percentage" |
| 112 | + id="alerts" |
| 113 | + {options} |
| 114 | + bind:search |
| 115 | + interactiveOutput |
| 116 | + bind:value={selectedAlert} |
| 117 | + on:select={() => (search = selectedAlert.toString())} /> |
| 118 | + <div style="align-self: flex-end"> |
| 119 | + <Button |
| 120 | + secondary |
| 121 | + disabled={alerts.length > 3 || (!search && !selectedAlert)} |
| 122 | + on:click={addAlert}> |
| 123 | + Add alert |
| 124 | + </Button> |
| 125 | + </div> |
105 | 126 | </div>
|
106 |
| - </div> |
107 |
| - </FormList> |
| 127 | + </FormList> |
108 | 128 |
|
109 |
| - {#if alerts.length} |
110 |
| - <Table noMargin noStyles transparent> |
111 |
| - <TableHeader> |
112 |
| - <TableCellHead>Alert at budget cap %</TableCellHead> |
113 |
| - <TableCellHead width={30} /> |
114 |
| - </TableHeader> |
115 |
| - <TableBody> |
116 |
| - {#each alerts.sort() as alert} |
117 |
| - <TableRow> |
118 |
| - <TableCellText title="Percentage"> |
119 |
| - {alert}% |
120 |
| - </TableCellText> |
121 |
| - <TableCell> |
122 |
| - <Button |
123 |
| - text |
124 |
| - round |
125 |
| - ariaLabel="remove alert" |
126 |
| - on:click={() => |
127 |
| - (alerts = alerts.filter((a) => a !== alert))}> |
128 |
| - <span class="icon-x" aria-hidden="true" /> |
129 |
| - </Button> |
130 |
| - </TableCell> |
131 |
| - </TableRow> |
132 |
| - {/each} |
133 |
| - </TableBody> |
134 |
| - </Table> |
| 129 | + {#if alerts.length} |
| 130 | + <Table noMargin noStyles transparent> |
| 131 | + <TableHeader> |
| 132 | + <TableCellHead>Alert at budget cap %</TableCellHead> |
| 133 | + <TableCellHead width={30} /> |
| 134 | + </TableHeader> |
| 135 | + <TableBody> |
| 136 | + {#each alerts.sort() as alert} |
| 137 | + <TableRow> |
| 138 | + <TableCellText title="Percentage"> |
| 139 | + {alert}% |
| 140 | + </TableCellText> |
| 141 | + <TableCell> |
| 142 | + <Button |
| 143 | + text |
| 144 | + round |
| 145 | + ariaLabel="remove alert" |
| 146 | + on:click={() => |
| 147 | + (alerts = alerts.filter((a) => a !== alert))}> |
| 148 | + <span class="icon-x" aria-hidden="true" /> |
| 149 | + </Button> |
| 150 | + </TableCell> |
| 151 | + </TableRow> |
| 152 | + {/each} |
| 153 | + </TableBody> |
| 154 | + </Table> |
| 155 | + {/if} |
135 | 156 | {/if}
|
136 | 157 | </svelte:fragment>
|
137 | 158 |
|
138 | 159 | <svelte:fragment slot="actions">
|
139 |
| - <Button disabled={isButtonDisabled} submit>Update</Button> |
| 160 | + {#if $organization?.billingPlan === BillingPlan.FREE || $organization?.billingPlan === BillingPlan.GITHUB_EDUCATION} |
| 161 | + <Button |
| 162 | + secondary |
| 163 | + href={$upgradeURL} |
| 164 | + on:click={() => { |
| 165 | + trackEvent('click_organization_upgrade', { |
| 166 | + from: 'button', |
| 167 | + source: 'billing_alerts_card' |
| 168 | + }); |
| 169 | + }} |
| 170 | + >Upgrade to Pro |
| 171 | + </Button> |
| 172 | + {:else} |
| 173 | + <Button disabled={isButtonDisabled} submit>Update</Button> |
| 174 | + {/if} |
140 | 175 | </svelte:fragment>
|
141 | 176 | </CardGrid>
|
142 | 177 | </Form>
|
0 commit comments