diff --git a/models/db/driver_postgresschema.go b/models/db/driver_postgresschema.go index ad2b5abc04a..616712fb2a0 100644 --- a/models/db/driver_postgresschema.go +++ b/models/db/driver_postgresschema.go @@ -4,8 +4,10 @@ package db import ( + "context" "database/sql" "database/sql/driver" + "errors" "sync" "gitea.dev/modules/setting" @@ -14,61 +16,34 @@ import ( "xorm.io/xorm/dialects" ) -var registerOnce sync.Once +type postgresSchemaDriver struct{} -func registerPostgresSchemaDriver() { - registerOnce.Do(func() { - sql.Register(sqlDriverPostgresSchema, &postgresSchemaDriver{}) - dialects.RegisterDriver(sqlDriverPostgresSchema, dialects.QueryDriver("postgres")) - }) -} +var registerPostgresSchemaDriver = sync.OnceFunc(func() { + sql.Register(sqlDriverPostgresSchema, &postgresSchemaDriver{}) + dialects.RegisterDriver(sqlDriverPostgresSchema, dialects.QueryDriver("postgres")) +}) -type postgresSchemaDriver struct { - pq.Driver -} - -// Open opens a new connection to the database. name is a connection string. -// This function opens the postgres connection in the default manner but immediately -// runs set_config to set the search_path appropriately -func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) { - conn, err := d.Driver.Open(name) +// Open opens the postgres connection in the default manner with default schema support. +// It immediately runs "set_config" to set the search_path appropriately. +func (*postgresSchemaDriver) Open(connStr string) (driver.Conn, error) { + conn, err := pq.Driver{}.Open(connStr) if err != nil { - return conn, err + return nil, err } - schemaValue, _ := driver.String.ConvertValue(setting.Database.Schema) - // golangci lint is incorrect here - there is no benefit to using driver.ExecerContext here - // and in any case pq does not implement it - if execer, ok := conn.(driver.Execer); ok { //nolint:staticcheck // see above - _, err := execer.Exec(`SELECT set_config( + connExec, ok := conn.(driver.ExecerContext) + if !ok { + return nil, errors.New("postgres driver does not implement ExecerContext interface") + } + _, err = connExec.ExecContext(context.Background(), `SELECT set_config( 'search_path', $1 || ',' || current_setting('search_path'), - false)`, []driver.Value{schemaValue}) - if err != nil { - _ = conn.Close() - return nil, err - } - return conn, nil - } - - stmt, err := conn.Prepare(`SELECT set_config( - 'search_path', - $1 || ',' || current_setting('search_path'), - false)`) + false)`, + []driver.NamedValue{{Ordinal: 1, Value: setting.Database.Schema}}, + ) if err != nil { _ = conn.Close() return nil, err } - defer stmt.Close() - - // driver.String.ConvertValue will never return err for string - - // golangci lint is incorrect here - there is no benefit to using stmt.ExecWithContext here - _, err = stmt.Exec([]driver.Value{schemaValue}) //nolint:staticcheck // see above - if err != nil { - _ = conn.Close() - return nil, err - } - return conn, nil } diff --git a/web_src/css/modules/dropdown.css b/web_src/css/modules/dropdown.css index 9d3dc48adae..02957fe31d9 100644 --- a/web_src/css/modules/dropdown.css +++ b/web_src/css/modules/dropdown.css @@ -80,6 +80,10 @@ border-top-width: 0; } +.ui.dropdown .menu .hidden { /* for hidden items and dividers */ + display: none; +} + .ui.dropdown .menu > .header { margin: 1rem 0 0.75rem; padding: 0 1.14285714rem; diff --git a/web_src/fomantic/build/components/dropdown.js b/web_src/fomantic/build/components/dropdown.js index b8f066db748..0faed1858c4 100644 --- a/web_src/fomantic/build/components/dropdown.js +++ b/web_src/fomantic/build/components/dropdown.js @@ -308,12 +308,12 @@ $.fn.dropdown = function(parameters) { firstUnfiltered: function() { module.verbose('Selecting first non-filtered element'); module.remove.selectedItem(); - $item + const $selectable = $item .not(selector.unselectable) - .not(selector.addition + selector.hidden) - .eq(0) - .addClass(className.selected) - ; + .not(selector.addition + selector.hidden); + let $selectedItem = $selectable.filter(`[data-value="${CSS.escape($input.val())}"]`); // GITEA-PATCH: try to re-select the last selected item for single selection + if (!$selectedItem.length) $selectedItem = $item.eq(0); + $selectedItem.addClass(className.selected); }, nextAvailable: function($selected) { $selected = $selected.eq(0); @@ -772,11 +772,13 @@ $.fn.dropdown = function(parameters) { if(!Array.isArray(preSelected)) { preSelected = preSelected && preSelected!=="" ? preSelected.split(settings.delimiter) : []; } - $.each(preSelected,function(index,value){ - $item.filter('[data-value="'+CSS.escape(value)+'"]') // GITEA-PATCH: use "CSS.escape" for query selector + if (module.is.multiple()) { // GITEA-PATCH: only hide selected items when the dropdown is "multiple selection" + $.each(preSelected, function (index, value) { + $item.filter('[data-value="' + CSS.escape(value) + '"]') // GITEA-PATCH: use "CSS.escape" for query selector .addClass(className.filtered) - ; - }); + ; + }); + } afterFiltered(); }); } diff --git a/web_src/js/features/repo-new.ts b/web_src/js/features/repo-new.ts index b690ace0f7f..8b1188f19f1 100644 --- a/web_src/js/features/repo-new.ts +++ b/web_src/js/features/repo-new.ts @@ -47,7 +47,6 @@ function initRepoNewTemplateSearch(form: HTMLFormElement) { value: String(tmplRepo.repository.id), }); } - $repoTemplateDropdown.fomanticExt.onResponseKeepSelectedItem($repoTemplateDropdown, inputRepoTemplate.value); return {results}; }, cache: false, diff --git a/web_src/js/modules/fomantic/dropdown.test.ts b/web_src/js/modules/fomantic/dropdown.test.ts index dd3497c8fce..542cb854b84 100644 --- a/web_src/js/modules/fomantic/dropdown.test.ts +++ b/web_src/js/modules/fomantic/dropdown.test.ts @@ -13,13 +13,13 @@ test('hideScopedEmptyDividers-simple', () => { `); hideScopedEmptyDividers(container); expect(container.innerHTML).toEqual(` -
+