diff --git a/app/actions/tenant.go b/app/actions/tenant.go
index 26bce8efc..7de4f239f 100644
--- a/app/actions/tenant.go
+++ b/app/actions/tenant.go
@@ -190,13 +190,14 @@ func (action *ResendSignUpEmail) GetKind() enum.EmailVerificationKind {
// UpdateTenantSettings is the input model used to update tenant settings
type UpdateTenantSettings struct {
- Logo *dto.ImageUpload `json:"logo"`
- Title string `json:"title"`
- Invitation string `json:"invitation"`
- WelcomeMessage string `json:"welcomeMessage"`
- WelcomeHeader string `json:"welcomeHeader"`
- Locale string `json:"locale"`
- CNAME string `json:"cname" format:"lower"`
+ Logo *dto.ImageUpload `json:"logo"`
+ Title string `json:"title"`
+ Invitation string `json:"invitation"`
+ WelcomeMessage string `json:"welcomeMessage"`
+ WelcomeHeader string `json:"welcomeHeader"`
+ Locale string `json:"locale"`
+ CNAME string `json:"cname" format:"lower"`
+ DefaultSort string `json:"defaultSort"`
}
func NewUpdateTenantSettings() *UpdateTenantSettings {
@@ -256,6 +257,18 @@ func (action *UpdateTenantSettings) Validate(ctx context.Context, user *entity.U
result.AddFieldFailure("cname", messages...)
}
+ validSorts := []string{"trending", "most-wanted", "most-discussed", "recent"}
+ sortValid := false
+ for _, s := range validSorts {
+ if action.DefaultSort == s {
+ sortValid = true
+ break
+ }
+ }
+ if !sortValid {
+ action.DefaultSort = "trending"
+ }
+
return result
}
diff --git a/app/handlers/admin.go b/app/handlers/admin.go
index e21d3724a..9bd600552 100644
--- a/app/handlers/admin.go
+++ b/app/handlers/admin.go
@@ -66,6 +66,7 @@ func UpdateSettings() web.HandlerFunc {
WelcomeHeader: action.WelcomeHeader,
CNAME: action.CNAME,
Locale: action.Locale,
+ DefaultSort: action.DefaultSort,
},
); err != nil {
return c.Failure(err)
diff --git a/app/handlers/post.go b/app/handlers/post.go
index 5d2f837c5..24f5224d3 100644
--- a/app/handlers/post.go
+++ b/app/handlers/post.go
@@ -17,9 +17,14 @@ func Index() web.HandlerFunc {
return func(c *web.Context) error {
c.SetCanonicalURL("")
+ view := c.QueryParam("view")
+ if view == "" {
+ view = c.Tenant().DefaultSort
+ }
+
searchPosts := &query.SearchPosts{
Query: c.QueryParam("query"),
- View: c.QueryParam("view"),
+ View: view,
Limit: c.QueryParam("limit"),
Tags: c.QueryParamAsArray("tags"),
}
@@ -77,6 +82,7 @@ func Index() web.HandlerFunc {
return c.Page(http.StatusOK, web.Props{
Page: "Home/Home.page",
+ Title: "Feedback",
Description: description,
// Header: c.Tenant().WelcomeHeader,
Data: data,
diff --git a/app/models/cmd/tenant.go b/app/models/cmd/tenant.go
index 7877377b7..751ca861b 100644
--- a/app/models/cmd/tenant.go
+++ b/app/models/cmd/tenant.go
@@ -27,13 +27,14 @@ type UpdateTenantEmailAuthAllowedSettings struct {
}
type UpdateTenantSettings struct {
- Logo *dto.ImageUpload
- Title string
- Invitation string
- WelcomeMessage string
- WelcomeHeader string
- CNAME string
- Locale string
+ Logo *dto.ImageUpload
+ Title string
+ Invitation string
+ WelcomeMessage string
+ WelcomeHeader string
+ CNAME string
+ Locale string
+ DefaultSort string
}
type UpdateTenantAdvancedSettings struct {
diff --git a/app/models/entity/tenant.go b/app/models/entity/tenant.go
index 064714600..590819f53 100644
--- a/app/models/entity/tenant.go
+++ b/app/models/entity/tenant.go
@@ -6,24 +6,25 @@ import (
// Tenant represents a tenant
type Tenant struct {
- ID int `json:"id"`
- Name string `json:"name"`
- Subdomain string `json:"subdomain"`
- Invitation string `json:"invitation"`
- WelcomeMessage string `json:"welcomeMessage"`
- WelcomeHeader string `json:"welcomeHeader"`
- CNAME string `json:"cname"`
- Status enum.TenantStatus `json:"status"`
- Locale string `json:"locale"`
- IsPrivate bool `json:"isPrivate"`
- LogoBlobKey string `json:"logoBlobKey"`
- CustomCSS string `json:"-"`
- AllowedSchemes string `json:"allowedSchemes"`
- IsEmailAuthAllowed bool `json:"isEmailAuthAllowed"`
- IsFeedEnabled bool `json:"isFeedEnabled"`
- PreventIndexing bool `json:"preventIndexing"`
- IsModerationEnabled bool `json:"isModerationEnabled"`
- HasCommercialFeatures bool `json:"hasCommercialFeatures"`
+ ID int `json:"id"`
+ Name string `json:"name"`
+ Subdomain string `json:"subdomain"`
+ Invitation string `json:"invitation"`
+ WelcomeMessage string `json:"welcomeMessage"`
+ WelcomeHeader string `json:"welcomeHeader"`
+ CNAME string `json:"cname"`
+ Status enum.TenantStatus `json:"status"`
+ Locale string `json:"locale"`
+ IsPrivate bool `json:"isPrivate"`
+ LogoBlobKey string `json:"logoBlobKey"`
+ CustomCSS string `json:"-"`
+ AllowedSchemes string `json:"allowedSchemes"`
+ IsEmailAuthAllowed bool `json:"isEmailAuthAllowed"`
+ IsFeedEnabled bool `json:"isFeedEnabled"`
+ PreventIndexing bool `json:"preventIndexing"`
+ IsModerationEnabled bool `json:"isModerationEnabled"`
+ HasCommercialFeatures bool `json:"hasCommercialFeatures"`
+ DefaultSort string `json:"defaultSort"`
}
func (t *Tenant) IsDisabled() bool {
diff --git a/app/pkg/web/testdata/home_ssr.html b/app/pkg/web/testdata/home_ssr.html
index 7d072bc97..05252b729 100755
--- a/app/pkg/web/testdata/home_ssr.html
+++ b/app/pkg/web/testdata/home_ssr.html
@@ -45,7 +45,7 @@
Please enable JavaScript
diff --git a/app/pkg/web/testdata/tenant.html b/app/pkg/web/testdata/tenant.html
index d8862b06a..a651b5bee 100755
--- a/app/pkg/web/testdata/tenant.html
+++ b/app/pkg/web/testdata/tenant.html
@@ -45,7 +45,7 @@ Please enable JavaScript
diff --git a/app/services/sqlstore/dbEntities/tenant.go b/app/services/sqlstore/dbEntities/tenant.go
index dad5671d7..a377de2ca 100644
--- a/app/services/sqlstore/dbEntities/tenant.go
+++ b/app/services/sqlstore/dbEntities/tenant.go
@@ -27,6 +27,7 @@ type Tenant struct {
IsModerationEnabled bool `db:"is_moderation_enabled"`
IsPro bool `db:"is_pro"`
HasPaddleSubscription bool `db:"has_paddle_subscription"`
+ DefaultSort string `db:"default_sort"`
}
func (t *Tenant) ToModel() *entity.Tenant {
@@ -63,6 +64,7 @@ func (t *Tenant) ToModel() *entity.Tenant {
PreventIndexing: t.PreventIndexing,
IsModerationEnabled: t.IsModerationEnabled,
HasCommercialFeatures: hasCommercialFeatures,
+ DefaultSort: t.DefaultSort,
}
return tenant
diff --git a/app/services/sqlstore/postgres/tenant.go b/app/services/sqlstore/postgres/tenant.go
index bf46acdd5..4c302ec39 100644
--- a/app/services/sqlstore/postgres/tenant.go
+++ b/app/services/sqlstore/postgres/tenant.go
@@ -80,8 +80,8 @@ func updateTenantSettings(ctx context.Context, c *cmd.UpdateTenantSettings) erro
c.Logo.BlobKey = ""
}
- query := "UPDATE tenants SET name = $1, invitation = $2, welcome_message = $3, welcome_header = $4, cname = $5, logo_bkey = $6, locale = $7 WHERE id = $8"
- _, err := trx.Execute(query, c.Title, c.Invitation, c.WelcomeMessage, c.WelcomeHeader, c.CNAME, c.Logo.BlobKey, c.Locale, tenant.ID)
+ query := "UPDATE tenants SET name = $1, invitation = $2, welcome_message = $3, welcome_header = $4, cname = $5, logo_bkey = $6, locale = $7, default_sort = $8 WHERE id = $9"
+ _, err := trx.Execute(query, c.Title, c.Invitation, c.WelcomeMessage, c.WelcomeHeader, c.CNAME, c.Logo.BlobKey, c.Locale, c.DefaultSort, tenant.ID)
if err != nil {
return errors.Wrap(err, "failed update tenant settings")
}
@@ -91,6 +91,7 @@ func updateTenantSettings(ctx context.Context, c *cmd.UpdateTenantSettings) erro
tenant.CNAME = c.CNAME
tenant.WelcomeMessage = c.WelcomeMessage
tenant.WelcomeHeader = c.WelcomeHeader
+ tenant.DefaultSort = c.DefaultSort
return nil
})
@@ -194,8 +195,8 @@ func createTenant(ctx context.Context, c *cmd.CreateTenant) error {
var id int
err := trx.Get(&id,
- `INSERT INTO tenants (name, subdomain, created_at, cname, invitation, welcome_message, status, is_private, custom_css, logo_bkey, locale, is_email_auth_allowed, is_feed_enabled, prevent_indexing, is_moderation_enabled)
- VALUES ($1, $2, $3, '', '', '', $4, false, '', '', $5, true, true, true, false)
+ `INSERT INTO tenants (name, subdomain, created_at, cname, invitation, welcome_message, status, is_private, custom_css, logo_bkey, locale, is_email_auth_allowed, is_feed_enabled, prevent_indexing, is_moderation_enabled, default_sort)
+ VALUES ($1, $2, $3, '', '', '', $4, false, '', '', $5, true, true, true, false, 'trending')
RETURNING id`, c.Name, c.Subdomain, now, c.Status, env.Config.Locale)
if err != nil {
return err
@@ -212,13 +213,13 @@ func getFirstTenant(ctx context.Context, q *query.GetFirstTenant) error {
return using(ctx, func(trx *dbx.Trx, _ *entity.Tenant, _ *entity.User) error {
tenant := dbEntities.Tenant{}
- err := trx.Get(&tenant, `
- SELECT t.id, t.name, t.subdomain, t.cname, t.invitation, t.locale, t.welcome_message, t.welcome_header, t.status, t.is_private, t.logo_bkey, t.custom_css, t.allowed_schemes, t.is_email_auth_allowed, t.is_feed_enabled, t.is_moderation_enabled, t.prevent_indexing, t.is_pro,
- (b.paddle_subscription_id IS NOT NULL AND b.stripe_subscription_id IS NULL) AS has_paddle_subscription
- FROM tenants t
- LEFT JOIN tenants_billing b ON b.tenant_id = t.id
- ORDER BY t.id LIMIT 1
- `)
+ err := trx.Get(&tenant, `
+ SELECT t.id, t.name, t.subdomain, t.cname, t.invitation, t.locale, t.welcome_message, t.welcome_header, t.status, t.is_private, t.logo_bkey, t.custom_css, t.allowed_schemes, t.is_email_auth_allowed, t.is_feed_enabled, t.is_moderation_enabled, t.prevent_indexing, t.is_pro, t.default_sort,
+ (b.paddle_subscription_id IS NOT NULL AND b.stripe_subscription_id IS NULL) AS has_paddle_subscription
+ FROM tenants t
+ LEFT JOIN tenants_billing b ON b.tenant_id = t.id
+ ORDER BY t.id LIMIT 1
+ `)
if err != nil {
return errors.Wrap(err, "failed to get first tenant")
}
@@ -232,14 +233,14 @@ func getTenantByDomain(ctx context.Context, q *query.GetTenantByDomain) error {
return using(ctx, func(trx *dbx.Trx, _ *entity.Tenant, _ *entity.User) error {
tenant := dbEntities.Tenant{}
- err := trx.Get(&tenant, `
- SELECT t.id, t.name, t.subdomain, t.cname, t.invitation, t.locale, t.welcome_message, t.welcome_header, t.status, t.is_private, t.logo_bkey, t.custom_css, t.allowed_schemes, t.is_email_auth_allowed, t.is_feed_enabled, t.is_moderation_enabled, t.prevent_indexing, t.is_pro,
- (b.paddle_subscription_id IS NOT NULL AND b.stripe_subscription_id IS NULL) AS has_paddle_subscription
- FROM tenants t
- LEFT JOIN tenants_billing b ON b.tenant_id = t.id
- WHERE t.subdomain = $1 OR t.subdomain = $2 OR t.cname = $3
- ORDER BY t.cname DESC
- `, env.Subdomain(q.Domain), q.Domain, q.Domain)
+ err := trx.Get(&tenant, `
+ SELECT t.id, t.name, t.subdomain, t.cname, t.invitation, t.locale, t.welcome_message, t.welcome_header, t.status, t.is_private, t.logo_bkey, t.custom_css, t.allowed_schemes, t.is_email_auth_allowed, t.is_feed_enabled, t.is_moderation_enabled, t.prevent_indexing, t.is_pro, t.default_sort,
+ (b.paddle_subscription_id IS NOT NULL AND b.stripe_subscription_id IS NULL) AS has_paddle_subscription
+ FROM tenants t
+ LEFT JOIN tenants_billing b ON b.tenant_id = t.id
+ WHERE t.subdomain = $1 OR t.subdomain = $2 OR t.cname = $3
+ ORDER BY t.cname DESC
+ `, env.Subdomain(q.Domain), q.Domain, q.Domain)
if err != nil {
return errors.Wrap(err, "failed to get tenant with domain '%s'", q.Domain)
}
diff --git a/migrations/202602170001_add_default_sort.sql b/migrations/202602170001_add_default_sort.sql
new file mode 100644
index 000000000..7e4e7f47a
--- /dev/null
+++ b/migrations/202602170001_add_default_sort.sql
@@ -0,0 +1,4 @@
+ALTER TABLE tenants ADD default_sort VARCHAR(50) NULL;
+UPDATE tenants SET default_sort = 'trending';
+ALTER TABLE tenants ALTER COLUMN default_sort SET NOT NULL;
+ALTER TABLE tenants ALTER COLUMN default_sort SET DEFAULT 'trending';
diff --git a/public/models/identity.ts b/public/models/identity.ts
index 582e1895e..eb8b9f98f 100644
--- a/public/models/identity.ts
+++ b/public/models/identity.ts
@@ -15,6 +15,7 @@ export interface Tenant {
isFeedEnabled: boolean
isModerationEnabled: boolean
hasCommercialFeatures: boolean
+ defaultSort: string
}
export enum TenantStatus {
diff --git a/public/pages/Administration/pages/GeneralSettings.page.tsx b/public/pages/Administration/pages/GeneralSettings.page.tsx
index 1a44518fa..c021f82ad 100644
--- a/public/pages/Administration/pages/GeneralSettings.page.tsx
+++ b/public/pages/Administration/pages/GeneralSettings.page.tsx
@@ -16,10 +16,11 @@ const GeneralSettingsPage = () => {
const [logo, setLogo] = useState(undefined)
const [cname, setCNAME] = useState(fider.session.tenant.cname)
const [locale, setLocale] = useState(fider.session.tenant.locale)
+ const [defaultSort, setDefaultSort] = useState(fider.session.tenant.defaultSort)
const [error, setError] = useState(undefined)
const handleSave = async (e: ButtonClickEvent) => {
- const result = await actions.updateTenantSettings({ title, cname, welcomeMessage, welcomeHeader, invitation, logo, locale })
+ const result = await actions.updateTenantSettings({ title, cname, welcomeMessage, welcomeHeader, invitation, logo, locale, defaultSort })
if (result.ok) {
e.preventEnable()
location.href = `/`
@@ -143,6 +144,19 @@ const GeneralSettingsPage = () => {
)}
+