Subject: [PATCH links] Adding filtering by domain to short links and link listings.

From: Peter Sanchez <[email-masked]>
Date: Thu, 31 Jul 2025 08:29:49 -0600

Implements: https://todo.code.netlandish.com/~netlandish/links/87
Changelog-added: Filtering by domain for shorts and link listings.
---
 api/graph/generated.go                        |  18 +-
 api/graph/model/models_gen.go                 |   2 +
 api/graph/schema.graphqls                     |   2 +
 api/graph/schema.resolvers.go                 |  22 +-
 internal/translations/catalog.go              | 416 +++++++++---------
 .../translations/locales/en/out.gotext.json   |   7 +
 .../locales/es/messages.gotext.json           |   5 +
 .../translations/locales/es/out.gotext.json   |   5 +
 list/routes.go                                |  46 +-
 list/routes_test.go                           |  39 ++
 short/routes.go                               |  48 +-
 short/routes_test.go                          |  39 ++
 static/js/advancedsearch.js                   |   9 +
 templates/link_short_list.html                |  14 +-
 templates/listing_list.html                   |  14 +-
 15 files changed, 460 insertions(+), 226 deletions(-)

diff --git a/api/graph/generated.go b/api/graph/generated.go
index c0901b0..c44ada2 100644
--- a/api/graph/generated.go
+++ b/api/graph/generated.go
@@ -25851,7 +25851,7 @@ func (ec *executionContext) unmarshalInputGetLinkShortInput(ctx context.Context,
 		asMap[k] = v
 	}
 
-	fieldsInOrder := [...]string{"orgSlug", "limit", "after", "before", "tag", "excludeTag"}
+	fieldsInOrder := [...]string{"orgSlug", "limit", "after", "before", "tag", "excludeTag", "domainId"}
 	for _, k := range fieldsInOrder {
 		v, ok := asMap[k]
 		if !ok {
@@ -25900,6 +25900,13 @@ func (ec *executionContext) unmarshalInputGetLinkShortInput(ctx context.Context,
 				return it, err
 			}
 			it.ExcludeTag = data
+		case "domainId":
+			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("domainId"))
+			data, err := ec.unmarshalOInt2ᚖint(ctx, v)
+			if err != nil {
+				return it, err
+			}
+			it.DomainID = data
 		}
 	}
 
@@ -25968,7 +25975,7 @@ func (ec *executionContext) unmarshalInputGetListingInput(ctx context.Context, o
 		asMap[k] = v
 	}
 
-	fieldsInOrder := [...]string{"orgSlug", "limit", "after", "before", "tag", "excludeTag"}
+	fieldsInOrder := [...]string{"orgSlug", "limit", "after", "before", "tag", "excludeTag", "domainId"}
 	for _, k := range fieldsInOrder {
 		v, ok := asMap[k]
 		if !ok {
@@ -26017,6 +26024,13 @@ func (ec *executionContext) unmarshalInputGetListingInput(ctx context.Context, o
 				return it, err
 			}
 			it.ExcludeTag = data
+		case "domainId":
+			ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("domainId"))
+			data, err := ec.unmarshalOInt2ᚖint(ctx, v)
+			if err != nil {
+				return it, err
+			}
+			it.DomainID = data
 		}
 	}
 
diff --git a/api/graph/model/models_gen.go b/api/graph/model/models_gen.go
index 065ae14..1f100d8 100644
--- a/api/graph/model/models_gen.go
+++ b/api/graph/model/models_gen.go
@@ -217,6 +217,7 @@ type GetLinkShortInput struct {
 	Before     *Cursor `json:"before,omitempty"`
 	Tag        *string `json:"tag,omitempty"`
 	ExcludeTag *string `json:"excludeTag,omitempty"`
+	DomainID   *int    `json:"domainId,omitempty"`
 }
 
 type GetListingDetailInput struct {
@@ -234,6 +235,7 @@ type GetListingInput struct {
 	Before     *Cursor `json:"before,omitempty"`
 	Tag        *string `json:"tag,omitempty"`
 	ExcludeTag *string `json:"excludeTag,omitempty"`
+	DomainID   *int    `json:"domainId,omitempty"`
 }
 
 type GetOrganizationsInput struct {
diff --git a/api/graph/schema.graphqls b/api/graph/schema.graphqls
index ea8c48a..02f9db8 100644
--- a/api/graph/schema.graphqls
+++ b/api/graph/schema.graphqls
@@ -624,6 +624,7 @@ input GetLinkShortInput {
     before: Cursor
     tag: String
     excludeTag: String
+    domainId: Int
 }
 
 input GetListingInput {
@@ -633,6 +634,7 @@ input GetListingInput {
     before: Cursor
     tag: String
     excludeTag: String
+    domainId: Int
 }
 
 input GetListingDetailInput {
diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go
index e056216..231ea5b 100644
--- a/api/graph/schema.resolvers.go
+++ b/api/graph/schema.resolvers.go
@@ -4810,8 +4810,8 @@ func (r *qRCodeResolver) CodeType(ctx context.Context, obj *models.QRCode) (mode
 func (r *queryResolver) Version(ctx context.Context) (*model.Version, error) {
 	return &model.Version{
 		Major:           0,
-		Minor:           5,
-		Patch:           1,
+		Minor:           6,
+		Patch:           0,
 		DeprecationDate: nil,
 	}, nil
 }
@@ -5641,9 +5641,7 @@ func (r *queryResolver) GetLinkShorts(ctx context.Context, input *model.GetLinkS
 	}
 
 	linkOpts := &database.FilterOptions{
-		Filter: sq.And{
-			sq.Expr("l.org_id = ?", org.ID),
-		},
+		Filter:  sq.Expr("l.org_id = ?", org.ID),
 		OrderBy: "l.id DESC",
 	}
 	if input.After != nil && input.Before != nil {
@@ -5652,6 +5650,13 @@ func (r *queryResolver) GetLinkShorts(ctx context.Context, input *model.GetLinkS
 		return nil, nil
 	}
 
+	if input.DomainID != nil && *input.DomainID != 0 {
+		linkOpts.Filter = sq.And{
+			linkOpts.Filter,
+			sq.Eq{"l.domain_id": *input.DomainID},
+		}
+	}
+
 	if (input.Tag != nil && *input.Tag != "") || (input.ExcludeTag != nil && *input.ExcludeTag != "") {
 		f := links.NewTagQuery("tag_link_shorts", "link_short_id")
 		subQText, subQVal, err := f.GetSubQuery(input.Tag, input.ExcludeTag)
@@ -5776,6 +5781,13 @@ func (r *queryResolver) GetListings(ctx context.Context, input *model.GetListing
 		OrderBy: "l.id DESC",
 	}
 
+	if input.DomainID != nil && *input.DomainID != 0 {
+		listingOpts.Filter = sq.And{
+			listingOpts.Filter,
+			sq.Eq{"l.domain_id": input.DomainID},
+		}
+	}
+
 	if (input.Tag != nil && *input.Tag != "") || (input.ExcludeTag != nil && *input.ExcludeTag != "") {
 		f := links.NewTagQuery("tag_listings", "listing_id")
 		subQText, subQVal, err := f.GetSubQuery(input.Tag, input.ExcludeTag)
diff --git a/internal/translations/catalog.go b/internal/translations/catalog.go
index bd38577..345ab3e 100644
--- a/internal/translations/catalog.go
+++ b/internal/translations/catalog.go
@@ -42,15 +42,15 @@ var messageKeyToIndex = map[string]int{
 	" you can host your own instance if you'd like full control over your own platform.": 412,
 	"%s":                                       437,
 	"%s Links":                                 527,
-	"%s: domain not found":                     680,
+	"%s: domain not found":                     681,
 	"- LinkTaco Team":                          337,
 	"100%% open source project":                411,
 	"A link was successfully created.":         487,
 	"A list was successfully created.":         621,
-	"A new link was created succesfully":       661,
+	"A new link was created succesfully":       662,
 	"A new member invitation was sent to %s":   166,
 	"A new register invitation was sent to %s": 164,
-	"A new short was created succesfully":      659,
+	"A new short was created succesfully":      660,
 	"A new window called Library will open":    560,
 	"A valid Organizaiton Slug is required.":   252,
 	"API Powered":                              392,
@@ -60,7 +60,7 @@ var messageKeyToIndex = map[string]int{
 	"Action":                                   11,
 	"Actions":                                  40,
 	"Add":                                      305,
-	"Add Link":                                 686,
+	"Add Link":                                 687,
 	"Add Member":                               463,
 	"Add OAuth2 Client":                        307,
 	"Add Personal Access Token":                294,
@@ -74,7 +74,7 @@ var messageKeyToIndex = map[string]int{
 	"Already have an account? Click here to login": 58,
 	"An invitation was sent to this user":          469,
 	"An note was successfully created.":            582,
-	"An short link was successfully created.":      673,
+	"An short link was successfully created.":      674,
 	"Analytics":   106,
 	"Apply":       112,
 	"Approve":     332,
@@ -131,29 +131,29 @@ var messageKeyToIndex = map[string]int{
 	"Confirmation User Not Found":                                                               191,
 	"Confirmation key is required.":                                                             171,
 	"Connect":                                                                                   555,
-	"Connect Mattermost":                                                                        639,
-	"Connect User":                                                                              645,
-	"Connect to Slack Workspace":                                                                693,
+	"Connect Mattermost":                                                                        640,
+	"Connect User":                                                                              646,
+	"Connect to Slack Workspace":                                                                694,
 	"Connected":                                                                                 556,
 	"Continue to Upgrade":                                                                       2,
 	"Country":                                                                                   108,
 	"Country analytics":                                                                         378,
-	"Create":                                                                                    629,
+	"Create":                                                                                    630,
 	"Create Domain":                                                                             432,
 	"Create Link":                                                                               479,
 	"Create Links":                                                                              609,
 	"Create List":                                                                               620,
 	"Create Note":                                                                               581,
 	"Create Organization":                                                                       453,
-	"Create QR Code":                                                                            628,
-	"Create Short Link":                                                                         670,
+	"Create QR Code":                                                                            629,
+	"Create Short Link":                                                                         671,
 	"Create link listings (ie, social media bios, etc.)": 363,
 	"Creation Date":                       624,
 	"Current Organization":                37,
 	"Current Password":                    65,
-	"Current password given is incorrect": 700,
+	"Current password given is incorrect": 701,
 	"CurrentSlug is required":             129,
-	"Custom background image":             631,
+	"Custom background image":             632,
 	"Custom domain + SSL":                 361,
 	"Days":                                114,
 	"Default Bookmark Visibility":         455,
@@ -167,7 +167,7 @@ var messageKeyToIndex = map[string]int{
 	"Delete Org Member":                   471,
 	"Delete Picture":                      615,
 	"Delete QR Code":                      546,
-	"Delete Short Link":                   676,
+	"Delete Short Link":                   677,
 	"Delete member %s (%s) from Organization %s?": 474,
 	"Description":              321,
 	"Description is required.": 154,
@@ -176,19 +176,19 @@ var messageKeyToIndex = map[string]int{
 	"Devices":                  111,
 	"Disabled":                 446,
 	"Disconnect":               554,
-	"Disconnect Mattermost":    636,
-	"Disconnect Slack":         687,
-	"Do you really want to disconnect this organization from mattermost":        638,
-	"Do you really want to disconnect this organization from slack":             689,
+	"Disconnect Mattermost":    637,
+	"Disconnect Slack":         688,
+	"Do you really want to disconnect this organization from mattermost":        639,
+	"Do you really want to disconnect this organization from slack":             690,
 	"Do you really whant to delete this bookmark?":                              538,
 	"Do you really whant to delete this domain":                                 440,
 	"Do you really whant to delete this link":                                   608,
-	"Do you really whant to delete this list":                                   627,
+	"Do you really whant to delete this list":                                   628,
 	"Do you really whant to delete this qr code":                                549,
-	"Do you want to connect this organization to mattermost?":                   641,
-	"Do you want to connect with slack?":                                        695,
+	"Do you want to connect this organization to mattermost?":                   642,
+	"Do you want to connect with slack?":                                        696,
 	"Do you want to delete":                                                     540,
-	"Do you want to proceed?":                                                   647,
+	"Do you want to proceed?":                                                   648,
 	"Do you want to revoke this personal access token? This can not be undone.": 297,
 	"Documentation":                          398,
 	"Domain":                                 613,
@@ -196,11 +196,11 @@ var messageKeyToIndex = map[string]int{
 	"Domain Not Found":                       221,
 	"Domain created successfully":            435,
 	"Domain in use. Can not change service.": 255,
-	"Domain not found":                       658,
+	"Domain not found":                       659,
 	"Domain successfully deleted":            438,
 	"DomainID is required":                   214,
 	"Domains":                                448,
-	"Download":                               630,
+	"Download":                               631,
 	"Download Image":                         545,
 	"Drag and drop this button to your web browser toolbar or your bookmarks.": 50,
 	"Duplicated short code":               222,
@@ -231,7 +231,7 @@ var messageKeyToIndex = map[string]int{
 	"Export":                              450,
 	"Export Data":                         550,
 	"Export in JSON or HTML":              391,
-	"Failed the '%s' tag.":                704,
+	"Failed the '%s' tag.":                705,
 	"Feature":                             343,
 	"Feed":                                499,
 	"File format":                         551,
@@ -280,15 +280,15 @@ var messageKeyToIndex = map[string]int{
 	"Import from Firefox":  388,
 	"Import from Pinboard": 387,
 	"Import from Safari":   390,
-	"In order to interact with Link Taco you have to connect you slack account with your link user":          691,
-	"In order to interact with the mattermost you have to connect your account with your link user":          646,
+	"In order to interact with Link Taco you have to connect you slack account with your link user":          692,
+	"In order to interact with the mattermost you have to connect your account with your link user":          647,
 	"In the left sidebar select the folder that you want to export":                                          566,
 	"In the left sidebar select the folder you want to export. To export all bookmarks select All Bookmarks": 561,
 	"In the top bookmark bar click on the three points at the top right":                                     567,
 	"Inactive Domain":                                  338,
 	"Include Tags":                                     504,
 	"Informative URL":                                  322,
-	"Installed successfully":                           663,
+	"Installed successfully":                           664,
 	"Instructions":                                     572,
 	"Integrations":                                     419,
 	"Invalid Confirmation Target":                      174,
@@ -304,17 +304,18 @@ var messageKeyToIndex = map[string]int{
 	"Invalid default permission value":                 139,
 	"Invalid domain ID.":                               209,
 	"Invalid domain name.":                             197,
-	"Invalid email and/or password":                    697,
+	"Invalid domain value given":                       626,
+	"Invalid email and/or password":                    698,
 	"Invalid email format":                             160,
 	"Invalid level value.":                             250,
 	"Invalid listing ID provided":                      275,
 	"Invalid listing for specified organization":       276,
 	"Invalid orgType":                                  248,
-	"Invalid organization given":                       666,
+	"Invalid organization given":                       667,
 	"Invalid origin source for importer.":              280,
 	"Invalid permissions for Organization ID":          203,
 	"Invalid service value.":                           198,
-	"Invalid slack response":                           694,
+	"Invalid slack response":                           695,
 	"Invalid status value.":                            251,
 	"Invalid tag cloud type without organization slug": 265,
 	"Invalid visibility":                               249,
@@ -330,7 +331,7 @@ var messageKeyToIndex = map[string]int{
 	"Link Listings":        362,
 	"Link Lists":           417,
 	"Link Not Found":       152,
-	"Link Search":          683,
+	"Link Search":          684,
 	"Link Short Not Found": 269,
 	"Link Shortening":      369,
 	"Link Shortner":        430,
@@ -348,7 +349,7 @@ var messageKeyToIndex = map[string]int{
 	"Links - Reset your password":          74,
 	"Linktaco: Invitation to Register":     259,
 	"List Not Found":                       240,
-	"List successfully deleted":            626,
+	"List successfully deleted":            627,
 	"Listing":                              368,
 	"Listing Link Not Found":               236,
 	"Listing Not Found":                    232,
@@ -368,7 +369,7 @@ var messageKeyToIndex = map[string]int{
 	"Mark as read":                         516,
 	"Mark as unread":                       517,
 	"MatterMost Integration":               384,
-	"Mattermost successfully disconnected": 637,
+	"Mattermost successfully disconnected": 638,
 	"Member List":                          477,
 	"Member added succesxfully":            475,
 	"Member successfully deleted":          473,
@@ -384,26 +385,26 @@ var messageKeyToIndex = map[string]int{
 	"Name may not exceed 255 characters":               199,
 	"Name may not exceed 500 characters":               200,
 	"New Password":                                     66,
-	"New passwords do not match":                       698,
+	"New passwords do not match":                       699,
 	"Next":                                             15,
 	"No Clients":                                       306,
 	"No Data":                                          121,
-	"No Domain":                                        672,
+	"No Domain":                                        673,
 	"No Domains":                                       431,
 	"No Links":                                         611,
 	"No Lists":                                         623,
-	"No QR Codes":                                      635,
-	"No Short Links":                                   669,
-	"No URL argument was given":                        679,
+	"No QR Codes":                                      636,
+	"No Short Links":                                   670,
+	"No URL argument was given":                        680,
 	"No accounts? Click here to create one":            87,
 	"No audit logs to display":                         14,
-	"No default organization found":                    667,
-	"No links were found for %s":                       652,
+	"No default organization found":                    668,
+	"No links were found for %s":                       653,
 	"No members":                                       478,
-	"No organization found":                            653,
+	"No organization found":                            654,
 	"No organizations":                                 498,
 	"No personal organization found for this user":     196,
-	"No slack connection found":                        649,
+	"No slack connection found":                        650,
 	"No, nevermind":                                    299,
 	"Not Found":                                        263,
 	"Note":                                             578,
@@ -435,8 +436,8 @@ var messageKeyToIndex = map[string]int{
 	"Organization Not Found":                               132,
 	"Organization Slug is required for user level domains": 253,
 	"Organization created successfully":                    459,
-	"Organization linked successfully with mattermost":     643,
-	"Organization linked successfully with slack":          696,
+	"Organization linked successfully with mattermost":     644,
+	"Organization linked successfully with slack":          697,
 	"Organization not found.":                              274,
 	"Organization updated successfully":                    462,
 	"Organizations":                                        36,
@@ -459,12 +460,12 @@ var messageKeyToIndex = map[string]int{
 	"Personal":               345,
 	"Personal Access Tokens": 284,
 	"Personal Tokens":        595,
-	"Please click in the following link to tie a org %s":                               662,
+	"Please click in the following link to tie a org %s":                               663,
 	"Please click the link below:":                                                     261,
 	"Please confirm your account":                                                      100,
-	"Please enter a valid email address.":                                              702,
-	"Please enter a valid phone number.":                                               703,
-	"Please link your slack user with link: %s":                                        684,
+	"Please enter a valid email address.":                                              703,
+	"Please enter a valid phone number.":                                               704,
+	"Please link your slack user with link: %s":                                        685,
 	"Please login to view multiple tag combos (sorry, this is to help stop bot abuse)": 6,
 	"Please upgrade to a Business organization to add members":                         465,
 	"Please upgrade your account to reactivate it":                                     340,
@@ -483,10 +484,10 @@ var messageKeyToIndex = map[string]int{
 	"Public Post":                    531,
 	"Public only":                    352,
 	"QR Code Details":                544,
-	"QR Code Listing":                633,
+	"QR Code Listing":                634,
 	"QR Code Not Found":              244,
 	"QR Code specific analytics":     375,
-	"QR Code succesfully created":    632,
+	"QR Code succesfully created":    633,
 	"QR Code successfully deleted":   548,
 	"QR Codes":                       625,
 	"QR Codes powered by Link Taco!": 542,
@@ -530,16 +531,16 @@ var messageKeyToIndex = map[string]int{
 	"Service":                                      428,
 	"Set up your account, so you can save links.":  60,
 	"Settings":                                     30,
-	"Short Code":                                   671,
+	"Short Code":                                   672,
 	"Short Code may not exceed 20 characters":      216,
-	"Short Link":                                   668,
-	"Short Link successfully deleted":              677,
+	"Short Link":                                   669,
+	"Short Link successfully deleted":              678,
 	"Short Links":                                  598,
 	"Short Not Found":                              242,
-	"Short link successfully updated.":             675,
+	"Short link successfully updated.":             676,
 	"Since we're a":                                410,
 	"Slack Integration":                            383,
-	"Slack successfully disconnected":              688,
+	"Slack successfully disconnected":              689,
 	"Slug":                                         31,
 	"Slug is required":                             130,
 	"Slug is required.":                            224,
@@ -555,11 +556,11 @@ var messageKeyToIndex = map[string]int{
 	"Something went wrong. Impossible to get the member data":                                                                    476,
 	"Something went wrong. The QR Code could not be deleted.":                                                                    547,
 	"Something went wrong. The link could not be deleted.":                                                                       606,
-	"Something went wrong. The user could not be linked.":                                                                        692,
+	"Something went wrong. The user could not be linked.":                                                                        693,
 	"Something went wrong. This bookmark could not be deleted.":                                                                  536,
 	"Something went wrong. This member could not be deleted: %s":                                                                 472,
-	"Sorry, free accounts do not support Mattermost Integration. Please upgrade to continue":                                     644,
-	"Sorry, free accounts do not support Slack Integration. Please upgrade to continue":                                          690,
+	"Sorry, free accounts do not support Mattermost Integration. Please upgrade to continue":                                     645,
+	"Sorry, free accounts do not support Slack Integration. Please upgrade to continue":                                          691,
 	"Sorry, you have exceeded the amount of free accounts available. Please update your current free account to create one more": 456,
 	"Source":                             558,
 	"Spanish":                            27,
@@ -580,17 +581,17 @@ var messageKeyToIndex = map[string]int{
 	"The %s domain is currently inactive":                            339,
 	"The User is not verified":                                       177,
 	"The User you try to invite is not verified":                     165,
-	"The code is required":                                           656,
+	"The code is required":                                           657,
 	"The domain is already registered in the system":                 205,
-	"The domain is required":                                         657,
+	"The domain is required":                                         658,
 	"The file is required":                                           281,
 	"The file submitted for this source should be html":              282,
 	"The file submitted for this source should be json":              283,
 	"The member was removed successfully":                            170,
 	"The passwords you entered do not match.":                        17,
-	"The text to be searched is required":                            651,
-	"The title is required":                                          654,
-	"The url is required":                                            655,
+	"The text to be searched is required":                            652,
+	"The title is required":                                          655,
+	"The url is required":                                            656,
 	"The user for given email is not a member of given organization": 169,
 	"The user was added successfully":                                178,
 	"There is already a default listing for this domain":             229,
@@ -601,9 +602,9 @@ var messageKeyToIndex = map[string]int{
 	"This email domain is not allowed":                                                                       162,
 	"This email is already registered":                                                                       187,
 	"This feature is not allowed for free user. Please upgrade.":                                             552,
-	"This feature is restricted to free accounts. Please upgrade.":                                           642,
+	"This feature is restricted to free accounts. Please upgrade.":                                           643,
 	"This feed has no links. Booo!":                                                                          509,
-	"This field is required.":                                                                                701,
+	"This field is required.":                                                                                702,
 	"This function is only allowed for business users.":                                                      163,
 	"This function is only allowed for paid users.":                                                          204,
 	"This function is only allowed for paid users. Please upgrade":                                           1,
@@ -616,7 +617,7 @@ var messageKeyToIndex = map[string]int{
 	"This shortCode can not be used. Please chose another one":                                               217,
 	"This slug can not be used. Please chose another one":                                                    134,
 	"This special link allows you to save to LinkTaco directly by using a bookmark in your web browser.":     49,
-	"This team is already tied to an organization":                                                           640,
+	"This team is already tied to an organization":                                                           641,
 	"This user does not follow this org":                                                                     246,
 	"This user is not allowed to perform this action":                                                        153,
 	"This username can not be used. Please chose another one":                                                188,
@@ -637,7 +638,7 @@ var messageKeyToIndex = map[string]int{
 	"Tour":                                 585,
 	"Try It FREE":                          353,
 	"URL":                                  603,
-	"URL Shortening powered by Link Taco!": 678,
+	"URL Shortening powered by Link Taco!": 679,
 	"URL is required.":                     213,
 	"URL may not exceed 2048 characters":   142,
 	"Unable to delete. Domain has active short links or link listings": 212,
@@ -660,31 +661,31 @@ var messageKeyToIndex = map[string]int{
 	"Update List":         612,
 	"Update Note":         577,
 	"Update Organization": 460,
-	"Update Short Link":   674,
+	"Update Short Link":   675,
 	"Update email":        42,
 	"Upgrade Org":         45,
 	"Upgrade the organization to activate them.":                 529,
 	"Upgrade your account to support private bookmarks.":         571,
 	"Upgrade your organization to paid to view the detail stats": 118,
-	"Url is required": 660,
+	"Url is required": 661,
 	"Use commas to separate your tags. Example: tag 1, tag 2, tag 3": 485,
 	"User Not Found":                         176,
-	"User connected successfully":            648,
+	"User connected successfully":            649,
 	"User email is required":                 158,
 	"User follows %s":                        245,
-	"User is not authenticated":              699,
+	"User is not authenticated":              700,
 	"User not found for given email":         168,
 	"User unfollows %s":                      247,
 	"Username":                               23,
 	"Username is required":                   182,
 	"Username may not exceed 150 characters": 183,
-	"View":                                   634,
+	"View":                                   635,
 	"View Audit Logs":                        46,
 	"Visibility":                             481,
 	"We sent you a confirmation email. Please click the link in that email to confirm your account.":     62,
-	"We sent you a direct message with instructions":                                                     685,
+	"We sent you a direct message with instructions":                                                     686,
 	"We sent you a new confirmation email. Please click the link in that email to confirm your account.": 105,
-	"We sent you a private msg": 650,
+	"We sent you a private msg": 651,
 	"Weeks":                     113,
 	"Welcome to LinkTaco!":      401,
 	"Welcome to LinkTaco! Here you can mix all your link saving and sharing needs in one tight little bundle. Much like a taco. A link taco if you will.": 4,
@@ -718,12 +719,12 @@ var messageKeyToIndex = map[string]int{
 	"Your bookmark import is being processed. We will notify you once it's complete.": 576,
 	"Your feed is empty :( Go follow some people. Try the Popular or Recent feeds to find some interesting people to follow.": 502,
 	"Your importing into a free account / organization, any private pinboard bookmarks will be marked restricted.":            570,
-	"Your link was successfully saved. Details here: %s":                                                                      682,
-	"Your short link was successfully created: %s":                                                                            681,
+	"Your link was successfully saved. Details here: %s":                                                                      683,
+	"Your short link was successfully created: %s":                                                                            682,
 	"and login": 73,
 	"bookmark":  490,
 	"bookmark, note, detail, popular, links, linktaco": 534,
-	"done":              665,
+	"done":              666,
 	"for":               429,
 	"invalid domain ID": 210,
 	"is a third-party application operated by": 329,
@@ -742,11 +743,11 @@ var messageKeyToIndex = map[string]int{
 	"saved":                                  512,
 	"short-service-domain is not configured": 220,
 	"social bookmarks, bookmarking, links, link sharing, link shortening, link listings, bookmarks, link saving, qr codes, analytics": 5,
-	"something went wrong: %s":                        664,
+	"something went wrong: %s":                        665,
 	"would like to access to your Link Taco account.": 328,
 }
 
-var enIndex = []uint32{ // 706 elements
+var enIndex = []uint32{ // 707 elements
 	// Entry 0 - 1F
 	0x00000000, 0x00000010, 0x0000004d, 0x00000061,
 	0x000000af, 0x00000143, 0x000001c3, 0x00000214,
@@ -923,33 +924,33 @@ var enIndex = []uint32{ // 706 elements
 	0x000047cd, 0x000047d9, 0x000047e0, 0x000047eb,
 	0x000047fa, 0x00004800, 0x0000480b, 0x00004818,
 	0x00004836, 0x00004842, 0x00004863, 0x00004870,
-	0x00004879, 0x00004887, 0x00004890, 0x000048aa,
-	0x000048d2, 0x000048e1, 0x000048e8, 0x000048f1,
-	0x00004909, 0x00004925, 0x00004935, 0x0000493a,
-	0x00004946, 0x0000495c, 0x00004981, 0x000049c4,
+	0x00004879, 0x00004887, 0x00004890, 0x000048ab,
+	0x000048c5, 0x000048ed, 0x000048fc, 0x00004903,
+	0x0000490c, 0x00004924, 0x00004940, 0x00004950,
+	0x00004955, 0x00004961, 0x00004977, 0x0000499c,
 	// Entry 280 - 29F
-	0x000049d7, 0x00004a04, 0x00004a3c, 0x00004a79,
-	0x00004aaa, 0x00004b01, 0x00004b0e, 0x00004b6c,
-	0x00004b84, 0x00004ba0, 0x00004bba, 0x00004bd4,
-	0x00004bf8, 0x00004c16, 0x00004c2c, 0x00004c42,
-	0x00004c56, 0x00004c6b, 0x00004c82, 0x00004c93,
-	0x00004cb7, 0x00004cc7, 0x00004cea, 0x00004d20,
-	0x00004d37, 0x00004d53, 0x00004d58, 0x00004d73,
-	0x00004d91, 0x00004d9c, 0x00004dab, 0x00004dbd,
+	0x000049df, 0x000049f2, 0x00004a1f, 0x00004a57,
+	0x00004a94, 0x00004ac5, 0x00004b1c, 0x00004b29,
+	0x00004b87, 0x00004b9f, 0x00004bbb, 0x00004bd5,
+	0x00004bef, 0x00004c13, 0x00004c31, 0x00004c47,
+	0x00004c5d, 0x00004c71, 0x00004c86, 0x00004c9d,
+	0x00004cae, 0x00004cd2, 0x00004ce2, 0x00004d05,
+	0x00004d3b, 0x00004d52, 0x00004d6e, 0x00004d73,
+	0x00004d8e, 0x00004dac, 0x00004db7, 0x00004dc6,
 	// Entry 2A0 - 2BF
-	0x00004dc8, 0x00004dd2, 0x00004dfa, 0x00004e0c,
-	0x00004e2d, 0x00004e3f, 0x00004e5f, 0x00004e84,
-	0x00004e9e, 0x00004eb6, 0x00004ee6, 0x00004f1c,
-	0x00004f28, 0x00004f55, 0x00004f84, 0x00004f8d,
-	0x00004f9e, 0x00004fbe, 0x00004ffc, 0x0000504e,
-	0x000050ac, 0x000050e0, 0x000050fb, 0x00005112,
-	0x00005135, 0x00005161, 0x0000517f, 0x0000519a,
-	0x000051b4, 0x000051d8, 0x000051f0, 0x00005214,
+	0x00004dd8, 0x00004de3, 0x00004ded, 0x00004e15,
+	0x00004e27, 0x00004e48, 0x00004e5a, 0x00004e7a,
+	0x00004e9f, 0x00004eb9, 0x00004ed1, 0x00004f01,
+	0x00004f37, 0x00004f43, 0x00004f70, 0x00004f9f,
+	0x00004fa8, 0x00004fb9, 0x00004fd9, 0x00005017,
+	0x00005069, 0x000050c7, 0x000050fb, 0x00005116,
+	0x0000512d, 0x00005150, 0x0000517c, 0x0000519a,
+	0x000051b5, 0x000051cf, 0x000051f3, 0x0000520b,
 	// Entry 2C0 - 2DF
-	0x00005237, 0x0000524f,
-} // Size: 2848 bytes
+	0x0000522f, 0x00005252, 0x0000526a,
+} // Size: 2852 bytes
 
-const enData string = "" + // Size: 21071 bytes
+const enData string = "" + // Size: 21098 bytes
 	"\x02Restricted Page\x02This function is only allowed for paid users. Ple" +
 	"ase upgrade\x02Continue to Upgrade\x02Social bookmarking plus link shari" +
 	"ng, shortening and listings all in one app.\x02Welcome to LinkTaco! Here" +
@@ -1235,47 +1236,47 @@ const enData string = "" + // Size: 21071 bytes
 	"o Links\x02Update List\x02Domain\x02Is Default\x02Delete Picture\x02Othe" +
 	"r\x02Other Name\x02Social Links\x02Listing successfully updated.\x02Crea" +
 	"te List\x02A list was successfully created.\x02Manage Links\x02No Lists" +
-	"\x02Creation Date\x02QR Codes\x02List successfully deleted\x02Do you rea" +
-	"lly whant to delete this list\x02Create QR Code\x02Create\x02Download" +
-	"\x02Custom background image\x02QR Code succesfully created\x02QR Code Li" +
-	"sting\x02View\x02No QR Codes\x02Disconnect Mattermost\x02Mattermost succ" +
-	"essfully disconnected\x02Do you really want to disconnect this organizat" +
-	"ion from mattermost\x02Connect Mattermost\x02This team is already tied t" +
-	"o an organization\x02Do you want to connect this organization to matterm" +
-	"ost?\x02This feature is restricted to free accounts. Please upgrade.\x02" +
-	"Organization linked successfully with mattermost\x02Sorry, free accounts" +
-	" do not support Mattermost Integration. Please upgrade to continue\x02Co" +
-	"nnect User\x02In order to interact with the mattermost you have to conne" +
-	"ct your account with your link user\x02Do you want to proceed?\x02User c" +
-	"onnected successfully\x02No slack connection found\x02We sent you a priv" +
-	"ate msg\x02The text to be searched is required\x02No links were found fo" +
-	"r %[1]s\x02No organization found\x02The title is required\x02The url is " +
-	"required\x02The code is required\x02The domain is required\x02Domain not" +
-	" found\x02A new short was created succesfully\x02Url is required\x02A ne" +
-	"w link was created succesfully\x02Please click in the following link to " +
-	"tie a org %[1]s\x02Installed successfully\x02something went wrong: %[1]s" +
-	"\x02done\x02Invalid organization given\x02No default organization found" +
-	"\x02Short Link\x02No Short Links\x02Create Short Link\x02Short Code\x02N" +
-	"o Domain\x02An short link was successfully created.\x02Update Short Link" +
-	"\x02Short link successfully updated.\x02Delete Short Link\x02Short Link " +
-	"successfully deleted\x02URL Shortening powered by Link Taco!\x02No URL a" +
-	"rgument was given\x02%[1]s: domain not found\x02Your short link was succ" +
-	"essfully created: %[1]s\x02Your link was successfully saved. Details her" +
-	"e: %[1]s\x02Link Search\x02Please link your slack user with link: %[1]s" +
-	"\x02We sent you a direct message with instructions\x02Add Link\x02Discon" +
-	"nect Slack\x02Slack successfully disconnected\x02Do you really want to d" +
-	"isconnect this organization from slack\x02Sorry, free accounts do not su" +
-	"pport Slack Integration. Please upgrade to continue\x02In order to inter" +
-	"act with Link Taco you have to connect you slack account with your link " +
-	"user\x02Something went wrong. The user could not be linked.\x02Connect t" +
-	"o Slack Workspace\x02Invalid slack response\x02Do you want to connect wi" +
-	"th slack?\x02Organization linked successfully with slack\x02Invalid emai" +
-	"l and/or password\x02New passwords do not match\x02User is not authentic" +
-	"ated\x02Current password given is incorrect\x02This field is required." +
-	"\x02Please enter a valid email address.\x02Please enter a valid phone nu" +
-	"mber.\x02Failed the '%[1]s' tag."
+	"\x02Creation Date\x02QR Codes\x02Invalid domain value given\x02List succ" +
+	"essfully deleted\x02Do you really whant to delete this list\x02Create QR" +
+	" Code\x02Create\x02Download\x02Custom background image\x02QR Code succes" +
+	"fully created\x02QR Code Listing\x02View\x02No QR Codes\x02Disconnect Ma" +
+	"ttermost\x02Mattermost successfully disconnected\x02Do you really want t" +
+	"o disconnect this organization from mattermost\x02Connect Mattermost\x02" +
+	"This team is already tied to an organization\x02Do you want to connect t" +
+	"his organization to mattermost?\x02This feature is restricted to free ac" +
+	"counts. Please upgrade.\x02Organization linked successfully with matterm" +
+	"ost\x02Sorry, free accounts do not support Mattermost Integration. Pleas" +
+	"e upgrade to continue\x02Connect User\x02In order to interact with the m" +
+	"attermost you have to connect your account with your link user\x02Do you" +
+	" want to proceed?\x02User connected successfully\x02No slack connection " +
+	"found\x02We sent you a private msg\x02The text to be searched is require" +
+	"d\x02No links were found for %[1]s\x02No organization found\x02The title" +
+	" is required\x02The url is required\x02The code is required\x02The domai" +
+	"n is required\x02Domain not found\x02A new short was created succesfully" +
+	"\x02Url is required\x02A new link was created succesfully\x02Please clic" +
+	"k in the following link to tie a org %[1]s\x02Installed successfully\x02" +
+	"something went wrong: %[1]s\x02done\x02Invalid organization given\x02No " +
+	"default organization found\x02Short Link\x02No Short Links\x02Create Sho" +
+	"rt Link\x02Short Code\x02No Domain\x02An short link was successfully cre" +
+	"ated.\x02Update Short Link\x02Short link successfully updated.\x02Delete" +
+	" Short Link\x02Short Link successfully deleted\x02URL Shortening powered" +
+	" by Link Taco!\x02No URL argument was given\x02%[1]s: domain not found" +
+	"\x02Your short link was successfully created: %[1]s\x02Your link was suc" +
+	"cessfully saved. Details here: %[1]s\x02Link Search\x02Please link your " +
+	"slack user with link: %[1]s\x02We sent you a direct message with instruc" +
+	"tions\x02Add Link\x02Disconnect Slack\x02Slack successfully disconnected" +
+	"\x02Do you really want to disconnect this organization from slack\x02Sor" +
+	"ry, free accounts do not support Slack Integration. Please upgrade to co" +
+	"ntinue\x02In order to interact with Link Taco you have to connect you sl" +
+	"ack account with your link user\x02Something went wrong. The user could " +
+	"not be linked.\x02Connect to Slack Workspace\x02Invalid slack response" +
+	"\x02Do you want to connect with slack?\x02Organization linked successful" +
+	"ly with slack\x02Invalid email and/or password\x02New passwords do not m" +
+	"atch\x02User is not authenticated\x02Current password given is incorrect" +
+	"\x02This field is required.\x02Please enter a valid email address.\x02Pl" +
+	"ease enter a valid phone number.\x02Failed the '%[1]s' tag."
 
-var esIndex = []uint32{ // 706 elements
+var esIndex = []uint32{ // 707 elements
 	// Entry 0 - 1F
 	0x00000000, 0x00000014, 0x0000006a, 0x00000089,
 	0x000000e0, 0x00000199, 0x00000233, 0x000002a4,
@@ -1453,32 +1454,32 @@ var esIndex = []uint32{ // 706 elements
 	0x00005578, 0x0000557d, 0x00005589, 0x00005598,
 	0x000055b0, 0x000055bc, 0x000055dc, 0x000055ea,
 	0x000055f5, 0x00005608, 0x00005614, 0x0000562f,
-	0x00005658, 0x00005669, 0x0000566f, 0x00005679,
-	0x00005699, 0x000056b6, 0x000056ca, 0x000056ce,
-	0x000056e1, 0x000056f8, 0x0000571b, 0x00005758,
+	0x0000564a, 0x00005673, 0x00005684, 0x0000568a,
+	0x00005694, 0x000056b4, 0x000056d1, 0x000056e5,
+	0x000056e9, 0x000056fc, 0x00005713, 0x00005736,
 	// Entry 280 - 29F
-	0x00005771, 0x000057ab, 0x000057e0, 0x00005829,
-	0x00005853, 0x000058b6, 0x000058c7, 0x00005921,
-	0x00005933, 0x00005950, 0x00005973, 0x00005992,
-	0x000059b6, 0x000059da, 0x000059f6, 0x00005a0e,
-	0x00005a22, 0x00005a3a, 0x00005a52, 0x00005a68,
-	0x00005a8c, 0x00005a9d, 0x00005ac3, 0x00005b12,
-	0x00005b28, 0x00005b3f, 0x00005b45, 0x00005b6b,
-	0x00005b98, 0x00005ba3, 0x00005bb4, 0x00005bc5,
+	0x00005773, 0x0000578c, 0x000057c6, 0x000057fb,
+	0x00005844, 0x0000586e, 0x000058d1, 0x000058e2,
+	0x0000593c, 0x0000594e, 0x0000596b, 0x0000598e,
+	0x000059ad, 0x000059d1, 0x000059f5, 0x00005a11,
+	0x00005a29, 0x00005a3d, 0x00005a55, 0x00005a6d,
+	0x00005a83, 0x00005aa7, 0x00005ab8, 0x00005ade,
+	0x00005b2d, 0x00005b43, 0x00005b5a, 0x00005b60,
+	0x00005b86, 0x00005bb3, 0x00005bbe, 0x00005bcf,
 	// Entry 2A0 - 2BF
-	0x00005bd3, 0x00005bdf, 0x00005c03, 0x00005c19,
-	0x00005c3b, 0x00005c4f, 0x00005c6f, 0x00005c8b,
-	0x00005cb2, 0x00005ccf, 0x00005cfc, 0x00005d35,
-	0x00005d41, 0x00005d7a, 0x00005dab, 0x00005db8,
-	0x00005dcd, 0x00005def, 0x00005e1d, 0x00005e94,
-	0x00005ef6, 0x00005f2a, 0x00005f45, 0x00005f62,
-	0x00005f7f, 0x00005fac, 0x00005fc9, 0x00005fee,
-	0x0000600e, 0x00006032, 0x0000604a, 0x00006071,
+	0x00005be0, 0x00005bee, 0x00005bfa, 0x00005c1e,
+	0x00005c34, 0x00005c56, 0x00005c6a, 0x00005c8a,
+	0x00005ca6, 0x00005ccd, 0x00005cea, 0x00005d17,
+	0x00005d50, 0x00005d5c, 0x00005d95, 0x00005dc6,
+	0x00005dd3, 0x00005de8, 0x00005e0a, 0x00005e38,
+	0x00005eaf, 0x00005f11, 0x00005f45, 0x00005f60,
+	0x00005f7d, 0x00005f9a, 0x00005fc7, 0x00005fe4,
+	0x00006009, 0x00006029, 0x0000604d, 0x00006065,
 	// Entry 2C0 - 2DF
-	0x00006099, 0x000060ac,
-} // Size: 2848 bytes
+	0x0000608c, 0x000060b4, 0x000060c7,
+} // Size: 2852 bytes
 
-const esData string = "" + // Size: 24748 bytes
+const esData string = "" + // Size: 24775 bytes
 	"\x02Página Restringida\x02Esta función solo está permitida para usuarios" +
 	" de pago. Por favor actualice su plan\x02Continuar para actualizar plan" +
 	"\x02Marcadores sociales más compartir enlaces, acortar y listar, todo en" +
@@ -1806,46 +1807,47 @@ const esData string = "" + // Size: 24748 bytes
 	"ks\x02Actualizar Lista\x02Dominio\x02Es por defecto\x02Eliminar Foto\x02" +
 	"Otro\x02Otro Nombre\x02Links Sociales\x02Lista creada con éxito\x02Crear" +
 	" Lista\x02Una lista fue creada con éxito\x02Manejar Links\x02Sin Listas" +
-	"\x02Fecha de Creación\x02Códigos QR\x02Lista eliminada con éxito\x02¿Rea" +
-	"lmente quieres eliminar esta lista?\x02Crear Código QR\x02Crear\x02Desca" +
-	"rgar\x02Fondo de pantalla personalizado\x02Código QR creado con éxito" +
-	"\x02Código QR de Lista\x02Ver\x02No hay Códigos QR\x02Desconectar Matter" +
-	"most\x02Mattermost desconectado con éxito\x02Desea realmente desconectar" +
-	" esta organización de mattermost\x02Connectar con Mattermost\x02Este equ" +
-	"ipo ya se encuentra vinculado a una organización\x02¿Deseas conectar est" +
-	"a organización con mattermost?\x02Esta función está restringida para cue" +
-	"ntas gratis. Por favor actualiza\x02La organización fue vinculada con éx" +
-	"ito\x02Lo sentimos, las cuentas gratuitas no soportan la integración con" +
-	" Mattermost. Por favor actualice\x02Conectar Usuario\x02Para interactuar" +
-	" con mattermost tienes que conectar tu cuenta con tu usuario de Link Tac" +
-	"o\x02¿Desea proceder?\x02Usuario conectado con éxito\x02Connexión con sl" +
-	"ack no encontrada\x02Te enviamos un mensaje privado\x02El texto a ser bu" +
-	"scado es requerido\x02No se encuentraron links para %[1]s\x02Organizació" +
-	"n no encontrada\x02El título es requerido\x02La url es requerida\x02El c" +
-	"ódigo es requerido\x02El dominio es requerido\x02Dominio no encontrado" +
-	"\x02A nuevo short fue creado con éxito\x02Url es requerida\x02Un nuevo e" +
-	"nlace fue creado con éxito\x02Por favor haga click en el próximo link pa" +
-	"ra vincular una organización %[1]s\x02Instalacción exitosa\x02algo salió" +
-	" mal: %[1]s\x02hecho\x02Organización inválida proporcionada\x02No se enc" +
-	"ontró organización predeterminada\x02Link Corto\x02Sin Links Cortos\x02C" +
-	"rear Link Corto\x02Código Corto\x02Sin Dominio\x02Un link corto fue crea" +
-	"do con éxito\x02Actualizar Link Corto\x02Link Corto actualizado con éxit" +
-	"o\x02Eliminar Link Corto\x02Link Corto eliminado con éxito\x02URL acorta" +
-	"da por Link Taco!\x02No se proporcionó un argumento de URL\x02%[1]s: dom" +
-	"inio no encontrado\x02Tu enlace corto fue creado con éxito: %[1]s\x02Tu " +
-	"enlace fue guardado con éxito. Detalles aquí: %[1]s\x02Buscar Link\x02Po" +
-	"r favor vincule tu usuario de slack con el link: %[1]s\x02Te enviamos un" +
-	" mensaje directo con instrucciones\x02Agregar Link\x02Desconectar de Sla" +
-	"ck\x02Slack fue desconectado con éxito\x02Desea desconectar esta organiz" +
-	"ación de slack\x02Lo sentimos, las cuentas gratis no soportan integració" +
-	"n con Slack. Por favor actualice su subscripcón para continuar\x02Para i" +
-	"nteractuar con Link Taco tienes que conectar tu cuenta de slack con tu u" +
-	"suario de Link Taco\x02Algo salió mal. El usuario no puede ser vinculado" +
-	".\x02Conectar a Slack Workspace\x02Respuesta de slack inválida\x02¿Desea" +
-	"s conectar con Slack?\x02Organización vinculada con éxito con slack\x02E" +
-	"mail y/o password inválido\x02Las nuevas contraseñas no coinciden\x02El " +
-	"usuario no está autenticado\x02La contraseña actual es incorrecta\x02Est" +
-	"e campo es requerido\x02Por favor introduzca un correo válido\x02Por fav" +
-	"or introduzca un número válido\x02El '%[1]s' falló."
+	"\x02Fecha de Creación\x02Códigos QR\x02Valor de dominio inválido\x02List" +
+	"a eliminada con éxito\x02¿Realmente quieres eliminar esta lista?\x02Crea" +
+	"r Código QR\x02Crear\x02Descargar\x02Fondo de pantalla personalizado\x02" +
+	"Código QR creado con éxito\x02Código QR de Lista\x02Ver\x02No hay Código" +
+	"s QR\x02Desconectar Mattermost\x02Mattermost desconectado con éxito\x02D" +
+	"esea realmente desconectar esta organización de mattermost\x02Connectar " +
+	"con Mattermost\x02Este equipo ya se encuentra vinculado a una organizaci" +
+	"ón\x02¿Deseas conectar esta organización con mattermost?\x02Esta funció" +
+	"n está restringida para cuentas gratis. Por favor actualiza\x02La organi" +
+	"zación fue vinculada con éxito\x02Lo sentimos, las cuentas gratuitas no " +
+	"soportan la integración con Mattermost. Por favor actualice\x02Conectar " +
+	"Usuario\x02Para interactuar con mattermost tienes que conectar tu cuenta" +
+	" con tu usuario de Link Taco\x02¿Desea proceder?\x02Usuario conectado co" +
+	"n éxito\x02Connexión con slack no encontrada\x02Te enviamos un mensaje p" +
+	"rivado\x02El texto a ser buscado es requerido\x02No se encuentraron link" +
+	"s para %[1]s\x02Organización no encontrada\x02El título es requerido\x02" +
+	"La url es requerida\x02El código es requerido\x02El dominio es requerido" +
+	"\x02Dominio no encontrado\x02A nuevo short fue creado con éxito\x02Url e" +
+	"s requerida\x02Un nuevo enlace fue creado con éxito\x02Por favor haga cl" +
+	"ick en el próximo link para vincular una organización %[1]s\x02Instalacc" +
+	"ión exitosa\x02algo salió mal: %[1]s\x02hecho\x02Organización inválida p" +
+	"roporcionada\x02No se encontró organización predeterminada\x02Link Corto" +
+	"\x02Sin Links Cortos\x02Crear Link Corto\x02Código Corto\x02Sin Dominio" +
+	"\x02Un link corto fue creado con éxito\x02Actualizar Link Corto\x02Link " +
+	"Corto actualizado con éxito\x02Eliminar Link Corto\x02Link Corto elimina" +
+	"do con éxito\x02URL acortada por Link Taco!\x02No se proporcionó un argu" +
+	"mento de URL\x02%[1]s: dominio no encontrado\x02Tu enlace corto fue crea" +
+	"do con éxito: %[1]s\x02Tu enlace fue guardado con éxito. Detalles aquí: " +
+	"%[1]s\x02Buscar Link\x02Por favor vincule tu usuario de slack con el lin" +
+	"k: %[1]s\x02Te enviamos un mensaje directo con instrucciones\x02Agregar " +
+	"Link\x02Desconectar de Slack\x02Slack fue desconectado con éxito\x02Dese" +
+	"a desconectar esta organización de slack\x02Lo sentimos, las cuentas gra" +
+	"tis no soportan integración con Slack. Por favor actualice su subscripcó" +
+	"n para continuar\x02Para interactuar con Link Taco tienes que conectar t" +
+	"u cuenta de slack con tu usuario de Link Taco\x02Algo salió mal. El usua" +
+	"rio no puede ser vinculado.\x02Conectar a Slack Workspace\x02Respuesta d" +
+	"e slack inválida\x02¿Deseas conectar con Slack?\x02Organización vinculad" +
+	"a con éxito con slack\x02Email y/o password inválido\x02Las nuevas contr" +
+	"aseñas no coinciden\x02El usuario no está autenticado\x02La contraseña a" +
+	"ctual es incorrecta\x02Este campo es requerido\x02Por favor introduzca u" +
+	"n correo válido\x02Por favor introduzca un número válido\x02El '%[1]s' f" +
+	"alló."
 
-	// Total table size 51515 bytes (50KiB); checksum: B449DFD5
+	// Total table size 51577 bytes (50KiB); checksum: 811A805E
diff --git a/internal/translations/locales/en/out.gotext.json b/internal/translations/locales/en/out.gotext.json
index 82f811b..45e5b4a 100644
--- a/internal/translations/locales/en/out.gotext.json
+++ b/internal/translations/locales/en/out.gotext.json
@@ -4579,6 +4579,13 @@
             "translatorComment": "Copied from source.",
             "fuzzy": true
         },
+        {
+            "id": "Invalid domain value given",
+            "message": "Invalid domain value given",
+            "translation": "Invalid domain value given",
+            "translatorComment": "Copied from source.",
+            "fuzzy": true
+        },
         {
             "id": "List successfully deleted",
             "message": "List successfully deleted",
diff --git a/internal/translations/locales/es/messages.gotext.json b/internal/translations/locales/es/messages.gotext.json
index cc891da..ed7f836 100644
--- a/internal/translations/locales/es/messages.gotext.json
+++ b/internal/translations/locales/es/messages.gotext.json
@@ -3327,6 +3327,11 @@
             "message": "QR Codes",
             "translation": "Códigos QR"
         },
+        {
+            "id": "Invalid domain value given",
+            "message": "Invalid domain value given",
+            "translation": "Valor de dominio inválido"
+        },
         {
             "id": "List successfully deleted",
             "message": "List successfully deleted",
diff --git a/internal/translations/locales/es/out.gotext.json b/internal/translations/locales/es/out.gotext.json
index cc891da..ed7f836 100644
--- a/internal/translations/locales/es/out.gotext.json
+++ b/internal/translations/locales/es/out.gotext.json
@@ -3327,6 +3327,11 @@
             "message": "QR Codes",
             "translation": "Códigos QR"
         },
+        {
+            "id": "Invalid domain value given",
+            "message": "Invalid domain value given",
+            "translation": "Valor de dominio inválido"
+        },
         {
             "id": "List successfully deleted",
             "message": "List successfully deleted",
diff --git a/list/routes.go b/list/routes.go
index 2f82358..2fe20c2 100644
--- a/list/routes.go
+++ b/list/routes.go
@@ -1043,6 +1043,7 @@ func (s *Service) ListingList(c echo.Context) error {
 	pd.Data["clear"] = lt.Translate("Clear")
 	pd.Data["is_default"] = lt.Translate("Is Default")
 	pd.Data["logs"] = lt.Translate("View Audit Logs")
+	pd.Data["domain"] = lt.Translate("Domain")
 
 	type GraphQLResponse struct {
 		Listings struct {
@@ -1057,8 +1058,8 @@ func (s *Service) ListingList(c echo.Context) error {
 
 	var result GraphQLResponse
 	op := gqlclient.NewOperation(
-		`query GetListings($orgSlug: String!, $after: Cursor, $before: Cursor, $tag: String, $excludeTag: String) {
-			getListings(input: {orgSlug: $orgSlug, after: $after, before: $before, tag: $tag, excludeTag: $excludeTag}) {
+		`query GetListings($orgSlug: String!, $after: Cursor, $before: Cursor, $tag: String, $excludeTag: String, $domain: Int) {
+			getListings(input: {orgSlug: $orgSlug, after: $after, before: $before, tag: $tag, excludeTag: $excludeTag, domainId: $domain}) {
 				result {
 					id
 					title
@@ -1104,6 +1105,16 @@ func (s *Service) ListingList(c echo.Context) error {
 		op.Var("before", c.QueryParam("prev"))
 	}
 
+	var domID int
+	if c.QueryParam("domain") != "" {
+		domID, err = strconv.Atoi(c.QueryParam("domain"))
+		if err != nil {
+			messages.Warning(c, lt.Translate("Invalid domain value given"))
+		} else {
+			op.Var("domain", domID)
+		}
+	}
+
 	err = links.Execute(c.Request().Context(), op, &result)
 	if err != nil {
 		if graphError, ok := err.(*gqlclient.Error); ok {
@@ -1114,16 +1125,43 @@ func (s *Service) ListingList(c echo.Context) error {
 	if c.QueryParam("prev") != "" {
 		slices.Reverse(result.Listings.Result)
 	}
+
+	// Get domain list.
+	opts = &database.FilterOptions{
+		Filter: sq.And{
+			sq.Eq{"d.service": models.DomainServiceList},
+			sq.Eq{"d.status": models.DomainStatusApproved},
+			sq.Eq{"d.is_active": true},
+			sq.Or{
+				sq.And{
+					sq.Eq{"d.level": models.DomainLevelUser},
+					sq.Eq{"d.org_id": org.ID},
+				},
+				sq.And{
+					sq.Eq{"d.level": models.DomainLevelSystem},
+					sq.Eq{"d.org_id": nil},
+				},
+			},
+		},
+		OrderBy: "d.lookup_name",
+	}
+	domains, err := models.GetDomains(c.Request().Context(), opts)
+	if err != nil {
+		return err
+	}
+
 	gmap := gobwebs.Map{
 		"pd":                pd,
 		"org":               org,
 		"navFlag":           "listing",
 		"lists":             result.Listings.Result,
-		"tagFilter":         strings.Replace(tag, ",", ", ", -1),
-		"excludeTagFilter":  strings.Replace(excludeTag, ",", ", ", -1),
+		"tagFilter":         strings.ReplaceAll(tag, ",", ", "),
+		"excludeTagFilter":  strings.ReplaceAll(excludeTag, ",", ", "),
 		"advancedSearch":    true,
 		"queries":           template.URL(queries.Encode()),
 		"autoCompleteOrgID": org.ID,
+		"domains":           domains,
+		"cur_domain":        domID,
 	}
 	if result.Listings.PageInfo.HasPrevPage {
 		gmap["prevURL"] = links.GetPaginationParams(c, "prev", result.Listings.PageInfo.Cursor, "next")
diff --git a/list/routes_test.go b/list/routes_test.go
index 72f30ea..38637a1 100644
--- a/list/routes_test.go
+++ b/list/routes_test.go
@@ -11,6 +11,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
+	"strconv"
 	"strings"
 	"testing"
 
@@ -138,6 +139,44 @@ func TestHandlers(t *testing.T) {
 		c.True(strings.Contains(htmlBody, "Title 2"))
 	})
 
+	t.Run("listing list with domain filter", func(t *testing.T) {
+		httpmock.Activate()
+		defer httpmock.DeactivateAndReset()
+		
+		// Create a domain in the test database
+		dbCtx := test.NewDBContext(srv.DB, "America/Managua")
+		domain := &models.Domain{
+			Name:       "Test List Domain",
+			LookupName: "list.example.com",
+			Level:      models.DomainLevelSystem,
+			Service:    models.DomainServiceList,
+			Status:     models.DomainStatusApproved,
+			IsActive:   true,
+		}
+		err := domain.Store(dbCtx)
+		c.NoError(err)
+
+		jsonResponse, err := httpmock.NewJsonResponder(http.StatusOK, httpmock.File("samples/listing_list.json"))
+		c.NoError(err)
+		httpmock.RegisterResponder("POST", "http://127.0.0.1:8080/query", jsonResponse)
+
+		request := httptest.NewRequest(http.MethodGet, "/:slug/list?domain="+strconv.Itoa(domain.ID), nil)
+		recorder := httptest.NewRecorder()
+		ctx := &server.Context{
+			Server:  srv,
+			Context: e.NewContext(request, recorder),
+			User:    user,
+		}
+		ctx.SetPath("/:slug/list")
+		ctx.SetParamNames("slug")
+		ctx.SetParamValues("personal-org")
+		err = test.MakeRequest(srv, listService.ListingList, ctx)
+		c.NoError(err)
+		c.Equal(http.StatusOK, recorder.Code)
+		htmlBody := recorder.Body.String()
+		c.True(strings.Contains(htmlBody, "list.example.com"))
+	})
+
 	t.Run("listing link manage", func(t *testing.T) {
 		httpmock.Activate()
 		defer httpmock.DeactivateAndReset()
diff --git a/short/routes.go b/short/routes.go
index ebbac75..4c92a39 100644
--- a/short/routes.go
+++ b/short/routes.go
@@ -73,6 +73,8 @@ func (s *Service) LinkShortList(c echo.Context) error {
 		return echo.NotFoundHandler(c)
 	}
 
+	lt := localizer.GetSessionLocalizer(c)
+
 	type GraphQLResponse struct {
 		LinkShorts struct {
 			Result   []models.LinkShort `json:"result"`
@@ -86,13 +88,14 @@ func (s *Service) LinkShortList(c echo.Context) error {
 
 	var result GraphQLResponse
 	op := gqlclient.NewOperation(
-		`query GetLinkShorts($slug: String!, $after: Cursor, $before: Cursor, $tag: String, $excludeTag: String) {
+		`query GetLinkShorts($slug: String!, $after: Cursor, $before: Cursor, $tag: String, $excludeTag: String, $domain: Int) {
 				getLinkShorts(input: {
 						orgSlug: $slug,
 						after: $after,
 						before: $before,
 						tag: $tag,
 						excludeTag: $excludeTag,
+						domainId: $domain,
 					}) {
 					result {
 						id
@@ -139,6 +142,16 @@ func (s *Service) LinkShortList(c echo.Context) error {
 		op.Var("before", c.QueryParam("prev"))
 	}
 
+	var domID int
+	if c.QueryParam("domain") != "" {
+		domID, err = strconv.Atoi(c.QueryParam("domain"))
+		if err != nil {
+			messages.Warning(c, lt.Translate("Invalid domain value given"))
+		} else {
+			op.Var("domain", domID)
+		}
+	}
+
 	err = links.Execute(c.Request().Context(), op, &result)
 	if err != nil {
 		if graphError, ok := err.(*gqlclient.Error); ok {
@@ -147,7 +160,6 @@ func (s *Service) LinkShortList(c echo.Context) error {
 		return err
 	}
 
-	lt := localizer.GetSessionLocalizer(c)
 	pd := localizer.NewPageData(lt.Translate("Short Links"))
 	pd.Data["edit"] = lt.Translate("Edit")
 	pd.Data["next"] = lt.Translate("Next")
@@ -166,21 +178,49 @@ func (s *Service) LinkShortList(c echo.Context) error {
 	pd.Data["exclude_tags"] = lt.Translate("Exclude Tags")
 	pd.Data["apply"] = lt.Translate("Apply")
 	pd.Data["clear"] = lt.Translate("Clear")
+	pd.Data["domain"] = lt.Translate("Domain")
 
 	linkShorts := result.LinkShorts.Result
 	if c.QueryParam("prev") != "" {
 		slices.Reverse(linkShorts)
 	}
+
+	// Get domain list.
+	opts = &database.FilterOptions{
+		Filter: sq.And{
+			sq.Eq{"d.service": models.DomainServiceShort},
+			sq.Eq{"d.status": models.DomainStatusApproved},
+			sq.Eq{"d.is_active": true},
+			sq.Or{
+				sq.And{
+					sq.Eq{"d.level": models.DomainLevelUser},
+					sq.Eq{"d.org_id": org.ID},
+				},
+				sq.And{
+					sq.Eq{"d.level": models.DomainLevelSystem},
+					sq.Eq{"d.org_id": nil},
+				},
+			},
+		},
+		OrderBy: "d.lookup_name",
+	}
+	domains, err := models.GetDomains(c.Request().Context(), opts)
+	if err != nil {
+		return err
+	}
+
 	gmap := gobwebs.Map{
 		"pd":                pd,
 		"links":             linkShorts,
 		"org":               org,
 		"navFlag":           "short",
-		"tagFilter":         strings.Replace(tag, ",", ", ", -1),
-		"excludeTagFilter":  strings.Replace(excludeTag, ",", ", ", -1),
+		"tagFilter":         strings.ReplaceAll(tag, ",", ", "),
+		"excludeTagFilter":  strings.ReplaceAll(excludeTag, ",", ", "),
 		"advancedSearch":    true,
 		"queries":           template.URL(queries.Encode()),
 		"autoCompleteOrgID": org.ID,
+		"domains":           domains,
+		"cur_domain":        domID,
 	}
 
 	if result.LinkShorts.PageInfo.HasPrevPage {
diff --git a/short/routes_test.go b/short/routes_test.go
index 91b1c91..ec708fa 100644
--- a/short/routes_test.go
+++ b/short/routes_test.go
@@ -11,6 +11,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
+	"strconv"
 	"strings"
 	"testing"
 
@@ -112,6 +113,44 @@ func TestHandlers(t *testing.T) {
 		c.Equal(http.StatusOK, recorder.Code)
 	})
 
+	t.Run("short list with domain filter", func(t *testing.T) {
+		httpmock.Activate()
+		defer httpmock.DeactivateAndReset()
+		
+		// Create a domain in the test database
+		dbCtx := test.NewDBContext(srv.DB, "America/Managua")
+		domain := &models.Domain{
+			Name:       "Test Domain",
+			LookupName: "test.example.com",
+			Level:      models.DomainLevelSystem,
+			Service:    models.DomainServiceShort,
+			Status:     models.DomainStatusApproved,
+			IsActive:   true,
+		}
+		err := domain.Store(dbCtx)
+		c.NoError(err)
+
+		jsonResponse, err := httpmock.NewJsonResponder(http.StatusOK, httpmock.File("samples/list_short_list.json"))
+		c.NoError(err)
+		httpmock.RegisterResponder("POST", "http://127.0.0.1:8080/query", jsonResponse)
+
+		request := httptest.NewRequest(http.MethodGet, "/:slug/short?domain="+strconv.Itoa(domain.ID), nil)
+		recorder := httptest.NewRecorder()
+		ctx := &server.Context{
+			Server:  srv,
+			Context: e.NewContext(request, recorder),
+			User:    loggedInUser,
+		}
+		ctx.SetPath("/:slug/short")
+		ctx.SetParamNames("slug")
+		ctx.SetParamValues("personal-org")
+		err = test.MakeRequest(srv, shortService.LinkShortList, ctx)
+		c.NoError(err)
+		c.Equal(http.StatusOK, recorder.Code)
+		htmlBody := recorder.Body.String()
+		c.True(strings.Contains(htmlBody, "test.example.com"))
+	})
+
 	t.Run("short delete", func(t *testing.T) {
 		httpmock.Activate()
 		defer httpmock.DeactivateAndReset()
diff --git a/static/js/advancedsearch.js b/static/js/advancedsearch.js
index 4b228a4..f800ce2 100644
--- a/static/js/advancedsearch.js
+++ b/static/js/advancedsearch.js
@@ -275,6 +275,15 @@ form.addEventListener("submit", function(e) {
         qURL.set("exclude", excludeValue);
     }
 
+    // Handle domain field
+    var domainValue = "";
+    if (form.elements["domain"] !== undefined) {
+        domainValue = form.elements.domain.value;
+        if (domainValue !== "") {
+            qURL.set("domain", domainValue);
+        }
+    }
+
     if (hasQ) {
         if (qValue === "") {
             form.elements.q.disabled = true;
diff --git a/templates/link_short_list.html b/templates/link_short_list.html
index 0a5c81b..9d0f30e 100644
--- a/templates/link_short_list.html
+++ b/templates/link_short_list.html
@@ -9,16 +9,26 @@
     <section id="advanced-search-div" {{if and (not .tagFilter) (not .excludeTagFilter)}}class="d-none"{{end}}>
         <form method="GET" id="advanced-search-form" action="{{reverse "short:link_short_list" .org.Slug}}">
             <div class="row">
-                <div class="col-5">
+                <div class="col-4">
                     <label>{{.pd.Data.include_tags}}</label>
                     <input type="text" name="tag" value="{{.tagFilter}}" class="tag-selector" autocomplete="off"/>
                     <div class="d-none autocomplete-tags"></div>
                 </div>
-                <div class="col-5">
+                <div class="col-3">
                     <label>{{.pd.Data.exclude_tags}}</label>
                     <input type="text" name="exclude" value="{{.excludeTagFilter}}" class="tag-selector" autocomplete="off"/>
                     <div class="d-none autocomplete-tags"></div>
                 </div>
+		<div class="col-3">
+                    <label>{{.pd.Data.domain}}</label>
+                    <select name="domain">
+                      <option value="">---</option>
+		      {{ range .domains }}
+		      <option value="{{ .ID }}"{{ if eq .ID $.cur_domain }} selected{{ end }}>{{ .LookupName }}</option>
+		      {{ end }}
+		    </select>
+                </div>
+
                 <div class="col-2 is-right">
                     <button type="submit" class="button primary is-small advanced-search-btn">{{.pd.Data.apply}}</button>
                     <a href="{{reverse "short:link_short_list" .org.Slug}}" class="button primary is-small advanced-search-btn">{{.pd.Data.clear}}</a>
diff --git a/templates/listing_list.html b/templates/listing_list.html
index 838e598..5605125 100644
--- a/templates/listing_list.html
+++ b/templates/listing_list.html
@@ -9,16 +9,26 @@
     <section id="advanced-search-div" {{if and (not .tagFilter) (not .excludeTagFilter)}}class="d-none"{{end}}>
         <form method="GET" id="advanced-search-form" action="{{reverse "list:listing_list" .org.Slug}}">
             <div class="row">
-                <div class="col-5">
+                <div class="col-4">
                     <label>{{.pd.Data.include_tags}}</label>
                     <input type="text" name="tag" value="{{.tagFilter}}" class="tag-selector" autocomplete="off"/>
                     <div class="d-none autocomplete-tags"></div>
                 </div>
-                <div class="col-5">
+                <div class="col-3">
                     <label>{{.pd.Data.exclude_tags}}</label>
                     <input type="text" name="exclude" value="{{.excludeTagFilter}}" class="tag-selector" autocomplete="off"/>
                     <div class="d-none autocomplete-tags"></div>
                 </div>
+		<div class="col-3">
+                    <label>{{.pd.Data.domain}}</label>
+                    <select name="domain">
+                      <option value="">---</option>
+		      {{ range .domains }}
+		      <option value="{{ .ID }}"{{ if eq .ID $.cur_domain }} selected{{ end }}>{{ .LookupName }}</option>
+		      {{ end }}
+		    </select>
+                </div>
+
                 <div class="col-2 is-right">
                     <button type="submit" class="button primary is-small advanced-search-btn">{{.pd.Data.apply}}</button>
                     <a href="{{reverse "list:listing_list" .org.Slug}}" class="button primary is-small advanced-search-btn">{{.pd.Data.clear}}</a>
-- 
2.49.1

---

From: "Peter Sanchez" <[email-masked]>
Date: Thu, 31 Jul 2025 08:31:24 -0600

Applied.

To [email-masked]:~netlandish/links
   8bec807..6111dea  master -> master