Received: from mail.netlandish.com (mail.netlandish.com [174.136.98.166]) by code.netlandish.com (Postfix) with ESMTP id 10B7111B4 for <~netlandish/links-dev@lists.code.netlandish.com>; Thu, 31 Jul 2025 14:29:11 +0000 (UTC) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.217.47; helo=mail-vs1-f47.google.com; envelope-from=peter@netlandish.com; receiver= Authentication-Results: mail.netlandish.com; dkim=pass (1024-bit key; unprotected) header.d=netlandish.com header.i=@netlandish.com header.b=I2HXv9rE Received: from mail-vs1-f47.google.com (mail-vs1-f47.google.com [209.85.217.47]) by mail.netlandish.com (Postfix) with ESMTP id 08B231D640A for <~netlandish/links-dev@lists.code.netlandish.com>; Thu, 31 Jul 2025 14:29:57 +0000 (UTC) Received: by mail-vs1-f47.google.com with SMTP id ada2fe7eead31-4fc19b5fd8cso124173137.2 for <~netlandish/links-dev@lists.code.netlandish.com>; Thu, 31 Jul 2025 07:29:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netlandish.com; s=google; t=1753972197; x=1754576997; darn=lists.code.netlandish.com; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=zOLPkD9h6s4X08xK/q2KLrSDh28ohl+v7j4/u3HfmdM=; b=I2HXv9rEFQarm9C46IL89OtmFgTKlgY+m4uBK0j6ZtRQaZg4FNYdi5gm6ZSgqmlNhP DxOCN8dARmzCSCKfFXgu/qsuAjkOqqf5X3moPwxsc6OkBXFGa+bmMrdzwYbVMFJ3FL4T Z4wjNOpPk7tkxjR4mgyAx5zxPiAdftZBTCBBk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1753972197; x=1754576997; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=zOLPkD9h6s4X08xK/q2KLrSDh28ohl+v7j4/u3HfmdM=; b=OAn9FuaqS1hh4Ueop0gMvVc0HhaHBueVt/FPy+ryQxtq7HWlIRuFtLJD9IQHEeoN68 ZKr21gNQR/H0wk6sQUZBaXPIKl1vI82+8+UxXeqPHl3YYdLUh42lir5/IXA7MK1fluA5 8K+D3aXhO5LcEcHRgmk358p8IzD8SsoBEmH3wFYcI6lxiKVmXushktnx9bapsriHrhPg oKmfMM+JGk3NhSQuD78mB8MWsrGGQ9CGreUoSiG0PVD+wEmSsqSUyLOJc+7esz7YpxOY dhmGLRhvjmTfLSiGzNz1z3OzwBRlcXQXiSx1XBDitNN7nwZsLUGfytKcZWLm5K+j6YQW p63w== X-Gm-Message-State: AOJu0YygVw1NMHhmVnbWdfg/adVh9HgdOmI3fSjDd6K2GZEIpmQg6IgJ 8lz9ByN7hx+kbAd8L078Po9Gj+XeWaj6D4RaHcJSgHckHpumqiertqlqmuC/BIVHRkqousrvob5 lfA5928183A== X-Gm-Gg: ASbGncvKlKGJAsAe9UQBLdkCrtFrVP3mdC9Dlh063Sqxr5MjeWezL7CMnLEMai3pZRn nuZ/u9OBT25MNTXO+shGjlt2Gm/0EtWVka85MLUm27sIq9QnihhS9y2PM0JsNS0JiSZVM5XjUK1 ED3pi7UkN6l4su+kf+6705jAoABKn2atdmPkSbm0+gWsm7CSCquH3yEHnsAWq/nX2whoAFJS252 iMt6HAti+T+Tffd99ycbdPzOXPtPsmSTJfu39J3hk3/R3NyUeNm2USymCdgxB2l0mv9x/Yp14xr aY+ikommzPTQOdv+e3oATqNSIwRP0N0nKLFah60mVKuXD790XQExLqyzj69u5uURv1qzzeSRkZ6 LmkIG4Kncm/ChZTExHitizcMBgx6LhjoK1g== X-Google-Smtp-Source: AGHT+IErNc+r71EWa++bq1QUESrOy3hU5GEP543pWfhWJzuxyPxWnls6BwpmnUiicijWSnnH5IMAvA== X-Received: by 2002:a05:6102:2acf:b0:4f1:7946:ed52 with SMTP id ada2fe7eead31-4fbe7f8691dmr5203092137.12.1753972195992; Thu, 31 Jul 2025 07:29:55 -0700 (PDT) Received: from localhost ([2803:2d60:1107:87f:d66b:baf5:556e:7f73]) by smtp.gmail.com with UTF8SMTPSA id a1e0cc1a2514c-88d8f34b3f0sm401072241.11.2025.07.31.07.29.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 31 Jul 2025 07:29:55 -0700 (PDT) From: Peter Sanchez To: ~netlandish/links-dev@lists.code.netlandish.com Cc: Peter Sanchez Subject: [PATCH links] Adding filtering by domain to short links and link listings. Date: Thu, 31 Jul 2025 08:29:49 -0600 Message-ID: <20250731142951.31235-1-peter@netlandish.com> X-Mailer: git-send-email 2.49.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 @@
-
+
-
+
+
+ + +
+
{{.pd.Data.clear}} 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 @@
-
+
-
+
+
+ + +
+
{{.pd.Data.clear}} -- 2.49.1