Merge pull request #120 from Retrospring/113-groups2lists
Rename Groups to Lists
This commit is contained in:
commit
bb0d85d613
|
@ -19,7 +19,7 @@
|
|||
# local requires to be seen by everyone:
|
||||
#= require_tree ./answerbox
|
||||
#= require_tree ./questionbox
|
||||
#= require groups
|
||||
#= require lists
|
||||
#= require inbox
|
||||
#= require memes
|
||||
#= require notifications
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
($ document).on "click", "input[type=checkbox][name=gm-group-check]", ->
|
||||
($ document).on "click", "input[type=checkbox][name=gm-list-check]", ->
|
||||
box = $(this)
|
||||
box.attr 'disabled', 'disabled'
|
||||
|
||||
groupName = box[0].dataset.group
|
||||
listName = box[0].dataset.list
|
||||
|
||||
count = Number ($ "span##{groupName}-members").html()
|
||||
count = Number ($ "span##{listName}-members").html()
|
||||
boxChecked = box[0].checked
|
||||
|
||||
count += if boxChecked then 1 else -1
|
||||
|
||||
$.ajax
|
||||
url: '/ajax/group_membership'
|
||||
url: '/ajax/list_membership'
|
||||
type: 'POST'
|
||||
data:
|
||||
user: box[0].dataset.user
|
||||
group: groupName
|
||||
list: listName
|
||||
add: boxChecked
|
||||
success: (data, status, jqxhr) ->
|
||||
if data.success
|
||||
box[0].checked = if data.checked? then data.checked else !boxChecked
|
||||
($ "span##{groupName}-members").html(count)
|
||||
($ "span##{listName}-members").html(count)
|
||||
showNotification data.message, data.success
|
||||
error: (jqxhr, status, error) ->
|
||||
box[0].checked = false
|
||||
|
@ -29,19 +29,19 @@
|
|||
box.removeAttr "disabled"
|
||||
|
||||
|
||||
$(document).on "keyup", "input#new-group-name", (evt) ->
|
||||
$(document).on "keyup", "input#new-list-name", (evt) ->
|
||||
if evt.which == 13 # return key
|
||||
evt.preventDefault()
|
||||
$("button#create-group").trigger 'click'
|
||||
$("button#create-list").trigger 'click'
|
||||
|
||||
|
||||
($ document).on "click", "button#create-group", ->
|
||||
($ document).on "click", "button#create-list", ->
|
||||
btn = $(this)
|
||||
btn.button "loading"
|
||||
input = ($ "input#new-group-name")
|
||||
input = ($ "input#new-list-name")
|
||||
|
||||
$.ajax
|
||||
url: '/ajax/create_group'
|
||||
url: '/ajax/create_list'
|
||||
type: 'POST'
|
||||
data:
|
||||
name: input.val()
|
||||
|
@ -49,7 +49,7 @@ $(document).on "keyup", "input#new-group-name", (evt) ->
|
|||
dataType: 'json'
|
||||
success: (data, status, jqxhr) ->
|
||||
if data.success
|
||||
($ "ul.list-group.groups--list").append(data.render)
|
||||
($ "#lists-list ul.list-group").append(data.render)
|
||||
input.val ''
|
||||
showNotification data.message, data.success
|
||||
error: (jqxhr, status, error) ->
|
||||
|
@ -59,14 +59,14 @@ $(document).on "keyup", "input#new-group-name", (evt) ->
|
|||
btn.button "reset"
|
||||
|
||||
|
||||
($ document).on "click", "a#delete-group", (ev) ->
|
||||
($ document).on "click", "a#delete-list", (ev) ->
|
||||
ev.preventDefault()
|
||||
btn = $(this)
|
||||
group = btn[0].dataset.group
|
||||
list = btn[0].dataset.list
|
||||
|
||||
swal
|
||||
title: translate('frontend.group.title')
|
||||
text: translate('frontend.group.text')
|
||||
title: translate('frontend.list.title')
|
||||
text: translate('frontend.list.text')
|
||||
type: "warning"
|
||||
showCancelButton: true
|
||||
confirmButtonColor: "#DD6B55"
|
||||
|
@ -75,14 +75,14 @@ $(document).on "keyup", "input#new-group-name", (evt) ->
|
|||
closeOnConfirm: true
|
||||
, ->
|
||||
$.ajax
|
||||
url: '/ajax/destroy_group'
|
||||
url: '/ajax/destroy_list'
|
||||
type: 'POST'
|
||||
data:
|
||||
group: group
|
||||
list: list
|
||||
dataType: 'json'
|
||||
success: (data, status, jqxhr) ->
|
||||
if data.success
|
||||
($ "li.list-group-item#group-#{group}").slideUp()
|
||||
($ "li.list-group-item#list-#{list}").slideUp()
|
||||
showNotification data.message, data.success
|
||||
error: (jqxhr, status, error) ->
|
||||
console.log jqxhr, status, error
|
|
@ -3,18 +3,11 @@ $(document).on "click", "button[name=qb-all-ask]", ->
|
|||
btn.button "loading"
|
||||
$("textarea[name=qb-all-question]").attr "readonly", "readonly"
|
||||
|
||||
rcptSelect = ($ 'select[name=qb-all-rcpt]')
|
||||
|
||||
rcpt = if rcptSelect.length > 0
|
||||
rcptSelect.first().val()
|
||||
else
|
||||
'followers'
|
||||
|
||||
$.ajax
|
||||
url: '/ajax/ask'
|
||||
type: 'POST'
|
||||
data:
|
||||
rcpt: rcpt
|
||||
rcpt: 'followers'
|
||||
question: $("textarea[name=qb-all-question]").val()
|
||||
anonymousQuestion: false
|
||||
success: (data, status, jqxhr) ->
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
class Ajax::GroupController < AjaxController
|
||||
class Ajax::ListController < AjaxController
|
||||
def create
|
||||
@response[:status] = :err
|
||||
|
||||
|
@ -13,35 +13,35 @@ class Ajax::GroupController < AjaxController
|
|||
rescue ActionController::ParameterMissing => e
|
||||
NewRelic::Agent.notice_error(e)
|
||||
@response[:status] = :toolong
|
||||
@response[:message] = I18n.t('messages.group.create.noname')
|
||||
@response[:message] = I18n.t('messages.list.create.noname')
|
||||
return
|
||||
end
|
||||
params.require :user
|
||||
|
||||
begin
|
||||
target_user = User.find_by_screen_name!(params[:user])
|
||||
group = Group.create! user: current_user, display_name: params[:name]
|
||||
list = List.create! user: current_user, display_name: params[:name]
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
NewRelic::Agent.notice_error(e)
|
||||
@response[:status] = :toolong
|
||||
@response[:message] = I18n.t('messages.group.create.toolong')
|
||||
@response[:message] = I18n.t('messages.list.create.toolong')
|
||||
return
|
||||
rescue ActiveRecord::RecordNotFound => e
|
||||
NewRelic::Agent.notice_error(e)
|
||||
@response[:status] = :notfound
|
||||
@response[:message] = I18n.t('messages.group.create.notfound')
|
||||
@response[:message] = I18n.t('messages.list.create.notfound')
|
||||
return
|
||||
rescue ActiveRecord::RecordNotUnique => e
|
||||
NewRelic::Agent.notice_error(e)
|
||||
@response[:status] = :exists
|
||||
@response[:message] = I18n.t('messages.group.create.exists')
|
||||
@response[:message] = I18n.t('messages.list.create.exists')
|
||||
return
|
||||
end
|
||||
|
||||
@response[:status] = :okay
|
||||
@response[:success] = true
|
||||
@response[:message] = I18n.t('messages.group.create.okay')
|
||||
@response[:render] = render_to_string(partial: 'modal/group/item', locals: { group: group, user: target_user })
|
||||
@response[:message] = I18n.t('messages.list.create.okay')
|
||||
@response[:render] = render_to_string(partial: 'modal/list/item', locals: { list: list, user: target_user })
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -53,20 +53,20 @@ class Ajax::GroupController < AjaxController
|
|||
return
|
||||
end
|
||||
|
||||
params.require :group
|
||||
params.require :list
|
||||
|
||||
begin
|
||||
Group.where(user: current_user, name: params[:group]).first.destroy!
|
||||
List.where(user: current_user, name: params[:list]).first.destroy!
|
||||
rescue ActiveRecord::RecordNotFound => e
|
||||
NewRelic::Agent.notice_error(e)
|
||||
@response[:status] = :notfound
|
||||
@response[:message] = I18n.t('messages.group.destroy.notfound')
|
||||
@response[:message] = I18n.t('messages.list.destroy.notfound')
|
||||
return
|
||||
end
|
||||
|
||||
@response[:status] = :okay
|
||||
@response[:success] = true
|
||||
@response[:message] = I18n.t('messages.group.destroy.okay')
|
||||
@response[:message] = I18n.t('messages.list.destroy.okay')
|
||||
end
|
||||
|
||||
def membership
|
||||
|
@ -79,30 +79,30 @@ class Ajax::GroupController < AjaxController
|
|||
end
|
||||
|
||||
params.require :user
|
||||
params.require :group
|
||||
params.require :list
|
||||
params.require :add
|
||||
|
||||
add = params[:add] == 'true'
|
||||
|
||||
begin
|
||||
group = current_user.groups.find_by_name!(params[:group])
|
||||
list = current_user.lists.find_by_name!(params[:list])
|
||||
rescue ActiveRecord::RecordNotFound => e
|
||||
NewRelic::Agent.notice_error(e)
|
||||
@response[:status] = :notfound
|
||||
@response[:message] = I18n.t('messages.group.membership.notfound')
|
||||
@response[:message] = I18n.t('messages.list.membership.notfound')
|
||||
return
|
||||
end
|
||||
|
||||
target_user = User.find_by_screen_name!(params[:user])
|
||||
|
||||
if add
|
||||
group.add_member target_user if group.members.find_by_user_id(target_user.id).nil?
|
||||
list.add_member target_user if list.members.find_by_user_id(target_user.id).nil?
|
||||
@response[:checked] = true
|
||||
@response[:message] = I18n.t('messages.group.membership.add')
|
||||
@response[:message] = I18n.t('messages.list.membership.add')
|
||||
else
|
||||
group.remove_member target_user unless group.members.find_by_user_id(target_user.id).nil?
|
||||
list.remove_member target_user unless list.members.find_by_user_id(target_user.id).nil?
|
||||
@response[:checked] = false
|
||||
@response[:message] = I18n.t('messages.group.membership.remove')
|
||||
@response[:message] = I18n.t('messages.list.membership.remove')
|
||||
end
|
||||
|
||||
@response[:status] = :okay
|
|
@ -27,7 +27,7 @@ class Ajax::QuestionController < AjaxController
|
|||
params.require :anonymousQuestion
|
||||
params.require :rcpt
|
||||
|
||||
is_never_anonymous = user_signed_in? && (params[:rcpt].start_with?('grp:') || params[:rcpt] == 'followers')
|
||||
is_never_anonymous = user_signed_in? && params[:rcpt] == 'followers'
|
||||
|
||||
begin
|
||||
question = Question.create!(content: params[:question],
|
||||
|
@ -50,22 +50,7 @@ class Ajax::QuestionController < AjaxController
|
|||
end
|
||||
|
||||
if params[:rcpt] == 'followers'
|
||||
unless current_user.nil?
|
||||
QuestionWorker.perform_async params[:rcpt], current_user.id, question.id
|
||||
end
|
||||
elsif params[:rcpt].start_with? 'grp:'
|
||||
unless current_user.nil?
|
||||
begin
|
||||
current_user.groups.find_by_name!(params[:rcpt].sub 'grp:', '')
|
||||
QuestionWorker.perform_async params[:rcpt], current_user.id, question.id
|
||||
rescue ActiveRecord::RecordNotFound => e
|
||||
NewRelic::Agent.notice_error(e)
|
||||
question.delete
|
||||
@response[:status] = :not_found
|
||||
@response[:message] = I18n.t('messages.question.create.not_found')
|
||||
return
|
||||
end
|
||||
end
|
||||
QuestionWorker.perform_async(current_user.id, question.id) unless current_user.nil?
|
||||
else
|
||||
u = User.find_by_id(params[:rcpt])
|
||||
if u.nil?
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
class GroupController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
|
||||
def index
|
||||
@group = current_user.groups.find_by_name!(params[:group_name])
|
||||
@timeline = @group.cursored_timeline(last_id: params[:last_id])
|
||||
@timeline_last_id = @timeline.map(&:id).min
|
||||
@more_data_available = !@group.cursored_timeline(last_id: @timeline_last_id, size: 1).count.zero?
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js { render layout: false }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
class ListController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
|
||||
def index
|
||||
@list = current_user.lists.find_by_name!(params[:list_name])
|
||||
@timeline = @list.cursored_timeline(last_id: params[:last_id])
|
||||
@timeline_last_id = @timeline.map(&:id).min
|
||||
@more_data_available = !@list.cursored_timeline(last_id: @timeline_last_id, size: 1).count.zero?
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js { render layout: false }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -61,13 +61,13 @@ class UserController < ApplicationController
|
|||
end
|
||||
# endregion
|
||||
|
||||
# region Groups
|
||||
def groups
|
||||
# region Lists
|
||||
def lists
|
||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||
@groups = if current_user == @user
|
||||
@user.groups
|
||||
@lists = if current_user == @user
|
||||
@user.lists
|
||||
else
|
||||
@user.groups.where(private: false)
|
||||
@user.lists.where(private: false)
|
||||
end.all
|
||||
end
|
||||
# endregion
|
||||
|
|
|
@ -166,7 +166,7 @@ module ApplicationHelper
|
|||
user_title user, "comments"
|
||||
end
|
||||
|
||||
def group_title(group)
|
||||
generate_title group.name
|
||||
def list_title(list)
|
||||
generate_title list.name
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
class GroupMember < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :group
|
||||
end
|
|
@ -1,10 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Group < ApplicationRecord
|
||||
include Group::TimelineMethods
|
||||
class List < ApplicationRecord
|
||||
include List::TimelineMethods
|
||||
|
||||
belongs_to :user
|
||||
has_many :group_members, dependent: :destroy
|
||||
has_many :list_members, dependent: :destroy
|
||||
|
||||
validates :name, length: { minimum: 1 }
|
||||
validates :display_name, length: { maximum: 30 }
|
||||
|
@ -15,13 +15,13 @@ class Group < ApplicationRecord
|
|||
self.name = '-followers-' if self.name == 'followers'
|
||||
end
|
||||
|
||||
alias members group_members
|
||||
alias members list_members
|
||||
|
||||
def add_member(user)
|
||||
GroupMember.create! group: self, user: user
|
||||
ListMember.create! list: self, user: user
|
||||
end
|
||||
|
||||
def remove_member(user)
|
||||
GroupMember.where(group: self, user: user).first!.destroy
|
||||
ListMember.where(list: self, user: user).first!.destroy
|
||||
end
|
||||
end
|
|
@ -1,11 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Group::TimelineMethods
|
||||
module List::TimelineMethods
|
||||
include CursorPaginatable
|
||||
|
||||
define_cursor_paginator :cursored_timeline, :timeline
|
||||
|
||||
# @return [Array] the groups' timeline
|
||||
# @return [Array] the lists' timeline
|
||||
def timeline
|
||||
Answer.where('user_id in (?)', members.pluck(:user_id)).order(:created_at).reverse_order
|
||||
end
|
|
@ -0,0 +1,4 @@
|
|||
class ListMember < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :list
|
||||
end
|
|
@ -34,8 +34,8 @@ class User < ApplicationRecord
|
|||
has_many :reports, dependent: :destroy
|
||||
has_many :moderation_comments, dependent: :destroy
|
||||
has_many :moderation_votes, dependent: :destroy
|
||||
has_many :groups, dependent: :destroy
|
||||
has_many :group_memberships, class_name: "GroupMember", foreign_key: 'user_id', dependent: :destroy
|
||||
has_many :lists, dependent: :destroy
|
||||
has_many :list_memberships, class_name: "ListMember", foreign_key: 'user_id', dependent: :destroy
|
||||
|
||||
has_many :subscriptions, dependent: :destroy
|
||||
|
||||
|
@ -110,10 +110,10 @@ class User < ApplicationRecord
|
|||
friends.include? target_user
|
||||
end
|
||||
|
||||
# @param group [Group]
|
||||
# @return [Boolean] true if +self+ is a member of +group+
|
||||
def member_of?(group)
|
||||
group_memberships.pluck(:group_id).include? group.id
|
||||
# @param list [List]
|
||||
# @return [Boolean] true if +self+ is a member of +list+
|
||||
def member_of?(list)
|
||||
list_memberships.pluck(:list_id).include? list.id
|
||||
end
|
||||
|
||||
# answers a question
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
= render 'shared/sidebar'
|
||||
.col-md-9.col-xs-12.col-sm-8
|
||||
= render 'layouts/messages'
|
||||
= render 'tabs/feed', group: @group
|
||||
= render 'tabs/feed', list: @list
|
||||
= yield
|
||||
.d-block.d-sm-none= render 'shared/links'
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
= render 'tabs/profile', user: @user
|
||||
= yield
|
||||
- if user_signed_in?
|
||||
= render 'modal/group', user: @user
|
||||
= render 'modal/list', user: @user
|
||||
- if current_user.mod? && @user != current_user
|
||||
= render 'modal/privileges', user: @user
|
||||
= render 'modal/ban', user: @user
|
||||
|
|
|
@ -8,5 +8,5 @@
|
|||
%button.btn.btn-default#load-more-btn{ type: :button, data: { last_id: @timeline_last_id } }
|
||||
= t 'views.actions.load'
|
||||
|
||||
- provide(:title, group_title(@group))
|
||||
- provide(:title, list_title(@list))
|
||||
- parent_layout 'feed'
|
|
@ -9,13 +9,5 @@
|
|||
.modal-body
|
||||
%textarea.form-control{ name: 'qb-all-question', placeholder: t('views.placeholder.question') }
|
||||
.modal-footer
|
||||
- if current_user.groups.count.positive?
|
||||
%label
|
||||
= t 'views.modal.ask.choose'
|
||||
%select.form-control{ name: 'qb-all-rcpt', autocomplete: :off }
|
||||
%option{ value: 'followers', selected: true }= t('views.general.follower').pluralize(2)
|
||||
%optgroup{ label: t('views.group.title').pluralize(2) }
|
||||
- current_user.groups.each do |group|
|
||||
%option{ value: "grp:#{group.name}" }= group.display_name
|
||||
%button.btn.btn-default{ type: :button, data: { dismiss: :modal } }= t 'views.actions.cancel'
|
||||
%button.btn.btn-primary{ name: 'qb-all-ask', type: :button, data: { loading_text: t('views.modal.ask.loading') } }= t 'views.actions.ask'
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
.modal.fade#modal-group-memberships{ aria: { hidden: true, labelledby: 'modal-group-memberships-label' }, role: :dialog, tabindex: -1 }
|
||||
.modal-dialog
|
||||
.modal-content
|
||||
.modal-header
|
||||
%h5.modal-title#modal-group-memberships-label= t 'views.modal.group.title'
|
||||
%button.close{ data: { dismiss: :modal }, type: :button }
|
||||
%span{ aria: { hidden: true } } ×
|
||||
%span.sr-only= t 'views.actions.close'
|
||||
%div{ role: :tabpanel }
|
||||
%ul.nav.nav-tabs.mt-1{ role: :tablist }
|
||||
%li.nav-item{ role: 'presentation' }
|
||||
%a.nav-link.active{ href: '#grouplist', aria: { controls: 'grouplist' }, data: { toggle: :tab }, role: :tab }
|
||||
= t 'views.modal.group.tabs.main'
|
||||
%li.nav-item{ role: 'presentation' }
|
||||
%a.nav-link{ href: '#create', aria: { controls: 'create' }, data: { toggle: :tab }, role: :tab }
|
||||
= t 'views.modal.group.tabs.create'
|
||||
|
||||
.tab-content
|
||||
.tab-pane.active{ role: :tabpanel, id: 'grouplist' }
|
||||
%ul.list-group
|
||||
- current_user.groups.each do |group|
|
||||
= render 'modal/group/item', group: group, user: user
|
||||
.tab-pane{ role: :tabpanel, id: 'create' }
|
||||
.modal-body
|
||||
%input.form-control#new-group-name{ type: :text, placeholder: t('views.modal.group.name') }
|
||||
%button.btn.btn-primary#create-group{ type: :button, data: { user: user.screen_name } }= t('views.modal.group.create')
|
||||
.modal-footer
|
||||
%button.btn.btn-primary{ name: 'gm-save', type: :button, data: { dismiss: :modal } }= t 'views.actions.done'
|
|
@ -0,0 +1,28 @@
|
|||
.modal.fade#modal-list-memberships{ aria: { hidden: true, labelledby: 'modal-list-memberships-label' }, role: :dialog, tabindex: -1 }
|
||||
.modal-dialog
|
||||
.modal-content
|
||||
.modal-header
|
||||
%h5.modal-title#modal-list-memberships-label= t 'views.modal.list.title'
|
||||
%button.close{ data: { dismiss: :modal }, type: :button }
|
||||
%span{ aria: { hidden: true } } ×
|
||||
%span.sr-only= t 'views.actions.close'
|
||||
%div{ role: :tabpanel }
|
||||
%ul.nav.nav-tabs.mt-1{ role: :tablist }
|
||||
%li.nav-item{ role: 'presentation' }
|
||||
%a.nav-link.active{ href: '#lists-list', aria: { controls: 'lists-list' }, data: { toggle: :tab }, role: :tab }
|
||||
= t 'views.modal.list.tabs.main'
|
||||
%li.nav-item{ role: 'presentation' }
|
||||
%a.nav-link{ href: '#create', aria: { controls: 'create' }, data: { toggle: :tab }, role: :tab }
|
||||
= t 'views.modal.list.tabs.create'
|
||||
|
||||
.tab-content
|
||||
.tab-pane.active{ role: :tabpanel, id: 'lists-list' }
|
||||
%ul.list-group
|
||||
- current_user.lists.each do |list|
|
||||
= render 'modal/list/item', list: list, user: user
|
||||
.tab-pane{ role: :tabpanel, id: 'create' }
|
||||
.modal-body
|
||||
%input.form-control#new-list-name{ type: :text, placeholder: t('views.modal.list.name') }
|
||||
%button.btn.btn-primary#create-list{ type: :button, data: { user: user.screen_name } }= t('views.modal.list.create')
|
||||
.modal-footer
|
||||
%button.btn.btn-primary{ name: 'gm-save', type: :button, data: { dismiss: :modal } }= t 'views.actions.done'
|
|
@ -7,7 +7,7 @@
|
|||
%button.close{ data: { dismiss: :modal }, type: :button }
|
||||
%span{ aria: { hidden: true } } ×
|
||||
%span.sr-only= t 'views.actions.close'
|
||||
%ul.list-group.groups--list
|
||||
%ul.list-group
|
||||
- if current_user.has_role?(:administrator)
|
||||
= render 'modal/privileges/item', privilege: 'moderator', description: t('views.modal.privilege.moderator'), user: user
|
||||
= render 'modal/privileges/item', privilege: 'admin', description: t('views.modal.privilege.admin'), user: user
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
%li.list-group-item{ id: "group-#{group.name}" }
|
||||
.media
|
||||
.pull-left
|
||||
.custom-control.custom-checkbox
|
||||
%input.custom-control-input{ type: :checkbox,
|
||||
id: "groupCheck#{group.id}",
|
||||
name: 'gm-group-check',
|
||||
data: { group: group.name, user: user.screen_name }, checked: user.member_of?(group), autocomplete: :off }
|
||||
%label.custom-control-label{ for: "groupCheck#{group.id}" }
|
||||
.media-body
|
||||
.list-group-item-heading= group.display_name
|
||||
.list-group-item-text.text-muted
|
||||
%span{ id: "#{group.name}-members" }= group.members.count
|
||||
= t 'views.modal.group.members'
|
||||
·
|
||||
%a.text-danger#delete-group{ href: '#', data: { group: group.name } }
|
||||
%i.fa.fa-close
|
||||
= t 'views.actions.delete'
|
|
@ -0,0 +1,18 @@
|
|||
%li.list-group-item{ id: "list-#{list.name}" }
|
||||
.media
|
||||
.pull-left
|
||||
.custom-control.custom-checkbox
|
||||
%input.custom-control-input{ type: :checkbox,
|
||||
id: "listCheck#{list.id}",
|
||||
name: 'gm-list-check',
|
||||
data: { list: list.name, user: user.screen_name }, checked: user.member_of?(list), autocomplete: :off }
|
||||
%label.custom-control-label{ for: "listCheck#{list.id}" }
|
||||
.media-body
|
||||
.list-group-item-heading= list.display_name
|
||||
.list-group-item-text.text-muted
|
||||
%span{ id: "#{list.name}-members" }= list.members.count
|
||||
= t 'views.modal.list.members'
|
||||
·
|
||||
%a.text-danger#delete-list{ href: '#', data: { list: list.name } }
|
||||
%i.fa.fa-close
|
||||
= t 'views.actions.delete'
|
|
@ -13,10 +13,10 @@
|
|||
%ul.nav.navbar-nav
|
||||
- unless @user.nil?
|
||||
- unless @user == current_user
|
||||
%li.nav-item.d-none.d-sm-block{ data: { toggle: 'tooltip', placement: 'bottom' }, title: t('views.actions.group') }
|
||||
%a.nav-link{ href: '#', data: { target: '#modal-group-memberships', toggle: :modal } }
|
||||
%i.fa.fa-users.hidden-xs
|
||||
%span.d-none.d-sm-inline.d-md-none= t('views.actions.group')
|
||||
%li.nav-item.d-none.d-sm-block{ data: { toggle: 'tooltip', placement: 'bottom' }, title: t('views.actions.list') }
|
||||
%a.nav-link{ href: '#', data: { target: '#modal-list-memberships', toggle: :modal } }
|
||||
%i.fa.fa-list.hidden-xs
|
||||
%span.d-none.d-sm-inline.d-md-none= t('views.actions.list')
|
||||
= render 'navigation/main/notifications'
|
||||
%li.nav-item.d-none.d-sm-block{ data: { toggle: 'tooltip', placement: 'bottom' }, title: t('views.actions.ask_question') }
|
||||
%a.nav-link{ href: '#', name: 'toggle-all-ask', data: { target: '#modal-ask-followers', toggle: :modal } }
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
= current_user.display_name
|
||||
.profile__screen-name
|
||||
= current_user.screen_name
|
||||
- unless @group.nil?
|
||||
- unless @list.nil?
|
||||
.card
|
||||
.card-header= t('views.group.members')
|
||||
.card-header= t('views.list.members')
|
||||
.card-body
|
||||
- if @group.members.empty?
|
||||
%p.text-muted No members yet!
|
||||
- @group.members.each do |member|
|
||||
- if @list.members.empty?
|
||||
%p.text-muted No members yet.
|
||||
- @list.members.each do |member|
|
||||
%a{ href: show_user_profile_path(member.user.screen_name), title: member.user.screen_name, data: { toggle: :tooltip, placement: :top } }
|
||||
%img.avatar-xs{ src: member.user.profile_picture.url(:medium) }
|
||||
|
||||
|
|
|
@ -65,11 +65,10 @@
|
|||
.row
|
||||
.col-md-4.col-sm-4.col-xs-12
|
||||
%h3
|
||||
%i.fa.fa-fw.fa-users.text-primary
|
||||
Groups
|
||||
%i.fa.fa-fw.fa-list.text-primary
|
||||
Lists
|
||||
%p
|
||||
Want to ask a question to a specific set of people? No problem!
|
||||
Set up unique groups of users and send them questions apart from everyone else.
|
||||
Want to keep an oversight of things? Organise users in Lists to create timelines of their answers.
|
||||
.col-md-4.col-sm-4.col-xs-12
|
||||
%h3
|
||||
%i.fa.fa-fw.fa-image.text-primary
|
||||
|
|
|
@ -3,23 +3,22 @@
|
|||
= list_group_item t('views.general.timeline'), root_path
|
||||
- if APP_CONFIG.dig(:features, :public, :enabled)
|
||||
= list_group_item t('views.general.public'), public_timeline_path
|
||||
.list-group-item.list-group-item-action.dropdown{ class: group ? 'active' : '' }
|
||||
.list-group-item.list-group-item-action.dropdown{ class: list ? 'active' : '' }
|
||||
%a.dropdown-toggle{ type: :button, data: { toggle: :dropdown }, aria: { haspopup: true, expanded: false } }
|
||||
- if group
|
||||
= group.display_name
|
||||
- if list
|
||||
= list.display_name
|
||||
- else
|
||||
Groups
|
||||
Lists
|
||||
.dropdown-menu
|
||||
- if current_user.groups.empty?
|
||||
- if current_user.lists.empty?
|
||||
.p-3
|
||||
%p Looks like you don't have any groups yet.
|
||||
%p Looks like you don't have any lists yet.
|
||||
%p
|
||||
You can create groups and add users to them using the
|
||||
%i.fa.fa-fw.fa-users
|
||||
You can create lists and add users to them using the
|
||||
%i.fa.fa-fw.fa-list
|
||||
icon in the navigation on user profiles that are not yours.
|
||||
%p.mb-0
|
||||
Once you have done that, the groups will be listed here and
|
||||
when selected, you'll get a timeline view of all users from
|
||||
that group.
|
||||
- current_user.groups.each do |group|
|
||||
%a.dropdown-item{ href: group_timeline_path(group.name) }= group.display_name
|
||||
Once you have done that, the lists will be shown here.
|
||||
When you select a list you'll get a timeline view of all users within that list.
|
||||
- current_user.lists.each do |list|
|
||||
%a.dropdown-item{ href: list_timeline_path(list.name) }= list.display_name
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
= t 'views.actions.title'
|
||||
%span.caret
|
||||
.dropdown-menu
|
||||
%a.dropdown-item.d-block.d-sm-none{ href: '#', data: { target: '#modal-group-memberships', toggle: :modal } }
|
||||
%i.fa.fa-users
|
||||
= t 'views.actions.group'
|
||||
%a.dropdown-item.d-block.d-sm-none{ href: '#', data: { target: '#modal-list-memberships', toggle: :modal } }
|
||||
%i.fa.fa-list
|
||||
= t 'views.actions.list'
|
||||
%a.dropdown-item{ href: '#', data: { action: 'report-user', target: user.screen_name } }
|
||||
%i.fa.fa-exclamation-triangle
|
||||
= t 'views.actions.report'
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
%ul
|
||||
- @groups.each do |group|
|
||||
%li
|
||||
- if group.private?
|
||||
%i.fa.fa-lock
|
||||
= group.display_name
|
||||
|
||||
- provide(:title, user_title(@user, 'groups'))
|
||||
- parent_layout 'user/profile'
|
|
@ -0,0 +1,9 @@
|
|||
%ul
|
||||
- @lists.each do |list|
|
||||
%li
|
||||
- if list.private?
|
||||
%i.fa.fa-lock
|
||||
= list.display_name
|
||||
|
||||
- provide(:title, user_title(@user, 'lists'))
|
||||
- parent_layout 'user/profile'
|
|
@ -1,28 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QuestionWorker
|
||||
include Sidekiq::Worker
|
||||
|
||||
sidekiq_options queue: :question, retry: false
|
||||
|
||||
# @param rcpt [String] recipient
|
||||
# @param user_id [Integer] user id passed from Devise
|
||||
# @param question_id [Integer] newly created question id
|
||||
def perform(rcpt, user_id, question_id)
|
||||
begin
|
||||
user = User.find(user_id)
|
||||
if rcpt == 'followers'
|
||||
user.followers.each do |f|
|
||||
Inbox.create(user_id: f.id, question_id: question_id, new: true)
|
||||
end
|
||||
elsif rcpt.start_with? 'grp:'
|
||||
user.groups.find_by_name!(rcpt.sub 'grp:', '').members.each do |m|
|
||||
Inbox.create(user_id: m.user.id, question_id: question_id, new: true)
|
||||
end
|
||||
else
|
||||
logger.info "unknown rcpt #{rcpt}"
|
||||
end
|
||||
rescue => e
|
||||
logger.info "failed to ask question: #{e.message}"
|
||||
NewRelic::Agent.notice_error(e)
|
||||
def perform(user_id, question_id)
|
||||
user = User.find(user_id)
|
||||
|
||||
user.followers.each do |f|
|
||||
Inbox.create(user_id: f.id, question_id: question_id, new: true)
|
||||
end
|
||||
rescue StandardError => e
|
||||
logger.info "failed to ask question: #{e.message}"
|
||||
NewRelic::Agent.notice_error(e)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,8 +30,8 @@ RailsAdmin.config do |config|
|
|||
config.included_models = %w[
|
||||
Answer
|
||||
Comment
|
||||
Group
|
||||
GroupMember
|
||||
List
|
||||
ListMember
|
||||
Inbox
|
||||
Notification
|
||||
Question
|
||||
|
|
|
@ -14,7 +14,7 @@ cs:
|
|||
fail:
|
||||
subscribe: "Nepodařilo se přihlásit k odběru na odpovědi."
|
||||
unsubscribe: "Nepodařilo se zrušit odběr na odpovědi."
|
||||
group:
|
||||
list:
|
||||
confirm:
|
||||
title: "Opravdu chcete smazat tuto skupinu?"
|
||||
text: "Nebudete tuto skupinu moci obnovit."
|
||||
|
@ -95,7 +95,7 @@ cs:
|
|||
destroy:
|
||||
fail: "Nesledujete tohoto uživatele."
|
||||
okay: "Používatel úspěšně odsledován."
|
||||
group:
|
||||
list:
|
||||
create:
|
||||
noname: "Prosím pojmenujte tuto skupinu."
|
||||
toolong: "Jméno skupiny příliš dlhé (max. 30 znaků)"
|
||||
|
@ -235,7 +235,7 @@ cs:
|
|||
terms: "Podmínky služby"
|
||||
privacy: "Ochrana osobních údajů"
|
||||
about: "O něm"
|
||||
group:
|
||||
list:
|
||||
title: "Skupina"
|
||||
members: "Členové"
|
||||
actions:
|
||||
|
@ -254,7 +254,7 @@ cs:
|
|||
load: "Načíst víc"
|
||||
follow: "Sledovat"
|
||||
unfollow: "Nesledovat"
|
||||
group: "Spravovat skupinové členství"
|
||||
list: "Spravovat skupinové členství"
|
||||
ban: "Správa Banů"
|
||||
privilege: "Zkontrolovat výsady %{user}"
|
||||
save: "Uložit změny"
|
||||
|
@ -424,7 +424,7 @@ cs:
|
|||
permanent: "Permanentně?"
|
||||
reason: "Důvod"
|
||||
hammertime: "Hammer Time"
|
||||
group:
|
||||
list:
|
||||
title: "Spravovat skupinové členství"
|
||||
tabs:
|
||||
main: "Skupiny"
|
||||
|
|
|
@ -14,10 +14,10 @@ de:
|
|||
fail:
|
||||
subscribe: "Das Abonnieren der Antwort schlug fehl."
|
||||
unsubscribe: "Das Deabonnieren der Antwort schlug fehl."
|
||||
group:
|
||||
list:
|
||||
confirm:
|
||||
title: "Diese Gruppe wirklich löschen?"
|
||||
text: "Es wird nicht möglich sein, diese Gruppe wieder zu erhalten."
|
||||
title: "Diese Liste wirklich löschen?"
|
||||
text: "Es wird nicht möglich sein, diese Liste wieder zu erhalten."
|
||||
destroy_question:
|
||||
confirm:
|
||||
title: "Bist du sicher?"
|
||||
|
@ -97,20 +97,20 @@ de:
|
|||
destroy:
|
||||
fail: "Du folgst diesem Benutzer nicht."
|
||||
okay: "Erfolgreich Benutzer entfolgt."
|
||||
group:
|
||||
list:
|
||||
create:
|
||||
noname: "Bitte gib dieser Gruppe einen Namen."
|
||||
toolong: "Gruppenname zu lang (maximal 30 Zeichen)"
|
||||
noname: "Bitte gib dieser Liste einen Namen."
|
||||
toolong: "Listenname zu lang (maximal 30 Zeichen)"
|
||||
notfound: "Konnte Benutzer nicht finden."
|
||||
exists: "Gruppe existiert bereits."
|
||||
okay: "Gruppe erfolgreich erstellt."
|
||||
exists: "Liste existiert bereits."
|
||||
okay: "Liste erfolgreich erstellt."
|
||||
destroy:
|
||||
notfound: "Konnte Gruppe nicht finden."
|
||||
okay: "Gruppe erfolgreich gelöscht."
|
||||
notfound: "Konnte Liste nicht finden."
|
||||
okay: "Liste erfolgreich gelöscht."
|
||||
membership:
|
||||
notfound: "Gruppe nicht gefunden."
|
||||
add: "Benutzer erfolgreich zur Gruppe hinzugefügt."
|
||||
remove: "Benutzer erfolgreich aus Gruppe entfernt."
|
||||
notfound: "Liste nicht gefunden."
|
||||
add: "Benutzer erfolgreich zur Liste hinzugefügt."
|
||||
remove: "Benutzer erfolgreich aus Liste entfernt."
|
||||
inbox:
|
||||
create:
|
||||
okay: "Erfolgreich neue Frage hinzugefügt."
|
||||
|
@ -152,7 +152,7 @@ de:
|
|||
okay: "Frage erfolgreich gelöscht."
|
||||
create:
|
||||
rec_inv: "Deine Frage ist zu lang."
|
||||
not_found: "Gruppe nicht gefunden"
|
||||
not_found: "Liste nicht gefunden"
|
||||
okay: "Frage erfolgreich gestellt."
|
||||
report:
|
||||
create:
|
||||
|
@ -237,8 +237,8 @@ de:
|
|||
terms: "Allgemeine Nutzungsbedingungen"
|
||||
privacy: Datenschutz
|
||||
about: Über
|
||||
group:
|
||||
title: Gruppe
|
||||
list:
|
||||
title: Liste
|
||||
members: Mitglieder
|
||||
actions:
|
||||
title: Aktionen
|
||||
|
@ -256,7 +256,7 @@ de:
|
|||
load: Mehr...
|
||||
follow: Folgen
|
||||
unfollow: Entfolgen
|
||||
group: "Verwalten von Gruppenmitgliedschaften"
|
||||
list: "Verwalten von Listenmitgliedschaften"
|
||||
ban: Bann-Steuerung
|
||||
privilege: "Prüfe %{user}'s Privilegien"
|
||||
save: "Änderungen speichern"
|
||||
|
@ -420,7 +420,7 @@ de:
|
|||
modal:
|
||||
ask:
|
||||
title: "Frage deine Follower"
|
||||
choose: "Gruppe:"
|
||||
choose: "Liste:"
|
||||
loading: Fragen…
|
||||
bancontrol:
|
||||
title: Bannkontrollzentrum
|
||||
|
@ -428,13 +428,13 @@ de:
|
|||
permanent: "Für immer?"
|
||||
reason: Grund
|
||||
hammertime: Hammerzeit!
|
||||
group:
|
||||
title: "Gruppenzugehörigkeit verwalten"
|
||||
list:
|
||||
title: "Listenzugehörigkeit verwalten"
|
||||
tabs:
|
||||
main: Gruppen
|
||||
create: "Neue Gruppe erstellen"
|
||||
create: "Gruppe erstellen"
|
||||
name: Gruppenname
|
||||
main: Listen
|
||||
create: "Neue Liste erstellen"
|
||||
create: "Liste erstellen"
|
||||
name: Listenname
|
||||
members: Mitglieder
|
||||
privilege:
|
||||
blogger: "Der Benutzer erhält dieses Privileg wenn er etwas (nettes) über Retrospring gebloggt hat."
|
||||
|
|
|
@ -13,10 +13,10 @@ en:
|
|||
fail:
|
||||
subscribe: "Failed to subscribe to answer."
|
||||
unsubscribe: "Failed to unsubscribe from answer."
|
||||
group:
|
||||
list:
|
||||
confirm:
|
||||
title: "Really delete this group?"
|
||||
text: "You will not be able to recover this group."
|
||||
title: "Really delete this list?"
|
||||
text: "You will not be able to recover this list."
|
||||
destroy_question:
|
||||
confirm:
|
||||
title: "Are you sure?"
|
||||
|
@ -94,20 +94,20 @@ en:
|
|||
destroy:
|
||||
fail: "You are not following that user."
|
||||
okay: "Successfully unfollowed user."
|
||||
group:
|
||||
list:
|
||||
create:
|
||||
noname: "Please give that group a name."
|
||||
toolong: "Group name too long (30 characters max.)"
|
||||
noname: "Please give that list a name."
|
||||
toolong: "List name too long (30 characters max.)"
|
||||
notfound: "Could not find user."
|
||||
exists: "Group already exists."
|
||||
okay: "Successfully created group."
|
||||
exists: "List already exists."
|
||||
okay: "Successfully created list."
|
||||
destroy:
|
||||
notfound: "Could not find group."
|
||||
okay: "Successfully deleted group."
|
||||
notfound: "Could not find list."
|
||||
okay: "Successfully deleted list."
|
||||
membership:
|
||||
notfound: "Group not found."
|
||||
add: "Successfully added user to group."
|
||||
remove: "Successfully removed user from group."
|
||||
notfound: "List not found."
|
||||
add: "Successfully added user to list."
|
||||
remove: "Successfully removed user from list."
|
||||
inbox:
|
||||
create:
|
||||
okay: "Successfully added new question."
|
||||
|
@ -149,7 +149,7 @@ en:
|
|||
okay: "Successfully deleted question."
|
||||
create:
|
||||
rec_inv: "Your question is too long."
|
||||
not_found: "Group not found"
|
||||
not_found: "List not found"
|
||||
okay: "Question asked successfully."
|
||||
report:
|
||||
create:
|
||||
|
@ -237,8 +237,8 @@ en:
|
|||
terms: "Terms of Service"
|
||||
privacy: "Privacy Policy"
|
||||
about: "About"
|
||||
group:
|
||||
title: "Group"
|
||||
list:
|
||||
title: "List"
|
||||
members: "Members"
|
||||
actions:
|
||||
title: "Actions"
|
||||
|
@ -256,7 +256,7 @@ en:
|
|||
load: "Load more"
|
||||
follow: "Follow"
|
||||
unfollow: "Unfollow"
|
||||
group: "Manage group memberships"
|
||||
list: "Manage list memberships"
|
||||
ban: "Ban Control"
|
||||
privilege: "Check %{user}'s privileges"
|
||||
save: "Save changes"
|
||||
|
@ -418,7 +418,7 @@ en:
|
|||
modal:
|
||||
ask:
|
||||
title: "Ask your followers"
|
||||
choose: "Choose group:"
|
||||
choose: "Choose list:"
|
||||
loading: "Asking..."
|
||||
bancontrol:
|
||||
title: "Ban Control Center"
|
||||
|
@ -426,13 +426,13 @@ en:
|
|||
permanent: "Permanently?"
|
||||
reason: "Reason"
|
||||
hammertime: "Hammer Time"
|
||||
group:
|
||||
title: "Manage group memberships"
|
||||
list:
|
||||
title: "Manage list memberships"
|
||||
tabs:
|
||||
main: "Groups"
|
||||
create: "Create new group"
|
||||
create: "Create group"
|
||||
name: "Group name"
|
||||
main: "Lists"
|
||||
create: "Create new list"
|
||||
create: "Create list"
|
||||
name: "List name"
|
||||
members: "members"
|
||||
privilege:
|
||||
moderator: "Someone trustworthy enough to help managing reports."
|
||||
|
|
|
@ -13,10 +13,10 @@ en_dizzle:
|
|||
fail:
|
||||
subscribe: "Failed ta subscribe ta answer."
|
||||
unsubscribe: "Failed ta unsubscribe from answer."
|
||||
group:
|
||||
list:
|
||||
confirm:
|
||||
title: "Straight-Up delete dis group?"
|
||||
text: "Yo ass aint gonna be able ta recover dis group."
|
||||
title: "Straight-Up delete dis list?"
|
||||
text: "Yo ass aint gonna be able ta recover dis list."
|
||||
destroy_question:
|
||||
confirm:
|
||||
title: "Is you sure?"
|
||||
|
@ -94,20 +94,20 @@ en_dizzle:
|
|||
destroy:
|
||||
fail: "Yo ass aint followin dat user."
|
||||
okay: "Successfully unfollowed user."
|
||||
group:
|
||||
list:
|
||||
create:
|
||||
noname: "Please give dat crew a name."
|
||||
toolong: "Group name too long (30 charactas max.)"
|
||||
toolong: "List name too long (30 charactas max.)"
|
||||
notfound: "Could not find user."
|
||||
exists: "Group already exists."
|
||||
okay: "Successfully pimped group."
|
||||
exists: "List already exists."
|
||||
okay: "Successfully pimped list."
|
||||
destroy:
|
||||
notfound: "Could not find group."
|
||||
okay: "Successfully deleted group."
|
||||
notfound: "Could not find list."
|
||||
okay: "Successfully deleted list."
|
||||
membership:
|
||||
notfound: "Group not found."
|
||||
add: "Successfully added user ta group."
|
||||
remove: "Successfully removed user from group."
|
||||
notfound: "List not found."
|
||||
add: "Successfully added user ta list."
|
||||
remove: "Successfully removed user from list."
|
||||
inbox:
|
||||
create:
|
||||
okay: "Successfully added freshly smoked up question."
|
||||
|
@ -149,7 +149,7 @@ en_dizzle:
|
|||
okay: "Successfully deleted question."
|
||||
create:
|
||||
rec_inv: "Yo crazy-ass question is too long."
|
||||
not_found: "Group not found"
|
||||
not_found: "List not found"
|
||||
okay: "Question asked successfully."
|
||||
report:
|
||||
create:
|
||||
|
@ -235,7 +235,7 @@ en_dizzle:
|
|||
terms: "Tha termz"
|
||||
privacy: "Shit that no one ain't read"
|
||||
about: "'bout"
|
||||
group:
|
||||
list:
|
||||
title: "Fam"
|
||||
members: "Peepz"
|
||||
actions:
|
||||
|
@ -254,7 +254,7 @@ en_dizzle:
|
|||
load: "Load sum more"
|
||||
follow: "Go check on tha homeboy"
|
||||
unfollow: "Stop checkin' on tha homeboy"
|
||||
group: "Manage crew memberships"
|
||||
list: "Manage crew memberships"
|
||||
ban: "Banish that fucker"
|
||||
privilege: "Peep %{user}z privileges"
|
||||
save: "Save chizzles"
|
||||
|
@ -424,7 +424,7 @@ en_dizzle:
|
|||
permanent: "Fo' all the timez?"
|
||||
reason: "Reason"
|
||||
hammertime: "Hammer Time"
|
||||
group:
|
||||
list:
|
||||
title: "Manage crew memberships"
|
||||
tabs:
|
||||
main: "Crews"
|
||||
|
|
|
@ -13,7 +13,7 @@ en_pirate:
|
|||
fail:
|
||||
subscribe: "Failed to subscribe to answer."
|
||||
unsubscribe: "Failed to unsubscribe from answer."
|
||||
group:
|
||||
list:
|
||||
confirm:
|
||||
title: "D' ye wish to send this crew t' Davy Jones' Locker?"
|
||||
text: "Ye gunna not be able to recover 'tis crew."
|
||||
|
@ -94,7 +94,7 @@ en_pirate:
|
|||
destroy:
|
||||
fail: "Ye not be spyin' on that user."
|
||||
okay: "No longer spyin' on user."
|
||||
group:
|
||||
list:
|
||||
create:
|
||||
noname: "Please gift that crew a moniker."
|
||||
toolong: "Crew moniker too long (30 characters max.)"
|
||||
|
@ -235,7 +235,7 @@ en_pirate:
|
|||
terms: "Terms of ye Service"
|
||||
privacy: "Pirat-y Policy"
|
||||
about: "About"
|
||||
group:
|
||||
list:
|
||||
title: "Crew"
|
||||
members: "Members"
|
||||
actions:
|
||||
|
@ -254,7 +254,7 @@ en_pirate:
|
|||
load: "Load more"
|
||||
follow: "Spy"
|
||||
unfollow: "Un-Spy"
|
||||
group: "Manage Crew memberships"
|
||||
list: "Manage Crew memberships"
|
||||
ban: "Ban Control"
|
||||
privilege: "Check %{user}'s privileges"
|
||||
save: "Save changes"
|
||||
|
@ -424,7 +424,7 @@ en_pirate:
|
|||
permanent: "Permanently?"
|
||||
reason: "Reason"
|
||||
hammertime: "Ye olde Hammer Time!"
|
||||
group:
|
||||
list:
|
||||
title: "Manage crew memberships"
|
||||
tabs:
|
||||
main: "Crews"
|
||||
|
|
|
@ -14,9 +14,9 @@ fr:
|
|||
fail:
|
||||
subscribe: "Échec de l'abonnement à la réponse."
|
||||
unsubscribe: "Échec du désabonnement à la réponse."
|
||||
group:
|
||||
list:
|
||||
confirm:
|
||||
title: "Voulez-vous vraiment supprimer ce groupe ?"
|
||||
title: "Voulez-vous vraiment supprimer cette liste ?"
|
||||
text: "Vous ne pourrez pas le récupérer."
|
||||
destroy_question:
|
||||
confirm:
|
||||
|
@ -97,18 +97,18 @@ fr:
|
|||
destroy:
|
||||
fail: "Vous ne suivez pas cet utilisateur."
|
||||
okay: "Vous ne suivez plus cet utilisateur."
|
||||
group:
|
||||
list:
|
||||
create:
|
||||
noname: "Veuillez donner un nom à ce groupe."
|
||||
toolong: "Le nom du groupe est trop long (30 caractères max.)"
|
||||
noname: "Veuillez donner un nom à cette liste."
|
||||
toolong: "Le nom de la liste est trop long (30 caractères max.)"
|
||||
notfound: "L'utilisateur est introuvable."
|
||||
exists: "Ce groupe existe déjà."
|
||||
okay: "Le groupe a été créé avec succès."
|
||||
exists: "Cette liste existe déjà."
|
||||
okay: "La liste a été créé avec succès."
|
||||
destroy:
|
||||
notfound: "Le groupe est introuvable."
|
||||
okay: "Le groupe a été supprimé avec succès."
|
||||
notfound: "La liste est introuvable."
|
||||
okay: "La liste a été supprimé avec succès."
|
||||
membership:
|
||||
notfound: "Le groupe est introuvable."
|
||||
notfound: "La liste est introuvable."
|
||||
add: "L'utilisateur a été ajouté avec succès."
|
||||
remove: "L'utilisateur a été enlevé avec succès."
|
||||
inbox:
|
||||
|
@ -152,7 +152,7 @@ fr:
|
|||
okay: "La question a été supprimée avec succès."
|
||||
create:
|
||||
rec_inv: "Votre question est trop longue."
|
||||
not_found: "Le groupe est introuvable."
|
||||
not_found: "La liste est introuvable."
|
||||
okay: "La question a été posée avec succès."
|
||||
report:
|
||||
create:
|
||||
|
@ -237,8 +237,8 @@ fr:
|
|||
terms: "Conditions générales d'utilisation"
|
||||
privacy: "Politique de confidentialité"
|
||||
about: "À propos"
|
||||
group:
|
||||
title: "Groupe"
|
||||
list:
|
||||
title: "Liste"
|
||||
members: "Membres"
|
||||
actions:
|
||||
title: "Actions"
|
||||
|
@ -256,7 +256,7 @@ fr:
|
|||
load: "Charger plus"
|
||||
follow: "Suivre"
|
||||
unfollow: "Ne plus suivre"
|
||||
group: "Gérer l'appartenance à un groupe"
|
||||
list: "Gérer l'appartenance à une liste"
|
||||
ban: "Contrôle des bannissements"
|
||||
privilege: "Vérifier les privilèges de %{user}"
|
||||
save: "Enregistrer les modifications"
|
||||
|
@ -418,7 +418,7 @@ fr:
|
|||
modal:
|
||||
ask:
|
||||
title: "Poser une question à vos abonnés"
|
||||
choose: "Choisir un groupe :"
|
||||
choose: "Choisir une liste :"
|
||||
loading: "Envoi..."
|
||||
bancontrol:
|
||||
title: "Centre de contrôle des bannissements"
|
||||
|
@ -426,13 +426,13 @@ fr:
|
|||
permanent: "Définitivement ?"
|
||||
reason: "Raison"
|
||||
hammertime: "Que le Marteau s'abatte"
|
||||
group:
|
||||
title: "Gérer l'appartenance à un groupe"
|
||||
list:
|
||||
title: "Gérer l'appartenance à une liste"
|
||||
tabs:
|
||||
main: "Groupes"
|
||||
create: "Créer un nouveau groupe"
|
||||
main: "Listes"
|
||||
create: "Créer une nouvelle liste"
|
||||
create: "Créer"
|
||||
name: "Nom du groupe"
|
||||
name: "Nom de la liste"
|
||||
members: "membres"
|
||||
privilege:
|
||||
blogger: "L'utilisateur obtient ce titre s'il a posté un article (agréable) à propos de Retrospring."
|
||||
|
|
|
@ -13,7 +13,7 @@ it:
|
|||
fail:
|
||||
subscribe: "Impossibile iscriversi alla risposta."
|
||||
unsubscribe: "Impossibile disiscriversi dalla risposta."
|
||||
group:
|
||||
list:
|
||||
confirm:
|
||||
title: "Vuoi davvero eliminare questo gruppo?"
|
||||
text: "Non sarai più in grado di recuperare questo gruppo."
|
||||
|
@ -94,7 +94,7 @@ it:
|
|||
destroy:
|
||||
fail: "Non stai seguendo quell'utente."
|
||||
okay: "Non stai più seguendo quell'utente."
|
||||
group:
|
||||
list:
|
||||
create:
|
||||
noname: "Per favore, dai un nome a quel gruppo."
|
||||
toolong: "Nome del gruppo troppo grande (massimo 30 caratteri)"
|
||||
|
@ -236,7 +236,7 @@ it:
|
|||
terms: "Termini di Servizio"
|
||||
privacy: "Normativa sulla privacy"
|
||||
about: "Informazioni"
|
||||
group:
|
||||
list:
|
||||
title: "Gruppo"
|
||||
members: "Membri"
|
||||
actions:
|
||||
|
@ -255,7 +255,7 @@ it:
|
|||
load: "Carica altro"
|
||||
follow: "Segui"
|
||||
unfollow: "Non seguire più"
|
||||
group: "Impostazioni sui gruppi"
|
||||
list: "Impostazioni sui gruppi"
|
||||
ban: "Controlla Ban"
|
||||
privilege: "Controlla i privilegi dell'%{user}"
|
||||
save: "Salva le impostazioni"
|
||||
|
@ -425,7 +425,7 @@ it:
|
|||
permanent: Permanentemente?
|
||||
reason: "Motivo"
|
||||
hammertime: "Tempo del ban"
|
||||
group:
|
||||
list:
|
||||
title: "Gestisci appartenenza a gruppi"
|
||||
tabs:
|
||||
main: "Gruppi"
|
||||
|
|
|
@ -13,7 +13,7 @@ ja:
|
|||
fail:
|
||||
subscribe: 回答の購読に失敗しました。
|
||||
unsubscribe: 回答の購読の解除に失敗しました。
|
||||
group:
|
||||
list:
|
||||
confirm:
|
||||
title: このグループを削除してもよろしいですか?
|
||||
text: このグループを復元することはできなくなります。
|
||||
|
@ -96,7 +96,7 @@ ja:
|
|||
destroy:
|
||||
fail: このユーザーをフォローしていません。
|
||||
okay: フォローの解除に成功しました。
|
||||
group:
|
||||
list:
|
||||
create:
|
||||
noname: グループに名前をつけてください。
|
||||
toolong: グループ名が長過ぎます(最大30文字)
|
||||
|
@ -236,7 +236,7 @@ ja:
|
|||
terms: 利用規約
|
||||
privacy: プライバシーポリシー
|
||||
about: Retrospringについて
|
||||
group:
|
||||
list:
|
||||
title: グループ
|
||||
members: メンバー
|
||||
actions:
|
||||
|
@ -255,7 +255,7 @@ ja:
|
|||
load: つづきを読み込む
|
||||
follow: フォロー
|
||||
unfollow: フォロー解除
|
||||
group: グループのメンバーを管理
|
||||
list: グループのメンバーを管理
|
||||
ban: 利用停止管理
|
||||
privilege: "%{user}の権限を確認する"
|
||||
save: 変更を保存する
|
||||
|
@ -425,7 +425,7 @@ ja:
|
|||
permanent: 永久的に追放しますか?
|
||||
reason: 理由
|
||||
hammertime: 利用停止時間
|
||||
group:
|
||||
list:
|
||||
title: グループのメンバーを管理
|
||||
tabs:
|
||||
main: グループ
|
||||
|
|
|
@ -102,16 +102,16 @@ Rails.application.routes.draw do
|
|||
match '/create_comment', to: 'comment#create', via: :post, as: :create_comment
|
||||
match '/destroy_comment', to: 'comment#destroy', via: :post, as: :destroy_comment
|
||||
match '/report', to: 'report#create', via: :post, as: :report
|
||||
match '/create_group', to: 'group#create', via: :post, as: :create_group
|
||||
match '/destroy_group', to: 'group#destroy', via: :post, as: :destroy_group
|
||||
match '/group_membership', to: 'group#membership', via: :post, as: :group_membership
|
||||
match '/create_list', to: 'list#create', via: :post, as: :create_list
|
||||
match '/destroy_list', to: 'list#destroy', via: :post, as: :destroy_list
|
||||
match '/list_membership', to: 'list#membership', via: :post, as: :list_membership
|
||||
match '/subscribe', to: 'subscription#subscribe', via: :post, as: :subscribe_answer
|
||||
match '/unsubscribe', to: 'subscription#unsubscribe', via: :post, as: :unsubscribe_answer
|
||||
end
|
||||
|
||||
match '/discover', to: 'discover#index', via: :get, as: :discover
|
||||
match '/public', to: 'public#index', via: :get, as: :public_timeline if APP_CONFIG.dig(:features, :public, :enabled)
|
||||
match '/group/:group_name', to: 'group#index', via: :get, as: :group_timeline
|
||||
match '/list/:list_name', to: 'list#index', via: :get, as: :list_timeline
|
||||
|
||||
match '/notifications(/:type)', to: 'notifications#index', via: :get, as: :notifications, defaults: {type: 'new'}
|
||||
|
||||
|
@ -129,7 +129,7 @@ Rails.application.routes.draw do
|
|||
match '/:username/q/:id', to: 'question#show', via: 'get', as: :show_user_question
|
||||
match '/:username/followers(/p/:page)', to: 'user#followers', via: 'get', as: :show_user_followers, defaults: {page: 1}
|
||||
match '/:username/friends(/p/:page)', to: 'user#friends', via: 'get', as: :show_user_friends, defaults: {page: 1}
|
||||
match '/:username/groups(/p/:page)', to: 'user#groups', via: 'get', as: :show_user_groups, defaults: {page: 1}
|
||||
match '/:username/lists(/p/:page)', to: 'user#lists', via: 'get', as: :show_user_lists, defaults: {page: 1}
|
||||
match '/:username/questions(/p/:page)', to: 'user#questions', via: 'get', as: :show_user_questions, defaults: {page: 1}
|
||||
|
||||
puts 'processing time of routes.rb: ' + "#{(Time.now - start).round(3).to_s.ljust(5, '0')}s".light_green
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RenameGroupsToLists < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
say "Renaming group-related tables"
|
||||
rename_table :groups, :lists
|
||||
rename_table :group_members, :list_members
|
||||
|
||||
say "Renaming group-related columns"
|
||||
rename_column :list_members, :group_id, :list_id
|
||||
|
||||
say "Cleaning up unused/already covered indexes"
|
||||
# Rails already renames the indexes for us when we rename tables or columns.
|
||||
# Neat!
|
||||
remove_index :list_members, name: "index_list_members_on_list_id"
|
||||
remove_index :list_members, name: "index_list_members_on_user_id"
|
||||
remove_index :lists, name: "index_lists_on_name"
|
||||
remove_index :lists, name: "index_lists_on_user_id"
|
||||
end
|
||||
end
|
42
db/schema.rb
42
db/schema.rb
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2020_05_17_192431) do
|
||||
ActiveRecord::Schema.define(version: 2020_05_25_145144) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -60,28 +60,6 @@ ActiveRecord::Schema.define(version: 2020_05_17_192431) do
|
|||
t.index ["user_id", "created_at"], name: "index_comments_on_user_id_and_created_at"
|
||||
end
|
||||
|
||||
create_table "group_members", id: :serial, force: :cascade do |t|
|
||||
t.integer "group_id", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.index ["group_id", "user_id"], name: "index_group_members_on_group_id_and_user_id", unique: true
|
||||
t.index ["group_id"], name: "index_group_members_on_group_id"
|
||||
t.index ["user_id"], name: "index_group_members_on_user_id"
|
||||
end
|
||||
|
||||
create_table "groups", id: :serial, force: :cascade do |t|
|
||||
t.integer "user_id", null: false
|
||||
t.string "name"
|
||||
t.string "display_name"
|
||||
t.boolean "private", default: true
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.index ["name"], name: "index_groups_on_name"
|
||||
t.index ["user_id", "name"], name: "index_groups_on_user_id_and_name", unique: true
|
||||
t.index ["user_id"], name: "index_groups_on_user_id"
|
||||
end
|
||||
|
||||
create_table "inboxes", id: :serial, force: :cascade do |t|
|
||||
t.integer "user_id"
|
||||
t.integer "question_id"
|
||||
|
@ -91,6 +69,24 @@ ActiveRecord::Schema.define(version: 2020_05_17_192431) do
|
|||
t.index ["user_id"], name: "index_inboxes_on_user_id"
|
||||
end
|
||||
|
||||
create_table "list_members", id: :serial, force: :cascade do |t|
|
||||
t.integer "list_id", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.index ["list_id", "user_id"], name: "index_list_members_on_list_id_and_user_id", unique: true
|
||||
end
|
||||
|
||||
create_table "lists", id: :serial, force: :cascade do |t|
|
||||
t.integer "user_id", null: false
|
||||
t.string "name"
|
||||
t.string "display_name"
|
||||
t.boolean "private", default: true
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.index ["user_id", "name"], name: "index_lists_on_user_id_and_name", unique: true
|
||||
end
|
||||
|
||||
create_table "moderation_comments", id: :serial, force: :cascade do |t|
|
||||
t.integer "report_id"
|
||||
t.integer "user_id"
|
||||
|
|
|
@ -6,7 +6,7 @@ Upon creation of a Retrospring account, some personal information such as your
|
|||
|
||||
Public information like a short biography, a link to your website, your location or a profile picture can be provided after registration. This information is viewable by any visitor of the site, registered or unregistered, and therefore should not contain any critical information about you or someone else.
|
||||
#### Answers and Questions
|
||||
Our Service primarily is designed to ask your friends and other people from around the world questions or answer them. Most of the information you provide us is information you are asking us to make public. This information does not only include the questions, answers, comments and smiles, but also the groups you create, the people you follow and other bits of information that result from using our Service.
|
||||
Our Service primarily is designed to ask your friends and other people from around the world questions or answer them. Most of the information you provide us is information you are asking us to make public. This information does not only include the questions, answers, comments and smiles, but also the lists you create, the people you follow and other bits of information that result from using our Service.
|
||||
#### Cookies
|
||||
Like many websites, we use cookies and similar technologies to collect additional website usage data and to improve our Services. A cookie is a small data file that is transferred to your computer's hard disk. Retrospring uses persistant cookies to improve the users browsing experience and to to better understand how you interact with our Services. Most Internet browsers automatically accept cookies. You can instruct your browser, by changing its settings, to stop accepting cookies or to prompt you before accepting a cookie from the websites you visit. However, the Services may not function properly if you disable cookies.
|
||||
#### Non-personal Identification Information
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require "rails_helper"
|
||||
|
||||
describe Ajax::GroupController, :ajax_controller, type: :controller do
|
||||
describe Ajax::ListController, :ajax_controller, type: :controller do
|
||||
let(:target_user) { FactoryBot.create(:user) }
|
||||
|
||||
describe "#create" do
|
||||
|
@ -29,8 +29,8 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
|
||||
before(:each) { sign_in(user) }
|
||||
|
||||
it "creates the group" do
|
||||
expect { subject }.to(change { user.groups.count }.by(1))
|
||||
it "creates the list" do
|
||||
expect { subject }.to(change { user.lists.count }.by(1))
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
@ -45,8 +45,8 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
}
|
||||
end
|
||||
|
||||
it "does not create the group" do
|
||||
expect { subject }.not_to(change { user.groups.count })
|
||||
it "does not create the list" do
|
||||
expect { subject }.not_to(change { user.lists.count })
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
@ -62,14 +62,14 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
}
|
||||
end
|
||||
|
||||
it "does not create the group" do
|
||||
expect { subject }.not_to(change { user.groups.count })
|
||||
it "does not create the list" do
|
||||
expect { subject }.not_to(change { user.lists.count })
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
end
|
||||
|
||||
context "when group name is invalid for reasons" do
|
||||
context "when list name is invalid for reasons" do
|
||||
let(:name) { "\u{1f43e}" }
|
||||
let(:expected_response) do
|
||||
{
|
||||
|
@ -79,14 +79,14 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
}
|
||||
end
|
||||
|
||||
it "does not create the group" do
|
||||
expect { subject }.not_to(change { user.groups.count })
|
||||
it "does not create the list" do
|
||||
expect { subject }.not_to(change { user.lists.count })
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
end
|
||||
|
||||
context "when group already exists" do
|
||||
context "when list already exists" do
|
||||
before(:each) { post(:create, params: params) }
|
||||
let(:expected_response) do
|
||||
{
|
||||
|
@ -96,20 +96,20 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
}
|
||||
end
|
||||
|
||||
it "does not create the group" do
|
||||
expect { subject }.not_to(change { user.groups.count })
|
||||
it "does not create the list" do
|
||||
expect { subject }.not_to(change { user.lists.count })
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
end
|
||||
|
||||
context "when someone else created a group with the same name" do
|
||||
context "when someone else created a list with the same name" do
|
||||
before(:each) do
|
||||
FactoryBot.create(:group, user: target_user, display_name: name)
|
||||
FactoryBot.create(:list, user: target_user, display_name: name)
|
||||
end
|
||||
|
||||
it "creates the group" do
|
||||
expect { subject }.to(change { user.groups.count }.by(1))
|
||||
it "creates the list" do
|
||||
expect { subject }.to(change { user.lists.count }.by(1))
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
@ -131,11 +131,11 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
|
||||
describe "#destroy" do
|
||||
let(:name) { "I signori della gallassia" }
|
||||
let(:group) { FactoryBot.create(:group, user: user, display_name: name) }
|
||||
let(:group_param) { group.name }
|
||||
let(:list) { FactoryBot.create(:list, user: user, display_name: name) }
|
||||
let(:list_param) { list.name }
|
||||
let(:params) do
|
||||
{
|
||||
"group" => group_param
|
||||
"list" => list_param
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -152,15 +152,15 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
|
||||
before(:each) { sign_in(user) }
|
||||
|
||||
it "deletes the group" do
|
||||
group
|
||||
expect { subject }.to(change { user.groups.count }.by(-1))
|
||||
it "deletes the list" do
|
||||
list
|
||||
expect { subject }.to(change { user.lists.count }.by(-1))
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
||||
context "when group param is missing" do
|
||||
let(:group_param) { "" }
|
||||
context "when list param is missing" do
|
||||
let(:list_param) { "" }
|
||||
let(:expected_response) do
|
||||
{
|
||||
"success" => false,
|
||||
|
@ -169,15 +169,15 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
}
|
||||
end
|
||||
|
||||
it "does not delete the group" do
|
||||
expect { subject }.not_to(change { user.groups.count })
|
||||
it "does not delete the list" do
|
||||
expect { subject }.not_to(change { user.lists.count })
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
end
|
||||
|
||||
context "when group does not exist" do
|
||||
let(:group_param) { "the-foobars-and-the-dingdongs" }
|
||||
context "when list does not exist" do
|
||||
let(:list_param) { "the-foobars-and-the-dingdongs" }
|
||||
let(:expected_response) do
|
||||
{
|
||||
"success" => false,
|
||||
|
@ -186,25 +186,25 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
}
|
||||
end
|
||||
|
||||
it "does not delete the group" do
|
||||
expect { subject }.not_to(change { user.groups.count })
|
||||
it "does not delete the list" do
|
||||
expect { subject }.not_to(change { user.lists.count })
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
end
|
||||
|
||||
context "when someone else created a group with the same name" do
|
||||
context "when someone else created a list with the same name" do
|
||||
before(:each) do
|
||||
group
|
||||
FactoryBot.create(:group, user: target_user, display_name: name)
|
||||
list
|
||||
FactoryBot.create(:list, user: target_user, display_name: name)
|
||||
end
|
||||
|
||||
it "deletes the group" do
|
||||
expect { subject }.to(change { user.groups.count }.by(-1))
|
||||
it "deletes the list" do
|
||||
expect { subject }.to(change { user.lists.count }.by(-1))
|
||||
end
|
||||
|
||||
it "does not delete the other users' group" do
|
||||
expect { subject }.not_to(change { target_user.groups.count })
|
||||
it "does not delete the other users' list" do
|
||||
expect { subject }.not_to(change { target_user.lists.count })
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
@ -227,12 +227,12 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
describe "#membership" do
|
||||
let(:name) { "The Agency" }
|
||||
let(:members) { [] }
|
||||
let(:group) { FactoryBot.create(:group, user: user, display_name: name, members: members) }
|
||||
let(:group_param) { group.name }
|
||||
let(:list) { FactoryBot.create(:list, user: user, display_name: name, members: members) }
|
||||
let(:list_param) { list.name }
|
||||
let(:target_user_param) { target_user.screen_name }
|
||||
let(:params) do
|
||||
{
|
||||
"group" => group_param,
|
||||
"list" => list_param,
|
||||
"user" => target_user_param,
|
||||
"add" => add_param
|
||||
}
|
||||
|
@ -257,17 +257,17 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
let(:expected_checked) { false }
|
||||
|
||||
it "does not do anything" do
|
||||
expect { subject }.not_to(change { group.members })
|
||||
expect(group.members.map { |gm| gm.user.id }.sort ).to eq([])
|
||||
expect { subject }.not_to(change { list.members })
|
||||
expect(list.members.map { |gm| gm.user.id }.sort ).to eq([])
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
||||
context "when the user was already added to the group" do
|
||||
context "when the user was already added to the list" do
|
||||
let(:members) { [target_user] }
|
||||
|
||||
it "removes the user from the group" do
|
||||
expect { subject }.to(change { group.reload.members.map { |gm| gm.user.id }.sort }.from([target_user.id]).to([]))
|
||||
it "removes the user from the list" do
|
||||
expect { subject }.to(change { list.reload.members.map { |gm| gm.user.id }.sort }.from([target_user.id]).to([]))
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
@ -278,26 +278,26 @@ describe Ajax::GroupController, :ajax_controller, type: :controller do
|
|||
let(:add_param) { "true" }
|
||||
let(:expected_checked) { true }
|
||||
|
||||
it "adds the user to the group" do
|
||||
expect { subject }.to(change { group.reload.members.map { |gm| gm.user.id }.sort }.from([]).to([target_user.id]))
|
||||
it "adds the user to the list" do
|
||||
expect { subject }.to(change { list.reload.members.map { |gm| gm.user.id }.sort }.from([]).to([target_user.id]))
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
||||
context "when the user was already added to the group" do
|
||||
context "when the user was already added to the list" do
|
||||
let(:members) { [target_user] }
|
||||
|
||||
it "does not add the user to the group again" do
|
||||
expect { subject }.not_to(change { group.members })
|
||||
expect(group.members.map { |gm| gm.user.id }.sort ).to eq([target_user.id])
|
||||
it "does not add the user to the list again" do
|
||||
expect { subject }.not_to(change { list.members })
|
||||
expect(list.members.map { |gm| gm.user.id }.sort ).to eq([target_user.id])
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
end
|
||||
end
|
||||
|
||||
context "when group does not exist" do
|
||||
let(:group_param) { "the-good-agency" }
|
||||
context "when list does not exist" do
|
||||
let(:list_param) { "the-good-agency" }
|
||||
let(:add_param) { "add" }
|
||||
let(:expected_response) do
|
||||
{
|
|
@ -40,7 +40,7 @@ describe Ajax::QuestionController, :ajax_controller, type: :controller do
|
|||
it "enqueues a QuestionWorker job" do
|
||||
allow(QuestionWorker).to receive(:perform_async)
|
||||
subject
|
||||
expect(QuestionWorker).to have_received(:perform_async).with(expected_rcpt, user.id, Question.last.id)
|
||||
expect(QuestionWorker).to have_received(:perform_async).with(user.id, Question.last.id)
|
||||
end
|
||||
|
||||
include_examples "returns the expected response"
|
||||
|
@ -146,55 +146,6 @@ describe Ajax::QuestionController, :ajax_controller, type: :controller do
|
|||
end
|
||||
end
|
||||
|
||||
context "when rcpt is a group" do
|
||||
let(:rcpt) { "grp:foobar" }
|
||||
|
||||
context "when group exists" do
|
||||
let(:group) { FactoryBot.create(:group, display_name: "FooBar", user: user) }
|
||||
before { group }
|
||||
|
||||
context "when anonymousQuestion is true" do
|
||||
let(:anonymous_question) { "true" }
|
||||
let(:expected_question_anonymous) { false }
|
||||
|
||||
include_examples "creates the question", false
|
||||
include_examples "enqueues a QuestionWorker job", "grp:foobar"
|
||||
end
|
||||
|
||||
context "when anonymousQuestion is false" do
|
||||
let(:anonymous_question) { "false" }
|
||||
let(:expected_question_anonymous) { false }
|
||||
|
||||
include_examples "creates the question", false
|
||||
include_examples "enqueues a QuestionWorker job", "grp:foobar"
|
||||
end
|
||||
end
|
||||
|
||||
context "when group does not exist" do
|
||||
let(:expected_response) do
|
||||
{
|
||||
"success" => false,
|
||||
"status" => "not_found",
|
||||
"message" => anything
|
||||
}
|
||||
end
|
||||
|
||||
context "when anonymousQuestion is true" do
|
||||
let(:anonymous_question) { "true" }
|
||||
|
||||
include_examples "does not create the question", false
|
||||
include_examples "does not enqueue a QuestionWorker job"
|
||||
end
|
||||
|
||||
context "when anonymousQuestion is false" do
|
||||
let(:anonymous_question) { "false" }
|
||||
|
||||
include_examples "does not create the question", false
|
||||
include_examples "does not enqueue a QuestionWorker job"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when rcpt is a non-existent user" do
|
||||
let(:rcpt) { "tripmeister_eder" }
|
||||
let(:anonymous_question) { "false" }
|
||||
|
@ -274,12 +225,6 @@ describe Ajax::QuestionController, :ajax_controller, type: :controller do
|
|||
include_examples "does not enqueue a QuestionWorker job"
|
||||
end
|
||||
|
||||
context "when rcpt is a group" do
|
||||
let(:rcpt) { "grp:foobar" }
|
||||
|
||||
include_examples "does not enqueue a QuestionWorker job"
|
||||
end
|
||||
|
||||
context "when rcpt is a non-existent user" do
|
||||
let(:rcpt) { "tripmeister_eder" }
|
||||
let(:expected_response) do
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :group do
|
||||
factory :list do
|
||||
sequence(:display_name) { |i| "#{Faker::Internet.username(specifier: 0..12, separators: %w[_])}#{i}" }
|
||||
user { FactoryBot.build(:user) }
|
||||
|
||||
|
@ -9,9 +9,9 @@ FactoryBot.define do
|
|||
members { [] }
|
||||
end
|
||||
|
||||
after(:create) do |group, evaluator|
|
||||
after(:create) do |list, evaluator|
|
||||
evaluator.members.each do |member|
|
||||
GroupMember.create(group_id: group.id, user_id: member.id)
|
||||
ListMember.create(list_id: list.id, user_id: member.id)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe(Group, type: :model) do
|
||||
RSpec.describe(List, type: :model) do
|
||||
let(:user) { FactoryBot.build(:user) }
|
||||
|
||||
describe 'name mangling' do
|
||||
subject do
|
||||
Group.new(user: user, display_name: display_name).tap(&:validate)
|
||||
List.new(user: user, display_name: display_name).tap(&:validate)
|
||||
end
|
||||
|
||||
{
|
||||
'great group' => 'great-group',
|
||||
'great list' => 'great-list',
|
||||
'followers' => '-followers-',
|
||||
' followers ' => '-followers-',
|
||||
" the game \t\nyes" => 'the-game-yes',
|
||||
|
@ -30,11 +30,11 @@ RSpec.describe(Group, type: :model) do
|
|||
|
||||
describe 'validations' do
|
||||
subject do
|
||||
Group.new(user: user, display_name: display_name).validate
|
||||
List.new(user: user, display_name: display_name).validate
|
||||
end
|
||||
|
||||
context "when display name is 'great group' (valid)" do
|
||||
let(:display_name) { 'great group' }
|
||||
context "when display name is 'great list' (valid)" do
|
||||
let(:display_name) { 'great list' }
|
||||
|
||||
it { is_expected.to be true }
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "rails_helper"
|
||||
|
||||
describe QuestionWorker do
|
||||
describe "#perform" do
|
||||
let(:user) { FactoryBot.create(:user) }
|
||||
let(:user_id) { user.id }
|
||||
let(:question) { FactoryBot.create(:question, user: user) }
|
||||
let(:question_id) { question.id }
|
||||
|
||||
before do
|
||||
5.times do
|
||||
other_user = FactoryBot.create(:user)
|
||||
other_user.follow(user)
|
||||
end
|
||||
end
|
||||
|
||||
subject { described_class.new.perform(user_id, question_id) }
|
||||
|
||||
it "places the question in the inbox of the user's followers" do
|
||||
expect { subject }
|
||||
.to(
|
||||
change { Inbox.where(user_id: user.followers.ids, question_id: question_id, new: true).count }
|
||||
.from(0)
|
||||
.to(5)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue