sforkowany z mirror/soapbox
rodzic
29cdc4867b
commit
f203a4d389
|
@ -0,0 +1,128 @@
|
|||
import { defineMessages } from 'react-intl';
|
||||
import api from '../api';
|
||||
import { importFetchedAccount, importFetchedAccounts } from './importer';
|
||||
import { showAlertForError } from './alerts';
|
||||
import snackbar from './snackbar';
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { ME_PATCH_SUCCESS } from './me';
|
||||
|
||||
export const ALIASES_SUGGESTIONS_CHANGE = 'ALIASES_SUGGESTIONS_CHANGE';
|
||||
export const ALIASES_SUGGESTIONS_READY = 'ALIASES_SUGGESTIONS_READY';
|
||||
export const ALIASES_SUGGESTIONS_CLEAR = 'ALIASES_SUGGESTIONS_CLEAR';
|
||||
|
||||
export const ALIASES_ADD_REQUEST = 'ALIASES_ADD_REQUEST';
|
||||
export const ALIASES_ADD_SUCCESS = 'ALIASES_ADD_SUCCESS';
|
||||
export const ALIASES_ADD_FAIL = 'ALIASES_ADD_FAIL';
|
||||
|
||||
export const ALIASES_REMOVE_REQUEST = 'ALIASES_REMOVE_REQUEST';
|
||||
export const ALIASES_REMOVE_SUCCESS = 'ALIASES_REMOVE_SUCCESS';
|
||||
export const ALIASES_REMOVE_FAIL = 'ALIASES_REMOVE_FAIL';
|
||||
|
||||
const messages = defineMessages({
|
||||
createSuccess: { id: 'aliases.success.add', defaultMessage: 'Account alias created successfully' },
|
||||
removeSuccess: { id: 'aliases.success.remove', defaultMessage: 'Account alias removed successfully' },
|
||||
});
|
||||
|
||||
export const fetchAliasesSuggestions = q => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const params = {
|
||||
q,
|
||||
resolve: true,
|
||||
limit: 4,
|
||||
};
|
||||
|
||||
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
|
||||
dispatch(importFetchedAccounts(data));
|
||||
dispatch(fetchAliasesSuggestionsReady(q, data));
|
||||
}).catch(error => dispatch(showAlertForError(error)));
|
||||
};
|
||||
|
||||
export const fetchAliasesSuggestionsReady = (query, accounts) => ({
|
||||
type: ALIASES_SUGGESTIONS_READY,
|
||||
query,
|
||||
accounts,
|
||||
});
|
||||
|
||||
export const clearAliasesSuggestions = () => ({
|
||||
type: ALIASES_SUGGESTIONS_CLEAR,
|
||||
});
|
||||
|
||||
export const changeAliasesSuggestions = value => ({
|
||||
type: ALIASES_SUGGESTIONS_CHANGE,
|
||||
value,
|
||||
});
|
||||
|
||||
export const addToAliases = (intl, apId) => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const alsoKnownAs = getState().getIn(['meta', 'pleroma', 'also_known_as']);
|
||||
|
||||
dispatch(addToAliasesRequest(apId));
|
||||
|
||||
api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: [...alsoKnownAs, apId] })
|
||||
.then((response => {
|
||||
dispatch(snackbar.success(intl.formatMessage(messages.createSuccess)));
|
||||
dispatch(addToAliasesSuccess(response.data));
|
||||
}))
|
||||
.catch(err => dispatch(addToAliasesFail(err)));
|
||||
};
|
||||
|
||||
export const addToAliasesRequest = (apId) => ({
|
||||
type: ALIASES_ADD_REQUEST,
|
||||
apId,
|
||||
});
|
||||
|
||||
export const addToAliasesSuccess = me => dispatch => {
|
||||
dispatch(importFetchedAccount(me));
|
||||
dispatch({
|
||||
type: ME_PATCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
dispatch({
|
||||
type: ALIASES_ADD_SUCCESS,
|
||||
});
|
||||
};
|
||||
|
||||
export const addToAliasesFail = (apId, error) => ({
|
||||
type: ALIASES_ADD_FAIL,
|
||||
apId,
|
||||
error,
|
||||
});
|
||||
|
||||
export const removeFromAliases = (intl, apId) => (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
|
||||
const alsoKnownAs = getState().getIn(['meta', 'pleroma', 'also_known_as']);
|
||||
|
||||
dispatch(removeFromAliasesRequest(apId));
|
||||
|
||||
api(getState).patch('/api/v1/accounts/update_credentials', { also_known_as: alsoKnownAs.filter(id => id !== apId) })
|
||||
.then(response => {
|
||||
dispatch(snackbar.success(intl.formatMessage(messages.removeSuccess)));
|
||||
dispatch(removeFromAliasesSuccess(response.data));
|
||||
})
|
||||
.catch(err => dispatch(removeFromAliasesFail(apId, err)));
|
||||
};
|
||||
|
||||
export const removeFromAliasesRequest = (apId) => ({
|
||||
type: ALIASES_REMOVE_REQUEST,
|
||||
apId,
|
||||
});
|
||||
|
||||
export const removeFromAliasesSuccess = me => dispatch => {
|
||||
dispatch(importFetchedAccount(me));
|
||||
dispatch({
|
||||
type: ME_PATCH_SUCCESS,
|
||||
me,
|
||||
});
|
||||
dispatch({
|
||||
type: ALIASES_REMOVE_SUCCESS,
|
||||
});
|
||||
};
|
||||
|
||||
export const removeFromAliasesFail = (apId, error) => ({
|
||||
type: ALIASES_REMOVE_FAIL,
|
||||
apId,
|
||||
error,
|
||||
});
|
|
@ -33,6 +33,7 @@ const messages = defineMessages({
|
|||
admin_settings: { id: 'navigation_bar.admin_settings', defaultMessage: 'Admin settings' },
|
||||
soapbox_config: { id: 'navigation_bar.soapbox_config', defaultMessage: 'Soapbox config' },
|
||||
import_data: { id: 'navigation_bar.import_data', defaultMessage: 'Import data' },
|
||||
account_aliases: { id: 'navigation_bar.account_aliases', defaultMessage: 'Account aliases' },
|
||||
security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
|
||||
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
|
||||
lists: { id: 'column.lists', defaultMessage: 'Lists' },
|
||||
|
@ -258,6 +259,10 @@ class SidebarMenu extends ImmutablePureComponent {
|
|||
<Icon id='cloud-upload' />
|
||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.import_data)}</span>
|
||||
</NavLink>
|
||||
<NavLink className='sidebar-menu-item' to='/settings/aliases' onClick={this.handleClose}>
|
||||
<Icon id='suitcase' />
|
||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.account_aliases)}</span>
|
||||
</NavLink>
|
||||
<NavLink className='sidebar-menu-item' to='/auth/edit' onClick={this.handleClose}>
|
||||
<Icon id='lock' />
|
||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.security)}</span>
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { makeGetAccount } from '../../../selectors';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Avatar from '../../../components/avatar';
|
||||
import DisplayName from '../../../components/display_name';
|
||||
import IconButton from '../../../components/icon_button';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { addToAliases } from '../../../actions/aliases';
|
||||
|
||||
const messages = defineMessages({
|
||||
add: { id: 'aliases.account.add', defaultMessage: 'Create alias' },
|
||||
});
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getAccount = makeGetAccount();
|
||||
|
||||
const mapStateToProps = (state, { accountId, added }) => {
|
||||
const account = getAccount(state, accountId);
|
||||
const apId = account.getIn(['pleroma', 'ap_id']);
|
||||
|
||||
return {
|
||||
account,
|
||||
apId,
|
||||
added: typeof added === 'undefined' ? state.getIn(['meta', 'pleroma', 'also_known_as']).includes(apId) : added,
|
||||
me: state.get('me'),
|
||||
};
|
||||
};
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onAdd: (intl, apId) => dispatch(addToAliases(intl, apId)),
|
||||
});
|
||||
|
||||
export default @connect(makeMapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Account extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
apId: PropTypes.string.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onAdd: PropTypes.func.isRequired,
|
||||
added: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
added: false,
|
||||
};
|
||||
|
||||
handleOnAdd = () => this.props.onAdd(this.props.intl, this.props.apId);
|
||||
|
||||
render() {
|
||||
const { account, accountId, intl, added, me } = this.props;
|
||||
|
||||
let button;
|
||||
|
||||
if (!added && accountId !== me) {
|
||||
button = (
|
||||
<div className='account__relationship'>
|
||||
<IconButton icon='plus' title={intl.formatMessage(messages.add)} onClick={this.handleOnAdd} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='account'>
|
||||
<div className='account__wrapper'>
|
||||
<div className='account__display-name'>
|
||||
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
|
||||
<DisplayName account={account} />
|
||||
</div>
|
||||
|
||||
{button}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { fetchAliasesSuggestions, clearAliasesSuggestions, changeAliasesSuggestions } from '../../../actions/aliases';
|
||||
import classNames from 'classnames';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import Button from 'soapbox/components/button';
|
||||
|
||||
const messages = defineMessages({
|
||||
search: { id: 'aliases.search', defaultMessage: 'Search your old account' },
|
||||
searchTitle: { id: 'tabs_bar.search', defaultMessage: 'Search' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
value: state.getIn(['aliases', 'suggestions', 'value']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onSubmit: value => dispatch(fetchAliasesSuggestions(value)),
|
||||
onClear: () => dispatch(clearAliasesSuggestions()),
|
||||
onChange: value => dispatch(changeAliasesSuggestions(value)),
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Search extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
onClear: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
handleChange = e => {
|
||||
this.props.onChange(e.target.value);
|
||||
}
|
||||
|
||||
handleKeyUp = e => {
|
||||
if (e.keyCode === 13) {
|
||||
this.props.onSubmit(this.props.value);
|
||||
}
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
this.props.onSubmit(this.props.value);
|
||||
}
|
||||
|
||||
handleClear = () => {
|
||||
this.props.onClear();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value, intl } = this.props;
|
||||
const hasValue = value.length > 0;
|
||||
|
||||
return (
|
||||
<div className='aliases_search search'>
|
||||
<label>
|
||||
<span style={{ display: 'none' }}>{intl.formatMessage(messages.search)}</span>
|
||||
|
||||
<input
|
||||
className='search__input'
|
||||
type='text'
|
||||
value={value}
|
||||
onChange={this.handleChange}
|
||||
onKeyUp={this.handleKeyUp}
|
||||
placeholder={intl.formatMessage(messages.search)}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<div role='button' tabIndex='0' className='search__icon' onClick={this.handleClear}>
|
||||
<Icon id='search' className={classNames({ active: !hasValue })} />
|
||||
<Icon id='times-circle' aria-label={intl.formatMessage(messages.search)} className={classNames({ active: hasValue })} />
|
||||
</div>
|
||||
<Button onClick={this.handleSubmit}>{intl.formatMessage(messages.searchTitle)}</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import Column from '../ui/components/column';
|
||||
import ColumnSubheading from '../ui/components/column_subheading';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
import Icon from 'soapbox/components/icon';
|
||||
import Search from './components/search';
|
||||
import Account from './components/account';
|
||||
import { removeFromAliases } from '../../actions/aliases';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.aliases', defaultMessage: 'Account aliases' },
|
||||
subheading_add_new: { id: 'column.aliases.subheading_add_new', defaultMessage: 'Add New Alias' },
|
||||
create_error: { id: 'column.aliases.create_error', defaultMessage: 'Error creating alias' },
|
||||
delete_error: { id: 'column.aliases.delete_error', defaultMessage: 'Error deleting alias' },
|
||||
subheading_aliases: { id: 'column.aliases.subheading_aliases', defaultMessage: 'Current aliases' },
|
||||
delete: { id: 'column.aliases.delete', defaultMessage: 'Delete' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
aliases: state.getIn(['meta', 'pleroma', 'also_known_as']),
|
||||
searchAccountIds: state.getIn(['aliases', 'suggestions', 'items']),
|
||||
});
|
||||
|
||||
export default @connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Aliases extends ImmutablePureComponent {
|
||||
|
||||
handleFilterDelete = e => {
|
||||
const { dispatch, intl } = this.props;
|
||||
dispatch(removeFromAliases(intl, e.currentTarget.dataset.value));
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, aliases, searchAccountIds } = this.props;
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.aliases' defaultMessage="You haven't created any account alias yet." />;
|
||||
|
||||
return (
|
||||
<Column className='aliases-settings-panel' icon='suitcase' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||
<ColumnSubheading text={intl.formatMessage(messages.subheading_add_new)} />
|
||||
<Search />
|
||||
<div className='aliases__accounts'>
|
||||
{searchAccountIds.map(accountId => <Account key={accountId} accountId={accountId} />)}
|
||||
</div>
|
||||
<ColumnSubheading text={intl.formatMessage(messages.subheading_aliases)} />
|
||||
<div className='aliases-settings-panel'>
|
||||
<ScrollableList
|
||||
scrollKey='aliases'
|
||||
emptyMessage={emptyMessage}
|
||||
>
|
||||
{aliases.map((alias, i) => (
|
||||
<div key={i} className='alias__container'>
|
||||
<div className='alias__details'>
|
||||
<span className='alias__list-label'><FormattedMessage id='aliases.account_label' defaultMessage='Old account:' /></span>
|
||||
<span className='alias__list-value'>{alias}</span>
|
||||
</div>
|
||||
<div className='alias__delete' role='button' tabIndex='0' onClick={this.handleFilterDelete} data-value={alias} aria-label={intl.formatMessage(messages.delete)}>
|
||||
<Icon className='alias__delete-icon' id='times' size={40} />
|
||||
<span className='alias__delete-label'><FormattedMessage id='aliases.aliases_list_delete' defaultMessage='Unlink alias' /></span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -38,6 +38,7 @@ const LinkFooter = ({ onOpenHotkeys, account, onClickLogOut }) => (
|
|||
{isAdmin(account) && <li><a href='/pleroma/admin'><FormattedMessage id='navigation_bar.admin_settings' defaultMessage='AdminFE' /></a></li>}
|
||||
{isAdmin(account) && <li><Link to='/soapbox/config'><FormattedMessage id='navigation_bar.soapbox_config' defaultMessage='Soapbox config' /></Link></li>}
|
||||
<li><Link to='/settings/import'><FormattedMessage id='navigation_bar.import_data' defaultMessage='Import data' /></Link></li>
|
||||
<li><Link to='/settings/aliases'><FormattedMessage id='navigation_bar.account_aliases' defaultMessage='Account aliases' /></Link></li>
|
||||
<li><a href='#' onClick={onOpenHotkeys}><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></a></li>
|
||||
</>}
|
||||
<li><Link to='/about'><FormattedMessage id='navigation_bar.info' defaultMessage='About this server' /></Link></li>
|
||||
|
|
|
@ -98,6 +98,7 @@ import {
|
|||
ScheduledStatuses,
|
||||
UserIndex,
|
||||
FederationRestrictions,
|
||||
Aliases,
|
||||
} from './util/async-components';
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
|
@ -261,6 +262,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
<WrappedRoute path='/settings/preferences' page={DefaultPage} component={Preferences} content={children} />
|
||||
<WrappedRoute path='/settings/profile' page={DefaultPage} component={EditProfile} content={children} />
|
||||
<WrappedRoute path='/settings/import' page={DefaultPage} component={ImportData} content={children} />
|
||||
<WrappedRoute path='/settings/aliases' page={DefaultPage} component={Aliases} content={children} />
|
||||
<WrappedRoute path='/backups' page={DefaultPage} component={Backups} content={children} />
|
||||
<WrappedRoute path='/soapbox/config' page={DefaultPage} component={SoapboxConfig} content={children} />
|
||||
|
||||
|
|
|
@ -249,3 +249,7 @@ export function UserIndex() {
|
|||
export function FederationRestrictions() {
|
||||
return import(/* webpackChunkName: "features/federation_restrictions" */'../../federation_restrictions');
|
||||
}
|
||||
|
||||
export function Aliases() {
|
||||
return import(/* webpackChunkName: "features/aliases" */'../../aliases');
|
||||
}
|
||||
|
|
|
@ -110,6 +110,12 @@
|
|||
"alert.unexpected.message": "Wystąpił nieoczekiwany błąd.",
|
||||
"alert.unexpected.return_home": "Wróć na stronę główną",
|
||||
"alert.unexpected.title": "O nie!",
|
||||
"aliases.account_label": "Stare konto:",
|
||||
"aliases.account.add": "Utwórz alias",
|
||||
"aliases.aliases_list_delete": "Odłącz alias",
|
||||
"aliases.search": "Szukaj swojego starego konta",
|
||||
"aliases.success.add": "Pomyślnie utworzono alias konta",
|
||||
"aliases.success.remove": "Pomyślnie usunięto alias konta",
|
||||
"audio.close": "Zamknij dźwięk",
|
||||
"audio.expand": "Rozwiń dźwięk",
|
||||
"audio.hide": "Ukryj dźwięk",
|
||||
|
@ -143,6 +149,12 @@
|
|||
"column.admin.moderation_log": "Dziennik moderacyjny",
|
||||
"column.admin.reports": "Zgłoszenia",
|
||||
"column.admin.reports.menu.moderation_log": "Dziennik moderacji",
|
||||
"column.aliases": "Aliasy kont",
|
||||
"column.aliases.create_error": "Błąd tworzenia aliasu",
|
||||
"column.aliases.delete": "Usuń",
|
||||
"column.aliases.delete_error": "Błąd usuwania aliasu",
|
||||
"column.aliases.subheading_add_new": "Dodaj nowy alias",
|
||||
"column.aliases.subheading_aliases": "Istniejące aliasy",
|
||||
"column.backups": "Kopie zapasowe",
|
||||
"column.blocks": "Zablokowani użytkownicy",
|
||||
"column.bookmarks": "Załadki",
|
||||
|
@ -305,6 +317,7 @@
|
|||
"emoji_button.travel": "Podróże i miejsca",
|
||||
"empty_column.account_timeline": "Brak wpisów tutaj!",
|
||||
"empty_column.account_unavailable": "Profil niedostępny",
|
||||
"empty_column.aliases": "Nie utworzyłeś(-aś) jeszcze żadnego aliasu konta.",
|
||||
"empty_column.blocks": "Nie zablokowałeś(-aś) jeszcze żadnego użytkownika.",
|
||||
"empty_column.bookmarks": "Nie masz jeszcze żadnej zakładki. Kiedy dodasz jakąś, pojawi się ona tutaj.",
|
||||
"empty_column.community": "Lokalna oś czasu jest pusta. Napisz coś publicznie, aby zagaić!",
|
||||
|
@ -480,6 +493,7 @@
|
|||
"morefollows.followers_label": "…i {count} więcej {count, plural, one {obserwujący(-a)} few {obserwujących} many {obserwujących} other {obserwujących}} na zdalnych stronach.",
|
||||
"morefollows.following_label": "…i {count} więcej {count, plural, one {obserwowany(-a)} few {obserwowanych} many {obserwowanych} other {obserwowanych}} na zdalnych stronach.",
|
||||
"mute_modal.hide_notifications": "Chcesz ukryć powiadomienia od tego użytkownika?",
|
||||
"navigation_bar.account_aliases": "Aliasy kont",
|
||||
"navigation_bar.admin_settings": "Ustawienia administracyjne",
|
||||
"navigation_bar.blocks": "Zablokowani użytkownicy",
|
||||
"navigation_bar.compose": "Utwórz nowy wpis",
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||
import {
|
||||
ALIASES_SUGGESTIONS_READY,
|
||||
ALIASES_SUGGESTIONS_CLEAR,
|
||||
ALIASES_SUGGESTIONS_CHANGE,
|
||||
} from '../actions/aliases';
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
suggestions: ImmutableMap({
|
||||
value: '',
|
||||
items: ImmutableList(),
|
||||
}),
|
||||
});
|
||||
|
||||
export default function aliasesReducer(state = initialState, action) {
|
||||
switch(action.type) {
|
||||
case ALIASES_SUGGESTIONS_CHANGE:
|
||||
return state.setIn(['suggestions', 'value'], action.value);
|
||||
case ALIASES_SUGGESTIONS_READY:
|
||||
return state.setIn(['suggestions', 'items'], ImmutableList(action.accounts.map(item => item.id)));
|
||||
case ALIASES_SUGGESTIONS_CLEAR:
|
||||
return state.update('suggestions', suggestions => suggestions.withMutations(map => {
|
||||
map.set('items', ImmutableList());
|
||||
map.set('value', '');
|
||||
}));
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
|
@ -53,6 +53,7 @@ import backups from './backups';
|
|||
import admin_log from './admin_log';
|
||||
import security from './security';
|
||||
import scheduled_statuses from './scheduled_statuses';
|
||||
import aliases from './aliases';
|
||||
|
||||
const appReducer = combineReducers({
|
||||
dropdown_menu,
|
||||
|
@ -107,6 +108,7 @@ const appReducer = combineReducers({
|
|||
admin_log,
|
||||
security,
|
||||
scheduled_statuses,
|
||||
aliases,
|
||||
});
|
||||
|
||||
// Clear the state (mostly) when the user logs out
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
@import 'components/datepicker';
|
||||
@import 'components/remote-timeline';
|
||||
@import 'components/federation-restrictions';
|
||||
@import 'components/aliases';
|
||||
|
||||
// Holiday
|
||||
@import 'holiday/halloween';
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
.aliases {
|
||||
&__accounts {
|
||||
overflow-y: auto;
|
||||
|
||||
.account__display-name {
|
||||
&:hover strong {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.account__avatar {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
&_search {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 10px;
|
||||
|
||||
.search__input {
|
||||
padding: 7px 30px 6px 10px;
|
||||
}
|
||||
|
||||
> label {
|
||||
flex: 1 1;
|
||||
}
|
||||
|
||||
> .search__icon .fa {
|
||||
top: 8px;
|
||||
right: 102px !important;
|
||||
}
|
||||
|
||||
> .button {
|
||||
width: 80px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.aliases-settings-panel {
|
||||
flex: 1;
|
||||
|
||||
.item-list article {
|
||||
border-bottom: 1px solid var(--primary-text-color--faint);
|
||||
|
||||
&:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.alias__container {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
|
||||
span.alias__list-label {
|
||||
padding-right: 5px;
|
||||
color: var(--primary-text-color--faint);
|
||||
}
|
||||
|
||||
span.alias__list-value span {
|
||||
padding-right: 5px;
|
||||
text-transform: capitalize;
|
||||
|
||||
&::after {
|
||||
content: ',';
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
&::after {
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alias__delete {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
cursor: pointer;
|
||||
|
||||
span.alias__delete-label {
|
||||
color: var(--primary-text-color--faint);
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.alias__delete-icon {
|
||||
background: none;
|
||||
color: var(--primary-text-color--faint);
|
||||
padding: 0 5px;
|
||||
margin: 0 auto;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slist--flex {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue