feat: overwrite project issue template
This commit is contained in:
parent
08cdb44490
commit
406aa46a5a
2
go.mod
2
go.mod
@ -7,7 +7,7 @@ toolchain go1.23.6
|
|||||||
require (
|
require (
|
||||||
code.gitea.io/sdk/gitea v0.20.0
|
code.gitea.io/sdk/gitea v0.20.0
|
||||||
github.com/a-h/templ v0.3.833
|
github.com/a-h/templ v0.3.833
|
||||||
github.com/bornholm/genai v0.0.0-20250222092500-1076426da67c
|
github.com/bornholm/genai v0.0.0-20250227201654-4c93b20ee628
|
||||||
github.com/caarlos0/env/v11 v11.2.2
|
github.com/caarlos0/env/v11 v11.2.2
|
||||||
github.com/gabriel-vasile/mimetype v1.4.7
|
github.com/gabriel-vasile/mimetype v1.4.7
|
||||||
github.com/google/go-github/v69 v69.2.0
|
github.com/google/go-github/v69 v69.2.0
|
||||||
|
2
go.sum
2
go.sum
@ -14,6 +14,8 @@ github.com/a-h/templ v0.3.833 h1:L/KOk/0VvVTBegtE0fp2RJQiBm7/52Zxv5fqlEHiQUU=
|
|||||||
github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
|
github.com/a-h/templ v0.3.833/go.mod h1:cAu4AiZhtJfBjMY0HASlyzvkrtjnHWPeEsyGK2YYmfk=
|
||||||
github.com/bornholm/genai v0.0.0-20250222092500-1076426da67c h1:bI0ebsgO1/7Jx6+ZQdDF/I6tTZxyB5hODYz7x/XxwK8=
|
github.com/bornholm/genai v0.0.0-20250222092500-1076426da67c h1:bI0ebsgO1/7Jx6+ZQdDF/I6tTZxyB5hODYz7x/XxwK8=
|
||||||
github.com/bornholm/genai v0.0.0-20250222092500-1076426da67c/go.mod h1:MnuvwSsBEWv/joeK/WgUyfZfOLcLTpd81NJdWoRpRfI=
|
github.com/bornholm/genai v0.0.0-20250222092500-1076426da67c/go.mod h1:MnuvwSsBEWv/joeK/WgUyfZfOLcLTpd81NJdWoRpRfI=
|
||||||
|
github.com/bornholm/genai v0.0.0-20250227201654-4c93b20ee628 h1:YsrF9+NUdwYPLfpJUUfD0h/yH0jvpnaMxtM/sPsFsPg=
|
||||||
|
github.com/bornholm/genai v0.0.0-20250227201654-4c93b20ee628/go.mod h1:kgZb50LiE3cLjyGdUzNwDtpxL5QRllZIsWT2Ub24fIM=
|
||||||
github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3Kg=
|
github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3Kg=
|
||||||
github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc=
|
github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
@ -85,8 +85,13 @@ func (m *IssueManager) GetUserProjects(ctx context.Context, user *model.User) ([
|
|||||||
return projects, nil
|
return projects, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *IssueManager) GenerateIssue(ctx context.Context, user *model.User, projectID string, issueSummary string) (string, string, string, error) {
|
type GeneratIssueOptions struct {
|
||||||
systemPrompt, err := m.getIssueSystemPrompt(ctx, user, projectID)
|
IssueSummary string
|
||||||
|
IssueTemplate string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *IssueManager) GenerateIssue(ctx context.Context, user *model.User, projectID string, issueSummary string, overwrittenIssueTemplate string) (string, string, string, error) {
|
||||||
|
systemPrompt, err := m.getIssueSystemPrompt(ctx, user, projectID, overwrittenIssueTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", "", errors.WithStack(err)
|
return "", "", "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
@ -135,17 +140,21 @@ func (m *IssueManager) GenerateIssue(ctx context.Context, user *model.User, proj
|
|||||||
return title, body, tips, nil
|
return title, body, tips, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *IssueManager) getIssueSystemPrompt(ctx context.Context, user *model.User, projectID string) (string, error) {
|
func (m *IssueManager) getIssueSystemPrompt(ctx context.Context, user *model.User, projectID string, issueTemplate string) (string, error) {
|
||||||
|
if issueTemplate == "" {
|
||||||
forge, err := m.getUserForge(ctx, user)
|
forge, err := m.getUserForge(ctx, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.WithStack(err)
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
issueTemplate, err := forge.GetIssueTemplate(ctx, projectID)
|
repoIssueTemplate, err := forge.GetIssueTemplate(ctx, projectID)
|
||||||
if err != nil && !errors.Is(err, port.ErrFileNotFound) {
|
if err != nil && !errors.Is(err, port.ErrFileNotFound) {
|
||||||
return "", errors.WithStack(err)
|
return "", errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issueTemplate = repoIssueTemplate
|
||||||
|
}
|
||||||
|
|
||||||
if issueTemplate == "" {
|
if issueTemplate == "" {
|
||||||
issueTemplate = issueDefaultTemplate
|
issueTemplate = issueDefaultTemplate
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,10 @@ const bodyPlaceholder = `
|
|||||||
Une fois votre demande générée, vous pourrez l'éditer puis la créer directement en cliquant sur le bouton 'Créer' ci-dessous.
|
Une fois votre demande générée, vous pourrez l'éditer puis la créer directement en cliquant sur le bouton 'Créer' ci-dessous.
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const issueTemplatePlaceholder = `
|
||||||
|
Vous pouvez surcharger le modèle de demande fourni par le projet en remplissant ce champ.
|
||||||
|
`
|
||||||
|
|
||||||
func NewIssueSummaryForm() *form.Form {
|
func NewIssueSummaryForm() *form.Form {
|
||||||
return form.New(
|
return form.New(
|
||||||
form.NewField(
|
form.NewField(
|
||||||
@ -47,6 +51,14 @@ func NewIssueSummaryForm() *form.Form {
|
|||||||
},
|
},
|
||||||
form.NonEmpty("Ce champ ne doit pas être vide."),
|
form.NonEmpty("Ce champ ne doit pas être vide."),
|
||||||
),
|
),
|
||||||
|
form.NewField(
|
||||||
|
"template",
|
||||||
|
form.Attrs{
|
||||||
|
"type": "textarea",
|
||||||
|
"rows": "20",
|
||||||
|
"placeholder": strings.TrimSpace(issueTemplatePlaceholder),
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +139,15 @@ templ IssuePage(vmodel IssuePageVModel) {
|
|||||||
"hx-on:change", "onSummaryChange(event)",
|
"hx-on:change", "onSummaryChange(event)",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
<details class="my-3">
|
||||||
|
<summary class="is-clickable">Paramètres avancés</summary>
|
||||||
|
@common.FormTextarea(
|
||||||
|
vmodel.SummaryForm, "issue-template", "template", "Surcharger le modèle de demande",
|
||||||
|
common.WithTextareaAttrs(
|
||||||
|
"hx-on:change", "onIssueTemplateChange(event)",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
</details>
|
||||||
<div class="buttons is-right">
|
<div class="buttons is-right">
|
||||||
<button type="submit" class="button is-info is-large">
|
<button type="submit" class="button is-info is-large">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
@ -184,6 +205,12 @@ templ IssuePage(vmodel IssuePageVModel) {
|
|||||||
sessionStorage.setItem(`summary-${projectId}`, summary);
|
sessionStorage.setItem(`summary-${projectId}`, summary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onIssueTemplateChange(evt) {
|
||||||
|
const issueTemplate = evt.currentTarget.value;
|
||||||
|
const projectId = document.getElementById("issue-project").value;
|
||||||
|
localStorage.setItem(`issue-template-${projectId}`, issueTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
function savePreferredProject() {
|
function savePreferredProject() {
|
||||||
const projectId = document.getElementById("issue-project").value;
|
const projectId = document.getElementById("issue-project").value;
|
||||||
localStorage.setItem(`preferred-project`, projectId);
|
localStorage.setItem(`preferred-project`, projectId);
|
||||||
@ -211,9 +238,22 @@ templ IssuePage(vmodel IssuePageVModel) {
|
|||||||
summaryTextarea.value = savedSummary;
|
summaryTextarea.value = savedSummary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function restoreIssueTemplate() {
|
||||||
|
const issueTemplateTextarea = document.getElementById("issue-template");
|
||||||
|
if (!issueTemplateTextarea) return;
|
||||||
|
const issueTemplate = issueTemplateTextarea.value;
|
||||||
|
if (issueTemplate !== "") return;
|
||||||
|
const projectId = document.getElementById("issue-project").value;
|
||||||
|
if (!projectId) return;
|
||||||
|
const savedIssueTemplate = localStorage.getItem(`issue-template-${projectId}`);
|
||||||
|
if (!savedIssueTemplate) return;
|
||||||
|
issueTemplateTextarea.value = savedIssueTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
htmx.onLoad(function(){
|
htmx.onLoad(function(){
|
||||||
restoreLastSummary();
|
restoreLastSummary();
|
||||||
restorePreferredProject();
|
restorePreferredProject();
|
||||||
|
restoreIssueTemplate();
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,10 @@ const bodyPlaceholder = `
|
|||||||
Une fois votre demande générée, vous pourrez l'éditer puis la créer directement en cliquant sur le bouton 'Créer' ci-dessous.
|
Une fois votre demande générée, vous pourrez l'éditer puis la créer directement en cliquant sur le bouton 'Créer' ci-dessous.
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const issueTemplatePlaceholder = `
|
||||||
|
Vous pouvez surcharger le modèle de demande fourni par le projet en remplissant ce champ.
|
||||||
|
`
|
||||||
|
|
||||||
func NewIssueSummaryForm() *form.Form {
|
func NewIssueSummaryForm() *form.Form {
|
||||||
return form.New(
|
return form.New(
|
||||||
form.NewField(
|
form.NewField(
|
||||||
@ -55,6 +59,14 @@ func NewIssueSummaryForm() *form.Form {
|
|||||||
},
|
},
|
||||||
form.NonEmpty("Ce champ ne doit pas être vide."),
|
form.NonEmpty("Ce champ ne doit pas être vide."),
|
||||||
),
|
),
|
||||||
|
form.NewField(
|
||||||
|
"template",
|
||||||
|
form.Attrs{
|
||||||
|
"type": "textarea",
|
||||||
|
"rows": "20",
|
||||||
|
"placeholder": strings.TrimSpace(issueTemplatePlaceholder),
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +155,7 @@ func IssuePage(vmodel IssuePageVModel) templ.Component {
|
|||||||
var templ_7745c5c3_Var5 string
|
var templ_7745c5c3_Var5 string
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(vmodel.IssueURL)
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(vmodel.IssueURL)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/issue/component/issue_page.templ`, Line: 97, Col: 89}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/http/handler/webui/issue/component/issue_page.templ`, Line: 109, Col: 89}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -200,7 +212,20 @@ func IssuePage(vmodel IssuePageVModel) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<div class=\"buttons is-right\"><button type=\"submit\" class=\"button is-info is-large\"><span class=\"icon\"><i class=\"fa fa-robot\"></i></span> <span>Générer</span></button></div></form></div><div class=\"column\"><h2 class=\"title is-size-3\">Votre demande</h2><form action=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<details class=\"my-3\"><summary class=\"is-clickable\">Paramètres avancés</summary>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = common.FormTextarea(
|
||||||
|
vmodel.SummaryForm, "issue-template", "template", "Surcharger le modèle de demande",
|
||||||
|
common.WithTextareaAttrs(
|
||||||
|
"hx-on:change", "onIssueTemplateChange(event)",
|
||||||
|
),
|
||||||
|
).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</details><div class=\"buttons is-right\"><button type=\"submit\" class=\"button is-info is-large\"><span class=\"icon\"><i class=\"fa fa-robot\"></i></span> <span>Générer</span></button></div></form></div><div class=\"column\"><h2 class=\"title is-size-3\">Votre demande</h2><form action=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -209,7 +234,7 @@ func IssuePage(vmodel IssuePageVModel) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\" method=\"post\" hx-disabled-elt=\"textarea, input, select, button\" hx-indicator=\"#generation-progress\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" method=\"post\" hx-disabled-elt=\"textarea, input, select, button\" hx-indicator=\"#generation-progress\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -221,14 +246,14 @@ func IssuePage(vmodel IssuePageVModel) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"buttons is-right\"><button type=\"submit\" class=\"button is-info is-large\"><span class=\"icon\"><i class=\"fa fa-rocket\"></i></span> <span>Créer</span></button></div></form></div></div><progress id=\"generation-progress\" class=\"htmx-indicator progress\"></progress> ")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<div class=\"buttons is-right\"><button type=\"submit\" class=\"button is-info is-large\"><span class=\"icon\"><i class=\"fa fa-rocket\"></i></span> <span>Créer</span></button></div></form></div></div><progress id=\"generation-progress\" class=\"htmx-indicator progress\"></progress> ")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
if vmodel.IssueTips != "" {
|
if vmodel.IssueTips != "" {
|
||||||
html := markdownToHTML(ctx, vmodel.IssueTips)
|
html := markdownToHTML(ctx, vmodel.IssueTips)
|
||||||
if html != "" {
|
if html != "" {
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "<article class=\"message is-info mt-5\"><div class=\"message-header\"><p><span class=\"icon\"><i class=\"fa fa-lightbulb\"></i></span>Questionnements</p><button class=\"delete\" aria-label=\"delete\" hx-on:click=\"onCloseMessage(this)\"></button></div><div class=\"message-body\"><div class=\"content\"><p>Utilisez ces quelques questions pour réfléchir aux éléments d'informations nécessaire à la bonne rédaction de votre demande:</p>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<article class=\"message is-info mt-5\"><div class=\"message-header\"><p><span class=\"icon\"><i class=\"fa fa-lightbulb\"></i></span>Questionnements</p><button class=\"delete\" aria-label=\"delete\" hx-on:click=\"onCloseMessage(this)\"></button></div><div class=\"message-body\"><div class=\"content\"><p>Utilisez ces quelques questions pour réfléchir aux éléments d'informations nécessaire à la bonne rédaction de votre demande:</p>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -236,13 +261,13 @@ func IssuePage(vmodel IssuePageVModel) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div></div></article>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</div></div></article>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</section></div><script type=\"text/javascript\">\n\t\tfunction onCloseMessage(closeElement) {\n\t\t\tcloseElement.closest('.message').style.display = 'none';\n\t\t}\n\n\t\tfunction onSummaryChange(evt) {\n\t\t\tconst summary = evt.currentTarget.value;\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tsessionStorage.setItem(`summary-${projectId}`, summary);\n\t\t}\n\n\t\tfunction savePreferredProject() {\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tlocalStorage.setItem(`preferred-project`, projectId);\n\t\t}\n\n\t\tfunction restorePreferredProject() {\n\t\t\tconst preferredProject = localStorage.getItem(`preferred-project`);\n\t\t\tif (!preferredProject) return;\n\t\t\tconst projectElement = document.getElementById(\"issue-project\");\n\t\t\tif (!projectElement) return;\n\t\t\tif (preferredProject === projectElement.value) return;\n\t\t\tprojectElement.value = preferredProject;\n\t\t\tprojectElement.dispatchEvent(new Event('change'));\n\t\t}\n\n\t\tfunction restoreLastSummary() {\n\t\t\tconst summaryTextarea = document.getElementById(\"issue-summary\");\n\t\t\tif (!summaryTextarea) return;\n const summary = summaryTextarea.value;\n\t\t\tif (summary !== \"\") return;\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tif (!projectId) return;\n\t\t\tconst savedSummary = sessionStorage.getItem(`summary-${projectId}`);\n\t\t\tif (!savedSummary) return;\n\t\t\tsummaryTextarea.value = savedSummary;\n\t\t}\n\n\t\thtmx.onLoad(function(){\n\t\t\trestoreLastSummary();\n\t\t\trestorePreferredProject();\n })\n\t\t</script>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</section></div><script type=\"text/javascript\">\n\t\tfunction onCloseMessage(closeElement) {\n\t\t\tcloseElement.closest('.message').style.display = 'none';\n\t\t}\n\n\t\tfunction onSummaryChange(evt) {\n\t\t\tconst summary = evt.currentTarget.value;\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tsessionStorage.setItem(`summary-${projectId}`, summary);\n\t\t}\n\n\t\tfunction onIssueTemplateChange(evt) {\n\t\t\tconst issueTemplate = evt.currentTarget.value;\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tlocalStorage.setItem(`issue-template-${projectId}`, issueTemplate);\n\t\t}\n\n\t\tfunction savePreferredProject() {\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tlocalStorage.setItem(`preferred-project`, projectId);\n\t\t}\n\n\t\tfunction restorePreferredProject() {\n\t\t\tconst preferredProject = localStorage.getItem(`preferred-project`);\n\t\t\tif (!preferredProject) return;\n\t\t\tconst projectElement = document.getElementById(\"issue-project\");\n\t\t\tif (!projectElement) return;\n\t\t\tif (preferredProject === projectElement.value) return;\n\t\t\tprojectElement.value = preferredProject;\n\t\t\tprojectElement.dispatchEvent(new Event('change'));\n\t\t}\n\n\t\tfunction restoreLastSummary() {\n\t\t\tconst summaryTextarea = document.getElementById(\"issue-summary\");\n\t\t\tif (!summaryTextarea) return;\n const summary = summaryTextarea.value;\n\t\t\tif (summary !== \"\") return;\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tif (!projectId) return;\n\t\t\tconst savedSummary = sessionStorage.getItem(`summary-${projectId}`);\n\t\t\tif (!savedSummary) return;\n\t\t\tsummaryTextarea.value = savedSummary;\n\t\t}\n\n\t\tfunction restoreIssueTemplate() {\n\t\t\tconst issueTemplateTextarea = document.getElementById(\"issue-template\");\n\t\t\tif (!issueTemplateTextarea) return;\n const issueTemplate = issueTemplateTextarea.value;\n\t\t\tif (issueTemplate !== \"\") return;\n\t\t\tconst projectId = document.getElementById(\"issue-project\").value;\n\t\t\tif (!projectId) return;\n\t\t\tconst savedIssueTemplate = localStorage.getItem(`issue-template-${projectId}`);\n\t\t\tif (!savedIssueTemplate) return;\n\t\t\tissueTemplateTextarea.value = savedIssueTemplate;\n\t\t}\n\n\t\thtmx.onLoad(function(){\n\t\t\trestoreLastSummary();\n\t\t\trestorePreferredProject();\n\t\t\trestoreIssueTemplate();\n })\n\t\t</script>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package issue
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"forge.cadoles.com/wpetit/clearcase/internal/core/service"
|
"forge.cadoles.com/wpetit/clearcase/internal/core/service"
|
||||||
httpCtx "forge.cadoles.com/wpetit/clearcase/internal/http/context"
|
httpCtx "forge.cadoles.com/wpetit/clearcase/internal/http/context"
|
||||||
@ -99,13 +100,21 @@ func (h *Handler) handleIssueSummaryForm(w http.ResponseWriter, r *http.Request)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
summary, err := form.FormFieldAttr[string](issueSummaryForm, "summary", "value")
|
issueSummary, err := form.FormFieldAttr[string](issueSummaryForm, "summary", "value")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.handleError(w, r, errors.WithStack(err))
|
h.handleError(w, r, errors.WithStack(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
issueTitle, issueBody, issueTips, err := h.issueManager.GenerateIssue(ctx, httpCtx.User(ctx), projectID, summary)
|
issueTemplate, err := form.FormFieldAttr[string](issueSummaryForm, "template", "value")
|
||||||
|
if err != nil {
|
||||||
|
h.handleError(w, r, errors.WithStack(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
issueTemplate = strings.TrimSpace(issueTemplate)
|
||||||
|
|
||||||
|
issueTitle, issueBody, issueTips, err := h.issueManager.GenerateIssue(ctx, httpCtx.User(ctx), projectID, issueSummary, issueTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.handleError(w, r, errors.WithStack(err))
|
h.handleError(w, r, errors.WithStack(err))
|
||||||
return
|
return
|
||||||
|
@ -13,13 +13,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewIssueManagerFromConfig(ctx context.Context, conf *config.Config) (*service.IssueManager, error) {
|
func NewIssueManagerFromConfig(ctx context.Context, conf *config.Config) (*service.IssueManager, error) {
|
||||||
llmCtx := provider.FromMap(ctx, "", map[string]string{
|
client, err := provider.Create(ctx,
|
||||||
string(provider.ContextKeyAPIBaseURL): conf.LLM.Provider.BaseURL,
|
provider.WithConfig(&provider.Config{
|
||||||
string(provider.ContextKeyAPIKey): conf.LLM.Provider.Key,
|
Provider: provider.Name(conf.LLM.Provider.Name),
|
||||||
string(provider.ContextKeyModel): conf.LLM.Provider.Model,
|
BaseURL: conf.LLM.Provider.BaseURL,
|
||||||
})
|
Key: conf.LLM.Provider.Key,
|
||||||
|
Model: conf.LLM.Provider.Model,
|
||||||
client, err := provider.Create(llmCtx, provider.Name(conf.LLM.Provider.Name))
|
}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not create llm client '%s'", conf.LLM.Provider.Name)
|
return nil, errors.Wrapf(err, "could not create llm client '%s'", conf.LLM.Provider.Name)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user