Skip to content

Commit 98eab88

Browse files
committed
#891 Hide various edit elements when user doesn't have write permissions
1 parent d595e56 commit 98eab88

File tree

8 files changed

+97
-41
lines changed

8 files changed

+97
-41
lines changed

browser/data-browser/src/components/SideBar/ResourceSideBar/DropEdge.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { styled } from 'styled-components';
33
import { useState } from 'react';
44
import { transition } from '../../../helpers/transition';
55
import { SideBarDropData } from '../useSidebarDnd';
6+
import { useCanWrite, useResource } from '@tomic/react';
67

78
interface DropEdgeProps {
89
parentHierarchy: string[];
@@ -21,6 +22,9 @@ export function DropEdge({
2122

2223
const parent = parentHierarchy.at(-1)!;
2324

25+
const parentResource = useResource(parent);
26+
27+
const [canWrite] = useCanWrite(parentResource);
2428
useDndMonitor({
2529
onDragStart: event => setDraggingSubject(event.active.id as string),
2630
onDragEnd: () => setDraggingSubject(undefined),
@@ -36,6 +40,10 @@ export function DropEdge({
3640
data,
3741
});
3842

43+
if (!canWrite) {
44+
return <></>;
45+
}
46+
3947
const shouldRender =
4048
!!activeDraggedSubject && !parentHierarchy.includes(activeDraggedSubject);
4149

browser/data-browser/src/components/SideBar/ResourceSideBar/FloatingActions.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useResource, useTitle } from '@tomic/react';
1+
import { useCanWrite, useResource, useTitle } from '@tomic/react';
22
import { useState } from 'react';
33
import { FaEllipsisV, FaPlus } from 'react-icons/fa';
44
import { styled, css } from 'styled-components';
@@ -20,18 +20,21 @@ export function FloatingActions({
2020
const parentResource = useResource(subject);
2121
const [parentName] = useTitle(parentResource);
2222
const [dropdownActive, setDropdownActive] = useState(false);
23+
const [canWrite] = useCanWrite(parentResource);
2324

2425
const handleAddClick = useNewRoute(subject);
2526

2627
return (
2728
<Wrapper className={className} dropdownActive={dropdownActive}>
28-
<IconButton
29-
data-test='add-subresource'
30-
onClick={handleAddClick}
31-
title={`Create new resource under ${parentName}`}
32-
>
33-
<FaPlus />
34-
</IconButton>
29+
{canWrite && (
30+
<IconButton
31+
data-test='add-subresource'
32+
onClick={handleAddClick}
33+
title={`Create new resource under ${parentName}`}
34+
>
35+
<FaPlus />
36+
</IconButton>
37+
)}
3538
<ResourceContextMenu
3639
simple
3740
subject={subject}

browser/data-browser/src/components/SideBar/ResourceSideBar/ResourceSideBar.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { Fragment, useEffect, useMemo, useState } from 'react';
2-
import { useString, useResource, useTitle, urls, useArray } from '@tomic/react';
2+
import {
3+
useString,
4+
useResource,
5+
useTitle,
6+
useArray,
7+
useCanWrite,
8+
core,
9+
dataBrowser,
10+
} from '@tomic/react';
311
import { useCurrentSubject } from '../../../helpers/useCurrentSubject';
412
import { SideBarItem } from '../SideBarItem';
513
import { AtomicLink } from '../../AtomicLink';
@@ -38,12 +46,15 @@ export function ResourceSideBar({
3846
const resource = useResource(subject, { allowIncomplete: true });
3947
const [currentUrl] = useCurrentSubject();
4048
const [title] = useTitle(resource);
41-
const [description] = useString(resource, urls.properties.description);
42-
49+
const [description] = useString(resource, core.properties.description);
50+
const [canWrite] = useCanWrite(resource);
4351
const active = currentUrl === subject;
4452
const [open, setOpen] = useState(active);
4553

46-
const [subResources] = useArray(resource, urls.properties.subResources);
54+
const [subResources] = useArray(
55+
resource,
56+
dataBrowser.properties.subResources,
57+
);
4758
const hasSubResources = subResources.length > 0;
4859

4960
const dragData: SideBarDragData = {
@@ -59,6 +70,7 @@ export function ResourceSideBar({
5970
} = useDraggable({
6071
id: subject,
6172
data: dragData,
73+
disabled: !canWrite,
6274
});
6375

6476
const isDragging = draggingNode?.id === subject;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { PropsWithChildren } from 'react';
2+
import { styled } from 'styled-components';
3+
import { lighten } from 'polished';
4+
5+
export function WarningBlock({
6+
children,
7+
}: PropsWithChildren): React.JSX.Element {
8+
return <Wrapper>{children}</Wrapper>;
9+
}
10+
11+
const Wrapper = styled.div`
12+
background-color: ${p => lighten(0.2, p.theme.colors.warning)};
13+
border: 2px solid ${p => p.theme.colors.warning};
14+
border-radius: ${p => p.theme.radius};
15+
padding: 1rem;
16+
`;
17+
18+
WarningBlock.Title = styled.p`
19+
font-weight: bold;
20+
color: ${p => lighten(-1, p.theme.colors.warning)};
21+
margin-bottom: 0px;
22+
`;

browser/data-browser/src/routes/SettingsAgent.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ import { ContainerNarrow } from '../components/Containers';
1717
import { AtomicLink } from '../components/AtomicLink';
1818
import { editURL } from '../helpers/navigation';
1919
import { useNavigate } from 'react-router';
20-
import { ErrorLook } from '../components/ErrorLook';
2120
import { Main } from '../components/Main';
21+
import { Column } from '../components/Row';
22+
import { WarningBlock } from '../components/WarningBlock';
2223

2324
const SettingsAgent: React.FunctionComponent = () => {
2425
const { agent, setAgent } = useSettings();
@@ -142,26 +143,26 @@ const SettingsAgent: React.FunctionComponent = () => {
142143
Key. Together, these can be used to edit data and sign Commits.
143144
</p>
144145
{agent ? (
145-
<>
146+
<Column>
146147
{agent.subject?.startsWith('http://localhost') && (
147-
<p>
148-
<ErrorLook>Warning:</ErrorLook>
148+
<WarningBlock>
149+
<WarningBlock.Title>Warning:</WarningBlock.Title>
149150
{
150151
"You're using a local Agent, which cannot authenticate on other domains, because its URL does not resolve."
151152
}
152-
</p>
153+
</WarningBlock>
153154
)}
154-
<LabelStyled>
155-
<FaUser /> You{"'"}re signed in as
156-
</LabelStyled>
157-
<p>
155+
<div>
156+
<LabelStyled>
157+
<FaUser /> You{"'"}re signed in as
158+
</LabelStyled>
158159
<ResourceInline subject={agent.subject!} />
159-
</p>
160+
</div>
160161
<Button onClick={() => navigate(editURL(agent.subject!))}>
161162
Edit profile
162163
</Button>
163164
<Margin />
164-
</>
165+
</Column>
165166
) : (
166167
<p>
167168
You can create your own Agent by hosting an{' '}

browser/data-browser/src/views/BookmarkPage/BookmarkPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ResourcePageProps } from '../ResourcePage';
22
import { useCallback } from 'react';
3-
import { urls, useString } from '@tomic/react';
3+
import { urls, useCanWrite, useString } from '@tomic/react';
44
import { EditableTitle } from '../../components/EditableTitle';
55
import { styled } from 'styled-components';
66
import { ContainerFull, ContainerNarrow } from '../../components/Containers';
@@ -20,6 +20,8 @@ export function BookmarkPage({ resource }: ResourcePageProps): JSX.Element {
2020

2121
const { preview, error, update, loading } = usePreview(resource);
2222

23+
const [canWrite] = useCanWrite(resource);
24+
2325
const handleUrlChange = useCallback(
2426
async (e: React.ChangeEvent<HTMLInputElement>) => {
2527
await setUrl(e.target.value);
@@ -43,6 +45,7 @@ export function BookmarkPage({ resource }: ResourcePageProps): JSX.Element {
4345
placeholder='https://example.com'
4446
value={url}
4547
onChange={handleUrlChange}
48+
disabled={!canWrite}
4649
/>
4750
</InputWrapper>
4851
</FieldWrapper>

browser/data-browser/src/views/ChatRoomPage.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
dataBrowser,
55
getTimestampNow,
66
useArray,
7+
useCanWrite,
78
useResource,
89
useStore,
910
useString,
@@ -188,6 +189,7 @@ const Message = memo(function Message({ subject, setReplyTo }: MessageProps) {
188189
const [lastCommit] = useSubject(resource, commits.properties.lastCommit);
189190
const [replyTo] = useSubject(resource, dataBrowser.properties.replyTo);
190191
const navigate = useNavigate();
192+
const [canWrite] = useCanWrite(resource);
191193

192194
function handleCopyUrl() {
193195
navigator.clipboard.writeText(subject);
@@ -205,14 +207,16 @@ const Message = memo(function Message({ subject, setReplyTo }: MessageProps) {
205207
<CommitDetail commitSubject={lastCommit!} />
206208
{replyTo && <MessageLine subject={replyTo} />}
207209
<MessageActions>
208-
<Button
209-
icon
210-
subtle
211-
onClick={() => navigate(editURL(subject))}
212-
title='Edit message'
213-
>
214-
<FaPencilAlt />
215-
</Button>
210+
{canWrite && (
211+
<Button
212+
icon
213+
subtle
214+
onClick={() => navigate(editURL(subject))}
215+
title='Edit message'
216+
>
217+
<FaPencilAlt />
218+
</Button>
219+
)}
216220
<Button
217221
icon
218222
subtle

browser/data-browser/src/views/DocumentPage.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -361,20 +361,23 @@ function DocumentPageShow({
361361
setEditMode,
362362
}: DocumentSubPageProps): JSX.Element {
363363
const [elements] = useArray(resource, dataBrowser.properties.elements);
364+
const [canWrite] = useCanWrite(resource);
364365

365366
return (
366367
<>
367368
<div style={{ display: 'flex', flexDirection: 'row' }}>
368369
<h1 style={{ flex: 1 }}>{resource.title}</h1>
369-
<Button
370-
data-test='document-edit'
371-
icon
372-
subtle
373-
onClick={() => setEditMode(true)}
374-
title='Edit mode'
375-
>
376-
<FaEdit />
377-
</Button>
370+
{canWrite && (
371+
<Button
372+
data-test='document-edit'
373+
icon
374+
subtle
375+
onClick={() => setEditMode(true)}
376+
title='Edit mode'
377+
>
378+
<FaEdit />
379+
</Button>
380+
)}
378381
</div>
379382
{elements.map(subject => (
380383
<ElementShow subject={subject} key={subject} />

0 commit comments

Comments
 (0)