Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Cofacts API type and handle optional article createdAt issue #397

Merged
merged 4 commits into from
Sep 18, 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
37 changes: 31 additions & 6 deletions src/graphql/cofacts-api.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ type Query {
type Article implements Node {
id: ID!
text: String
createdAt: String!

"""May be null for legacy articles"""
createdAt: String
updatedAt: String
status: ReplyRequestStatusEnum!
references: [ArticleReference]
Expand Down Expand Up @@ -279,6 +281,12 @@ type Article implements Node {
"""Attachment hash to search or identify files"""
attachmentHash: String
cooccurrences: [Cooccurrence!]

"""Transcript contributors of the article"""
contributors: [Contributor!]!

"""Time when the article was last transcribed"""
transcribedAt: String
}

"""Basic entity. Modeled after Relay's GraphQL Server Specification."""
Expand Down Expand Up @@ -338,7 +346,9 @@ type ArticleReply {
"""
ownVote: FeedbackVote
status: ArticleReplyStatusEnum!
createdAt: String!

"""May be null for legacy article-replies"""
createdAt: String
updatedAt: String
}

Expand All @@ -347,7 +357,9 @@ type Reply implements Node {

"""The user submitted this reply version"""
user: User
createdAt: String!

"""May be null for legacy replies"""
createdAt: String
text: String
type: ReplyTypeEnum!
reference: String
Expand Down Expand Up @@ -980,6 +992,14 @@ type Cooccurrence implements Node {
updatedAt: String!
}

type Contributor {
"""The user who contributed to this article."""
user: User
userId: String!
appId: String!
updatedAt: String
}

type Ydoc {
"""Binary that stores as base64 encoded string"""
data: String
Expand Down Expand Up @@ -1046,6 +1066,11 @@ input ListArticleFilter {
"""Show only articles with(out) article replies created by specified user"""
articleRepliesFrom: UserAndExistInput

"""
Show only articles with(out) article transcript contributed by specified user
"""
transcribedBy: UserAndExistInput

"""

When true, return only articles with any article replies that has more positive feedback than negative.
Expand Down Expand Up @@ -1098,9 +1123,9 @@ input UserAndExistInput {

"""

When true (or not specified), return only entries with the specified user's involvement.
When false, return only entries that the specified user did not involve.
When true (or not specified), return only entries with the specified user's involvement.
When false, return only entries that the specified user did not involve.

"""
exists: Boolean = true
}
Expand Down
6 changes: 6 additions & 0 deletions src/lib/__tests__/sharedUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ describe('date-fns', () => {
expect(format(new Date(612921600000))).toMatchInlineSnapshot(
`"Jun 4, 1989"`
);

// Handles invalid date
expect(format(new Date(-Infinity))).toMatchInlineSnapshot(`"unknown date"`);
expect(formatDistanceToNow(new Date('wrong'))).toMatchInlineSnapshot(
`"unknown time"`
);
});

it('use other locale', () => {
Expand Down
12 changes: 10 additions & 2 deletions src/lib/sharedUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,19 @@ let locale = require(`date-fns/locale/${(process.env.LOCALE || 'en_US').replace(
locale = locale.default ? locale.default : locale;

function formatAbsolute(date, format = 'PP', config = {}) {
return dateFnsFormat(date, format, { ...config, locale });
try {
return dateFnsFormat(date, format, { ...config, locale });
} catch (e) {
return t`unknown date`;
}
}

export function formatDistanceToNow(date, config = {}) {
return dateFnsFormatDistanceToNow(date, { ...config, locale });
try {
return dateFnsFormatDistanceToNow(date, { ...config, locale });
} catch (e) {
return t`unknown time`;
}
}

const THRESHOLD = 86400 * 2 * 1000; // 2 days in milliseconds
Expand Down
4 changes: 3 additions & 1 deletion src/webhook/handlers/choosingArticle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,9 @@ const choosingArticle: ChatbotPostbackHandler = async (params) => {
const aiReply = await createAIReply(selectedArticleId, userId);

if (aiReply) {
const articleCreatedAt = new Date(GetArticle.createdAt);
const articleCreatedAt = new Date(
GetArticle.createdAt ?? -Infinity /* Triggers invalid date */
);
const aiReplyCreatedAt = new Date(aiReply.createdAt);

const aiReplyWithin30Days = isBefore(
Expand Down
4 changes: 3 additions & 1 deletion src/webhook/handlers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,9 @@ export function createReplyMessages(
article: CreateReplyMessagesArticleFragment,
selectedArticleId: string
): Message[] {
const articleDate = format(new Date(article.createdAt));
const articleDate = format(
new Date(article.createdAt ?? -Infinity /* Triggers invalid date */)
);
const articleUrl = getArticleURL(selectedArticleId);
const typeStr = createTypeWords(reply.type).toLocaleLowerCase();

Expand Down
33 changes: 25 additions & 8 deletions typegen/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,11 @@ export type Article = Node & {
attachmentUrl: Maybe<Scalars['String']>;
/** Number of normal article categories */
categoryCount: Scalars['Int'];
/** Transcript contributors of the article */
contributors: Array<Contributor>;
cooccurrences: Maybe<Array<Cooccurrence>>;
createdAt: Scalars['String'];
/** May be null for legacy articles */
createdAt: Maybe<Scalars['String']>;
/** Hyperlinks in article text */
hyperlinks: Maybe<Array<Maybe<Hyperlink>>>;
id: Scalars['ID'];
Expand All @@ -184,6 +187,8 @@ export type Article = Node & {
stats: Maybe<Array<Maybe<Analytics>>>;
status: ReplyRequestStatusEnum;
text: Maybe<Scalars['String']>;
/** Time when the article was last transcribed */
transcribedAt: Maybe<Scalars['String']>;
updatedAt: Maybe<Scalars['String']>;
/** The user submitted this article */
user: Maybe<User>;
Expand Down Expand Up @@ -338,7 +343,8 @@ export type ArticleReply = {
article: Maybe<Article>;
articleId: Scalars['String'];
canUpdateStatus: Scalars['Boolean'];
createdAt: Scalars['String'];
/** May be null for legacy article-replies */
createdAt: Maybe<Scalars['String']>;
feedbackCount: Scalars['Int'];
feedbacks: Array<ArticleReplyFeedback>;
negativeFeedbackCount: Scalars['Int'];
Expand Down Expand Up @@ -479,6 +485,14 @@ export type Contribution = {
date: Maybe<Scalars['String']>;
};

export type Contributor = {
appId: Scalars['String'];
updatedAt: Maybe<Scalars['String']>;
/** The user who contributed to this article. */
user: Maybe<User>;
userId: Scalars['String'];
};

export type Cooccurrence = Node & {
appId: Scalars['String'];
articleIds: Array<Scalars['String']>;
Expand Down Expand Up @@ -607,6 +621,8 @@ export type ListArticleFilter = {
selfOnly: InputMaybe<Scalars['Boolean']>;
/** Returns only articles with the specified statuses */
statuses: InputMaybe<Array<ArticleStatusEnum>>;
/** Show only articles with(out) article transcript contributed by specified user */
transcribedBy: InputMaybe<UserAndExistInput>;
/** Specifies how the transcript of `mediaUrl` can be used to search. Can only specify `transcript` when `mediaUrl` is specified. */
transcript: InputMaybe<TranscriptFilter>;
/** Show only articles created by the specific user. */
Expand Down Expand Up @@ -1169,7 +1185,8 @@ export type RelatedArticleOrderBy = {

export type Reply = Node & {
articleReplies: Array<ArticleReply>;
createdAt: Scalars['String'];
/** May be null for legacy replies */
createdAt: Maybe<Scalars['String']>;
/** Hyperlinks in reply text or reference. May be empty array if no URLs are included. `null` when hyperlinks are still fetching. */
hyperlinks: Maybe<Array<Maybe<Hyperlink>>>;
id: Scalars['ID'];
Expand Down Expand Up @@ -1399,7 +1416,7 @@ export type GetArticleInChoosingArticleQueryVariables = Exact<{
}>;


export type GetArticleInChoosingArticleQuery = { GetArticle: { text: string | null, replyCount: number, articleType: ArticleTypeEnum, createdAt: string, articleReplies: Array<{ positiveFeedbackCount: number, negativeFeedbackCount: number, reply: { id: string, type: ReplyTypeEnum, text: string | null } | null }> } | null };
export type GetArticleInChoosingArticleQuery = { GetArticle: { text: string | null, replyCount: number, articleType: ArticleTypeEnum, createdAt: string | null, articleReplies: Array<{ positiveFeedbackCount: number, negativeFeedbackCount: number, reply: { id: string, type: ReplyTypeEnum, text: string | null } | null }> } | null };

export type SubmitReplyRequestWithoutReasonMutationVariables = Exact<{
id: Scalars['String'];
Expand All @@ -1414,13 +1431,13 @@ export type GetReplyRelatedDataQueryVariables = Exact<{
}>;


export type GetReplyRelatedDataQuery = { GetReply: { type: ReplyTypeEnum, text: string | null, reference: string | null, createdAt: string } | null, GetArticle: { text: string | null, replyCount: number, createdAt: string, articleReplies: Array<{ replyId: string, createdAt: string }> } | null };
export type GetReplyRelatedDataQuery = { GetReply: { type: ReplyTypeEnum, text: string | null, reference: string | null, createdAt: string | null } | null, GetArticle: { text: string | null, replyCount: number, createdAt: string | null, articleReplies: Array<{ replyId: string, createdAt: string | null }> } | null };

export type CreateReferenceWordsReplyFragment = { reference: string | null, type: ReplyTypeEnum, createdAt: string };
export type CreateReferenceWordsReplyFragment = { reference: string | null, type: ReplyTypeEnum, createdAt: string | null };

export type CreateReplyMessagesReplyFragment = { text: string | null, reference: string | null, type: ReplyTypeEnum, createdAt: string };
export type CreateReplyMessagesReplyFragment = { text: string | null, reference: string | null, type: ReplyTypeEnum, createdAt: string | null };

export type CreateReplyMessagesArticleFragment = { replyCount: number, createdAt: string };
export type CreateReplyMessagesArticleFragment = { replyCount: number, createdAt: string | null };

export type CreateHighlightContentsHighlightFragment = { text: string | null, hyperlinks: Array<{ title: string | null, summary: string | null } | null> | null };

Expand Down
Loading