diff --git a/packages/app/src/app/components/SandboxList/SandboxList.tsx b/packages/app/src/app/components/SandboxList/SandboxList.tsx index d3e44b19c93..4ed53eda179 100644 --- a/packages/app/src/app/components/SandboxList/SandboxList.tsx +++ b/packages/app/src/app/components/SandboxList/SandboxList.tsx @@ -23,7 +23,7 @@ import { interface ISandboxListProps { sandboxes: SmallSandbox[]; isCurrentUser: boolean; - onDelete: () => void; + onDelete: (id: string) => void; } export const SandboxList: React.FC = ({ diff --git a/packages/app/src/app/pages/Profile/Sandboxes/elements.js b/packages/app/src/app/pages/Profile/Sandboxes/NoSandboxes.tsx similarity index 52% rename from packages/app/src/app/pages/Profile/Sandboxes/elements.js rename to packages/app/src/app/pages/Profile/Sandboxes/NoSandboxes.tsx index 5e24bc59f88..18056cce410 100644 --- a/packages/app/src/app/pages/Profile/Sandboxes/elements.js +++ b/packages/app/src/app/pages/Profile/Sandboxes/NoSandboxes.tsx @@ -1,35 +1,13 @@ -import * as React from 'react'; -import styled from 'styled-components'; - +import React from 'react'; import Centered from '@codesandbox/common/lib/components/flex/Centered'; import Margin from '@codesandbox/common/lib/components/spacing/Margin'; +import { ErrorTitle } from './elements'; -export const Navigation = styled.div` - width: 100%; - display: flex; - align-items: center; - justify-content: center; - - padding-bottom: 2rem; -`; - -export const Notice = styled.div` - color: rgba(255, 255, 255, 0.5); - padding: 2rem 0; - padding-bottom: 0; - - margin-bottom: 2rem; -`; - -const ErrorTitle = styled.div` - font-size: 1.25rem; - color: ${props => - props.theme.light ? 'rgba(0, 0, 0, 0.7)' : 'rgba(255, 255, 255, 0.7)'}; -`; const prefix = { currentSandboxes: ["You don't have", "This user doesn't have"], currentLikedSandboxes: ["You haven't liked", "This user didn't like"], }; + export const NoSandboxes = ({ source, isCurrentUser }) => ( diff --git a/packages/app/src/app/pages/Profile/Sandboxes/Sandboxes.tsx b/packages/app/src/app/pages/Profile/Sandboxes/Sandboxes.tsx new file mode 100644 index 00000000000..6c0b8e457b0 --- /dev/null +++ b/packages/app/src/app/pages/Profile/Sandboxes/Sandboxes.tsx @@ -0,0 +1,143 @@ +import React, { useEffect, useCallback } from 'react'; +import { Link } from 'react-router-dom'; +import { dashboardUrl } from '@codesandbox/common/lib/utils/url-generator'; +import { useOvermind } from 'app/overmind'; +import { SandboxList } from 'app/components/SandboxList'; +import { NoSandboxes } from './NoSandboxes'; +import { Navigation, NavButton, Notice } from './elements'; + +const PER_PAGE_COUNT = 15; + +interface ISandboxesProps { + source: string; + page?: number; + baseUrl: string; +} + +export const Sandboxes: React.FC = ({ + source, + page = 1, + baseUrl, +}) => { + const { + state: { profile }, + actions: { + profile: { + sandboxesPageChanged, + likedSandboxesPageChanged, + deleteSandboxClicked, + }, + }, + } = useOvermind(); + const { isProfileCurrentUser, isLoadingSandboxes } = profile; + const sandboxes = profile[source]; + + const sandboxesPageChangedCallback = useCallback(sandboxesPageChanged, [ + page, + ]); + + const likedSandboxesPageChangedCallback = useCallback( + likedSandboxesPageChanged, + [page] + ); + + useEffect(() => { + const fetch = (force = false) => { + if (isLoadingSandboxes) { + return; + } + + if (force || !sandboxes || !getPage(sandboxes, page)) { + switch (source) { + case 'currentSandboxes': + sandboxesPageChangedCallback({ page, force }); + break; + case 'currentLikedSandboxes': + likedSandboxesPageChangedCallback({ page }); + break; + default: + } + } + }; + fetch(); + }, [ + page, + source, + isLoadingSandboxes, + sandboxes, + sandboxesPageChangedCallback, + likedSandboxesPageChangedCallback, + ]); + + const getPage = (sourcePage: any, pageNumber: number) => { + if (!sourcePage) { + return undefined; + } + return sourcePage.get ? sourcePage.get(pageNumber) : sourcePage[pageNumber]; + }; + + const getSandboxesByPage = (allSandboxes: any, pageNumber: number) => + allSandboxes.get ? allSandboxes.get(pageNumber) : allSandboxes[pageNumber]; + + // Get Last Page + const getLastPage = () => { + if (source === 'currentSandboxes') { + const { sandboxCount } = profile.current; + + return Math.ceil(sandboxCount / PER_PAGE_COUNT); + } + + const { givenLikeCount } = profile.current; + + return Math.ceil(givenLikeCount / PER_PAGE_COUNT); + }; + + // Delete Sandbox + const deleteSandbox = (id: string) => { + deleteSandboxClicked({ id }); + }; + + if ( + isLoadingSandboxes || + !sandboxes || + !getSandboxesByPage(sandboxes, page) + ) { + return
; + } + + const sandboxesPage = getSandboxesByPage(sandboxes, page); + + if (sandboxesPage.length === 0) + return ; + + return ( +
+ {isProfileCurrentUser && ( + + You + {"'"} + re viewing your own profile, so you can see your private and unlisted + sandboxes. Others can + {"'"} + t. To manage your sandboxes you can go to your dashboard{' '} + here. + + )} + + +
+ {page > 1 && ( + {'<'} + )} + {getLastPage() !== page && ( + {'>'} + )} +
+
+
+ ); +}; diff --git a/packages/app/src/app/pages/Profile/Sandboxes/elements.ts b/packages/app/src/app/pages/Profile/Sandboxes/elements.ts new file mode 100644 index 00000000000..989f176c8a6 --- /dev/null +++ b/packages/app/src/app/pages/Profile/Sandboxes/elements.ts @@ -0,0 +1,32 @@ +import styled, { css } from 'styled-components'; +import { Button } from '@codesandbox/common/lib/components/Button'; + +export const Navigation = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 100%; + padding-bottom: 2rem; +`; + +export const NavButton = styled(Button).attrs({ + small: true, +})` + margin: 0 0.5rem; +`; + +export const Notice = styled.div` + padding: 2rem 0; + padding-bottom: 0; + margin-bottom: 2rem; + color: rgba(255, 255, 255, 0.5); +`; + +export const ErrorTitle = styled.div` + ${({ theme }) => css` + color: ${theme.light + ? css`rgba(0, 0, 0, 0.7)` + : css`rgba(255, 255, 255, 0.7)`}; + font-size: 1.25rem; + `} +`; diff --git a/packages/app/src/app/pages/Profile/Sandboxes/index.js b/packages/app/src/app/pages/Profile/Sandboxes/index.js deleted file mode 100644 index e49197ec6e6..00000000000 --- a/packages/app/src/app/pages/Profile/Sandboxes/index.js +++ /dev/null @@ -1,146 +0,0 @@ -import * as React from 'react'; -import { Link } from 'react-router-dom'; -import { Button } from '@codesandbox/common/lib/components/Button'; -import { dashboardUrl } from '@codesandbox/common/lib/utils/url-generator'; -import { inject, observer } from 'app/componentConnectors'; -import { SandboxList } from 'app/components/SandboxList'; -import { Navigation, Notice, NoSandboxes } from './elements'; - -const PER_PAGE_COUNT = 15; - -class Sandboxes extends React.Component { - static defaultProps = { - page: 1, - }; - - getPage(source, page) { - if (!source) { - return undefined; - } - return source.get ? source.get(page) : source[page]; - } - - fetch(force = false) { - const { signals, source, store, page } = this.props; - - if (store.profile.isLoadingSandboxes) { - return; - } - - if ( - force || - !store.profile[source] || - !this.getPage(store.profile[source], page) - ) { - switch (source) { - case 'currentSandboxes': - signals.profile.sandboxesPageChanged({ page }); - break; - case 'currentLikedSandboxes': - signals.profile.likedSandboxesPageChanged({ page }); - break; - default: - } - } - } - - componentDidMount() { - this.fetch(); - } - - componentDidUpdate(prevProps) { - if ( - prevProps.page !== this.props.page || - prevProps.source !== this.props.source - ) { - this.fetch(); - } - } - - getSandboxesByPage(sandboxes, page) { - return sandboxes.get ? sandboxes.get(page) : sandboxes[page]; - } - - getLastPage = () => { - if (this.props.source === 'currentSandboxes') { - const { sandboxCount } = this.props.store.profile.current; - - return Math.ceil(sandboxCount / PER_PAGE_COUNT); - } - - const { givenLikeCount } = this.props.store.profile.current; - - return Math.ceil(givenLikeCount / PER_PAGE_COUNT); - }; - - deleteSandbox = id => { - this.props.signals.profile.deleteSandboxClicked({ id }); - }; - - render() { - const { store, source, page, baseUrl } = this.props; - const { isProfileCurrentUser } = store.profile; - const { isLoadingSandboxes } = store.profile; - const sandboxes = store.profile[source]; - - if ( - isLoadingSandboxes || - !sandboxes || - !this.getSandboxesByPage(sandboxes, page) - ) { - return
; - } - - const sandboxesPage = this.getSandboxesByPage(sandboxes, page); - - if (sandboxesPage.length === 0) - return ( - - ); - - return ( -
- {isProfileCurrentUser && ( - - You - {"'"} - re viewing your own profile, so you can see your private and - unlisted sandboxes. Others can - {"'"} - t. To manage your sandboxes you can go to your dashboard{' '} - here. - - )} - - -
- {page > 1 && ( - - )} - {this.getLastPage() !== page && ( - - )} -
-
-
- ); - } -} - -export default inject('signals', 'store')(observer(Sandboxes)); diff --git a/packages/app/src/app/pages/Profile/Sandboxes/index.ts b/packages/app/src/app/pages/Profile/Sandboxes/index.ts new file mode 100644 index 00000000000..ac8837a20a7 --- /dev/null +++ b/packages/app/src/app/pages/Profile/Sandboxes/index.ts @@ -0,0 +1 @@ +export { Sandboxes } from './Sandboxes'; diff --git a/packages/app/src/app/pages/Profile/index.js b/packages/app/src/app/pages/Profile/index.js index 3bc831a7ff3..f1064608b85 100644 --- a/packages/app/src/app/pages/Profile/index.js +++ b/packages/app/src/app/pages/Profile/index.js @@ -13,7 +13,7 @@ import { NotFound } from 'app/pages/common/NotFound'; import Header from './Header'; import Navigation from './Navigation'; import Showcase from './Showcase'; -import Sandboxes from './Sandboxes'; +import { Sandboxes } from './Sandboxes'; import { Container, Content } from './elements'; type Props = {