Skip to content

Commit

Permalink
Add profile directory
Browse files Browse the repository at this point in the history
Fix #5578
  • Loading branch information
Gargron committed Dec 5, 2018
1 parent 58a29db commit 7ddedd9
Show file tree
Hide file tree
Showing 22 changed files with 444 additions and 6 deletions.
2 changes: 1 addition & 1 deletion app/controllers/api/v1/accounts/credentials_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def update
private

def account_params
params.permit(:display_name, :note, :avatar, :header, :locked, :bot, fields_attributes: [:name, :value])
params.permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, fields_attributes: [:name, :value])
end

def user_settings_params
Expand Down
48 changes: 48 additions & 0 deletions app/controllers/directories_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# frozen_string_literal: true

class DirectoriesController < ApplicationController
layout 'public'

before_action :set_instance_presenter
before_action :set_tag, only: :show
before_action :set_tags
before_action :set_accounts

def index
render :index
end

def show
render :index
end

private

def set_tag
@tag = Tag.find_by!(name: params[:id].downcase)
end

def set_tags
@tags = Tag.joins(:account_tag_stat).where('accounts_count > 0').order(name: :asc).limit(30)
end

def set_accounts
@accounts = Account.searchable.discoverable.page(params[:page]).per(50).tap do |query|
query.merge!(Account.tagged_with(@tag.id)) if @tag

if popular_requested?
query.merge!(Account.popular)
else
query.merge!(Account.by_recent_status)
end
end
end

def set_instance_presenter
@instance_presenter = InstancePresenter.new
end

def popular_requested?
request.path.ends_with?('/popular')
end
end
2 changes: 1 addition & 1 deletion app/controllers/settings/profiles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def update
private

def account_params
params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, fields_attributes: [:name, :value])
params.require(:account).permit(:display_name, :note, :avatar, :header, :locked, :bot, :discoverable, fields_attributes: [:name, :value])
end

def set_account
Expand Down
165 changes: 165 additions & 0 deletions app/javascript/styles/mastodon/widgets.scss
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,168 @@
border-radius: 0;
}
}

.page-header {
background: lighten($ui-base-color, 8%);
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);
border-radius: 4px;
padding: 60px 15px;
text-align: center;
margin: 10px 0;

h1 {
color: $primary-text-color;
font-size: 36px;
line-height: 1.1;
font-weight: 700;
margin-bottom: 10px;
}

p {
font-size: 15px;
color: $darker-text-color;
}
}

.directory {
background: $ui-base-color;
border-radius: 0 0 4px 4px;
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);

&__tag {
box-sizing: border-box;
margin-bottom: 10px;

a {
display: flex;
align-items: center;
justify-content: space-between;
background: $ui-base-color;
border-radius: 4px;
padding: 15px;
text-decoration: none;
color: inherit;
box-shadow: 0 0 15px rgba($base-shadow-color, 0.2);

&:hover,
&:active,
&:focus {
background: lighten($ui-base-color, 8%);
}
}

&.active a {
background: $ui-highlight-color;
cursor: default;
}

h4 {
flex: 1 1 auto;
font-size: 18px;
font-weight: 700;
color: $primary-text-color;

.fa {
color: $darker-text-color;
}

small {
display: block;
font-weight: 400;
font-size: 15px;
margin-top: 8px;
color: $darker-text-color;
}
}

&.active h4 {
&,
.fa,
small {
color: $primary-text-color;
}
}

.avatar-stack {
flex: 0 0 auto;
width: (36px + 4px) * 3;
}

&.active .avatar-stack .account__avatar {
border-color: $ui-highlight-color;
}
}
}

.avatar-stack {
display: flex;
justify-content: flex-end;

.account__avatar {
flex: 0 0 auto;
width: 36px;
height: 36px;
border-radius: 50%;
position: relative;
margin-left: -10px;
border: 2px solid $ui-base-color;

&:nth-child(1) {
z-index: 1;
}

&:nth-child(2) {
z-index: 2;
}

&:nth-child(3) {
z-index: 3;
}
}
}

.accounts-table {
width: 100%;

.account {
padding: 0;
border: 0;
}

thead th {
text-align: center;
text-transform: uppercase;
color: $darker-text-color;
font-weight: 700;
padding: 10px;

&:first-child {
text-align: left;
}
}

tbody td {
padding: 15px 0;
vertical-align: middle;
border-bottom: 1px solid lighten($ui-base-color, 8%);
}

tbody tr:last-child td {
border-bottom: 0;
}

&__count {
width: 120px;
text-align: center;
font-size: 15px;
font-weight: 500;
color: $primary-text-color;

small {
display: block;
color: $darker-text-color;
font-weight: 400;
font-size: 14px;
}
}
}
43 changes: 43 additions & 0 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
# featured_collection_url :string
# fields :jsonb
# actor_type :string
# discoverable :boolean
#

class Account < ApplicationRecord
Expand Down Expand Up @@ -89,6 +90,10 @@ class Account < ApplicationRecord
scope :matches_display_name, ->(value) { where(arel_table[:display_name].matches("#{value}%")) }
scope :matches_domain, ->(value) { where(arel_table[:domain].matches("%#{value}%")) }
scope :searchable, -> { where(suspended: false).where(moved_to_account_id: nil) }
scope :discoverable, -> { where(discoverable: true).joins(:account_stat) }
scope :tagged_with, ->(tag) { joins(:accounts_tags).where(accounts_tags: { tag_id: tag }) }
scope :popular, -> { order('account_stats.followers_count desc') }
scope :by_recent_status, -> { order('account_stats.last_status_at desc') }

delegate :email,
:unconfirmed_email,
Expand Down Expand Up @@ -174,6 +179,44 @@ def keypair
@keypair ||= OpenSSL::PKey::RSA.new(private_key || public_key)
end

def tags_as_strings
tags.pluck(:name).join(' ')
end

def tags_as_strings=(tag_names)
tag_names.map!(&:downcase)
tag_names.uniq!

# Existing hashtags
hashtags_map = Tag.where(name: tag_names).each_with_object({}) { |tag, h| h[tag.name] = tag }

# Initialize not yet existing hashtags
tag_names.each do |name|
next if hashtags_map.key?(name)
hashtags_map[name.downcase] = Tag.new(name: name)
end

# Remove hashtags that are to be deleted
tags.each do |tag|
if hashtags_map.key?(tag.name)
hashtags_map.delete(tag.name)
else
transaction do
tags.delete(tag)
tag.decrement_count!(:accounts_count)
end
end
end

# Add hashtags that were so far missing
hashtags_map.each_value do |tag|
transaction do
tags << tag
tag.increment_count!(:accounts_count)
end
end
end

def fields
(self[:fields] || []).map { |f| Field.new(self, f) }
end
Expand Down
12 changes: 10 additions & 2 deletions app/models/account_stat.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: account_stats
Expand All @@ -11,16 +10,25 @@
# followers_count :bigint(8) default(0), not null
# created_at :datetime not null
# updated_at :datetime not null
# last_status_at :datetime
#

class AccountStat < ApplicationRecord
belongs_to :account, inverse_of: :account_stat

def increment_count!(key)
update(key => public_send(key) + 1)
update(attributes_for_increment(key))
end

def decrement_count!(key)
update(key => [public_send(key) - 1, 0].max)
end

private

def attributes_for_increment(key)
attrs = { key => public_send(key) + 1 }
attrs[:last_status_at] = Time.now.utc if key == :statuses_count
attrs
end
end
23 changes: 23 additions & 0 deletions app/models/account_tag_stat.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: account_tag_stats
#
# id :bigint(8) not null, primary key
# tag_id :bigint(8) not null
# accounts_count :bigint(8) default(0), not null
# created_at :datetime not null
# updated_at :datetime not null
#

class AccountTagStat < ApplicationRecord
belongs_to :tag, inverse_of: :account_tag_stat

def increment_count!(key)
update(key => public_send(key) + 1)
end

def decrement_count!(key)
update(key => [public_send(key) - 1, 0].max)
end
end
3 changes: 3 additions & 0 deletions app/models/concerns/account_associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,8 @@ module AccountAssociations

# Account migrations
belongs_to :moved_to_account, class_name: 'Account', optional: true

# Hashtags
has_and_belongs_to_many :tags
end
end
1 change: 1 addition & 0 deletions app/models/concerns/account_counters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module AccountCounters
:followers_count=,
:increment_count!,
:decrement_count!,
:last_status_at,
to: :account_stat

def account_stat
Expand Down
Loading

0 comments on commit 7ddedd9

Please sign in to comment.