Compare commits

..

No commits in common. "323c6cba20db618d48f4939d1fcaaa036ec0a0d7" and "9c62ca568962bdefb12aaee21c479025b0dea515" have entirely different histories.

25 changed files with 85 additions and 142 deletions

View File

@ -88,7 +88,7 @@ func main() {
} }
func runEnvironmentToIni(c *cli.Context) error { func runEnvironmentToIni(c *cli.Context) error {
setting.InitWorkPathAndCfgProvider(os.Getenv, setting.ArgWorkPathAndCustomConf{ setting.InitWorkPathAndCommonConfig(os.Getenv, setting.ArgWorkPathAndCustomConf{
WorkPath: c.String("work-path"), WorkPath: c.String("work-path"),
CustomPath: c.String("custom-path"), CustomPath: c.String("custom-path"),
CustomConf: c.String("config"), CustomConf: c.String("config"),

2
go.mod
View File

@ -122,7 +122,7 @@ require (
mvdan.cc/xurls/v2 v2.4.0 mvdan.cc/xurls/v2 v2.4.0
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
xorm.io/builder v0.3.12 xorm.io/builder v0.3.12
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75 xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e
) )
require ( require (

4
go.sum
View File

@ -1923,5 +1923,5 @@ strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM= xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75 h1:ReBAlO50dCIXCWF8Gbi0ZRa62AGAwCJNCPaUNUa7JSg= xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e h1:d5PY6mwuQK5/7T6VKfFswaKMzLmGTHkJ/ZS7+cUIAjk=
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw= xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=

View File

@ -123,10 +123,7 @@ func newXORMEngine() (*xorm.Engine, error) {
// SyncAllTables sync the schemas of all tables, is required by unit test code // SyncAllTables sync the schemas of all tables, is required by unit test code
func SyncAllTables() error { func SyncAllTables() error {
_, err := x.StoreEngine("InnoDB").SyncWithOptions(xorm.SyncOptions{ return x.StoreEngine("InnoDB").Sync2(tables...)
WarnIfDatabaseColumnMissed: true,
}, tables...)
return err
} }
// InitEngine initializes the xorm.Engine and sets it as db.DefaultContext // InitEngine initializes the xorm.Engine and sets it as db.DefaultContext

View File

@ -229,41 +229,39 @@ func (issues IssueList) loadMilestones(ctx context.Context) error {
return nil return nil
} }
func (issues IssueList) LoadProjects(ctx context.Context) error { func (issues IssueList) getProjectIDs() []int64 {
issueIDs := issues.getIssueIDs() ids := make(container.Set[int64], len(issues))
projectMaps := make(map[int64]*project_model.Project, len(issues)) for _, issue := range issues {
left := len(issueIDs) ids.Add(issue.ProjectID())
}
return ids.Values()
}
type projectWithIssueID struct { func (issues IssueList) loadProjects(ctx context.Context) error {
*project_model.Project `xorm:"extends"` projectIDs := issues.getProjectIDs()
IssueID int64 if len(projectIDs) == 0 {
return nil
} }
projectMaps := make(map[int64]*project_model.Project, len(projectIDs))
left := len(projectIDs)
for left > 0 { for left > 0 {
limit := db.DefaultMaxInSize limit := db.DefaultMaxInSize
if left < limit { if left < limit {
limit = left limit = left
} }
projects := make([]*projectWithIssueID, 0, limit)
err := db.GetEngine(ctx). err := db.GetEngine(ctx).
Table("project"). In("id", projectIDs[:limit]).
Select("project.*, project_issue.issue_id"). Find(&projectMaps)
Join("INNER", "project_issue", "project.id = project_issue.project_id").
In("project_issue.issue_id", issueIDs[:limit]).
Find(&projects)
if err != nil { if err != nil {
return err return err
} }
for _, project := range projects {
projectMaps[project.IssueID] = project.Project
}
left -= limit left -= limit
issueIDs = issueIDs[limit:] projectIDs = projectIDs[limit:]
} }
for _, issue := range issues { for _, issue := range issues {
issue.Project = projectMaps[issue.ID] issue.Project = projectMaps[issue.ProjectID()]
} }
return nil return nil
} }
@ -543,7 +541,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error {
return fmt.Errorf("issue.loadAttributes: loadMilestones: %w", err) return fmt.Errorf("issue.loadAttributes: loadMilestones: %w", err)
} }
if err := issues.LoadProjects(ctx); err != nil { if err := issues.loadProjects(ctx); err != nil {
return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err) return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err)
} }

View File

@ -66,12 +66,8 @@ func TestIssueList_LoadAttributes(t *testing.T) {
} }
if issue.ID == int64(1) { if issue.ID == int64(1) {
assert.Equal(t, int64(400), issue.TotalTrackedTime) assert.Equal(t, int64(400), issue.TotalTrackedTime)
assert.NotNil(t, issue.Project)
} else if issue.ID == int64(2) { } else if issue.ID == int64(2) {
assert.Equal(t, int64(3682), issue.TotalTrackedTime) assert.Equal(t, int64(3682), issue.TotalTrackedTime)
assert.Nil(t, issue.Project)
} else {
assert.Nil(t, issue.Project)
} }
} }
} }

View File

@ -27,6 +27,11 @@ func (issue *Issue) LoadProject(ctx context.Context) (err error) {
return err return err
} }
// ProjectID return project id if issue was assigned to one
func (issue *Issue) ProjectID() int64 {
return issue.projectID(db.DefaultContext)
}
func (issue *Issue) projectID(ctx context.Context) int64 { func (issue *Issue) projectID(ctx context.Context) int64 {
var ip project_model.ProjectIssue var ip project_model.ProjectIssue
has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip) has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)

View File

@ -89,12 +89,6 @@ func (s *stringWithDefault) Set(v string) {
// InitWorkPathAndCommonConfig will set AppWorkPath, CustomPath and CustomConf, init default config provider by CustomConf and load common settings, // InitWorkPathAndCommonConfig will set AppWorkPath, CustomPath and CustomConf, init default config provider by CustomConf and load common settings,
func InitWorkPathAndCommonConfig(getEnvFn func(name string) string, args ArgWorkPathAndCustomConf) { func InitWorkPathAndCommonConfig(getEnvFn func(name string) string, args ArgWorkPathAndCustomConf) {
InitWorkPathAndCfgProvider(getEnvFn, args)
LoadCommonSettings()
}
// InitWorkPathAndCfgProvider will set AppWorkPath, CustomPath and CustomConf, init default config provider by CustomConf
func InitWorkPathAndCfgProvider(getEnvFn func(name string) string, args ArgWorkPathAndCustomConf) {
tryAbsPath := func(paths ...string) string { tryAbsPath := func(paths ...string) string {
s := paths[len(paths)-1] s := paths[len(paths)-1]
for i := len(paths) - 2; i >= 0; i-- { for i := len(paths) - 2; i >= 0; i-- {
@ -192,4 +186,6 @@ func InitWorkPathAndCfgProvider(getEnvFn func(name string) string, args ArgWorkP
AppWorkPath = tmpWorkPath.Value AppWorkPath = tmpWorkPath.Value
CustomPath = tmpCustomPath.Value CustomPath = tmpCustomPath.Value
CustomConf = tmpCustomConf.Value CustomConf = tmpCustomConf.Value
LoadCommonSettings()
} }

View File

@ -383,7 +383,7 @@ func ViewProject(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplProjectsView) ctx.HTML(http.StatusOK, tplProjectsView)
} }
func getActionIssues(ctx *context.Context) issues_model.IssueList { func getActionIssues(ctx *context.Context) []*issues_model.Issue {
commaSeparatedIssueIDs := ctx.FormString("issue_ids") commaSeparatedIssueIDs := ctx.FormString("issue_ids")
if len(commaSeparatedIssueIDs) == 0 { if len(commaSeparatedIssueIDs) == 0 {
return nil return nil
@ -429,14 +429,9 @@ func UpdateIssueProject(ctx *context.Context) {
return return
} }
if err := issues.LoadProjects(ctx); err != nil {
ctx.ServerError("LoadProjects", err)
return
}
projectID := ctx.FormInt64("id") projectID := ctx.FormInt64("id")
for _, issue := range issues { for _, issue := range issues {
oldProjectID := issue.Project.ID oldProjectID := issue.ProjectID()
if oldProjectID == projectID { if oldProjectID == projectID {
continue continue
} }

View File

@ -1984,7 +1984,7 @@ func checkIssueRights(ctx *context.Context, issue *issues_model.Issue) {
} }
} }
func getActionIssues(ctx *context.Context) issues_model.IssueList { func getActionIssues(ctx *context.Context) []*issues_model.Issue {
commaSeparatedIssueIDs := ctx.FormString("issue_ids") commaSeparatedIssueIDs := ctx.FormString("issue_ids")
if len(commaSeparatedIssueIDs) == 0 { if len(commaSeparatedIssueIDs) == 0 {
return nil return nil
@ -2749,7 +2749,7 @@ func UpdateIssueStatus(ctx *context.Context) {
log.Warn("Unrecognized action: %s", action) log.Warn("Unrecognized action: %s", action)
} }
if _, err := issues.LoadRepositories(ctx); err != nil { if _, err := issues_model.IssueList(issues).LoadRepositories(ctx); err != nil {
ctx.ServerError("LoadRepositories", err) ctx.ServerError("LoadRepositories", err)
return return
} }

View File

@ -378,14 +378,9 @@ func UpdateIssueProject(ctx *context.Context) {
return return
} }
if err := issues.LoadProjects(ctx); err != nil {
ctx.ServerError("LoadProjects", err)
return
}
projectID := ctx.FormInt64("id") projectID := ctx.FormInt64("id")
for _, issue := range issues { for _, issue := range issues {
oldProjectID := issue.Project.ID oldProjectID := issue.ProjectID()
if oldProjectID == projectID { if oldProjectID == projectID {
continue continue
} }

View File

@ -11,16 +11,16 @@
</a> </a>
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column --> <!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
<div class="ui secondary menu item navbar-mobile-right"> <div class="ui secondary menu item navbar-mobile-right gt-gap-2">
{{if .IsSigned}} {{if .IsSigned}}
<a id="mobile-notifications-icon" class="item gt-w-auto gt-p-3" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{.locale.Tr "notifications"}}" aria-label="{{.locale.Tr "notifications"}}"> <a class="item mobile-right-item gt-mr-2 gt-p-3" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{.locale.Tr "notifications"}}" aria-label="{{.locale.Tr "notifications"}}">
<div class="gt-relative"> <div class="gt-relative">
{{svg "octicon-bell"}} {{svg "octicon-bell"}}
<span class="notification_count{{if not $notificationUnreadCount}} gt-hidden{{end}}">{{$notificationUnreadCount}}</span> <span class="notification_count{{if not $notificationUnreadCount}} gt-hidden{{end}}">{{$notificationUnreadCount}}</span>
</div> </div>
</a> </a>
{{end}} {{end}}
<button class="item gt-w-auto ui icon mini button gt-p-3 gt-m-0" id="navbar-expand-toggle">{{svg "octicon-three-bars"}}</button> <button class="item mobile-right-item ui icon mini button gt-p-3 gt-m-0" id="navbar-expand-toggle">{{svg "octicon-three-bars"}}</button>
</div> </div>

View File

@ -165,6 +165,13 @@
<div class="item">item</div> <div class="item">item</div>
</div> </div>
</div> </div>
<div class="ui button dropdown">
<span class="text">button dropdown</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<div class="item">item</div>
</div>
</div>
<div class="ui search selection dropdown"> <div class="ui search selection dropdown">
<span class="text">search ...</span> <span class="text">search ...</span>
<input name="value" class="search"> <input name="value" class="search">
@ -205,40 +212,19 @@
<div> <div>
<div class="ui dropdown mini button"> <div class="ui dropdown mini button">
<span class="text">mini dropdown</span> <span class="text">small dropdown</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 12 "dropdown icon"}}
<div class="menu">
<div class="item">item</div>
</div> </div>
<div class="ui dropdown tiny button">
<span class="text">tiny dropdown</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</div>
<div class="ui button dropdown">
<span class="text">button dropdown</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</div> </div>
<div class="ui dropdown large button"> <div class="ui dropdown large button">
<span class="text">large dropdown</span> <span class="text">large dropdown</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 18 "dropdown icon"}}
<div class="menu">
<div class="item">item</div>
</div> </div>
</div> </div>
<div>
<div class="ui dropdown mini compact button">
<span class="text">mini compact</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</div>
<div class="ui dropdown tiny compact button">
<span class="text">tiny compact</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</div>
<div class="ui button compact dropdown">
<span class="text">button compact</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</div>
<div class="ui dropdown large compact button">
<span class="text">large compact</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</div>
</div> </div>
</div> </div>

View File

@ -54,9 +54,9 @@
{{$description := .DescriptionHTML $.Context}} {{$description := .DescriptionHTML $.Context}}
{{if $description}}<p>{{$description}}</p>{{end}} {{if $description}}<p>{{$description}}</p>{{end}}
{{if .Topics}} {{if .Topics}}
<div class="gt-df gt-fw gt-gap-2 gt-mb-3"> <div class="ui tags">
{{range .Topics}} {{range .Topics}}
{{if ne . ""}}<a class="ui label" href="{{AppSubUrl}}/explore/repos?q={{.}}&topic=1">{{.}}</a>{{end}} {{if ne . ""}}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic=1"><div class="ui small label topic">{{.}}</div></a>{{end}}
{{end}} {{end}}
</div> </div>
{{end}} {{end}}

View File

@ -26,8 +26,7 @@
{{.locale.Tr "repo.diff.browse_source"}} {{.locale.Tr "repo.diff.browse_source"}}
</a> </a>
{{if and ($.Permission.CanWrite $.UnitTypeCode) (not $.Repository.IsArchived) (not .IsDeleted)}}{{- /* */ -}} {{if and ($.Permission.CanWrite $.UnitTypeCode) (not $.Repository.IsArchived) (not .IsDeleted)}}{{- /* */ -}}
<div class="ui dropdown primary tiny button"> <div class="ui primary tiny floating dropdown icon button">{{.locale.Tr "repo.commit.operations"}}
{{.locale.Tr "repo.commit.operations"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}} {{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu"> <div class="menu">
<div class="ui header">{{.locale.Tr "repo.commit.operations"}}</div> <div class="ui header">{{.locale.Tr "repo.commit.operations"}}</div>

View File

@ -49,7 +49,7 @@
</div> </div>
</div> </div>
<script id="diff-data-script" type="module"> <script id="diff-data-script" type="module">
const diffDataFiles = [{{range $i, $file := .Diff.Files}}{Name:"{{$file.Name}}",NameHash:"{{$file.NameHash}}",Type:{{$file.Type}},IsBin:{{$file.IsBin}},Addition:{{$file.Addition}},Deletion:{{$file.Deletion}},IsViewed:{{$file.IsViewed}}},{{end}}]; const diffDataFiles = [{{range $i, $file := .Diff.Files}}{Name:"{{$file.Name}}",NameHash:"{{$file.NameHash}}",Type:{{$file.Type}},IsBin:{{$file.IsBin}},Addition:{{$file.Addition}},Deletion:{{$file.Deletion}}},{{end}}];
const diffData = { const diffData = {
isIncomplete: {{.Diff.IsIncomplete}}, isIncomplete: {{.Diff.IsIncomplete}},
tooManyFilesMessage: "{{$.locale.Tr "repo.diff.too_many_files"}}", tooManyFilesMessage: "{{$.locale.Tr "repo.diff.too_many_files"}}",

View File

@ -192,9 +192,9 @@
</div> </div>
</div> </div>
<div class="ui select-project list"> <div class="ui select-project list">
<span class="no-select item {{if .Issue.Project}}gt-hidden{{end}}">{{.locale.Tr "repo.issues.new.no_projects"}}</span> <span class="no-select item {{if .Issue.ProjectID}}gt-hidden{{end}}">{{.locale.Tr "repo.issues.new.no_projects"}}</span>
<div class="selected"> <div class="selected">
{{if .Issue.Project}} {{if .Issue.ProjectID}}
<a class="item muted sidebar-item-link" href="{{.Issue.Project.Link}}"> <a class="item muted sidebar-item-link" href="{{.Issue.Project.Link}}">
{{svg .Issue.Project.IconName 18 "gt-mr-3"}}{{.Issue.Project.Title}} {{svg .Issue.Project.IconName 18 "gt-mr-3"}}{{.Issue.Project.Title}}
</a> </a>

View File

@ -1,5 +1,3 @@
{{/* No account links, no way to add account links: Menu will not be shown. */}}
{{if or .AccountLinks .OrderedOAuth2Names}}
<h4 class="ui top attached header"> <h4 class="ui top attached header">
{{.locale.Tr "settings.manage_account_links"}} {{.locale.Tr "settings.manage_account_links"}}
{{if .OrderedOAuth2Names}} {{if .OrderedOAuth2Names}}
@ -25,6 +23,7 @@
<div class="item"> <div class="item">
{{.locale.Tr "settings.manage_account_links_desc"}} {{.locale.Tr "settings.manage_account_links_desc"}}
</div> </div>
{{if .AccountLinks}}
{{range $loginSource, $provider := .AccountLinks}} {{range $loginSource, $provider := .AccountLinks}}
<div class="item gt-df gt-ac"> <div class="item gt-df gt-ac">
<div class="gt-f1"> <div class="gt-f1">
@ -38,6 +37,7 @@
</button> </button>
</div> </div>
{{end}} {{end}}
{{end}}
</div> </div>
</div> </div>
@ -51,4 +51,3 @@
</div> </div>
{{template "base/modal_actions_confirm" .}} {{template "base/modal_actions_confirm" .}}
</div> </div>
{{end}}

View File

@ -2192,17 +2192,6 @@ table th[data-sortt-desc] .svg {
- "> .ui.label > .delete.icon": the "x" icon for removing a label item in multiple selection dropdown - "> .ui.label > .delete.icon": the "x" icon for removing a label item in multiple selection dropdown
*/ */
.ui.dropdown.mini.button,
.ui.dropdown.tiny.button {
padding-right: 20px;
}
.ui.dropdown.button {
padding-right: 22px;
}
.ui.dropdown.large.button {
padding-right: 24px;
}
/* Gitea uses SVG images instead of Fomantic builtin "<i>" font icons, so we need to reset the icon styles */ /* Gitea uses SVG images instead of Fomantic builtin "<i>" font icons, so we need to reset the icon styles */
.ui.ui.dropdown > .icon.icon { .ui.ui.dropdown > .icon.icon {
position: initial; /* plain dropdown and button dropdown use flex layout for icons */ position: initial; /* plain dropdown and button dropdown use flex layout for icons */

View File

@ -32,6 +32,10 @@
font-size: 12px; font-size: 12px;
} }
.ui.repository.list .item .ui.tags {
margin-bottom: 0.5rem;
}
.ui.repository.list .repo-title .labels { .ui.repository.list .repo-title .labels {
word-break: normal; word-break: normal;
flex-shrink: 0; flex-shrink: 0;

View File

@ -75,7 +75,6 @@ Gitea's private styles use `g-` prefix.
.gt-self-start { align-self: flex-start !important; } .gt-self-start { align-self: flex-start !important; }
.gt-self-end { align-self: flex-end !important; } .gt-self-end { align-self: flex-end !important; }
.gt-no-underline { text-decoration-line: none !important; } .gt-no-underline { text-decoration-line: none !important; }
.gt-w-auto { width: auto !important; }
.gt-overflow-x-auto { overflow-x: auto !important; } .gt-overflow-x-auto { overflow-x: auto !important; }
.gt-overflow-x-scroll { overflow-x: scroll !important; } .gt-overflow-x-scroll { overflow-x: scroll !important; }

View File

@ -34,10 +34,6 @@
justify-content: center; justify-content: center;
} }
#navbar .dropdown .item {
justify-content: stretch;
}
#navbar a.item:hover, #navbar a.item:hover,
#navbar button.item:hover { #navbar button.item:hover {
background: var(--color-nav-hover-bg); background: var(--color-nav-hover-bg);
@ -89,19 +85,19 @@
#navbar.navbar-menu-open .item { #navbar.navbar-menu-open .item {
display: flex; display: flex;
width: 100%; width: 100%;
margin: 0;
} }
#navbar.navbar-menu-open .navbar-left #navbar-logo { #navbar.navbar-menu-open .navbar-left #navbar-logo {
justify-content: flex-start; justify-content: flex-start;
width: auto; width: 50%;
min-height: 48px;
} }
#navbar.navbar-menu-open .navbar-left .navbar-mobile-right { #navbar.navbar-menu-open .navbar-left .navbar-mobile-right {
justify-content: flex-end; justify-content: flex-end;
width: 50%; width: 50%;
min-height: 48px; min-height: 48px;
} }
#navbar #mobile-notifications-icon { #navbar.navbar-menu-open .mobile-right-item {
margin-right: 6px !important; width: auto !important;
} }
} }

View File

@ -10,7 +10,7 @@
/> />
<a <a
v-if="item.isFile" v-if="item.isFile"
:class="['file gt-ellipsis', {'viewed': item.file.IsViewed}]" class="file gt-ellipsis"
:href="item.isFile ? '#diff-' + item.file.NameHash : ''" :href="item.isFile ? '#diff-' + item.file.NameHash : ''"
>{{ item.name }}</a> >{{ item.name }}</a>
<SvgIcon <SvgIcon
@ -148,8 +148,4 @@ a:hover {
text-decoration: none; text-decoration: none;
color: var(--color-text); color: var(--color-text);
} }
a.file.viewed {
color: var(--color-text-light-3);
}
</style> </style>

View File

@ -395,6 +395,8 @@ function initGlobalShowModal() {
if (colorPickers.length > 0) { if (colorPickers.length > 0) {
initCompColorPicker(); // FIXME: this might cause duplicate init initCompColorPicker(); // FIXME: this might cause duplicate init
} }
// all non-"ok" buttons which do not have "type" should not submit the form, should not be triggered by "Enter"
$modal.find('form button:not(.ok):not([type])').attr('type', 'button');
$modal.modal('setting', { $modal.modal('setting', {
onApprove: () => { onApprove: () => {
// "form-fetch-action" can handle network errors gracefully, // "form-fetch-action" can handle network errors gracefully,

View File

@ -1,4 +1,3 @@
import {diffTreeStore} from '../modules/stores.js';
import {setFileFolding} from './file-fold.js'; import {setFileFolding} from './file-fold.js';
const {csrfToken, pageData} = window.config; const {csrfToken, pageData} = window.config;
@ -54,17 +53,9 @@ export function initViewedCheckboxListenerFor() {
const hasChangedLabel = form.parentNode.querySelector('.changed-since-last-review'); const hasChangedLabel = form.parentNode.querySelector('.changed-since-last-review');
hasChangedLabel?.remove(); hasChangedLabel?.remove();
const fileName = checkbox.getAttribute('name');
// check if the file is in our difftreestore and if we find it -> change the IsViewed status
const fileInPageData = diffTreeStore().files.find((x) => x.Name === fileName);
if (fileInPageData) {
fileInPageData.IsViewed = this.checked;
}
// Unfortunately, actual forms cause too many problems, hence another approach is needed // Unfortunately, actual forms cause too many problems, hence another approach is needed
const files = {}; const files = {};
files[fileName] = this.checked; files[checkbox.getAttribute('name')] = this.checked;
const data = {files}; const data = {files};
const headCommitSHA = form.getAttribute('data-headcommit'); const headCommitSHA = form.getAttribute('data-headcommit');
if (headCommitSHA) data.headCommitSHA = headCommitSHA; if (headCommitSHA) data.headCommitSHA = headCommitSHA;