Merge branch 'master' into glitch-soc/merge-upstream
This commit is contained in:
		
						commit
						88a0395a58
					
				
							
								
								
									
										1
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Gemfile
									
									
									
									
									
								
							@ -10,6 +10,7 @@ gem 'rails', '~> 5.2.1'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
gem 'hamlit-rails', '~> 0.2'
 | 
					gem 'hamlit-rails', '~> 0.2'
 | 
				
			||||||
gem 'pg', '~> 1.0'
 | 
					gem 'pg', '~> 1.0'
 | 
				
			||||||
 | 
					gem 'makara', '~> 0.4'
 | 
				
			||||||
gem 'pghero', '~> 2.1'
 | 
					gem 'pghero', '~> 2.1'
 | 
				
			||||||
gem 'dotenv-rails', '~> 2.2', '< 2.3'
 | 
					gem 'dotenv-rails', '~> 2.2', '< 2.3'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -324,6 +324,8 @@ GEM
 | 
				
			|||||||
      nokogiri (>= 1.5.9)
 | 
					      nokogiri (>= 1.5.9)
 | 
				
			||||||
    mail (2.7.0)
 | 
					    mail (2.7.0)
 | 
				
			||||||
      mini_mime (>= 0.1.1)
 | 
					      mini_mime (>= 0.1.1)
 | 
				
			||||||
 | 
					    makara (0.4.0)
 | 
				
			||||||
 | 
					      activerecord (>= 3.0.0)
 | 
				
			||||||
    marcel (0.3.2)
 | 
					    marcel (0.3.2)
 | 
				
			||||||
      mimemagic (~> 0.3.2)
 | 
					      mimemagic (~> 0.3.2)
 | 
				
			||||||
    mario-redis-lock (1.2.1)
 | 
					    mario-redis-lock (1.2.1)
 | 
				
			||||||
@ -700,6 +702,7 @@ DEPENDENCIES
 | 
				
			|||||||
  letter_opener_web (~> 1.3)
 | 
					  letter_opener_web (~> 1.3)
 | 
				
			||||||
  link_header (~> 0.0)
 | 
					  link_header (~> 0.0)
 | 
				
			||||||
  lograge (~> 0.10)
 | 
					  lograge (~> 0.10)
 | 
				
			||||||
 | 
					  makara (~> 0.4)
 | 
				
			||||||
  mario-redis-lock (~> 1.2)
 | 
					  mario-redis-lock (~> 1.2)
 | 
				
			||||||
  memory_profiler
 | 
					  memory_profiler
 | 
				
			||||||
  microformats (~> 4.0)
 | 
					  microformats (~> 4.0)
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,12 @@ module Admin
 | 
				
			|||||||
      redirect_to admin_invites_path
 | 
					      redirect_to admin_invites_path
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def deactivate_all
 | 
				
			||||||
 | 
					      authorize :invite, :deactivate_all?
 | 
				
			||||||
 | 
					      Invite.available.in_batches.update_all(expires_at: Time.now.utc)
 | 
				
			||||||
 | 
					      redirect_to admin_invites_path
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private
 | 
					    private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def resource_params
 | 
					    def resource_params
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ module StreamEntriesHelper
 | 
				
			|||||||
          safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('settings.edit_profile')])
 | 
					          safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('settings.edit_profile')])
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      elsif current_account.following?(account) || current_account.requested?(account)
 | 
					      elsif current_account.following?(account) || current_account.requested?(account)
 | 
				
			||||||
        link_to account_unfollow_path(account), class: 'button logo-button', data: { method: :post } do
 | 
					        link_to account_unfollow_path(account), class: 'button logo-button button--destructive', data: { method: :post } do
 | 
				
			||||||
          safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.unfollow')])
 | 
					          safe_join([render(file: Rails.root.join('app', 'javascript', 'images', 'logo.svg')), t('accounts.unfollow')])
 | 
				
			||||||
        end
 | 
					        end
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
 | 
				
			|||||||
@ -140,7 +140,7 @@ export function redraft(status) {
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function deleteStatus(id, withRedraft = false) {
 | 
					export function deleteStatus(id, router, withRedraft = false) {
 | 
				
			||||||
  return (dispatch, getState) => {
 | 
					  return (dispatch, getState) => {
 | 
				
			||||||
    const status = getState().getIn(['statuses', id]);
 | 
					    const status = getState().getIn(['statuses', id]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -153,6 +153,10 @@ export function deleteStatus(id, withRedraft = false) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      if (withRedraft) {
 | 
					      if (withRedraft) {
 | 
				
			||||||
        dispatch(redraft(status));
 | 
					        dispatch(redraft(status));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!getState().getIn(['compose', 'mounted'])) {
 | 
				
			||||||
 | 
					          router.push('/statuses/new');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }).catch(error => {
 | 
					    }).catch(error => {
 | 
				
			||||||
      dispatch(deleteStatusFail(id, error));
 | 
					      dispatch(deleteStatusFail(id, error));
 | 
				
			||||||
 | 
				
			|||||||
@ -96,11 +96,11 @@ export default class StatusActionBar extends ImmutablePureComponent {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleDeleteClick = () => {
 | 
					  handleDeleteClick = () => {
 | 
				
			||||||
    this.props.onDelete(this.props.status);
 | 
					    this.props.onDelete(this.props.status, this.context.router.history);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleRedraftClick = () => {
 | 
					  handleRedraftClick = () => {
 | 
				
			||||||
    this.props.onDelete(this.props.status, true);
 | 
					    this.props.onDelete(this.props.status, this.context.router.history, true);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handlePinClick = () => {
 | 
					  handlePinClick = () => {
 | 
				
			||||||
 | 
				
			|||||||
@ -93,14 +93,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
 | 
				
			|||||||
    }));
 | 
					    }));
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onDelete (status, withRedraft = false) {
 | 
					  onDelete (status, history, withRedraft = false) {
 | 
				
			||||||
    if (!deleteModal) {
 | 
					    if (!deleteModal) {
 | 
				
			||||||
      dispatch(deleteStatus(status.get('id'), withRedraft));
 | 
					      dispatch(deleteStatus(status.get('id'), history, withRedraft));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      dispatch(openModal('CONFIRM', {
 | 
					      dispatch(openModal('CONFIRM', {
 | 
				
			||||||
        message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
 | 
					        message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
 | 
				
			||||||
        confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
 | 
					        confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
 | 
				
			||||||
        onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)),
 | 
					        onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)),
 | 
				
			||||||
      }));
 | 
					      }));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ export default class Upload extends ImmutablePureComponent {
 | 
				
			|||||||
    onUndo: PropTypes.func.isRequired,
 | 
					    onUndo: PropTypes.func.isRequired,
 | 
				
			||||||
    onDescriptionChange: PropTypes.func.isRequired,
 | 
					    onDescriptionChange: PropTypes.func.isRequired,
 | 
				
			||||||
    onOpenFocalPoint: PropTypes.func.isRequired,
 | 
					    onOpenFocalPoint: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					    onSubmit: PropTypes.func.isRequired,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  state = {
 | 
					  state = {
 | 
				
			||||||
@ -28,6 +29,17 @@ export default class Upload extends ImmutablePureComponent {
 | 
				
			|||||||
    dirtyDescription: null,
 | 
					    dirtyDescription: null,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleKeyDown = (e) => {
 | 
				
			||||||
 | 
					    if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
 | 
				
			||||||
 | 
					      this.handleSubmit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleSubmit = () => {
 | 
				
			||||||
 | 
					    this.handleInputBlur();
 | 
				
			||||||
 | 
					    this.props.onSubmit();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleUndoClick = () => {
 | 
					  handleUndoClick = () => {
 | 
				
			||||||
    this.props.onUndo(this.props.media.get('id'));
 | 
					    this.props.onUndo(this.props.media.get('id'));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -93,6 +105,7 @@ export default class Upload extends ImmutablePureComponent {
 | 
				
			|||||||
                    onFocus={this.handleInputFocus}
 | 
					                    onFocus={this.handleInputFocus}
 | 
				
			||||||
                    onChange={this.handleInputChange}
 | 
					                    onChange={this.handleInputChange}
 | 
				
			||||||
                    onBlur={this.handleInputBlur}
 | 
					                    onBlur={this.handleInputBlur}
 | 
				
			||||||
 | 
					                    onKeyDown={this.handleKeyDown}
 | 
				
			||||||
                  />
 | 
					                  />
 | 
				
			||||||
                </label>
 | 
					                </label>
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ import { connect } from 'react-redux';
 | 
				
			|||||||
import Upload from '../components/upload';
 | 
					import Upload from '../components/upload';
 | 
				
			||||||
import { undoUploadCompose, changeUploadCompose } from '../../../actions/compose';
 | 
					import { undoUploadCompose, changeUploadCompose } from '../../../actions/compose';
 | 
				
			||||||
import { openModal } from '../../../actions/modal';
 | 
					import { openModal } from '../../../actions/modal';
 | 
				
			||||||
 | 
					import { submitCompose } from '../../../actions/compose';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const mapStateToProps = (state, { id }) => ({
 | 
					const mapStateToProps = (state, { id }) => ({
 | 
				
			||||||
  media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id),
 | 
					  media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id),
 | 
				
			||||||
@ -21,6 +22,10 @@ const mapDispatchToProps = dispatch => ({
 | 
				
			|||||||
    dispatch(openModal('FOCAL_POINT', { id }));
 | 
					    dispatch(openModal('FOCAL_POINT', { id }));
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onSubmit () {
 | 
				
			||||||
 | 
					    dispatch(submitCompose());
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default connect(mapStateToProps, mapDispatchToProps)(Upload);
 | 
					export default connect(mapStateToProps, mapDispatchToProps)(Upload);
 | 
				
			||||||
 | 
				
			|||||||
@ -139,6 +139,7 @@ export default class GettingStarted extends ImmutablePureComponent {
 | 
				
			|||||||
            {multiColumn && <li><Link to='/keyboard-shortcuts'><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></Link> · </li>}
 | 
					            {multiColumn && <li><Link to='/keyboard-shortcuts'><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></Link> · </li>}
 | 
				
			||||||
            <li><a href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a> · </li>
 | 
					            <li><a href='/auth/edit'><FormattedMessage id='getting_started.security' defaultMessage='Security' /></a> · </li>
 | 
				
			||||||
            <li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this instance' /></a> · </li>
 | 
					            <li><a href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About this instance' /></a> · </li>
 | 
				
			||||||
 | 
					            <li><a href='https://joinmastodon.org/apps' target='_blank'><FormattedMessage id='navigation_bar.apps' defaultMessage='Mobile apps' /></a> · </li>
 | 
				
			||||||
            <li><a href='/terms' target='_blank'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of service' /></a> · </li>
 | 
					            <li><a href='/terms' target='_blank'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of service' /></a> · </li>
 | 
				
			||||||
            <li><a href='/settings/applications' target='_blank'><FormattedMessage id='getting_started.developers' defaultMessage='Developers' /></a> · </li>
 | 
					            <li><a href='/settings/applications' target='_blank'><FormattedMessage id='getting_started.developers' defaultMessage='Developers' /></a> · </li>
 | 
				
			||||||
            <li><a href='https://github.com/tootsuite/documentation#documentation' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a> · </li>
 | 
					            <li><a href='https://github.com/tootsuite/documentation#documentation' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a> · </li>
 | 
				
			||||||
 | 
				
			|||||||
@ -65,11 +65,11 @@ export default class ActionBar extends React.PureComponent {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleDeleteClick = () => {
 | 
					  handleDeleteClick = () => {
 | 
				
			||||||
    this.props.onDelete(this.props.status);
 | 
					    this.props.onDelete(this.props.status, this.context.router.history);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleRedraftClick = () => {
 | 
					  handleRedraftClick = () => {
 | 
				
			||||||
    this.props.onDelete(this.props.status, true);
 | 
					    this.props.onDelete(this.props.status, this.context.router.history, true);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleDirectClick = () => {
 | 
					  handleDirectClick = () => {
 | 
				
			||||||
 | 
				
			|||||||
@ -174,16 +174,16 @@ export default class Status extends ImmutablePureComponent {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  handleDeleteClick = (status, withRedraft = false) => {
 | 
					  handleDeleteClick = (status, history, withRedraft = false) => {
 | 
				
			||||||
    const { dispatch, intl } = this.props;
 | 
					    const { dispatch, intl } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!deleteModal) {
 | 
					    if (!deleteModal) {
 | 
				
			||||||
      dispatch(deleteStatus(status.get('id'), withRedraft));
 | 
					      dispatch(deleteStatus(status.get('id'), history, withRedraft));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      dispatch(openModal('CONFIRM', {
 | 
					      dispatch(openModal('CONFIRM', {
 | 
				
			||||||
        message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
 | 
					        message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
 | 
				
			||||||
        confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
 | 
					        confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
 | 
				
			||||||
        onConfirm: () => dispatch(deleteStatus(status.get('id'), withRedraft)),
 | 
					        onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)),
 | 
				
			||||||
      }));
 | 
					      }));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -35,6 +35,17 @@
 | 
				
			|||||||
    transition: all 200ms ease-out;
 | 
					    transition: all 200ms ease-out;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &--destructive {
 | 
				
			||||||
 | 
					    transition: none;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &:active,
 | 
				
			||||||
 | 
					    &:focus,
 | 
				
			||||||
 | 
					    &:hover {
 | 
				
			||||||
 | 
					      background-color: $error-red;
 | 
				
			||||||
 | 
					      transition: none;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  &:disabled {
 | 
					  &:disabled {
 | 
				
			||||||
    background-color: $ui-primary-color;
 | 
					    background-color: $ui-primary-color;
 | 
				
			||||||
    cursor: default;
 | 
					    cursor: default;
 | 
				
			||||||
 | 
				
			|||||||
@ -110,6 +110,18 @@
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.button--destructive {
 | 
				
			||||||
 | 
					    &:active,
 | 
				
			||||||
 | 
					    &:focus,
 | 
				
			||||||
 | 
					    &:hover {
 | 
				
			||||||
 | 
					      background: $error-red;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      svg path:last-child {
 | 
				
			||||||
 | 
					        fill: $error-red;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @media screen and (max-width: $no-gap-breakpoint) {
 | 
					  @media screen and (max-width: $no-gap-breakpoint) {
 | 
				
			||||||
    svg {
 | 
					    svg {
 | 
				
			||||||
      display: none;
 | 
					      display: none;
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,14 @@ class User < ApplicationRecord
 | 
				
			|||||||
  include Settings::Extend
 | 
					  include Settings::Extend
 | 
				
			||||||
  include Omniauthable
 | 
					  include Omniauthable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ACTIVE_DURATION = 7.days
 | 
					  # The home and list feeds will be stored in Redis for this amount
 | 
				
			||||||
 | 
					  # of time, and status fan-out to followers will include only people
 | 
				
			||||||
 | 
					  # within this time frame. Lowering the duration may improve performance
 | 
				
			||||||
 | 
					  # if lots of people sign up, but not a lot of them check their feed
 | 
				
			||||||
 | 
					  # every day. Raising the duration reduces the amount of expensive
 | 
				
			||||||
 | 
					  # RegenerationWorker jobs that need to be run when those people come
 | 
				
			||||||
 | 
					  # to check their feed
 | 
				
			||||||
 | 
					  ACTIVE_DURATION = ENV.fetch('USER_ACTIVE_DAYS', 7).to_i.days
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  devise :two_factor_authenticatable,
 | 
					  devise :two_factor_authenticatable,
 | 
				
			||||||
         otp_secret_encryption_key: Rails.configuration.x.otp_secret
 | 
					         otp_secret_encryption_key: Rails.configuration.x.otp_secret
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,10 @@ class InvitePolicy < ApplicationPolicy
 | 
				
			|||||||
    min_required_role?
 | 
					    min_required_role?
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def deactivate_all?
 | 
				
			||||||
 | 
					    admin?
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def destroy?
 | 
					  def destroy?
 | 
				
			||||||
    owner? || (Setting.min_invite_role == 'admin' ? admin? : staff?)
 | 
					    owner? || (Setting.min_invite_role == 'admin' ? admin? : staff?)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ class ProcessMentionsService < BaseService
 | 
				
			|||||||
        end
 | 
					        end
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      next match if mention_undeliverable?(mentioned_account)
 | 
					      next match if mention_undeliverable?(mentioned_account) || mentioned_account&.suspended
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      mentions << mentioned_account.mentions.where(status: status).first_or_create(status: status)
 | 
					      mentions << mentioned_account.mentions.where(status: status).first_or_create(status: status)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,22 +9,28 @@
 | 
				
			|||||||
      %li= filter_link_to t('admin.invites.filter.available'), available: 1, expired: nil
 | 
					      %li= filter_link_to t('admin.invites.filter.available'), available: 1, expired: nil
 | 
				
			||||||
      %li= filter_link_to t('admin.invites.filter.expired'), available: nil, expired: 1
 | 
					      %li= filter_link_to t('admin.invites.filter.expired'), available: nil, expired: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%hr.spacer/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- if policy(:invite).create?
 | 
					- if policy(:invite).create?
 | 
				
			||||||
  %p= t('invites.prompt')
 | 
					  %p= t('invites.prompt')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  = render 'invites/form'
 | 
					  = render 'invites/form'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  %hr/
 | 
					  %hr.spacer/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%table.table
 | 
					.table-wrapper
 | 
				
			||||||
  %thead
 | 
					  %table.table
 | 
				
			||||||
    %tr
 | 
					    %thead
 | 
				
			||||||
      %th
 | 
					      %tr
 | 
				
			||||||
      %th= t('invites.table.uses')
 | 
					        %th
 | 
				
			||||||
      %th= t('invites.table.expires_at')
 | 
					        %th= t('invites.table.uses')
 | 
				
			||||||
      %th
 | 
					        %th= t('invites.table.expires_at')
 | 
				
			||||||
      %th
 | 
					        %th
 | 
				
			||||||
  %tbody
 | 
					        %th
 | 
				
			||||||
    = render @invites
 | 
					    %tbody
 | 
				
			||||||
 | 
					      = render @invites
 | 
				
			||||||
 | 
					
 | 
				
			||||||
= paginate @invites
 | 
					= paginate @invites
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- if policy(:invite).deactivate_all?
 | 
				
			||||||
 | 
					  = link_to t('admin.invites.deactivate_all'), deactivate_all_admin_invites_path, method: :post, data: { confirm: t('admin.accounts.are_you_sure') }, class: 'button'
 | 
				
			||||||
 | 
				
			|||||||
@ -42,6 +42,6 @@
 | 
				
			|||||||
            %h4= t 'footer.more'
 | 
					            %h4= t 'footer.more'
 | 
				
			||||||
            %ul
 | 
					            %ul
 | 
				
			||||||
              %li= link_to t('about.source_code'), Mastodon::Version.source_url
 | 
					              %li= link_to t('about.source_code'), Mastodon::Version.source_url
 | 
				
			||||||
              %li= link_to 'joinmastodon.org', 'https://joinmastodon.org'
 | 
					              %li= link_to t('about.apps'), 'https://joinmastodon.org/apps'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
= render template: 'layouts/application'
 | 
					= render template: 'layouts/application'
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@ en:
 | 
				
			|||||||
    about_this: About
 | 
					    about_this: About
 | 
				
			||||||
    administered_by: 'Administered by:'
 | 
					    administered_by: 'Administered by:'
 | 
				
			||||||
    api: API
 | 
					    api: API
 | 
				
			||||||
 | 
					    apps: Mobile apps
 | 
				
			||||||
    closed_registrations: Registrations are currently closed on this instance. However! You can find a different instance to make an account on and get access to the very same network from there.
 | 
					    closed_registrations: Registrations are currently closed on this instance. However! You can find a different instance to make an account on and get access to the very same network from there.
 | 
				
			||||||
    contact: Contact
 | 
					    contact: Contact
 | 
				
			||||||
    contact_missing: Not set
 | 
					    contact_missing: Not set
 | 
				
			||||||
@ -281,6 +282,7 @@ en:
 | 
				
			|||||||
      search: Search
 | 
					      search: Search
 | 
				
			||||||
      title: Known instances
 | 
					      title: Known instances
 | 
				
			||||||
    invites:
 | 
					    invites:
 | 
				
			||||||
 | 
					      deactivate_all: Deactivate all
 | 
				
			||||||
      filter:
 | 
					      filter:
 | 
				
			||||||
        all: All
 | 
					        all: All
 | 
				
			||||||
        available: Available
 | 
					        available: Available
 | 
				
			||||||
 | 
				
			|||||||
@ -137,7 +137,12 @@ Rails.application.routes.draw do
 | 
				
			|||||||
    resources :email_domain_blocks, only: [:index, :new, :create, :destroy]
 | 
					    resources :email_domain_blocks, only: [:index, :new, :create, :destroy]
 | 
				
			||||||
    resources :action_logs, only: [:index]
 | 
					    resources :action_logs, only: [:index]
 | 
				
			||||||
    resource :settings, only: [:edit, :update]
 | 
					    resource :settings, only: [:edit, :update]
 | 
				
			||||||
    resources :invites, only: [:index, :create, :destroy]
 | 
					
 | 
				
			||||||
 | 
					    resources :invites, only: [:index, :create, :destroy] do
 | 
				
			||||||
 | 
					      collection do
 | 
				
			||||||
 | 
					        post :deactivate_all
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    resources :relays, only: [:index, :new, :create, :destroy] do
 | 
					    resources :relays, only: [:index, :new, :create, :destroy] do
 | 
				
			||||||
      member do
 | 
					      member do
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ class CopyStatusStats < ActiveRecord::Migration[5.2]
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  def up
 | 
					  def up
 | 
				
			||||||
    safety_assured do
 | 
					    safety_assured do
 | 
				
			||||||
      Status.where.not(id: StatusStat.select('status_id')).select('id').find_in_batches do |statuses|
 | 
					      Status.unscoped.select('id').find_in_batches(batch_size: 5_000) do |statuses|
 | 
				
			||||||
        execute <<-SQL.squish
 | 
					        execute <<-SQL.squish
 | 
				
			||||||
          INSERT INTO status_stats (status_id, reblogs_count, favourites_count, created_at, updated_at)
 | 
					          INSERT INTO status_stats (status_id, reblogs_count, favourites_count, created_at, updated_at)
 | 
				
			||||||
          SELECT id, reblogs_count, favourites_count, created_at, updated_at
 | 
					          SELECT id, reblogs_count, favourites_count, created_at, updated_at
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user