Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
scratch-www
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
scratch-www
Commits
4f54e14e
Unverified
Commit
4f54e14e
authored
May 03, 2021
by
Paul Kaplan
Committed by
GitHub
May 03, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5306 from paulkaplan/studio-info-styling
Studio info styling
parents
4f29d89b
8c104ed3
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
236 additions
and
149 deletions
+236
-149
src/redux/studio.js
src/redux/studio.js
+5
-6
src/views/studio/studio-description.jsx
src/views/studio/studio-description.jsx
+20
-22
src/views/studio/studio-follow.jsx
src/views/studio/studio-follow.jsx
+16
-18
src/views/studio/studio-image.jsx
src/views/studio/studio-image.jsx
+31
-34
src/views/studio/studio-info.jsx
src/views/studio/studio-info.jsx
+4
-12
src/views/studio/studio-tab-nav.jsx
src/views/studio/studio-tab-nav.jsx
+14
-13
src/views/studio/studio-title.jsx
src/views/studio/studio-title.jsx
+19
-20
src/views/studio/studio.jsx
src/views/studio/studio.jsx
+29
-24
src/views/studio/studio.scss
src/views/studio/studio.scss
+98
-0
No files found.
src/redux/studio.js
View file @
4f54e14e
...
@@ -13,7 +13,7 @@ const Status = keyMirror({
...
@@ -13,7 +13,7 @@ const Status = keyMirror({
});
});
const
getInitialState
=
()
=>
({
const
getInitialState
=
()
=>
({
infoStatus
:
Status
.
NOT_FETCHED
,
infoStatus
:
Status
.
FETCHING
,
title
:
''
,
title
:
''
,
description
:
''
,
description
:
''
,
openToAll
:
false
,
openToAll
:
false
,
...
@@ -38,12 +38,14 @@ const studioReducer = (state, action) => {
...
@@ -38,12 +38,14 @@ const studioReducer = (state, action) => {
case
'
SET_INFO
'
:
case
'
SET_INFO
'
:
return
{
return
{
...
state
,
...
state
,
...
action
.
info
...
action
.
info
,
infoStatus
:
Status
.
FETCHED
};
};
case
'
SET_ROLES
'
:
case
'
SET_ROLES
'
:
return
{
return
{
...
state
,
...
state
,
...
action
.
roles
...
action
.
roles
,
rolesStatus
:
Status
.
FETCHED
};
};
case
'
SET_FETCH_STATUS
'
:
case
'
SET_FETCH_STATUS
'
:
if
(
action
.
error
)
{
if
(
action
.
error
)
{
...
@@ -95,14 +97,12 @@ const selectIsFetchingRoles = state => state.studio.rolesStatus === Status.FETCH
...
@@ -95,14 +97,12 @@ const selectIsFetchingRoles = state => state.studio.rolesStatus === Status.FETCH
// Thunks
// Thunks
const
getInfo
=
()
=>
((
dispatch
,
getState
)
=>
{
const
getInfo
=
()
=>
((
dispatch
,
getState
)
=>
{
dispatch
(
setFetchStatus
(
'
infoStatus
'
,
Status
.
FETCHING
));
const
studioId
=
selectStudioId
(
getState
());
const
studioId
=
selectStudioId
(
getState
());
api
({
uri
:
`/studios/
${
studioId
}
`
},
(
err
,
body
,
res
)
=>
{
api
({
uri
:
`/studios/
${
studioId
}
`
},
(
err
,
body
,
res
)
=>
{
if
(
err
||
typeof
body
===
'
undefined
'
||
res
.
statusCode
!==
200
)
{
if
(
err
||
typeof
body
===
'
undefined
'
||
res
.
statusCode
!==
200
)
{
dispatch
(
setFetchStatus
(
'
infoStatus
'
,
Status
.
ERROR
,
err
));
dispatch
(
setFetchStatus
(
'
infoStatus
'
,
Status
.
ERROR
,
err
));
return
;
return
;
}
}
dispatch
(
setFetchStatus
(
'
infoStatus
'
,
Status
.
FETCHED
));
dispatch
(
setInfo
({
dispatch
(
setInfo
({
title
:
body
.
title
,
title
:
body
.
title
,
description
:
body
.
description
,
description
:
body
.
description
,
...
@@ -130,7 +130,6 @@ const getRoles = () => ((dispatch, getState) => {
...
@@ -130,7 +130,6 @@ const getRoles = () => ((dispatch, getState) => {
dispatch
(
setFetchStatus
(
'
rolesStatus
'
,
Status
.
ERROR
,
err
));
dispatch
(
setFetchStatus
(
'
rolesStatus
'
,
Status
.
ERROR
,
err
));
return
;
return
;
}
}
dispatch
(
setFetchStatus
(
'
rolesStatus
'
,
Status
.
FETCHED
));
dispatch
(
setRoles
({
dispatch
(
setRoles
({
manager
:
body
.
manager
,
manager
:
body
.
manager
,
curator
:
body
.
curator
,
curator
:
body
.
curator
,
...
...
src/views/studio/studio-description.jsx
View file @
4f54e14e
...
@@ -8,31 +8,29 @@ import {selectCanEditInfo} from '../../redux/studio-permissions';
...
@@ -8,31 +8,29 @@ import {selectCanEditInfo} from '../../redux/studio-permissions';
import
{
import
{
mutateStudioDescription
,
selectIsMutatingDescription
,
selectDescriptionMutationError
mutateStudioDescription
,
selectIsMutatingDescription
,
selectDescriptionMutationError
}
from
'
../../redux/studio-mutations
'
;
}
from
'
../../redux/studio-mutations
'
;
import
classNames
from
'
classnames
'
;
const
StudioDescription
=
({
const
StudioDescription
=
({
descriptionError
,
isFetching
,
isMutating
,
description
,
canEditInfo
,
handleUpdate
descriptionError
,
isFetching
,
isMutating
,
description
,
canEditInfo
,
handleUpdate
})
=>
(
})
=>
{
<
div
>
const
fieldClassName
=
classNames
(
'
studio-description
'
,
{
<
h3
>
Description
</
h3
>
'
mod-fetching
'
:
isFetching
,
{
isFetching
?
(
'
mod-mutating
'
:
isMutating
<
h4
>
Fetching...
</
h4
>
});
)
:
(
canEditInfo
?
(
return
(
<
label
>
<
React
.
Fragment
>
<
textarea
<
textarea
rows=
"5"
rows=
"20"
cols=
"100"
className=
{
fieldClassName
}
disabled=
{
isMutating
}
disabled=
{
isMutating
||
!
canEditInfo
||
isFetching
}
defaultValue=
{
description
}
defaultValue=
{
description
}
onBlur=
{
e
=>
e
.
target
.
value
!==
description
&&
onBlur=
{
e
=>
e
.
target
.
value
!==
description
&&
handleUpdate
(
e
.
target
.
value
)
}
handleUpdate
(
e
.
target
.
value
)
}
/>
/>
{
descriptionError
&&
<
div
>
Error mutating description:
{
descriptionError
}
</
div
>
}
{
descriptionError
&&
<
div
>
Error mutating description:
{
descriptionError
}
</
div
>
}
</
label
>
</
React
.
Fragment
>
)
:
(
);
<
div
>
{
description
}
</
div
>
};
))
}
</
div
>
);
StudioDescription
.
propTypes
=
{
StudioDescription
.
propTypes
=
{
descriptionError
:
PropTypes
.
string
,
descriptionError
:
PropTypes
.
string
,
...
...
src/views/studio/studio-follow.jsx
View file @
4f54e14e
...
@@ -2,43 +2,42 @@
...
@@ -2,43 +2,42 @@
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
PropTypes
from
'
prop-types
'
;
import
{
connect
}
from
'
react-redux
'
;
import
{
connect
}
from
'
react-redux
'
;
import
{
selectIsFollowing
,
selectIsFetchingRoles
}
from
'
../../redux/studio
'
;
import
{
selectIsFollowing
}
from
'
../../redux/studio
'
;
import
{
selectCanFollowStudio
}
from
'
../../redux/studio-permissions
'
;
import
{
selectCanFollowStudio
}
from
'
../../redux/studio-permissions
'
;
import
{
import
{
mutateFollowingStudio
,
selectIsMutatingFollowing
,
selectFollowingMutationError
mutateFollowingStudio
,
selectIsMutatingFollowing
,
selectFollowingMutationError
}
from
'
../../redux/studio-mutations
'
;
}
from
'
../../redux/studio-mutations
'
;
import
classNames
from
'
classnames
'
;
const
StudioFollow
=
({
const
StudioFollow
=
({
canFollow
,
canFollow
,
isFetching
,
isFollowing
,
isFollowing
,
isMutating
,
isMutating
,
followingError
,
followingError
,
handleFollow
handleFollow
})
=>
(
})
=>
{
<
div
>
if
(
!
canFollow
)
return
null
;
<
h3
>
Following
</
h3
>
const
fieldClassName
=
classNames
(
'
button
'
,
{
<
div
>
'
mod-mutating
'
:
isMutating
});
return
(
<
React
.
Fragment
>
<
button
<
button
disabled=
{
isFetching
||
isMutating
||
!
canFollow
}
className=
{
fieldClassName
}
disabled=
{
isMutating
}
onClick=
{
()
=>
handleFollow
(
!
isFollowing
)
}
onClick=
{
()
=>
handleFollow
(
!
isFollowing
)
}
>
>
{
isFetching
?
(
{
isMutating
?
'
...
'
:
(
'
Fetching...
'
isFollowing
?
'
Unfollow Studio
'
:
'
Follow Studio
'
)
:
(
isFollowing
?
'
Unfollow
'
:
'
Follow
'
)
}
)
}
</
button
>
</
button
>
{
followingError
&&
<
div
>
Error mutating following:
{
followingError
}
</
div
>
}
{
followingError
&&
<
div
>
Error mutating following:
{
followingError
}
</
div
>
}
{
!
canFollow
&&
<
div
>
Must be logged in to follow
</
div
>
}
</
React
.
Fragment
>
</
div
>
);
</
div
>
};
);
StudioFollow
.
propTypes
=
{
StudioFollow
.
propTypes
=
{
canFollow
:
PropTypes
.
bool
,
canFollow
:
PropTypes
.
bool
,
isFetching
:
PropTypes
.
bool
,
isFollowing
:
PropTypes
.
bool
,
isFollowing
:
PropTypes
.
bool
,
isMutating
:
PropTypes
.
bool
,
isMutating
:
PropTypes
.
bool
,
followingError
:
PropTypes
.
string
,
followingError
:
PropTypes
.
string
,
...
@@ -48,7 +47,6 @@ StudioFollow.propTypes = {
...
@@ -48,7 +47,6 @@ StudioFollow.propTypes = {
export
default
connect
(
export
default
connect
(
state
=>
({
state
=>
({
canFollow
:
selectCanFollowStudio
(
state
),
canFollow
:
selectCanFollowStudio
(
state
),
isFetching
:
selectIsFetchingRoles
(
state
),
isMutating
:
selectIsMutatingFollowing
(
state
),
isMutating
:
selectIsMutatingFollowing
(
state
),
isFollowing
:
selectIsFollowing
(
state
),
isFollowing
:
selectIsFollowing
(
state
),
followingError
:
selectFollowingMutationError
(
state
)
followingError
:
selectFollowingMutationError
(
state
)
...
...
src/views/studio/studio-image.jsx
View file @
4f54e14e
...
@@ -8,43 +8,40 @@ import {selectCanEditInfo} from '../../redux/studio-permissions';
...
@@ -8,43 +8,40 @@ import {selectCanEditInfo} from '../../redux/studio-permissions';
import
{
import
{
mutateStudioImage
,
selectIsMutatingImage
,
selectImageMutationError
mutateStudioImage
,
selectIsMutatingImage
,
selectImageMutationError
}
from
'
../../redux/studio-mutations
'
;
}
from
'
../../redux/studio-mutations
'
;
import
Spinner
from
'
../../components/spinner/spinner.jsx
'
;
import
classNames
from
'
classnames
'
;
const
blankImage
=
'
data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
'
;
const
StudioImage
=
({
const
StudioImage
=
({
imageError
,
isFetching
,
isMutating
,
image
,
canEditInfo
,
handleUpdate
imageError
,
isFetching
,
isMutating
,
image
,
canEditInfo
,
handleUpdate
})
=>
(
})
=>
{
<
div
>
const
fieldClassName
=
classNames
(
'
studio-image
'
,
{
<
h3
>
Image
</
h3
>
'
mod-fetching
'
:
isFetching
,
{
isFetching
?
(
'
mod-mutating
'
:
isMutating
<
h4
>
Fetching...
</
h4
>
});
)
:
(
const
src
=
isMutating
?
blankImage
:
(
image
||
blankImage
);
<
div
>
return
(
<
div
style=
{
{
width
:
'
200px
'
,
height
:
'
150px
'
,
border
:
'
1px solid green
'
}
}
>
<
div
className=
{
fieldClassName
}
>
{
isMutating
?
<
img
<
Spinner
color=
"blue"
/>
:
style=
{
{
width
:
'
300px
'
,
height
:
'
225px
'
,
objectFit
:
'
cover
'
}
}
<
img
src=
{
src
}
style=
{
{
objectFit
:
'
contain
'
}
}
/>
src=
{
image
}
{
canEditInfo
&&
!
isFetching
&&
/>
}
<
React
.
Fragment
>
</
div
>
<
input
{
canEditInfo
&&
disabled=
{
isMutating
}
<
label
>
type=
"file"
<
input
accept=
"image/*"
disabled=
{
isMutating
}
onChange=
{
e
=>
{
type=
"file"
handleUpdate
(
e
.
target
);
accept=
"image/*"
e
.
target
.
value
=
''
;
onChange=
{
e
=>
{
}
}
handleUpdate
(
e
.
target
);
/>
e
.
target
.
value
=
''
;
{
imageError
&&
<
div
>
Error mutating image:
{
imageError
}
</
div
>
}
}
}
</
React
.
Fragment
>
/>
}
{
imageError
&&
<
div
>
Error mutating image:
{
imageError
}
</
div
>
}
</
div
>
</
label
>
);
}
};
</
div
>
)
}
</
div
>
);
StudioImage
.
propTypes
=
{
StudioImage
.
propTypes
=
{
imageError
:
PropTypes
.
string
,
imageError
:
PropTypes
.
string
,
...
...
src/views/studio/studio-info.jsx
View file @
4f54e14e
import
React
,
{
useEffect
}
from
'
react
'
;
import
React
,
{
useEffect
}
from
'
react
'
;
import
PropTypes
from
'
prop-types
'
;
import
PropTypes
from
'
prop-types
'
;
import
{
connect
}
from
'
react-redux
'
;
import
{
connect
}
from
'
react-redux
'
;
import
Debug
from
'
./debug.jsx
'
;
import
StudioDescription
from
'
./studio-description.jsx
'
;
import
StudioDescription
from
'
./studio-description.jsx
'
;
import
StudioFollow
from
'
./studio-follow.jsx
'
;
import
StudioFollow
from
'
./studio-follow.jsx
'
;
import
StudioTitle
from
'
./studio-title.jsx
'
;
import
StudioTitle
from
'
./studio-title.jsx
'
;
...
@@ -11,7 +10,7 @@ import {selectIsLoggedIn} from '../../redux/session';
...
@@ -11,7 +10,7 @@ import {selectIsLoggedIn} from '../../redux/session';
import
{
getInfo
,
getRoles
}
from
'
../../redux/studio
'
;
import
{
getInfo
,
getRoles
}
from
'
../../redux/studio
'
;
const
StudioInfo
=
({
const
StudioInfo
=
({
isLoggedIn
,
studio
,
onLoadInfo
,
onLoadRoles
isLoggedIn
,
onLoadInfo
,
onLoadRoles
})
=>
{
})
=>
{
useEffect
(()
=>
{
// Load studio info after first render
useEffect
(()
=>
{
// Load studio info after first render
onLoadInfo
();
onLoadInfo
();
...
@@ -22,30 +21,23 @@ const StudioInfo = ({
...
@@ -22,30 +21,23 @@ const StudioInfo = ({
},
[
isLoggedIn
]);
},
[
isLoggedIn
]);
return
(
return
(
<
div
>
<
React
.
Fragment
>
<
h2
>
Studio Info
</
h2
>
<
StudioTitle
/>
<
StudioTitle
/>
<
StudioDescription
/>
<
StudioFollow
/>
<
StudioFollow
/>
<
StudioImage
/>
<
StudioImage
/>
<
Debug
<
StudioDescription
/>
label=
"Studio Info"
</
React
.
Fragment
>
data=
{
studio
}
/>
</
div
>
);
);
};
};
StudioInfo
.
propTypes
=
{
StudioInfo
.
propTypes
=
{
isLoggedIn
:
PropTypes
.
bool
,
isLoggedIn
:
PropTypes
.
bool
,
studio
:
PropTypes
.
shape
({}),
// TODO remove, just for <Debug />
onLoadInfo
:
PropTypes
.
func
,
onLoadInfo
:
PropTypes
.
func
,
onLoadRoles
:
PropTypes
.
func
onLoadRoles
:
PropTypes
.
func
};
};
export
default
connect
(
export
default
connect
(
state
=>
({
state
=>
({
studio
:
state
.
studio
,
isLoggedIn
:
selectIsLoggedIn
(
state
)
isLoggedIn
:
selectIsLoggedIn
(
state
)
}),
}),
{
{
...
...
src/views/studio/studio-tab-nav.jsx
View file @
4f54e14e
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
useRouteMatch
,
NavLink
}
from
'
react-router-dom
'
;
import
{
useRouteMatch
,
NavLink
}
from
'
react-router-dom
'
;
import
SubNavigation
from
'
../../components/subnavigation/subnavigation.jsx
'
;
const
StudioTabNav
=
()
=>
{
const
StudioTabNav
=
()
=>
{
const
match
=
useRouteMatch
();
const
match
=
useRouteMatch
();
return
(
return
(
<
div
>
<
SubNavigation
align=
"left"
className=
"studio-tab-nav"
>
<
NavLink
<
NavLink
active
Style=
{
{
textDecoration
:
'
underline
'
}
}
active
ClassName=
"active"
to=
{
`${match.url}`
}
to=
{
`${match.url}`
}
exact
exact
>
>
Projects
<
li
>
Projects
</
li
>
</
NavLink
>
</
NavLink
>
|
<
NavLink
<
NavLink
active
Style=
{
{
textDecoration
:
'
underline
'
}
}
active
ClassName=
"active"
to=
{
`${match.url}/curators`
}
to=
{
`${match.url}/curators`
}
>
>
Curators
<
li
>
Curators
</
li
>
</
NavLink
>
</
NavLink
>
|
<
NavLink
<
NavLink
active
Style=
{
{
textDecoration
:
'
underline
'
}
}
active
ClassName=
"active"
to=
{
`${match.url}/comments`
}
to=
{
`${match.url}/comments`
}
>
>
Comments
<
li
>
Comments
</
li
>
</
NavLink
>
</
NavLink
>
|
<
NavLink
<
NavLink
active
Style=
{
{
textDecoration
:
'
underline
'
}
}
active
ClassName=
"active"
to=
{
`${match.url}/activity`
}
to=
{
`${match.url}/activity`
}
>
>
Activity
<
li
>
Activity
</
li
>
</
NavLink
>
</
NavLink
>
</
div
>
</
SubNavigation
>
);
);
};
};
...
...
src/views/studio/studio-title.jsx
View file @
4f54e14e
...
@@ -6,29 +6,28 @@ import {connect} from 'react-redux';
...
@@ -6,29 +6,28 @@ import {connect} from 'react-redux';
import
{
selectStudioTitle
,
selectIsFetchingInfo
}
from
'
../../redux/studio
'
;
import
{
selectStudioTitle
,
selectIsFetchingInfo
}
from
'
../../redux/studio
'
;
import
{
selectCanEditInfo
}
from
'
../../redux/studio-permissions
'
;
import
{
selectCanEditInfo
}
from
'
../../redux/studio-permissions
'
;
import
{
mutateStudioTitle
,
selectIsMutatingTitle
,
selectTitleMutationError
}
from
'
../../redux/studio-mutations
'
;
import
{
mutateStudioTitle
,
selectIsMutatingTitle
,
selectTitleMutationError
}
from
'
../../redux/studio-mutations
'
;
import
classNames
from
'
classnames
'
;
const
StudioTitle
=
({
const
StudioTitle
=
({
titleError
,
isFetching
,
isMutating
,
title
,
canEditInfo
,
handleUpdate
titleError
,
isFetching
,
isMutating
,
title
,
canEditInfo
,
handleUpdate
})
=>
(
})
=>
{
<
div
>
const
fieldClassName
=
classNames
(
'
studio-title
'
,
{
<
h3
>
Title
</
h3
>
'
mod-fetching
'
:
isFetching
,
{
isFetching
?
(
'
mod-mutating
'
:
isMutating
<
h4
>
Fetching...
</
h4
>
});
)
:
(
canEditInfo
?
(
return
(
<
label
>
<
React
.
Fragment
>
<
input
<
textarea
disabled=
{
isMutating
}
className=
{
fieldClassName
}
defaultValue=
{
title
}
disabled=
{
isMutating
||
!
canEditInfo
||
isFetching
}
onBlur=
{
e
=>
e
.
target
.
value
!==
title
&&
defaultValue=
{
title
}
handleUpdate
(
e
.
target
.
value
)
}
onBlur=
{
e
=>
e
.
target
.
value
!==
title
&&
/>
handleUpdate
(
e
.
target
.
value
)
}
{
titleError
&&
<
div
>
Error mutating title:
{
titleError
}
</
div
>
}
/>
</
label
>
{
titleError
&&
<
div
>
Error mutating title:
{
titleError
}
</
div
>
}
)
:
(
</
React
.
Fragment
>
<
div
>
{
title
}
</
div
>
);
))
}
};
</
div
>
);
StudioTitle
.
propTypes
=
{
StudioTitle
.
propTypes
=
{
titleError
:
PropTypes
.
string
,
titleError
:
PropTypes
.
string
,
...
...
src/views/studio/studio.jsx
View file @
4f54e14e
...
@@ -28,40 +28,45 @@ const {getInitialState, studioReducer} = require('../../redux/studio');
...
@@ -28,40 +28,45 @@ const {getInitialState, studioReducer} = require('../../redux/studio');
const
{
commentsReducer
}
=
require
(
'
../../redux/comments
'
);
const
{
commentsReducer
}
=
require
(
'
../../redux/comments
'
);
const
{
studioMutationsReducer
}
=
require
(
'
../../redux/studio-mutations
'
);
const
{
studioMutationsReducer
}
=
require
(
'
../../redux/studio-mutations
'
);
import
'
./studio.scss
'
;
const
StudioShell
=
()
=>
{
const
StudioShell
=
()
=>
{
const
match
=
useRouteMatch
();
const
match
=
useRouteMatch
();
return
(
return
(
<
div
style=
{
{
maxWidth
:
'
960px
'
,
margin
:
'
auto
'
}
}
>
<
div
className=
"studio-shell"
>
<
StudioInfo
/>
<
div
className=
"studio-info"
>
<
hr
/>
<
StudioInfo
/>
<
StudioTabNav
/>
</
div
>
<
div
>
<
div
className=
"studio-tabs"
>
<
Switch
>
<
StudioTabNav
/>
<
Route
path=
{
`${match.path}/curators`
}
>
<
div
>
<
StudioCurators
/>
<
Switch
>
</
Route
>
<
Route
path=
{
`${match.path}/curators`
}
>
<
Route
path=
{
`${match.path}/comments`
}
>
<
StudioCurators
/>
<
StudioComments
/>
</
Route
>
</
Route
>
<
Route
path=
{
`${match.path}/comments`
}
>
<
Route
path=
{
`${match.path}/activity`
}
>
<
StudioComments
/>
<
StudioActivity
/>
</
Route
>
</
Route
>
<
Route
path=
{
`${match.path}/activity`
}
>
<
Route
path=
{
`${match.path}/projects`
}
>
<
StudioActivity
/>
{
/* We can force /projects back to / this way */
}
</
Route
>
<
Redirect
to=
{
match
.
url
}
/>
<
Route
path=
{
`${match.path}/projects`
}
>
</
Route
>
{
/* We can force /projects back to / this way */
}
<
Route
path=
{
match
.
path
}
>
<
Redirect
to=
{
match
.
url
}
/>
<
StudioProjects
/>
</
Route
>
</
Route
>
<
Route
path=
{
match
.
path
}
>
</
Switch
>
<
StudioProjects
/>
</
Route
>
</
Switch
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
);
);
};
};
render
(
render
(
<
Page
>
<
Page
className=
"studio-page"
>
<
Router
>
<
Router
>
<
Switch
>
<
Switch
>
{
/* Use variable studioPath to support /studio-playground/ or future route */
}
{
/* Use variable studioPath to support /studio-playground/ or future route */
}
...
...
src/views/studio/studio.scss
0 → 100644
View file @
4f54e14e
@import
"../../colors"
;
@import
"../../frameless"
;
$radius
:
8px
;
.studio-page
{
background-color
:
#E9F1FC
;
#view
{
/* Reset some defaults on width and margin */
background-color
:
transparent
;
max-width
:
1240px
;
min-width
:
auto
;
margin
:
50px
auto
;
display
:
block
;
.studio-shell
{
padding
:
0
20px
;
display
:
grid
;
gap
:
40px
;
/* Side-by-side with fixed width sidebar */
grid-template-columns
:
300px
minmax
(
0
,
1fr
);
/* Stack vertically at medium size and smaller */
@media
#{
$medium-and-smaller
}
{
&
{
grid-template-columns
:
minmax
(
0
,
1fr
);
}
}
}
}
}
.studio-info
{
justify-self
:
center
;
width
:
300px
;
height
:
fit-content
;
display
:
grid
;
grid-template-columns
:
minmax
(
0
,
1fr
);
gap
:
20px
;
.studio-title
,
.studio-description
{
background
:
transparent
;
margin
:
0
-8px
;
/* Outset the border horizontally */
padding
:
5px
8px
;
border
:
2px
dashed
$ui-blue-25percent
;
border-radius
:
$radius
;
resize
:
none
;
&
:disabled
{
border-color
:
transparent
;
}
}
.studio-title
{
font-size
:
28px
;
font-weight
:
500
;
}
.studio-description
:disabled
{
background
:
$ui-blue-10percent
;
}
}
.studio-tab-nav
{
border-bottom
:
1px
solid
$active-dark-gray
;
padding-bottom
:
8px
;
li
{
background
:
$active-gray
;
}
.active
>
li
{
background
:
$ui-blue
;
}
}
/* Modification classes for different interaction states */
.mod-fetching
{
/* When a field has no content to display yet */
position
:
relative
;
min-height
:
30px
;
&
:
:
after
{
content
:
''
;
width
:
100%
;
height
:
100%
;
position
:
absolute
;
top
:
0
;
left
:
0
;
background
:
#a0c6fc
;
border-radius
:
$radius
;
}
/* For elements that can't use :after, force reset some internals
to get the same visual (e.g. for textareas)*/
border-radius
:
$radius
;
background
:
#a0c6fc
!
important
;
color
:
#a0c6fc
!
important
;
border
:
none
!
important
;
margin
:
0
!
important
;
padding
:
0
!
important
;
}
.mod-mutating
{
/* When a field has sent a change to the server */
cursor
:
wait
;
opacity
:
.5
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment