Progress on group account search
Added group member search, group removed account, album add styles
This commit is contained in:
parent
67eb9d5890
commit
1a8ecc672c
|
@ -52,7 +52,7 @@ class Api::V1::Groups::AccountsController < Api::BaseController
|
||||||
|
|
||||||
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
render json: @group, serializer: REST::GroupRelationshipSerializer, relationships: relationships
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def relationships
|
def relationships
|
||||||
|
|
|
@ -34,6 +34,10 @@ class Api::V1::Groups::RemovedAccountsController < Api::BaseController
|
||||||
render_empty_success
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def search
|
||||||
|
# : todo :
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_group
|
def set_group
|
||||||
|
|
|
@ -113,6 +113,16 @@ class Api::V1::GroupsController < Api::BaseController
|
||||||
render_empty_success
|
render_empty_success
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def member_search
|
||||||
|
@accounts = Group.search_for_members(@group, params[:q], DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
def removed_accounts_search
|
||||||
|
@accounts = Group.search_for_removed_accounts(@group, params[:q], DEFAULT_ACCOUNTS_LIMIT)
|
||||||
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_group
|
def set_group
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
List as ImmutableList,
|
List as ImmutableList,
|
||||||
} from 'immutable'
|
} from 'immutable'
|
||||||
|
import debounce from 'lodash.debounce'
|
||||||
import api, { getLinks } from '../api'
|
import api, { getLinks } from '../api'
|
||||||
import { me } from '../initial_state'
|
import { me } from '../initial_state'
|
||||||
import { importFetchedAccounts } from './importer'
|
import { importFetchedAccounts } from './importer'
|
||||||
|
@ -33,6 +34,8 @@ export const GROUP_LEAVE_REQUEST = 'GROUP_LEAVE_REQUEST'
|
||||||
export const GROUP_LEAVE_SUCCESS = 'GROUP_LEAVE_SUCCESS'
|
export const GROUP_LEAVE_SUCCESS = 'GROUP_LEAVE_SUCCESS'
|
||||||
export const GROUP_LEAVE_FAIL = 'GROUP_LEAVE_FAIL'
|
export const GROUP_LEAVE_FAIL = 'GROUP_LEAVE_FAIL'
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
export const GROUP_MEMBERS_FETCH_REQUEST = 'GROUP_MEMBERS_FETCH_REQUEST'
|
export const GROUP_MEMBERS_FETCH_REQUEST = 'GROUP_MEMBERS_FETCH_REQUEST'
|
||||||
export const GROUP_MEMBERS_FETCH_SUCCESS = 'GROUP_MEMBERS_FETCH_SUCCESS'
|
export const GROUP_MEMBERS_FETCH_SUCCESS = 'GROUP_MEMBERS_FETCH_SUCCESS'
|
||||||
export const GROUP_MEMBERS_FETCH_FAIL = 'GROUP_MEMBERS_FETCH_FAIL'
|
export const GROUP_MEMBERS_FETCH_FAIL = 'GROUP_MEMBERS_FETCH_FAIL'
|
||||||
|
@ -41,6 +44,11 @@ export const GROUP_MEMBERS_EXPAND_REQUEST = 'GROUP_MEMBERS_EXPAND_REQUEST'
|
||||||
export const GROUP_MEMBERS_EXPAND_SUCCESS = 'GROUP_MEMBERS_EXPAND_SUCCESS'
|
export const GROUP_MEMBERS_EXPAND_SUCCESS = 'GROUP_MEMBERS_EXPAND_SUCCESS'
|
||||||
export const GROUP_MEMBERS_EXPAND_FAIL = 'GROUP_MEMBERS_EXPAND_FAIL'
|
export const GROUP_MEMBERS_EXPAND_FAIL = 'GROUP_MEMBERS_EXPAND_FAIL'
|
||||||
|
|
||||||
|
export const GROUP_MEMBERS_SEARCH_SUCCESS = 'GROUP_MEMBERS_SEARCH_SUCCESS'
|
||||||
|
export const CLEAR_GROUP_MEMBERS_SEARCH = 'CLEAR_GROUP_MEMBERS_SEARCH'
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
export const GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST = 'GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST'
|
export const GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST = 'GROUP_REMOVED_ACCOUNTS_FETCH_REQUEST'
|
||||||
export const GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS'
|
export const GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_FETCH_SUCCESS'
|
||||||
export const GROUP_REMOVED_ACCOUNTS_FETCH_FAIL = 'GROUP_REMOVED_ACCOUNTS_FETCH_FAIL'
|
export const GROUP_REMOVED_ACCOUNTS_FETCH_FAIL = 'GROUP_REMOVED_ACCOUNTS_FETCH_FAIL'
|
||||||
|
@ -49,6 +57,11 @@ export const GROUP_REMOVED_ACCOUNTS_EXPAND_REQUEST = 'GROUP_REMOVED_ACCOUNTS_EXP
|
||||||
export const GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS'
|
export const GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_EXPAND_SUCCESS'
|
||||||
export const GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL = 'GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL'
|
export const GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL = 'GROUP_REMOVED_ACCOUNTS_EXPAND_FAIL'
|
||||||
|
|
||||||
|
export const GROUP_REMOVED_ACCOUNTS_SEARCH_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_SEARCH_SUCCESS'
|
||||||
|
export const CLEAR_GROUP_REMOVED_ACCOUNTS_SEARCH = 'CLEAR_GROUP_REMOVED_ACCOUNTS_SEARCH'
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
export const GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST'
|
export const GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_REMOVE_REQUEST'
|
||||||
export const GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS'
|
export const GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_REMOVE_SUCCESS'
|
||||||
export const GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL = 'GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL'
|
export const GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL = 'GROUP_REMOVED_ACCOUNTS_REMOVE_FAIL'
|
||||||
|
@ -57,6 +70,8 @@ export const GROUP_REMOVED_ACCOUNTS_CREATE_REQUEST = 'GROUP_REMOVED_ACCOUNTS_CRE
|
||||||
export const GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS'
|
export const GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS = 'GROUP_REMOVED_ACCOUNTS_CREATE_SUCCESS'
|
||||||
export const GROUP_REMOVED_ACCOUNTS_CREATE_FAIL = 'GROUP_REMOVED_ACCOUNTS_CREATE_FAIL'
|
export const GROUP_REMOVED_ACCOUNTS_CREATE_FAIL = 'GROUP_REMOVED_ACCOUNTS_CREATE_FAIL'
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
export const GROUP_JOIN_REQUESTS_FETCH_REQUEST = 'GROUP_JOIN_REQUESTS_FETCH_REQUEST'
|
export const GROUP_JOIN_REQUESTS_FETCH_REQUEST = 'GROUP_JOIN_REQUESTS_FETCH_REQUEST'
|
||||||
export const GROUP_JOIN_REQUESTS_FETCH_SUCCESS = 'GROUP_JOIN_REQUESTS_FETCH_SUCCESS'
|
export const GROUP_JOIN_REQUESTS_FETCH_SUCCESS = 'GROUP_JOIN_REQUESTS_FETCH_SUCCESS'
|
||||||
export const GROUP_JOIN_REQUESTS_FETCH_FAIL = 'GROUP_JOIN_REQUESTS_FETCH_FAIL'
|
export const GROUP_JOIN_REQUESTS_FETCH_FAIL = 'GROUP_JOIN_REQUESTS_FETCH_FAIL'
|
||||||
|
@ -457,7 +472,7 @@ const expandMembersRequest = (groupId) => ({
|
||||||
type: GROUP_MEMBERS_EXPAND_REQUEST,
|
type: GROUP_MEMBERS_EXPAND_REQUEST,
|
||||||
groupId,
|
groupId,
|
||||||
})
|
})
|
||||||
``
|
|
||||||
const expandMembersSuccess = (groupId, accounts, next) => ({
|
const expandMembersSuccess = (groupId, accounts, next) => ({
|
||||||
type: GROUP_MEMBERS_EXPAND_SUCCESS,
|
type: GROUP_MEMBERS_EXPAND_SUCCESS,
|
||||||
groupId,
|
groupId,
|
||||||
|
@ -472,6 +487,43 @@ const expandMembersFail = (groupId, error) => ({
|
||||||
error,
|
error,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const fetchGroupMembersAdminSearch = (groupId, query) => (dispatch, getState) => {
|
||||||
|
if (!groupId || !query) return
|
||||||
|
debouncedFetchGroupMembersAdminSearch(groupId, query, dispatch, getState)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const debouncedFetchGroupMembersAdminSearch = debounce((groupId, query, dispatch, getState) => {
|
||||||
|
if (!groupId || !query) return
|
||||||
|
|
||||||
|
api(getState).get(`/api/v1/groups/${groupId}/member_search`, {
|
||||||
|
params: {
|
||||||
|
q: query,
|
||||||
|
resolve: false,
|
||||||
|
limit: 4,
|
||||||
|
},
|
||||||
|
}).then((response) => {
|
||||||
|
dispatch(importFetchedAccounts(response.data))
|
||||||
|
dispatch(fetchGroupMembersAdminSearchSuccess(response.data))
|
||||||
|
}).catch((error) => {
|
||||||
|
//
|
||||||
|
})
|
||||||
|
}, 650, { leading: true })
|
||||||
|
|
||||||
|
const fetchGroupMembersAdminSearchSuccess = (accounts) => ({
|
||||||
|
type: GROUP_MEMBERS_SEARCH_SUCCESS,
|
||||||
|
accounts,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const clearGroupMembersAdminSearch = () => (dispatch) => {
|
||||||
|
dispatch({ type: CLEAR_GROUP_MEMBERS_SEARCH })
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Fetch removed accounts for the given groupId and imports paginated
|
* @description Fetch removed accounts for the given groupId and imports paginated
|
||||||
* accounts and sets in user_lists reducer.
|
* accounts and sets in user_lists reducer.
|
||||||
|
@ -557,6 +609,43 @@ const expandRemovedAccountsFail = (groupId, error) => ({
|
||||||
error,
|
error,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const fetchGroupRemovedAccountsAdminSearch = (groupId, query) => (dispatch, getState) => {
|
||||||
|
if (!groupId || !query) return
|
||||||
|
debouncedFetchGroupRemovedAccountsAdminSearch(groupId, query, dispatch, getState)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const debouncedFetchGroupRemovedAccountsAdminSearch = debounce((groupId, query, dispatch, getState) => {
|
||||||
|
if (!groupId || !query) return
|
||||||
|
|
||||||
|
api(getState).get(`/api/v1/groups/${groupId}/removed_accounts_search`, {
|
||||||
|
params: {
|
||||||
|
q: query,
|
||||||
|
resolve: false,
|
||||||
|
limit: 4,
|
||||||
|
},
|
||||||
|
}).then((response) => {
|
||||||
|
dispatch(importFetchedAccounts(response.data))
|
||||||
|
dispatch(fetchGroupRemovedAccountsAdminSearchSuccess(response.data))
|
||||||
|
}).catch((error) => {
|
||||||
|
//
|
||||||
|
})
|
||||||
|
}, 650, { leading: true })
|
||||||
|
|
||||||
|
const fetchGroupRemovedAccountsAdminSearchSuccess = (accounts) => ({
|
||||||
|
type: GROUP_REMOVED_ACCOUNTS_SEARCH_SUCCESS,
|
||||||
|
accounts,
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const clearGroupRemovedAccountsAdminSearch = () => (dispatch) => {
|
||||||
|
dispatch({ type: CLEAR_GROUP_REMOVED_ACCOUNTS_SEARCH })
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Remove a "removed account" from a group with the given groupId and accountId.
|
* @description Remove a "removed account" from a group with the given groupId and accountId.
|
||||||
* @param {String} groupId
|
* @param {String} groupId
|
||||||
|
|
|
@ -64,7 +64,7 @@ class Account extends ImmutablePureComponent {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionButton = (onActionClick && actionIcon) ? (
|
const actionButton = (onActionClick && (actionIcon || actionTitle)) ? (
|
||||||
<Button
|
<Button
|
||||||
onClick={this.handleAction}
|
onClick={this.handleAction}
|
||||||
isOutline={true}
|
isOutline={true}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { NavLink } from 'react-router-dom'
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { CX } from '../constants'
|
import { CX } from '../constants'
|
||||||
|
@ -15,29 +14,45 @@ class Album extends React.PureComponent {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleOnOpenAlbumCreation = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { album, isDummy } = this.props
|
const {
|
||||||
|
album,
|
||||||
|
isAddable,
|
||||||
|
isDummy,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
const title = isAddable ? 'New album' : 'Album title'
|
||||||
|
const subtitle = isAddable ? '' : '10 Items'
|
||||||
|
const to = isAddable ? undefined : `/photos`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.d, _s.minW162PX, _s.px5, _s.flex1].join(' ')}>
|
<div className={[_s.d, _s.minW162PX, _s.px5, _s.flex1].join(' ')}>
|
||||||
{
|
{
|
||||||
!isDummy &&
|
!isDummy &&
|
||||||
<NavLink
|
<Button
|
||||||
className={[_s.d, _s.noUnderline].join(' ')}
|
noClasses
|
||||||
to='/'
|
className={[_s.d, _s.noUnderline, _s.noOutline, _s.bgTransparent].join(' ')}
|
||||||
|
to={to}
|
||||||
|
onClick={isAddable ? this.handleOnOpenAlbumCreation : undefined}
|
||||||
>
|
>
|
||||||
<div className={[_s.d, _s.w100PC, _s.mt5, _s.mb10].join(' ')}>
|
<div className={[_s.d, _s.w100PC, _s.mt5, _s.mb10].join(' ')}>
|
||||||
<div className={[_s.d, _s.w100PC, _s.pt100PC].join(' ')}>
|
<div className={[_s.d, _s.w100PC, _s.pt100PC].join(' ')}>
|
||||||
<div className={[_s.d, _s.posAbs, _s.top0, _s.w100PC, _s.right0, _s.bottom0, _s.left0].join(' ')}>
|
<div className={[_s.d, _s.posAbs, _s.top0, _s.w100PC, _s.right0, _s.bottom0, _s.left0].join(' ')}>
|
||||||
<div className={[_s.d, _s.w100PC, _s.h100PC, _s.radiusSmall, _s.bgTertiary, _s.border1PX, _s.borderColorSecondary].join(' ')} />
|
<div className={[_s.d, _s.w100PC, _s.h100PC, _s.aiCenter, _s.jcCenter, _s.radiusSmall, _s.bgTertiary, _s.border1PX, _s.borderColorSecondary].join(' ')}>
|
||||||
|
{ isAddable && <Icon id='add' size='20px' /> }
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={[_s.d, _s.w100PC, _s.pt7, _s.mb15].join(' ')}>
|
<div className={[_s.d, _s.w100PC, _s.pt7, _s.mb15].join(' ')}>
|
||||||
<Text weight='bold'>Profile Photos</Text>
|
<Text weight='bold'>{title}</Text>
|
||||||
<Text color='secondary' size='small' className={_s.mt5}>1 Item</Text>
|
{ !isAddable && <Text color='secondary' size='small' className={_s.mt5}>{subtitle}</Text> }
|
||||||
</div>
|
</div>
|
||||||
</NavLink>
|
</Button>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -95,6 +95,8 @@ class MediaItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
const statusUrl = `/${account.getIn(['acct'])}/posts/${status.get('id')}`;
|
const statusUrl = `/${account.getIn(['acct'])}/posts/${status.get('id')}`;
|
||||||
|
|
||||||
|
// : todo : fix dimensions to be like albums
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.d, _s.pt25PC].join(' ')}>
|
<div className={[_s.d, _s.pt25PC].join(' ')}>
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses}>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
// : todo :
|
|
@ -15,55 +15,6 @@ class ToastsContainer extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { notifications } = this.props
|
const { notifications } = this.props
|
||||||
|
|
||||||
console.log("notifications:", notifications)
|
|
||||||
|
|
||||||
// const notifications = [
|
|
||||||
// {
|
|
||||||
// key: '1',
|
|
||||||
// title: 'Error',
|
|
||||||
// to: 'to',
|
|
||||||
// image: 'https://gab.com/media/user/58077e8a49705.jpg',
|
|
||||||
// message: 'Unable to follow @andrew',
|
|
||||||
// date: new Date(),
|
|
||||||
// isImageAccount: true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// key: '2',
|
|
||||||
// title: 'Success',
|
|
||||||
// to: 'to',
|
|
||||||
// image: 'https://gab.com/media/user/58077e8a49705.jpg',
|
|
||||||
// message: 'Your gab was posted. Click here to view',
|
|
||||||
// date: new Date(),
|
|
||||||
// isImageAccount: false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// key: '3',
|
|
||||||
// title: '',
|
|
||||||
// to: 'to',
|
|
||||||
// image: 'https://gab.com/media/user/58077e8a49705.jpg',
|
|
||||||
// message: 'Unable to follow @andrew',
|
|
||||||
// date: new Date(),
|
|
||||||
// isImageAccount: true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// key: '4',
|
|
||||||
// title: '',
|
|
||||||
// to: 'to',
|
|
||||||
// image: 'https://gab.com/media/user/58077e8a49705.jpg',
|
|
||||||
// message: 'Your gab was posted. Click here to view',
|
|
||||||
// date: new Date(),
|
|
||||||
// isImageAccount: false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// key: '5',
|
|
||||||
// title: '',
|
|
||||||
// to: 'to',
|
|
||||||
// message: 'Your gab was deleted',
|
|
||||||
// date: new Date(),
|
|
||||||
// isImageAccount: false,
|
|
||||||
// },
|
|
||||||
// ]
|
|
||||||
|
|
||||||
const hasNotifications = !!notifications && notifications.size > 0
|
const hasNotifications = !!notifications && notifications.size > 0
|
||||||
|
|
||||||
const containerClasses = CX({
|
const containerClasses = CX({
|
||||||
|
@ -76,6 +27,7 @@ class ToastsContainer extends React.PureComponent {
|
||||||
pt15: 1,
|
pt15: 1,
|
||||||
heightMax100VH: 1,
|
heightMax100VH: 1,
|
||||||
pb10: 1,
|
pb10: 1,
|
||||||
|
saveAreaInsetMB: 1,
|
||||||
displayNone: !hasNotifications
|
displayNone: !hasNotifications
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,13 @@ class AccountAlbums extends ImmutablePureComponent {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {
|
||||||
|
account,
|
||||||
|
isMe,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
if (!account) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Block>
|
<Block>
|
||||||
<div className={[_s.d, _s.px10, _s.py10].join(' ')}>
|
<div className={[_s.d, _s.px10, _s.py10].join(' ')}>
|
||||||
|
@ -76,18 +83,18 @@ class AccountAlbums extends ImmutablePureComponent {
|
||||||
<TabBar tabs={[
|
<TabBar tabs={[
|
||||||
{
|
{
|
||||||
title: 'All Photos',
|
title: 'All Photos',
|
||||||
to: '/'
|
to: `/${account.get('username')}/photos`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Albums',
|
title: 'Albums',
|
||||||
isActive: true,
|
isActive: true,
|
||||||
to: '/'
|
to: `/${account.get('username')}/albums`,
|
||||||
},
|
},
|
||||||
]}/>
|
]}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={[_s.d, _s.w100PC, _s.flexRow, _s.flexWrap, _s.px10, _s.mb15, _s.pb10].join(' ')}>
|
<div className={[_s.d, _s.w100PC, _s.flexRow, _s.flexWrap, _s.px10, _s.mb15, _s.pb10].join(' ')}>
|
||||||
<Album />
|
{ isMe && <Album isAddable /> }
|
||||||
<Album />
|
<Album />
|
||||||
<Album />
|
<Album />
|
||||||
<Album />
|
<Album />
|
||||||
|
@ -111,7 +118,7 @@ class AccountAlbums extends ImmutablePureComponent {
|
||||||
// account,
|
// account,
|
||||||
// } = this.props
|
// } = this.props
|
||||||
|
|
||||||
// if (!account) return null
|
|
||||||
|
|
||||||
// return (
|
// return (
|
||||||
// <Block>
|
// <Block>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
// : todo :
|
|
@ -10,6 +10,7 @@ import { me } from '../initial_state'
|
||||||
import {
|
import {
|
||||||
fetchMembers,
|
fetchMembers,
|
||||||
expandMembers,
|
expandMembers,
|
||||||
|
fetchGroupMembersAdminSearch,
|
||||||
} from '../actions/groups'
|
} from '../actions/groups'
|
||||||
import { openPopover } from '../actions/popover'
|
import { openPopover } from '../actions/popover'
|
||||||
import Account from '../components/account'
|
import Account from '../components/account'
|
||||||
|
@ -21,6 +22,10 @@ import ScrollableList from '../components/scrollable_list'
|
||||||
|
|
||||||
class GroupMembers extends ImmutablePureComponent {
|
class GroupMembers extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
state = {
|
||||||
|
query: '',
|
||||||
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { groupId } = this.props
|
const { groupId } = this.props
|
||||||
|
|
||||||
|
@ -44,20 +49,29 @@ class GroupMembers extends ImmutablePureComponent {
|
||||||
this.props.onExpandMembers(this.props.groupId)
|
this.props.onExpandMembers(this.props.groupId)
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleOnChange = (query) => {
|
||||||
|
this.setState({ query })
|
||||||
|
this.props.onChange(this.props.groupId, query)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
accountIds,
|
listAccountIds,
|
||||||
|
searchAcountIds,
|
||||||
hasMore,
|
hasMore,
|
||||||
group,
|
group,
|
||||||
relationships,
|
relationships,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
const { query } = this.state
|
||||||
|
|
||||||
if (!group || !relationships) return <ColumnIndicator type='loading' />
|
if (!group || !relationships) return <ColumnIndicator type='loading' />
|
||||||
|
|
||||||
const isAdminOrMod = relationships ? (relationships.get('admin') || relationships.get('moderator')) : false
|
const isAdminOrMod = relationships ? (relationships.get('admin') || relationships.get('moderator')) : false
|
||||||
|
|
||||||
if (!isAdminOrMod) return <ColumnIndicator type='missing' />
|
if (!isAdminOrMod) return <ColumnIndicator type='missing' />
|
||||||
|
|
||||||
|
const accountIds = !!query ? searchAcountIds : listAccountIds
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Block>
|
<Block>
|
||||||
<BlockHeading title='Group Members' />
|
<BlockHeading title='Group Members' />
|
||||||
|
@ -67,11 +81,8 @@ class GroupMembers extends ImmutablePureComponent {
|
||||||
id='group-member-search'
|
id='group-member-search'
|
||||||
placeholder='Search group members'
|
placeholder='Search group members'
|
||||||
prependIcon='search'
|
prependIcon='search'
|
||||||
// value={value}
|
value={query}
|
||||||
onKeyUp={this.handleKeyUp}
|
|
||||||
onChange={this.handleOnChange}
|
onChange={this.handleOnChange}
|
||||||
onFocus={this.handleOnFocus}
|
|
||||||
onBlur={this.handleOnBlur}
|
|
||||||
autoComplete='off'
|
autoComplete='off'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,17 +120,21 @@ class GroupMembers extends ImmutablePureComponent {
|
||||||
const mapStateToProps = (state, { params }) => {
|
const mapStateToProps = (state, { params }) => {
|
||||||
const groupId = isObject(params) ? params['id'] : -1
|
const groupId = isObject(params) ? params['id'] : -1
|
||||||
const group = groupId === -1 ? null : state.getIn(['groups', groupId])
|
const group = groupId === -1 ? null : state.getIn(['groups', groupId])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
group,
|
group,
|
||||||
groupId,
|
groupId,
|
||||||
|
listAccountIds: state.getIn(['user_lists', 'groups', groupId, 'items']),
|
||||||
|
searchAcountIds: state.getIn(['group_lists', 'member_search_accounts']),
|
||||||
relationships: state.getIn(['group_relationships', groupId]),
|
relationships: state.getIn(['group_relationships', groupId]),
|
||||||
accountIds: state.getIn(['user_lists', 'groups', groupId, 'items']),
|
|
||||||
hasMore: !!state.getIn(['user_lists', 'groups', groupId, 'next']),
|
hasMore: !!state.getIn(['user_lists', 'groups', groupId, 'next']),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
onChange(groupId, query) {
|
||||||
|
dispatch(fetchGroupMembersAdminSearch(groupId, query))
|
||||||
|
},
|
||||||
onFetchMembers(groupId) {
|
onFetchMembers(groupId) {
|
||||||
dispatch(fetchMembers(groupId))
|
dispatch(fetchMembers(groupId))
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,13 +3,13 @@ import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { defineMessages, injectIntl } from 'react-intl'
|
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
import isObject from 'lodash.isobject'
|
import isObject from 'lodash.isobject'
|
||||||
import {
|
import {
|
||||||
fetchRemovedAccounts,
|
fetchRemovedAccounts,
|
||||||
expandRemovedAccounts,
|
expandRemovedAccounts,
|
||||||
removeRemovedAccount,
|
removeRemovedAccount,
|
||||||
|
fetchGroupRemovedAccountsAdminSearch,
|
||||||
} from '../actions/groups'
|
} from '../actions/groups'
|
||||||
import { FormattedMessage } from 'react-intl'
|
import { FormattedMessage } from 'react-intl'
|
||||||
import Account from '../components/account'
|
import Account from '../components/account'
|
||||||
|
@ -21,6 +21,10 @@ import ScrollableList from '../components/scrollable_list'
|
||||||
|
|
||||||
class GroupRemovedAccounts extends ImmutablePureComponent {
|
class GroupRemovedAccounts extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
state = {
|
||||||
|
query: '',
|
||||||
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const { groupId } = this.props
|
const { groupId } = this.props
|
||||||
|
|
||||||
|
@ -37,16 +41,24 @@ class GroupRemovedAccounts extends ImmutablePureComponent {
|
||||||
this.props.onExpandRemovedAccounts(this.props.groupId)
|
this.props.onExpandRemovedAccounts(this.props.groupId)
|
||||||
}, 300, { leading: true })
|
}, 300, { leading: true })
|
||||||
|
|
||||||
|
handleOnChange = (query) => {
|
||||||
|
this.setState({ query })
|
||||||
|
this.props.onChange(this.props.groupId, query)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
accountIds,
|
listAccountIds,
|
||||||
|
searchAcountIds,
|
||||||
hasMore,
|
hasMore,
|
||||||
group,
|
group,
|
||||||
intl,
|
|
||||||
} = this.props
|
} = this.props
|
||||||
|
const { query } = this.state
|
||||||
|
|
||||||
if (!group) return <ColumnIndicator type='loading' />
|
if (!group) return <ColumnIndicator type='loading' />
|
||||||
|
|
||||||
|
const accountIds = !!query ? searchAcountIds : listAccountIds
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Block>
|
<Block>
|
||||||
<BlockHeading title='Removed Accounts' />
|
<BlockHeading title='Removed Accounts' />
|
||||||
|
@ -55,11 +67,8 @@ class GroupRemovedAccounts extends ImmutablePureComponent {
|
||||||
id='group-member-search'
|
id='group-member-search'
|
||||||
placeholder='Search removed group members'
|
placeholder='Search removed group members'
|
||||||
prependIcon='search'
|
prependIcon='search'
|
||||||
// value={value}
|
value={query}
|
||||||
onKeyUp={this.handleKeyUp}
|
|
||||||
onChange={this.handleOnChange}
|
onChange={this.handleOnChange}
|
||||||
onFocus={this.handleOnFocus}
|
|
||||||
onBlur={this.handleOnBlur}
|
|
||||||
autoComplete='off'
|
autoComplete='off'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -73,11 +82,11 @@ class GroupRemovedAccounts extends ImmutablePureComponent {
|
||||||
{
|
{
|
||||||
accountIds && accountIds.map((id) => (
|
accountIds && accountIds.map((id) => (
|
||||||
<Account
|
<Account
|
||||||
|
compact
|
||||||
key={id}
|
key={id}
|
||||||
id={id}
|
id={id}
|
||||||
actionIcon='subtract'
|
|
||||||
onActionClick={() => this.props.onRemoveRemovedAccount(group.get('id'), id)}
|
onActionClick={() => this.props.onRemoveRemovedAccount(group.get('id'), id)}
|
||||||
actionTitle={intl.formatMessage(messages.remove)}
|
actionTitle='Allow to join'
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -88,10 +97,6 @@ class GroupRemovedAccounts extends ImmutablePureComponent {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
remove: { id: 'groups.removed_accounts', defaultMessage: 'Allow joining' },
|
|
||||||
})
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { params }) => {
|
const mapStateToProps = (state, { params }) => {
|
||||||
const groupId = isObject(params) ? params['id'] : -1
|
const groupId = isObject(params) ? params['id'] : -1
|
||||||
const group = groupId === -1 ? null : state.getIn(['groups', groupId])
|
const group = groupId === -1 ? null : state.getIn(['groups', groupId])
|
||||||
|
@ -99,12 +104,16 @@ const mapStateToProps = (state, { params }) => {
|
||||||
return {
|
return {
|
||||||
group,
|
group,
|
||||||
groupId,
|
groupId,
|
||||||
accountIds: state.getIn(['user_lists', 'group_removed_accounts', groupId, 'items']),
|
listAccountIds: state.getIn(['user_lists', 'group_removed_accounts', groupId, 'items']),
|
||||||
|
searchAcountIds: state.getIn(['group_lists', 'removed_search_accounts']),
|
||||||
hasMore: !!state.getIn(['user_lists', 'group_removed_accounts', groupId, 'next']),
|
hasMore: !!state.getIn(['user_lists', 'group_removed_accounts', groupId, 'next']),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
onChange(groupId, query) {
|
||||||
|
dispatch(fetchGroupRemovedAccountsAdminSearch(groupId, query))
|
||||||
|
},
|
||||||
onFetchRemovedAccounts(groupId) {
|
onFetchRemovedAccounts(groupId) {
|
||||||
dispatch(fetchRemovedAccounts(groupId))
|
dispatch(fetchRemovedAccounts(groupId))
|
||||||
},
|
},
|
||||||
|
@ -125,4 +134,4 @@ GroupRemovedAccounts.propTypes = {
|
||||||
onRemoveRemovedAccount: PropTypes.func.isRequired,
|
onRemoveRemovedAccount: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(GroupRemovedAccounts))
|
export default connect(mapStateToProps, mapDispatchToProps)(GroupRemovedAccounts)
|
|
@ -174,7 +174,7 @@ class ChatMessageItem extends ImmutablePureComponent {
|
||||||
!!expirationDate &&
|
!!expirationDate &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<DotTextSeperator />
|
<DotTextSeperator />
|
||||||
<Text size='extraSmall' color='tertiary' className={_s.ml5}>Expires in {timeUntilExpiration}</Text>
|
<Text size='extraSmall' color='tertiary' className={_s.ml5}>Expires {timeUntilExpiration}</Text>
|
||||||
<Icon id='stopwatch' size='11px' className={[_s.d, _s.ml5, _s.displayInline, _s.cSecondary].join(' ')} />
|
<Icon id='stopwatch' size='11px' className={[_s.d, _s.ml5, _s.displayInline, _s.cSecondary].join(' ')} />
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ class MessagesLayout extends React.PureComponent {
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
icon: 'add',
|
icon: 'add',
|
||||||
to: '/messages/new',
|
to: `'/messages/new'`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'cog',
|
icon: 'cog',
|
||||||
|
|
|
@ -16,6 +16,10 @@ import {
|
||||||
GROUPS_BY_TAG_FETCH_REQUEST,
|
GROUPS_BY_TAG_FETCH_REQUEST,
|
||||||
GROUPS_BY_TAG_FETCH_SUCCESS,
|
GROUPS_BY_TAG_FETCH_SUCCESS,
|
||||||
GROUPS_BY_TAG_FETCH_FAIL,
|
GROUPS_BY_TAG_FETCH_FAIL,
|
||||||
|
GROUP_MEMBERS_SEARCH_SUCCESS,
|
||||||
|
CLEAR_GROUP_MEMBERS_SEARCH,
|
||||||
|
GROUP_REMOVED_ACCOUNTS_SEARCH_SUCCESS,
|
||||||
|
CLEAR_GROUP_REMOVED_ACCOUNTS_SEARCH,
|
||||||
} from '../actions/groups'
|
} from '../actions/groups'
|
||||||
import {
|
import {
|
||||||
GROUP_TIMELINE_SORTING_TYPE_TOP,
|
GROUP_TIMELINE_SORTING_TYPE_TOP,
|
||||||
|
@ -51,6 +55,8 @@ const initialState = ImmutableMap({
|
||||||
}),
|
}),
|
||||||
by_category: ImmutableMap(),
|
by_category: ImmutableMap(),
|
||||||
by_tag: ImmutableMap(),
|
by_tag: ImmutableMap(),
|
||||||
|
member_search_accounts: ImmutableList(),
|
||||||
|
removed_search_accounts: ImmutableList(),
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function groupLists(state = initialState, action) {
|
export default function groupLists(state = initialState, action) {
|
||||||
|
@ -144,6 +150,14 @@ export default function groupLists(state = initialState, action) {
|
||||||
items: ImmutableList(),
|
items: ImmutableList(),
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
}))
|
}))
|
||||||
|
case GROUP_MEMBERS_SEARCH_SUCCESS:
|
||||||
|
return state.set('member_search_accounts', ImmutableList(action.accounts.map((item) => item.id)))
|
||||||
|
case CLEAR_GROUP_MEMBERS_SEARCH:
|
||||||
|
return state.set('member_search_accounts', ImmutableList())
|
||||||
|
case GROUP_REMOVED_ACCOUNTS_SEARCH_SUCCESS:
|
||||||
|
return state.set('removed_search_accounts', ImmutableList(action.accounts.map((item) => item.id)))
|
||||||
|
case CLEAR_GROUP_REMOVED_ACCOUNTS_SEARCH:
|
||||||
|
return state.set('removed_search_accounts', ImmutableList())
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
|
@ -404,7 +404,7 @@ class Account < ApplicationRecord
|
||||||
records
|
records
|
||||||
end
|
end
|
||||||
|
|
||||||
def advanced_search_for(terms, account, limit = 10, following = false, offset = 0, options = {})
|
def advanced_search_for(terms, account, limit = 10, offset = 0, options = {})
|
||||||
textsearch, query = generate_query_for_search(terms)
|
textsearch, query = generate_query_for_search(terms)
|
||||||
@onlyVerified = options[:onlyVerified] || false
|
@onlyVerified = options[:onlyVerified] || false
|
||||||
|
|
||||||
|
@ -426,7 +426,6 @@ class Account < ApplicationRecord
|
||||||
|
|
||||||
records = find_by_sql([sql, account.id, account.id, limit, offset])
|
records = find_by_sql([sql, account.id, account.id, limit, offset])
|
||||||
|
|
||||||
|
|
||||||
ActiveRecord::Associations::Preloader.new.preload(records, :account_stat)
|
ActiveRecord::Associations::Preloader.new.preload(records, :account_stat)
|
||||||
records
|
records
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,6 +70,16 @@ class Group < ApplicationRecord
|
||||||
.limit(25)
|
.limit(25)
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def search_for_members(group, term, limit)
|
||||||
|
pattern = '%' + sanitize_sql_like(term.strip) + '%'
|
||||||
|
group.accounts.where("LOWER(username) LIKE LOWER(?)", pattern).limit(limit)
|
||||||
|
end
|
||||||
|
|
||||||
|
def search_for_removed_accounts(group, term, limit)
|
||||||
|
pattern = '%' + sanitize_sql_like(term.strip) + '%'
|
||||||
|
group.removed_accounts.where("LOWER(username) LIKE LOWER(?)", pattern).limit(limit)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_password?
|
def has_password?
|
||||||
|
|
|
@ -4,13 +4,13 @@ class AccountSearchService < BaseService
|
||||||
attr_reader :query, :limit, :offset, :options, :account
|
attr_reader :query, :limit, :offset, :options, :account
|
||||||
|
|
||||||
def call(query, account = nil, options = {})
|
def call(query, account = nil, options = {})
|
||||||
puts "query:"+query.inspect
|
|
||||||
@query = query.strip
|
@query = query.strip
|
||||||
@limit = options[:limit].to_i
|
@limit = options[:limit].to_i
|
||||||
@offset = options[:offset].to_i
|
@offset = options[:offset].to_i
|
||||||
@onlyVerified = options[:onlyVerified] || false
|
@onlyVerified = options[:onlyVerified] || false
|
||||||
@options = options
|
@options = options
|
||||||
@account = account
|
@account = account
|
||||||
|
@group = options[:group] || nil
|
||||||
|
|
||||||
search_service_results
|
search_service_results
|
||||||
end
|
end
|
||||||
|
@ -84,7 +84,7 @@ class AccountSearchService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def advanced_search_results
|
def advanced_search_results
|
||||||
Account.advanced_search_for(terms_for_query, account, limit, options[:following], offset, onlyVerified: @onlyVerified)
|
Account.advanced_search_for(terms_for_query, account, limit, offset, onlyVerified: @onlyVerified)
|
||||||
end
|
end
|
||||||
|
|
||||||
def simple_search_results
|
def simple_search_results
|
||||||
|
|
|
@ -349,6 +349,9 @@ Rails.application.routes.draw do
|
||||||
member do
|
member do
|
||||||
delete '/statuses/:status_id', to: 'groups#destroy_status'
|
delete '/statuses/:status_id', to: 'groups#destroy_status'
|
||||||
post '/statuses/:status_id/approve', to: 'groups#approve_status'
|
post '/statuses/:status_id/approve', to: 'groups#approve_status'
|
||||||
|
|
||||||
|
get '/member_search', to: 'groups#member_search'
|
||||||
|
get '/removed_accounts_search', to: 'groups#removed_accounts_search'
|
||||||
end
|
end
|
||||||
|
|
||||||
get '/category/:category', to: 'groups#by_category'
|
get '/category/:category', to: 'groups#by_category'
|
||||||
|
|
Loading…
Reference in New Issue