-
Notifications
You must be signed in to change notification settings - Fork 1
Sharing UI: display user names #25
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -24,11 +24,19 @@ const TABS: { id: TabId; label: string; icon: React.ReactElement }[] = [ | |||||
|
|
||||||
| function FileTypeIcon({ share, registry }: { share: Share; registry: FileTypeRegistry }) { | ||||||
| if (share.resourceType !== 'RESOURCE_TYPE_FILE') { | ||||||
| return <span className="swan-shares-item-icon"><folderIcon.react stylesheet="listing" /></span>; | ||||||
| return ( | ||||||
| <span className="swan-shares-item-icon"> | ||||||
| <folderIcon.react stylesheet="listing" /> | ||||||
| </span> | ||||||
| ); | ||||||
| } | ||||||
| const fileTypes = registry.getFileTypesForPath(share.name); | ||||||
| const Icon = fileTypes.length > 0 && fileTypes[0].icon ? fileTypes[0].icon.react : fileIcon.react; | ||||||
| return <span className="swan-shares-item-icon"><Icon stylesheet="listing" /></span>; | ||||||
| return ( | ||||||
| <span className="swan-shares-item-icon"> | ||||||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here |
||||||
| <Icon stylesheet="listing" /> | ||||||
| </span> | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| function ShareItem({ | ||||||
|
|
@@ -44,9 +52,9 @@ function ShareItem({ | |||||
| }) { | ||||||
| let meta = ''; | ||||||
| if (share.shareDirection === 'WITH_ME' && share.sharedBy) { | ||||||
| meta = `from ${share.sharedBy}`; | ||||||
| meta = `from ${share.sharedBy.displayName || share.sharedBy.opaqueId}`; | ||||||
| } else if (share.shareDirection === 'BY_ME' && share.shareType === 'REGULAR' && share.sharedWith.length > 0) { | ||||||
| meta = `with ${share.sharedWith.map(g => g.opaqueId).join(', ')}`; | ||||||
| meta = `with ${share.sharedWith.map(g => ('displayName' in g ? g.displayName : g.opaqueId)).join(', ')}`; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These types of checks can be simplified, but it's a minor suggestion
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are other places where this can be applied. |
||||||
| } | ||||||
|
|
||||||
| const handleContext = (e: React.MouseEvent) => { | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,15 +24,39 @@ interface RawResourceInfo { | |
| type?: ResourceType; | ||
| } | ||
|
|
||
| interface RawSharedByMeRegular { | ||
| interface RawGranteeUserInfo { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason to have different interfaces that are the same? They actually represent the same entity (user, person, account.. not sure what's the most appropriate name), that can be a person that creates or receives a share. |
||
| id: { opaque_id: string }; | ||
| mail: string; | ||
| display_name: string; | ||
| } | ||
|
|
||
| interface RawCreatorUserInfo { | ||
| id: { opaque_id: string }; | ||
| mail: string; | ||
| display_name: string; | ||
| } | ||
|
|
||
| interface RawSharedByMeRegularUser { | ||
| share: { | ||
| id: { opaque_id: string }; | ||
| resource_id: { opaque_id: string }; | ||
| grantee: RawUserGrantee | RawGroupGrantee; | ||
| grantee: RawUserGrantee; | ||
| }; | ||
| resource_info: RawResourceInfo; | ||
| grantee_user_info: RawGranteeUserInfo; | ||
| } | ||
|
|
||
| interface RawSharedByMeRegularGroup { | ||
| share: { | ||
| id: { opaque_id: string }; | ||
| resource_id: { opaque_id: string }; | ||
| grantee: RawGroupGrantee; | ||
| }; | ||
| resource_info: RawResourceInfo; | ||
| } | ||
|
|
||
| type RawSharedByMeRegular = RawSharedByMeRegularUser | RawSharedByMeRegularGroup; | ||
|
|
||
| interface RawSharedByMePublic { | ||
| public_share: { | ||
| id: { opaque_id: string }; | ||
|
|
@@ -52,12 +76,31 @@ interface RawSharedWithMe { | |
| }; | ||
| }; | ||
| resource_info: RawResourceInfo; | ||
| creator_user_info?: RawCreatorUserInfo; | ||
| } | ||
|
|
||
| interface Grantee { | ||
| type: GranteeType; | ||
| interface InvalidGrantee { | ||
| type: 'GRANTEE_TYPE_INVALID'; | ||
| opaqueId: string; | ||
| } | ||
| interface GroupGrantee { | ||
| type: 'GRANTEE_TYPE_GROUP'; | ||
| opaqueId: string; | ||
| } | ||
| interface UserGrantee { | ||
| type: 'GRANTEE_TYPE_USER'; | ||
| opaqueId: string; | ||
| mail: string; | ||
| displayName: string; | ||
| } | ||
|
|
||
| type Grantee = InvalidGrantee | GroupGrantee | UserGrantee; | ||
|
|
||
| interface Creator { | ||
| opaqueId: string; | ||
| mail?: string; | ||
| displayName?: string; | ||
| } | ||
|
|
||
| interface _Share { | ||
| shareDirection: ShareDirection; | ||
|
|
@@ -83,7 +126,7 @@ interface ByMePublicShare extends _Share { | |
| interface WithMeRegularShare extends _Share { | ||
| shareDirection: 'WITH_ME'; | ||
| shareType: 'REGULAR'; | ||
| sharedBy: string; | ||
| sharedBy: Creator; | ||
| } | ||
|
|
||
| export type Share = ByMeRegularShare | ByMePublicShare | WithMeRegularShare; | ||
|
|
@@ -116,6 +159,19 @@ export async function fetchShares(): Promise<Share[]> { | |
| ? share.share.grantee.user_id.opaque_id | ||
| : share.share.grantee.group_id.opaque_id; | ||
|
|
||
| const grantee: Grantee = | ||
| 'grantee_user_info' in share | ||
| ? { | ||
| type: 'GRANTEE_TYPE_USER', | ||
| opaqueId: sharedWithOpaqueId, | ||
| mail: share.grantee_user_info.mail, | ||
| displayName: share.grantee_user_info.display_name | ||
| } | ||
| : { | ||
| type: share.share.grantee.type, | ||
| opaqueId: sharedWithOpaqueId | ||
| }; | ||
|
|
||
| if (!byMeMerged.has(resourceId)) { | ||
| byMeMerged.set(resourceId, { | ||
| shareDirection: 'BY_ME', | ||
|
|
@@ -125,18 +181,10 @@ export async function fetchShares(): Promise<Share[]> { | |
| name: share.resource_info.name, | ||
| path: share.resource_info.path.slice('/eos'.length), // TODO: Don't hardcode this prefix | ||
| rawPath: share.resource_info.path, | ||
| sharedWith: [ | ||
| { | ||
| type: share.share.grantee.type, | ||
| opaqueId: sharedWithOpaqueId | ||
| } | ||
| ] | ||
| sharedWith: [grantee] | ||
| }); | ||
| } else { | ||
| byMeMerged.get(resourceId)?.sharedWith.push({ | ||
| type: share.share.grantee.type, | ||
| opaqueId: sharedWithOpaqueId | ||
| }); | ||
| byMeMerged.get(resourceId)?.sharedWith.push(grantee); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -168,7 +216,11 @@ export async function fetchShares(): Promise<Share[]> { | |
| name: share.resource_info.name, | ||
| path: share.resource_info.path.slice('/eos'.length), // TODO: Don't hardcode this prefix | ||
| rawPath: share.resource_info.path, | ||
| sharedBy: share.received_share.share.creator.opaque_id | ||
| sharedBy: { | ||
| opaqueId: share.received_share.share.creator.opaque_id, | ||
| mail: share.creator_user_info?.mail, | ||
| displayName: share.creator_user_info?.display_name | ||
| } | ||
| }); | ||
| } | ||
|
|
||
|
|
@@ -180,6 +232,7 @@ export interface ShareGranteeDetail { | |
| type: GranteeType; | ||
| opaqueId: string; | ||
| role: ShareRole; | ||
| displayName?: string; | ||
| } | ||
|
|
||
| export interface UserSearchResult { | ||
|
|
@@ -214,16 +267,22 @@ export async function fetchSharesForResource(rawPath: string): Promise<ShareGran | |
|
|
||
| for (const item of data.shares as RawSharedByMeRegular[]) { | ||
| const grantee = item.share.grantee; | ||
| const opaqueId = | ||
| grantee.type === 'GRANTEE_TYPE_USER' | ||
| ? grantee.user_id.opaque_id | ||
| : grantee.group_id.opaque_id; | ||
| results.push({ | ||
| const opaqueId = grantee.type === 'GRANTEE_TYPE_USER' ? grantee.user_id.opaque_id : grantee.group_id.opaque_id; | ||
|
|
||
| const detail: ShareGranteeDetail = { | ||
| shareId: item.share.id.opaque_id, | ||
| type: grantee.type, | ||
| opaqueId, | ||
| role: roleFromRawPermissions((item.share as Record<string, unknown>).permissions as Record<string, unknown> | undefined) | ||
| }); | ||
| role: roleFromRawPermissions( | ||
| (item.share as Record<string, unknown>).permissions as Record<string, unknown> | undefined | ||
| ) | ||
| }; | ||
|
|
||
| if ('grantee_user_info' in item) { | ||
| detail.displayName = item.grantee_user_info.display_name; | ||
| } | ||
|
|
||
| results.push(detail); | ||
| } | ||
|
|
||
| return results; | ||
|
|
@@ -298,7 +357,7 @@ export async function findUsers(query: string, signal?: AbortSignal): Promise<Us | |
| } | ||
|
|
||
| const data = await resp.json(); | ||
| return (data.items as Array<Record<string, unknown>>).map((u) => ({ | ||
| return (data.items as Array<Record<string, unknown>>).map(u => ({ | ||
| opaqueId: (u.id as Record<string, string>).opaque_id, | ||
| idp: (u.id as Record<string, string>).idp, | ||
| displayName: (u.display_name as string) || (u.username as string) || '', | ||
|
|
@@ -317,7 +376,7 @@ export async function findGroups(query: string, signal?: AbortSignal): Promise<G | |
| } | ||
|
|
||
| const data = await resp.json(); | ||
| return (data.items as Array<Record<string, unknown>>).map((g) => ({ | ||
| return (data.items as Array<Record<string, unknown>>).map(g => ({ | ||
| opaqueId: (g.id as Record<string, string>).opaque_id, | ||
| displayName: (g.group_name as string) || (g.id as Record<string, string>).opaque_id | ||
| })); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a formatting change