Skip to content

Commit be37293

Browse files
authored
hotfix: date type (#3527)
1 parent 649445f commit be37293

File tree

4 files changed

+228
-30
lines changed

4 files changed

+228
-30
lines changed

__tests__/posts.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10874,3 +10874,97 @@ describe('mutate poll vote', () => {
1087410874
);
1087510875
});
1087610876
});
10877+
10878+
describe('query userPostsWithAnalytics', () => {
10879+
const QUERY = /* GraphQL */ `
10880+
query UserPostsWithAnalytics($first: Int, $after: String) {
10881+
userPostsWithAnalytics(first: $first, after: $after) {
10882+
edges {
10883+
node {
10884+
id
10885+
title
10886+
analytics {
10887+
id
10888+
impressions
10889+
reputation
10890+
upvotes
10891+
}
10892+
}
10893+
}
10894+
pageInfo {
10895+
hasNextPage
10896+
endCursor
10897+
}
10898+
}
10899+
}
10900+
`;
10901+
10902+
beforeEach(async () => {
10903+
await saveFixtures(
10904+
con,
10905+
User,
10906+
usersFixture.map((item) => ({
10907+
...item,
10908+
id: `${item.id}-upwa`,
10909+
})),
10910+
);
10911+
10912+
await saveFixtures(
10913+
con,
10914+
Post,
10915+
postsFixture.slice(0, 3).map((item) => ({
10916+
...item,
10917+
id: `${item.id}-upwa`,
10918+
shortId: `${item.shortId}-upwa`,
10919+
url: `https://example.com/posts/${item.id}-upwa`,
10920+
canonicalUrl: `https://example.com/posts/${item.id}-upwa`,
10921+
yggdrasilId: randomUUID(),
10922+
authorId: '1-upwa',
10923+
})),
10924+
);
10925+
10926+
await saveFixtures(
10927+
con,
10928+
PostAnalytics,
10929+
postsFixture.slice(0, 3).map((item) =>
10930+
con.getRepository(PostAnalytics).create({
10931+
id: `${item.id}-upwa`,
10932+
impressions: 100,
10933+
impressionsAds: 50,
10934+
reputation: 25,
10935+
upvotes: 10,
10936+
}),
10937+
),
10938+
);
10939+
});
10940+
10941+
it('should require authentication', async () => {
10942+
await testQueryErrorCode(client, { query: QUERY }, 'UNAUTHENTICATED');
10943+
});
10944+
10945+
it('should return paginated posts with analytics for the user', async () => {
10946+
loggedUser = '1-upwa';
10947+
10948+
const res = await client.query(QUERY, { variables: { first: 10 } });
10949+
10950+
expect(res.errors).toBeFalsy();
10951+
expect(res.data.userPostsWithAnalytics.edges).toHaveLength(3);
10952+
expect(res.data.userPostsWithAnalytics.edges[0].node).toMatchObject({
10953+
id: expect.stringContaining('-upwa'),
10954+
analytics: {
10955+
impressions: 150,
10956+
reputation: 25,
10957+
upvotes: 10,
10958+
},
10959+
});
10960+
});
10961+
10962+
it('should return empty for user with no posts', async () => {
10963+
loggedUser = '2-upwa';
10964+
10965+
const res = await client.query(QUERY, { variables: { first: 10 } });
10966+
10967+
expect(res.errors).toBeFalsy();
10968+
expect(res.data.userPostsWithAnalytics.edges).toHaveLength(0);
10969+
});
10970+
});

__tests__/users.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
addHours,
88
addSeconds,
99
addYears,
10+
format,
1011
startOfDay,
1112
startOfISOWeek,
1213
subDays,
@@ -59,6 +60,7 @@ import {
5960
} from '../src/entity';
6061
import { UserProfileAnalytics } from '../src/entity/user/UserProfileAnalytics';
6162
import { UserProfileAnalyticsHistory } from '../src/entity/user/UserProfileAnalyticsHistory';
63+
import { PostAnalyticsHistory } from '../src/entity/posts/PostAnalyticsHistory';
6264
import { sourcesFixture } from './fixture/source';
6365
import {
6466
CioTransactionalMessageTemplateId,
@@ -7963,3 +7965,87 @@ describe('query userProfileAnalyticsHistory', () => {
79637965
expect(res.data.userProfileAnalyticsHistory.edges).toHaveLength(0);
79647966
});
79657967
});
7968+
7969+
describe('query userPostsAnalytics', () => {
7970+
const QUERY = /* GraphQL */ `
7971+
query UserPostsAnalytics {
7972+
userPostsAnalytics {
7973+
id
7974+
impressions
7975+
upvotes
7976+
comments
7977+
}
7978+
}
7979+
`;
7980+
7981+
it('should require authentication', async () => {
7982+
await testQueryErrorCode(client, { query: QUERY }, 'UNAUTHENTICATED');
7983+
});
7984+
7985+
it('should return null when no analytics exist', async () => {
7986+
loggedUser = '1';
7987+
7988+
const res = await client.query(QUERY);
7989+
7990+
expect(res.errors).toBeFalsy();
7991+
expect(res.data.userPostsAnalytics).toBeNull();
7992+
});
7993+
});
7994+
7995+
describe('query userPostsAnalyticsHistory', () => {
7996+
const QUERY = /* GraphQL */ `
7997+
query UserPostsAnalyticsHistory {
7998+
userPostsAnalyticsHistory {
7999+
date
8000+
impressions
8001+
impressionsAds
8002+
}
8003+
}
8004+
`;
8005+
8006+
beforeEach(async () => {
8007+
await saveFixtures(con, Post, [
8008+
{
8009+
id: 'p1-upah',
8010+
shortId: 'sp1-upah',
8011+
title: 'Test Post',
8012+
url: 'https://example.com/p1-upah',
8013+
sourceId: 'a',
8014+
authorId: '1',
8015+
},
8016+
]);
8017+
8018+
await con.getRepository(PostAnalyticsHistory).save([
8019+
{
8020+
id: 'p1-upah',
8021+
date: format(new Date(), 'yyyy-MM-dd'),
8022+
impressions: 100,
8023+
impressionsAds: 50,
8024+
},
8025+
{
8026+
id: 'p1-upah',
8027+
date: format(subDays(new Date(), 1), 'yyyy-MM-dd'),
8028+
impressions: 80,
8029+
impressionsAds: 40,
8030+
},
8031+
]);
8032+
});
8033+
8034+
it('should require authentication', async () => {
8035+
await testQueryErrorCode(client, { query: QUERY }, 'UNAUTHENTICATED');
8036+
});
8037+
8038+
it('should return aggregated daily impressions history', async () => {
8039+
loggedUser = '1';
8040+
8041+
const res = await client.query(QUERY);
8042+
8043+
expect(res.errors).toBeFalsy();
8044+
expect(res.data.userPostsAnalyticsHistory).toHaveLength(2);
8045+
expect(res.data.userPostsAnalyticsHistory[0]).toMatchObject({
8046+
date: expect.any(String),
8047+
impressions: 150,
8048+
impressionsAds: 50,
8049+
});
8050+
});
8051+
});

src/graphorm/index.ts

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -819,31 +819,6 @@ const obj = new GraphORM({
819819
childColumn: 'postId',
820820
},
821821
},
822-
isBoosted: {
823-
select: (ctx, alias, qb) => {
824-
const subQuery = qb
825-
.subQuery()
826-
.select('1')
827-
.from('campaign_post', 'cp')
828-
.where(`cp."postId" = "${alias}".id`)
829-
.andWhere('cp.state = :activeCampaignState')
830-
.getQuery();
831-
qb.setParameter('activeCampaignState', 1); // CampaignState.Active
832-
return `EXISTS${subQuery}`;
833-
},
834-
transform: (value: boolean, ctx, parent) => {
835-
const post = parent as Post;
836-
const isAuthor = post?.authorId && ctx.userId === post.authorId;
837-
const isScout = post?.scoutId && ctx.userId === post.scoutId;
838-
839-
// Only show boost status to author/scout
840-
if (isAuthor || isScout) {
841-
return value;
842-
}
843-
844-
return null;
845-
},
846-
},
847822
analytics: {
848823
relation: {
849824
isMany: false,
@@ -1702,6 +1677,11 @@ const obj = new GraphORM({
17021677
`;
17031678
},
17041679
},
1680+
reputation: {
1681+
transform: (value) => {
1682+
return Math.max(0, value);
1683+
},
1684+
},
17051685
},
17061686
},
17071687
UserProfileAnalytics: {

src/schema/posts.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -818,11 +818,6 @@ export const typeDefs = /* GraphQL */ `
818818
"""
819819
numPollVotes: Int
820820
821-
"""
822-
Whether the post is currently being boosted (only visible to author/scout)
823-
"""
824-
isBoosted: Boolean
825-
826821
"""
827822
Post analytics
828823
"""
@@ -1054,6 +1049,8 @@ export const typeDefs = /* GraphQL */ `
10541049
type PostAnalyticsPublic {
10551050
id: ID!
10561051
impressions: Int!
1052+
reputation: Int!
1053+
upvotes: Int!
10571054
}
10581055
10591056
type PostAnalyticsHistory {
@@ -1280,6 +1277,20 @@ export const typeDefs = /* GraphQL */ `
12801277
"""
12811278
id: ID!
12821279
): PostAnalyticsHistoryConnection! @auth
1280+
1281+
"""
1282+
Get paginated list of posts authored by the authenticated user with analytics
1283+
"""
1284+
userPostsWithAnalytics(
1285+
"""
1286+
Paginate after opaque cursor
1287+
"""
1288+
after: String
1289+
"""
1290+
Paginate first
1291+
"""
1292+
first: Int
1293+
): PostConnection! @auth
12831294
}
12841295
12851296
extend type Mutation {
@@ -2390,6 +2401,33 @@ export const resolvers: IResolvers<unknown, BaseContext> = traceResolvers<
23902401
},
23912402
);
23922403
},
2404+
userPostsWithAnalytics: async (
2405+
_,
2406+
args: ConnectionArguments,
2407+
ctx: AuthContext,
2408+
info,
2409+
): Promise<ConnectionRelay<GQLPost>> => {
2410+
return queryPaginatedByDate(
2411+
ctx,
2412+
info,
2413+
args,
2414+
{ key: 'createdAt' },
2415+
{
2416+
queryBuilder: (builder) => {
2417+
builder.queryBuilder = builder.queryBuilder
2418+
.andWhere(`${builder.alias}.authorId = :userId`, {
2419+
userId: ctx.userId,
2420+
})
2421+
.andWhere(`${builder.alias}.deleted = false`)
2422+
.andWhere(`${builder.alias}.visible = true`);
2423+
2424+
return builder;
2425+
},
2426+
orderByKey: 'DESC',
2427+
readReplica: true,
2428+
},
2429+
);
2430+
},
23932431
},
23942432
Mutation: {
23952433
createSourcePostModeration: async (

0 commit comments

Comments
 (0)