Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4954a6b

Browse files
authored
feat: Initial workspaces page route + skeleton (#220)
This implements an initial route for the workspaces page at `/workspaces/{user}/{workspace}`, and an additional storybook entry:<img width="1723" alt="image" src="https://user-images.githubusercontent.com/88213859/153271281-801a5889-f60e-458c-809f-396a2d6385fa.png">Just the header is rendering right now. Will be adding the additional sections prototyped in#219 in subsequent PRsRelated to#67
1 parent6009c90 commit4954a6b

File tree

5 files changed

+191
-0
lines changed

5 files changed

+191
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import{Story}from"@storybook/react"
2+
importReactfrom"react"
3+
import{Workspace,WorkspaceProps}from"./Workspace"
4+
import{MockWorkspace}from"../../test_helpers"
5+
6+
exportdefault{
7+
title:"Workspace",
8+
component:Workspace,
9+
argTypes:{},
10+
}
11+
12+
constTemplate:Story<WorkspaceProps>=(args)=><Workspace{...args}/>
13+
14+
exportconstExample=Template.bind({})
15+
Example.args={
16+
workspace:MockWorkspace,
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import{render,screen}from"@testing-library/react"
2+
importReactfrom"react"
3+
import{Workspace}from"./Workspace"
4+
import{MockWorkspace}from"../../test_helpers"
5+
6+
describe("Workspace",()=>{
7+
it("renders",async()=>{
8+
// When
9+
render(<Workspaceworkspace={MockWorkspace}/>)
10+
11+
// Then
12+
constelement=awaitscreen.findByText(MockWorkspace.name)
13+
expect(element).toBeDefined()
14+
})
15+
})
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
importBoxfrom"@material-ui/core/Box"
2+
importPaperfrom"@material-ui/core/Paper"
3+
importTypographyfrom"@material-ui/core/Typography"
4+
import{makeStyles}from"@material-ui/core/styles"
5+
importCloudCircleIconfrom"@material-ui/icons/CloudCircle"
6+
importLinkfrom"next/link"
7+
importReactfrom"react"
8+
9+
import*asAPIfrom"../../api"
10+
11+
exportinterfaceWorkspaceProps{
12+
workspace:API.Workspace
13+
}
14+
15+
namespaceConstants{
16+
exportconstTitleIconSize=48
17+
exportconstCardRadius=8
18+
exportconstCardPadding=20
19+
}
20+
21+
/**
22+
* Workspace is the top-level component for viewing an individual workspace
23+
*/
24+
exportconstWorkspace:React.FC<WorkspaceProps>=({ workspace})=>{
25+
conststyles=useStyles()
26+
27+
return(
28+
<divclassName={styles.root}>
29+
<WorkspaceHeaderworkspace={workspace}/>
30+
</div>
31+
)
32+
}
33+
34+
/**
35+
* Component for the header at the top of the workspace page
36+
*/
37+
exportconstWorkspaceHeader:React.FC<WorkspaceProps>=({ workspace})=>{
38+
conststyles=useStyles()
39+
40+
return(
41+
<Paperelevation={0}className={styles.section}>
42+
<divclassName={styles.horizontal}>
43+
<WorkspaceHeroIcon/>
44+
<divclassName={styles.vertical}>
45+
<Typographyvariant="h4">{workspace.name}</Typography>
46+
<Typographyvariant="body2"color="textSecondary">
47+
<Linkhref="#"diff-0b3aad4d6efb78b7eb0b282b4538fa011688351bec376a585628de21a1623ad2-empty-48-0" data-selected="false" role="gridcell" tabindex="-1" valign="top">
48+
</Typography>
49+
</div>
50+
</div>
51+
</Paper>
52+
)
53+
}
54+
55+
/**
56+
* Component to render the 'Hero Icon' in the header of a workspace
57+
*/
58+
exportconstWorkspaceHeroIcon:React.FC=()=>{
59+
return(
60+
<Boxmr="1em">
61+
<CloudCircleIconwidth={Constants.TitleIconSize}height={Constants.TitleIconSize}/>
62+
</Box>
63+
)
64+
}
65+
66+
exportconstuseStyles=makeStyles((theme)=>{
67+
return{
68+
root:{
69+
display:"flex",
70+
flexDirection:"column",
71+
},
72+
horizontal:{
73+
display:"flex",
74+
flexDirection:"row",
75+
},
76+
vertical:{
77+
display:"flex",
78+
flexDirection:"column",
79+
},
80+
section:{
81+
border:`1px solid${theme.palette.divider}`,
82+
borderRadius:Constants.CardRadius,
83+
padding:Constants.CardPadding,
84+
},
85+
icon:{
86+
width:Constants.TitleIconSize,
87+
height:Constants.TitleIconSize,
88+
},
89+
}
90+
})

‎site/components/Workspace/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export*from"./Workspace"
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
importReactfrom"react"
2+
importuseSWRfrom"swr"
3+
import{makeStyles}from"@material-ui/core/styles"
4+
import{useRouter}from"next/router"
5+
import{Navbar}from"../../../components/Navbar"
6+
import{Footer}from"../../../components/Page"
7+
import{useUser}from"../../../contexts/UserContext"
8+
import{firstOrItem}from"../../../util/array"
9+
import{ErrorSummary}from"../../../components/ErrorSummary"
10+
import{FullScreenLoader}from"../../../components/Loader/FullScreenLoader"
11+
import{Workspace}from"../../../components/Workspace"
12+
13+
import*asAPIfrom"../../../api"
14+
15+
constWorkspacesPage:React.FC=()=>{
16+
conststyles=useStyles()
17+
constrouter=useRouter()
18+
const{ me, signOut}=useUser(true)
19+
20+
const{user:userQueryParam,workspace:workspaceQueryParam}=router.query
21+
22+
const{data:workspace,error:workspaceError}=useSWR<API.Workspace,Error>(()=>{
23+
constuserParam=firstOrItem(userQueryParam,null)
24+
constworkspaceParam=firstOrItem(workspaceQueryParam,null)
25+
26+
// TODO(Bryan): Getting non-personal users isn't supported yet in the backend.
27+
// So if the user is the same as 'me', use 'me' as the parameter
28+
constnormalizedUserParam=me&&userParam===me.id ?"me" :userParam
29+
30+
// The SWR API expects us to 'throw' if the query isn't ready yet, so these casts to `any` are OK
31+
// because the API expects exceptions.
32+
return`/api/v2/workspaces/${(normalizedUserParamasany).toString()}/${(workspaceParamasany).toString()}`
33+
})
34+
35+
if(workspaceError){
36+
return<ErrorSummaryerror={workspaceError}/>
37+
}
38+
39+
if(!me||!workspace){
40+
return<FullScreenLoader/>
41+
}
42+
43+
return(
44+
<divclassName={styles.root}>
45+
<Navbaruser={me}onSignOut={signOut}/>
46+
47+
<divclassName={styles.inner}>
48+
<Workspaceworkspace={workspace}/>
49+
</div>
50+
51+
<Footer/>
52+
</div>
53+
)
54+
}
55+
56+
constuseStyles=makeStyles(()=>({
57+
root:{
58+
display:"flex",
59+
flexDirection:"column",
60+
},
61+
inner:{
62+
maxWidth:"1380px",
63+
margin:"1em auto",
64+
width:"100%",
65+
},
66+
}))
67+
68+
exportdefaultWorkspacesPage

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp