Moments: Change default sort order in the overview to "newest" #3280
Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
parent
0d49ed43f2
commit
cc97759806
15 changed files with 121 additions and 82 deletions
|
@ -160,7 +160,7 @@ export default [
|
|||
path: "/moments",
|
||||
component: Albums,
|
||||
meta: { title: $gettext("Moments"), auth: true },
|
||||
props: { view: "moment", defaultOrder: "moment", staticFilter: { type: "moment" } },
|
||||
props: { view: "moment", defaultOrder: "newest", staticFilter: { type: "moment" } },
|
||||
},
|
||||
{
|
||||
name: "moment",
|
||||
|
|
|
@ -173,11 +173,6 @@ export default {
|
|||
this.searchExpanded = !this.searchExpanded;
|
||||
this.growDesc = !this.growDesc;
|
||||
},
|
||||
updateAlbum() {
|
||||
if (this.album.wasChanged()) {
|
||||
this.album.update();
|
||||
}
|
||||
},
|
||||
setView(name) {
|
||||
if (name) {
|
||||
this.refresh({'view': name});
|
||||
|
|
|
@ -821,11 +821,6 @@ export default {
|
|||
this.isMini = this.isRestricted;
|
||||
}
|
||||
},
|
||||
createAlbum() {
|
||||
let name = "New Album";
|
||||
const album = new Album({Title: name, Favorite: false});
|
||||
album.save();
|
||||
},
|
||||
toggleIsMini() {
|
||||
this.isMini = !this.isMini;
|
||||
localStorage.setItem('last_navigation_mode', `${this.isMini}`);
|
||||
|
|
|
@ -176,6 +176,7 @@ export default {
|
|||
}
|
||||
|
||||
this.model.update().then((m) => {
|
||||
this.$notify.success(this.$gettext("Changes successfully saved"));
|
||||
this.categories = this.$config.albumCategories();
|
||||
this.$emit('close');
|
||||
});
|
||||
|
|
|
@ -217,7 +217,11 @@ export default {
|
|||
|
||||
this.loading = true;
|
||||
|
||||
this.model.updateLink(link).finally(() => this.loading = false);
|
||||
this.model.updateLink(link).then(() => {
|
||||
this.$notify.success(this.$gettext("Changes successfully saved"));
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
remove(index) {
|
||||
const link = this.links[index];
|
||||
|
@ -230,6 +234,7 @@ export default {
|
|||
this.loading = true;
|
||||
|
||||
this.model.removeLink(link).then(() => {
|
||||
this.$notify.success(this.$gettext("Changes successfully saved"));
|
||||
this.links.splice(index, 1);
|
||||
}).finally(() => this.loading = false);
|
||||
},
|
||||
|
|
|
@ -343,7 +343,6 @@ export default {
|
|||
{value: 'favorites', text: this.$gettext('Favorites')},
|
||||
{value: 'name', text: this.$gettext('Name')},
|
||||
{value: 'place', text: this.$gettext('Location')},
|
||||
{value: 'moment', text: this.$gettext('Place & Time')},
|
||||
{value: 'newest', text: this.$gettext('Newest First')},
|
||||
{value: 'oldest', text: this.$gettext('Oldest First')},
|
||||
{value: 'added', text: this.$gettext('Recently Added')},
|
||||
|
@ -777,19 +776,32 @@ export default {
|
|||
this.loadMore();
|
||||
},
|
||||
create() {
|
||||
// Use month and year as default title.
|
||||
let title = DateTime.local().toFormat("LLLL yyyy");
|
||||
|
||||
// Add suffix if the album title already exists.
|
||||
if (this.results.findIndex(a => a.Title.startsWith(title)) !== -1) {
|
||||
const existing = this.results.filter(a => a.Title.startsWith(title));
|
||||
title = `${title} (${existing.length + 1})`;
|
||||
const re = new RegExp(`${title} \\((\\d?)\\)`, 'i');
|
||||
let i = 1;
|
||||
this.results.forEach(a => {
|
||||
const found = a.Title.match(re);
|
||||
if (found[1]) {
|
||||
const n = parseInt(found[1]);
|
||||
if (n > i) {
|
||||
i = n;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
title = `${title} (${i + 1})`;
|
||||
}
|
||||
|
||||
const album = new Album({"Title": title, "Favorite": false});
|
||||
|
||||
album.save();
|
||||
album.save().then(() => this.$notify.success(this.$gettext("Album created")));
|
||||
},
|
||||
onSave(album) {
|
||||
album.update();
|
||||
album.update().then(() => this.$notify.success(this.$gettext("Changes successfully saved")));
|
||||
},
|
||||
addSelection(uid) {
|
||||
const pos = this.selection.indexOf(uid);
|
||||
|
|
|
@ -94,18 +94,13 @@ func CreateAlbum(router *gin.RouterGroup) {
|
|||
AbortUnexpected(c)
|
||||
return
|
||||
}
|
||||
|
||||
event.SuccessMsg(i18n.MsgAlbumCreated)
|
||||
} else {
|
||||
// Exists, restore if necessary.
|
||||
a = found
|
||||
if !a.Deleted() {
|
||||
event.InfoMsg(i18n.ErrAlreadyExists, a.Title())
|
||||
c.JSON(http.StatusOK, a)
|
||||
return
|
||||
} else if err := a.Restore(); err == nil {
|
||||
event.SuccessMsg(i18n.MsgRestored, a.Title())
|
||||
} else {
|
||||
} else if err := a.Restore(); err != nil {
|
||||
// Report unexpected error.
|
||||
log.Errorf("album: %s (restore)", err)
|
||||
AbortUnexpected(c)
|
||||
|
@ -167,8 +162,6 @@ func UpdateAlbum(router *gin.RouterGroup) {
|
|||
|
||||
UpdateClientConfig()
|
||||
|
||||
event.SuccessMsg(i18n.MsgAlbumSaved)
|
||||
|
||||
// PublishAlbumEvent(EntityUpdated, uid, c)
|
||||
|
||||
SaveAlbumAsYaml(a)
|
||||
|
@ -221,8 +214,6 @@ func DeleteAlbum(router *gin.RouterGroup) {
|
|||
|
||||
SaveAlbumAsYaml(a)
|
||||
|
||||
event.SuccessMsg(i18n.MsgAlbumDeleted, clean.Log(a.AlbumTitle))
|
||||
|
||||
c.JSON(http.StatusOK, a)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -8,9 +8,7 @@ import (
|
|||
|
||||
"github.com/photoprism/photoprism/internal/acl"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/event"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
"github.com/photoprism/photoprism/internal/i18n"
|
||||
"github.com/photoprism/photoprism/internal/query"
|
||||
"github.com/photoprism/photoprism/pkg/clean"
|
||||
"github.com/photoprism/photoprism/pkg/txt"
|
||||
|
@ -59,8 +57,6 @@ func UpdateLink(c *gin.Context) {
|
|||
|
||||
UpdateClientConfig()
|
||||
|
||||
event.SuccessMsg(i18n.MsgAlbumSaved)
|
||||
|
||||
PublishAlbumEvent(EntityUpdated, link.ShareUID, c)
|
||||
|
||||
c.JSON(http.StatusOK, link)
|
||||
|
@ -86,8 +82,6 @@ func DeleteLink(c *gin.Context) {
|
|||
|
||||
UpdateClientConfig()
|
||||
|
||||
event.SuccessMsg(i18n.MsgAlbumSaved)
|
||||
|
||||
PublishAlbumEvent(EntityUpdated, link.ShareUID, c)
|
||||
|
||||
c.JSON(http.StatusOK, link)
|
||||
|
@ -138,8 +132,6 @@ func CreateLink(c *gin.Context) {
|
|||
|
||||
UpdateClientConfig()
|
||||
|
||||
event.SuccessMsg(i18n.MsgAlbumSaved)
|
||||
|
||||
PublishAlbumEvent(EntityUpdated, link.ShareUID, c)
|
||||
|
||||
c.JSON(http.StatusOK, link)
|
||||
|
|
|
@ -423,7 +423,7 @@ func (m *Album) IsDefault() bool {
|
|||
}
|
||||
|
||||
// SetTitle changes the album name.
|
||||
func (m *Album) SetTitle(title string) {
|
||||
func (m *Album) SetTitle(title string) *Album {
|
||||
title = strings.Trim(title, "_&|{}<>: \n\r\t\\")
|
||||
title = strings.ReplaceAll(title, "\"", "“")
|
||||
title = txt.Shorten(title, txt.ClipDefault, txt.Ellipsis)
|
||||
|
@ -445,10 +445,26 @@ func (m *Album) SetTitle(title string) {
|
|||
if m.AlbumSlug == "" {
|
||||
m.AlbumSlug = "-"
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// UpdateSlug updates title and slug of generated albums if needed.
|
||||
func (m *Album) UpdateSlug(title, slug string) error {
|
||||
// SetLocation sets a new album location.
|
||||
func (m *Album) SetLocation(location, state, country string) *Album {
|
||||
if location != "" {
|
||||
m.AlbumLocation = txt.Shorten(location, txt.ClipDefault, txt.Ellipsis)
|
||||
}
|
||||
|
||||
if state != "" || country != "" && country != "zz" {
|
||||
m.AlbumCountry = txt.Clip(country, txt.ClipCountry)
|
||||
m.AlbumState = txt.Clip(clean.State(state, country), txt.ClipCategory)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// UpdateTitleAndLocation updates title, location, and slug of generated albums if needed.
|
||||
func (m *Album) UpdateTitleAndLocation(title, location, state, country, slug string) error {
|
||||
title = txt.Clip(title, txt.ClipDefault)
|
||||
slug = txt.Clip(slug, txt.ClipSlug)
|
||||
|
||||
|
@ -463,7 +479,7 @@ func (m *Album) UpdateSlug(title, slug string) error {
|
|||
changed = true
|
||||
}
|
||||
|
||||
if !changed {
|
||||
if !changed && state == m.AlbumState && country == m.AlbumCountry {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -471,11 +487,27 @@ func (m *Album) UpdateSlug(title, slug string) error {
|
|||
m.SetTitle(title)
|
||||
}
|
||||
|
||||
return m.Updates(Values{"album_title": m.AlbumTitle, "album_slug": m.AlbumSlug})
|
||||
// Skip location?
|
||||
if location == "" && state == "" && (country == "" || country == "zz") {
|
||||
return m.Updates(Values{
|
||||
"album_title": m.AlbumTitle,
|
||||
"album_slug": m.AlbumSlug,
|
||||
})
|
||||
}
|
||||
|
||||
m.SetLocation(location, state, country)
|
||||
|
||||
return m.Updates(Values{
|
||||
"album_title": m.AlbumTitle,
|
||||
"album_location": m.AlbumLocation,
|
||||
"album_state": m.AlbumState,
|
||||
"album_country": m.AlbumCountry,
|
||||
"album_slug": m.AlbumSlug,
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateState updates the album location.
|
||||
func (m *Album) UpdateState(title, slug, stateName, countryCode string) error {
|
||||
// UpdateTitleAndState updates the album location.
|
||||
func (m *Album) UpdateTitleAndState(title, slug, stateName, countryCode string) error {
|
||||
title = txt.Clip(title, txt.ClipDefault)
|
||||
slug = txt.Clip(slug, txt.ClipSlug)
|
||||
|
||||
|
@ -536,7 +568,6 @@ func (m *Album) SaveForm(f form.Album) error {
|
|||
|
||||
// Update sets a new value for a database column.
|
||||
func (m *Album) Update(attr string, value interface{}) error {
|
||||
|
||||
return UnscopedDb().Model(m).Update(attr, value).Error
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ func TestAlbum_UpdateSlug(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := album.UpdateSlug("November / 2002", "november-2002"); err != nil {
|
||||
if err := album.UpdateTitleAndLocation("November / 2002", "", "", "", "november-2002"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ func TestAlbum_UpdateState(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := album.UpdateState("Alberta", "canada-alberta", "Alberta", "ca"); err != nil {
|
||||
if err := album.UpdateTitleAndState("Alberta", "canada-alberta", "Alberta", "ca"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ func (w *Moments) Start() (err error) {
|
|||
} else {
|
||||
for _, mom := range results {
|
||||
if a := entity.FindMonthAlbum(mom.Year, mom.Month); a != nil {
|
||||
if err := a.UpdateSlug(mom.Title(), mom.Slug()); err != nil {
|
||||
if err := a.UpdateTitleAndLocation(mom.Title(), "", "", "", mom.Slug()); err != nil {
|
||||
log.Errorf("moments: %s (update slug)", err.Error())
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ func (w *Moments) Start() (err error) {
|
|||
}
|
||||
|
||||
if a := entity.FindAlbumByAttr(S{mom.Slug(), mom.TitleSlug()}, S{f.Serialize()}, entity.AlbumMoment); a != nil {
|
||||
if err := a.UpdateSlug(mom.Title(), mom.Slug()); err != nil {
|
||||
if err := a.UpdateTitleAndLocation(mom.Title(), "", mom.State, mom.Country, mom.Slug()); err != nil {
|
||||
log.Errorf("moments: %s (update slug)", err.Error())
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ func (w *Moments) Start() (err error) {
|
|||
}
|
||||
} else if a := entity.NewMomentsAlbum(mom.Title(), mom.Slug(), f.Serialize()); a != nil {
|
||||
a.AlbumYear = mom.Year
|
||||
a.AlbumCountry = mom.Country
|
||||
a.SetLocation("", mom.State, mom.Country)
|
||||
|
||||
if err := a.Create(); err != nil {
|
||||
log.Errorf("moments: %s", err)
|
||||
|
@ -193,7 +193,7 @@ func (w *Moments) Start() (err error) {
|
|||
}
|
||||
|
||||
if a := entity.FindAlbumByAttr(S{mom.Slug(), mom.TitleSlug()}, S{f.Serialize()}, entity.AlbumState); a != nil {
|
||||
if err := a.UpdateState(mom.Title(), mom.Slug(), mom.State, mom.Country); err != nil {
|
||||
if err := a.UpdateTitleAndState(mom.Title(), mom.Slug(), mom.State, mom.Country); err != nil {
|
||||
log.Errorf("moments: %s (update state)", err.Error())
|
||||
}
|
||||
|
||||
|
@ -205,9 +205,7 @@ func (w *Moments) Start() (err error) {
|
|||
log.Infof("moments: %s restored", clean.Log(a.AlbumTitle))
|
||||
}
|
||||
} else if a := entity.NewStateAlbum(mom.Title(), mom.Slug(), f.Serialize()); a != nil {
|
||||
a.AlbumLocation = mom.CountryName()
|
||||
a.AlbumCountry = mom.Country
|
||||
a.AlbumState = mom.State
|
||||
a.SetLocation(mom.CountryName(), mom.State, mom.Country)
|
||||
|
||||
if err := a.Create(); err != nil {
|
||||
log.Errorf("moments: %s", err)
|
||||
|
@ -231,7 +229,7 @@ func (w *Moments) Start() (err error) {
|
|||
}
|
||||
|
||||
if a := entity.FindAlbumByAttr(S{mom.Slug(), mom.TitleSlug()}, S{f.Serialize()}, entity.AlbumMoment); a != nil {
|
||||
if err := a.UpdateSlug(mom.Title(), mom.Slug()); err != nil {
|
||||
if err := a.UpdateTitleAndLocation(mom.Title(), "", "", "", mom.Slug()); err != nil {
|
||||
log.Errorf("moments: %s (update slug)", err.Error())
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ import (
|
|||
// Moment contains photo counts per month and year
|
||||
type Moment struct {
|
||||
Label string `json:"Label"`
|
||||
Country string `json:"Country"`
|
||||
State string `json:"State"`
|
||||
Year int `json:"Year"`
|
||||
Month int `json:"Month"`
|
||||
State string `json:"State"`
|
||||
Country string `json:"Country"`
|
||||
PhotoCount int `json:"PhotoCount"`
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,15 @@ func (m Moment) CountryName() string {
|
|||
return maps.CountryName(m.Country)
|
||||
}
|
||||
|
||||
// Location returns the location name for the moment.
|
||||
func (m Moment) Location() string {
|
||||
if state := clean.State(m.State, m.Country); state != "" {
|
||||
return fmt.Sprintf("%s, %s", state, m.CountryName())
|
||||
}
|
||||
|
||||
return m.CountryName()
|
||||
}
|
||||
|
||||
// Slug returns an identifier string for a moment.
|
||||
func (m Moment) Slug() (s string) {
|
||||
state := clean.State(m.State, m.Country)
|
||||
|
@ -201,7 +210,7 @@ func MomentsTime(threshold int, public bool) (results Moments, err error) {
|
|||
// MomentsCountries returns the most popular countries by year.
|
||||
func MomentsCountries(threshold int, public bool) (results Moments, err error) {
|
||||
db := UnscopedDb().Table("photos").
|
||||
Select("photo_country AS country, photo_year AS year, COUNT(*) AS photo_count ").
|
||||
Select("photo_year AS year, photo_country AS country, COUNT(*) AS photo_count").
|
||||
Where("photos.photo_quality >= 3 AND deleted_at IS NULL AND photo_country <> 'zz' AND photo_year > 0")
|
||||
|
||||
// Ignore private pictures?
|
||||
|
@ -209,7 +218,7 @@ func MomentsCountries(threshold int, public bool) (results Moments, err error) {
|
|||
db = db.Where("photo_private = 0")
|
||||
}
|
||||
|
||||
db = db.Group("photo_country, photo_year").
|
||||
db = db.Group("photo_year, photo_country").
|
||||
Having("photo_count >= ?", threshold)
|
||||
|
||||
if err := db.Scan(&results).Error; err != nil {
|
||||
|
|
|
@ -31,7 +31,7 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||
|
||||
// Base query.
|
||||
s := UnscopedDb().Table("albums").
|
||||
Select("albums.*, cp.photo_count, cl.link_count, CASE WHEN albums.album_year = 0 THEN 0 ELSE 1 END AS has_year").
|
||||
Select("albums.*, cp.photo_count, cl.link_count, CASE WHEN albums.album_year = 0 THEN 0 ELSE 1 END AS has_year, CASE WHEN albums.album_location = '' THEN 1 ELSE 0 END AS no_location").
|
||||
Joins("LEFT JOIN (SELECT album_uid, count(photo_uid) AS photo_count FROM photos_albums WHERE hidden = 0 AND missing = 0 GROUP BY album_uid) AS cp ON cp.album_uid = albums.album_uid").
|
||||
Joins("LEFT JOIN (SELECT share_uid, count(share_uid) AS link_count FROM links GROUP BY share_uid) AS cl ON cl.share_uid = albums.album_uid").
|
||||
Where("albums.deleted_at IS NULL")
|
||||
|
@ -84,15 +84,19 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||
switch f.Order {
|
||||
case sortby.Count:
|
||||
s = s.Order("photo_count DESC, albums.album_title, albums.album_uid DESC")
|
||||
case sortby.Newest:
|
||||
case sortby.Moment, sortby.Newest:
|
||||
if f.Type == entity.AlbumDefault || f.Type == entity.AlbumState {
|
||||
s = s.Order("albums.album_uid DESC")
|
||||
} else if f.Type == entity.AlbumMoment {
|
||||
s = s.Order("has_year, albums.album_year DESC, albums.album_month DESC, albums.album_day DESC, albums.album_title, albums.album_uid DESC")
|
||||
} else {
|
||||
s = s.Order("albums.album_year DESC, albums.album_month DESC, albums.album_day DESC, albums.album_title, albums.album_uid DESC")
|
||||
}
|
||||
case sortby.Oldest:
|
||||
if f.Type == entity.AlbumDefault || f.Type == entity.AlbumState {
|
||||
s = s.Order("albums.album_uid ASC")
|
||||
} else if f.Type == entity.AlbumMoment {
|
||||
s = s.Order("has_year, albums.album_year ASC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid ASC")
|
||||
} else {
|
||||
s = s.Order("albums.album_year ASC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid ASC")
|
||||
}
|
||||
|
@ -100,10 +104,8 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||
s = s.Order("albums.album_uid DESC")
|
||||
case sortby.Edited:
|
||||
s = s.Order("albums.updated_at DESC, albums.album_uid DESC")
|
||||
case sortby.Moment:
|
||||
s = s.Order("albums.album_favorite DESC, has_year, albums.album_year DESC, albums.album_month DESC, albums.album_title ASC, albums.album_uid DESC")
|
||||
case sortby.Place:
|
||||
s = s.Order("albums.album_location, albums.album_title, albums.album_year DESC, albums.album_month ASC, albums.album_day ASC, albums.album_uid DESC")
|
||||
s = s.Order("no_location, albums.album_location, has_year, albums.album_year DESC, albums.album_month ASC, albums.album_day ASC, albums.album_title, albums.album_uid DESC")
|
||||
case sortby.Path:
|
||||
s = s.Order("albums.album_path, albums.album_uid DESC")
|
||||
case sortby.Category:
|
||||
|
@ -124,6 +126,12 @@ func UserAlbums(f form.SearchAlbums, sess *entity.Session) (results AlbumResults
|
|||
} else {
|
||||
s = s.Order("albums.album_title ASC, albums.album_uid DESC")
|
||||
}
|
||||
case sortby.NameReverse:
|
||||
if f.Type == entity.AlbumFolder {
|
||||
s = s.Order("albums.album_path DESC, albums.album_uid DESC")
|
||||
} else {
|
||||
s = s.Order("albums.album_title DESC, albums.album_uid DESC")
|
||||
}
|
||||
default:
|
||||
s = s.Order("albums.album_favorite DESC, albums.album_title ASC, albums.album_uid DESC")
|
||||
}
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
package sortby
|
||||
|
||||
const (
|
||||
Default = ""
|
||||
Relevance = "relevance"
|
||||
Duration = "duration"
|
||||
Size = "size"
|
||||
Count = "count"
|
||||
Added = "added"
|
||||
Imported = "imported"
|
||||
Edited = "edited"
|
||||
Newest = "newest"
|
||||
Oldest = "oldest"
|
||||
Place = "place"
|
||||
Moment = "moment"
|
||||
Favorites = "favorites"
|
||||
Name = "name"
|
||||
Path = "path"
|
||||
Slug = "slug"
|
||||
Category = "category"
|
||||
Similar = "similar"
|
||||
Random = "random"
|
||||
Invalid = "invalid"
|
||||
Default = ""
|
||||
Relevance = "relevance"
|
||||
Duration = "duration"
|
||||
Size = "size"
|
||||
Count = "count"
|
||||
Added = "added"
|
||||
Imported = "imported"
|
||||
Edited = "edited"
|
||||
Newest = "newest"
|
||||
Oldest = "oldest"
|
||||
Place = "place"
|
||||
Moment = "moment"
|
||||
Favorites = "favorites"
|
||||
Name = "name"
|
||||
NameReverse = "name_reverse"
|
||||
Path = "path"
|
||||
Slug = "slug"
|
||||
Category = "category"
|
||||
Similar = "similar"
|
||||
Random = "random"
|
||||
Invalid = "invalid"
|
||||
)
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
const (
|
||||
Ellipsis = "…"
|
||||
ClipCountry = 2
|
||||
ClipRole = 32
|
||||
ClipKeyword = 40
|
||||
ClipIP = 48
|
||||
|
|
Loading…
Reference in a new issue