diff --git a/src/lib/utils/wave/types/waveProgram.ts b/src/lib/utils/wave/types/waveProgram.ts index 9d9b7089c..74575134d 100644 --- a/src/lib/utils/wave/types/waveProgram.ts +++ b/src/lib/utils/wave/types/waveProgram.ts @@ -137,6 +137,7 @@ export const waveProgramRepoWithDetailsDtoSchema = z.object({ pointsUsed: z.number().int(), pointsBudget: z.number().int().nullable(), pointsRemaining: z.number().int().nullable(), + pointsBudgetOverride: z.number().int().nullable().optional(), pointsMultiplier: z.number().int().optional(), repo: z.object({ stargazersCount: z.number().int().nullable().optional(), diff --git a/src/lib/utils/wave/wavePrograms.ts b/src/lib/utils/wave/wavePrograms.ts index 5b08ad86a..133a6f28c 100644 --- a/src/lib/utils/wave/wavePrograms.ts +++ b/src/lib/utils/wave/wavePrograms.ts @@ -184,6 +184,36 @@ export async function unfeatureWaveProgramRepo( }); } +export async function setRepoBudgetOverride( + f = fetch, + waveProgramId: string, + orgRepoId: string, + pointsBudget: number, +) { + await authenticatedCall( + f, + `/api/wave-programs/${waveProgramId}/repos/${orgRepoId}/budget-override`, + { + method: 'PUT', + body: JSON.stringify({ pointsBudget }), + }, + ); +} + +export async function removeRepoBudgetOverride( + f = fetch, + waveProgramId: string, + orgRepoId: string, +) { + await authenticatedCall( + f, + `/api/wave-programs/${waveProgramId}/repos/${orgRepoId}/budget-override`, + { + method: 'DELETE', + }, + ); +} + export async function addIssueToWaveProgram( f = fetch, waveProgramId: string, diff --git a/src/routes/(pages)/wave/(base-layout)/admin/repos/+layout.ts b/src/routes/(pages)/wave/(base-layout)/admin/repos/+layout.ts index f57398683..f557a4e0b 100644 --- a/src/routes/(pages)/wave/(base-layout)/admin/repos/+layout.ts +++ b/src/routes/(pages)/wave/(base-layout)/admin/repos/+layout.ts @@ -9,8 +9,9 @@ export const load = async ({ parent, fetch, depends }) => { const canManageTags = user.permissions?.includes('manageTags'); const canFeatureRepos = user.permissions?.includes('featureWaveRepos'); + const canManagePoints = user.permissions?.includes('managePoints'); - if (!canManageTags && !canFeatureRepos) { + if (!canManageTags && !canFeatureRepos && !canManagePoints) { throw redirect(302, '/wave/admin'); } @@ -24,5 +25,6 @@ export const load = async ({ parent, fetch, depends }) => { tags, canManageTags: !!canManageTags, canFeatureRepos: !!canFeatureRepos, + canManagePoints: !!canManagePoints, }; }; diff --git a/src/routes/(pages)/wave/(base-layout)/admin/repos/components/budget-override-modal.svelte b/src/routes/(pages)/wave/(base-layout)/admin/repos/components/budget-override-modal.svelte new file mode 100644 index 000000000..780b7070d --- /dev/null +++ b/src/routes/(pages)/wave/(base-layout)/admin/repos/components/budget-override-modal.svelte @@ -0,0 +1,113 @@ + + +