Skip to content

Commit

Permalink
Merge branch 'main' into add-pending-filter-to-unrepied-host-applicat…
Browse files Browse the repository at this point in the history
…ions-tab
  • Loading branch information
hdiniz authored Oct 1, 2024
2 parents bd6ecd7 + 7295939 commit 7e3360f
Show file tree
Hide file tree
Showing 38 changed files with 457 additions and 238 deletions.
26 changes: 15 additions & 11 deletions components/FilesViewerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ type FilesViewerModalProps = {
allowOutsideInteraction?: boolean;
canDownload?: boolean;
canOpenInNewWindow?: boolean;
hideCloseButton?: boolean;
};

export default function FilesViewerModal({
Expand All @@ -144,6 +145,7 @@ export default function FilesViewerModal({
openFileUrl,
canDownload = true,
canOpenInNewWindow = true,
hideCloseButton = false,
}: FilesViewerModalProps) {
const intl = useIntl();
const initialIndex = openFileUrl ? files?.findIndex(f => f.url === openFileUrl) : 0;
Expand Down Expand Up @@ -217,7 +219,7 @@ export default function FilesViewerModal({
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div
className={clsx(
'absolute inset-0 z-[1500] bg-foreground/25 backdrop-blur-sm',
'absolute inset-0 z-[1500] backdrop-blur-sm',
open ? 'animate-in fade-in-0' : 'animate-out fade-out-0',
)}
onClick={onClose}
Expand Down Expand Up @@ -279,16 +281,18 @@ export default function FilesViewerModal({
</ButtonLink>
</StyledTooltip>
)}
<StyledTooltip
containerCursor="pointer"
noArrow
content={intl.formatMessage({ id: 'Close', defaultMessage: 'Close' })}
delayHide={0}
>
<Button onClick={onClose}>
<X size="24" aria-hidden="true" />
</Button>
</StyledTooltip>
{!hideCloseButton && (
<StyledTooltip
containerCursor="pointer"
noArrow
content={intl.formatMessage({ id: 'Close', defaultMessage: 'Close' })}
delayHide={0}
>
<Button onClick={onClose}>
<X size="24" aria-hidden="true" />
</Button>
</StyledTooltip>
)}
</Flex>
</Header>
{hasMultipleFiles && (
Expand Down
2 changes: 1 addition & 1 deletion components/budget/ExpenseBudgetItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ const ExpenseBudgetItem = ({
fontSize="11px"
cursor="pointer"
buttonSize="tiny"
onClick={() => setShowFilesViewerModal(true)}
onClick={useDrawer ? expandExpense : () => setShowFilesViewerModal(true)}
px={2}
ml={-2}
isBorderless
Expand Down
127 changes: 0 additions & 127 deletions components/collective-page/sections/Projects.js

This file was deleted.

205 changes: 205 additions & 0 deletions components/collective-page/sections/Projects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import React from 'react';
import { gql, useQuery } from '@apollo/client';
import { css } from '@styled-system/css';
import { isEmpty } from 'lodash';
import { FormattedMessage, useIntl } from 'react-intl';
import styled from 'styled-components';

import { API_V2_CONTEXT } from '../../../lib/graphql/helpers';
import type {
ProjectsSectionSearchQuery,
ProjectsSectionSearchQueryVariables,
} from '../../../lib/graphql/types/v2/graphql';
import useDebounced from '../../../lib/hooks/useDebounced';

import { CONTRIBUTE_CARD_WIDTH } from '../../contribute-cards/constants';
import ContributeProject from '../../contribute-cards/ContributeProject';
import CreateNew from '../../contribute-cards/CreateNew';
import { EmptyResults } from '../../dashboard/EmptyResults';
import { Box } from '../../Grid';
import HorizontalScroller from '../../HorizontalScroller';
import Link from '../../Link';
import LoadingGrid from '../../LoadingGrid';
import StyledButton from '../../StyledButton';
import { P } from '../../Text';
import { Input } from '../../ui/Input';
import ContainerSectionContent from '../ContainerSectionContent';
import ContributeCardsContainer from '../ContributeCardsContainer';
import SectionTitle from '../SectionTitle';

const ProjectSectionCardFields = gql`
fragment ProjectSectionCardFields on Account {
id
legacyId
slug
name
description
imageUrl
isActive
isArchived
backgroundImageUrl(height: 208)
}
`;

const CONTRIBUTE_CARD_PADDING_X = [15, 18];

const ContributeCardContainer = styled(Box).attrs({ px: CONTRIBUTE_CARD_PADDING_X })(
css({
scrollSnapAlign: ['center', null, 'start'],
}),
);

type ProjectsProps = {
collective: {
slug: string;
name: string;
currency: string;
isActive: string;
};
projects: { id: number; isArchived?: boolean; isActive?: boolean; contributors?: object[] }[];
isAdmin: boolean;
showTitle: boolean;
};

function getContributeCardsScrollDistance(width) {
const oneCardScrollDistance = CONTRIBUTE_CARD_WIDTH + CONTRIBUTE_CARD_PADDING_X[0] * 2;
if (width <= oneCardScrollDistance * 2) {
return oneCardScrollDistance;
} else if (width <= oneCardScrollDistance * 4) {
return oneCardScrollDistance * 2;
} else {
return oneCardScrollDistance * 3;
}
}

export default function Projects(props: ProjectsProps) {
const { collective, isAdmin } = props;
const intl = useIntl();
const hasProjectsSection = (props.projects.length >= 0 && !collective.isActive) || isAdmin;

const [searchTerm, setSearchTerm] = React.useState('');
const deboucedSearchTerm = useDebounced(searchTerm, 1000);
const isSearching = !isEmpty(deboucedSearchTerm);
const query = useQuery<ProjectsSectionSearchQuery, ProjectsSectionSearchQueryVariables>(
gql`
query ProjectsSectionSearch($slug: String, $searchTerm: String) {
account(slug: $slug) {
projects: childrenAccounts(accountType: [PROJECT], searchTerm: $searchTerm) {
totalCount
nodes {
...ProjectSectionCardFields
}
}
}
}
${ProjectSectionCardFields}
`,
{
context: API_V2_CONTEXT,
variables: {
slug: props.collective.slug,
searchTerm: deboucedSearchTerm,
},
skip: !isSearching,
},
);

const searchProjects = React.useMemo(
() => (query.data?.account?.projects?.nodes || []).filter(p => isAdmin || !p.isArchived),
[isAdmin, query.data?.account?.projects?.nodes],
);
const collectiveProjects = React.useMemo(
() => props.projects.filter(p => isAdmin || !p.isArchived),
[isAdmin, props.projects],
);

const hasMore = isSearching && !query.loading && query.data?.account?.projects?.totalCount > searchProjects.length;
const isLoadingSearch = isSearching && query.loading;
const displayedProjects = !isSearching ? collectiveProjects : searchProjects;
if (!hasProjectsSection) {
return null;
}

return (
<Box pt={[4, 5]} data-cy="Projects">
<ContainerSectionContent>
<SectionTitle>
<FormattedMessage id="Projects" defaultMessage="Projects" />
</SectionTitle>
<P color="black.700" mb={4}>
{isAdmin ? (
<FormattedMessage
id="CollectivePage.SectionProjects.AdminDescription"
defaultMessage="Manage finances for a project or initiative separate from your collective budget."
/>
) : (
<FormattedMessage
id="CollectivePage.SectionProjects.Description"
defaultMessage="Support the following initiatives from {collectiveName}."
values={{ collectiveName: collective.name }}
/>
)}
</P>
{collectiveProjects?.length > 10 && (
<Input
placeholder={intl.formatMessage({ defaultMessage: 'Search projects...', id: 'Dw9Bae' })}
type="search"
value={searchTerm}
onChange={e => setSearchTerm(e.target.value)}
/>
)}
</ContainerSectionContent>

<Box mb={4}>
<HorizontalScroller container={ContributeCardsContainer} getScrollDistance={getContributeCardsScrollDistance}>
{isLoadingSearch && (
<div className="ml-8 self-center">
<LoadingGrid />
</div>
)}
{isSearching && !isLoadingSearch && isEmpty(displayedProjects) && (
<div className="ml-8 self-center">
<div className="w-60 text-center">
<EmptyResults onResetFilters={() => setSearchTerm('')} hasFilters={false} entityType="PROJECTS" />
</div>
</div>
)}
{displayedProjects.map(project => (
<Box key={project.id} px={CONTRIBUTE_CARD_PADDING_X}>
<ContributeProject
collective={collective}
project={project}
disableCTA={!project.isActive}
hideContributors={!displayedProjects.some(project => project.contributors?.length)}
/>
</Box>
))}
{hasMore && (
<div className="self-center">
<div className="w-60 text-center">
<Link href={`/${collective.slug}/projects`}>
<FormattedMessage defaultMessage="More results" id="irPBg/" />
</Link>
</div>
</div>
)}
{isAdmin && (
<ContributeCardContainer minHeight={150}>
<CreateNew route={`/${collective.slug}/projects/create`}>
<FormattedMessage id="SectionProjects.CreateProject" defaultMessage="Create Project" />
</CreateNew>
</ContributeCardContainer>
)}
</HorizontalScroller>
<ContainerSectionContent>
<Link href={`/${collective.slug}/projects`}>
<StyledButton mt={4} width={1} buttonSize="small" fontSize="14px">
<FormattedMessage id="CollectivePage.SectionProjects.ViewAll" defaultMessage="View all projects" />
</StyledButton>
</Link>
</ContainerSectionContent>
</Box>
</Box>
);
}
Loading

0 comments on commit 7e3360f

Please sign in to comment.