-
-
Notifications
You must be signed in to change notification settings - Fork 725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable setting a customized user guide link in general settings #2686
Enable setting a customized user guide link in general settings #2686
Conversation
8a250d0
to
030730b
Compare
@@ -8,6 +8,7 @@ module GeneralSettingsEditPreferences | |||
def edit | |||
super | |||
@preferences_general << :bugherd_api_key | |||
@preferences_general << :user_guide_link |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this, should I create a method below to fill @preferences_general
and avoid these two lines ? Or something else ?
@@ -0,0 +1,22 @@ | |||
require 'spec_helper' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also not sure about where to put this file. I treated it as a feature test, is that correct ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's fine. If you wanted to test the whole feature, you would visit the root path /
and test if the URL of the link is correct. That would be more apt for a feature test.
@@ -4,6 +4,9 @@ | |||
# we can allow to be modified in the UI by adding appropriate form | |||
# elements to existing or new configuration pages. | |||
|
|||
# General Preferences | |||
preference :user_guide_link, :string, default: nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I add a default user guide link (http://www.openfoodnetwork.org/platform/user-guide/ for example). Right now if no link is provided, it just links to the current page. @RachL what do you think ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please add a default user guide to stay backwards compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, can we put this config entry on the content_configuration, below footer_about_url?
We should avoid putting more entries on this general config page if possible.
@RachL would it be ok what Luis said ? Put it in the content section |
@luisramos0 do you mean here : blabla/admin/content/edit ? |
I think that's what he means yes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work. Like @luisramos0 I would like to see this link field under Settings / Content.
@@ -4,6 +4,9 @@ | |||
# we can allow to be modified in the UI by adding appropriate form | |||
# elements to existing or new configuration pages. | |||
|
|||
# General Preferences | |||
preference :user_guide_link, :string, default: nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please add a default user guide to stay backwards compatible.
@@ -0,0 +1,22 @@ | |||
require 'spec_helper' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's fine. If you wanted to test the whole feature, you would visit the root path /
and test if the URL of the link is correct. That would be more apt for a feature test.
030730b
to
82eeb6b
Compare
@mkllnk @RachL @luisramos0 I moved it to content config and tests in |
@@ -9,7 +9,8 @@ def edit | |||
{name: I18n.t('admin.contents.edit.main_links'), preferences: [:menu_1, :menu_1_icon_name, :menu_2, :menu_2_icon_name, :menu_3, :menu_3_icon_name, :menu_4, :menu_4_icon_name, :menu_5, :menu_5_icon_name, :menu_6, :menu_6_icon_name, :menu_7, :menu_7_icon_name]}, | |||
{name: I18n.t('admin.contents.edit.footer_and_external_links'), preferences: [:footer_logo, | |||
:footer_facebook_url, :footer_twitter_url, :footer_instagram_url, :footer_linkedin_url, :footer_googleplus_url, :footer_pinterest_url, | |||
:footer_email, :community_forum_url, :footer_links_md, :footer_about_url]}] | |||
:footer_email, :community_forum_url, :footer_links_md, :footer_about_url]}, | |||
{name: I18n.t('admin.contents.edit.user_guide'), preferences: [:user_guide_link]}] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This #edit
is getting hairy and hard to read. Honestly, I find it hard to understand what you just did. What about splitting these preference sections into objects that return each of this individual hashes and then we simply merge them into an array here? that is an approach that served me well in the past. Something like (I haven't tried it, but it should work ):
# app/models/preference_sections/user_guide_section.rb
class UserGuideSection
def name
I18n.t('admin.contents.edit.user_guide')
end
def preferences
[:user_guide_link]
end
end
# app/controllers/admin/contents_controller.rb
module Admin
class ContentsController < Spree::Admin::BaseController
def edit
@preference_sections = preference_sections.map do |preference_section|
{ name: preference_section.name, preferences: preference_section.preferences }
end
end
private
# Returns an array with the instances of preference sections, which all respond to #name and #preferences.
def preference_sections
Dir["models/preference_sections/**/*.rb"].map do |filename|
basename = File.basename(filename, '.rb')
basename.camelize.constantize.new
end
end
end
This makes it really easy to add, remove and change sections/preferences. And keep adding them all the time (whether they should be preferences in the UI or config settings in ofn_install it's another topic).
spec/features/admin/content_spec.rb
Outdated
click_button 'Update' | ||
|
||
expect(page).to have_content 'Your content has been successfully updated!' | ||
expect(ContentConfig.user_guide_link).to eq 'http://www.openfoodnetwork.org/platform/user-guide/' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
being this a feature spec, this expectation shouldn't be here because it belongs to a deeper testing level (unit? something in between?). It does not exert the UI but a class. If line 50 passes, is because ContentConfig
worked. I would simply remove it because Spree::Preferences::FileConfiguration
is already tested by Spree.
82eeb6b
to
cc43d78
Compare
@sauloperez your solution works great ! It is cleaner indeed. Thoughts ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! This is so much better. I love it when a pull request is not just changing, but improving the code. :-D
I commented on two things I would change. They are not a big deal, but it would be nice to make it perfect. :-)
def preference_sections | ||
Dir["app/models/preference_sections/*.rb"].map do |filename| | ||
basename = 'PreferenceSections::' + File.basename(filename, '.rb').camelize | ||
basename.constantize.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very clever. But I would prefer it more explicit. The problems I see:
- From the code I can't see what is loaded. I need to go to the directory to find out.
- I can't navigate to a section declaration using my IDE.
- The dependency on these classes cannot be detected automatically.
- One file not following the file name / class name convention breaks the code (class not found).
- We cannot define the order or the sections here. They may appear random depending on the file system.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to give another opinion, let me answer these questions:
From the code I can't see what is loaded. I need to go to the directory to find out.
Like anything in an Object-oriented system. And that's a great benefit; you can read what the code does at an abstract level to understand how an algorithm works. You can get into detail if you need to by reading the objects' implementations.
I can't navigate to a section declaration using my IDE.
Indeed that is a con, but there's no direct reference to a particular section so checking the dir you'll see the section object you are interested in. No a big deal with so simple objects.
The dependency on these classes cannot be detected automatically.
Probably the biggest downside. We just have the call to Dir
which won't be automatically detected.
One file not following the file name / class name convention breaks the code (class not found).
The file convention is being *.rb
as shown in line 27. As for the class name, any name under that namespace will be picked. So unless you change this method or you don't declare the new class under the PreferenceSections
namespace any will work.
We cannot define the order or the sections here. They may appear random depending on the file system.
Easy to fix by using sort_by
with a method each section object declares, and that could be even more explicit than a big array as we have now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot define the order or the sections
Easy to fix by using sort_by with a method each section object declares, and that could be even more explicit than a big array as we have now.
Adding something like priority levels to the sections so that they can be sorted creates a dependency between the sections. I can't change the position of one section without knowing the positions of all other sections. A list (array) solves this very well.
The file convention is being *.rb
- The file needs to have the same name as the class it contains. (This fails for class names containing
API
orURL
unless we name the filesa_p_i
andu_r_l
.) - They need to be in that directory. (You can't have them somewhere else and you can't have another rb file in that directory.)
These conventions are not a big deal, but I don't see any need for this flexibility here. It's a trade-off between having more code (but stupid code) and some auto-loading algorithm relying on conventions. In this case I voted for the dumb array, because it solves the sorting as well.
app/models/content_configuration.rb
Outdated
@@ -69,4 +69,7 @@ class ContentConfiguration < Spree::Preferences::FileConfiguration | |||
EOS | |||
|
|||
preference :footer_about_url, :string, default: "http://www.openfoodnetwork.org/ofn-local/open-food-network-australia/" | |||
|
|||
#User Guide | |||
preference :user_guide_link, :string, default: 'http://www.openfoodnetwork.org/platform/user-guide/' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just followed that link and the current URL is https://guide.openfoodnetwork.org/. We should use that here.
def preference_sections | ||
[ | ||
PreferenceSections::HeaderSection.new, | ||
PreferenceSections::HomePageSection.new, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mkllnk something like this ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I probably would have omitted the new
here and called it somewhere else to reduce code duplication and separate the two concerns "list the sections" and "initialise a section to use it". But I'm happy with this.
PreferenceSections::GroupSignupPageSection.new, | ||
PreferenceSections::MainLinksSection.new, | ||
PreferenceSections::FooterAndExternalLinksSection.new, | ||
PreferenceSections::UserGuideSection.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this misses a bit the point and violates Open-closed principle (sorry, I think the buzzword is relevant in this context), but it is still better than it was, so 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay so it should be open to extension and closed to change, right?
View one
Closed to change means that I'm not allowed to change a file. Adding a file is an extension and good. So we just have files following a convention and auto-load them.
View two
Classes, files, directories are all data structures. Adding a section is just adding a line here. That's extension, not modification. And if you add a file to a directory, you modify that directory as well. In the end, we want to change the list of sections here and insert one particular section at a certain position. This code makes that really clear.
def preference_sections | ||
[ | ||
PreferenceSections::HeaderSection.new, | ||
PreferenceSections::HomePageSection.new, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I probably would have omitted the new
here and called it somewhere else to reduce code duplication and separate the two concerns "list the sections" and "initialise a section to use it". But I'm happy with this.
PreferenceSections::GroupSignupPageSection.new, | ||
PreferenceSections::MainLinksSection.new, | ||
PreferenceSections::FooterAndExternalLinksSection.new, | ||
PreferenceSections::UserGuideSection.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay so it should be open to extension and closed to change, right?
View one
Closed to change means that I'm not allowed to change a file. Adding a file is an extension and good. So we just have files following a convention and auto-load them.
View two
Classes, files, directories are all data structures. Adding a section is just adding a line here. That's extension, not modification. And if you add a file to a directory, you modify that directory as well. In the end, we want to change the list of sections here and insert one particular section at a certain position. This code makes that really clear.
def preference_sections | ||
Dir["app/models/preference_sections/*.rb"].map do |filename| | ||
basename = 'PreferenceSections::' + File.basename(filename, '.rb').camelize | ||
basename.constantize.new |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot define the order or the sections
Easy to fix by using sort_by with a method each section object declares, and that could be even more explicit than a big array as we have now.
Adding something like priority levels to the sections so that they can be sorted creates a dependency between the sections. I can't change the position of one section without knowing the positions of all other sections. A list (array) solves this very well.
The file convention is being *.rb
- The file needs to have the same name as the class it contains. (This fails for class names containing
API
orURL
unless we name the filesa_p_i
andu_r_l
.) - They need to be in that directory. (You can't have them somewhere else and you can't have another rb file in that directory.)
These conventions are not a big deal, but I don't see any need for this flexibility here. It's a trade-off between having more code (but stupid code) and some auto-loading algorithm relying on conventions. In this case I voted for the dumb array, because it solves the sorting as well.
Testing Notes
https://docs.google.com/document/d/1uqQcthv0-sL4MsNrNCfKr9QdteQpJRqhsPZe_jYpjLo/edit# |
What? Why?
Closes #2593 #2631
In configuration > general settings, a field is available to add an external link for the user guide.
What should we test?
A superadmin can add a custom user guide link.
Non superadmins can't.
Release notes
An admin can now add a custom user guide link in Configuration > General Settings.
Changelog Category: Added
Dependencies
This adds customizations to Spree::Config.
Documentation updates
There could be a line added where this new feature is mentioned but I'm not sure where to put it.