richie-education 2.25.0-b2.dev27 → 2.25.0-b2.dev31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { defineMessages } from 'react-intl';
2
2
  import { useJoanieApi } from 'contexts/JoanieApiContext';
3
3
  import { QueryOptions, useResource, useResources, UseResourcesProps } from 'hooks/useResources';
4
- import { API, Contract, ContractFilters } from 'types/Joanie';
4
+ import { API, Contract, ContractResourceQuery } from 'types/Joanie';
5
5
 
6
6
  const messages = defineMessages({
7
7
  errorGet: {
@@ -16,7 +16,7 @@ const messages = defineMessages({
16
16
  },
17
17
  });
18
18
 
19
- const props: UseResourcesProps<Contract, ContractFilters, API['user']['contracts']> = {
19
+ const props: UseResourcesProps<Contract, ContractResourceQuery, API['user']['contracts']> = {
20
20
  queryKey: ['contracts'],
21
21
  apiInterface: () => useJoanieApi().user.contracts,
22
22
  session: true,
@@ -34,7 +34,7 @@ export const useUserContracts = useResources(props);
34
34
  */
35
35
  const organizationProps: UseResourcesProps<
36
36
  Contract,
37
- ContractFilters,
37
+ ContractResourceQuery,
38
38
  API['organizations']['contracts']
39
39
  > = {
40
40
  ...props,
@@ -44,7 +44,7 @@ const organizationProps: UseResourcesProps<
44
44
 
45
45
  export const useOrganizationContract = (
46
46
  id: string,
47
- filters: ContractFilters,
47
+ filters: ContractResourceQuery,
48
48
  queryOptions?: QueryOptions<Contract>,
49
49
  ) => {
50
50
  return useResource(organizationProps)(id, filters, {
@@ -57,7 +57,7 @@ export const useOrganizationContract = (
57
57
  };
58
58
 
59
59
  export const useOrganizationContracts = (
60
- filters: ContractFilters,
60
+ filters: ContractResourceQuery,
61
61
  queryOptions?: QueryOptions<Contract>,
62
62
  ) => {
63
63
  return useResources(organizationProps)(filters, {
@@ -1,6 +1,4 @@
1
- import { useMemo } from 'react';
2
1
  import { useOrganizationContracts } from 'hooks/useContracts';
3
- import { useCourseProductRelation } from 'hooks/useCourseProductRelation';
4
2
  import { PER_PAGE } from 'settings';
5
3
  import { ContractState, CourseProductRelation, Organization } from 'types/Joanie';
6
4
 
@@ -13,30 +11,15 @@ const useTeacherPendingContractsCount = ({
13
11
  organizationId,
14
12
  courseProductRelationId,
15
13
  }: UseTeacherPendingContractsCountProps) => {
16
- const {
17
- item: training,
18
- states: { isFetched: isTrainingFetched },
19
- } = useCourseProductRelation(courseProductRelationId, {
14
+ const { items: contracts, meta } = useOrganizationContracts({
20
15
  organization_id: organizationId,
16
+ course_product_relation_id: courseProductRelationId,
17
+ signature_state: ContractState.LEARNER_SIGNED,
18
+ page: 1,
19
+ page_size: PER_PAGE.teacherContractList,
21
20
  });
22
21
 
23
- const isActive = useMemo(() => {
24
- return !!(organizationId && (!courseProductRelationId || isTrainingFetched));
25
- }, [organizationId, courseProductRelationId, isTrainingFetched]);
26
-
27
- const { items: contracts, meta } = useOrganizationContracts(
28
- {
29
- organization_id: organizationId,
30
- course_id: training?.course.id,
31
- product_id: training?.product.id,
32
- signature_state: ContractState.LEARNER_SIGNED,
33
- page: 1,
34
- page_size: PER_PAGE.teacherContractList,
35
- },
36
- { enabled: isActive },
37
- );
38
-
39
- if (isActive) {
22
+ if (organizationId) {
40
23
  return {
41
24
  contracts,
42
25
  pendingContractCount: meta?.pagination?.count ?? 0,
@@ -78,19 +78,22 @@ describe('pages/TeacherDashboardContracts', () => {
78
78
  }).many(3);
79
79
  const organization = OrganizationFactory().one();
80
80
 
81
+ // OrganizationContractFilter request all organizations forwho the user have access
81
82
  fetchMock.get(`https://joanie.test/api/v1.0/organizations/`, [organization]);
83
+ // TeacherDashboardContracts request a paginated list of contracts to display
82
84
  fetchMock.get(
83
- `https://joanie.test/api/v1.0/organizations/${organization.id}/contracts/?signature_state=signed&course_id=1&product_id=2&page=1&page_size=25`,
85
+ `https://joanie.test/api/v1.0/organizations/${organization.id}/contracts/?signature_state=signed&course_product_relation_id=2&page=1&page_size=25`,
84
86
  { results: contracts, count: 0, previous: null, next: null },
85
87
  );
88
+ // useTeacherContractsToSign request all contract to sign, without pagination
86
89
  fetchMock.get(
87
- `https://joanie.test/api/v1.0/organizations/${organization.id}/contracts/?signature_state=half_signed&course_id=1&product_id=2`,
90
+ `https://joanie.test/api/v1.0/organizations/${organization.id}/contracts/?signature_state=half_signed&course_product_relation_id=2`,
88
91
  { results: [], count: 0, previous: null, next: null },
89
92
  );
90
93
 
91
94
  render(
92
95
  <Wrapper
93
- path="/courses/:courseId/products/:productId/contracts"
96
+ path="/courses/:courseId/products/:courseProductRelationId/contracts"
94
97
  initialEntry="/courses/1/products/2/contracts"
95
98
  />,
96
99
  );
@@ -7,9 +7,9 @@ import { ContractHelper, ContractStatePoV } from 'utils/ContractHelper';
7
7
  import { useOrganizationContracts } from 'hooks/useContracts';
8
8
  import Banner, { BannerType } from 'components/Banner';
9
9
  import { PER_PAGE } from 'settings';
10
- import { ContractFilters } from 'types/Joanie';
10
+ import { ContractResourceQuery } from 'types/Joanie';
11
11
 
12
- import ContractFiltersBar from '../components/ContractFilters';
12
+ import ContractFiltersBar from '../components/ContractFiltersBar';
13
13
  import useTeacherContractFilters, {
14
14
  TeacherDashboardContractsParams,
15
15
  } from '../hooks/useTeacherContractFilters';
@@ -62,7 +62,7 @@ const TeacherDashboardContracts = () => {
62
62
  }));
63
63
  }, [contracts]);
64
64
 
65
- const handleFiltersChange = (newFilters: Partial<ContractFilters>) => {
65
+ const handleFiltersChange = (newFilters: Partial<ContractResourceQuery>) => {
66
66
  // Reset pagination
67
67
  pagination.setPage(1);
68
68
  setFilters((prevFilters) => ({ ...prevFilters, ...newFilters }));
@@ -83,8 +83,7 @@ const TeacherDashboardContracts = () => {
83
83
  <div className="dashboard__page__actions">
84
84
  <ContractActionsBar
85
85
  organizationId={filters.organization_id!}
86
- courseId={filters.course_id}
87
- productId={filters.product_id}
86
+ courseProductRelationId={filters.course_product_relation_id}
88
87
  />
89
88
  <ContractFiltersBar
90
89
  defaultValues={initialFilters}
@@ -1,18 +1,16 @@
1
- import { CourseListItem, Organization, Product } from 'types/Joanie';
1
+ import { Organization, CourseProductRelation } from 'types/Joanie';
2
2
  import useTeacherContractsToSign from 'pages/TeacherDashboardContractsLayout/hooks/useTeacherContractsToSign';
3
3
  import SignOrganizationContractButton from '../SignOrganizationContractButton';
4
4
 
5
5
  interface ContractActionsProps {
6
- courseId?: CourseListItem['id'];
7
- productId?: Product['id'];
8
6
  organizationId: Organization['id'];
7
+ courseProductRelationId?: CourseProductRelation['id'];
9
8
  }
10
9
 
11
- const ContractActionsBar = ({ courseId, productId, organizationId }: ContractActionsProps) => {
10
+ const ContractActionsBar = ({ organizationId, courseProductRelationId }: ContractActionsProps) => {
12
11
  const { canSignContracts, contractsToSignCount } = useTeacherContractsToSign({
13
12
  organizationId,
14
- courseId,
15
- productId,
13
+ courseProductRelationId,
16
14
  });
17
15
  return (
18
16
  canSignContracts && (
@@ -12,7 +12,7 @@ import { ContractState } from 'types/Joanie';
12
12
  import { OrganizationFactory } from 'utils/test/factories/joanie';
13
13
  import { expectNoSpinner } from 'utils/test/expectSpinner';
14
14
  import { noop } from 'utils';
15
- import ContractFilters from '.';
15
+ import ContractFiltersBar from '.';
16
16
 
17
17
  jest.mock('utils/context', () => ({
18
18
  __esModule: true,
@@ -22,7 +22,7 @@ jest.mock('utils/context', () => ({
22
22
  }).one(),
23
23
  }));
24
24
 
25
- describe('ContractFilters', () => {
25
+ describe('<ContractFiltersBar/>', () => {
26
26
  const Wrapper = ({ children }: PropsWithChildren) => {
27
27
  return (
28
28
  <IntlProvider locale="en">
@@ -58,7 +58,7 @@ describe('ContractFilters', () => {
58
58
 
59
59
  render(
60
60
  <Wrapper>
61
- <ContractFilters onFiltersChange={filterChange} defaultValues={defaultValues} />
61
+ <ContractFiltersBar onFiltersChange={filterChange} defaultValues={defaultValues} />
62
62
  </Wrapper>,
63
63
  );
64
64
 
@@ -105,7 +105,7 @@ describe('ContractFilters', () => {
105
105
 
106
106
  render(
107
107
  <Wrapper>
108
- <ContractFilters
108
+ <ContractFiltersBar
109
109
  onFiltersChange={noop}
110
110
  defaultValues={defaultValues}
111
111
  hideFilterSignatureState={true}
@@ -136,7 +136,7 @@ describe('ContractFilters', () => {
136
136
 
137
137
  render(
138
138
  <Wrapper>
139
- <ContractFilters
139
+ <ContractFiltersBar
140
140
  onFiltersChange={noop}
141
141
  defaultValues={defaultValues}
142
142
  hideFilterOrganization={true}
@@ -165,7 +165,7 @@ describe('ContractFilters', () => {
165
165
 
166
166
  render(
167
167
  <Wrapper>
168
- <ContractFilters onFiltersChange={handleChange} />
168
+ <ContractFiltersBar onFiltersChange={handleChange} />
169
169
  </Wrapper>,
170
170
  );
171
171
 
@@ -24,7 +24,7 @@ export interface ContractListFilters {
24
24
  signature_state?: ContractState;
25
25
  }
26
26
 
27
- interface ContractFiltersProps {
27
+ interface ContractFiltersBarProps {
28
28
  onFiltersChange: (filters: Partial<ContractListFilters>) => void;
29
29
  defaultValues?: ContractListFilters;
30
30
  hideFilterOrganization?: boolean;
@@ -36,12 +36,12 @@ interface FilterProps {
36
36
  onChange: (value: Partial<ContractListFilters>) => void;
37
37
  }
38
38
 
39
- const ContractFilters = ({
39
+ const ContractFiltersBar = ({
40
40
  defaultValues,
41
41
  onFiltersChange,
42
42
  hideFilterOrganization = false,
43
43
  hideFilterSignatureState = false,
44
- }: ContractFiltersProps) => {
44
+ }: ContractFiltersBarProps) => {
45
45
  return (
46
46
  <div className="dashboard__page__actions-row dashboard__page__actions-row--end">
47
47
  {!hideFilterOrganization && (
@@ -122,4 +122,4 @@ const SignatureStateFilter = ({ defaultValue, onChange }: FilterProps) => {
122
122
  );
123
123
  };
124
124
 
125
- export default ContractFilters;
125
+ export default ContractFiltersBar;
@@ -1,15 +1,14 @@
1
1
  import { useMemo, useState } from 'react';
2
2
  import { useParams, useSearchParams } from 'react-router-dom';
3
- import { ContractFilters, ContractState } from 'types/Joanie';
3
+ import { ContractResourceQuery, ContractState } from 'types/Joanie';
4
4
 
5
5
  export type TeacherDashboardContractsParams = {
6
6
  organizationId?: string;
7
- courseId?: string;
8
- productId?: string;
7
+ courseProductRelationId?: string;
9
8
  };
10
9
 
11
10
  const useTeacherContractFilters = () => {
12
- const { courseId, organizationId, productId } = useParams<TeacherDashboardContractsParams>();
11
+ const { organizationId, courseProductRelationId } = useParams<TeacherDashboardContractsParams>();
13
12
  const [searchParams] = useSearchParams();
14
13
 
15
14
  const initialFilters = useMemo(
@@ -17,12 +16,11 @@ const useTeacherContractFilters = () => {
17
16
  signature_state:
18
17
  (searchParams.get('signature_state') as ContractState) || ContractState.SIGNED,
19
18
  organization_id: organizationId,
20
- course_id: courseId,
21
- product_id: productId,
19
+ course_product_relation_id: courseProductRelationId,
22
20
  }),
23
21
  [],
24
22
  );
25
- const [filters, setFilters] = useState<ContractFilters>(initialFilters);
23
+ const [filters, setFilters] = useState<ContractResourceQuery>(initialFilters);
26
24
 
27
25
  return { initialFilters, filters, setFilters };
28
26
  };
@@ -1,25 +1,25 @@
1
1
  import useContractAbilities from 'hooks/useContractAbilities';
2
2
  import { useOrganizationContracts } from 'hooks/useContracts';
3
- import { ContractState, CourseListItem, Organization, Product } from 'types/Joanie';
3
+ import { ContractState, Organization, CourseProductRelation } from 'types/Joanie';
4
4
  import { ContractActions } from 'utils/AbilitiesHelper/types';
5
5
 
6
6
  interface UseTeacherContractsToSignProps {
7
- courseId?: CourseListItem['id'];
8
- productId?: Product['id'];
9
7
  organizationId?: Organization['id'];
8
+ courseProductRelationId?: CourseProductRelation['id'];
10
9
  }
11
10
 
12
11
  const useTeacherContractsToSign = ({
13
- courseId,
14
- productId,
15
12
  organizationId,
13
+ courseProductRelationId,
16
14
  }: UseTeacherContractsToSignProps) => {
17
- const { items: contractsToSign, meta: contractsToSignMeta } = useOrganizationContracts({
18
- signature_state: ContractState.LEARNER_SIGNED,
19
- organization_id: organizationId,
20
- course_id: courseId,
21
- product_id: productId,
22
- });
15
+ const { items: contractsToSign, meta: contractsToSignMeta } = useOrganizationContracts(
16
+ {
17
+ signature_state: ContractState.LEARNER_SIGNED,
18
+ organization_id: organizationId,
19
+ course_product_relation_id: courseProductRelationId,
20
+ },
21
+ { enabled: !!organizationId },
22
+ );
23
23
  const contractAbilities = useContractAbilities(contractsToSign);
24
24
  const contractsToSignCount = contractsToSignMeta?.pagination?.count ?? 0;
25
25
 
@@ -427,10 +427,9 @@ export enum ContractState {
427
427
  LEARNER_SIGNED = 'half_signed',
428
428
  SIGNED = 'signed',
429
429
  }
430
- export interface ContractFilters extends PaginatedResourceQuery {
430
+ export interface ContractResourceQuery extends PaginatedResourceQuery {
431
431
  organization_id?: Organization['id'];
432
- course_id?: CourseListItem['id'];
433
- product_id?: Product['id'];
432
+ course_product_relation_id?: CourseProductRelation['id'];
434
433
  contract_ids?: Contract['id'][];
435
434
  signature_state?: ContractState;
436
435
  }
@@ -516,8 +515,8 @@ interface APIUser {
516
515
  };
517
516
  contracts: {
518
517
  get(
519
- filters?: ContractFilters,
520
- ): ContractFilters extends { id: string }
518
+ filters?: ContractResourceQuery,
519
+ ): ContractResourceQuery extends { id: string }
521
520
  ? Promise<Nullable<Contract>>
522
521
  : Promise<PaginatedResponse<Contract>>;
523
522
  download(id: string): Promise<File>;
@@ -542,8 +541,8 @@ export interface API {
542
541
  ): Filters extends { id: string } ? Promise<Nullable<Organization>> : Promise<Organization[]>;
543
542
  contracts: {
544
543
  get(
545
- filters?: ContractFilters,
546
- ): ContractFilters extends { id: string }
544
+ filters?: ContractResourceQuery,
545
+ ): ContractResourceQuery extends { id: string }
547
546
  ? Promise<Nullable<Contract>>
548
547
  : Promise<PaginatedResponse<Contract>>;
549
548
  getSignatureLinks(
@@ -33,9 +33,9 @@ export const TeacherDashboardOrganizationSidebar = () => {
33
33
  const intl = useIntl();
34
34
  const getRoutePath = getDashboardRoutePath(intl);
35
35
  const getRouteLabel = getDashboardRouteLabel(intl);
36
- const { organizationId, productId: courseProductRelationId } = useParams<{
36
+ const { organizationId, courseProductRelationId } = useParams<{
37
37
  organizationId: string;
38
- productId?: string;
38
+ courseProductRelationId?: string;
39
39
  }>();
40
40
  const {
41
41
  item: organization,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "richie-education",
3
- "version": "2.25.0-b2.dev27",
3
+ "version": "2.25.0-b2.dev31",
4
4
  "description": "A CMS to build learning portals for Open Education",
5
5
  "main": "sandbox/manage.py",
6
6
  "scripts": {