* Validate website_url profile field is a url related to issue #14300 May need a data update script to (fixup? remove?) invalid profiles since not being able to save existing profiles will cause problems. * Check that URI is a valid url Require the scheme to be one of https or http, not something like mailto:// or telnet:// (nobody would do that, but don't try and link to it if they did). * Rubocop fixup for validation rule URI::regexp is obsolete and should not be used. Instead, use URI::DEFAULT_PARSER.make_regexp Prefer %w[] literals for arrays of words Prefer the new style validations `validates :column, format: value` to validates_format_of * Permit empty website_url fields The previous validation was rejecting nil, which was the default. This caused a lot of user factory calls to fail (since users didn't need website urls in the profiles during testing unless the test was about the website url link). * Use :url validation as suggested * Update validation error message The validate_url gem gives a more complete error message to the user. Update the spec to expect this. * Use url_field rather than text_field in profile form https://apidock.com/rails/v6.1.3.1/ActionView/Helpers/FormHelper/url_field * Add data update to either fixup or clear invalid website urls Checking blazer there are about 2600 profiles with "invalid" website urls, typically a hostname, sometimes a hostname + path component, which should be fixed up. Naively add https:// to the front of the url, check that a valid scheme and host are present on the resulting url, and save. If an invalid url is generated (specifically, if host or scheme are nil), just set the website url (with the invalid link) to an empty string. It's possible we'd want to notify users affected by this, that was not included in this pass. * Skip validations for intentionally invalid test cases
169 lines
7.5 KiB
Text
169 lines
7.5 KiB
Text
<%= javascript_packs_with_chunks_tag "colorPreview", "validateFileInputs", "stickySaveFooter", defer: true %>
|
|
|
|
<%= render "users/additional_authentication" %>
|
|
|
|
<%= form_with(url: profile_path(@user.profile_id), method: "put", html: { class: "sticky-footer-form" }) do |f| %>
|
|
|
|
<div class="crayons-card crayons-card--content-rows">
|
|
<h2>User</h2>
|
|
|
|
<div class="crayons-field">
|
|
<%= f.label :name, for: "user[name]", class: "crayons-field__label" %>
|
|
<%= f.text_field "user[name]", maxlength: 30, class: "crayons-textfield", placeholder: "John Doe", value: @user.name %>
|
|
</div>
|
|
|
|
<div class="crayons-field">
|
|
<%= f.label :email, for: "user[email]", class: "crayons-field__label" %>
|
|
<%= f.text_field "user[email]", class: "crayons-textfield", placeholder: "john.doe@example.com", value: @user.email %>
|
|
</div>
|
|
|
|
<div class="crayons-field crayons-field--checkbox">
|
|
<%= f.check_box "users_setting[display_email_on_profile]", class: "crayons-checkbox", checked: @user.setting.display_email_on_profile %>
|
|
<%= f.label :display_email_on_profile, for: "users_setting[display_email_on_profile]", class: "crayons-field__label" %>
|
|
</div>
|
|
|
|
<div class="crayons-field">
|
|
<%= f.label :username, for: "user[username]", class: "crayons-field__label" %>
|
|
<%= f.text_field "user[username]", maxlength: 30, class: "crayons-textfield", placeholder: "johndoe", value: @user.username %>
|
|
</div>
|
|
|
|
<div class="crayons-field">
|
|
<%= f.label :profile_image, for: "user[profile_image]", class: "crayons-field__label" %>
|
|
|
|
<div class="flex items-center">
|
|
<% if @user.profile_image_url.present? %>
|
|
<span class="crayons-avatar crayons-avatar--xl mr-2">
|
|
<img alt="<%= @user.username %> profile image" src="<%= Images::Profile.call(@user.profile_image_url, length: 50) %>" class="crayons-avatar__image" loading="lazy" />
|
|
</span>
|
|
<% end %>
|
|
<%= f.file_field "user[profile_image]", accept: "image/*", class: "crayons-card crayons-card--secondary p-3 flex items-center flex-1 w-100" %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<% profile = @user.profile %>
|
|
|
|
<div class="crayons-card crayons-card--content-rows">
|
|
<h2>Basic</h2>
|
|
|
|
<div class="crayons-field">
|
|
<label class="crayons-field__label" for="profile[website_url]">
|
|
Website URL
|
|
</label>
|
|
<%= f.url_field "profile[website_url]",
|
|
value: profile.website_url,
|
|
placeholder: "https://yoursite.com",
|
|
class: "crayons-textfield js-color-field" %>
|
|
</div>
|
|
|
|
<div class="crayons-field crayons-field--checkbox">
|
|
<%= f.check_box "profile[display_email_on_profile]",
|
|
checked: @user.setting.display_email_on_profile,
|
|
class: "crayons-checkbox" %>
|
|
<label class="crayons-field__label" for="profile[display_email_on_profile]">
|
|
Display email on profile
|
|
</label>
|
|
</div>
|
|
|
|
<div class="crayons-field">
|
|
<label class="crayons-field__label" for="profile[location]">
|
|
Location
|
|
</label>
|
|
<%= f.text_field "profile[location]",
|
|
value: profile.location,
|
|
placeholder: "Halifax, Nova Scotia",
|
|
class: "crayons-textfield js-color-field" %>
|
|
</div>
|
|
|
|
<div class="crayons-field">
|
|
<label class="crayons-field__label" for="profile[summary]">
|
|
Bio
|
|
</label>
|
|
<%= f.text_field "profile[summary]",
|
|
value: profile.summary,
|
|
placeholder: "A short bio...",
|
|
class: "crayons-textfield js-color-field" %>
|
|
</div>
|
|
</div>
|
|
|
|
<% ProfileFieldGroup.non_empty_groups.each do |group| %>
|
|
<% next if group.name == "Basic" # TODO: @citizen428 Remove this after user settings work (email field) %>
|
|
<% next if group.name == "Links" # TODO: [@jacobherrington] Remove this when we drop social links %>
|
|
<% next if group.name == "Branding" # TODO: [@msarit @jacobherrington] May be further refactored later as part of Profiles work %>
|
|
<div class="crayons-card crayons-card--content-rows">
|
|
<h2><%= group.name %></h2>
|
|
<% if group.description.present? %>
|
|
<div class="color-base-60"><%= group.description %></div>
|
|
<% end %>
|
|
|
|
<% group.profile_fields.each do |field| %>
|
|
<% next if field.attribute_name == "display_email_on_profile" %>
|
|
<div class="crayons-field <%= "crayons-field--checkbox" if field.input_type == "check_box" %>">
|
|
<% if field["input_type"] == "check_box" %>
|
|
<%= f.public_send(field["input_type"],
|
|
"profile[#{field.attribute_name}]",
|
|
checked: profile.public_send(field.attribute_name),
|
|
class: "crayons-checkbox") %>
|
|
<label class="crayons-field__label" for="<%= "profile[#{field.attribute_name}]" %>">
|
|
<%= field.label %>
|
|
</label>
|
|
<% else %>
|
|
<label class="crayons-field__label" for="<%= "profile[#{field.attribute_name}]" %>">
|
|
<%= field.label %>
|
|
</label>
|
|
<%= f.public_send(field["input_type"],
|
|
"profile[#{field.attribute_name}]",
|
|
value: profile.public_send(field.attribute_name),
|
|
placeholder: field["placeholder_text"],
|
|
class: "crayons-textfield") %>
|
|
<% end %>
|
|
<% if field.description.present? %>
|
|
<p class="crayons-field__description"><%= field.description %></p>
|
|
<% end %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
<% end %>
|
|
|
|
<% users_setting = @user.setting %>
|
|
<div class="crayons-card crayons-card--content-rows">
|
|
<h2>Branding</h2>
|
|
<div class="crayons-field ">
|
|
<label class="crayons-field__label" for="users_setting[brand_color1]">
|
|
Brand color 1
|
|
</label>
|
|
<div class="flex items-center w-100 m:w-50">
|
|
<%= f.public_send("text_field", "users_setting[brand_color1]",
|
|
value: users_setting.public_send("brand_color1"),
|
|
placeholder: "#000000",
|
|
class: "crayons-textfield js-color-field") %>
|
|
<%= f.public_send("color_field",
|
|
"users_setting[brand_color1]",
|
|
value: users_setting.public_send("brand_color1"),
|
|
class: "crayons-color-selector js-color-field ml-2") %>
|
|
</div>
|
|
<p class="crayons-field__description">Used for backgrounds, borders etc.</p>
|
|
</div>
|
|
|
|
<div class="crayons-field ">
|
|
<label class="crayons-field__label" for="users_setting[brand_color1]">
|
|
Brand color 2
|
|
</label>
|
|
<div class="flex items-center w-100 m:w-50">
|
|
<%= f.public_send("text_field", "users_setting[brand_color2]",
|
|
value: users_setting.public_send("brand_color2"),
|
|
placeholder: "#000000",
|
|
class: "crayons-textfield js-color-field") %>
|
|
<%= f.public_send("color_field",
|
|
"users_setting[brand_color2]",
|
|
value: users_setting.public_send("brand_color2"),
|
|
class: "crayons-color-selector js-color-field ml-2") %>
|
|
</div>
|
|
<p class="crayons-field__description">Used for texts (usually put on Brand color 1).</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="save-footer crayons-card crayons-card--content-rows">
|
|
<button type="submit" class="crayons-btn">Save Profile Information</button>
|
|
</div>
|
|
<% end %>
|