Skip to content

Commit

Permalink
Merge pull request #771 from coopdevs/improve_onboarding_base
Browse files Browse the repository at this point in the history
Impove Onboarding / Membership management process
  • Loading branch information
markets authored Feb 15, 2025
2 parents 9db9786 + 153122f commit d4f6efd
Show file tree
Hide file tree
Showing 42 changed files with 311 additions and 161 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ jobs:
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Install ImageMagick
uses: mfinelli/setup-imagemagick@v6
with:
cache: true
- name: Run tests
env:
RAILS_ENV: test
Expand Down
5 changes: 4 additions & 1 deletion app/admin/organization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
column :posts do |organization|
organization.posts.count
end
column :highlighted
actions
end

Expand All @@ -37,6 +38,7 @@

form do |f|
f.inputs do
f.input :highlighted, hint: "Highlighted Time Banks will appear first"
f.input :name
f.input :email
f.input :web
Expand Down Expand Up @@ -71,7 +73,8 @@ def destroy
filter :neighborhood
filter :created_at
filter :updated_at
filter :highlighted

permit_params :name, :email, :web, :phone, :city, :neighborhood,
:address, :description, :public_opening_times, :logo
:address, :description, :public_opening_times, :logo, :highlighted
end
13 changes: 12 additions & 1 deletion app/admin/petition.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
ActiveAdmin.register Petition do
actions :index
actions :index, :destroy

controller do
def destroy
if resource.accepted?
redirect_to admin_petitions_path, alert: "ACCEPTED petitions can't be deleted"
else
super
end
end
end

index do
id_column
Expand All @@ -9,6 +19,7 @@
column :status do |petition|
petition.status.upcase
end
actions
end

filter :organization
Expand Down
4 changes: 4 additions & 0 deletions app/admin/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
redirect_to action: :index
end

scope :all
scope :without_memberships

index do
selectable_column
column do |user|
Expand All @@ -29,6 +32,7 @@
column :posts do |u|
u.posts.count
end
column :created_at
actions
end

Expand Down
4 changes: 4 additions & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ ul.statistics li{
padding-left: 1.5rem;
}

.alert a {
text-decoration: underline;
}

// fields that contain an error
.field_with_errors{
color: red;
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def after_sign_in_path_for(user)
elsif user.members.present?
users_path
else
page_path("about")
organizations_path
end
end

Expand Down
2 changes: 2 additions & 0 deletions app/controllers/members_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ def destroy
toggle_active_posts
@member.destroy

OrganizationNotifier.member_deleted(@member.user.username, current_organization).deliver_later

redirect_to request.referer.include?(organizations_path) ? organizations_path : manage_users_path
end

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/organizations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def index

organizations = Organization.where.not(id: @user_organizations&.pluck(:id))
organizations = organizations.search_by_query(params[:q]) if params[:q].present?
@organizations = organizations.page(params[:page]).per(25)
@organizations = organizations.order(highlighted: :desc).page(params[:page]).per(25)
end

def show
Expand Down
11 changes: 5 additions & 6 deletions app/controllers/petitions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ class PetitionsController < ApplicationController

def create
petition = Petition.new petition_params
petition.status = "pending"

if petition.save
OrganizationNotifier.new_petition(petition).deliver_now
OrganizationNotifier.petition_sent(petition).deliver_now
OrganizationNotifier.new_petition(petition).deliver_later
OrganizationNotifier.petition_sent(petition).deliver_later

flash[:notice] = t('petitions.application_status', status: t("petitions.status.sent"))
else
flash[:error] = t('errors.internal_server_error.description')
flash[:error] = petition.errors.full_messages.to_sentence
end

redirect_back fallback_location: organization_path(petition.organization)
Expand All @@ -25,14 +24,14 @@ def update
petition.user.add_to_organization(petition.organization) if status == 'accepted'
flash[:notice] = t('petitions.application_status', status: t("petitions.status.#{status}"))
else
flash[:error] = t('errors.internal_server_error.description')
flash[:error] = petition.errors.full_messages.to_sentence
end

redirect_to manage_petitions_path
end

def manage
@status = params[:status] || 'pending'
@status = params[:status] || Petition::DEFAULT_STATUS
@users = User.joins(:petitions).where(petitions: { organization_id: current_organization.id, status: @status }).page(params[:page]).per(20)
end

Expand Down
4 changes: 4 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,8 @@ def alert_class(alert)
'alert-info'
end
end

def show_no_membership_warning?
current_user&.no_membership_warning? && !devise_controller?
end
end
11 changes: 11 additions & 0 deletions app/jobs/membership_warning_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class MembershipWarningJob < ActiveJob::Base
queue_as :cron

def perform
User.without_memberships.find_each do |user|
if user.created_at.to_date == 15.days.ago.to_date && user.no_membership_warning?
OrganizationNotifier.no_membership_warning(user).deliver_now
end
end
end
end
32 changes: 27 additions & 5 deletions app/mailers/organization_notifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ class OrganizationNotifier < ActionMailer::Base
def recent_posts(posts, locale, users)
@offers = posts.where(type: "Offer").take(10)
@inquiries = posts.where(type: "Inquiry").take(10)

@organization_name = posts.take.organization.name

I18n.with_locale(locale) do
Expand All @@ -15,23 +14,46 @@ def recent_posts(posts, locale, users)
def new_petition(petition)
@user = petition.user
organization = petition.organization
org_managers = organization.all_managers
@organization_name = organization.name

I18n.with_locale(locale) do
I18n.with_locale(org_managers.first&.locale) do
mail(
subject: 'New Application',
bcc: organization.users.joins(:members).where(members: { manager: true }).pluck(:email).uniq
subject: "New Application - #{organization.name}",
bcc: org_managers.pluck(:email).uniq
)
end
end

def petition_sent(petition)
@organization_name = petition.organization.name

I18n.with_locale(locale) do
I18n.with_locale(petition.user.locale) do
mail(
subject: 'Application sent correctly',
to: petition.user.email
)
end
end

def member_deleted(username, organization)
@username = username
org_managers = organization.all_managers

I18n.with_locale(org_managers.first&.locale) do
mail(
subject: "Membership deleted - #{organization.name}",
bcc: org_managers.pluck(:email).uniq
)
end
end

def no_membership_warning(user)
I18n.with_locale(user.locale) do
mail(
subject: "Do not forget to join a Timebank",
to: user.email
)
end
end
end
8 changes: 6 additions & 2 deletions app/models/organization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,19 @@ class Organization < ApplicationRecord
before_validation :ensure_url
after_create :create_account

def to_s
"#{name}"
end

def all_transfers_with_accounts
all_transfers.
includes(movements: { account: :accountable }).
order("transfers.created_at DESC").
distinct
end

def to_s
"#{name}"
def all_managers
users.where(members: { manager: true })
end

def display_name_with_uid
Expand Down
6 changes: 5 additions & 1 deletion app/models/petition.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class Petition < ApplicationRecord
enum status: %i[pending accepted declined]
DEFAULT_STATUS = "pending"

enum status: %i[pending accepted declined], _default: DEFAULT_STATUS

belongs_to :user
belongs_to :organization

validates :user_id, uniqueness: { scope: :organization_id }
end
9 changes: 9 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class User < ApplicationRecord
accepts_nested_attributes_for :members, allow_destroy: true

default_scope { order("users.id ASC") }
scope :without_memberships, -> { where.missing(:members) }
scope :actives, -> { joins(:members).where(members: { active: true }) }
scope :online_active, -> { where("sign_in_count > 0") }
scope :notifications, -> { where(notifications: true) }
Expand Down Expand Up @@ -93,6 +94,14 @@ def active?(organization)
organization && !!(as_member_of(organization).try :active)
end

def memberships?
members.any?
end

def no_membership_warning?
confirmed? && terms_accepted_at.present? && !memberships?
end

def member(organization)
members.where(organization_id: organization).first
end
Expand Down
2 changes: 2 additions & 0 deletions app/services/push_notifications/broadcast.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "net/http"

module PushNotifications
class Broadcast
class PostError < ::StandardError; end
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions app/views/application/_no_membership_warning.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="alert alert-info">
<%= t('layouts.application.no_memberhsip_warning', link: organizations_path).html_safe %>
</div>
2 changes: 1 addition & 1 deletion app/views/devise/confirmations/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="panel-body">
<h2><%= t(".resend_instructions") %></h2>
<p class="description"><%= t(".resend_instructions_description") %></p>
<%= render 'layouts/messages' %>
<%= render 'application/flash_messages' %>
<%= show_error_messages!(resource) %>
<%= form_for resource, url: confirmation_path(resource_name), html: { method: :post } do |f| %>
<div class="form-group">
Expand Down
2 changes: 1 addition & 1 deletion app/views/devise/passwords/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div class="panel" id="login-box">
<div class="panel-body">
<h2><%= t(".change_password") %></h2>
<%= render 'layouts/messages' %>
<%= render 'application/flash_messages' %>
<%= show_error_messages!(resource) %>
<%= form_for resource, url: password_path(resource_name), html: { method: :put } do |f| %>
<%= f.hidden_field :reset_password_token %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/devise/passwords/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="panel-body">
<h2><%= t(".forgot_question") %></h2>
<p class="description"><%= t(".forgot_question_description") %></p>
<%= render 'layouts/messages' %>
<%= render 'application/flash_messages' %>
<%= show_error_messages!(resource) %>
<%= form_for resource, url: password_path(resource_name), html: { method: :post } do |f| %>
<div class="form-group">
Expand Down
2 changes: 1 addition & 1 deletion app/views/devise/sessions/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="col-xs-12 col-sm-8 col-md-6 col-lg-6 col-sm-offset-2 col-md-offset-3 col-lg-offset-3">
<div class="panel" id="login-box">
<div class="panel-body">
<%= render 'layouts/messages' %>
<%= render 'application/flash_messages' %>
<%= show_error_messages!(resource) %>
<%= form_for resource, url: session_path(resource_name) do |f| %>
<div class="form-group">
Expand Down
2 changes: 1 addition & 1 deletion app/views/devise/unlocks/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div class="panel-body">
<h2><%= t(".resend_instructions") %></h2>
<p class="description"><%= t(".resend_instructions_description") %></p>
<%= render 'layouts/messages' %>
<%= render 'application/flash_messages' %>
<%= show_error_messages!(resource) %>
<%= form_for resource, url: unlock_path(resource_name), html: { method: :post } do |f| %>
<div class="form-group">
Expand Down
3 changes: 2 additions & 1 deletion app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
<body class="<%= get_body_css_class(controller_name) %>">
<%= render 'navbar' %>
<div class="container content">
<%= render 'layouts/messages' unless devise_controller? %>
<%= render 'application/flash_messages' unless devise_controller? %>
<div class="container-fluid">
<%= render 'application/no_membership_warning' if show_no_membership_warning? %>
<%= yield %>
</div>
<%= organization_logo %>
Expand Down
1 change: 1 addition & 0 deletions app/views/organization_notifier/member_deleted.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= t("organization_notifier.member_deleted.body", username: @username) %>
2 changes: 1 addition & 1 deletion app/views/organization_notifier/new_petition.html.erb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<%= t('petitions.new_body', username: @user.username, here_link: link_to(t('global.here'), manage_petitions_url)).html_safe %>
<%= t('petitions.new_body', username: @user.username, organization_name: @organization_name, here_link: link_to(t('global.here'), manage_petitions_url)).html_safe %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= t('layouts.application.no_memberhsip_warning', link: organizations_url).html_safe %>
7 changes: 3 additions & 4 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,15 @@ class Application < Rails::Application
# ActiveJob configuration
config.active_job.queue_adapter = :sidekiq

# ActionMailer background queues
config.action_mailer.deliver_later_queue_name = :mailers

# Use db/structure.sql with SQL as schema format
# This is needed to store in the schema SQL statements not covered by the ORM
config.active_record.schema_format = :sql

# Guard against DNS rebinding attacks by permitting hosts
# localhost is necessary for the docker image
config.hosts = ENV.fetch('ALLOWED_HOSTS', 'localhost').split(' ')
# config.hosts << 'timeoverflow.local'
# config.hosts << 'staging.timeoverflow.org'
# config.hosts << 'www.timeoverflow.org'
# config.hosts << 'timeoverflow.org'
end
end
Loading

0 comments on commit d4f6efd

Please sign in to comment.