Various improvements (#332)

* Fix locale fallbacks
* Make header links relative
* Improve like button style
* Other small improvements...
This commit is contained in:
Riccardo Graziosi
2024-05-09 19:23:45 +02:00
committed by GitHub
parent a292b133b0
commit 747483cfa3
32 changed files with 115 additions and 61 deletions

View File

@@ -4,27 +4,15 @@
.flex-column,
.mr-3;
$like_button_size: 11px;
.likeButton {
@extend .mb-2;
border-left: $like_button_size solid transparent;
border-right: $like_button_size solid transparent;
border-bottom: $like_button_size solid rgba(35,35,35,.2);
&:hover {
border-bottom-color: var(--primary-color);
cursor: pointer;
}
}
.likeButton.liked {
border-bottom-color: var(--primary-color);
.likeButton:hover {
cursor: pointer;
transform: scale(1.15);
}
.likeCountLabel {
@extend .mt-2;
text-align: center;
font-size: 17px;
font-size: 20px;
}
}

View File

@@ -19,6 +19,9 @@ class ApplicationController < ActionController::Base
end
def load_tenant_data
# Set default locale
I18n.locale = I18n.default_locale
current_tenant = get_tenant_from_request(request)
return unless current_tenant
@@ -38,7 +41,7 @@ class ApplicationController < ActionController::Base
@tenant_billing = TenantBilling.first_or_create
@boards = Board.select(:id, :name, :slug).order(order: :asc)
# Setup locale
# Set tenant locale
I18n.locale = @tenant.locale
end

View File

@@ -172,6 +172,7 @@ class BillingController < ApplicationController
@tenant_setting = @tenant.tenant_setting
@tenant_billing = @tenant.tenant_billing
@boards = Board.select(:id, :name, :slug).order(order: :asc)
@header_full_urls = true
I18n.locale = @tenant.locale
# needed because signing out from 'billing' subdomain cause authenticity token error

View File

@@ -7,7 +7,7 @@ class TenantsController < ApplicationController
def new
@page_title = "Create your feedback space"
@o_auths = OAuth.unscoped.where(tenant_id: nil, is_enabled: true)
@o_auths = OAuth.unscoped.where(tenant_id: nil, is_enabled: true).order(created_at: :asc)
end
def show
@@ -102,7 +102,7 @@ class TenantsController < ApplicationController
# Given a new_subdomain
# Returns true if it is available, false otherwise
def is_available
subdomain = params[:new_subdomain]
subdomain = params[:new_subdomain].downcase
return unless subdomain.present?
return if RESERVED_SUBDOMAINS.include?(subdomain)

View File

@@ -44,7 +44,7 @@ const Return = ({ tenantBilling, homeUrl, billingUrl }: Props) => {
if (status === 'complete') {
return (
<Box customClass="billingContainer">
<h2>Success</h2>
<h2>Success!</h2>
<p>Thank you for choosing Astuto! Your subscription will be activated shortly.</p>
<ActionLink onClick={() => window.location.href = homeUrl} icon={<BackIcon />}>

View File

@@ -1,4 +1,5 @@
import * as React from 'react';
import { LikeIcon, SolidLikeIcon } from '../common/Icons';
interface Props {
postId: number;
@@ -35,6 +36,7 @@ const LikeButtonP = ({
className={`likeButton${liked ? ' liked' : ''}`}
hidden={!showLikeButton}
>
{ liked ? <SolidLikeIcon /> : <LikeIcon />}
</div>
{ showLikeCount && <span className="likeCountLabel">{likeCount}</span> }
</div>

View File

@@ -119,6 +119,7 @@ const OAuthForm = ({
<label htmlFor="logo">{ getLabel('o_auth', 'logo') }</label>
<input
{...register('logo')}
placeholder='https://example.com/logo.png'
id="logo"
className="formControl"
/>

View File

@@ -133,6 +133,7 @@ const GeneralSiteSettingsP = ({
<label htmlFor="siteLogo">{ getLabel('tenant', 'site_logo') }</label>
<input
{...register('siteLogo')}
placeholder='https://example.com/logo.png'
id="siteLogo"
className="formControl"
/>

View File

@@ -45,6 +45,9 @@ const TenantSignUpForm = ({
<div className="formRow">
<div className="input-group">
<div className="input-group-prepend">
<div className="input-group-text">https://</div>
</div>
<input
{...register('subdomain', {
required: true,
@@ -57,7 +60,7 @@ const TenantSignUpForm = ({
},
},
})}
placeholder={getLabel('tenant', 'subdomain')}
placeholder={getLabel('tenant', 'subdomain').toLowerCase()}
id="tenantSubdomain"
className="formControl"
/>

View File

@@ -9,6 +9,7 @@ import { MdContentCopy, MdDone, MdOutlineArrowBack } from 'react-icons/md';
import { GrTest, GrClearOption } from 'react-icons/gr';
import { MdOutlineLibraryBooks } from "react-icons/md";
import { MdVerified } from "react-icons/md";
import { BiLike, BiSolidLike } from "react-icons/bi";
export const EditIcon = () => <FiEdit />;
@@ -38,4 +39,8 @@ export const StaffIcon = () => (
</span>
);
export const ClearIcon = () => <GrClearOption />;
export const ClearIcon = () => <GrClearOption />;
export const LikeIcon = ({size = 32}) => <BiLike size={size} />;
export const SolidLikeIcon = ({size = 32}) => <BiSolidLike size={size} />;

View File

@@ -14,7 +14,7 @@ export interface IOAuth {
callbackUrl?: string;
tenantId?: number;
defaultOAuthIsEnabled: boolean;
defaultOAuthIsEnabled?: boolean;
}
export interface IOAuthJSON {
@@ -33,7 +33,7 @@ export interface IOAuthJSON {
callback_url?: string;
tenant_id?: string;
default_o_auth_is_enabled: boolean;
default_o_auth_is_enabled?: boolean;
}
export const oAuthJSON2JS = (oAuthJSON: IOAuthJSON): IOAuth => ({

View File

@@ -2,6 +2,8 @@ import I18n from "i18n-js"
I18n.translations = <%= I18n::JS.filtered_translations.to_json %>
I18n.locale = LOCALE
I18n.defaultLocale = "en"
I18n.fallbacks = <%= Rails.env.production? ? true : false %>
I18n.pluralization["zh-CN"] = function(count) { return ["other"] }
I18n.pluralization["vi"] = function(count) { return ["other"] }

View File

@@ -6,7 +6,13 @@ class ApplicationMailer < ActionMailer::Base
def set_mail_from_for_multitenancy
if Rails.application.multi_tenancy?
from = "#{Current.tenant_or_raise!.site_name} <#{ENV.fetch('EMAIL_MAIL_FROM', 'notifications@astuto.io')}>"
from = "#{Current.tenant.site_name} <#{ENV.fetch('EMAIL_MAIL_FROM', 'notifications@astuto.io')}>"
# Set a specific 'from' for the Devise::Mailer#confirmation_instructions method on tenant signup
if self.class.name == "Devise::Mailer" && action_name == "confirmation_instructions" && Current.tenant.users.count == 1
from = "Astuto <#{ENV.fetch('EMAIL_MAIL_FROM', 'notifications@astuto.io')}>"
end
mail.from = from
end
end

View File

@@ -1,6 +1,7 @@
class TenantMailer < ApplicationMailer
layout :choose_layout
skip_after_action :set_mail_from_for_multitenancy
before_action :set_locale_to_english
def trial_start(tenant:)
@tenant = tenant
@@ -20,7 +21,7 @@ class TenantMailer < ApplicationMailer
@tenant = tenant
Current.tenant = tenant
@trial_ends_at = tenant.tenant_billing.trial_ends_at
@trial_ends_at = tenant.tenant_billing.trial_ends_at.to_date
mail(
from: email_from_riccardo,
@@ -62,7 +63,7 @@ class TenantMailer < ApplicationMailer
@tenant = tenant
Current.tenant = tenant
@subscription_ends_at = Current.tenant.tenant_billing.subscription_ends_at
@subscription_ends_at = Current.tenant.tenant_billing.subscription_ends_at.to_date
mail(
from: email_from_astuto,
@@ -97,4 +98,8 @@ class TenantMailer < ApplicationMailer
def choose_layout
action_name == 'trial_mid' || action_name == 'trial_end' ? 'mailer_no_style' : 'mailer'
end
def set_locale_to_english
I18n.locale = :en
end
end

View File

@@ -65,6 +65,14 @@ class User < ApplicationRecord
"https://secure.gravatar.com/avatar/#{gravatar_id}"
end
def full_name_or_email
if full_name.present? && full_name != I18n.t('defaults.user_full_name') && full_name != I18n.t('defaults.user_full_name', locale: 'en')
full_name
else
email
end
end
def owner?
role == 'owner'
end

View File

@@ -1,6 +1,10 @@
<p><%= t('mailers.devise.welcome_greeting', email: @email, site_name: Current.tenant_or_raise!.site_name) %></p>
<p>
<%= t('mailers.devise.welcome_greeting', email: @email, site_name: Current.tenant.users.count == 1 ? "Astuto" : Current.tenant.site_name) %>
</p>
<p><%= t('mailers.devise.confirmation_instructions.body') %></p>
<p>
<%= t('mailers.devise.confirmation_instructions.body') %>
</p>
<p>
<%= link_to t('mailers.devise.confirmation_instructions.action'),

View File

@@ -66,3 +66,20 @@
method: :delete,
class: "btn btn-danger btn-block" %>
</div>
<br />
<% if Rails.application.multi_tenancy? && user_signed_in? && current_user.owner? %>
<div class="edit_user">
<h3>Delete feedback space</h3>
<p>
Deleting the feedback space will also delete all the feedback and users associated with it. This action cannot be undone.
</p>
<p>
If you want to delete the feedback space, please send an email to <a href="mailto:info@astuto.io">info@astuto.io</a> from the email address associated with this feedback space.
</p>
</div>
<% end %>
<br />

View File

@@ -6,14 +6,14 @@
<ul class="dropdown-menu boards-dropdown" aria-labelledby="navbarDropdown">
<% boards.each do |board| %>
<li>
<%= link_to board.name, get_url_for(method(:board_url), resource: board), class: 'dropdown-item' %>
<%= link_to board.name, @header_full_urls ? get_url_for(method(:board_url), resource: board) : board_path(board), class: 'dropdown-item' %>
</li>
<% end %>
</ul>
<% else %>
<% boards.each do |board| %>
<li class="nav-item<%= board.id == @board.id ? ' active' : '' unless @board.nil? %>">
<%= link_to board.name, get_url_for(method(:board_url), resource: board), class: 'nav-link' %>
<%= link_to board.name, @header_full_urls ? get_url_for(method(:board_url), resource: board) : board_path(board), class: 'nav-link' %>
</li>
<% end %>
<% end %>

View File

@@ -1,7 +1,7 @@
<nav class="header">
<div class="container">
<%=
link_to get_url_for(method(:root_url)), class: 'brand' do
link_to @header_full_urls ? get_url_for(method(:root_url)) : root_path, class: 'brand' do
app_name = content_tag :span, @tenant.site_name
logo = image_tag(@tenant.site_logo ? @tenant.site_logo : "", class: 'logo', skip_pipeline: true)
@@ -31,7 +31,7 @@
<ul class="boardsNav">
<% if @tenant_setting.show_roadmap_in_header %>
<li class="nav-item<%= (current_page?(roadmap_path) or (@tenant_setting.root_board_id == 0 and current_page?(root_path))) ? ' active' : '' %>">
<%= link_to t('roadmap.title'), get_url_for(method(:roadmap_url)), class: 'nav-link' %>
<%= link_to t('roadmap.title'), @header_full_urls ? get_url_for(method(:roadmap_url)) : roadmap_path, class: 'nav-link' %>
</li>
<% end %>
@@ -47,14 +47,21 @@
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<% if current_user.moderator? %>
<%=
link_to t('header.menu.site_settings'),
current_user.admin? ? get_url_for(method(:site_settings_general_url)) : get_url_for(method(:site_settings_users_url)),
class: 'dropdown-item'
%>
<% if current_user.admin? or current_user.owner? %>
<%=
link_to t('header.menu.site_settings'),
@header_full_urls ? get_url_for(method(:site_settings_general_url)) : site_settings_general_path,
class: 'dropdown-item'
%>
<% else %>
<%=
link_to t('header.menu.site_settings'),
@header_full_urls ? get_url_for(method(:site_settings_users_url)) : site_settings_users_path,
class: 'dropdown-item'
%>
<% end %>
<% if current_user.owner? and Rails.application.multi_tenancy? %>
<%= link_to get_url_for(method(:request_billing_page_url)), class: 'dropdown-item', data: {turbolinks: false} do %>
<%= link_to @header_full_urls ? get_url_for(method(:request_billing_page_url)) : request_billing_page_path, class: 'dropdown-item', data: {turbolinks: false} do %>
<%= t('billing.title') %>
<% if not Current.tenant.tenant_billing.has_active_subscription? %>
<span style="color: red; font-size: 18px;">⚠️</span>
@@ -65,11 +72,11 @@
<div class="dropdown-divider"></div>
<% end %>
<%= link_to t('header.menu.profile_settings'), get_url_for(method(:edit_user_registration_url)), class: 'dropdown-item' %>
<%= link_to t('header.menu.profile_settings'), @header_full_urls ? get_url_for(method(:edit_user_registration_url)) : edit_user_registration_path, class: 'dropdown-item' %>
<div class="dropdown-divider"></div>
<% unless @disable_sign_out %>
<%= button_to t('header.menu.sign_out'), get_url_for(method(:destroy_user_session_url)), method: :delete, class: 'dropdown-item' %>
<%= button_to t('header.menu.sign_out'), destroy_user_session_path, method: :delete, class: 'dropdown-item' %>
<% else %>
<small style="font-size: 12px; color: grey; padding: 0.25rem 1.5rem;">
Sign out disabled
@@ -79,7 +86,7 @@
</li>
<% else %>
<li class="nav-item">
<%= link_to t('header.log_in'), get_url_for(method(:new_user_session_url)), class: 'nav-link' %>
<%= link_to t('header.log_in'), @header_full_urls ? get_url_for(method(:new_user_session_url)) : new_user_session_path, class: 'nav-link' %>
</li>
<% end %>
</ul>

View File

@@ -1,5 +1,5 @@
<p>
Hello <%= @tenant.owner.full_name %>!
Hello <%= @tenant.owner.full_name_or_email %>!
</p>
<p>
@@ -7,7 +7,7 @@ We're sorry to see you go. <b>Your subscription has been cancelled and won't be
</p>
<p>
Your current subscription will remain active until <%= @subscription_ends_at.strftime('%B %d, %Y') %>.
Your current subscription will remain active until <%= I18n.localize @subscription_ends_at, format: :long %>.
</p>
<p>

View File

@@ -1,5 +1,5 @@
<p>
Hello <%= @tenant.owner.full_name %>!
Hello <%= @tenant.owner.full_name_or_email %>!
</p>
<p>

View File

@@ -1,5 +1,5 @@
<p>
Hello <%= @tenant.owner.full_name %>!
Hello <%= @tenant.owner.full_name_or_email %>!
</p>
<p>

View File

@@ -1,5 +1,5 @@
<p>
Hi <%= @tenant.owner.full_name %>,
Hi <%= @tenant.owner.full_name_or_email %>,
</p>
<p>

View File

@@ -1,5 +1,5 @@
<p>
Hi <%= @tenant.owner.full_name %>,
Hi <%= @tenant.owner.full_name_or_email %>,
</p>
<p>
@@ -15,7 +15,7 @@ How's your Astuto trial going? If you have any questions or encounter any issues
</p>
<p>
Also remember that your trial period will expire on <%= @trial_ends_at.strftime('%B %d, %Y') %>.
Also remember that your trial period will expire on <%= I18n.localize @trial_ends_at, format: :long %>.
</p>
<p>

View File

@@ -1,5 +1,5 @@
<p>
Hello <%= @tenant.owner.full_name %>,
Hello <%= @tenant.owner.full_name_or_email %>,
</p>
<p>

View File

@@ -1,4 +1,4 @@
<%= render 'user_mailer/opening', user_name: @user.full_name %>
<%= render 'user_mailer/opening', user_name: @user.full_name_or_email %>
<p>
<%= t('mailers.user.notify_comment_owner.body_html', user: @comment.user.full_name, post: @comment.post.title) %>:

View File

@@ -1,4 +1,4 @@
<%= render 'user_mailer/opening', user_name: @user.full_name %>
<%= render 'user_mailer/opening', user_name: @user.full_name_or_email %>
<p>
<%= t('mailers.user.notify_follower_of_post_status_change.body_html', post: @post.title) %>:

View File

@@ -1,4 +1,4 @@
<%= render 'user_mailer/opening', user_name: @user.full_name %>
<%= render 'user_mailer/opening', user_name: @user.full_name_or_email %>
<p>
<%= t('mailers.user.notify_follower_of_post_update.body_html', user: @comment.user.full_name, post: @comment.post.title) %>:

View File

@@ -1,4 +1,4 @@
<%= render 'user_mailer/opening', user_name: @user.full_name %>
<%= render 'user_mailer/opening', user_name: @user.full_name_or_email %>
<p>
<%= t('mailers.user.notify_post_owner.body_html', user: @comment.user.full_name, post: @comment.post.title) %>:

View File

@@ -11,6 +11,9 @@ module App
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0
# Set default locale
config.i18n.default_locale = :en
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading

View File

@@ -3,8 +3,6 @@ I18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml')]
I18n.available_locales = [:en, :it, :de, :fr, :es, 'zh-CN', :ru, :vi]
I18n.default_locale = :en
# Custom pluralization rules
# Those must be mirrored in app/javascript/translations/index.js.erb
I18n::Backend::Simple.include(I18n::Backend::Pluralization)

View File

@@ -19,7 +19,7 @@ task notify_tenants_trial_period: [:environment] do
tenants_mid_trial.each do |tenant|
puts "Delivering trial_mid email for #{tenant.site_name}..."
TenantMailer.trial_mid(tenant: tenant).deliver_later
TenantMailer.trial_mid(tenant: tenant).deliver_now
end
# Notify tenants end of trial
@@ -28,7 +28,7 @@ task notify_tenants_trial_period: [:environment] do
tenants_end_trial.each do |tenant|
puts "Delivering trial_end email for #{tenant.site_name}..."
TenantMailer.trial_end(tenant: tenant).deliver_later
TenantMailer.trial_end(tenant: tenant).deliver_now
end
rescue Exception => e
error_subject = "Scheduled Task 'notify_tenants_trial_period.rake' Failed"