feat: usage page fixes, implement date range picker, disable scale plan

This commit is contained in:
Arman
2023-11-20 22:06:27 +01:00
parent 2b77ab5fde
commit e2882009de
8 changed files with 302 additions and 27 deletions
+93 -17
View File
@@ -7,12 +7,12 @@
"name": "@appwrite/console",
"dependencies": {
"@appwrite.io/console": "^0.3.0",
"@appwrite.io/pink": "0.1.0-next.9",
"@appwrite.io/pink-icons": "^0.1.0-next.9",
"@appwrite.io/pink": "0.1.0",
"@appwrite.io/pink-icons": "^0.1.0",
"@popperjs/core": "^2.11.8",
"@sentry/svelte": "^7.66.0",
"@sentry/tracing": "^7.66.0",
"@stripe/stripe-js": "^1.54.2",
"@stripe/stripe-js": "^2.1.11",
"ai": "^2.2.11",
"analytics": "^0.8.9",
"dayjs": "^1.11.9",
@@ -29,6 +29,7 @@
"web-vitals": "^3.4.0"
},
"devDependencies": {
"@melt-ui/svelte": "^0.61.2",
"@playwright/test": "^1.37.1",
"@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.24.0",
@@ -165,19 +166,19 @@
}
},
"node_modules/@appwrite.io/pink": {
"version": "0.1.0-next.9",
"resolved": "https://registry.npmjs.org/@appwrite.io/pink/-/pink-0.1.0-next.9.tgz",
"integrity": "sha512-W5xVm2ZXlEqbbKv0GkpnM5saunDKdSfuhWouLnORsonENGFsG529PxRjqeClz4zrlkt2x1DiwN175wpgV3GoEQ==",
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@appwrite.io/pink/-/pink-0.1.0.tgz",
"integrity": "sha512-z+4wiTH2PBMrbxvXiNjGQY0hs6ziCbKSb2rK0O/2M3aa9CHN/dBDSTpWCcED8G9BWDkeS5XMVZrQbyrdqMVc/Q==",
"dependencies": {
"@appwrite.io/pink-icons": "0.1.0-next.9",
"@appwrite.io/pink-icons": "0.1.0",
"normalize.css": "^8.0.1",
"the-new-css-reset": "^1.7.3"
"the-new-css-reset": "^1.11.2"
}
},
"node_modules/@appwrite.io/pink-icons": {
"version": "0.1.0-next.9",
"resolved": "https://registry.npmjs.org/@appwrite.io/pink-icons/-/pink-icons-0.1.0-next.9.tgz",
"integrity": "sha512-6t4Pqt/xugjpJQyaMx1u/7Gt9CkW5iItDAgUKcIMm84E4NbDJq8ZdAhhvctGQQppKUgHDPi+6x1XveUUd7tdbg=="
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@appwrite.io/pink-icons/-/pink-icons-0.1.0.tgz",
"integrity": "sha512-Y5DmvosdCoBD0oyqKV+ncbXTzQuhX0WOe4N7uonMaz1NaFm3ODaIb/CF77hV2vg86oOQ+f+BirdhfPsBue2pNA=="
},
"node_modules/@babel/code-frame": {
"version": "7.22.13",
@@ -1293,6 +1294,31 @@
"node": ">=14"
}
},
"node_modules/@floating-ui/core": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.0.tgz",
"integrity": "sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==",
"dev": true,
"dependencies": {
"@floating-ui/utils": "^0.1.3"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.3.tgz",
"integrity": "sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==",
"dev": true,
"dependencies": {
"@floating-ui/core": "^1.4.2",
"@floating-ui/utils": "^0.1.3"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.6.tgz",
"integrity": "sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==",
"dev": true
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.13",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
@@ -1326,6 +1352,15 @@
"integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
"dev": true
},
"node_modules/@internationalized/date": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.5.0.tgz",
"integrity": "sha512-nw0Q+oRkizBWMioseI8+2TeUPEyopJVz5YxoYVzR0W1v+2YytiYah7s/ot35F149q/xAg4F1gT/6eTd+tsUpFQ==",
"dev": true,
"dependencies": {
"@swc/helpers": "^0.5.0"
}
},
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@@ -1810,6 +1845,23 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@melt-ui/svelte": {
"version": "0.61.2",
"resolved": "https://registry.npmjs.org/@melt-ui/svelte/-/svelte-0.61.2.tgz",
"integrity": "sha512-BHkD9G31zQBToA4euDRBgTQRvWxT9scufOVCXgDO6HKTvyxFspbWT2bgiSFqAK4BbAGDn9Ao36Q8F9O71KN4OQ==",
"dev": true,
"dependencies": {
"@floating-ui/core": "^1.3.1",
"@floating-ui/dom": "^1.4.5",
"@internationalized/date": "^3.5.0",
"dequal": "^2.0.3",
"focus-trap": "^7.5.2",
"nanoid": "^4.0.2"
},
"peerDependencies": {
"svelte": ">=3 <5"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2003,9 +2055,9 @@
}
},
"node_modules/@stripe/stripe-js": {
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.54.2.tgz",
"integrity": "sha512-R1PwtDvUfs99cAjfuQ/WpwJ3c92+DAMy9xGApjqlWQMj0FKQabUAys2swfTRNzuYAYJh7NqK2dzcYVNkKLEKUg=="
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.1.11.tgz",
"integrity": "sha512-GRyInO+VPMjjgUzVPKpDtz+5s8JKssJ99uhWBGo09yxDQBb+bhkm6PxmVa8C+qsSd30JFO1Z+pgIJ0AMmmZJKg=="
},
"node_modules/@sveltejs/adapter-static": {
"version": "2.0.3",
@@ -2087,6 +2139,15 @@
"vite": "^4.0.0"
}
},
"node_modules/@swc/helpers": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.3.tgz",
"integrity": "sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==",
"dev": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@testing-library/dom": {
"version": "9.3.3",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz",
@@ -4536,6 +4597,15 @@
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
"dev": true
},
"node_modules/focus-trap": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz",
"integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==",
"dev": true,
"dependencies": {
"tabbable": "^6.2.0"
}
},
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
@@ -8504,6 +8574,12 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true
},
"node_modules/tabbable": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
"dev": true
},
"node_modules/test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
@@ -8526,9 +8602,9 @@
"dev": true
},
"node_modules/the-new-css-reset": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/the-new-css-reset/-/the-new-css-reset-1.11.1.tgz",
"integrity": "sha512-AsNpvcX9YkVja3ZwVYjwULYOyelhse4Atnnple2wPwrKdf3tEBXECBPAoTN+tMSFiFbi00jyprt7F9vhHornMw=="
"version": "1.11.2",
"resolved": "https://registry.npmjs.org/the-new-css-reset/-/the-new-css-reset-1.11.2.tgz",
"integrity": "sha512-m/JQ/srn+e5SAI7MVCZOJ1hoxoE1w1uA96birT52Y9769GN9e0M4K1PBxlz05Vq4HprX11ASBjM2TcQs4WXnXg=="
},
"node_modules/tiny-glob": {
"version": "0.2.9",
+2 -1
View File
@@ -21,10 +21,10 @@
"@appwrite.io/console": "^0.3.0",
"@appwrite.io/pink": "0.1.0-next.9",
"@appwrite.io/pink-icons": "^0.1.0-next.9",
"@stripe/stripe-js": "^1.54.2",
"@popperjs/core": "^2.11.8",
"@sentry/svelte": "^7.66.0",
"@sentry/tracing": "^7.66.0",
"@stripe/stripe-js": "^1.54.2",
"ai": "^2.2.11",
"analytics": "^0.8.9",
"dayjs": "^1.11.9",
@@ -41,6 +41,7 @@
"web-vitals": "^3.4.0"
},
"devDependencies": {
"@melt-ui/svelte": "^0.61.2",
"@playwright/test": "^1.37.1",
"@sveltejs/adapter-static": "^2.0.3",
"@sveltejs/kit": "^1.24.0",
+1
View File
@@ -28,3 +28,4 @@ export { default as Helper } from './helper.svelte';
export { default as Label } from './label.svelte';
export { default as InputProjectId } from './inputProjectId.svelte';
export { default as InputDate } from './inputDate.svelte';
export { default as InputDateRange } from './inputDateRange.svelte';
@@ -0,0 +1,179 @@
<script lang="ts">
import { createDateRangePicker, type DateRange } from '@melt-ui/svelte';
import { Label } from '.';
const {
elements: {
calendar,
cell,
content,
grid,
heading,
nextButton,
prevButton,
startSegment,
endSegment,
trigger
},
states: { months, headingValue, daysOfWeek, segmentContents, value },
helpers: { isDateDisabled, isDateUnavailable }
} = createDateRangePicker();
export let data: DateRange;
export let showLabel = true;
export let label: string;
export let id: string;
export let required = false;
export let hideRequired = false;
export let tooltip: string;
export let optionalText: string;
export let showDates = true;
$: if ($value) {
data = $value;
}
$: console.log(data);
</script>
{#if label}
<Label {required} {hideRequired} {tooltip} {optionalText} hide={!showLabel} for={id}>
{label}
</Label>
<!-- <span class="label" use:label>Hotel Nights</span> -->
{/if}
<div class="u-flex u-gap-4">
{#if showDates}
{#each $segmentContents.start as seg}
<div {...$startSegment(seg.part)} use:startSegment>
{seg.value}
</div>
{/each}
<div aria-hidden="true">-</div>
{#each $segmentContents.end as seg}
<div {...$endSegment(seg.part)} use:endSegment>
{seg.value}
</div>
{/each}
{/if}
<div>
<button {...$trigger} use:trigger class="button is-secondary" type="button">
<slot>Open calendar</slot>
</button>
</div>
</div>
<div {...$content} use:content class="card dt-container">
<div {...$calendar} use:calendar class="u-flex u-flex-vertical">
<header class="u-flex u-main-space-between u-cross-center">
<button type="button" class="button is-only-icon is-text" use:prevButton>
<span class="icon-cheveron-left" aria-label="previous month"></span>
</button>
<div {...$heading} use:heading>
{$headingValue}
</div>
<button type="button" class="button is-only-icon is-text" use:nextButton>
<span class="icon-cheveron-right" aria-label="next month"></span>
</button>
</header>
{#each $months as month}
<table use:grid>
<thead aria-hidden="true">
<tr>
{#each $daysOfWeek as day}
<th class="dt-cell">
<span class="u-flex u-main-center u-cross-center">
{day}
</span>
</th>
{/each}
</tr>
</thead>
<tbody>
{#each month.weeks as days}
<tr>
{#each days as date}
<td
class="dt-cell"
role="gridcell"
aria-disabled={$isDateDisabled(date) ||
$isDateUnavailable(date)}>
<div
{...$cell(date, month.value)}
use:cell
class="u-flex u-main-center u-cross-center dt-button">
{date.day}
</div>
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
{/each}
</div>
</div>
<style lang="scss">
:global(.theme-dark) .dt-button {
--dt-text-hover: var(--color-neutral-20);
--dt-button-hover: var(--color-neutral-200);
--dt-border-hover: var(--color-neutral-70);
--dt-text-active: var(--color-neutral-60);
--dt-button-active: var(--color-neutral-200);
--dt-border-active: var(--color-neutral-60);
}
:global(.theme-light) .dt-button {
--dt-text-hover: var(--color-neutral-100);
--dt-button-hover: var(--color-neutral-30);
--dt-border-hover: var(--color-neutral-15);
--dt-text-active: var(--color-neutral-100);
--dt-button-active: var(--color-neutral-30);
--dt-border-active: var(--color-neutral-15);
}
.dt-container {
min-width: 20rem;
}
.dt-cell {
height: 1.5rem;
width: 1.5rem;
padding: 0.1rem;
border-radius: 100%;
user-select: none;
[aria-disabled='true'] {
pointer-events: none;
opacity: 0.4;
}
}
.dt-button {
aspect-ratio: 1/1;
border-radius: 100%;
cursor: pointer;
&:hover,
&[data-highlighted],
&[data-range-highlighted] {
background-color: hsl(var(--dt-button-hover));
color: hsl(var(--dt-text-hover));
}
&[data-selected] {
background-color: hsl(var(--dt-button-active));
color: hsl(var(--dt-text-active));
}
}
// [data-melt-calendar-cell][data-unavailable] {
// @apply pointer-events-none text-red-400 line-through;
// }
// [data-melt-calendar-cell][data-selected] {
// @apply bg-magnum-400 text-neutral-950;
// }
// [data-melt-calendar-cell][data-outside-visible-months] {
// @apply pointer-events-none cursor-default opacity-40 hover:bg-transparent;
// }
// [data-melt-calendar-cell][data-outside-month] {
// @apply pointer-events-none cursor-default opacity-0 hover:bg-transparent;
// }
</style>
+3 -4
View File
@@ -38,10 +38,9 @@ export const load: LayoutLoad = async ({ depends, url }) => {
];
if (!acceptedRoutes.some((n) => url.pathname.startsWith(n))) {
const redirectUrl = url.pathname
? `${url.search}&redirect=${url.pathname}`
: url.search;
throw redirect(303, `/login${redirectUrl}`);
const redirectUrl = url.pathname ? `redirect=${url.pathname}` : '';
const path = url.search ? `${url.search}&${redirectUrl}` : `?${redirectUrl}`;
throw redirect(303, `/login${path}`);
}
}
};
@@ -6,7 +6,7 @@
import { wizard } from '$lib/stores/wizard.js';
import { organization } from '$lib/stores/organization';
import UsageRates from '$routes/console/wizard/cloudOrganization/usageRates.svelte';
import { InputDate, InputSelect } from '$lib/elements/forms';
import { InputDate, InputDateRange, InputSelect } from '$lib/elements/forms';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
@@ -34,6 +34,8 @@
}
</script>
<InputDateRange></InputDateRange>
<Container>
<Heading tag="h2" size="5">Usage</Heading>
<div class="u-flex u-main-space-between common-section u-cross-center">
@@ -56,7 +58,7 @@
</p>
{/if}
<InputDate id="date" label="test" showLabel={false}></InputDate>
<!-- <InputDate id="date" label="test" showLabel={false}></InputDate> -->
<div class="u-flex u-gap-8 u-cross-center">
<p class="text">Usage period:</p>
@@ -104,7 +104,11 @@
</LabelCard>
</li>
<li>
<LabelCard name="plan" bind:group={$createOrganization.billingPlan} value="tier-2">
<LabelCard
name="plan"
bind:group={$createOrganization.billingPlan}
value="tier-2"
disabled>
<svelte:fragment slot="custom">
<div class="u-flex u-flex-vertical u-gap-4 u-width-full-line">
<h4 class="body-text-2 u-bold">
@@ -114,7 +118,8 @@
{tierScale.description}
</p>
</div>
<Pill>14 DAY FREE TRIAL</Pill>
<!-- <Pill>14 DAY FREE TRIAL</Pill> -->
<Pill>COMING SOON</Pill>
</svelte:fragment>
</LabelCard>
</li>
@@ -10,6 +10,7 @@
import type { OrganizationUsage } from '$lib/sdk/billing';
import type { Models } from '@appwrite.io/console';
import { sizeToBytes } from '$lib/helpers/sizeConvertion';
import { Pill } from '$lib/elements';
let usage: OrganizationUsage = null;
let members: Models.MembershipList = null;
@@ -112,6 +113,11 @@
</h4>
<p class="u-color-text-gray u-small">{tierFree.description}</p>
</div>
{#if $organization.billingPlan === 'tier-0'}
<Pill disabled>CURRENT PLAN</Pill>
{:else}
<Pill>14 DAY FREE TRIAL</Pill>
{/if}
</svelte:fragment>
</LabelCard>
</li>
@@ -133,6 +139,11 @@
{tierPro.description}
</p>
</div>
{#if $organization.billingPlan === 'tier-1'}
<Pill disabled>CURRENT PLAN</Pill>
{:else}
<Pill>14 DAY FREE TRIAL</Pill>
{/if}
</svelte:fragment>
</LabelCard>
</li>
@@ -141,7 +152,7 @@
name="plan"
bind:group={$changeOrganizationTier.billingPlan}
value="tier-2"
disabled={$organization.billingPlan === 'tier-2'}>
disabled>
<svelte:fragment slot="custom" let:disabled>
<div
class="u-flex u-flex-vertical u-gap-4 u-width-full-line"
@@ -153,6 +164,7 @@
{tierScale.description}
</p>
</div>
<Pill disabled>COMING SOON</Pill>
</svelte:fragment>
</LabelCard>
</li>