From ea0685136ef92321513d2b23649b0806c54c74fe Mon Sep 17 00:00:00 2001 From: Georg Gadinger Date: Mon, 25 May 2020 18:04:54 +0200 Subject: [PATCH] Rename Groups to Lists haha regexp go brrr special thanks to @seatsea for helping me out with the French locales --- .../javascripts/application.js.erb.coffee | 2 +- .../{groups.coffee => lists.coffee} | 38 +++--- ...group_controller.rb => list_controller.rb} | 38 +++--- app/controllers/ajax/question_controller.rb | 2 +- app/controllers/group_controller.rb | 15 --- app/controllers/list_controller.rb | 15 +++ app/controllers/user_controller.rb | 10 +- app/helpers/application_helper.rb | 4 +- app/models/group_member.rb | 4 - app/models/{group.rb => list.rb} | 12 +- .../{group => list}/timeline_methods.rb | 4 +- app/models/list_member.rb | 4 + app/models/user.rb | 12 +- app/views/layouts/feed.haml | 2 +- app/views/layouts/user/profile.haml | 2 +- app/views/{group => list}/index.haml | 2 +- app/views/{group => list}/index.js.erb | 0 app/views/modal/_ask.haml | 8 +- app/views/modal/_group.haml | 28 ----- app/views/modal/_list.haml | 28 +++++ app/views/modal/group/_item.haml | 18 --- app/views/modal/list/_item.haml | 18 +++ app/views/navigation/_main.haml | 8 +- app/views/shared/_sidebar.haml | 10 +- app/views/static/front.haml | 7 +- app/views/tabs/_feed.haml | 25 ++-- app/views/user/_actions.haml | 6 +- app/views/user/groups.haml | 9 -- app/views/user/lists.haml | 9 ++ app/workers/question_worker.rb | 2 +- config/initializers/rails_admin.rb | 4 +- config/locales/cs.yml | 10 +- config/locales/de.yml | 48 ++++---- config/locales/en.yml | 48 ++++---- config/locales/en_dizzle.yml | 32 +++--- config/locales/en_pirate.yml | 10 +- config/locales/fr.yml | 40 +++---- config/locales/it.yml | 10 +- config/locales/ja.yml | 10 +- config/routes.rb | 10 +- .../20200525145144_rename_groups_to_lists.rb | 20 ++++ db/schema.rb | 42 +++---- service-docs/en/policy/privacy.md | 2 +- ...roller_spec.rb => list_controller_spec.rb} | 108 +++++++++--------- .../ajax/question_controller_spec.rb | 12 +- spec/factories/{group.rb => list.rb} | 6 +- spec/models/{group_spec.rb => list_spec.rb} | 12 +- 47 files changed, 390 insertions(+), 376 deletions(-) rename app/assets/javascripts/{groups.coffee => lists.coffee} (68%) rename app/controllers/ajax/{group_controller.rb => list_controller.rb} (61%) delete mode 100644 app/controllers/group_controller.rb create mode 100644 app/controllers/list_controller.rb delete mode 100644 app/models/group_member.rb rename app/models/{group.rb => list.rb} (59%) rename app/models/{group => list}/timeline_methods.rb (76%) create mode 100644 app/models/list_member.rb rename app/views/{group => list}/index.haml (90%) rename app/views/{group => list}/index.js.erb (100%) delete mode 100644 app/views/modal/_group.haml create mode 100644 app/views/modal/_list.haml delete mode 100644 app/views/modal/group/_item.haml create mode 100644 app/views/modal/list/_item.haml delete mode 100644 app/views/user/groups.haml create mode 100644 app/views/user/lists.haml create mode 100644 db/migrate/20200525145144_rename_groups_to_lists.rb rename spec/controllers/ajax/{group_controller_spec.rb => list_controller_spec.rb} (66%) rename spec/factories/{group.rb => list.rb} (70%) rename spec/models/{group_spec.rb => list_spec.rb} (81%) diff --git a/app/assets/javascripts/application.js.erb.coffee b/app/assets/javascripts/application.js.erb.coffee index ae5efb02..fe79c335 100644 --- a/app/assets/javascripts/application.js.erb.coffee +++ b/app/assets/javascripts/application.js.erb.coffee @@ -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 diff --git a/app/assets/javascripts/groups.coffee b/app/assets/javascripts/lists.coffee similarity index 68% rename from app/assets/javascripts/groups.coffee rename to app/assets/javascripts/lists.coffee index 9e2f86d1..99376beb 100644 --- a/app/assets/javascripts/groups.coffee +++ b/app/assets/javascripts/lists.coffee @@ -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 diff --git a/app/controllers/ajax/group_controller.rb b/app/controllers/ajax/list_controller.rb similarity index 61% rename from app/controllers/ajax/group_controller.rb rename to app/controllers/ajax/list_controller.rb index 352147ef..1fec4cd7 100644 --- a/app/controllers/ajax/group_controller.rb +++ b/app/controllers/ajax/list_controller.rb @@ -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 diff --git a/app/controllers/ajax/question_controller.rb b/app/controllers/ajax/question_controller.rb index 81ee5ef7..ec465915 100644 --- a/app/controllers/ajax/question_controller.rb +++ b/app/controllers/ajax/question_controller.rb @@ -56,7 +56,7 @@ class Ajax::QuestionController < AjaxController elsif params[:rcpt].start_with? 'grp:' unless current_user.nil? begin - current_user.groups.find_by_name!(params[:rcpt].sub 'grp:', '') + current_user.lists.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) diff --git a/app/controllers/group_controller.rb b/app/controllers/group_controller.rb deleted file mode 100644 index 3e19e921..00000000 --- a/app/controllers/group_controller.rb +++ /dev/null @@ -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 diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb new file mode 100644 index 00000000..0c305dee --- /dev/null +++ b/app/controllers/list_controller.rb @@ -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 diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index 0274a595..204044cf 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -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 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index d87d9704..e61b6a71 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -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 diff --git a/app/models/group_member.rb b/app/models/group_member.rb deleted file mode 100644 index 5bdf6dc0..00000000 --- a/app/models/group_member.rb +++ /dev/null @@ -1,4 +0,0 @@ -class GroupMember < ApplicationRecord - belongs_to :user - belongs_to :group -end diff --git a/app/models/group.rb b/app/models/list.rb similarity index 59% rename from app/models/group.rb rename to app/models/list.rb index 8a90b598..77bec53b 100644 --- a/app/models/group.rb +++ b/app/models/list.rb @@ -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 diff --git a/app/models/group/timeline_methods.rb b/app/models/list/timeline_methods.rb similarity index 76% rename from app/models/group/timeline_methods.rb rename to app/models/list/timeline_methods.rb index cf42dcbc..3cf68e5e 100644 --- a/app/models/group/timeline_methods.rb +++ b/app/models/list/timeline_methods.rb @@ -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 diff --git a/app/models/list_member.rb b/app/models/list_member.rb new file mode 100644 index 00000000..97c1ed68 --- /dev/null +++ b/app/models/list_member.rb @@ -0,0 +1,4 @@ +class ListMember < ApplicationRecord + belongs_to :user + belongs_to :list +end diff --git a/app/models/user.rb b/app/models/user.rb index 990f656a..8bec2c60 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -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 diff --git a/app/views/layouts/feed.haml b/app/views/layouts/feed.haml index 615fd51d..a62654f7 100644 --- a/app/views/layouts/feed.haml +++ b/app/views/layouts/feed.haml @@ -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' diff --git a/app/views/layouts/user/profile.haml b/app/views/layouts/user/profile.haml index f33dfa8f..7720beb3 100644 --- a/app/views/layouts/user/profile.haml +++ b/app/views/layouts/user/profile.haml @@ -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 diff --git a/app/views/group/index.haml b/app/views/list/index.haml similarity index 90% rename from app/views/group/index.haml rename to app/views/list/index.haml index e45235a4..26ddbd5d 100644 --- a/app/views/group/index.haml +++ b/app/views/list/index.haml @@ -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' diff --git a/app/views/group/index.js.erb b/app/views/list/index.js.erb similarity index 100% rename from app/views/group/index.js.erb rename to app/views/list/index.js.erb diff --git a/app/views/modal/_ask.haml b/app/views/modal/_ask.haml index c99b4a6b..c834d9ae 100644 --- a/app/views/modal/_ask.haml +++ b/app/views/modal/_ask.haml @@ -9,13 +9,13 @@ .modal-body %textarea.form-control{ name: 'qb-all-question', placeholder: t('views.placeholder.question') } .modal-footer - - if current_user.groups.count.positive? + - if current_user.lists.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 + %optlist{ label: t('views.list.title').pluralize(2) } + - current_user.lists.each do |list| + %option{ value: "grp:#{list.name}" }= list.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' diff --git a/app/views/modal/_group.haml b/app/views/modal/_group.haml deleted file mode 100644 index 6ad41b08..00000000 --- a/app/views/modal/_group.haml +++ /dev/null @@ -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' diff --git a/app/views/modal/_list.haml b/app/views/modal/_list.haml new file mode 100644 index 00000000..0e1b7d2a --- /dev/null +++ b/app/views/modal/_list.haml @@ -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' diff --git a/app/views/modal/group/_item.haml b/app/views/modal/group/_item.haml deleted file mode 100644 index fd525549..00000000 --- a/app/views/modal/group/_item.haml +++ /dev/null @@ -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' diff --git a/app/views/modal/list/_item.haml b/app/views/modal/list/_item.haml new file mode 100644 index 00000000..1f0f47f6 --- /dev/null +++ b/app/views/modal/list/_item.haml @@ -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' diff --git a/app/views/navigation/_main.haml b/app/views/navigation/_main.haml index 04c93eab..6566cc18 100644 --- a/app/views/navigation/_main.haml +++ b/app/views/navigation/_main.haml @@ -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 } } diff --git a/app/views/shared/_sidebar.haml b/app/views/shared/_sidebar.haml index c8d8b09b..69a534d1 100644 --- a/app/views/shared/_sidebar.haml +++ b/app/views/shared/_sidebar.haml @@ -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) } diff --git a/app/views/static/front.haml b/app/views/static/front.haml index d56aa3ff..7a205b6f 100644 --- a/app/views/static/front.haml +++ b/app/views/static/front.haml @@ -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. + ?????????? .col-md-4.col-sm-4.col-xs-12 %h3 %i.fa.fa-fw.fa-image.text-primary diff --git a/app/views/tabs/_feed.haml b/app/views/tabs/_feed.haml index cf5a4a7e..a709d7af 100644 --- a/app/views/tabs/_feed.haml +++ b/app/views/tabs/_feed.haml @@ -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 diff --git a/app/views/user/_actions.haml b/app/views/user/_actions.haml index f03e1db4..ceea4584 100644 --- a/app/views/user/_actions.haml +++ b/app/views/user/_actions.haml @@ -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' diff --git a/app/views/user/groups.haml b/app/views/user/groups.haml deleted file mode 100644 index 41a8547d..00000000 --- a/app/views/user/groups.haml +++ /dev/null @@ -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' diff --git a/app/views/user/lists.haml b/app/views/user/lists.haml new file mode 100644 index 00000000..3a675de4 --- /dev/null +++ b/app/views/user/lists.haml @@ -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' diff --git a/app/workers/question_worker.rb b/app/workers/question_worker.rb index 53d72c75..9e1c2fc5 100644 --- a/app/workers/question_worker.rb +++ b/app/workers/question_worker.rb @@ -14,7 +14,7 @@ class QuestionWorker 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| + user.lists.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 diff --git a/config/initializers/rails_admin.rb b/config/initializers/rails_admin.rb index f63405d2..16b180ba 100644 --- a/config/initializers/rails_admin.rb +++ b/config/initializers/rails_admin.rb @@ -30,8 +30,8 @@ RailsAdmin.config do |config| config.included_models = %w[ Answer Comment - Group - GroupMember + List + ListMember Inbox Notification Question diff --git a/config/locales/cs.yml b/config/locales/cs.yml index 3d82fbb2..0ce7e61b 100644 --- a/config/locales/cs.yml +++ b/config/locales/cs.yml @@ -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" diff --git a/config/locales/de.yml b/config/locales/de.yml index 177e96db..7d73fd47 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -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." diff --git a/config/locales/en.yml b/config/locales/en.yml index 03d56529..f663e63c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -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." diff --git a/config/locales/en_dizzle.yml b/config/locales/en_dizzle.yml index 525105d3..8fd7fbd9 100644 --- a/config/locales/en_dizzle.yml +++ b/config/locales/en_dizzle.yml @@ -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" diff --git a/config/locales/en_pirate.yml b/config/locales/en_pirate.yml index 3e27d0df..d10444c3 100644 --- a/config/locales/en_pirate.yml +++ b/config/locales/en_pirate.yml @@ -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" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index f1f17579..6ac3841e 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -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." diff --git a/config/locales/it.yml b/config/locales/it.yml index b155a5a4..46839850 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -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" diff --git a/config/locales/ja.yml b/config/locales/ja.yml index 0d96e79c..f4136090 100644 --- a/config/locales/ja.yml +++ b/config/locales/ja.yml @@ -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: グループ diff --git a/config/routes.rb b/config/routes.rb index c9e051e2..d9958377 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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 diff --git a/db/migrate/20200525145144_rename_groups_to_lists.rb b/db/migrate/20200525145144_rename_groups_to_lists.rb new file mode 100644 index 00000000..c394c124 --- /dev/null +++ b/db/migrate/20200525145144_rename_groups_to_lists.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index 674dc6f5..ae76782d 100644 --- a/db/schema.rb +++ b/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" diff --git a/service-docs/en/policy/privacy.md b/service-docs/en/policy/privacy.md index fed77955..88be2983 100644 --- a/service-docs/en/policy/privacy.md +++ b/service-docs/en/policy/privacy.md @@ -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 diff --git a/spec/controllers/ajax/group_controller_spec.rb b/spec/controllers/ajax/list_controller_spec.rb similarity index 66% rename from spec/controllers/ajax/group_controller_spec.rb rename to spec/controllers/ajax/list_controller_spec.rb index dd9e171f..4c5bb134 100644 --- a/spec/controllers/ajax/group_controller_spec.rb +++ b/spec/controllers/ajax/list_controller_spec.rb @@ -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 { diff --git a/spec/controllers/ajax/question_controller_spec.rb b/spec/controllers/ajax/question_controller_spec.rb index add68805..8d27e61c 100644 --- a/spec/controllers/ajax/question_controller_spec.rb +++ b/spec/controllers/ajax/question_controller_spec.rb @@ -146,12 +146,12 @@ describe Ajax::QuestionController, :ajax_controller, type: :controller do end end - context "when rcpt is a group" do + context "when rcpt is a list" do let(:rcpt) { "grp:foobar" } - context "when group exists" do - let(:group) { FactoryBot.create(:group, display_name: "FooBar", user: user) } - before { group } + context "when list exists" do + let(:list) { FactoryBot.create(:list, display_name: "FooBar", user: user) } + before { list } context "when anonymousQuestion is true" do let(:anonymous_question) { "true" } @@ -170,7 +170,7 @@ describe Ajax::QuestionController, :ajax_controller, type: :controller do end end - context "when group does not exist" do + context "when list does not exist" do let(:expected_response) do { "success" => false, @@ -274,7 +274,7 @@ describe Ajax::QuestionController, :ajax_controller, type: :controller do include_examples "does not enqueue a QuestionWorker job" end - context "when rcpt is a group" do + context "when rcpt is a list" do let(:rcpt) { "grp:foobar" } include_examples "does not enqueue a QuestionWorker job" diff --git a/spec/factories/group.rb b/spec/factories/list.rb similarity index 70% rename from spec/factories/group.rb rename to spec/factories/list.rb index 6c0ce165..d0304ea0 100644 --- a/spec/factories/group.rb +++ b/spec/factories/list.rb @@ -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 diff --git a/spec/models/group_spec.rb b/spec/models/list_spec.rb similarity index 81% rename from spec/models/group_spec.rb rename to spec/models/list_spec.rb index bec7560c..4732d873 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/list_spec.rb @@ -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