Skip to content
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

refactor: Link landscapes directly to shared files, links and visualizations #1229

Merged
merged 14 commits into from
Oct 24, 2023
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"slate-history": "^0.100.0",
"slate-hyperscript": "^0.100.0",
"slate-react": "^0.100.0",
"terraso-client-shared": "github:techmatters/terraso-client-shared#5e56086",
"terraso-client-shared": "github:techmatters/terraso-client-shared#d577669",
"use-debounce": "^9.0.4",
"uuid": "^9.0.1",
"web-vitals": "^3.5.0",
Expand Down
7 changes: 5 additions & 2 deletions src/group/components/GroupSharedDataUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,12 @@ const GroupSharedDataUpload = () => {
<PageHeader
header={t('group.shared_data_upload_title', { name: group.name })}
/>
<GroupContextProvider group={group} owner={group}>
<GroupContextProvider owner={group}>
<SharedDataUpload
groupSlug={slug}
targetInput={{
targetType: 'group',
targetSlug: slug,
}}
onCancel={onCancel}
onCompleteSuccess={onCompleteSuccess}
/>
Expand Down
4 changes: 4 additions & 0 deletions src/group/components/GroupSharedDataUploadFiles.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ test('GroupSharedDataUpload: Complete Success', async () => {
await waitFor(() => expect(uploadButton).not.toHaveAttribute('disabled'));
await act(async () => fireEvent.click(uploadButton));
expect(navigate.mock.calls[0]).toEqual(['/groups/slug-1']);

const saveCall = terrasoApi.request.mock.calls[0];
expect(saveCall[0].body.get('target_type')).toBe('group');
expect(saveCall[0].body.get('target_slug')).toBe('slug-1');
});

test('GroupSharedDataUpload: PDF Success', async () => {
Expand Down
40 changes: 38 additions & 2 deletions src/group/components/GroupView.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import { render, screen } from 'tests/utils';
import { render, screen, within } from 'tests/utils';
import React from 'react';
import { useParams } from 'react-router-dom';
import * as terrasoApi from 'terraso-client-shared/terrasoApi/api';
Expand Down Expand Up @@ -98,6 +98,29 @@ test('GroupView: Display data', async () => {
},
})),
};
const accountMembership = {
id: 'user-id',
userRole: 'MEMBER',
membershipStatus: 'APPROVED',
};
const sharedResources = {
edges: Array(6)
.fill(0)
.map((item, index) => ({
node: {
source: {
id: `de-${index}`,
createdAt: '2022-05-20T16:25:21.536679+00:00',
name: `Data Entry ${index}`,
createdBy: { id: 'user-id', firstName: 'First', lastName: 'Last' },
description: `Description ${index}`,
size: 3456,
entryType: 'FILE',
visualizations: { edges: [] },
},
},
})),
};
terrasoApi.requestGraphQL.mockReturnValue(
Promise.resolve({
groups: {
Expand All @@ -109,6 +132,8 @@ test('GroupView: Display data', async () => {
website: 'https://www.group.org',
email: '[email protected]',
memberships,
accountMembership,
sharedResources,
},
},
],
Expand All @@ -135,6 +160,17 @@ test('GroupView: Display data', async () => {
).toBeInTheDocument();
expect(screen.getByText(/\+2/i)).toBeInTheDocument();
expect(
screen.getByRole('button', { name: 'Join Group' })
screen.getByRole('button', { name: 'Leave: Group name' })
).toBeInTheDocument();

// Shared Data
const sharedDataRegion = within(
screen.getByRole('region', { name: 'Shared files and Links' })
);
expect(
sharedDataRegion.getByRole('heading', { name: 'Shared files and Links' })
).toBeInTheDocument();
const entriesList = within(sharedDataRegion.getByRole('list'));
const items = entriesList.getAllByRole('listitem');
expect(items.length).toBe(6);
});
14 changes: 9 additions & 5 deletions src/group/groupFragments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,17 @@ export const groupsListFields = /* GraphQL */ `
}
`;

export const dataEntries = /* GraphQL */ `
fragment dataEntries on GroupNode {
dataEntries(resourceType_In: $resourceTypes) {
export const groupDataEntries = /* GraphQL */ `
fragment groupDataEntries on GroupNode {
sharedResources {
edges {
node {
...dataEntry
...dataEntryVisualizations
source {
... on DataEntryNode {
...dataEntry
...dataEntryVisualizations
}
}
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/group/groupService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
import * as terrasoApi from 'terraso-client-shared/terrasoApi/api';
import { graphql } from 'terrasoApi/shared/graphqlSchema';

import { extractDataEntries } from 'sharedData/sharedDataUtils';

import type { Group } from './groupSlice';

export const fetchGroupToUpdate = (slug: string) => {
Expand Down Expand Up @@ -54,18 +56,22 @@ export const fetchGroupToView = async (slug: string) => {
...groupMembersInfo
...groupMembersPending
...accountMembership
...groupDataEntries
}
}
}
}
`);
return terrasoApi
.requestGraphQL(query, { slug })
.requestGraphQL(query, {
slug,
})
.then(resp => resp.groups?.edges.at(0)?.node || Promise.reject('not_found'))
.then(group => ({
..._.omit(['memberships', 'membershipsCount'], group),
membersInfo: extractMembersInfo(group),
accountMembership: extractAccountMembership(group),
dataEntries: extractDataEntries(group),
}));
};

Expand Down
2 changes: 2 additions & 0 deletions src/group/groupSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import type { Message } from 'terraso-client-shared/notifications/notificationsS
import { createAsyncThunk } from 'terraso-client-shared/store/utils';

import * as groupService from 'group/groupService';
import { setList } from 'sharedData/sharedDataSlice';

export type Group = {
slug: string;
Expand All @@ -45,6 +46,7 @@ export const fetchGroupView = createAsyncThunk(
async (slug: string, user, { dispatch }) => {
const group = await groupService.fetchGroupToView(slug);
dispatch(setMemberships(getMemberships([group])));
dispatch(setList(group.dataEntries));
return group;
}
);
Expand Down
8 changes: 5 additions & 3 deletions src/landscape/components/LandscapeSharedDataUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import React, { useCallback, useEffect, useMemo } from 'react';
import _ from 'lodash/fp';
import { usePermissionRedirect } from 'permissions';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
Expand Down Expand Up @@ -85,11 +84,14 @@ const LandscapeSharedDataUpload = () => {
name: landscape.name,
})}
/>
<GroupContextProvider group={landscape.defaultGroup} owner={landscape}>
<GroupContextProvider owner={landscape}>
<SharedDataUpload
groupSlug={_.get('defaultGroup.slug', landscape)}
onCancel={onCancel}
onCompleteSuccess={onCompleteSuccess}
targetInput={{
targetType: 'landscape',
targetSlug: slug,
}}
/>
</GroupContextProvider>
</PageContainer>
Expand Down
13 changes: 13 additions & 0 deletions src/landscape/components/LandscapeSharedDataUploadLinks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,17 @@ test('LandscapeSharedDataUpload: Complete Success', async () => {
search: 'scrollTo=shared-data-card-title',
},
]);
expect(terrasoApi.requestGraphQL).toHaveBeenCalledTimes(3);
const saveCall = terrasoApi.requestGraphQL.mock.calls[2];
expect(saveCall[1]).toStrictEqual({
input: {
description: '',
entryType: 'link',
targetType: 'landscape',
targetSlug: 'slug-1',
name: 'name 1',
resourceType: 'link',
url: 'https://test1.com',
},
});
});
3 changes: 1 addition & 2 deletions src/landscape/components/LandscapeSharedDataVisualization.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,9 @@ const LandscapeSharedDataVisualization = () => {
}

return (
<GroupContextProvider group={landscape.defaultGroup} owner={landscape}>
<GroupContextProvider owner={landscape}>
<VisualizationWrapper
configSlug={configSlug}
groupSlug={landscape.defaultGroup.slug}
onDeleted={() => navigate(`/landscapes/${landscapeSlug}`)}
/>
</GroupContextProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,13 @@ test('LandscapeSharedDataVisualization: Display visualization', async () => {
expect(domElement.querySelector('p').textContent).toEqual(
'Custom Label: val11'
);

// Validate api call input to fetch visualization config
// It should contain the owner slug and type
const fetchCall = terrasoApi.requestGraphQL.mock.calls[3];
expect(fetchCall[1]).toStrictEqual({
configSlug: 'config-slug',
ownerSlug: 'jose-landscape-deafult-test-4',
ownerType: 'landscape',
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const LandscapeSharedDataVisualizationConfig = () => {

return (
<PageContainer>
<GroupContextProvider group={landscape.defaultGroup} owner={landscape}>
<GroupContextProvider owner={landscape}>
<VisualizationConfigForm
onCompleteSuccess={onCompleteSuccess}
onCancel={onCancel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,33 +255,25 @@ test('LandscapeSharedDataVisualizationConfig: Create visualization', async () =>
},
});
}
if (trimmedQuery.startsWith('query group')) {
if (trimmedQuery.startsWith('query dataEntries')) {
return Promise.resolve({
groups: {
dataEntries: {
edges: [
{
node: {
dataEntries: {
edges: [
{
node: {
createdAt: '2022-05-17T23:32:50.606587+00:00',
createdBy: {
id: 'dc695d00-d6b4-45b2-ab8d-f48206d998da',
lastName: 'Buitrón',
firstName: 'José',
},
description: '',
id: 'f00c5564-cf93-471a-94c2-b930cbb0a4f8',
name: 'File 1',
resourceType: 'text/csv',
size: 3565,
url: 'https://file-url',
visualizations: { edges: [] },
},
},
],
createdAt: '2022-05-17T23:32:50.606587+00:00',
createdBy: {
id: 'dc695d00-d6b4-45b2-ab8d-f48206d998da',
lastName: 'Buitrón',
firstName: 'José',
},
description: '',
id: 'f00c5564-cf93-471a-94c2-b930cbb0a4f8',
name: 'File 1',
resourceType: 'text/csv',
size: 3565,
url: 'https://file-url',
visualizations: { edges: [] },
},
},
],
Expand Down Expand Up @@ -327,6 +319,14 @@ test('LandscapeSharedDataVisualizationConfig: Create visualization', async () =>
await testAnnotateStep();
await testPreviewStep(map, events);

// Fetch data entries validation
const fetchCall = terrasoApi.requestGraphQL.mock.calls[3];
expect(fetchCall[1]).toStrictEqual({
resourceTypes: ['csv', 'xls', 'xlsx'],
slug: 'landscape-slug',
type: 'landscape',
});

// Save
await act(async () =>
fireEvent.click(screen.getByRole('button', { name: 'Publish' }))
Expand All @@ -335,7 +335,8 @@ test('LandscapeSharedDataVisualizationConfig: Create visualization', async () =>
const saveCall = terrasoApi.requestGraphQL.mock.calls[4];
expect(saveCall[1]).toStrictEqual({
input: {
groupId: '6a625efb-4ec8-45e8-ad6a-eb052cc3fe65',
ownerId: 'e9a65bef-4ef1-4058-bba3-fc73b53eb779',
ownerType: 'landscape',
title: 'Test Title',
configuration: JSON.stringify({
datasetConfig: {
Expand Down
Loading