@@ -26,6 +26,7 @@ import {
2626 ListWrapper ,
2727 VisibilityIconWrapper
2828} from './style' ;
29+ import { TypedMutationTrigger , TypedUseQuery } from '@reduxjs/toolkit/dist/query/react' ;
2930
3031const options = {
3132 PUBLIC : 'Anyone with the link can edit' ,
@@ -158,6 +159,20 @@ interface SelectedResource {
158159 [ key : string ] : unknown ;
159160}
160161
162+ type ResourceAccessArg = {
163+ resourceType : string ;
164+ resourceId : string ;
165+ resourceAccessMappingPayload : {
166+ grant_access : string [ ] ;
167+ revoke_access : string [ ] ;
168+ notify_users : boolean ;
169+ } ;
170+ } ;
171+
172+
173+ import type { MutationTrigger } from '@reduxjs/toolkit/query/react' ;
174+ import { startCase } from 'lodash' ;
175+
161176interface ShareModalProps {
162177 /** Function to close the share modal */
163178 handleShareModalClose : ( ) => void ;
@@ -186,11 +201,13 @@ interface ShareModalProps {
186201 fetchSuggestions : ( value : string ) => Promise < User [ ] > ;
187202 handleCopy : ( ) => void ;
188203 handleUpdateVisibility : ( value : string ) => Promise < { error : string } > ,
189- isUpdatingVisibility : boolean ,
190204 handleShareWithNewUsers : ( newUsers : User [ ] ) => Promise < { error : string } > ,
191205 canShareWithNewUsers : boolean ,
192206 handleRevokeAccess : ( revokedUsser : User [ ] ) => Promise < { error : string } >
193207 canRevokeAccess : boolean ,
208+ resourceAccessMutator : MutationTrigger < ResourceAccessArg > ,
209+ notify : ( { message, event_type } : { message : string , event_type : "success" | "error" } ) => void ,
210+ useGetAllUsersQuery : any ,
194211}
195212
196213/**
@@ -206,40 +223,158 @@ const ShareModal: React.FC<ShareModalProps> = ({
206223 hostURL = null ,
207224 handleCopy,
208225 handleUpdateVisibility,
209- isUpdatingVisibility,
210226 canShareWithNewUsers,
211- handleRevokeAccess,
212- handleShareWithNewUsers,
213227 isVisibilitySelectorDisabled = false ,
214- fetchSuggestions
228+ fetchSuggestions,
229+ resourceAccessMutator,
230+ notify,
231+ useGetAllUsersQuery,
232+
215233} : ShareModalProps ) : JSX . Element => {
216- const theme = useTheme ( ) ;
234+ const theme = useTheme ( ) ;
217235 const [ openMenu , setMenu ] = useState < boolean > ( false ) ;
218236 const [ shareUserData , setShareUserData ] = useState < User [ ] > ( [ ] ) ;
219- const [ resourceVisibility , setVisibility ] = useState ( selectedResource . visibility )
237+ const [ resourceVisibility , setVisibility ] = useState ( selectedResource . visibility )
238+ const [ isUpdatingVisibility , setUpdatingVisibility ] = useState ( false )
239+
240+
241+
242+
243+ const resourceType = dataName === "design" ? "pattern" : dataName ;
244+
245+
246+ const handleShareWithNewUsers = async ( newUsers : User [ ] ) => {
247+ console . log ( "new users" , newUsers )
248+ const grantAccessList = newUsers . map ( user => ( {
249+ actor_id : user . user_id ?? user . id ,
250+ actor_type : "user"
251+ } ) )
252+ const emails = newUsers . map ( u => u . email )
253+
254+ const response = await resourceAccessMutator ( {
255+ resourceType,
256+ resourceId : selectedResource ?. id ,
257+ resourceAccessMappingPayload : {
258+ grant_access : [ ...grantAccessList ] ,
259+ revoke_access : [ ] ,
260+ notify_users : true
261+ }
262+ } )
263+
264+
265+
266+ if ( ! response ?. error ) {
267+ const msg = `${ dataName } shared with ${ emails . join ( ", " ) } ` ;
268+ notify ( {
269+ message : msg ,
270+ event_type : "success"
271+ } ) ;
272+ }
273+
274+ if ( response ?. error ) {
275+ notify ( {
276+ message : `An error occurred. ${ dataName } not shared` ,
277+ event_type : "error"
278+ } ) ;
279+ }
280+
281+ return {
282+ error : response ?. error ?. error
283+ }
284+
285+ } ;
286+
287+
288+ const handleRevokeAccess = async ( revokedUsers : User [ ] ) => {
289+ const revokeAccessList = revokedUsers . map ( user => ( {
290+ actor_id : user . id ,
291+ actor_type : "user"
292+ } ) )
293+ const emails = revokedUsers . map ( u => u . email )
294+
295+ const response = await resourceAccessMutator ( {
296+ resourceType,
297+ resourceId : selectedResource ?. id ,
298+ resourceAccessMappingPayload : {
299+ grant_access : [ ] ,
300+ revoke_access : [ ...revokeAccessList ] ,
301+ notify_users : true
302+ }
303+ } )
304+
305+
306+ if ( ! response ?. error ) {
307+ const msg = `Access to ${ dataName } revoked for ${ emails . join ( ", " ) } ` ;
308+ notify ( {
309+ message : msg ,
310+ event_type : "success"
311+ } ) ;
312+
313+ }
314+
315+ if ( response ?. error ) {
316+ notify ( {
317+ message : `failed to revokke access to ${ dataName } ` ,
318+ event_type : "error"
319+ } ) ;
320+ }
321+
322+ return {
323+ error : response ?. error ?. error
324+ }
325+
326+ } ;
327+
220328
221329 const handleDelete = async ( email : string ) => {
222330 const revoked = shareUserData . find ( user => user . email == email )
223331 if ( ! revoked ) {
224332 console . error ( "cant revoke user without acesss" )
225- return { error :"" }
333+ return { error : "" }
226334 }
227335 return handleRevokeAccess ( [ revoked ] )
228336 } ;
229337
230- const handleOptionClick = async ( event : SelectChangeEvent < unknown > ) => {
338+
339+ const notifyVisibilityChange = ( res : any , value : any ) => {
340+ const UPDATE_VISIBILITY_MSG = `${ startCase ( dataName ) } '${ selectedResource . name } ' is now ${ value } ` ;
341+ const FAILED_TO_UPDATE_VISIBILITY_MSG = `Failed to update visibility. ${ res ?. error ?. error || "" } ` ;
342+
343+ if ( ! res . error ) {
344+ notify ( {
345+ message : UPDATE_VISIBILITY_MSG ,
346+ event_type : "success"
347+ } ) ;
348+ } else {
349+
350+ notify ( {
351+ message : FAILED_TO_UPDATE_VISIBILITY_MSG ,
352+ event_type : "error"
353+ } ) ;
354+ }
355+ }
356+
357+ const updateVisisbility = async ( event : SelectChangeEvent < unknown > ) => {
231358 const value = event . target . value as string ;
232- if ( value == resourceVisibility ) {
233- console . error ( "visibility is already " , value )
359+
360+ if ( value == resourceVisibility ) {
361+ console . error ( "visibility is already " , value )
234362 return
235363 }
236364
237- const res = await handleUpdateVisibility ( value )
238- if ( ! res ?. error ) {
239- setVisibility ( value )
365+ try {
366+ setUpdatingVisibility ( true )
367+ const res = await handleUpdateVisibility ( value )
368+ notifyVisibilityChange ( res , value )
369+ if ( ! res ?. error ) {
370+ setVisibility ( value )
371+ }
372+ } finally {
373+ setUpdatingVisibility ( false )
240374 }
241375 } ;
242376
377+
243378 const handleMenuClose = ( ) => setMenu ( false ) ;
244379
245380
@@ -276,6 +411,7 @@ const ShareModal: React.FC<ShareModalProps> = ({
276411 hostURL = { hostURL }
277412 />
278413 }
414+ useGetAllUsersQuery = { useGetAllUsersQuery }
279415 fetchSuggestions = { fetchSuggestions }
280416 />
281417
@@ -298,7 +434,7 @@ const ShareModal: React.FC<ShareModalProps> = ({
298434
299435 { isUpdatingVisibility && < CircularProgress size = { 24 } /> }
300436
301-
437+
302438 { ! isUpdatingVisibility && resourceVisibility === SHARE_MODE . PUBLIC && (
303439 < PublicIcon
304440 width = { 24 }
@@ -326,7 +462,7 @@ const ShareModal: React.FC<ShareModalProps> = ({
326462 open = { openMenu }
327463 onClose = { handleMenuClose }
328464 onOpen = { ( ) => setMenu ( true ) }
329- onChange = { handleOptionClick }
465+ onChange = { updateVisisbility }
330466 disabled = { isVisibilitySelectorDisabled || isUpdatingVisibility }
331467 >
332468 { Object . values ( SHARE_MODE ) . map ( ( option ) => (
0 commit comments