Skip to content
This repository has been archived by the owner on Nov 28, 2024. It is now read-only.

Commit

Permalink
Merge pull request #19 from graasp/15/home
Browse files Browse the repository at this point in the history
15/home
  • Loading branch information
pyphilia authored Jul 28, 2021
2 parents bc95e77 + a47c26a commit 46e886d
Show file tree
Hide file tree
Showing 9 changed files with 690 additions and 598 deletions.
15 changes: 9 additions & 6 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
name: Cypress tests
name: cypress tests
on: [push]
jobs:
cypress-run:
runs-on: ubuntu-latest
steps:
- name: Checkout
- name: checkout
uses: actions/checkout@v2

- name: Cypress run
- name: install
# network-concurrency 1 is necessary to avoid errors when using github packages
run: yarn cache clean && rm yarn.lock && yarn install --network-concurrency 1

- name: cypress run
uses: cypress-io/github-action@v2
env:
REACT_APP_API_HOST: ${{ secrets.REACT_APP_API_HOST }}
REACT_APP_NODE_ENV: test
with:
# network-concurrency 1 is necessary to avoid errors when using github packages
install-command: yarn install --network-concurrency 1
install: false
config: baseUrl=http://localhost:3000
start: yarn start:ci
wait-on: 'http://localhost:3000'
Expand All @@ -23,5 +26,5 @@ jobs:
headless: true
quiet: true

- name: Coverage Report
- name: coverage report
run: npx nyc report --reporter=text-summary
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@graasp/query-client": "git://github.com/graasp/graasp-query-client.git",
"@graasp/ui": "git://github.com/graasp/graasp-ui.git",
"@graasp/ui": "git://github.com/graasp/graasp-ui.git#master",
"@material-ui/core": "4.11.4",
"@material-ui/icons": "4.11.2",
"@material-ui/lab": "4.0.0-alpha.58",
Expand Down Expand Up @@ -68,11 +68,11 @@
]
},
"devDependencies": {
"@graasp/websockets": "git://github.com/graasp/graasp-websockets.git",
"@commitlint/cli": "12.1.1",
"@commitlint/config-conventional": "12.1.1",
"@cypress/code-coverage": "3.9.6",
"@cypress/instrument-cra": "1.4.0",
"@graasp/websockets": "git://github.com/graasp/graasp-websockets.git",
"@testing-library/jest-dom": "5.11.6",
"@testing-library/react": "11.2.2",
"@testing-library/user-event": "13.1.8",
Expand All @@ -86,7 +86,7 @@
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-react": "7.23.2",
"husky": "6.0.0",
"husky": "7.0.1",
"npm-run-all": "4.1.5",
"prettier": "2.3.0",
"pretty-quick": "3.1.0",
Expand Down
3 changes: 2 additions & 1 deletion src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import {
} from 'react-router-dom';
import { buildMainPath, HOME_PATH } from '../config/paths';
import MainScreen from './main/MainScreen';
import Home from './main/Home';

export const App = () => (
<Router>
<Switch>
<Route path={buildMainPath()} exact component={MainScreen} />
<Route path={buildMainPath({ id: null })} exact component={MainScreen} />
<Route path={HOME_PATH} exact component={MainScreen} />
<Route path={HOME_PATH} exact component={Home} />
<Redirect to={HOME_PATH} />
</Switch>
</Router>
Expand Down
64 changes: 64 additions & 0 deletions src/components/common/ItemCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import { useHistory } from 'react-router';
import { ItemIcon } from '@graasp/ui';
import PropTypes from 'prop-types';
import CardContent from '@material-ui/core/CardContent';
import truncate from 'lodash.truncate';
import Typography from '@material-ui/core/Typography';
import CardActionArea from '@material-ui/core/CardActionArea';
import { buildMainPath } from '../../config/paths';
import { ITEM_CARD_MAX_LENGTH } from '../../config/constants';

const useStyles = makeStyles((theme) => ({
bullet: {
display: 'inline-block',
margin: '0 2px',
transform: 'scale(0.8)',
},
title: {
display: 'flex',
alignItems: 'center',
},
iconClass: {
marginRight: theme.spacing(1),
},
}));

const SimpleCard = ({ item }) => {
const classes = useStyles();
const { push } = useHistory();

const onClick = () => {
push(buildMainPath({ rootId: item.id, id: null }));
};
return (
<Card className={classes.root}>
<CardActionArea onClick={onClick}>
<CardContent>
<Typography variant="h5" component="h2" className={classes.title}>
<ItemIcon
type={item.type}
extra={item.extra}
name={item.name}
iconClass={classes.iconClass}
/>
{truncate(item.name, { length: ITEM_CARD_MAX_LENGTH })}
</Typography>
</CardContent>
</CardActionArea>
</Card>
);
};

SimpleCard.propTypes = {
item: PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
extra: PropTypes.shape({}).isRequired,
}).isRequired,
};

export default SimpleCard;
179 changes: 179 additions & 0 deletions src/components/main/Home.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import {
Main,
MainMenu as GraaspMainMenu,
DynamicTreeView,
Loader,
} from '@graasp/ui';
import { Divider, Grid, Container } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';
import { useHistory } from 'react-router';
import HeaderRightContent from './HeaderRightContent';
import { hooks } from '../../config/queryClient';
import { buildTreeItemClass } from '../../config/selectors';
import ItemCard from '../common/ItemCard';
import { buildMainPath } from '../../config/paths';

const { useItem, useOwnItems, useChildren, useSharedItems } = hooks;

const useStyles = makeStyles((theme) => ({
divider: {
margin: theme.spacing(2, 0),
},
}));

const Home = () => {
const { t } = useTranslation();
const classes = useStyles();
const { push } = useHistory();

const { data: ownItems, isLoading: isLoadingOwnItems } = useOwnItems();
const { data: sharedItems, isLoading: isLoadingSharedItems } =
useSharedItems();

const renderSharedItems = () => {
if (isLoadingSharedItems) {
return <Loader />;
}

if (!sharedItems?.size) {
return null;
}

return (
<>
<Divider className={classes.divider} />
<Typography variant="h4">{t('Shared Items')}</Typography>
<Grid container spacing={3} justify="center">
{sharedItems.map((i) => (
<Grid item lg={3} md={4} sm={6}>
<ItemCard item={i} />
</Grid>
))}
</Grid>
</>
);
};

const renderOwnItems = () => {
if (isLoadingOwnItems) {
return <Loader />;
}

if (!ownItems?.size) {
return null;
}

return (
<>
<Typography variant="h4">{t('My Items')}</Typography>
<Grid container spacing={3} justify="center">
{ownItems.map((i) => (
<Grid item lg={3} md={4} sm={6}>
<ItemCard item={i} />
</Grid>
))}
</Grid>
</>
);
};

const renderContent = () => (
<Container>
{renderOwnItems()}
{renderSharedItems()}
</Container>
);

const renderOwnItemsMenu = () => {
const rootOwnId = 'own';

if (isLoadingOwnItems) {
return <Loader />;
}

if (!ownItems?.size) {
return null;
}

return (
<GraaspMainMenu>
<DynamicTreeView
rootLabel={t('My Items')}
rootId={rootOwnId}
useItem={useItem}
buildTreeItemClass={(nodeId) => buildTreeItemClass(nodeId)}
initialExpendedItems={[]}
showCheckbox={false}
showItemFilter={() => true}
onTreeItemSelect={(payload) => {
if (payload !== rootOwnId) {
push(buildMainPath({ rootId: payload, id: null }));
}
}}
useChildren={useChildren}
shouldFetchChildrenForItem={() => false}
isTreeItemDisabled={() => false}
items={ownItems}
/>
</GraaspMainMenu>
);
};

const renderSharedItemsMenu = () => {
const rootSharedId = 'shared';

if (isLoadingSharedItems) {
return <Loader />;
}

if (!sharedItems?.size) {
return null;
}

return (
<GraaspMainMenu>
<DynamicTreeView
rootLabel={t('Shared Items')}
rootId={rootSharedId}
useItem={useItem}
buildTreeItemClass={(nodeId) => buildTreeItemClass(nodeId)}
initialExpendedItems={[]}
showCheckbox={false}
showItemFilter={() => true}
onTreeItemSelect={(payload) => {
if (payload !== rootSharedId) {
push(buildMainPath({ rootId: payload, id: null }));
}
}}
useChildren={useChildren}
shouldFetchChildrenForItem={() => false}
isTreeItemDisabled={() => false}
items={sharedItems}
/>
</GraaspMainMenu>
);
};

const sidebar = (
<>
{renderOwnItemsMenu()}
{renderSharedItemsMenu()}
</>
);

return (
<Main
open
sidebar={sidebar}
headerLeftContent={t('Graasp Perform')}
headerRightContent={<HeaderRightContent />}
>
{renderContent()}
</Main>
);
};

export default Home;
2 changes: 2 additions & 0 deletions src/config/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,5 @@ export const SCREEN_MAX_HEIGHT = window.innerHeight * 0.8;

export const buildGraaspComposeItemRoute = (id) =>
`${GRAASP_COMPOSE_HOST}/items/${id}`;

export const ITEM_CARD_MAX_LENGTH = 18;
7 changes: 6 additions & 1 deletion src/langs/en.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"translations": {}
"translations": {
"Graasp Perform": "Graasp Perform",
"My Items": "My Items",
"Shared Items": "Shared Items",
"You are not signed in.": "You are not signed in."
}
}
7 changes: 6 additions & 1 deletion src/langs/fr.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"translations": {}
"translations": {
"Graasp Perform": "Graasp Perform",
"My Items": "Mes Eléments",
"Shared Items": "Eléments Partagés",
"You are not signed in.": "Vous n'êtes pas connecté."
}
}
Loading

0 comments on commit 46e886d

Please sign in to comment.