Merge branch 'main' into feat-prop-1297-login-for-github-education-program

This commit is contained in:
ernstmul
2024-10-28 07:38:50 +01:00
6 changed files with 69 additions and 23 deletions
+1 -1
View File
@@ -983,7 +983,7 @@ export class Billing {
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
'post',
'patch',
uri,
{
'content-type': 'application/json'
+3 -3
View File
@@ -42,7 +42,7 @@ export const ResourcesFriendly = {
file: { singular: 'File', plural: 'Files' },
bucket: { singular: 'Bucket', plural: 'Buckets' },
function: { singular: 'Function', plural: 'Functions' },
'environment variable': { singular: 'Environment Variable', plural: 'Environment Variables' },
'environment-variable': { singular: 'Environment Variable', plural: 'Environment Variables' },
deployment: { singular: 'Deployment', plural: 'Deployments' },
database: { singular: 'Database', plural: 'Databases' },
collection: { singular: 'Collection', plural: 'Collections' },
@@ -102,7 +102,7 @@ export const migrationFormToResources = (
addResource('function');
}
if (formData.functions.env) {
addResource('environment variable');
addResource('environment-variable');
}
if (formData.functions.inactive) {
addResource('deployment');
@@ -156,7 +156,7 @@ export const resourcesToMigrationForm = (
if (resources.includes('function') && isVersionAtLeast(version, '1.4.0')) {
formData.functions.root = true;
}
if (resources.includes('environment variable') && isVersionAtLeast(version, '1.4.0')) {
if (resources.includes('environment-variable') && isVersionAtLeast(version, '1.4.0')) {
formData.functions.env = true;
}
if (resources.includes('deployment') && isVersionAtLeast(version, '1.4.0')) {
@@ -344,7 +344,7 @@
<div />
<span>Import all functions and their active deployment</span>
<ul>
{#if resources?.includes('environment variable')}
{#if resources?.includes('environment-variable')}
<li class="checkbox-field">
<input
type="checkbox"
@@ -18,6 +18,7 @@
let currentInvoice: Invoice;
let extraMembers = 0;
let currentPlan;
let availableCredit = 0;
const today = new Date();
onMount(async () => {
@@ -30,6 +31,11 @@
extraMembers = members.total > 1 ? members.total - 1 : 0;
currentPlan = await sdk.forConsole.billing.getPlan($organization?.$id);
const creditList = await sdk.forConsole.billing.listCredits($organization.$id, [
Query.offset(0)
]);
availableCredit = creditList.available;
});
$: extraUsage = (currentInvoice?.amount ?? 0) - (currentPlan?.price ?? 0);
@@ -141,6 +147,33 @@
</CollapsibleItem>
{/if}
{#if $organization?.billingPlan !== BillingPlan.FREE && availableCredit > 0}
<CollapsibleItem noContent gap={4}>
<span class="body-text-2 u-flex u-cross-center u-gap-2"
><svg
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M14.166 7.93434C14.4784 8.24676 14.4784 8.75329 14.166 9.06571L8.56603 14.6657C8.25361 14.9781 7.74708 14.9781 7.43466 14.6657L1.83466 9.06571C1.67842 8.90947 1.60032 8.70469 1.60034 8.49992V4.50002C1.60034 3.17454 2.67486 2.10002 4.00034 2.10002H8.00056C8.20523 2.10008 8.40987 2.17818 8.56603 2.33434L14.166 7.93434ZM4.00034 5.30002C4.44217 5.30002 4.80034 4.94185 4.80034 4.50002C4.80034 4.05819 4.44217 3.70002 4.00034 3.70002C3.55851 3.70002 3.20034 4.05819 3.20034 4.50002C3.20034 4.94185 3.55851 5.30002 4.00034 5.30002Z"
fill="#00BC5D" />
</svg>
Credits to be applied</span>
<div
class="body-text-2 u-margin-inline-start-auto"
style="color: var(--web-green-500, #10B981)">
-{formatCurrency(
Math.min(availableCredit, currentInvoice?.amount ?? 0)
)}
</div>
</CollapsibleItem>
{/if}
<CollapsibleItem noContent gap={4}>
<span class="body-text-2">Current total (USD)</span>
<span class="tooltip u-cross-center" aria-label="total info">
@@ -156,7 +189,13 @@
{$organization?.billingPlan === BillingPlan.FREE ||
$organization?.billingPlan === BillingPlan.GITHUB_EDUCATION
? formatCurrency(0)
: formatCurrency(currentInvoice?.amount ?? 0)}
: formatCurrency(
Math.max(
(currentInvoice?.amount ?? 0) -
Math.min(availableCredit, currentInvoice?.amount ?? 0),
0
)
)}
</div>
</CollapsibleItem>
</Collapsible>
@@ -1,5 +1,5 @@
import { sdk } from '$lib/stores/sdk';
import { Query } from '@appwrite.io/console';
import { Query, type Models } from '@appwrite.io/console';
import type { PageLoad } from './$types';
import type { Organization } from '$lib/stores/organization';
import type { Invoice } from '$lib/sdk/billing';
@@ -48,22 +48,33 @@ export const load: PageLoad = async ({ params, parent }) => {
sdk.forConsole.teams.listMemberships(params.organization)
]);
const queries: string[] = [];
const projectNames: { [key: string]: Models.Project } = {};
if (usage?.projects?.length > 0) {
queries.push(
Query.equal(
'$id',
usage.projects.map((p) => p.projectId)
)
);
}
// in batches of 100 (the max number of values in a query)
const requests = [];
const chunk = 100;
for (let i = 0; i < usage.projects.length; i += chunk) {
const queries = [
Query.limit(chunk),
Query.equal(
'$id',
usage.projects.slice(i, i + chunk).map((p) => p.projectId)
)
];
requests.push(sdk.forConsole.projects.list(queries));
}
const projectNames = await sdk.forConsole.projects.list(queries);
const responses = await Promise.all(requests);
for (const response of responses) {
for (const project of response.projects) {
projectNames[project.$id] = project;
}
}
}
return {
organizationUsage: usage,
projectNames: projectNames.projects,
projectNames,
invoices,
currentInvoice,
organizationMembers
@@ -21,10 +21,6 @@
export let projects: OrganizationUsage['projects'];
export let metric: Metric;
function getProjectName(projectId: string): string {
return data.projectNames.find((project) => project.$id === projectId)?.name;
}
function getProjectUsageLink(projectId: string): string {
return `${base}/project-${projectId}/settings/usage`;
}
@@ -69,7 +65,7 @@
{#each groupByProject(metric).sort((a, b) => b.usage - a.usage) as project}
<TableRow>
<TableCellText title="Project" style="padding-left: 0;">
{getProjectName(project.projectId)}
{data.projectNames[project.projectId]?.name ?? 'Unknown'}
</TableCellText>
<TableCellText title="Usage">{format(project.usage)}</TableCellText>
{#if $canSeeProjects}