Gestion des autorisations côté serveur #20
|
@ -26,8 +26,7 @@ export function DecisionSupportFilePanel() {
|
||||||
itemFilter: (item: Item) => (item as DecisionSupportFile).status === DecisionSupportFileStatus.Closed
|
itemFilter: (item: Item) => (item as DecisionSupportFile).status === DecisionSupportFileStatus.Closed
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ItemPanel
|
<ItemPanel
|
||||||
className='is-link'
|
className='is-link'
|
||||||
|
|
|
@ -11,8 +11,6 @@ export interface TabDefinition {
|
||||||
label: string
|
label: string
|
||||||
itemFilter?: (item: Item) => boolean
|
itemFilter?: (item: Item) => boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface ItemPanelProps {
|
export interface ItemPanelProps {
|
||||||
className?: string
|
className?: string
|
||||||
itemIconClassName?: string
|
itemIconClassName?: string
|
||||||
|
@ -30,9 +28,12 @@ export const ItemPanel: FunctionComponent<ItemPanelProps> = (props) => {
|
||||||
const {
|
const {
|
||||||
title, className, newItemUrl,
|
title, className, newItemUrl,
|
||||||
itemKey, itemLabel,
|
itemKey, itemLabel,
|
||||||
itemIconClassName, itemUrl
|
itemIconClassName, itemUrl,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const items = props.items || [];
|
||||||
|
const tabs = props.tabs || [];
|
||||||
|
|
||||||
const [ state, setState ] = useState({ selectedTab: 0, filteredItems: [] });
|
const [ state, setState ] = useState({ selectedTab: 0, filteredItems: [] });
|
||||||
|
|
||||||
const filterItemsForTab = (tab: TabDefinition, items: Item[]) => {
|
const filterItemsForTab = (tab: TabDefinition, items: Item[]) => {
|
||||||
|
@ -42,7 +43,6 @@ export const ItemPanel: FunctionComponent<ItemPanelProps> = (props) => {
|
||||||
|
|
||||||
const selectTab = (tabIndex: number) => {
|
const selectTab = (tabIndex: number) => {
|
||||||
setState(state => {
|
setState(state => {
|
||||||
const { tabs, items } = props;
|
|
||||||
const newTab = Array.isArray(tabs) && tabs.length > 0 ? tabs[tabIndex] : null;
|
const newTab = Array.isArray(tabs) && tabs.length > 0 ? tabs[tabIndex] : null;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -61,7 +61,7 @@ export const ItemPanel: FunctionComponent<ItemPanelProps> = (props) => {
|
||||||
filteredItems: filterItemsForTab(newTab, items),
|
filteredItems: filterItemsForTab(newTab, items),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [props.items, props.tabs]);
|
}, [items, tabs]);
|
||||||
|
|
||||||
const itemElements = state.filteredItems.map((item: Item, i: number) => {
|
const itemElements = state.filteredItems.map((item: Item, i: number) => {
|
||||||
return (
|
return (
|
||||||
|
@ -74,8 +74,6 @@ export const ItemPanel: FunctionComponent<ItemPanelProps> = (props) => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabs = props.tabs || [];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className={`panel ${className}`}>
|
<nav className={`panel ${className}`}>
|
||||||
<div className="level is-mobile panel-heading mb-0">
|
<div className="level is-mobile panel-heading mb-0">
|
||||||
|
|
|
@ -2,8 +2,8 @@ import React, { useEffect, useState, Fragment } from 'react';
|
||||||
import { Page } from '../Page';
|
import { Page } from '../Page';
|
||||||
import { WithLoader } from '../WithLoader';
|
import { WithLoader } from '../WithLoader';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
import { useWorkgroupsQuery } from '../../gql/queries/workgroups';
|
import { useWorkgroupsQuery, useWorkgroups } from '../../gql/queries/workgroups';
|
||||||
import { useUserProfileQuery } from '../../gql/queries/profile';
|
import { useUserProfileQuery, useUserProfile } from '../../gql/queries/profile';
|
||||||
import { MembersPanel } from './MembersPanel';
|
import { MembersPanel } from './MembersPanel';
|
||||||
import { User } from '../../types/user';
|
import { User } from '../../types/user';
|
||||||
import { InfoPanel } from './InfoPanel';
|
import { InfoPanel } from './InfoPanel';
|
||||||
|
@ -12,18 +12,18 @@ import { useJoinWorkgroupMutation, useLeaveWorkgroupMutation, useCloseWorkgroupM
|
||||||
|
|
||||||
export function WorkgroupPage() {
|
export function WorkgroupPage() {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const workgroupsQuery = useWorkgroupsQuery({
|
const { workgroups } = useWorkgroups({
|
||||||
variables:{
|
variables:{
|
||||||
filter: {
|
filter: {
|
||||||
ids: [id],
|
ids: [id],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const userProfileQuery = useUserProfileQuery();
|
const { user } = useUserProfile();
|
||||||
|
|
||||||
const [ joinWorkgroup, joinWorkgroupMutation ] = useJoinWorkgroupMutation();
|
const [ joinWorkgroup ] = useJoinWorkgroupMutation();
|
||||||
const [ leaveWorkgroup, leaveWorkgroupMutation ] = useLeaveWorkgroupMutation();
|
const [ leaveWorkgroup ] = useLeaveWorkgroupMutation();
|
||||||
const [ closeWorkgroup, closeWorkgroupMutation ] = useCloseWorkgroupMutation();
|
const [ closeWorkgroup ] = useCloseWorkgroupMutation();
|
||||||
|
|
||||||
const [ state, setState ] = useState({
|
const [ state, setState ] = useState({
|
||||||
userProfileId: '',
|
userProfileId: '',
|
||||||
|
@ -37,14 +37,12 @@ export function WorkgroupPage() {
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!workgroupsQuery.data) return;
|
setState(state => ({...state, workgroup:{ ...state.workgroup, ...workgroups[0]}}));
|
||||||
setState(state => ({...state, workgroup:{ ...state.workgroup, ...workgroupsQuery.data.workgroups[0]}}));
|
}, [workgroups]);
|
||||||
}, [workgroupsQuery.data]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!userProfileQuery.data) return;
|
setState(state => ({...state, userProfileId: user.id }));
|
||||||
setState(state => ({...state, userProfileId: userProfileQuery.data.userProfile.id }));
|
}, [user]);
|
||||||
}, [userProfileQuery.data]);
|
|
||||||
|
|
||||||
const onJoinWorkgroupClick = () => {
|
const onJoinWorkgroupClick = () => {
|
||||||
joinWorkgroup({
|
joinWorkgroup({
|
||||||
|
@ -56,6 +54,18 @@ export function WorkgroupPage() {
|
||||||
|
|
||||||
const onLeaveWorkgroupClick = () => {
|
const onLeaveWorkgroupClick = () => {
|
||||||
leaveWorkgroup({
|
leaveWorkgroup({
|
||||||
|
update: (cache, result) => {
|
||||||
|
cache.modify({
|
||||||
|
id: cache.identify(result.data.leaveWorkgroup),
|
||||||
|
fields: {
|
||||||
|
members(existingMembers, { readField }) {
|
||||||
|
return existingMembers.filter(
|
||||||
|
user => state.userProfileId !== readField('id', user)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
variables: {
|
variables: {
|
||||||
workgroupId: state.workgroup.id,
|
workgroupId: state.workgroup.id,
|
||||||
}
|
}
|
||||||
|
@ -123,16 +133,14 @@ export function WorkgroupPage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<WithLoader loading={[workgroupsQuery.loading, userProfileQuery.loading, joinWorkgroupMutation.loading, leaveWorkgroupMutation.loading]}>
|
<div className="columns">
|
||||||
<div className="columns">
|
<div className="column">
|
||||||
<div className="column">
|
<InfoPanel workgroup={state.workgroup as Workgroup} />
|
||||||
<InfoPanel workgroup={state.workgroup as Workgroup} />
|
|
||||||
</div>
|
|
||||||
<div className="column">
|
|
||||||
<MembersPanel users={state.workgroup.members as User[]} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</WithLoader>
|
<div className="column">
|
||||||
|
<MembersPanel users={state.workgroup.members as User[]} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
|
@ -34,7 +34,6 @@ export const client = new ApolloClient<any>({
|
||||||
|
|
||||||
function mergeArrayByField<T>(fieldName: string) {
|
function mergeArrayByField<T>(fieldName: string) {
|
||||||
return (existing: T[] = [], incoming: T[], { readField, mergeObjects }) => {
|
return (existing: T[] = [], incoming: T[], { readField, mergeObjects }) => {
|
||||||
if (incoming.length === 0) return [];
|
|
||||||
|
|
||||||
const merged: any[] = existing ? existing.slice(0) : [];
|
const merged: any[] = existing ? existing.slice(0) : [];
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,16 @@ mutation createDecisionSupportFile($changes: DecisionSupportFileChanges!) {
|
||||||
status,
|
status,
|
||||||
sections,
|
sections,
|
||||||
createdAt,
|
createdAt,
|
||||||
updatedAt
|
updatedAt,
|
||||||
|
workgroup {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
members {
|
||||||
|
id,
|
||||||
|
email,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
@ -27,7 +36,16 @@ mutation updateDecisionSupportFile($id: ID!, $changes: DecisionSupportFileChange
|
||||||
status,
|
status,
|
||||||
sections,
|
sections,
|
||||||
createdAt,
|
createdAt,
|
||||||
updatedAt
|
updatedAt,
|
||||||
|
workgroup {
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
members {
|
||||||
|
id,
|
||||||
|
email,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,9 @@ export const QUERY_DECISION_SUPPORT_FILES = gql`
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
members {
|
members {
|
||||||
id
|
id,
|
||||||
|
email,
|
||||||
|
name
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ func (r *WorkgroupRepository) CreateWorkgroup(ctx context.Context, changes Workg
|
||||||
Name: changes.Name,
|
Name: changes.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.db.Model(&Workgroup{}).Create(workgroup).Error; err != nil {
|
if err := r.db.Model(&Workgroup{}).Preload("Members").Create(workgroup).Error; err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ func (r *WorkgroupRepository) RemoveUserFromWorkgroup(ctx context.Context, userI
|
||||||
|
|
||||||
func (r *WorkgroupRepository) Find(ctx context.Context, id string) (*Workgroup, error) {
|
func (r *WorkgroupRepository) Find(ctx context.Context, id string) (*Workgroup, error) {
|
||||||
wg := &Workgroup{}
|
wg := &Workgroup{}
|
||||||
query := r.db.Model(wg).Where("id = ?", id)
|
query := r.db.Model(wg).Preload("Members").Where("id = ?", id)
|
||||||
|
|
||||||
if err := query.First(&wg).Error; err != nil {
|
if err := query.First(&wg).Error; err != nil {
|
||||||
return nil, errs.WithStack(err)
|
return nil, errs.WithStack(err)
|
||||||
|
|
Loading…
Reference in New Issue