Skip to content

Commit

Permalink
DEV: Migrate social_links theme setting to new objects setting type
Browse files Browse the repository at this point in the history
This commit migrates the `social_links` theme setting to `type: objects`. Since [discourse/discourse@a440e15](discourse/discourse@a440e15), we have started to support objects typed theme setting so we are switching this theme component to use it instead as it provides a much better UX for configuring the settings required for the theme component.
  • Loading branch information
tgxworld committed May 3, 2024
1 parent 6242bac commit e847b8f
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 31 deletions.
8 changes: 4 additions & 4 deletions javascripts/discourse/components/custom-footer.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,15 @@
</div>

<div class="social">
{{#each this.socialLinks as |link|}}
{{#each (theme-setting "social_links") as |link|}}
<a
class="social-link"
data-easyfooter-social-link={{link.dataName}}
data-easyfooter-social-link={{dasherize link.text}}
title={{link.title}}
target={{link.target}}
href={{link.href}}
href={{link.url}}
>
{{d-icon link.icon}}
{{d-icon link.icon_name}}
</a>
{{/each}}
</div>
Expand Down
22 changes: 0 additions & 22 deletions javascripts/discourse/components/custom-footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,4 @@ export default class extends Component {
target,
};
});

socialLinks = settings.social_links
.split("|")
.filter(Boolean)
.map((link) => {
const fragments = link.split(",").map((fragment) => fragment.trim());
const text = fragments[0];
const dataName = dasherize(text);
const title = fragments[1];
const href = fragments[2];
const target = fragments[3] === "blank" ? "_blank" : "";
const icon = fragments[4].toLowerCase();

return {
text,
dataName,
title,
href,
target,
icon,
};
});
}
21 changes: 20 additions & 1 deletion locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,27 @@ en:
description: "Add links to link sections. One item per line in this order:<br>Parent, text, URL, target, title, referrer policy<br>It is a good idea to keep the number of links under each section similar<br><b>Parent:</b> the name of the parent section which this link shows under. Use the `text` value from the list above<br><b>Text:</b> the text that shows for this link<br><b>URL:</b> the path this item links to. You can use relative paths as well.<br><b>Target:</b> Choose whether this item will open in a new tab or in the same tab. Use blank to open the link in a new tab, or use self to open it in the same tab.<br><b>Title:</b> the text that shows when the link is hovered.<br/><b>Referrer Policy:</b> the referrer policy to use in the link."
small_links:
description: "You can add small links at the bottom of the footer like Terms of Service and Privacy. One item per line in this order:<br>Text, URL, target<br><b>Text:</b> The text that shows for the small link<br><b>URL:</b> The path of the link<br><b>Target:</b> Use blank to open the link in a new tab and use self to open it in the same tab"

social_links:
description: "Enter the social links you'd like to add to the footer in this format:<br> provider, title, URL, target<br><b>Provider:</b> is the name of the provider like Facebook or Twitter<br><b>Title:</b> The text that shows when the link is hovered<br><b>URL:</b> The path you'd like the link to have<br><b>Target:</b> Use blank to open the link in a new tab and use self to open it in the same tab<br><b>Icon:</b> use a FontAwesome5 icon name (brand icons need a 'fab-' prefix)."
description: "Social links you'd like to add to the footer"
schema:
properties:
text:
label: Text
description: Text to be displayed for the link
title:
label: Title
description: The title attribute of the link
url:
label: URL
description: The URL the link points to
target:
label: Target
description: The target attribute of the link
icon_name:
label: Icon Name
description: FontAwesome5 icon name (brand icons need a 'fab-' prefix)

show_footer_on_login_required_page:
description: "Check this setting if you want the footer to be displayed on the login-required page (only applies if your site is private)"
svg_icons:
Expand Down
45 changes: 45 additions & 0 deletions migrations/settings/0004-migrate-social-links-setting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
export default function migrate(settings, helpers) {
const oldSocialLinks = settings.get("social_links");

if (oldSocialLinks) {
const newSocialLinks = [];

oldSocialLinks.split("|").forEach((oldSocialLink) => {
const [linkText, linkTitle, linkUrl, linkTarget, linkIcon] = oldSocialLink
.split(",")
.map((value) => value.trim());

if (linkText) {
const newLink = {
text: linkText,
};

if (linkTitle) {
newLink.title = linkTitle.substring(0, 1000);
}

if (linkUrl && helpers.isValidUrl(linkUrl) && linkUrl.length <= 2048) {
newLink.url = linkUrl;
} else {
newLink.url = "#";
}

if (linkTarget === "self") {
newLink.target = "_self";
} else {
newLink.target = "_blank";
}

if (linkIcon && linkIcon.length <= 200) {
newLink.icon_name = linkIcon.toLowerCase();
}

newSocialLinks.push(newLink);
}
});

settings.set("social_links", newSocialLinks);
}

return settings;
}
55 changes: 52 additions & 3 deletions settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,58 @@ small_links:
default: "Privacy, #, self|Terms of service, #, self| About, #, self"

social_links:
type: list
list_type: simple
default: "Facebook, Join us on Facebook, #, blank,fab-facebook|Twitter, show some love on Twitter, #, blank,fab-twitter| Youtube, Check out our latest videos on Youtube, #, blank,fab-youtube"
type: objects
default:
- text: Facebook
title: Join us on Facebook
url: "#"
target: _blank
icon_name: fab-facebook
- text: Twitter
title: Show some love on Twitter
url: "#"
target: _blank
icon_name: fab-twitter
- text: Youtube
title: Check out our latest videos on Youtube
url: "#"
target: _blank
icon_name: fab-youtube
schema:
name: social link
identifier: text
properties:
text:
type: string
required: true
validations:
min_length: 1
max_length: 1000
title:
type: string
validations:
min_length: 1
max_length: 1000
url:
type: string
required: true
validations:
min_length: 1
max_length: 2048
url: true
target:
type: string
default: _blank
choices:
- _blank
- _self
- _parent
- _top
icon_name:
type: string
validations:
min_length: 1
max_length: 200

show_footer_on_login_required_page:
default: true
Expand Down
199 changes: 199 additions & 0 deletions spec/migrations/0004_migrate_social_links_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# frozen_string_literal: true

RSpec.describe "0004-migrate-social-links-setting migration" do
let!(:theme) { upload_theme_component }

it "does not migrate links which do not have a text property" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value: " ,some title, /some/url",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq([])
end

it "should migrate title property correctly if previous title property is valid" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value: "Some Text, Some Title",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq(
[{ "text" => "Some Text", "title" => "Some Title", "url" => "#", "target" => "_blank" }],
)
end

it "should truncate title property to 1000 chars if previous title property is more than 1000 chars" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value: "Some Text, #{"a" * 1001}",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq(
[{ "text" => "Some Text", "title" => "#{"a" * 1000}", "url" => "#", "target" => "_blank" }],
)
end

it "should set URL property to `#` if previous URL property is invalid, empty or is more than 2048 chars" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value:
"Some Text, Some Title|Some Text 2, Some Title 2, not a URL|Some Text 3, Some Title 3, #{"a" * 2049}",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq(
[
{ "text" => "Some Text", "title" => "Some Title", "url" => "#", "target" => "_blank" },
{ "text" => "Some Text 2", "title" => "Some Title 2", "url" => "#", "target" => "_blank" },
{ "text" => "Some Text 3", "title" => "Some Title 3", "url" => "#", "target" => "_blank" },
],
)
end

it "should migrate URL property correctly if previous URL property is valid" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value: "Some Text, Some Title, /some/url|Some Text 2, Some Title 2, http://example.com",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq(
[
{
"text" => "Some Text",
"title" => "Some Title",
"url" => "/some/url",
"target" => "_blank",
},
{
"text" => "Some Text 2",
"title" => "Some Title 2",
"url" => "http://example.com",
"target" => "_blank",
},
],
)
end

it "sets target property to `_self` if previous target property is `self`" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value: "Some Text, Some Title, /some/url, self",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq(
[
{
"text" => "Some Text",
"title" => "Some Title",
"url" => "/some/url",
"target" => "_self",
},
],
)
end

it "does not set target property if previous target property is invalid or empty" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value:
"Some Text, Some Title, /some/url|Some Text 2, Some Title 2, http://example.com, not a target",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq(
[
{
"text" => "Some Text",
"title" => "Some Title",
"url" => "/some/url",
"target" => "_blank",
},
{
"text" => "Some Text 2",
"title" => "Some Title 2",
"url" => "http://example.com",
"target" => "_blank",
},
],
)
end

it "does not set icon_name property if previous icon_name property is empty or more than 200 chars" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value:
"Some Text, Some Title, /some/url, self|Some Text 2, Some Title 2, http://example.com, self, #{"a" * 201}",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq(
[
{
"text" => "Some Text",
"title" => "Some Title",
"url" => "/some/url",
"target" => "_self",
},
{
"text" => "Some Text 2",
"title" => "Some Title 2",
"url" => "http://example.com",
"target" => "_self",
},
],
)
end

it "sets the icon_name property correctly if previous icon_name property is present" do
theme.theme_settings.create!(
name: "social_links",
theme:,
data_type: ThemeSetting.types[:string],
value: "Some Text, Some Title, /some/url, self, some-icon",
)

run_theme_migration(theme, "0004-migrate-social-links-setting")

expect(theme.settings[:social_links].value).to eq(
[
{
"text" => "Some Text",
"title" => "Some Title",
"url" => "/some/url",
"target" => "_self",
"icon_name" => "some-icon",
},
],
)
end
end
2 changes: 1 addition & 1 deletion spec/system/footer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
)

expect(page).to have_css(
"a.social-link[data-easyfooter-social-link='twitter'][title='show some love on Twitter'][href='#'][target='_blank'] .d-icon-fab-twitter",
"a.social-link[data-easyfooter-social-link='twitter'][title='Show some love on Twitter'][href='#'][target='_blank'] .d-icon-fab-twitter",
)

expect(page).to have_css(
Expand Down

0 comments on commit e847b8f

Please sign in to comment.