mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-24 01:51:57 +03:00
PR template section: Persist the user selection
The user can choose whether to use a PR template and that will be persisted accross PRs. - remove the PR template section from the Project settings
This commit is contained in:
parent
41b9ed4ad7
commit
eba7f9c388
@ -90,6 +90,7 @@
|
||||
let isDraft = $state<boolean>($preferredPRAction === PRAction.CreateDraft);
|
||||
|
||||
let modal = $state<ReturnType<typeof Modal>>();
|
||||
let templateSelector = $state<ReturnType<typeof PrTemplateSection>>();
|
||||
let isEditing = $state<boolean>(true);
|
||||
let isLoading = $state<boolean>(false);
|
||||
let pullRequestTemplateBody = $state<string | undefined>(undefined);
|
||||
@ -98,10 +99,10 @@
|
||||
let aiDescriptionDirective = $state<string | undefined>(undefined);
|
||||
let showAiBox = $state<boolean>(false);
|
||||
|
||||
let showPRTemplateSelect = $state<boolean>(false);
|
||||
|
||||
function handleToggleUseTemplate() {
|
||||
showPRTemplateSelect = !showPRTemplateSelect;
|
||||
async function handleToggleUseTemplate() {
|
||||
if (!templateSelector) return;
|
||||
const displaying = templateSelector.imports.showing;
|
||||
await templateSelector.setUsePullRequestTemplate(!displaying);
|
||||
}
|
||||
|
||||
const canUseAI = $derived.by(() => {
|
||||
@ -350,8 +351,9 @@
|
||||
<ToggleButton
|
||||
icon="doc"
|
||||
label="Use PR template"
|
||||
checked={showPRTemplateSelect}
|
||||
checked={!!templateSelector?.imports.showing}
|
||||
onclick={handleToggleUseTemplate}
|
||||
disabled={!templateSelector?.imports.hasTemplates}
|
||||
/>
|
||||
<ToggleButton
|
||||
icon="ai-small"
|
||||
@ -366,9 +368,7 @@
|
||||
</div>
|
||||
|
||||
<!-- PR TEMPLATE SELECT -->
|
||||
{#if showPRTemplateSelect}
|
||||
<PrTemplateSection bind:pullRequestTemplateBody />
|
||||
{/if}
|
||||
<PrTemplateSection bind:this={templateSelector} bind:pullRequestTemplateBody />
|
||||
|
||||
<!-- DESCRIPTION FIELD -->
|
||||
<div class="pr-description-field text-input">
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { ForgeService } from '$lib/backend/forge';
|
||||
import { Project } from '$lib/backend/projects';
|
||||
import { ProjectService, ProjectsService } from '$lib/backend/projects';
|
||||
import Select from '$lib/select/Select.svelte';
|
||||
import SelectItem from '$lib/select/SelectItem.svelte';
|
||||
import { getContext } from '@gitbutler/shared/context';
|
||||
@ -11,29 +11,22 @@
|
||||
|
||||
let { pullRequestTemplateBody = $bindable() }: Props = $props();
|
||||
|
||||
const project = getContext(Project);
|
||||
const projectsService = getContext(ProjectsService);
|
||||
const projectService = getContext(ProjectService);
|
||||
const forgeService = getContext(ForgeService);
|
||||
|
||||
let allAvailableTemplates = $state<{ label: string; value: string }[]>([]);
|
||||
|
||||
const defaultReviewTemplatePath = $derived(
|
||||
project.git_host.reviewTemplatePath ?? allAvailableTemplates[0]?.value
|
||||
);
|
||||
let selectedReviewTemplatePath = $state<string | undefined>(undefined);
|
||||
const actualReviewTemplatePath = $derived(
|
||||
selectedReviewTemplatePath ?? defaultReviewTemplatePath
|
||||
);
|
||||
|
||||
let useReviewTemplate = $state<boolean | undefined>(undefined);
|
||||
const defaultUseReviewTemplate = $derived(!!project.git_host.reviewTemplatePath);
|
||||
const actualUseReviewTemplate = $derived(useReviewTemplate ?? defaultUseReviewTemplate);
|
||||
const projectStore = projectService.project;
|
||||
const project = $derived($projectStore);
|
||||
const reviewTemplatePath = $derived(project?.git_host.reviewTemplatePath);
|
||||
const show = $derived(!!reviewTemplatePath);
|
||||
|
||||
// Fetch PR template content
|
||||
$effect(() => {
|
||||
console.log('defaultReviewTemplatePath', defaultReviewTemplatePath);
|
||||
|
||||
if (actualUseReviewTemplate && actualReviewTemplatePath) {
|
||||
forgeService.getReviewTemplateContent(actualReviewTemplatePath).then((template) => {
|
||||
if (!project) return;
|
||||
if (reviewTemplatePath) {
|
||||
forgeService.getReviewTemplateContent(reviewTemplatePath).then((template) => {
|
||||
pullRequestTemplateBody = template;
|
||||
});
|
||||
}
|
||||
@ -41,6 +34,7 @@
|
||||
|
||||
// Fetch available PR templates
|
||||
$effect(() => {
|
||||
if (!project) return;
|
||||
forgeService.getAvailableReviewTemplates().then((availableTemplates) => {
|
||||
if (availableTemplates) {
|
||||
allAvailableTemplates = availableTemplates.map((availableTemplate) => {
|
||||
@ -52,27 +46,61 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
async function setPullRequestTemplatePath(value: string) {
|
||||
if (!project) return;
|
||||
project.git_host.reviewTemplatePath = value;
|
||||
await projectsService.updateProject(project);
|
||||
}
|
||||
|
||||
export async function setUsePullRequestTemplate(value: boolean) {
|
||||
if (!project) return;
|
||||
|
||||
setTemplate: {
|
||||
if (!value) {
|
||||
project.git_host.reviewTemplatePath = undefined;
|
||||
pullRequestTemplateBody = undefined;
|
||||
break setTemplate;
|
||||
}
|
||||
|
||||
if (allAvailableTemplates[0]) {
|
||||
project.git_host.reviewTemplatePath = allAvailableTemplates[0].value;
|
||||
break setTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
await projectsService.updateProject(project);
|
||||
}
|
||||
|
||||
export const imports = {
|
||||
get showing() {
|
||||
return show;
|
||||
},
|
||||
get hasTemplates() {
|
||||
return allAvailableTemplates.length > 0;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="pr-template__wrap">
|
||||
<Select
|
||||
value={actualReviewTemplatePath}
|
||||
options={allAvailableTemplates.map(({ label, value }) => ({ label, value }))}
|
||||
placeholder="No PR templates found ¯\_(ツ)_/¯"
|
||||
flex="1"
|
||||
searchable
|
||||
disabled={allAvailableTemplates.length <= 1}
|
||||
onselect={(value) => {
|
||||
selectedReviewTemplatePath = value;
|
||||
}}
|
||||
>
|
||||
{#snippet itemSnippet({ item, highlighted })}
|
||||
<SelectItem selected={item.value === actualReviewTemplatePath} {highlighted}>
|
||||
{item.label}
|
||||
</SelectItem>
|
||||
{/snippet}
|
||||
</Select>
|
||||
</div>
|
||||
{#if show}
|
||||
<div class="pr-template__wrap">
|
||||
<Select
|
||||
value={reviewTemplatePath}
|
||||
options={allAvailableTemplates.map(({ label, value }) => ({ label, value }))}
|
||||
placeholder="No PR templates found ¯\_(ツ)_/¯"
|
||||
flex="1"
|
||||
searchable
|
||||
disabled={allAvailableTemplates.length <= 1}
|
||||
onselect={setPullRequestTemplatePath}
|
||||
>
|
||||
{#snippet itemSnippet({ item, highlighted })}
|
||||
<SelectItem selected={item.value === reviewTemplatePath} {highlighted}>
|
||||
{item.label}
|
||||
</SelectItem>
|
||||
{/snippet}
|
||||
</Select>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
.pr-template__wrap {
|
||||
|
@ -1,133 +0,0 @@
|
||||
<script lang="ts">
|
||||
import notFoundSvg from '$lib/assets/empty-state/not-found.svg?raw';
|
||||
import { ForgeService } from '$lib/backend/forge';
|
||||
import { ProjectService, ProjectsService } from '$lib/backend/projects';
|
||||
import SectionCard from '$lib/components/SectionCard.svelte';
|
||||
import Select from '$lib/select/Select.svelte';
|
||||
import SelectItem from '$lib/select/SelectItem.svelte';
|
||||
import Section from '$lib/settings/Section.svelte';
|
||||
import Link from '$lib/shared/Link.svelte';
|
||||
import Spacer from '$lib/shared/Spacer.svelte';
|
||||
import Toggle from '$lib/shared/Toggle.svelte';
|
||||
import { getContext } from '@gitbutler/shared/context';
|
||||
import EmptyStatePlaceholder from '@gitbutler/ui/EmptyStatePlaceholder.svelte';
|
||||
|
||||
const projectsService = getContext(ProjectsService);
|
||||
const projectService = getContext(ProjectService);
|
||||
const forgeService = getContext(ForgeService);
|
||||
|
||||
const projectStore = projectService.project;
|
||||
const project = $derived($projectStore);
|
||||
const useTemplate = $derived(!!project?.git_host.reviewTemplatePath);
|
||||
const selectedTemplate = $derived(project?.git_host.reviewTemplatePath);
|
||||
let allAvailableTemplates = $state<{ label: string; value: string }[]>([]);
|
||||
let isTemplatesAvailable = $state(false);
|
||||
|
||||
$effect(() => {
|
||||
if (!project) {
|
||||
return;
|
||||
}
|
||||
|
||||
forgeService.getAvailableReviewTemplates().then((availableTemplates) => {
|
||||
if (availableTemplates) {
|
||||
allAvailableTemplates = availableTemplates.map((availableTemplate) => {
|
||||
return {
|
||||
label: availableTemplate,
|
||||
value: availableTemplate
|
||||
};
|
||||
});
|
||||
|
||||
isTemplatesAvailable = allAvailableTemplates.length > 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
async function setUsePullRequestTemplate(value: boolean) {
|
||||
if (!project) return;
|
||||
|
||||
setTemplate: {
|
||||
if (!value) {
|
||||
project.git_host.reviewTemplatePath = undefined;
|
||||
break setTemplate;
|
||||
}
|
||||
|
||||
if (allAvailableTemplates[0]) {
|
||||
project.git_host.reviewTemplatePath = allAvailableTemplates[0].value;
|
||||
break setTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
await projectsService.updateProject(project);
|
||||
}
|
||||
|
||||
async function setPullRequestTemplatePath(value: string) {
|
||||
if (!project) return;
|
||||
project.git_host.reviewTemplatePath = value;
|
||||
await projectsService.updateProject(project);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Section>
|
||||
<div class="stack-v">
|
||||
<SectionCard
|
||||
roundedBottom={!useTemplate}
|
||||
orientation="row"
|
||||
labelFor="use-pull-request-template-boolean"
|
||||
>
|
||||
<svelte:fragment slot="title">Pull request templates</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
<Toggle
|
||||
id="use-pull-request-template-boolean"
|
||||
checked={useTemplate}
|
||||
disabled={!isTemplatesAvailable}
|
||||
on:click={(e) => {
|
||||
setUsePullRequestTemplate(
|
||||
(e.target as MouseEvent['target'] & { checked: boolean }).checked
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="caption">
|
||||
If enabled, we will use the path below to set the initial body of any pull requested created
|
||||
on this project through GitButler.
|
||||
</svelte:fragment>
|
||||
</SectionCard>
|
||||
|
||||
{#if useTemplate}
|
||||
<SectionCard roundedTop={false} orientation="row">
|
||||
{#if isTemplatesAvailable}
|
||||
<Select
|
||||
value={selectedTemplate}
|
||||
options={allAvailableTemplates.map(({ label, value }) => ({ label, value }))}
|
||||
label="Available Templates"
|
||||
wide={true}
|
||||
searchable
|
||||
disabled={allAvailableTemplates.length === 0}
|
||||
onselect={(value) => {
|
||||
setPullRequestTemplatePath(value);
|
||||
}}
|
||||
>
|
||||
{#snippet itemSnippet({ item, highlighted })}
|
||||
<SelectItem selected={item.value === selectedTemplate} {highlighted}>
|
||||
{item.label}
|
||||
</SelectItem>
|
||||
{/snippet}
|
||||
</Select>
|
||||
{:else}
|
||||
<EmptyStatePlaceholder image={notFoundSvg} topBottomPadding={20}>
|
||||
{#snippet caption()}
|
||||
No templates found in the project
|
||||
<span class="text-11">
|
||||
<Link
|
||||
href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository"
|
||||
>How to create a template</Link
|
||||
></span
|
||||
>
|
||||
{/snippet}
|
||||
</EmptyStatePlaceholder>
|
||||
{/if}
|
||||
</SectionCard>
|
||||
{/if}
|
||||
</div>
|
||||
</Section>
|
||||
<Spacer />
|
@ -13,7 +13,6 @@
|
||||
import CommitSigningForm from '$lib/settings/userPreferences/CommitSigningForm.svelte';
|
||||
import DetailsForm from '$lib/settings/userPreferences/DetailsForm.svelte';
|
||||
import PreferencesForm from '$lib/settings/userPreferences/PreferencesForm.svelte';
|
||||
import PullRequestTemplateForm from '$lib/settings/userPreferences/PullRequestTemplateForm.svelte';
|
||||
import RemoveProjectForm from '$lib/settings/userPreferences/RemoveProjectForm.svelte';
|
||||
import Spacer from '$lib/shared/Spacer.svelte';
|
||||
|
||||
@ -47,8 +46,6 @@
|
||||
{#if $baseBranchSwitching}
|
||||
<BaseBranchSwitch />
|
||||
{/if}
|
||||
|
||||
<PullRequestTemplateForm />
|
||||
<RemoveProjectForm />
|
||||
</Section>
|
||||
</TabContent>
|
||||
|
Loading…
Reference in New Issue
Block a user