Skip to content

Commit

Permalink
Merge pull request #4793 from Giveth/feat/delete-draft-projec
Browse files Browse the repository at this point in the history
Feat/delete draft projec
  • Loading branch information
MohammadPCh authored Oct 1, 2024
2 parents a54076c + b8891aa commit 14c4b07
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 84 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"devDependencies": {
"@babel/preset-typescript": "^7.23.3",
"@next/bundle-analyzer": "^14.1.0",
"@tanstack/react-query-devtools": "^5.58.0",
"@testing-library/cypress": "^10.0.1",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
Expand Down
50 changes: 37 additions & 13 deletions src/apollo/apolloClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { useMemo } from 'react';
import { ApolloClient, InMemoryCache, ApolloLink } from '@apollo/client';
import {
ApolloClient,
InMemoryCache,
ApolloLink,
NormalizedCacheObject,
} from '@apollo/client';
import { RetryLink } from '@apollo/client/link/retry';
import { setContext } from '@apollo/client/link/context';
import { onError } from '@apollo/client/link/error';
Expand All @@ -14,20 +19,21 @@ import { signOut } from '@/features/user/user.thunks';
import config from '@/configuration';
import { setShowSignWithWallet } from '@/features/modal/modal.slice';

let apolloClient: any;
let apolloClient: ApolloClient<NormalizedCacheObject> | undefined;

const ssrMode = isSSRMode;

export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__';

const parseHeaders = (rawHeaders: any) => {
// Parses headers into the Headers object
const parseHeaders = (rawHeaders: string) => {
const headers = new Headers();
// Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
// https://tools.ietf.org/html/rfc7230#section-3.2
const preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ');
preProcessedHeaders.split(/\r?\n/).forEach((line: any) => {
preProcessedHeaders.split(/\r?\n/).forEach((line: string) => {
const parts = line.split(':');
const key = parts.shift().trim();
const key = parts.shift()?.trim();
if (key) {
const value = parts.join(':').trim();
headers.append(key, value);
Expand All @@ -36,6 +42,7 @@ const parseHeaders = (rawHeaders: any) => {
return headers;
};

// Custom fetch logic with file upload handling
const uploadFetch = (url: string, options: any) =>
new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
Expand All @@ -49,8 +56,11 @@ const uploadFetch = (url: string, options: any) =>
'responseURL' in xhr
? xhr.responseURL
: opts.headers.get('X-Request-URL');
// TypeScript fix: Explicitly cast `xhr` to `XMLHttpRequest` to access responseText
const body =
'response' in xhr ? xhr.response : (xhr as any).responseText;
'response' in xhr
? xhr.response
: (xhr as XMLHttpRequest).responseText;
resolve(new Response(body, opts));
};
xhr.onerror = () => {
Expand All @@ -76,26 +86,30 @@ const uploadFetch = (url: string, options: any) =>
xhr.send(options.body);
});

const customFetch = (uri: any, options: any) => {
// Custom fetch function to determine when to use upload fetch or standard fetch
const customFetch = (uri: string, options: any) => {
if (options.useUpload) {
return uploadFetch(uri, options);
}
return fetch(uri, options);
};

function createApolloClient() {
// Creates the Apollo Client with the custom link setup
function createApolloClient(): ApolloClient<NormalizedCacheObject> {
let userWalletAddress: string | null;
if (!ssrMode) {
userWalletAddress = localStorage.getItem(StorageLabel.USER);
}

const retryLink = new RetryLink();

// Custom link for handling file uploads
const httpLink = createUploadLink({
uri: config.BACKEND_LINK,
fetch: customFetch as any,
});

// Auth link to add Authorization and locale headers
const authLink = setContext((_, { headers }) => {
let locale: string | null = !ssrMode
? localStorage.getItem(StorageLabel.LOCALE)
Expand All @@ -117,12 +131,13 @@ function createApolloClient() {
};
});

// Error handling link
const errorLink = onError(({ graphQLErrors, networkError, operation }) => {
if (graphQLErrors) {
console.log('operation', operation);
graphQLErrors.forEach(err => {
console.error('err', JSON.stringify(err));
const { message, locations, path } = err;
const { message } = err;
if (message.toLowerCase().includes('authentication required')) {
console.log(Date.now(), 'sign out from graphQL');
// removes token and user from store
Expand Down Expand Up @@ -190,7 +205,10 @@ function createApolloClient() {
});
}

export function initializeApollo(initialState = null) {
// Initialize Apollo Client for SSR and client-side rendering
export function initializeApollo(
initialState: any = null,
): ApolloClient<NormalizedCacheObject> {
const _apolloClient = apolloClient ?? createApolloClient();

// If your page has Next.js data fetching methods that use Apollo Client, the initial state
Expand All @@ -202,7 +220,7 @@ export function initializeApollo(initialState = null) {
// Merge the existing cache into data passed from getStaticProps/getServerSideProps
const data = merge(initialState, existingCache, {
// combine arrays using object equality (like in sets)
arrayMerge: (destinationArray, sourceArray) => [
arrayMerge: (destinationArray: any[], sourceArray: any[]) => [
...sourceArray,
...destinationArray.filter(d =>
sourceArray.every(s => !isEqual(d, s)),
Expand All @@ -221,18 +239,24 @@ export function initializeApollo(initialState = null) {
return _apolloClient;
}

export function addApolloState(client: any, pageProps: any) {
// Adds Apollo Client's state to pageProps
export function addApolloState(
client: ApolloClient<NormalizedCacheObject>,
pageProps: any,
) {
if (pageProps?.props) {
pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract();
}

return pageProps;
}

// Custom React hook to use Apollo Client
export function useApollo(pageProps: any) {
const state = pageProps[APOLLO_STATE_PROP_NAME];

return useMemo(() => initializeApollo(state), [state]);
}

export const client = initializeApollo();
// Export the client instance
export const client: ApolloClient<NormalizedCacheObject> = initializeApollo();
6 changes: 6 additions & 0 deletions src/apollo/gql/gqlProjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -804,3 +804,9 @@ export const FETCH_RECURRING_DONATIONS_BY_DATE = gql`
}
}
`;

export const DELETE_DRAFT_PROJECT = gql`
mutation ($projectId: Float!) {
deleteDraftProject(projectId: $projectId)
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { ONE_MONTH_SECONDS } from '@/lib/constants/constants';
import ExternalLink from '@/components/ExternalLink';
import { ChainType } from '@/types/config';
import NetworkLogo from '@/components/NetworkLogo';
import { EOrderBy } from '../../userProfile/UserProfile.view';
import { EOrderBy } from '../../userProfile/projectsTab/type';

const itemPerPage = 10;

Expand Down
13 changes: 0 additions & 13 deletions src/components/views/userProfile/UserProfile.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
isUserRegistered,
shortenAddress,
} from '@/lib/helpers';
import { EDirection } from '@/apollo/types/gqlEnums';
import ExternalLink from '@/components/ExternalLink';
import IncompleteProfileToast from '@/components/views/userProfile/IncompleteProfileToast';
import { useAppDispatch, useAppSelector } from '@/features/hooks';
Expand All @@ -45,18 +44,6 @@ import { IGiverPFPToken } from '@/apollo/types/types';
import { useProfileContext } from '@/context/profile.context';
import { useGeneralWallet } from '@/providers/generalWalletProvider';

export enum EOrderBy {
TokenAmount = 'TokenAmount',
UsdAmount = 'UsdAmount',
CreationDate = 'CreationDate',
Donations = 'Donations',
}

export interface IOrder {
by: EOrderBy;
direction: EDirection;
}

export interface IUserProfileView {}

const UserProfileView: FC<IUserProfileView> = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ import { smallFormatDate, formatTxLink } from '@/lib/helpers';
import { slugToProjectView } from '@/lib/routeCreators';
import ExternalLink from '@/components/ExternalLink';
import { IWalletDonation } from '@/apollo/types/types';
import {
EOrderBy,
IOrder,
} from '@/components/views/userProfile/UserProfile.view';
import SortIcon from '@/components/SortIcon';
import DonationStatus from '@/components/badges/DonationStatusBadge';
import {
Expand All @@ -27,6 +23,7 @@ import {
import { Badge, EBadgeStatus } from '@/components/Badge';
import { formatDonation } from '@/helpers/number';
import NetworkLogo from '@/components/NetworkLogo';
import { EOrderBy, IOrder } from '../../projectsTab/type';

interface OneTimeDonationTable {
donations: IWalletDonation[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { IWalletDonation } from '@/apollo/types/types';
import Pagination from '@/components/Pagination';
import NothingToSee from '@/components/views/userProfile/NothingToSee';
import DonationTable from '@/components/views/userProfile/donationsTab/oneTimeTab/OneTimeDonationsTable';
import { IOrder, EOrderBy } from '../../UserProfile.view';
import { EOrderBy, IOrder } from '../../projectsTab/type';
import { useProfileContext } from '@/context/profile.context';
import { WrappedSpinner } from '@/components/Spinner';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,55 @@
import styled from 'styled-components';
import { type FC } from 'react';
import { useState, type FC } from 'react';
import { Button, Flex, IconTrash32, P } from '@giveth/ui-design-system';
import { useIntl } from 'react-intl';
import { useMutation } from '@tanstack/react-query';
import { IProject } from '@/apollo/types/types';
import { Modal } from '@/components/modals/Modal';
import { IModal } from '@/types/common';
import { useModalAnimation } from '@/hooks/useModalAnimation';
import { client } from '@/apollo/apolloClient';
import { DELETE_DRAFT_PROJECT } from '@/apollo/gql/gqlProjects';
import { useAppDispatch } from '@/features/hooks';
import { fetchUserByAddress } from '@/features/user/user.thunks';
import { useGeneralWallet } from '@/providers/generalWalletProvider';

interface IDeleteProjectModal extends IModal {
project: IProject;
refetchProjects: () => void;
}

const DeleteProjectModal: FC<IDeleteProjectModal> = ({
setShowModal,
project,
refetchProjects,
}) => {
const [isLoading, setIsLoading] = useState(false);
const { formatMessage } = useIntl();
const { isAnimating, closeModal } = useModalAnimation(setShowModal);
const dispatch = useAppDispatch();
const { walletAddress } = useGeneralWallet();

const { mutate: deleteProject, isPending } = useMutation({
mutationFn: (projectId: number) =>
client.mutate({
mutation: DELETE_DRAFT_PROJECT,
variables: { projectId: projectId },
}),
onSuccess: async () => {
setIsLoading(true);
await refetchProjects();
walletAddress &&
(await dispatch(fetchUserByAddress(walletAddress)));
setIsLoading(false);
closeModal();
},
});

const handleRemoveProject = async () => {
deleteProject(Number(project.id));
};

const loading = isPending || isLoading;

return (
<Modal
Expand Down Expand Up @@ -44,7 +77,8 @@ const DeleteProjectModal: FC<IDeleteProjectModal> = ({
id: 'component.delete_project.yes',
})}
size='small'
onClick={() => setShowModal(true)}
onClick={handleRemoveProject}
loading={loading}
/>
<Button
buttonType='texty-gray'
Expand All @@ -53,6 +87,7 @@ const DeleteProjectModal: FC<IDeleteProjectModal> = ({
})}
size='small'
onClick={() => setShowModal(false)}
disabled={loading}
/>
</Flex>
</ModalContainer>
Expand Down
Loading

0 comments on commit 14c4b07

Please sign in to comment.