Skip to content

Commit

Permalink
Return list of active campaigns in projectBySlug web service
Browse files Browse the repository at this point in the history
related to #1051
  • Loading branch information
mohammadranjbarz committed Sep 4, 2023
1 parent 8568a89 commit 3867ac5
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 6 deletions.
5 changes: 4 additions & 1 deletion src/entities/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
getQfRoundTotalProjectsDonationsSum,
} from '../repositories/qfRoundRepository';
import { EstimatedMatching } from '../types/qfTypes';
import { Campaign } from './campaign';
// tslint:disable-next-line:no-var-requires
const moment = require('moment');

Expand Down Expand Up @@ -101,7 +102,6 @@ export enum OrderField {
QualityScore = 'qualityScore',
Verified = 'verified',
Reactions = 'totalReactions',
Traceable = 'traceCampaignId',
Donations = 'totalDonations',
TraceDonations = 'totalTraceDonations',
AcceptGiv = 'givingBlocksId',
Expand Down Expand Up @@ -390,6 +390,9 @@ export class Project extends BaseEntity {
@Field({ nullable: true })
reaction?: Reaction;

@Field(type => [Campaign], { nullable: true })
campaigns: Campaign[];

// only projects with status active can be listed automatically
static pendingReviewSince(maximumDaysForListing: Number) {
const maxDaysForListing = moment()
Expand Down
86 changes: 86 additions & 0 deletions src/resolvers/projectResolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5387,6 +5387,92 @@ function projectBySlugTestCases() {
assert.isTrue(project.projectPower.totalPower > 0);
});

it('should return projects including active campaigns', async () => {
const projectWithCampaign = await saveProjectDirectlyToDb({
...createProjectData(),
title: String(new Date().getTime()),
slug: String(new Date().getTime()),
});
const projectWithoutCampaign = await saveProjectDirectlyToDb({
...createProjectData(),
title: String(new Date().getTime()),
slug: String(new Date().getTime()),
});

const campaign = await Campaign.create({
isActive: true,
type: CampaignType.ManuallySelected,
slug: generateRandomString(),
title: 'title1',
description: 'description1',
photo: 'https://google.com',
relatedProjectsSlugs: [projectWithCampaign.slug as string],
order: 1,
}).save();
const result = await axios.post(graphqlUrl, {
query: fetchProjectsBySlugQuery,
variables: {
slug: projectWithCampaign.slug,
},
});

const project = result.data.data.projectBySlug;
assert.equal(Number(project.id), projectWithCampaign.id);

assert.exists(project.campaigns);
assert.isNotEmpty(project.campaigns);

const projectWithoutCampaignResult = await axios.post(graphqlUrl, {
query: fetchProjectsBySlugQuery,
variables: {
slug: projectWithoutCampaign.slug,
},
});

const project2 = projectWithoutCampaignResult.data.data.projectBySlug;
assert.equal(Number(project2.id), projectWithoutCampaign.id);

assert.isEmpty(project2.campaigns);

await campaign.remove();
});

it('should return projects including active campaigns, even when sent slug is in the slugHistory of project', async () => {
const projectWithCampaign = await saveProjectDirectlyToDb({
...createProjectData(),
title: String(new Date().getTime()),
slug: String(new Date().getTime()),
});
const previousSlug = `${String(new Date().getTime())}-previous`;
projectWithCampaign.slugHistory = [previousSlug];
await projectWithCampaign.save();

const campaign = await Campaign.create({
isActive: true,
type: CampaignType.ManuallySelected,
slug: generateRandomString(),
title: 'title1',
description: 'description1',
photo: 'https://google.com',
relatedProjectsSlugs: [previousSlug],
order: 1,
}).save();
const result = await axios.post(graphqlUrl, {
query: fetchProjectsBySlugQuery,
variables: {
slug: previousSlug,
},
});

const project = result.data.data.projectBySlug;
assert.equal(Number(project.id), projectWithCampaign.id);

assert.exists(project.campaigns);
assert.isNotEmpty(project.campaigns);

await campaign.remove();
});

it('should return projects including project future power rank', async () => {
await AppDataSource.getDataSource().query(
'truncate power_snapshot cascade',
Expand Down
14 changes: 9 additions & 5 deletions src/resolvers/projectResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,11 +486,6 @@ export class ProjectResolver {
return query.andWhere(`project.${filter} ${acceptGiv} NULL`);
}

if (filter === 'traceCampaignId') {
const isRequested = filterValue ? 'IS NOT' : 'IS';
return query.andWhere(`project.${filter} ${isRequested} NULL`);
}

if (
(filter === FilterField.AcceptFundOnGnosis ||
filter === FilterField.AcceptFundOnCelo ||
Expand Down Expand Up @@ -896,6 +891,15 @@ export class ProjectResolver {
.leftJoinAndSelect('project.projectInstantPower', 'projectInstantPower')
.leftJoinAndSelect('project.qfRounds', 'qfRounds')
.leftJoinAndSelect('project.projectFuturePower', 'projectFuturePower')
.leftJoinAndMapMany(
'project.campaigns',
Campaign,
'campaigns',
'(campaigns."relatedProjectsSlugs" && ARRAY[:slug]::text[] OR campaigns."relatedProjectsSlugs" && project."slugHistory") AND campaigns."isActive" = TRUE',
{
slug,
},
)
.leftJoin('project.adminUser', 'user')
.addSelect(publicSelectionFields); // aliased selection

Expand Down
18 changes: 18 additions & 0 deletions test/graphqlQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,24 @@ export const fetchProjectsBySlugQuery = `
listed
reviewStatus
givingBlocksId
campaigns {
id
title
description
type
photo
video
videoPreview
slug
isActive
order
landingLink
filterFields
sortingField
createdAt
updatedAt
}
givbackFactor
projectPower {
totalPower
Expand Down

0 comments on commit 3867ac5

Please sign in to comment.