Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

7 - Grant access to edit a document to a user #172

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions features/grant_document_access.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#language: fr

Fonctionnalité: Essayer d'accorder à un utilisateur les droits d'édition d'un document

Scénario: dont on est l'auteur

Soit un document dont je suis l'auteur affiché comme glose
Et une session active avec mon compte
Quand j'essaye d'accorder les droits d'édition à "bill"
Alors "bill" peut modifier le document

Scénario: dont on n'est pas l'auteur

Soit un document dont je ne suis pas l'auteur affiché comme glose
Et une session active avec mon compte
Quand j'essaye d'accorder les droits d'édition à "alice"
Alors alice ne peut pas modifier le document

Scénario: sans etre connecté

Soit un document dont je suis l'auteur affiché comme glose
Et une session active avec mon compte
Quand j'essaye d'accorder les droits d'édition à "bill"
Alors bill ne peut pas modifier le document
7 changes: 7 additions & 0 deletions features/step_definitions/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,10 @@
Quand("je clique sur la référence temporelle {string} avec pour commentaire {string}") do |timecode, comment|
find(:xpath, "//p[contains(., \"#{timecode}\")]", match: :first).click
end

Quand("j'essaye d'accorder les droits d'édition à {string}") do |userName|
find(".more-btn > button").trigger("click")
find(".dropdown-item-share").click
find(".add-user-input").fill_in with: userName
find(".add-user-input-btn").click
end
35 changes: 35 additions & 0 deletions features/step_definitions/outcome.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,38 @@
Alors('le texte du premier passage de la glose est :') do |text|
expect(find('.editable.content', match: :first).text).to match /\A#{text}\z/
end

Alors('{string} peux modifier le document') do |string|
sign_out
sign_in(string, 'madhatter')
find('.editable.content').click
find('textarea').fill_in with: 'content'
leave_textarea
expect(find('.editable.content', match: :first).text).to match 'content'
sign_out
end

Alors('alice ne peux pas modifier le document') do
sign_out
sign_in('alice', 'whiterabbit')
find('.editable.content').trigger("click")
find('textarea').fill_in with: 'content'
find('.navbar').click
find('.editable.content').trigger("click")
find('.navbar').trigger("click")
expect(page).not_to have_selector('.editable.content', text: 'content')
sign_out
end

Alors('bill ne peux pas modifier le document') do
sign_out
sign_in('bill', 'madhatter')
find('.editable.content').trigger("click")
find('textarea').fill_in with: 'content'
find('.navbar').click
find('.editable.content').trigger("click")
find('.navbar').trigger("click")
find('.navbar').trigger("click")
expect(page).not_to have_selector('.editable.content', text: 'content')
sign_out
end
78 changes: 78 additions & 0 deletions frontend/src/components/More.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import Dropdown from 'react-bootstrap/Dropdown';
import {ThreeDotsVertical} from 'react-bootstrap-icons';
import {useEffect, useState} from 'react';
import {Button, InputGroup, ListGroup, Modal} from 'react-bootstrap';
import Form from 'react-bootstrap/Form';

export default function More({metadata, backend}) {
const [show, setShow] = useState(false);
const [userName, setUserName] = useState('');
const [loading, setLoading] = useState(false);
const [document, setDocument] = useState(metadata);

const handleClose = () => setShow(false);
const handleShow = () => setShow(true);

let addEditor = () => {
if (!loading) {
setLoading(true);
const payload = {...document, editors: [...(document.editors ?? [])]};
const formattedUserName = userName.trim();

if (payload.editors.includes(formattedUserName) || formattedUserName === '') {
setUserName('');
setLoading(false);
return;
}

payload.editors.push(formattedUserName);

backend.putDocument(payload).then(({rev}) => {
payload._rev = rev;
setDocument(payload);
setUserName('');
setLoading(false);
});
}
};

return (
<>
<Dropdown className="float-end more-btn">
<Dropdown.Toggle variant="ghost">
<ThreeDotsVertical/>
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item as="button" onClick={handleShow} className="dropdown-item-share">Share</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>

<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Invite user to edit document</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form.Label htmlFor="inputPassword5">Username</Form.Label>
<InputGroup className="mb-3">
<Form.Control
className="add-user-input"
value={userName}
onInput={(event) => setUserName(event.target.value)}
/>
<Button variant="primary" onClick={addEditor} className="add-user-input-btn">
Invite
</Button>
</InputGroup>
</Modal.Body>
<Modal.Body>
<h5>Editors</h5>
<ListGroup>
{(document && document.editors ? document.editors : []).map((user) => (
<ListGroup.Item key={user}>{user}</ListGroup.Item>
))}
</ListGroup>
</Modal.Body>
</Modal>
</>
);
}
12 changes: 7 additions & 5 deletions frontend/src/routes/Lectern.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import BrowseTools from '../components/BrowseTools';
import EditableText from '../components/EditableText';
import DocumentSources from '../components/DocumentSources';
import Type, { TypeBadge } from '../components/Type';
import More from '../components/More';

function Lectern({backend}) {

Expand Down Expand Up @@ -99,7 +100,7 @@ function Lectern({backend}) {
</Col>
<Col className="lectern">
<Row className ="runningHead">
<RunningHeadSource metadata={ sourceMetadata } />
<RunningHeadSource metadata={ sourceMetadata } backend={backend} />
<RunningHeadMargin {...{backend}}
metadata={ metadata.find(x => (x._id === margin)) }
/>
Expand Down Expand Up @@ -158,12 +159,12 @@ function PassageMargin({active, scholium, rubric, backend, setLastUpdate}) {
);
}

function RunningHeadSource({metadata}) {
function RunningHeadSource({metadata, backend}) {
return (
<Col className="main">
<BookmarkFill className="icon" />
<Metadata metadata={metadata} />
<TypeBadge type={metadata?.type} />
<BookmarkFill className="icon"/>
<Metadata metadata={metadata}/>
<TypeBadge type={metadata?.type}/>
</Col>
);
}
Expand All @@ -173,6 +174,7 @@ function RunningHeadMargin({metadata, backend}) {
return (
<Col xs={5} className="scholium">
<BrowseTools id={metadata._id} closable={true} />
<More metadata={metadata} backend={backend} />
<Metadata metadata={metadata} editable={true} {...{backend}} />
<Type metadata={metadata} editable={true} {...{backend}}/>
</Col>
Expand Down
Loading