Skip to content

Commit 30e20f7

Browse files
authored
Merge branch 'main' into fix-regression-of-29430
2 parents aae39fb + b7fb20e commit 30e20f7

23 files changed

+879
-731
lines changed

package-lock.json

Lines changed: 15 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"@citation-js/plugin-software-formats": "0.6.1",
1111
"@github/markdown-toolbar-element": "2.2.3",
1212
"@github/relative-time-element": "4.4.3",
13-
"@github/text-expander-element": "2.7.1",
13+
"@github/text-expander-element": "2.8.0",
1414
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
1515
"@primer/octicons": "19.11.0",
1616
"@silverwind/vue3-calendar-heatmap": "2.0.6",
@@ -39,6 +39,7 @@
3939
"monaco-editor": "0.51.0",
4040
"monaco-editor-webpack-plugin": "7.1.0",
4141
"pdfobject": "2.3.0",
42+
"perfect-debounce": "1.0.0",
4243
"postcss": "8.4.41",
4344
"postcss-loader": "8.1.1",
4445
"postcss-nesting": "13.0.0",
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package repo
5+
6+
import (
7+
"net/http"
8+
9+
"code.gitea.io/gitea/models/db"
10+
issues_model "code.gitea.io/gitea/models/issues"
11+
"code.gitea.io/gitea/models/unit"
12+
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
13+
"code.gitea.io/gitea/modules/optional"
14+
"code.gitea.io/gitea/services/context"
15+
)
16+
17+
type issueSuggestion struct {
18+
ID int64 `json:"id"`
19+
Title string `json:"title"`
20+
State string `json:"state"`
21+
PullRequest *struct {
22+
Merged bool `json:"merged"`
23+
Draft bool `json:"draft"`
24+
} `json:"pull_request,omitempty"`
25+
}
26+
27+
// IssueSuggestions returns a list of issue suggestions
28+
func IssueSuggestions(ctx *context.Context) {
29+
keyword := ctx.Req.FormValue("q")
30+
31+
canReadIssues := ctx.Repo.CanRead(unit.TypeIssues)
32+
canReadPulls := ctx.Repo.CanRead(unit.TypePullRequests)
33+
34+
var isPull optional.Option[bool]
35+
if canReadPulls && !canReadIssues {
36+
isPull = optional.Some(true)
37+
} else if canReadIssues && !canReadPulls {
38+
isPull = optional.Some(false)
39+
}
40+
41+
searchOpt := &issue_indexer.SearchOptions{
42+
Paginator: &db.ListOptions{
43+
Page: 0,
44+
PageSize: 5,
45+
},
46+
Keyword: keyword,
47+
RepoIDs: []int64{ctx.Repo.Repository.ID},
48+
IsPull: isPull,
49+
IsClosed: nil,
50+
SortBy: issue_indexer.SortByUpdatedDesc,
51+
}
52+
53+
ids, _, err := issue_indexer.SearchIssues(ctx, searchOpt)
54+
if err != nil {
55+
ctx.ServerError("SearchIssues", err)
56+
return
57+
}
58+
issues, err := issues_model.GetIssuesByIDs(ctx, ids, true)
59+
if err != nil {
60+
ctx.ServerError("FindIssuesByIDs", err)
61+
return
62+
}
63+
64+
suggestions := make([]*issueSuggestion, 0, len(issues))
65+
66+
for _, issue := range issues {
67+
suggestion := &issueSuggestion{
68+
ID: issue.ID,
69+
Title: issue.Title,
70+
State: string(issue.State()),
71+
}
72+
73+
if issue.IsPull {
74+
if err := issue.LoadPullRequest(ctx); err != nil {
75+
ctx.ServerError("LoadPullRequest", err)
76+
return
77+
}
78+
if issue.PullRequest != nil {
79+
suggestion.PullRequest = &struct {
80+
Merged bool `json:"merged"`
81+
Draft bool `json:"draft"`
82+
}{
83+
Merged: issue.PullRequest.HasMerged,
84+
Draft: issue.PullRequest.IsWorkInProgress(ctx),
85+
}
86+
}
87+
}
88+
89+
suggestions = append(suggestions, suggestion)
90+
}
91+
92+
ctx.JSON(http.StatusOK, suggestions)
93+
}

routers/web/web.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,7 @@ func registerRoutes(m *web.Router) {
11781178
})
11791179
})
11801180
}, context.RepoRef())
1181+
m.Get("/issues/suggestions", repo.IssueSuggestions)
11811182
}, ignSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader)
11821183
// end "/{username}/{reponame}": view milestone, label, issue, pull, etc
11831184

templates/shared/combomarkdowneditor.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Template Attributes:
4444
<button class="markdown-toolbar-button markdown-switch-easymde" data-tooltip-content="{{ctx.Locale.Tr "editor.buttons.switch_to_legacy.tooltip"}}">{{svg "octicon-arrow-switch"}}</button>
4545
</div>
4646
</markdown-toolbar>
47-
<text-expander keys=": @" suffix="">
47+
<text-expander keys=": @ #" multiword="#" suffix="">
4848
<textarea class="markdown-text-editor"{{if .TextareaName}} name="{{.TextareaName}}"{{end}}{{if .TextareaPlaceholder}} placeholder="{{.TextareaPlaceholder}}"{{end}}{{if .TextareaAriaLabel}} aria-label="{{.TextareaAriaLabel}}"{{end}}{{if .DisableAutosize}} data-disable-autosize="{{.DisableAutosize}}"{{end}}>{{.TextareaContent}}</textarea>
4949
</text-expander>
5050
<script>

web_src/js/components/ActionRunStatus.vue

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,21 @@
22
Please also update the template file above if this vue is modified.
33
action status accepted: success, skipped, waiting, blocked, running, failure, cancelled, unknown
44
-->
5-
<script lang="ts">
5+
<script lang="ts" setup>
66
import {SvgIcon} from '../svg.ts';
77
8-
export default {
9-
components: {SvgIcon},
10-
props: {
11-
status: {
12-
type: String,
13-
required: true,
14-
},
15-
size: {
16-
type: Number,
17-
default: 16,
18-
},
19-
className: {
20-
type: String,
21-
default: '',
22-
},
23-
localeStatus: {
24-
type: String,
25-
default: '',
26-
},
27-
},
28-
};
8+
withDefaults(defineProps<{
9+
status: '',
10+
size?: number,
11+
className?: string,
12+
localeStatus?: string,
13+
}>(), {
14+
size: 16,
15+
className: undefined,
16+
localeStatus: undefined,
17+
});
2918
</script>
19+
3020
<template>
3121
<span class="tw-flex tw-items-center" :data-tooltip-content="localeStatus" v-if="status">
3222
<SvgIcon name="octicon-check-circle-fill" class="text green" :size="size" :class-name="className" v-if="status === 'success'"/>

web_src/js/components/ActivityHeatmap.vue

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,56 @@
1-
<script lang="ts">
1+
<script lang="ts" setup>
22
// TODO: Switch to upstream after https://github.com/razorness/vue3-calendar-heatmap/pull/34 is merged
33
import {CalendarHeatmap} from '@silverwind/vue3-calendar-heatmap';
4+
import {onMounted, ref} from 'vue';
5+
import type {Value as HeatmapValue, Locale as HeatmapLocale} from '@silverwind/vue3-calendar-heatmap';
46
5-
export default {
6-
components: {CalendarHeatmap},
7-
props: {
8-
values: {
9-
type: Array,
10-
default: () => [],
11-
},
12-
locale: {
13-
type: Object,
14-
default: () => {},
15-
},
16-
},
17-
data: () => ({
18-
colorRange: [
19-
'var(--color-secondary-alpha-60)',
20-
'var(--color-secondary-alpha-60)',
21-
'var(--color-primary-light-4)',
22-
'var(--color-primary-light-2)',
23-
'var(--color-primary)',
24-
'var(--color-primary-dark-2)',
25-
'var(--color-primary-dark-4)',
26-
],
27-
endDate: new Date(),
28-
}),
29-
mounted() {
30-
// work around issue with first legend color being rendered twice and legend cut off
31-
const legend = document.querySelector('.vch__external-legend-wrapper');
32-
legend.setAttribute('viewBox', '12 0 80 10');
33-
legend.style.marginRight = '-12px';
34-
},
35-
methods: {
36-
handleDayClick(e) {
37-
// Reset filter if same date is clicked
38-
const params = new URLSearchParams(document.location.search);
39-
const queryDate = params.get('date');
40-
// Timezone has to be stripped because toISOString() converts to UTC
41-
const clickedDate = new Date(e.date - (e.date.getTimezoneOffset() * 60000)).toISOString().substring(0, 10);
7+
defineProps<{
8+
values?: HeatmapValue[];
9+
locale: {
10+
textTotalContributions: string;
11+
heatMapLocale: Partial<HeatmapLocale>;
12+
noDataText: string;
13+
tooltipUnit: string;
14+
};
15+
}>();
4216
43-
if (queryDate && queryDate === clickedDate) {
44-
params.delete('date');
45-
} else {
46-
params.set('date', clickedDate);
47-
}
17+
const colorRange = [
18+
'var(--color-secondary-alpha-60)',
19+
'var(--color-secondary-alpha-60)',
20+
'var(--color-primary-light-4)',
21+
'var(--color-primary-light-2)',
22+
'var(--color-primary)',
23+
'var(--color-primary-dark-2)',
24+
'var(--color-primary-dark-4)',
25+
];
4826
49-
params.delete('page');
27+
const endDate = ref(new Date());
5028
51-
const newSearch = params.toString();
52-
window.location.search = newSearch.length ? `?${newSearch}` : '';
53-
},
54-
},
55-
};
29+
onMounted(() => {
30+
// work around issue with first legend color being rendered twice and legend cut off
31+
const legend = document.querySelector<HTMLElement>('.vch__external-legend-wrapper');
32+
legend.setAttribute('viewBox', '12 0 80 10');
33+
legend.style.marginRight = '-12px';
34+
});
35+
36+
function handleDayClick(e: Event & {date: Date}) {
37+
// Reset filter if same date is clicked
38+
const params = new URLSearchParams(document.location.search);
39+
const queryDate = params.get('date');
40+
// Timezone has to be stripped because toISOString() converts to UTC
41+
const clickedDate = new Date(e.date.getTime() - (e.date.getTimezoneOffset() * 60000)).toISOString().substring(0, 10);
42+
43+
if (queryDate && queryDate === clickedDate) {
44+
params.delete('date');
45+
} else {
46+
params.set('date', clickedDate);
47+
}
48+
49+
params.delete('page');
50+
51+
const newSearch = params.toString();
52+
window.location.search = newSearch.length ? `?${newSearch}` : '';
53+
}
5654
</script>
5755
<template>
5856
<div class="total-contributions">

0 commit comments

Comments
 (0)