mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-10 02:54:15 +00:00
use PostsFeed
component
This commit is contained in:
parent
4da1a0b506
commit
81167c455e
@ -3,67 +3,15 @@ import * as antd from "antd"
|
|||||||
import { Translation } from "react-i18next"
|
import { Translation } from "react-i18next"
|
||||||
|
|
||||||
import { Icons } from "components/Icons"
|
import { Icons } from "components/Icons"
|
||||||
import { Skeleton, ActionsBar, AdminTools } from "components"
|
import { Skeleton, PostsFeed } from "components"
|
||||||
import { Session, User } from "models"
|
import { Session, User } from "models"
|
||||||
|
|
||||||
import { SessionsView, StatisticsView } from "./components"
|
|
||||||
|
|
||||||
import "./index.less"
|
import "./index.less"
|
||||||
|
|
||||||
const SelfViewComponents = {
|
|
||||||
sessionsView: SessionsView,
|
|
||||||
statisticsView: StatisticsView,
|
|
||||||
}
|
|
||||||
|
|
||||||
const SelfViewTabDecorators = {
|
|
||||||
sessionsView: (
|
|
||||||
<div>
|
|
||||||
<Icons.Key /> Sessions
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
statisticsView: (
|
|
||||||
<div>
|
|
||||||
<Icons.PieChart /> Statistics
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
class SelfView extends React.Component {
|
|
||||||
renderComponents = () => {
|
|
||||||
const renderTagDecorator = (key) => {
|
|
||||||
if (typeof this.props.decorators[key] !== "undefined") {
|
|
||||||
return this.props.decorators[key]
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.keys(this.props.components).map((key, index) => {
|
|
||||||
const Component = this.props.components[key]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<antd.Tabs.TabPane tab={renderTagDecorator(key)} key={index}>
|
|
||||||
<div key={key}>
|
|
||||||
<Component {...this.props.componentProps} />
|
|
||||||
</div>
|
|
||||||
</antd.Tabs.TabPane>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<antd.Tabs defaultActiveKey="0" centered>
|
|
||||||
{this.renderComponents()}
|
|
||||||
</antd.Tabs>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Account extends React.Component {
|
export default class Account extends React.Component {
|
||||||
static bindApp = ["userController", "sessionController"]
|
static bindApp = ["userController", "sessionController"]
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
hasManager: false,
|
|
||||||
isSelf: false,
|
isSelf: false,
|
||||||
user: null,
|
user: null,
|
||||||
sessions: null
|
sessions: null
|
||||||
@ -88,28 +36,11 @@ export default class Account extends React.Component {
|
|||||||
state.user = await this.props.contexts.app.userController.getData({ username: requestedUser })
|
state.user = await this.props.contexts.app.userController.getData({ username: requestedUser })
|
||||||
}
|
}
|
||||||
|
|
||||||
state.hasManager = await User.hasRole("manager")
|
|
||||||
state.hasAdmin = await User.hasRole("admin")
|
state.hasAdmin = await User.hasRole("admin")
|
||||||
|
|
||||||
this.setState(state)
|
this.setState(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSignOutAll = () => {
|
|
||||||
return this.props.contexts.app.sessionController.destroyAllSessions()
|
|
||||||
}
|
|
||||||
|
|
||||||
openUserEdit = async () => {
|
|
||||||
const result = await AdminTools.open.dataManager(this.state.user)
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
this.setState({ user: result })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
openRolesManager = async () => {
|
|
||||||
await AdminTools.open.rolesManager(this.state.user._id)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const user = this.state.user
|
const user = this.state.user
|
||||||
|
|
||||||
@ -136,47 +67,19 @@ export default class Account extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="extension">
|
<div className="extension">
|
||||||
<div className="rolesList">
|
<div className="badgesList">
|
||||||
{user.roles.map((role, index) => {
|
{user.badges.map((role, index) => {
|
||||||
return <antd.Tag>{role}</antd.Tag>
|
return <antd.Tag>{role}</antd.Tag>
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="posts">
|
||||||
{(this.state.isSelf || this.state.hasManager) && <ActionsBar spaced padding="8px">
|
<PostsFeed
|
||||||
<antd.Button
|
fromUserId={user._id}
|
||||||
icon={<Icons.Edit />}
|
/>
|
||||||
shape="round"
|
</div>
|
||||||
onClick={this.openUserEdit}
|
|
||||||
>
|
|
||||||
<Translation>
|
|
||||||
{(t) => <>{t("Edit")}</>}
|
|
||||||
</Translation>
|
|
||||||
</antd.Button>
|
|
||||||
{this.state.hasAdmin && <antd.Button
|
|
||||||
icon={<Icons.Link />}
|
|
||||||
shape="round"
|
|
||||||
onClick={this.openRolesManager}
|
|
||||||
>
|
|
||||||
<Translation>
|
|
||||||
{(t) => <>{t("Manage roles")}</>}
|
|
||||||
</Translation>
|
|
||||||
</antd.Button>}
|
|
||||||
</ActionsBar>}
|
|
||||||
|
|
||||||
{this.state.isSelf && (
|
|
||||||
<SelfView
|
|
||||||
components={SelfViewComponents}
|
|
||||||
decorators={SelfViewTabDecorators}
|
|
||||||
componentProps={{
|
|
||||||
sessions: this.state.sessions,
|
|
||||||
user: this.state.user,
|
|
||||||
handleSignOutAll: this.handleSignOutAll,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,67 +1,76 @@
|
|||||||
@borderColor: #33333396;
|
@borderColor : #dddddd;
|
||||||
@borderRadius: 12px;
|
@borderRadius: 12px;
|
||||||
|
|
||||||
.account_wrapper {
|
.account_wrapper {
|
||||||
.card {
|
.card {
|
||||||
display: flex;
|
display : flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
color: var(--background-color-contrast);
|
color : var(--background-color-contrast);
|
||||||
|
|
||||||
h1,h2,h3,h4,h5,h6,span {
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6,
|
||||||
|
span {
|
||||||
color: var(--background-color-contrast);
|
color: var(--background-color-contrast);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
position: relative;
|
position : relative;
|
||||||
display: inline-flex;
|
display : inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
z-index: 15;
|
z-index: 15;
|
||||||
width: 100%;
|
width : 100%;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
|
||||||
font-family: "Roboto Mono", monospace;
|
font-family: "Roboto Mono", monospace;
|
||||||
//color: #333;
|
|
||||||
color: var(--background-color-contrast);
|
color : var(--background-color-contrast);
|
||||||
|
border : 1px solid var(--border-color);
|
||||||
border: 1px solid @borderColor;
|
|
||||||
border-radius: @borderRadius;
|
border-radius: @borderRadius;
|
||||||
|
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 70px;
|
width : 70px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
margin: 0;
|
margin : 0;
|
||||||
font-size: 35px;
|
font-size: 35px;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension {
|
.extension {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-flex;
|
display : inline-flex;
|
||||||
|
|
||||||
top: -10px;
|
top : -10px;
|
||||||
width: 100%;
|
width : 100%;
|
||||||
padding: 19px 10px 10px 10px;
|
padding: 19px 10px 10px 10px;
|
||||||
|
|
||||||
border-top: 0;
|
border-top : 0;
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
|
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-color: transparent @borderColor @borderColor @borderColor;
|
|
||||||
|
border-color : var(--border-color);
|
||||||
|
border-top-color: transparent;
|
||||||
|
|
||||||
border-radius: 0 0 @borderRadius @borderRadius;
|
border-radius: 0 0 @borderRadius @borderRadius;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
>div {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,88 +1,15 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import * as antd from "antd"
|
import { PostCreator, PostsFeed } from "components"
|
||||||
import { PostCard, PostCreator } from "components"
|
|
||||||
import { InfiniteScroll } from "antd-mobile"
|
|
||||||
|
|
||||||
import "./index.less"
|
import "./index.less"
|
||||||
|
|
||||||
export default class PostsExplorer extends React.Component {
|
export default class PostsExplorer extends React.Component {
|
||||||
state = {
|
|
||||||
loading: true,
|
|
||||||
skipStep: 0,
|
|
||||||
lastLength: 0,
|
|
||||||
posts: [],
|
|
||||||
}
|
|
||||||
|
|
||||||
api = window.app.request
|
|
||||||
|
|
||||||
componentDidMount = async () => {
|
|
||||||
this.toogleLoading(true)
|
|
||||||
|
|
||||||
await this.fetchPosts()
|
|
||||||
|
|
||||||
window.app.ws.listen(`new.post`, (data) => {
|
|
||||||
this.addPost(data)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.toogleLoading(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
toogleLoading = (to) => {
|
|
||||||
this.setState({ loading: to ?? !this.state.loading })
|
|
||||||
}
|
|
||||||
|
|
||||||
addPost = (post) => {
|
|
||||||
this.setState({
|
|
||||||
posts: [post, ...this.state.posts],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchPosts = async () => {
|
|
||||||
const posts = await this.api.get.feed(undefined, {
|
|
||||||
feedSkip: this.state.skipStep,
|
|
||||||
}).catch(error => {
|
|
||||||
console.error(error)
|
|
||||||
antd.message.error(error)
|
|
||||||
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
|
|
||||||
if (posts) {
|
|
||||||
console.log(posts)
|
|
||||||
this.setState({ posts: [...posts, ...this.state.posts,], lastLength: posts.length })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hasMore = () => {
|
|
||||||
return this.state.posts.length < this.state.lastLength
|
|
||||||
}
|
|
||||||
|
|
||||||
loadMore = async () => {
|
|
||||||
await this.setState({ skipStep: this.state.skipStep + 1 })
|
|
||||||
await this.fetchPosts()
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.loading) {
|
|
||||||
return <antd.Skeleton active />
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className="explore">
|
return <div className="explore">
|
||||||
<div className="wrapper">
|
<div className="header">
|
||||||
<div className="header">
|
<PostCreator />
|
||||||
<PostCreator />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
|
||||||
this.state.posts.map(post => {
|
|
||||||
return <PostCard data={post} />
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
<InfiniteScroll loadMore={this.loadMore} hasMore={this.hasMore} >
|
|
||||||
<div>Loading more...</div>
|
|
||||||
</InfiniteScroll>
|
|
||||||
</div>
|
</div>
|
||||||
|
<PostsFeed />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.wrapper {
|
.header {
|
||||||
display : flex;
|
display : flex;
|
||||||
flex-direction : column;
|
flex-direction : column;
|
||||||
align-items : center;
|
align-items : center;
|
||||||
@ -14,18 +14,9 @@
|
|||||||
|
|
||||||
width : 100%;
|
width : 100%;
|
||||||
max-width: 40vw;
|
max-width: 40vw;
|
||||||
|
}
|
||||||
|
|
||||||
.header {
|
>div {
|
||||||
display : flex;
|
margin-bottom: 15px;
|
||||||
flex-direction : column;
|
|
||||||
align-items : center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
>div {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user