Progress
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { changeValue, submit, reset } from '../../actions/group_editor'
|
||||
import Block from '../../components/block'
|
||||
import Button from '../../components/button'
|
||||
import Icon from '../../components/icon'
|
||||
import Input from '../../components/icon'
|
||||
import { changeValue, submit, reset } from '../actions/group_editor'
|
||||
import Button from '../components/button'
|
||||
import Divider from '../components/divider'
|
||||
import Input from '../components/input'
|
||||
import Text from '../components/text'
|
||||
import Textarea from '../components/textarea'
|
||||
import FileInput from '../components/file_input'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'groups.form.title', defaultMessage: 'Enter a new group title' },
|
||||
@@ -69,45 +71,55 @@ class Create extends PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { title, description, coverImage, disabled, intl } = this.props
|
||||
const {
|
||||
title,
|
||||
description,
|
||||
coverImage,
|
||||
disabled,
|
||||
intl
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<Block>
|
||||
<form className='group-form' onSubmit={this.handleSubmit}>
|
||||
<div>
|
||||
<Input
|
||||
type='text'
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={intl.formatMessage(messages.title)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<textarea
|
||||
className='standard'
|
||||
type='text'
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={intl.formatMessage(messages.description)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='group_cover_image' className='group-form__file-label--selected'>
|
||||
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
</label>
|
||||
<input
|
||||
type='file'
|
||||
className='group-form__file'
|
||||
id='group_cover_image'
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
/>
|
||||
<button className='button'>{intl.formatMessage(messages.create)}</button>
|
||||
</div>
|
||||
</form>
|
||||
</Block>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.title)}
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={'New group title...'}
|
||||
/>
|
||||
|
||||
<Divider invisible />
|
||||
|
||||
<Textarea
|
||||
title={intl.formatMessage(messages.description)}
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={'Some group description...'}
|
||||
/>
|
||||
|
||||
<Divider invisible />
|
||||
|
||||
<FileInput
|
||||
title={intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
width='340px'
|
||||
height='145px'
|
||||
/>
|
||||
|
||||
<Divider invisible />
|
||||
|
||||
<Button
|
||||
className={_s.marginLeft10PX}
|
||||
>
|
||||
<Text color='white'>
|
||||
{intl.formatMessage(messages.create)}
|
||||
</Text>
|
||||
</Button>
|
||||
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { changeValue, submit, setUp } from '../../../actions/group_editor';
|
||||
import { changeValue, submit, setUp } from '../../actions/group_editor';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ColumnIndicator from '../../../components/column_indicator';
|
||||
import ColumnIndicator from '../../components/column_indicator';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const messages = defineMessages({
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from '../introduction'
|
||||
@@ -1,20 +0,0 @@
|
||||
.list-adder {
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
@include size(100%);
|
||||
|
||||
@media screen and (max-width: 420px) {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
&__account {
|
||||
background: lighten($ui-base-color, 13%);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&__lists {
|
||||
background: lighten($ui-base-color, 13%);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import { setupListAdder, resetListAdder } from '../../actions/lists';
|
||||
import List from './components/list';
|
||||
import Account from '../../components/account';
|
||||
import IconButton from '../../components/icon_button';
|
||||
import NewListForm from '../lists_directory/components/new_list_form';
|
||||
// import NewListForm from '../lists_directory/components/new_list_form';
|
||||
|
||||
const getOrderedLists = createSelector([state => state.get('lists')], lists => {
|
||||
if (!lists) {
|
||||
@@ -67,7 +67,9 @@ class ListAdder extends ImmutablePureComponent {
|
||||
return (
|
||||
<div className='modal-root__modal compose-modal'>
|
||||
<div className='compose-modal__header'>
|
||||
<h3 className='compose-modal__header__title'>{intl.formatMessage(messages.headerTitle)}</h3>
|
||||
<h3 className='compose-modal__header__title'>
|
||||
{intl.formatMessage(messages.headerTitle)}
|
||||
</h3>
|
||||
<IconButton className='compose-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={this.onClickClose} size={20} />
|
||||
</div>
|
||||
<div className='compose-modal__content'>
|
||||
@@ -78,12 +80,14 @@ class ListAdder extends ImmutablePureComponent {
|
||||
|
||||
<br />
|
||||
|
||||
<NewListForm />
|
||||
{ /* <NewListForm /> */ }
|
||||
|
||||
<br />
|
||||
|
||||
<div className='list-adder__lists'>
|
||||
{listIds.map(ListId => <List key={ListId} listId={ListId} />)}
|
||||
{
|
||||
listIds.map(ListId => <List key={ListId} listId={ListId} />)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
73
app/javascript/gabsocial/features/list_create.js
Normal file
73
app/javascript/gabsocial/features/list_create.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { changeListEditorTitle, submitListEditor } from '../actions/lists'
|
||||
import Button from '../components/button'
|
||||
import Input from '../components/input'
|
||||
import Text from '../components/text'
|
||||
|
||||
const messages = defineMessages({
|
||||
label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' },
|
||||
create: { id: 'lists.new.create_title', defaultMessage: 'Create' },
|
||||
})
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
value: state.getIn(['listEditor', 'title']),
|
||||
disabled: state.getIn(['listEditor', 'isSubmitting']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onChange: value => dispatch(changeListEditorTitle(value)),
|
||||
onSubmit: () => dispatch(submitListEditor(true)),
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListCreate extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
value,
|
||||
disabled,
|
||||
intl,
|
||||
onSubmit,
|
||||
onChange
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.label)}
|
||||
placeholder='My new list...'
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onSubmit={onSubmit}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
<div className={[_s.default, _s.marginVertical10PX, _s.paddingVertical5PX, _s.marginLeft10PX].join(' ')}>
|
||||
<Text color='secondary' size='small'>
|
||||
Lists are private and only you can see who is on a list.<br/>
|
||||
No one else can view your lists. No one knows that they are on your list.
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className={_s.marginLeft10PX}
|
||||
>
|
||||
<Text color='white'>
|
||||
{intl.formatMessage(messages.create)}
|
||||
</Text>
|
||||
</Button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
1
app/javascript/gabsocial/features/list_edit/index.js
Normal file
1
app/javascript/gabsocial/features/list_edit/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './list_edit'
|
||||
@@ -6,6 +6,7 @@ import Account from './components/account';
|
||||
import ListEditorSearch from './components/list_editor_search';
|
||||
import EditListForm from './components/edit_list_form/edit_list_form';
|
||||
import IconButton from '../../components/icon_button';
|
||||
import Input from '../../components/input'
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
accountIds: state.getIn(['listEditor', 'accounts', 'items']),
|
||||
@@ -28,7 +29,7 @@ const messages = defineMessages({
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class ListEditor extends ImmutablePureComponent {
|
||||
class ListEdit extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
listId: PropTypes.string.isRequired,
|
||||
@@ -42,7 +43,7 @@ class ListEditor extends ImmutablePureComponent {
|
||||
|
||||
componentDidMount() {
|
||||
const { onInitialize, listId } = this.props;
|
||||
onInitialize(listId);
|
||||
if (listId) onInitialize(listId);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@@ -57,36 +58,44 @@ class ListEditor extends ImmutablePureComponent {
|
||||
const { accountIds, searchAccountIds, intl } = this.props;
|
||||
|
||||
return (
|
||||
<div className='modal-root__modal compose-modal'>
|
||||
<div className='compose-modal__header'>
|
||||
<h3 className='compose-modal__header__title'>
|
||||
{intl.formatMessage(messages.editList)}
|
||||
</h3>
|
||||
<IconButton className='compose-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={this.onClickClose} size={20} />
|
||||
</div>
|
||||
<div className='compose-modal__content'>
|
||||
<div className='list-editor'>
|
||||
<EditListForm />
|
||||
<br />
|
||||
|
||||
{
|
||||
accountIds.size > 0 &&
|
||||
<div>
|
||||
<div className='list-editor__accounts'>
|
||||
{accountIds.map(accountId => <Account key={accountId} accountId={accountId} added />)}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<br />
|
||||
<ListEditorSearch />
|
||||
<div className='list-editor__accounts'>
|
||||
{searchAccountIds.map(accountId => <Account key={accountId} accountId={accountId} />)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.editList)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
|
||||
// return (
|
||||
// <div className='modal-root__modal compose-modal'>
|
||||
// <div className='compose-modal__header'>
|
||||
// <h3 className='compose-modal__header__title'>
|
||||
// {intl.formatMessage(messages.editList)}
|
||||
// </h3>
|
||||
// <IconButton className='compose-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={this.onClickClose} size={20} />
|
||||
// </div>
|
||||
// <div className='compose-modal__content'>
|
||||
// <div className='list-editor'>
|
||||
// <EditListForm />
|
||||
// <br />
|
||||
|
||||
// {
|
||||
// accountIds.size > 0 &&
|
||||
// <div>
|
||||
// <div className='list-editor__accounts'>
|
||||
// {accountIds.map(accountId => <Account key={accountId} accountId={accountId} added />)}
|
||||
// </div>
|
||||
// </div>
|
||||
// }
|
||||
|
||||
// <br />
|
||||
// <ListEditorSearch />
|
||||
// <div className='list-editor__accounts'>
|
||||
// {searchAccountIds.map(accountId => <Account key={accountId} accountId={accountId} />)}
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// </div>
|
||||
// );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './list_editor'
|
||||
@@ -1,66 +0,0 @@
|
||||
.list-editor {
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
|
||||
@include size(100%);
|
||||
|
||||
@media screen and (max-width: 420px) {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
h4 {
|
||||
padding: 15px 0;
|
||||
background: lighten($ui-base-color, 13%);
|
||||
border-radius: 8px 8px 0 0;
|
||||
|
||||
@include text-sizing(16px, 500, 1, center);
|
||||
}
|
||||
|
||||
.drawer__inner {
|
||||
border-radius: 0 0 8px 8px;
|
||||
|
||||
&.backdrop {
|
||||
width: calc(100% - 60px);
|
||||
box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4);
|
||||
border-radius: 0 0 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&__accounts {
|
||||
background: lighten($ui-base-color, 13%);
|
||||
overflow-y: auto;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.account {
|
||||
&__display-name {
|
||||
&:hover strong {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 10px 0;
|
||||
|
||||
>label {
|
||||
flex: 1 1;
|
||||
}
|
||||
|
||||
>.search__icon .fa {
|
||||
right: 102px !important;
|
||||
}
|
||||
|
||||
>.button {
|
||||
width: 80px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,9 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { createSelector } from 'reselect'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { fetchLists } from '../../actions/lists'
|
||||
import ColumnIndicator from '../../components/column_indicator'
|
||||
import List from '../../components/list'
|
||||
import { fetchLists } from '../actions/lists'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import List from '../components/list'
|
||||
|
||||
const messages = defineMessages({
|
||||
add: { id: 'lists.new.create', defaultMessage: 'Add List' },
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './new_list_form'
|
||||
@@ -1,48 +0,0 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { changeListEditorTitle, submitListEditor } from '../../../../actions/lists';
|
||||
import ColumnInlineForm from '../../../../components/column_inline_form';
|
||||
|
||||
const messages = defineMessages({
|
||||
label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' },
|
||||
create: { id: 'lists.new.create_title', defaultMessage: 'Create' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
value: state.getIn(['listEditor', 'title']),
|
||||
disabled: state.getIn(['listEditor', 'isSubmitting']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onChange: value => dispatch(changeListEditorTitle(value)),
|
||||
onSubmit: () => dispatch(submitListEditor(true)),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class NewListForm extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { value, disabled, intl, onSubmit, onChange } = this.props;
|
||||
|
||||
return (
|
||||
<ColumnInlineForm
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onSubmit={onSubmit}
|
||||
label={intl.formatMessage(messages.label)}
|
||||
btnTitle={intl.formatMessage(messages.create)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './lists_directory'
|
||||
@@ -28,6 +28,7 @@ import NotificationsPage from '../../pages/notifications_page'
|
||||
import ListPage from '../../pages/list_page'
|
||||
import ListsPage from '../../pages/lists_page'
|
||||
import BasicPage from '../../pages/basic_page'
|
||||
import ModalPage from '../../pages/modal_page'
|
||||
import SettingsPage from '../../pages/settings_page'
|
||||
|
||||
import {
|
||||
@@ -51,7 +52,9 @@ import {
|
||||
GroupTimeline,
|
||||
HashtagTimeline,
|
||||
HomeTimeline,
|
||||
ListCreate,
|
||||
ListsDirectory,
|
||||
ListEdit,
|
||||
ListTimeline,
|
||||
Mutes,
|
||||
Notifications,
|
||||
@@ -141,18 +144,21 @@ class SwitchingArea extends PureComponent {
|
||||
<WrappedRoute path='/timeline/all' exact page={BasicPage} component={CommunityTimeline} content={children} componentParams={{ title: 'Hashtag Timeline' }} />
|
||||
|
||||
<WrappedRoute path='/groups' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'featured' }} />
|
||||
<WrappedRoute path='/groups/new' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'new' }} />
|
||||
<WrappedRoute path='/groups/browse/member' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'member' }} />
|
||||
<WrappedRoute path='/groups/browse/admin' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'admin' }} />
|
||||
|
||||
<WrappedRoute path='/groups/create' page={GroupsPage} component={GroupCreate} content={children} componentParams={{ showCreateForm: true, activeTab: 'featured' }} />
|
||||
<WrappedRoute path='/groups/create' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Create Group' }} />
|
||||
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
|
||||
<WrappedRoute path='/groups/:id/removed_accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} />
|
||||
<WrappedRoute path='/groups/:id/edit' page={GroupPage} component={GroupEdit} content={children} />
|
||||
<WrappedRoute path='/groups/:id/edit' page={ModalPage} component={GroupEdit} content={children} componentParams={{ title: 'Edit Group' }} />
|
||||
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} />
|
||||
|
||||
<WrappedRoute path='/tags/:id' publicRoute page={BasicPage} component={HashtagTimeline} content={children} componentParams={{ title: 'Hashtag' }} />
|
||||
|
||||
<WrappedRoute path='/lists' exact page={ListsPage} component={ListsDirectory} content={children} />
|
||||
<WrappedRoute path='/lists/create' exact page={ModalPage} component={ListCreate} content={children} componentParams={{ title: 'Create List' }} />
|
||||
<WrappedRoute path='/lists/:id/edit' exact page={ModalPage} component={ListEdit} content={children} componentParams={{ title: 'Edit List' }} />
|
||||
<WrappedRoute path='/list/:id' page={ListPage} component={ListTimeline} content={children} />
|
||||
|
||||
<WrappedRoute path='/notifications' exact page={NotificationsPage} component={Notifications} content={children} />
|
||||
@@ -162,7 +168,7 @@ class SwitchingArea extends PureComponent {
|
||||
<WrappedRoute path='/search/hashtags' exact page={SearchPage} component={Search} content={children} />
|
||||
<WrappedRoute path='/search/groups' exact page={SearchPage} component={Search} content={children} />
|
||||
|
||||
{/*
|
||||
{ /*
|
||||
<WrappedRoute path='/settings/account' exact page={SettingsPage} component={AccountSettings} content={children} />
|
||||
<WrappedRoute path='/settings/profile' exact page={SettingsPage} component={ProfileSettings} content={children} />
|
||||
<WrappedRoute path='/settings/domain_blocks' exact page={SettingsPage} component={DomainBlocks} content={children} />
|
||||
|
||||
@@ -55,11 +55,11 @@ export function GroupsCollection() {
|
||||
}
|
||||
|
||||
export function GroupCreate() {
|
||||
return import(/* webpackChunkName: "features/groups_create" */'../../group_create')
|
||||
return import(/* webpackChunkName: "features/group_create" */'../../group_create')
|
||||
}
|
||||
|
||||
export function GroupEdit() {
|
||||
return import(/* webpackChunkName: "features/groups/timeline" */'../../groups/edit')
|
||||
return import(/* webpackChunkName: "features/group_edit" */'../../group_edit')
|
||||
}
|
||||
|
||||
export function GroupMembers() {
|
||||
@@ -82,16 +82,16 @@ export function HomeTimeline() {
|
||||
return import(/* webpackChunkName: "features/home_timeline" */'../../home_timeline')
|
||||
}
|
||||
|
||||
export function ListAdder() {
|
||||
return import(/*webpackChunkName: "features/list_adder" */'../../list_adder')
|
||||
export function ListCreate() {
|
||||
return import(/* webpackChunkName: "features/list_create" */'../../list_create')
|
||||
}
|
||||
|
||||
export function ListsDirectory() {
|
||||
return import(/* webpackChunkName: "features/lists_directory" */'../../lists_directory')
|
||||
}
|
||||
|
||||
export function ListEditor() {
|
||||
return import(/* webpackChunkName: "features/list_editor" */'../../list_editor')
|
||||
export function ListEdit() {
|
||||
return import(/* webpackChunkName: "features/list_editor" */'../../list_edit')
|
||||
}
|
||||
|
||||
export function ListTimeline() {
|
||||
|
||||
Reference in New Issue
Block a user