Skip to content

Commit

Permalink
feat: Making it possible to revoke a group
Browse files Browse the repository at this point in the history
  • Loading branch information
cballevre committed Mar 21, 2024
1 parent 958c55c commit cc3e998
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 17 deletions.
16 changes: 11 additions & 5 deletions packages/cozy-sharing/.storybook/preview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CozyTheme from 'cozy-ui/transpiled/react/providers/CozyTheme'
import { CozyProvider, createFakeClient } from 'cozy-client'

import enLocale from '../locales/en.json'
import SharingContext from "../src/context";

const preview = {
decorators: [
Expand Down Expand Up @@ -40,11 +41,16 @@ const preview = {
<CozyProvider client={fakeClient}>
<CozyTheme>
<BreakpointsProvider>
<I18n lang="en" dictRequire={() => enLocale}>
<div style={{position: "relative"}}>
<Story />
</div>
</I18n>
<SharingContext.Provider value={{
revokeGroup: () => {},
revokeSelf: () => {}
}}>
<I18n lang="en" dictRequire={() => enLocale}>
<div style={{position: "relative"}}>
<Story />
</div>
</I18n>
</SharingContext.Provider>
</BreakpointsProvider>
</CozyTheme>
</CozyProvider>
Expand Down
15 changes: 15 additions & 0 deletions packages/cozy-sharing/src/SharingProvider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import reducer, {
updateSharingLink,
revokeSharingLink,
revokeRecipient,
revokeGroup as revokeGroupFromState,
revokeSelf,
receivePaths,
isOwner,
Expand Down Expand Up @@ -71,6 +72,7 @@ export class SharingProvider extends Component {
share: this.share,
onShared: onShared,
revoke: this.revoke,
revokeGroup: this.revokeGroup,
revokeSelf: this.revokeSelf,
shareByLink: this.shareByLink,
updateDocumentPermissions: this.updateDocumentPermissions,
Expand Down Expand Up @@ -291,6 +293,19 @@ export class SharingProvider extends Component {
)
}

revokeGroup = async (document, sharingId, recipientIndex) => {
const { client, doctype } = this.props
const sharing = getSharingById(this.state, sharingId)
await this.sharingCol.revokeGroup(sharing, recipientIndex)
this.dispatch(
revokeGroupFromState(
sharing,
recipientIndex,
document.path || (await fetchFilesPaths(client, doctype, [document]))
)
)
}

revokeSelf = async document => {
const sharing = getSharingForSelf(this.state, document.id)
await this.sharingCol.revokeSelf(sharing)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,56 @@ import {
makeActions,
divider
} from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
import ActionsMenuMobileHeader from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuMobileHeader'
import DropdownButton from 'cozy-ui/transpiled/react/DropdownButton'
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
import Spinner from 'cozy-ui/transpiled/react/Spinner'
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'

import { permission } from './actions/permission'
import { revokeGroup } from './actions/revokeGroup'
import { revokeGroup as revokeGroupAction } from './actions/revokeGroup'
import { useSharingContext } from '../../hooks/useSharingContext'
import { GroupAvatar } from '../Avatar/GroupAvatar'

const GroupRecipientPermissions = ({
name,
isOwner,
instance,
sharingId,
groupIndex,
read_only: isReadOnly = false,
className
}) => {
const { t } = useI18n()
const buttonRef = useRef()
const client = useClient()
const { revokeGroup, revokeSelf } = useSharingContext()

const [isMenuDisplayed, setMenuDisplayed] = useState(false)
const [revoking, setRevoking] = useState(false)

const instanceMatchesClient =
instance !== undefined && instance === client.options.uri
const shouldShowMenu = (instanceMatchesClient && !isOwner) || isOwner
const shouldShowMenu =
!revoking && ((instanceMatchesClient && !isOwner) || isOwner)

const toggleMenu = () => setMenuDisplayed(!isMenuDisplayed)
const hideMenu = () => setMenuDisplayed(false)

const handleRevocation = () => {
// TODO : Need to be implemented
const handleRevocation = async () => {
setRevoking(true)
if (isOwner) {
await revokeGroup(document, sharingId, groupIndex)
} else {
await revokeSelf(document)
}
setRevoking(false)
}

const type = isReadOnly ? 'one-way' : 'two-way'

const actions = makeActions([permission, divider, revokeGroup], {
const actions = makeActions([permission, divider, revokeGroupAction], {
t,
type,
isOwner,
Expand All @@ -46,6 +64,7 @@ const GroupRecipientPermissions = ({

return (
<div className={className}>
{revoking && <Spinner />}
{shouldShowMenu && (
<>
<DropdownButton
Expand All @@ -67,7 +86,17 @@ const GroupRecipientPermissions = ({
}}
autoClose
onClose={hideMenu}
/>
>
<ActionsMenuMobileHeader>
<ListItemIcon>
<GroupAvatar size="small" />
</ListItemIcon>
<ListItemText
primary={name}
primaryTypographyProps={{ variant: 'h6' }}
/>
</ActionsMenuMobileHeader>
</ActionsMenu>
</>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
import React, { forwardRef } from 'react'

import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem'
import Icon from 'cozy-ui/transpiled/react/Icon'
import EyeIcon from 'cozy-ui/transpiled/react/Icons/Eye'
import RenameIcon from 'cozy-ui/transpiled/react/Icons/Rename'
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
import Radios from 'cozy-ui/transpiled/react/Radios'

const permission = ({ t, type }) => {
const title = t(`Share.type.${type}`)
const icon = type === 'two-way' ? RenameIcon : EyeIcon

return {
name: 'permission',
label: title,
icon,
icon: null,
action: null,
Component: forwardRef(function RevokeItem(props, ref) {
return (
<ActionsMenuItem {...props} ref={ref} button={false}>
<ListItemIcon>
<Icon icon={icon} />
<Radios checked={true} />
</ListItemIcon>
<ListItemText primary={title} />
</ActionsMenuItem>
Expand Down
28 changes: 28 additions & 0 deletions packages/cozy-sharing/src/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const RECEIVE_SHARINGS = 'RECEIVE_SHARINGS'
const ADD_SHARING = 'ADD_SHARING'
const UPDATE_SHARING = 'UPDATE_SHARING'
const REVOKE_RECIPIENT = 'REVOKE_RECIPIENT'
const REVOKE_GROUP = 'REVOKE_GROUP'
const REVOKE_SELF = 'REVOKE_SELF'
const ADD_SHARING_LINK = 'ADD_SHARING_LINK'
const UPDATE_SHARING_LINK = 'UPDATE_SHARING_LINK'
Expand Down Expand Up @@ -62,6 +63,30 @@ export const revokeRecipient = (sharing, index, path) => {
path
}
}
export const revokeGroup = (sharing, index, path) => {
return {
type: REVOKE_GROUP,
/* We can't just simply remove a group,
because we use the index to remove the other group
*/
sharing: {
...sharing,
attributes: {
...sharing.attributes,
groups: sharing.attributes.groups.map((g, idx) => {
if (idx === index) {
return {
...g,
revoked: true
}
}
return g
})
}
},
path
}
}
export const revokeSelf = sharing => ({ type: REVOKE_SELF, sharing })
export const addSharingLink = data => ({ type: ADD_SHARING_LINK, data })
export const updateSharingLink = data => ({ type: UPDATE_SHARING_LINK, data })
Expand Down Expand Up @@ -149,6 +174,7 @@ const byDocId = (state = {}, action) => {
)
case ADD_SHARING:
return indexSharing(state, action.data)
case REVOKE_GROUP:
case REVOKE_RECIPIENT:
case UPDATE_SHARING:
if (areAllRecipientsRevoked(action.sharing)) {
Expand Down Expand Up @@ -220,6 +246,7 @@ const sharings = (state = [], action) => {
const filtered_state = state.filter(s => s.id !== action.data.id)
return [...filtered_state, action.data]
case UPDATE_SHARING:
case REVOKE_GROUP:
case REVOKE_RECIPIENT:
return state.map(s => {
return s.id !== action.sharing.id ? s : action.sharing
Expand All @@ -242,6 +269,7 @@ const sharedPaths = (state = [], action) => {
// eslint-disable-next-line
const newState = [...state, action.path]
return newState
case REVOKE_GROUP:
case REVOKE_RECIPIENT:
if (areAllRecipientsRevoked(action.sharing)) {
return state.filter(p => p !== action.path)
Expand Down

0 comments on commit cc3e998

Please sign in to comment.