Skip to content
This repository has been archived by the owner on Jan 23, 2025. It is now read-only.

fix: some loaders to display data first and pagination bugs #967

Merged
merged 3 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions cypress/e2e/item/copy/listCopyItem.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ const copyItem = ({
toItemPath: string;
rootId?: string;
}) => {
const menuSelector = `#${buildItemMenuButtonId(id)}`;
cy.get(menuSelector).click();
cy.get(`#${buildItemMenuButtonId(id)}`).click();
cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_COPY_BUTTON_CLASS}`).click();
cy.fillTreeModal(toItemPath, rootId);
};
Expand Down
3 changes: 1 addition & 2 deletions cypress/e2e/item/delete/listRecycleItem.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { ITEM_LAYOUT_MODES } from '../../../../src/enums';
import { SAMPLE_ITEMS } from '../../../fixtures/items';

const recycleItem = (id: string) => {
const menuSelector = `#${buildItemMenuButtonId(id)}`;
cy.get(menuSelector).click();
cy.get(`#${buildItemMenuButtonId(id)}`).click();
cy.get(`#${buildItemMenu(id)} .${ITEM_MENU_RECYCLE_BUTTON_CLASS}`).click();
};

Expand Down
21 changes: 19 additions & 2 deletions cypress/e2e/item/pin/pinItem.cy.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,34 @@
import { HOME_PATH } from '../../../../src/config/paths';
import { HOME_PATH, buildItemPath } from '../../../../src/config/paths';
import {
PIN_ITEM_BUTTON_CLASS,
buildDownloadButtonId,
buildItemMenu,
buildItemMenuButtonId,
} from '../../../../src/config/selectors';
import { ITEM_LAYOUT_MODES } from '../../../../src/enums';
import { ITEMS_SETTINGS, PINNED_ITEM } from '../../../fixtures/items';
import {
ITEMS_SETTINGS,
PINNED_ITEM,
PUBLISHED_ITEM,
} from '../../../fixtures/items';

const togglePinButton = (itemId: string) => {
cy.get(`#${buildItemMenuButtonId(itemId)}`).click();
cy.get(`#${buildItemMenu(itemId)} .${PIN_ITEM_BUTTON_CLASS}`).click();
};

describe('Anonymous', () => {
const itemId = PUBLISHED_ITEM.id;
beforeEach(() => {
cy.setUpApi({ currentMember: null, items: [PUBLISHED_ITEM] });
cy.visit(buildItemPath(itemId));
});
it("Can see item but can't pin", () => {
cy.get(`#${buildDownloadButtonId(itemId)}`).should('be.visible');
cy.get(`#${buildItemMenuButtonId(itemId)}`).should('not.exist');
});
});

describe('Pinning Item', () => {
describe('Successfully pinning item in List', () => {
beforeEach(() => {
Expand Down
9 changes: 1 addition & 8 deletions cypress/support/commands/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,19 @@ import {
buildItemLink,
buildItemsTableRowIdAttribute,
} from '../../../src/config/selectors';
import { NAVIGATE_PAUSE, WAIT_FOR_ITEM_TABLE_ROW_TIME } from '../constants';

Cypress.Commands.add('goToItemInGrid', (id) => {
cy.wait(NAVIGATE_PAUSE);
cy.get(`#${buildItemLink(id)}`).click();
});

Cypress.Commands.add('goToItemInList', (id) => {
cy.wait(NAVIGATE_PAUSE);
cy.get(buildItemsTableRowIdAttribute(id), {
timeout: WAIT_FOR_ITEM_TABLE_ROW_TIME,
}).click();
cy.get(buildItemsTableRowIdAttribute(id)).click();
});

Cypress.Commands.add('goToHome', () => {
cy.wait(NAVIGATE_PAUSE);
cy.get(`#${NAVIGATION_HOME_LINK_ID}`).click();
});

Cypress.Commands.add('goToItemWithNavigation', (id) => {
cy.wait(NAVIGATE_PAUSE);
cy.get(`[href="${buildItemPath(id)}"]`).click();
});
30 changes: 17 additions & 13 deletions src/components/item/ItemContent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Container, styled } from '@mui/material';
import { Container, Skeleton, styled } from '@mui/material';

import { Api } from '@graasp/query-client';
import {
Expand Down Expand Up @@ -66,27 +66,31 @@ const FileContent = ({
item,
}: {
item: LocalFileItemType | S3FileItemType;
}): JSX.Element => {
}): JSX.Element | null => {
const { data: fileUrl, isLoading, isError } = useFileContentUrl(item.id);

if (fileUrl) {
return (
<StyledContainer>
<FileItem
fileUrl={fileUrl}
id={buildFileItemId(item.id)}
item={item}
pdfViewerLink={buildPdfViewerLink(GRAASP_ASSETS_URL)}
/>
</StyledContainer>
);
}

if (isLoading) {
return <Loader />;
return <Skeleton height="50vh" />;
}

if (isError) {
return <ErrorAlert id={ITEM_SCREEN_ERROR_ALERT_ID} />;
}

return (
<StyledContainer>
<FileItem
fileUrl={fileUrl}
id={buildFileItemId(item.id)}
item={item}
pdfViewerLink={buildPdfViewerLink(GRAASP_ASSETS_URL)}
/>
</StyledContainer>
);
return null;
};

/**
Expand Down
47 changes: 13 additions & 34 deletions src/components/item/header/ItemHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,25 @@
import Stack from '@mui/material/Stack';

import { Loader, useShortenURLParams } from '@graasp/ui';

import { ITEM_ID_PARAMS } from '@/config/paths';

import { hooks } from '../../../config/queryClient';
import { ITEM_HEADER_ID } from '../../../config/selectors';
import ErrorAlert from '../../common/ErrorAlert';
import Navigation from '../../layout/Navigation';
import ItemHeaderActions from './ItemHeaderActions';

const { useItem } = hooks;

type Props = {
showNavigation?: boolean;
};

const ItemHeader = ({ showNavigation = true }: Props): JSX.Element => {
const itemId = useShortenURLParams(ITEM_ID_PARAMS);
const { data: item, isLoading: isItemLoading, isError } = useItem(itemId);

if (isItemLoading) {
return <Loader />;
}

if (isError) {
return <ErrorAlert />;
}

return (
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
mb={1}
id={ITEM_HEADER_ID}
>
{/* display empty div to render actions on the right */}
{showNavigation ? <Navigation /> : <div />}
<ItemHeaderActions item={item} />
</Stack>
);
};
const ItemHeader = ({ showNavigation = true }: Props): JSX.Element | null => (
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
mb={1}
id={ITEM_HEADER_ID}
>
{/* display empty div to render actions on the right */}
{showNavigation ? <Navigation /> : <div />}
<ItemHeaderActions />
</Stack>
);

export default ItemHeader;
22 changes: 13 additions & 9 deletions src/components/item/header/ItemHeaderActions.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Stack } from '@mui/material';

import { DiscriminatedItem, ItemType, PermissionLevel } from '@graasp/sdk';
import { ChatboxButton } from '@graasp/ui';
import { ItemType, PermissionLevel } from '@graasp/sdk';
import { ChatboxButton, useShortenURLParams } from '@graasp/ui';

import EditButton from '@/components/common/EditButton';
import DownloadButton from '@/components/main/DownloadButton';
import { ITEM_ID_PARAMS } from '@/config/paths';

import { ITEM_TYPES_WITH_CAPTIONS } from '../../../config/constants';
import { useBuilderTranslation } from '../../../config/i18n';
Expand All @@ -25,13 +26,10 @@ import ItemMenu from '../../main/ItemMenu';
import ItemSettingsButton from '../settings/ItemSettingsButton';
import ModeButton from './ModeButton';

const { useItemMemberships } = hooks;
const { useItemMemberships, useItem } = hooks;

type Props = {
item?: DiscriminatedItem;
};

const ItemHeaderActions = ({ item }: Props): JSX.Element => {
const ItemHeaderActions = (): JSX.Element => {
const itemId = useShortenURLParams(ITEM_ID_PARAMS);
const { t: translateBuilder } = useBuilderTranslation();
const {
editingItemId,
Expand All @@ -42,6 +40,7 @@ const ItemHeaderActions = ({ item }: Props): JSX.Element => {
} = useLayoutContext();

const { data: member } = useCurrentUserContext();
const { data: item } = useItem(itemId);

const { data: memberships } = useItemMemberships(item?.id);
const canEdit = isItemUpdateAllowedForUser({
Expand Down Expand Up @@ -73,7 +72,12 @@ const ItemHeaderActions = ({ item }: Props): JSX.Element => {
<>
{showEditButton && <EditButton item={item} />}
{/* prevent moving from top header to avoid confusion */}
<ItemMenu item={item} canMove={false} canEdit={showEditButton} />
<ItemMenu
item={item}
canMove={false}
canAdmin={canAdmin}
canEdit={showEditButton}
/>

<ShareButton itemId={item.id} />
<ChatboxButton
Expand Down
2 changes: 1 addition & 1 deletion src/components/main/ItemActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import CopyButton from './CopyButton';
type Props = {
selectedIds: string[];
};

// todo: not used anymore ?
const ItemActionsRenderer = ({ selectedIds }: Props): JSX.Element => (
<>
<MoveButton
Expand Down
25 changes: 22 additions & 3 deletions src/components/main/ItemCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { CSSProperties, PropsWithChildren } from 'react';
import { Link } from 'react-router-dom';

import { DiscriminatedItem, ItemMembership, ItemType } from '@graasp/sdk';
import {
DiscriminatedItem,
ItemMembership,
ItemType,
PermissionLevel,
} from '@graasp/sdk';
import { Card as GraaspCard, Thumbnail } from '@graasp/ui';

import truncate from 'lodash.truncate';
Expand All @@ -12,7 +17,10 @@ import { hooks } from '../../config/queryClient';
import { buildItemCard, buildItemLink } from '../../config/selectors';
import defaultImage from '../../resources/avatar.png';
import { stripHtml } from '../../utils/item';
import { isItemUpdateAllowedForUser } from '../../utils/membership';
import {
getHighestPermissionForMemberFromMemberships,
isItemUpdateAllowedForUser,
} from '../../utils/membership';
import EditButton from '../common/EditButton';
import FavoriteButton from '../common/FavoriteButton';
import { useCurrentUserContext } from '../context/CurrentUserContext';
Expand Down Expand Up @@ -80,6 +88,12 @@ const ItemComponent = ({
memberships,
memberId: member?.id,
});
const canAdmin = member?.id
? getHighestPermissionForMemberFromMemberships({
memberships,
memberId: member?.id,
})?.permission === PermissionLevel.Admin
: false;

const Actions = (
<>
Expand All @@ -103,7 +117,12 @@ const ItemComponent = ({
name={item.name}
creator={item.creator?.name}
ItemMenu={
<ItemMenu item={item} canEdit={enableEdition} canMove={canMove} />
<ItemMenu
item={item}
canEdit={enableEdition}
canAdmin={canAdmin}
canMove={canMove}
/>
}
Thumbnail={ThumbnailComponent}
cardId={buildItemCard(item.id)}
Expand Down
Loading
Loading