mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Merge pull request #729 from omnivore-app/labels-in-highlights
Support labels in highlights
This commit is contained in:
commit
309c581cf5
11 changed files with 588 additions and 189 deletions
|
|
@ -94,8 +94,7 @@ export const updateLabelsInPage = async (
|
|||
}
|
||||
}
|
||||
|
||||
export const deleteLabelInPages = async (
|
||||
userId: string,
|
||||
export const deleteLabel = async (
|
||||
label: string,
|
||||
ctx: PageContext
|
||||
): Promise<boolean> => {
|
||||
|
|
@ -104,8 +103,12 @@ export const deleteLabelInPages = async (
|
|||
index: INDEX_ALIAS,
|
||||
body: {
|
||||
script: {
|
||||
source:
|
||||
'ctx._source.labels.removeIf(label -> label.name == params.label)',
|
||||
source: `if (ctx._source.highlights != null) {
|
||||
ctx._source.highlights[0].labels.removeIf(label -> label.name == params.label)
|
||||
}
|
||||
if (ctx._source.labels != null) {
|
||||
ctx._source.labels.removeIf(label -> label.name == params.label)
|
||||
}`,
|
||||
lang: 'painless',
|
||||
params: {
|
||||
label: label,
|
||||
|
|
@ -113,12 +116,12 @@ export const deleteLabelInPages = async (
|
|||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
term: {
|
||||
userId,
|
||||
},
|
||||
must: {
|
||||
term: {
|
||||
userId: ctx.uid,
|
||||
},
|
||||
},
|
||||
should: [
|
||||
{
|
||||
nested: {
|
||||
path: 'labels',
|
||||
|
|
@ -129,11 +132,28 @@ export const deleteLabelInPages = async (
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
nested: {
|
||||
path: 'highlights',
|
||||
query: {
|
||||
nested: {
|
||||
path: 'highlights.labels',
|
||||
query: {
|
||||
term: {
|
||||
'highlights.labels.name': label,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
refresh: ctx.refresh,
|
||||
conflicts: 'proceed', // ignore conflicts
|
||||
})
|
||||
|
||||
body.updated > 0 &&
|
||||
|
|
@ -146,7 +166,7 @@ export const deleteLabelInPages = async (
|
|||
}
|
||||
}
|
||||
|
||||
export const updateLabelInPage = async (
|
||||
export const updateLabel = async (
|
||||
label: Label,
|
||||
ctx: PageContext
|
||||
): Promise<boolean> => {
|
||||
|
|
@ -155,8 +175,14 @@ export const updateLabelInPage = async (
|
|||
index: INDEX_ALIAS,
|
||||
body: {
|
||||
script: {
|
||||
source: `ctx._source.labels.removeIf(l -> l.id == params.label.id);
|
||||
ctx._source.labels.add(params.label)`,
|
||||
source: `if (ctx._source.labels != null) {
|
||||
ctx._source.labels.removeIf(l -> l.id == params.label.id);
|
||||
ctx._source.labels.add(params.label)
|
||||
}
|
||||
if (ctx._source.highlights != null) {
|
||||
ctx._source.highlights[0].labels.removeIf(l -> l.id == params.label.id);
|
||||
ctx._source.highlights[0].labels.add(params.label)
|
||||
}`,
|
||||
lang: 'painless',
|
||||
params: {
|
||||
label: label,
|
||||
|
|
@ -164,12 +190,12 @@ export const updateLabelInPage = async (
|
|||
},
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
term: {
|
||||
userId: ctx.uid,
|
||||
},
|
||||
must: {
|
||||
term: {
|
||||
userId: ctx.uid,
|
||||
},
|
||||
},
|
||||
should: [
|
||||
{
|
||||
nested: {
|
||||
path: 'labels',
|
||||
|
|
@ -180,7 +206,23 @@ export const updateLabelInPage = async (
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
nested: {
|
||||
path: 'highlights',
|
||||
query: {
|
||||
nested: {
|
||||
path: 'highlights.labels',
|
||||
query: {
|
||||
term: {
|
||||
'highlights.labels.id': label.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -198,3 +240,60 @@ export const updateLabelInPage = async (
|
|||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const setLabelsForHighlight = async (
|
||||
highlightId: string,
|
||||
labels: Label[],
|
||||
ctx: PageContext
|
||||
): Promise<boolean> => {
|
||||
try {
|
||||
const { body } = await client.updateByQuery({
|
||||
index: INDEX_ALIAS,
|
||||
body: {
|
||||
script: {
|
||||
source: `ctx._source.highlights[0].labels = params.labels`,
|
||||
lang: 'painless',
|
||||
params: {
|
||||
labels: labels,
|
||||
},
|
||||
},
|
||||
query: {
|
||||
nested: {
|
||||
path: 'highlights',
|
||||
query: {
|
||||
term: {
|
||||
'highlights.id': highlightId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
refresh: ctx.refresh,
|
||||
conflicts: 'proceed', // ignore conflicts
|
||||
})
|
||||
|
||||
if (!body.updated) {
|
||||
return false
|
||||
}
|
||||
|
||||
for (const label of labels) {
|
||||
await ctx.pubsub.entityCreated<Label & { highlightId: string }>(
|
||||
EntityType.LABEL,
|
||||
{ highlightId, ...label },
|
||||
ctx.uid
|
||||
)
|
||||
}
|
||||
|
||||
return true
|
||||
} catch (e) {
|
||||
if (
|
||||
e instanceof ResponseError &&
|
||||
e.message === 'document_missing_exception'
|
||||
) {
|
||||
console.log('highlight has been deleted', highlightId)
|
||||
return false
|
||||
}
|
||||
console.error('failed to set labels for highlight in elastic', e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,7 @@ export interface Highlight {
|
|||
annotation?: string | null
|
||||
sharedAt?: Date | null
|
||||
updatedAt?: Date | null
|
||||
labels?: Label[]
|
||||
}
|
||||
|
||||
export interface Page {
|
||||
|
|
|
|||
|
|
@ -111,8 +111,8 @@ export type Article = {
|
|||
readingProgressPercent: Scalars['Float'];
|
||||
savedAt: Scalars['Date'];
|
||||
savedByViewer?: Maybe<Scalars['Boolean']>;
|
||||
sharedComment?: Maybe<Scalars['String']>;
|
||||
shareInfo?: Maybe<LinkShareInfo>;
|
||||
sharedComment?: Maybe<Scalars['String']>;
|
||||
siteIcon?: Maybe<Scalars['String']>;
|
||||
siteName?: Maybe<Scalars['String']>;
|
||||
slug: Scalars['String'];
|
||||
|
|
@ -192,6 +192,11 @@ export type ArticleSavingRequestSuccess = {
|
|||
articleSavingRequest: ArticleSavingRequest;
|
||||
};
|
||||
|
||||
export type ArticleSuccess = {
|
||||
__typename?: 'ArticleSuccess';
|
||||
article: Article;
|
||||
};
|
||||
|
||||
export type ArticlesError = {
|
||||
__typename?: 'ArticlesError';
|
||||
errorCodes: Array<ArticlesErrorCode>;
|
||||
|
|
@ -209,11 +214,6 @@ export type ArticlesSuccess = {
|
|||
pageInfo: PageInfo;
|
||||
};
|
||||
|
||||
export type ArticleSuccess = {
|
||||
__typename?: 'ArticleSuccess';
|
||||
article: Article;
|
||||
};
|
||||
|
||||
export enum ContentReader {
|
||||
Pdf = 'PDF',
|
||||
Web = 'WEB'
|
||||
|
|
@ -776,6 +776,22 @@ export type LinkShareInfo = {
|
|||
title: Scalars['String'];
|
||||
};
|
||||
|
||||
export type LogOutError = {
|
||||
__typename?: 'LogOutError';
|
||||
errorCodes: Array<LogOutErrorCode>;
|
||||
};
|
||||
|
||||
export enum LogOutErrorCode {
|
||||
LogOutFailed = 'LOG_OUT_FAILED'
|
||||
}
|
||||
|
||||
export type LogOutResult = LogOutError | LogOutSuccess;
|
||||
|
||||
export type LogOutSuccess = {
|
||||
__typename?: 'LogOutSuccess';
|
||||
message?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type LoginError = {
|
||||
__typename?: 'LoginError';
|
||||
errorCodes: Array<LoginErrorCode>;
|
||||
|
|
@ -802,22 +818,6 @@ export type LoginSuccess = {
|
|||
me: User;
|
||||
};
|
||||
|
||||
export type LogOutError = {
|
||||
__typename?: 'LogOutError';
|
||||
errorCodes: Array<LogOutErrorCode>;
|
||||
};
|
||||
|
||||
export enum LogOutErrorCode {
|
||||
LogOutFailed = 'LOG_OUT_FAILED'
|
||||
}
|
||||
|
||||
export type LogOutResult = LogOutError | LogOutSuccess;
|
||||
|
||||
export type LogOutSuccess = {
|
||||
__typename?: 'LogOutSuccess';
|
||||
message?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type MergeHighlightError = {
|
||||
__typename?: 'MergeHighlightError';
|
||||
errorCodes: Array<MergeHighlightErrorCode>;
|
||||
|
|
@ -872,8 +872,8 @@ export type Mutation = {
|
|||
generateApiKey: GenerateApiKeyResult;
|
||||
googleLogin: LoginResult;
|
||||
googleSignup: GoogleSignupResult;
|
||||
login: LoginResult;
|
||||
logOut: LogOutResult;
|
||||
login: LoginResult;
|
||||
mergeHighlight: MergeHighlightResult;
|
||||
reportItem: ReportItemResult;
|
||||
revokeApiKey: RevokeApiKeyResult;
|
||||
|
|
@ -885,6 +885,7 @@ export type Mutation = {
|
|||
setDeviceToken: SetDeviceTokenResult;
|
||||
setFollow: SetFollowResult;
|
||||
setLabels: SetLabelsResult;
|
||||
setLabelsForHighlight: SetLabelsResult;
|
||||
setLinkArchived: ArchiveLinkResult;
|
||||
setShareArticle: SetShareArticleResult;
|
||||
setShareHighlight: SetShareHighlightResult;
|
||||
|
|
@ -1056,6 +1057,11 @@ export type MutationSetLabelsArgs = {
|
|||
};
|
||||
|
||||
|
||||
export type MutationSetLabelsForHighlightArgs = {
|
||||
input: SetLabelsForHighlightInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationSetLinkArchivedArgs = {
|
||||
input: ArchiveLinkInput;
|
||||
};
|
||||
|
|
@ -1234,8 +1240,8 @@ export type Query = {
|
|||
__typename?: 'Query';
|
||||
apiKeys: ApiKeysResult;
|
||||
article: ArticleResult;
|
||||
articles: ArticlesResult;
|
||||
articleSavingRequest: ArticleSavingRequestResult;
|
||||
articles: ArticlesResult;
|
||||
feedArticles: FeedArticlesResult;
|
||||
getFollowers: GetFollowersResult;
|
||||
getFollowing: GetFollowingResult;
|
||||
|
|
@ -1263,6 +1269,11 @@ export type QueryArticleArgs = {
|
|||
};
|
||||
|
||||
|
||||
export type QueryArticleSavingRequestArgs = {
|
||||
id: Scalars['ID'];
|
||||
};
|
||||
|
||||
|
||||
export type QueryArticlesArgs = {
|
||||
after?: InputMaybe<Scalars['String']>;
|
||||
first?: InputMaybe<Scalars['Int']>;
|
||||
|
|
@ -1273,11 +1284,6 @@ export type QueryArticlesArgs = {
|
|||
};
|
||||
|
||||
|
||||
export type QueryArticleSavingRequestArgs = {
|
||||
id: Scalars['ID'];
|
||||
};
|
||||
|
||||
|
||||
export type QueryFeedArticlesArgs = {
|
||||
after?: InputMaybe<Scalars['String']>;
|
||||
first?: InputMaybe<Scalars['Int']>;
|
||||
|
|
@ -1643,6 +1649,11 @@ export enum SetLabelsErrorCode {
|
|||
Unauthorized = 'UNAUTHORIZED'
|
||||
}
|
||||
|
||||
export type SetLabelsForHighlightInput = {
|
||||
highlightId: Scalars['ID'];
|
||||
labelIds: Array<Scalars['ID']>;
|
||||
};
|
||||
|
||||
export type SetLabelsInput = {
|
||||
labelIds: Array<Scalars['ID']>;
|
||||
pageId: Scalars['ID'];
|
||||
|
|
@ -1757,6 +1768,13 @@ export type SetWebhookSuccess = {
|
|||
webhook: Webhook;
|
||||
};
|
||||
|
||||
export type ShareStats = {
|
||||
__typename?: 'ShareStats';
|
||||
readDuration: Scalars['Int'];
|
||||
saveCount: Scalars['Int'];
|
||||
viewCount: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type SharedArticleError = {
|
||||
__typename?: 'SharedArticleError';
|
||||
errorCodes: Array<SharedArticleErrorCode>;
|
||||
|
|
@ -1773,13 +1791,6 @@ export type SharedArticleSuccess = {
|
|||
article: Article;
|
||||
};
|
||||
|
||||
export type ShareStats = {
|
||||
__typename?: 'ShareStats';
|
||||
readDuration: Scalars['Int'];
|
||||
saveCount: Scalars['Int'];
|
||||
viewCount: Scalars['Int'];
|
||||
};
|
||||
|
||||
export type SignupError = {
|
||||
__typename?: 'SignupError';
|
||||
errorCodes: Array<Maybe<SignupErrorCode>>;
|
||||
|
|
@ -1861,6 +1872,12 @@ export type Subscription = {
|
|||
url?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export enum SubscriptionStatus {
|
||||
Active = 'ACTIVE',
|
||||
Deleted = 'DELETED',
|
||||
Unsubscribed = 'UNSUBSCRIBED'
|
||||
}
|
||||
|
||||
export type SubscriptionsError = {
|
||||
__typename?: 'SubscriptionsError';
|
||||
errorCodes: Array<SubscriptionsErrorCode>;
|
||||
|
|
@ -1878,12 +1895,6 @@ export type SubscriptionsSuccess = {
|
|||
subscriptions: Array<Subscription>;
|
||||
};
|
||||
|
||||
export enum SubscriptionStatus {
|
||||
Active = 'ACTIVE',
|
||||
Deleted = 'DELETED',
|
||||
Unsubscribed = 'UNSUBSCRIBED'
|
||||
}
|
||||
|
||||
export type UnsubscribeError = {
|
||||
__typename?: 'UnsubscribeError';
|
||||
errorCodes: Array<UnsubscribeErrorCode>;
|
||||
|
|
@ -2200,6 +2211,11 @@ export type UserPersonalization = {
|
|||
|
||||
export type UserResult = UserError | UserSuccess;
|
||||
|
||||
export type UserSuccess = {
|
||||
__typename?: 'UserSuccess';
|
||||
user: User;
|
||||
};
|
||||
|
||||
export type UsersError = {
|
||||
__typename?: 'UsersError';
|
||||
errorCodes: Array<UsersErrorCode>;
|
||||
|
|
@ -2216,11 +2232,6 @@ export type UsersSuccess = {
|
|||
users: Array<User>;
|
||||
};
|
||||
|
||||
export type UserSuccess = {
|
||||
__typename?: 'UserSuccess';
|
||||
user: User;
|
||||
};
|
||||
|
||||
export type Webhook = {
|
||||
__typename?: 'Webhook';
|
||||
contentType: Scalars['String'];
|
||||
|
|
@ -2258,6 +2269,11 @@ export enum WebhookEvent {
|
|||
|
||||
export type WebhookResult = WebhookError | WebhookSuccess;
|
||||
|
||||
export type WebhookSuccess = {
|
||||
__typename?: 'WebhookSuccess';
|
||||
webhook: Webhook;
|
||||
};
|
||||
|
||||
export type WebhooksError = {
|
||||
__typename?: 'WebhooksError';
|
||||
errorCodes: Array<WebhooksErrorCode>;
|
||||
|
|
@ -2275,11 +2291,6 @@ export type WebhooksSuccess = {
|
|||
webhooks: Array<Webhook>;
|
||||
};
|
||||
|
||||
export type WebhookSuccess = {
|
||||
__typename?: 'WebhookSuccess';
|
||||
webhook: Webhook;
|
||||
};
|
||||
|
||||
|
||||
|
||||
export type ResolverTypeWrapper<T> = Promise<T> | T;
|
||||
|
|
@ -2375,11 +2386,11 @@ export type ResolversTypes = {
|
|||
ArticleSavingRequestResult: ResolversTypes['ArticleSavingRequestError'] | ResolversTypes['ArticleSavingRequestSuccess'];
|
||||
ArticleSavingRequestStatus: ArticleSavingRequestStatus;
|
||||
ArticleSavingRequestSuccess: ResolverTypeWrapper<ArticleSavingRequestSuccess>;
|
||||
ArticleSuccess: ResolverTypeWrapper<ArticleSuccess>;
|
||||
ArticlesError: ResolverTypeWrapper<ArticlesError>;
|
||||
ArticlesErrorCode: ArticlesErrorCode;
|
||||
ArticlesResult: ResolversTypes['ArticlesError'] | ResolversTypes['ArticlesSuccess'];
|
||||
ArticlesSuccess: ResolverTypeWrapper<ArticlesSuccess>;
|
||||
ArticleSuccess: ResolverTypeWrapper<ArticleSuccess>;
|
||||
Boolean: ResolverTypeWrapper<Scalars['Boolean']>;
|
||||
ContentReader: ContentReader;
|
||||
CreateArticleError: ResolverTypeWrapper<CreateArticleError>;
|
||||
|
|
@ -2492,15 +2503,15 @@ export type ResolversTypes = {
|
|||
LabelsSuccess: ResolverTypeWrapper<LabelsSuccess>;
|
||||
Link: ResolverTypeWrapper<Link>;
|
||||
LinkShareInfo: ResolverTypeWrapper<LinkShareInfo>;
|
||||
LogOutError: ResolverTypeWrapper<LogOutError>;
|
||||
LogOutErrorCode: LogOutErrorCode;
|
||||
LogOutResult: ResolversTypes['LogOutError'] | ResolversTypes['LogOutSuccess'];
|
||||
LogOutSuccess: ResolverTypeWrapper<LogOutSuccess>;
|
||||
LoginError: ResolverTypeWrapper<LoginError>;
|
||||
LoginErrorCode: LoginErrorCode;
|
||||
LoginInput: LoginInput;
|
||||
LoginResult: ResolversTypes['LoginError'] | ResolversTypes['LoginSuccess'];
|
||||
LoginSuccess: ResolverTypeWrapper<LoginSuccess>;
|
||||
LogOutError: ResolverTypeWrapper<LogOutError>;
|
||||
LogOutErrorCode: LogOutErrorCode;
|
||||
LogOutResult: ResolversTypes['LogOutError'] | ResolversTypes['LogOutSuccess'];
|
||||
LogOutSuccess: ResolverTypeWrapper<LogOutSuccess>;
|
||||
MergeHighlightError: ResolverTypeWrapper<MergeHighlightError>;
|
||||
MergeHighlightErrorCode: MergeHighlightErrorCode;
|
||||
MergeHighlightInput: MergeHighlightInput;
|
||||
|
|
@ -2573,6 +2584,7 @@ export type ResolversTypes = {
|
|||
SetFollowSuccess: ResolverTypeWrapper<SetFollowSuccess>;
|
||||
SetLabelsError: ResolverTypeWrapper<SetLabelsError>;
|
||||
SetLabelsErrorCode: SetLabelsErrorCode;
|
||||
SetLabelsForHighlightInput: SetLabelsForHighlightInput;
|
||||
SetLabelsInput: SetLabelsInput;
|
||||
SetLabelsResult: ResolversTypes['SetLabelsError'] | ResolversTypes['SetLabelsSuccess'];
|
||||
SetLabelsSuccess: ResolverTypeWrapper<SetLabelsSuccess>;
|
||||
|
|
@ -2596,11 +2608,11 @@ export type ResolversTypes = {
|
|||
SetWebhookInput: SetWebhookInput;
|
||||
SetWebhookResult: ResolversTypes['SetWebhookError'] | ResolversTypes['SetWebhookSuccess'];
|
||||
SetWebhookSuccess: ResolverTypeWrapper<SetWebhookSuccess>;
|
||||
ShareStats: ResolverTypeWrapper<ShareStats>;
|
||||
SharedArticleError: ResolverTypeWrapper<SharedArticleError>;
|
||||
SharedArticleErrorCode: SharedArticleErrorCode;
|
||||
SharedArticleResult: ResolversTypes['SharedArticleError'] | ResolversTypes['SharedArticleSuccess'];
|
||||
SharedArticleSuccess: ResolverTypeWrapper<SharedArticleSuccess>;
|
||||
ShareStats: ResolverTypeWrapper<ShareStats>;
|
||||
SignupError: ResolverTypeWrapper<SignupError>;
|
||||
SignupErrorCode: SignupErrorCode;
|
||||
SignupInput: SignupInput;
|
||||
|
|
@ -2615,11 +2627,11 @@ export type ResolversTypes = {
|
|||
SubscribeResult: ResolversTypes['SubscribeError'] | ResolversTypes['SubscribeSuccess'];
|
||||
SubscribeSuccess: ResolverTypeWrapper<SubscribeSuccess>;
|
||||
Subscription: ResolverTypeWrapper<{}>;
|
||||
SubscriptionStatus: SubscriptionStatus;
|
||||
SubscriptionsError: ResolverTypeWrapper<SubscriptionsError>;
|
||||
SubscriptionsErrorCode: SubscriptionsErrorCode;
|
||||
SubscriptionsResult: ResolversTypes['SubscriptionsError'] | ResolversTypes['SubscriptionsSuccess'];
|
||||
SubscriptionsSuccess: ResolverTypeWrapper<SubscriptionsSuccess>;
|
||||
SubscriptionStatus: SubscriptionStatus;
|
||||
UnsubscribeError: ResolverTypeWrapper<UnsubscribeError>;
|
||||
UnsubscribeErrorCode: UnsubscribeErrorCode;
|
||||
UnsubscribeResult: ResolversTypes['UnsubscribeError'] | ResolversTypes['UnsubscribeSuccess'];
|
||||
|
|
@ -2680,21 +2692,21 @@ export type ResolversTypes = {
|
|||
UserErrorCode: UserErrorCode;
|
||||
UserPersonalization: ResolverTypeWrapper<UserPersonalization>;
|
||||
UserResult: ResolversTypes['UserError'] | ResolversTypes['UserSuccess'];
|
||||
UserSuccess: ResolverTypeWrapper<UserSuccess>;
|
||||
UsersError: ResolverTypeWrapper<UsersError>;
|
||||
UsersErrorCode: UsersErrorCode;
|
||||
UsersResult: ResolversTypes['UsersError'] | ResolversTypes['UsersSuccess'];
|
||||
UsersSuccess: ResolverTypeWrapper<UsersSuccess>;
|
||||
UserSuccess: ResolverTypeWrapper<UserSuccess>;
|
||||
Webhook: ResolverTypeWrapper<Webhook>;
|
||||
WebhookError: ResolverTypeWrapper<WebhookError>;
|
||||
WebhookErrorCode: WebhookErrorCode;
|
||||
WebhookEvent: WebhookEvent;
|
||||
WebhookResult: ResolversTypes['WebhookError'] | ResolversTypes['WebhookSuccess'];
|
||||
WebhookSuccess: ResolverTypeWrapper<WebhookSuccess>;
|
||||
WebhooksError: ResolverTypeWrapper<WebhooksError>;
|
||||
WebhooksErrorCode: WebhooksErrorCode;
|
||||
WebhooksResult: ResolversTypes['WebhooksError'] | ResolversTypes['WebhooksSuccess'];
|
||||
WebhooksSuccess: ResolverTypeWrapper<WebhooksSuccess>;
|
||||
WebhookSuccess: ResolverTypeWrapper<WebhookSuccess>;
|
||||
};
|
||||
|
||||
/** Mapping between all available schema types and the resolvers parents */
|
||||
|
|
@ -2719,10 +2731,10 @@ export type ResolversParentTypes = {
|
|||
ArticleSavingRequestError: ArticleSavingRequestError;
|
||||
ArticleSavingRequestResult: ResolversParentTypes['ArticleSavingRequestError'] | ResolversParentTypes['ArticleSavingRequestSuccess'];
|
||||
ArticleSavingRequestSuccess: ArticleSavingRequestSuccess;
|
||||
ArticleSuccess: ArticleSuccess;
|
||||
ArticlesError: ArticlesError;
|
||||
ArticlesResult: ResolversParentTypes['ArticlesError'] | ResolversParentTypes['ArticlesSuccess'];
|
||||
ArticlesSuccess: ArticlesSuccess;
|
||||
ArticleSuccess: ArticleSuccess;
|
||||
Boolean: Scalars['Boolean'];
|
||||
CreateArticleError: CreateArticleError;
|
||||
CreateArticleInput: CreateArticleInput;
|
||||
|
|
@ -2813,13 +2825,13 @@ export type ResolversParentTypes = {
|
|||
LabelsSuccess: LabelsSuccess;
|
||||
Link: Link;
|
||||
LinkShareInfo: LinkShareInfo;
|
||||
LogOutError: LogOutError;
|
||||
LogOutResult: ResolversParentTypes['LogOutError'] | ResolversParentTypes['LogOutSuccess'];
|
||||
LogOutSuccess: LogOutSuccess;
|
||||
LoginError: LoginError;
|
||||
LoginInput: LoginInput;
|
||||
LoginResult: ResolversParentTypes['LoginError'] | ResolversParentTypes['LoginSuccess'];
|
||||
LoginSuccess: LoginSuccess;
|
||||
LogOutError: LogOutError;
|
||||
LogOutResult: ResolversParentTypes['LogOutError'] | ResolversParentTypes['LogOutSuccess'];
|
||||
LogOutSuccess: LogOutSuccess;
|
||||
MergeHighlightError: MergeHighlightError;
|
||||
MergeHighlightInput: MergeHighlightInput;
|
||||
MergeHighlightResult: ResolversParentTypes['MergeHighlightError'] | ResolversParentTypes['MergeHighlightSuccess'];
|
||||
|
|
@ -2877,6 +2889,7 @@ export type ResolversParentTypes = {
|
|||
SetFollowResult: ResolversParentTypes['SetFollowError'] | ResolversParentTypes['SetFollowSuccess'];
|
||||
SetFollowSuccess: SetFollowSuccess;
|
||||
SetLabelsError: SetLabelsError;
|
||||
SetLabelsForHighlightInput: SetLabelsForHighlightInput;
|
||||
SetLabelsInput: SetLabelsInput;
|
||||
SetLabelsResult: ResolversParentTypes['SetLabelsError'] | ResolversParentTypes['SetLabelsSuccess'];
|
||||
SetLabelsSuccess: SetLabelsSuccess;
|
||||
|
|
@ -2896,10 +2909,10 @@ export type ResolversParentTypes = {
|
|||
SetWebhookInput: SetWebhookInput;
|
||||
SetWebhookResult: ResolversParentTypes['SetWebhookError'] | ResolversParentTypes['SetWebhookSuccess'];
|
||||
SetWebhookSuccess: SetWebhookSuccess;
|
||||
ShareStats: ShareStats;
|
||||
SharedArticleError: SharedArticleError;
|
||||
SharedArticleResult: ResolversParentTypes['SharedArticleError'] | ResolversParentTypes['SharedArticleSuccess'];
|
||||
SharedArticleSuccess: SharedArticleSuccess;
|
||||
ShareStats: ShareStats;
|
||||
SignupError: SignupError;
|
||||
SignupInput: SignupInput;
|
||||
SignupResult: ResolversParentTypes['SignupError'] | ResolversParentTypes['SignupSuccess'];
|
||||
|
|
@ -2960,17 +2973,17 @@ export type ResolversParentTypes = {
|
|||
UserError: UserError;
|
||||
UserPersonalization: UserPersonalization;
|
||||
UserResult: ResolversParentTypes['UserError'] | ResolversParentTypes['UserSuccess'];
|
||||
UserSuccess: UserSuccess;
|
||||
UsersError: UsersError;
|
||||
UsersResult: ResolversParentTypes['UsersError'] | ResolversParentTypes['UsersSuccess'];
|
||||
UsersSuccess: UsersSuccess;
|
||||
UserSuccess: UserSuccess;
|
||||
Webhook: Webhook;
|
||||
WebhookError: WebhookError;
|
||||
WebhookResult: ResolversParentTypes['WebhookError'] | ResolversParentTypes['WebhookSuccess'];
|
||||
WebhookSuccess: WebhookSuccess;
|
||||
WebhooksError: WebhooksError;
|
||||
WebhooksResult: ResolversParentTypes['WebhooksError'] | ResolversParentTypes['WebhooksSuccess'];
|
||||
WebhooksSuccess: WebhooksSuccess;
|
||||
WebhookSuccess: WebhookSuccess;
|
||||
};
|
||||
|
||||
export type SanitizeDirectiveArgs = {
|
||||
|
|
@ -3060,8 +3073,8 @@ export type ArticleResolvers<ContextType = ResolverContext, ParentType extends R
|
|||
readingProgressPercent?: Resolver<ResolversTypes['Float'], ParentType, ContextType>;
|
||||
savedAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
|
||||
savedByViewer?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
|
||||
sharedComment?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
shareInfo?: Resolver<Maybe<ResolversTypes['LinkShareInfo']>, ParentType, ContextType>;
|
||||
sharedComment?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
siteIcon?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
siteName?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
slug?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
|
|
@ -3118,6 +3131,11 @@ export type ArticleSavingRequestSuccessResolvers<ContextType = ResolverContext,
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type ArticleSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['ArticleSuccess'] = ResolversParentTypes['ArticleSuccess']> = {
|
||||
article?: Resolver<ResolversTypes['Article'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type ArticlesErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['ArticlesError'] = ResolversParentTypes['ArticlesError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['ArticlesErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -3133,11 +3151,6 @@ export type ArticlesSuccessResolvers<ContextType = ResolverContext, ParentType e
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type ArticleSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['ArticleSuccess'] = ResolversParentTypes['ArticleSuccess']> = {
|
||||
article?: Resolver<ResolversTypes['Article'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type CreateArticleErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['CreateArticleError'] = ResolversParentTypes['CreateArticleError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['CreateArticleErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -3546,20 +3559,6 @@ export type LinkShareInfoResolvers<ContextType = ResolverContext, ParentType ext
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type LoginErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['LoginError'] = ResolversParentTypes['LoginError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['LoginErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type LoginResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['LoginResult'] = ResolversParentTypes['LoginResult']> = {
|
||||
__resolveType: TypeResolveFn<'LoginError' | 'LoginSuccess', ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type LoginSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['LoginSuccess'] = ResolversParentTypes['LoginSuccess']> = {
|
||||
me?: Resolver<ResolversTypes['User'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type LogOutErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['LogOutError'] = ResolversParentTypes['LogOutError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['LogOutErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -3574,6 +3573,20 @@ export type LogOutSuccessResolvers<ContextType = ResolverContext, ParentType ext
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type LoginErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['LoginError'] = ResolversParentTypes['LoginError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['LoginErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type LoginResultResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['LoginResult'] = ResolversParentTypes['LoginResult']> = {
|
||||
__resolveType: TypeResolveFn<'LoginError' | 'LoginSuccess', ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type LoginSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['LoginSuccess'] = ResolversParentTypes['LoginSuccess']> = {
|
||||
me?: Resolver<ResolversTypes['User'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type MergeHighlightErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['MergeHighlightError'] = ResolversParentTypes['MergeHighlightError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['MergeHighlightErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -3609,8 +3622,8 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
|
|||
generateApiKey?: Resolver<ResolversTypes['GenerateApiKeyResult'], ParentType, ContextType, RequireFields<MutationGenerateApiKeyArgs, 'input'>>;
|
||||
googleLogin?: Resolver<ResolversTypes['LoginResult'], ParentType, ContextType, RequireFields<MutationGoogleLoginArgs, 'input'>>;
|
||||
googleSignup?: Resolver<ResolversTypes['GoogleSignupResult'], ParentType, ContextType, RequireFields<MutationGoogleSignupArgs, 'input'>>;
|
||||
login?: Resolver<ResolversTypes['LoginResult'], ParentType, ContextType, RequireFields<MutationLoginArgs, 'input'>>;
|
||||
logOut?: Resolver<ResolversTypes['LogOutResult'], ParentType, ContextType>;
|
||||
login?: Resolver<ResolversTypes['LoginResult'], ParentType, ContextType, RequireFields<MutationLoginArgs, 'input'>>;
|
||||
mergeHighlight?: Resolver<ResolversTypes['MergeHighlightResult'], ParentType, ContextType, RequireFields<MutationMergeHighlightArgs, 'input'>>;
|
||||
reportItem?: Resolver<ResolversTypes['ReportItemResult'], ParentType, ContextType, RequireFields<MutationReportItemArgs, 'input'>>;
|
||||
revokeApiKey?: Resolver<ResolversTypes['RevokeApiKeyResult'], ParentType, ContextType, RequireFields<MutationRevokeApiKeyArgs, 'id'>>;
|
||||
|
|
@ -3622,6 +3635,7 @@ export type MutationResolvers<ContextType = ResolverContext, ParentType extends
|
|||
setDeviceToken?: Resolver<ResolversTypes['SetDeviceTokenResult'], ParentType, ContextType, RequireFields<MutationSetDeviceTokenArgs, 'input'>>;
|
||||
setFollow?: Resolver<ResolversTypes['SetFollowResult'], ParentType, ContextType, RequireFields<MutationSetFollowArgs, 'input'>>;
|
||||
setLabels?: Resolver<ResolversTypes['SetLabelsResult'], ParentType, ContextType, RequireFields<MutationSetLabelsArgs, 'input'>>;
|
||||
setLabelsForHighlight?: Resolver<ResolversTypes['SetLabelsResult'], ParentType, ContextType, RequireFields<MutationSetLabelsForHighlightArgs, 'input'>>;
|
||||
setLinkArchived?: Resolver<ResolversTypes['ArchiveLinkResult'], ParentType, ContextType, RequireFields<MutationSetLinkArchivedArgs, 'input'>>;
|
||||
setShareArticle?: Resolver<ResolversTypes['SetShareArticleResult'], ParentType, ContextType, RequireFields<MutationSetShareArticleArgs, 'input'>>;
|
||||
setShareHighlight?: Resolver<ResolversTypes['SetShareHighlightResult'], ParentType, ContextType, RequireFields<MutationSetShareHighlightArgs, 'input'>>;
|
||||
|
|
@ -3702,8 +3716,8 @@ export type ProfileResolvers<ContextType = ResolverContext, ParentType extends R
|
|||
export type QueryResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query']> = {
|
||||
apiKeys?: Resolver<ResolversTypes['ApiKeysResult'], ParentType, ContextType>;
|
||||
article?: Resolver<ResolversTypes['ArticleResult'], ParentType, ContextType, RequireFields<QueryArticleArgs, 'slug' | 'username'>>;
|
||||
articles?: Resolver<ResolversTypes['ArticlesResult'], ParentType, ContextType, Partial<QueryArticlesArgs>>;
|
||||
articleSavingRequest?: Resolver<ResolversTypes['ArticleSavingRequestResult'], ParentType, ContextType, RequireFields<QueryArticleSavingRequestArgs, 'id'>>;
|
||||
articles?: Resolver<ResolversTypes['ArticlesResult'], ParentType, ContextType, Partial<QueryArticlesArgs>>;
|
||||
feedArticles?: Resolver<ResolversTypes['FeedArticlesResult'], ParentType, ContextType, Partial<QueryFeedArticlesArgs>>;
|
||||
getFollowers?: Resolver<ResolversTypes['GetFollowersResult'], ParentType, ContextType, Partial<QueryGetFollowersArgs>>;
|
||||
getFollowing?: Resolver<ResolversTypes['GetFollowingResult'], ParentType, ContextType, Partial<QueryGetFollowingArgs>>;
|
||||
|
|
@ -3995,6 +4009,13 @@ export type SetWebhookSuccessResolvers<ContextType = ResolverContext, ParentType
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type ShareStatsResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['ShareStats'] = ResolversParentTypes['ShareStats']> = {
|
||||
readDuration?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
||||
saveCount?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
||||
viewCount?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type SharedArticleErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['SharedArticleError'] = ResolversParentTypes['SharedArticleError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['SharedArticleErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -4009,13 +4030,6 @@ export type SharedArticleSuccessResolvers<ContextType = ResolverContext, ParentT
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type ShareStatsResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['ShareStats'] = ResolversParentTypes['ShareStats']> = {
|
||||
readDuration?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
||||
saveCount?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
||||
viewCount?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type SignupErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['SignupError'] = ResolversParentTypes['SignupError']> = {
|
||||
errorCodes?: Resolver<Array<Maybe<ResolversTypes['SignupErrorCode']>>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -4265,6 +4279,11 @@ export type UserResultResolvers<ContextType = ResolverContext, ParentType extend
|
|||
__resolveType: TypeResolveFn<'UserError' | 'UserSuccess', ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type UserSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UserSuccess'] = ResolversParentTypes['UserSuccess']> = {
|
||||
user?: Resolver<ResolversTypes['User'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type UsersErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UsersError'] = ResolversParentTypes['UsersError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['UsersErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -4279,11 +4298,6 @@ export type UsersSuccessResolvers<ContextType = ResolverContext, ParentType exte
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type UserSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['UserSuccess'] = ResolversParentTypes['UserSuccess']> = {
|
||||
user?: Resolver<ResolversTypes['User'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type WebhookResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['Webhook'] = ResolversParentTypes['Webhook']> = {
|
||||
contentType?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
createdAt?: Resolver<ResolversTypes['Date'], ParentType, ContextType>;
|
||||
|
|
@ -4305,6 +4319,11 @@ export type WebhookResultResolvers<ContextType = ResolverContext, ParentType ext
|
|||
__resolveType: TypeResolveFn<'WebhookError' | 'WebhookSuccess', ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type WebhookSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['WebhookSuccess'] = ResolversParentTypes['WebhookSuccess']> = {
|
||||
webhook?: Resolver<ResolversTypes['Webhook'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type WebhooksErrorResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['WebhooksError'] = ResolversParentTypes['WebhooksError']> = {
|
||||
errorCodes?: Resolver<Array<ResolversTypes['WebhooksErrorCode']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
|
|
@ -4319,11 +4338,6 @@ export type WebhooksSuccessResolvers<ContextType = ResolverContext, ParentType e
|
|||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type WebhookSuccessResolvers<ContextType = ResolverContext, ParentType extends ResolversParentTypes['WebhookSuccess'] = ResolversParentTypes['WebhookSuccess']> = {
|
||||
webhook?: Resolver<ResolversTypes['Webhook'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
};
|
||||
|
||||
export type Resolvers<ContextType = ResolverContext> = {
|
||||
AddPopularReadError?: AddPopularReadErrorResolvers<ContextType>;
|
||||
AddPopularReadResult?: AddPopularReadResultResolvers<ContextType>;
|
||||
|
|
@ -4343,10 +4357,10 @@ export type Resolvers<ContextType = ResolverContext> = {
|
|||
ArticleSavingRequestError?: ArticleSavingRequestErrorResolvers<ContextType>;
|
||||
ArticleSavingRequestResult?: ArticleSavingRequestResultResolvers<ContextType>;
|
||||
ArticleSavingRequestSuccess?: ArticleSavingRequestSuccessResolvers<ContextType>;
|
||||
ArticleSuccess?: ArticleSuccessResolvers<ContextType>;
|
||||
ArticlesError?: ArticlesErrorResolvers<ContextType>;
|
||||
ArticlesResult?: ArticlesResultResolvers<ContextType>;
|
||||
ArticlesSuccess?: ArticlesSuccessResolvers<ContextType>;
|
||||
ArticleSuccess?: ArticleSuccessResolvers<ContextType>;
|
||||
CreateArticleError?: CreateArticleErrorResolvers<ContextType>;
|
||||
CreateArticleResult?: CreateArticleResultResolvers<ContextType>;
|
||||
CreateArticleSavingRequestError?: CreateArticleSavingRequestErrorResolvers<ContextType>;
|
||||
|
|
@ -4423,12 +4437,12 @@ export type Resolvers<ContextType = ResolverContext> = {
|
|||
LabelsSuccess?: LabelsSuccessResolvers<ContextType>;
|
||||
Link?: LinkResolvers<ContextType>;
|
||||
LinkShareInfo?: LinkShareInfoResolvers<ContextType>;
|
||||
LoginError?: LoginErrorResolvers<ContextType>;
|
||||
LoginResult?: LoginResultResolvers<ContextType>;
|
||||
LoginSuccess?: LoginSuccessResolvers<ContextType>;
|
||||
LogOutError?: LogOutErrorResolvers<ContextType>;
|
||||
LogOutResult?: LogOutResultResolvers<ContextType>;
|
||||
LogOutSuccess?: LogOutSuccessResolvers<ContextType>;
|
||||
LoginError?: LoginErrorResolvers<ContextType>;
|
||||
LoginResult?: LoginResultResolvers<ContextType>;
|
||||
LoginSuccess?: LoginSuccessResolvers<ContextType>;
|
||||
MergeHighlightError?: MergeHighlightErrorResolvers<ContextType>;
|
||||
MergeHighlightResult?: MergeHighlightResultResolvers<ContextType>;
|
||||
MergeHighlightSuccess?: MergeHighlightSuccessResolvers<ContextType>;
|
||||
|
|
@ -4489,10 +4503,10 @@ export type Resolvers<ContextType = ResolverContext> = {
|
|||
SetWebhookError?: SetWebhookErrorResolvers<ContextType>;
|
||||
SetWebhookResult?: SetWebhookResultResolvers<ContextType>;
|
||||
SetWebhookSuccess?: SetWebhookSuccessResolvers<ContextType>;
|
||||
ShareStats?: ShareStatsResolvers<ContextType>;
|
||||
SharedArticleError?: SharedArticleErrorResolvers<ContextType>;
|
||||
SharedArticleResult?: SharedArticleResultResolvers<ContextType>;
|
||||
SharedArticleSuccess?: SharedArticleSuccessResolvers<ContextType>;
|
||||
ShareStats?: ShareStatsResolvers<ContextType>;
|
||||
SignupError?: SignupErrorResolvers<ContextType>;
|
||||
SignupResult?: SignupResultResolvers<ContextType>;
|
||||
SignupSuccess?: SignupSuccessResolvers<ContextType>;
|
||||
|
|
@ -4540,17 +4554,17 @@ export type Resolvers<ContextType = ResolverContext> = {
|
|||
UserError?: UserErrorResolvers<ContextType>;
|
||||
UserPersonalization?: UserPersonalizationResolvers<ContextType>;
|
||||
UserResult?: UserResultResolvers<ContextType>;
|
||||
UserSuccess?: UserSuccessResolvers<ContextType>;
|
||||
UsersError?: UsersErrorResolvers<ContextType>;
|
||||
UsersResult?: UsersResultResolvers<ContextType>;
|
||||
UsersSuccess?: UsersSuccessResolvers<ContextType>;
|
||||
UserSuccess?: UserSuccessResolvers<ContextType>;
|
||||
Webhook?: WebhookResolvers<ContextType>;
|
||||
WebhookError?: WebhookErrorResolvers<ContextType>;
|
||||
WebhookResult?: WebhookResultResolvers<ContextType>;
|
||||
WebhookSuccess?: WebhookSuccessResolvers<ContextType>;
|
||||
WebhooksError?: WebhooksErrorResolvers<ContextType>;
|
||||
WebhooksResult?: WebhooksResultResolvers<ContextType>;
|
||||
WebhooksSuccess?: WebhooksSuccessResolvers<ContextType>;
|
||||
WebhookSuccess?: WebhookSuccessResolvers<ContextType>;
|
||||
};
|
||||
|
||||
export type DirectiveResolvers<ContextType = ResolverContext> = {
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ type Article {
|
|||
readingProgressPercent: Float!
|
||||
savedAt: Date!
|
||||
savedByViewer: Boolean
|
||||
sharedComment: String
|
||||
shareInfo: LinkShareInfo
|
||||
sharedComment: String
|
||||
siteIcon: String
|
||||
siteName: String
|
||||
slug: String!
|
||||
|
|
@ -156,6 +156,10 @@ type ArticleSavingRequestSuccess {
|
|||
articleSavingRequest: ArticleSavingRequest!
|
||||
}
|
||||
|
||||
type ArticleSuccess {
|
||||
article: Article!
|
||||
}
|
||||
|
||||
type ArticlesError {
|
||||
errorCodes: [ArticlesErrorCode!]!
|
||||
}
|
||||
|
|
@ -171,10 +175,6 @@ type ArticlesSuccess {
|
|||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type ArticleSuccess {
|
||||
article: Article!
|
||||
}
|
||||
|
||||
enum ContentReader {
|
||||
PDF
|
||||
WEB
|
||||
|
|
@ -686,6 +686,20 @@ type LinkShareInfo {
|
|||
title: String!
|
||||
}
|
||||
|
||||
type LogOutError {
|
||||
errorCodes: [LogOutErrorCode!]!
|
||||
}
|
||||
|
||||
enum LogOutErrorCode {
|
||||
LOG_OUT_FAILED
|
||||
}
|
||||
|
||||
union LogOutResult = LogOutError | LogOutSuccess
|
||||
|
||||
type LogOutSuccess {
|
||||
message: String
|
||||
}
|
||||
|
||||
type LoginError {
|
||||
errorCodes: [LoginErrorCode!]!
|
||||
}
|
||||
|
|
@ -710,20 +724,6 @@ type LoginSuccess {
|
|||
me: User!
|
||||
}
|
||||
|
||||
type LogOutError {
|
||||
errorCodes: [LogOutErrorCode!]!
|
||||
}
|
||||
|
||||
enum LogOutErrorCode {
|
||||
LOG_OUT_FAILED
|
||||
}
|
||||
|
||||
union LogOutResult = LogOutError | LogOutSuccess
|
||||
|
||||
type LogOutSuccess {
|
||||
message: String
|
||||
}
|
||||
|
||||
type MergeHighlightError {
|
||||
errorCodes: [MergeHighlightErrorCode!]!
|
||||
}
|
||||
|
|
@ -775,8 +775,8 @@ type Mutation {
|
|||
generateApiKey(input: GenerateApiKeyInput!): GenerateApiKeyResult!
|
||||
googleLogin(input: GoogleLoginInput!): LoginResult!
|
||||
googleSignup(input: GoogleSignupInput!): GoogleSignupResult!
|
||||
login(input: LoginInput!): LoginResult!
|
||||
logOut: LogOutResult!
|
||||
login(input: LoginInput!): LoginResult!
|
||||
mergeHighlight(input: MergeHighlightInput!): MergeHighlightResult!
|
||||
reportItem(input: ReportItemInput!): ReportItemResult!
|
||||
revokeApiKey(id: ID!): RevokeApiKeyResult!
|
||||
|
|
@ -788,6 +788,7 @@ type Mutation {
|
|||
setDeviceToken(input: SetDeviceTokenInput!): SetDeviceTokenResult!
|
||||
setFollow(input: SetFollowInput!): SetFollowResult!
|
||||
setLabels(input: SetLabelsInput!): SetLabelsResult!
|
||||
setLabelsForHighlight(input: SetLabelsForHighlightInput!): SetLabelsResult!
|
||||
setLinkArchived(input: ArchiveLinkInput!): ArchiveLinkResult!
|
||||
setShareArticle(input: SetShareArticleInput!): SetShareArticleResult!
|
||||
setShareHighlight(input: SetShareHighlightInput!): SetShareHighlightResult!
|
||||
|
|
@ -890,8 +891,8 @@ type Profile {
|
|||
type Query {
|
||||
apiKeys: ApiKeysResult!
|
||||
article(slug: String!, username: String!): ArticleResult!
|
||||
articles(after: String, first: Int, includePending: Boolean, query: String, sharedOnly: Boolean, sort: SortParams): ArticlesResult!
|
||||
articleSavingRequest(id: ID!): ArticleSavingRequestResult!
|
||||
articles(after: String, first: Int, includePending: Boolean, query: String, sharedOnly: Boolean, sort: SortParams): ArticlesResult!
|
||||
feedArticles(after: String, first: Int, sharedByUser: ID, sort: SortParams): FeedArticlesResult!
|
||||
getFollowers(userId: ID): GetFollowersResult!
|
||||
getFollowing(userId: ID): GetFollowingResult!
|
||||
|
|
@ -1195,6 +1196,11 @@ enum SetLabelsErrorCode {
|
|||
UNAUTHORIZED
|
||||
}
|
||||
|
||||
input SetLabelsForHighlightInput {
|
||||
highlightId: ID!
|
||||
labelIds: [ID!]!
|
||||
}
|
||||
|
||||
input SetLabelsInput {
|
||||
labelIds: [ID!]!
|
||||
pageId: ID!
|
||||
|
|
@ -1300,6 +1306,12 @@ type SetWebhookSuccess {
|
|||
webhook: Webhook!
|
||||
}
|
||||
|
||||
type ShareStats {
|
||||
readDuration: Int!
|
||||
saveCount: Int!
|
||||
viewCount: Int!
|
||||
}
|
||||
|
||||
type SharedArticleError {
|
||||
errorCodes: [SharedArticleErrorCode!]!
|
||||
}
|
||||
|
|
@ -1314,12 +1326,6 @@ type SharedArticleSuccess {
|
|||
article: Article!
|
||||
}
|
||||
|
||||
type ShareStats {
|
||||
readDuration: Int!
|
||||
saveCount: Int!
|
||||
viewCount: Int!
|
||||
}
|
||||
|
||||
type SignupError {
|
||||
errorCodes: [SignupErrorCode]!
|
||||
}
|
||||
|
|
@ -1396,6 +1402,12 @@ type Subscription {
|
|||
url: String
|
||||
}
|
||||
|
||||
enum SubscriptionStatus {
|
||||
ACTIVE
|
||||
DELETED
|
||||
UNSUBSCRIBED
|
||||
}
|
||||
|
||||
type SubscriptionsError {
|
||||
errorCodes: [SubscriptionsErrorCode!]!
|
||||
}
|
||||
|
|
@ -1411,12 +1423,6 @@ type SubscriptionsSuccess {
|
|||
subscriptions: [Subscription!]!
|
||||
}
|
||||
|
||||
enum SubscriptionStatus {
|
||||
ACTIVE
|
||||
DELETED
|
||||
UNSUBSCRIBED
|
||||
}
|
||||
|
||||
type UnsubscribeError {
|
||||
errorCodes: [UnsubscribeErrorCode!]!
|
||||
}
|
||||
|
|
@ -1707,6 +1713,10 @@ type UserPersonalization {
|
|||
|
||||
union UserResult = UserError | UserSuccess
|
||||
|
||||
type UserSuccess {
|
||||
user: User!
|
||||
}
|
||||
|
||||
type UsersError {
|
||||
errorCodes: [UsersErrorCode!]!
|
||||
}
|
||||
|
|
@ -1721,10 +1731,6 @@ type UsersSuccess {
|
|||
users: [User!]!
|
||||
}
|
||||
|
||||
type UserSuccess {
|
||||
user: User!
|
||||
}
|
||||
|
||||
type Webhook {
|
||||
contentType: String!
|
||||
createdAt: Date!
|
||||
|
|
@ -1760,6 +1766,10 @@ enum WebhookEvent {
|
|||
|
||||
union WebhookResult = WebhookError | WebhookSuccess
|
||||
|
||||
type WebhookSuccess {
|
||||
webhook: Webhook!
|
||||
}
|
||||
|
||||
type WebhooksError {
|
||||
errorCodes: [WebhooksErrorCode!]!
|
||||
}
|
||||
|
|
@ -1774,7 +1784,3 @@ union WebhooksResult = WebhooksError | WebhooksSuccess
|
|||
type WebhooksSuccess {
|
||||
webhooks: [Webhook!]!
|
||||
}
|
||||
|
||||
type WebhookSuccess {
|
||||
webhook: Webhook!
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ import {
|
|||
setBookmarkArticleResolver,
|
||||
setDeviceTokenResolver,
|
||||
setFollowResolver,
|
||||
setLabelsForHighlightResolver,
|
||||
setLabelsResolver,
|
||||
setLinkArchivedResolver,
|
||||
setShareArticleResolver,
|
||||
|
|
@ -161,6 +162,7 @@ export const functionResolvers = {
|
|||
setWebhook: setWebhookResolver,
|
||||
deleteWebhook: deleteWebhookResolver,
|
||||
revokeApiKey: revokeApiKeyResolver,
|
||||
setLabelsForHighlight: setLabelsForHighlightResolver,
|
||||
},
|
||||
Query: {
|
||||
me: getMeUserResolver,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
MutationCreateLabelArgs,
|
||||
MutationDeleteLabelArgs,
|
||||
MutationSetLabelsArgs,
|
||||
MutationSetLabelsForHighlightArgs,
|
||||
MutationUpdateLabelArgs,
|
||||
SetLabelsError,
|
||||
SetLabelsErrorCode,
|
||||
|
|
@ -24,16 +25,19 @@ import { analytics } from '../../utils/analytics'
|
|||
import { env } from '../../env'
|
||||
import { User } from '../../entity/user'
|
||||
import { Label } from '../../entity/label'
|
||||
import { ILike, In } from 'typeorm'
|
||||
import { ILike } from 'typeorm'
|
||||
import { getRepository, setClaims } from '../../entity/utils'
|
||||
import { createPubSubClient } from '../../datalayer/pubsub'
|
||||
import { AppDataSource } from '../../server'
|
||||
import { getPageById } from '../../elastic/pages'
|
||||
import {
|
||||
deleteLabelInPages,
|
||||
updateLabelInPage,
|
||||
deleteLabel,
|
||||
setLabelsForHighlight,
|
||||
updateLabel,
|
||||
updateLabelsInPage,
|
||||
} from '../../elastic/labels'
|
||||
import { getHighlightById } from '../../elastic/highlights'
|
||||
import { getLabelsByIds } from '../../services/labels'
|
||||
|
||||
export const labelsResolver = authorized<LabelsSuccess, LabelsError>(
|
||||
async (_obj, _params, { claims: { uid }, log }) => {
|
||||
|
|
@ -174,8 +178,8 @@ export const deleteLabelResolver = authorized<
|
|||
}
|
||||
}
|
||||
|
||||
// delete label in elastic pages
|
||||
await deleteLabelInPages(uid, label.name, {
|
||||
// delete label in elastic pages and highlights
|
||||
await deleteLabel(labelId, {
|
||||
pubsub: createPubSubClient(),
|
||||
uid,
|
||||
})
|
||||
|
|
@ -223,11 +227,13 @@ export const setLabelsResolver = authorized<
|
|||
errorCodes: [SetLabelsErrorCode.NotFound],
|
||||
}
|
||||
}
|
||||
if (page.userId !== uid) {
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
const labels = await getRepository(Label).find({
|
||||
where: { id: In(labelIds), user: { id: user.id } },
|
||||
select: ['id', 'name', 'color', 'description', 'createdAt'],
|
||||
})
|
||||
const labels = await getLabelsByIds(uid, labelIds)
|
||||
if (labels.length !== labelIds.length) {
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.NotFound],
|
||||
|
|
@ -316,15 +322,10 @@ export const updateLabelResolver = authorized<
|
|||
}
|
||||
}
|
||||
|
||||
const updated = await updateLabelInPage(label, {
|
||||
await updateLabel(label, {
|
||||
pubsub,
|
||||
uid,
|
||||
})
|
||||
if (!updated) {
|
||||
return {
|
||||
errorCodes: [UpdateLabelErrorCode.BadRequest],
|
||||
}
|
||||
}
|
||||
|
||||
return { label }
|
||||
} catch (error) {
|
||||
|
|
@ -334,3 +335,71 @@ export const updateLabelResolver = authorized<
|
|||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const setLabelsForHighlightResolver = authorized<
|
||||
SetLabelsSuccess,
|
||||
SetLabelsError,
|
||||
MutationSetLabelsForHighlightArgs
|
||||
>(async (_, { input }, { claims: { uid }, log, pubsub }) => {
|
||||
log.info('setLabelsForHighlightResolver')
|
||||
|
||||
const { highlightId, labelIds } = input
|
||||
|
||||
try {
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
const highlight = await getHighlightById(highlightId)
|
||||
if (!highlight) {
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.NotFound],
|
||||
}
|
||||
}
|
||||
if (highlight.userId !== uid) {
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
const labels = await getLabelsByIds(uid, labelIds)
|
||||
if (labels.length !== labelIds.length) {
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.NotFound],
|
||||
}
|
||||
}
|
||||
|
||||
// set labels in the highlights
|
||||
const updated = await setLabelsForHighlight(highlightId, labels, {
|
||||
pubsub,
|
||||
uid,
|
||||
})
|
||||
if (!updated) {
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.NotFound],
|
||||
}
|
||||
}
|
||||
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
event: 'labels_set_for_highlight',
|
||||
properties: {
|
||||
highlightId,
|
||||
labelIds,
|
||||
env: env.server.apiEnv,
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
labels,
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(error)
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.BadRequest],
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1738,6 +1738,11 @@ const schema = gql`
|
|||
NOT_FOUND
|
||||
}
|
||||
|
||||
input SetLabelsForHighlightInput {
|
||||
highlightId: ID!
|
||||
labelIds: [ID!]!
|
||||
}
|
||||
|
||||
# Mutations
|
||||
type Mutation {
|
||||
googleLogin(input: GoogleLoginInput!): LoginResult!
|
||||
|
|
@ -1806,6 +1811,7 @@ const schema = gql`
|
|||
setWebhook(input: SetWebhookInput!): SetWebhookResult!
|
||||
deleteWebhook(id: ID!): DeleteWebhookResult!
|
||||
revokeApiKey(id: ID!): RevokeApiKeyResult!
|
||||
setLabelsForHighlight(input: SetLabelsForHighlightInput!): SetLabelsResult!
|
||||
}
|
||||
|
||||
# FIXME: remove sort from feedArticles after all cached tabs are closed
|
||||
|
|
|
|||
|
|
@ -66,3 +66,13 @@ export const addLabelToPage = async (
|
|||
ctx
|
||||
)
|
||||
}
|
||||
|
||||
export const getLabelsByIds = async (
|
||||
userId: string,
|
||||
labelIds: string[]
|
||||
): Promise<Label[]> => {
|
||||
return getRepository(Label).find({
|
||||
where: { id: In(labelIds), user: { id: userId } },
|
||||
select: ['id', 'name', 'color', 'description', 'createdAt'],
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { InFilter, ReadFilter } from '../../src/utils/search'
|
|||
import {
|
||||
ArticleSavingRequestStatus,
|
||||
Highlight,
|
||||
Label,
|
||||
Page,
|
||||
PageContext,
|
||||
PageType,
|
||||
|
|
@ -18,7 +19,7 @@ import {
|
|||
searchPages,
|
||||
updatePage,
|
||||
} from '../../src/elastic/pages'
|
||||
import { addLabelInPage } from '../../src/elastic/labels'
|
||||
import { addLabelInPage, setLabelsForHighlight } from '../../src/elastic/labels'
|
||||
import {
|
||||
addHighlightToPage,
|
||||
searchHighlights,
|
||||
|
|
@ -250,4 +251,54 @@ describe('elastic api', () => {
|
|||
expect(searchResults[0].id).to.eq(highlightId)
|
||||
})
|
||||
})
|
||||
|
||||
describe('setLabelsForHighlight', () => {
|
||||
const page = {
|
||||
id: 'testPageId',
|
||||
hash: 'test set labels for highlight hash',
|
||||
userId: userId,
|
||||
pageType: PageType.Article,
|
||||
title: 'test set labels for highlight title',
|
||||
content: '<p>test</p>',
|
||||
slug: 'test set labels for highlight slug',
|
||||
createdAt: new Date(),
|
||||
savedAt: new Date(),
|
||||
readingProgressPercent: 100,
|
||||
readingProgressAnchorIndex: 0,
|
||||
url: 'https://blog.omnivore.app/p/setting-labels-for-highlight',
|
||||
state: ArticleSavingRequestStatus.Succeeded,
|
||||
}
|
||||
const highlightId = 'highlightId'
|
||||
const label: Label = {
|
||||
id: 'test label id',
|
||||
name: 'test label',
|
||||
color: '#07D2D1',
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
// create a testing page
|
||||
await createPage(page, ctx)
|
||||
|
||||
const highlightData: Highlight = {
|
||||
patch: 'test set labels patch',
|
||||
quote: 'test set labels quote',
|
||||
shortId: 'test set labels shortId',
|
||||
id: highlightId,
|
||||
userId: page.userId,
|
||||
createdAt: new Date(),
|
||||
}
|
||||
|
||||
await addHighlightToPage(page.id, highlightData, ctx)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await deletePage(page.id, ctx)
|
||||
})
|
||||
|
||||
it('sets labels for highlights', async () => {
|
||||
const result = await setLabelsForHighlight(highlightId, [label], ctx)
|
||||
|
||||
expect(result).to.be.true
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -9,11 +9,15 @@ import { Label } from '../../src/entity/label'
|
|||
import { expect } from 'chai'
|
||||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { Page, PageContext } from '../../src/elastic/types'
|
||||
import { Highlight, Page, PageContext } from '../../src/elastic/types'
|
||||
import { getRepository } from '../../src/entity/utils'
|
||||
import { getPageById } from '../../src/elastic/pages'
|
||||
import { addLabelInPage } from '../../src/elastic/labels'
|
||||
import { createPubSubClient } from '../../src/datalayer/pubsub'
|
||||
import {
|
||||
addHighlightToPage,
|
||||
getHighlightById,
|
||||
} from '../../src/elastic/highlights'
|
||||
|
||||
describe('Labels API', () => {
|
||||
const username = 'fakeUser'
|
||||
|
|
@ -238,6 +242,30 @@ describe('Labels API', () => {
|
|||
expect(updatedPage?.labels).not.to.include(toDeleteLabel)
|
||||
})
|
||||
})
|
||||
|
||||
context('when a highlight has this label', () => {
|
||||
const highlightId = 'testDeleteLabel'
|
||||
|
||||
before(async () => {
|
||||
const highlight: Highlight = {
|
||||
id: highlightId,
|
||||
patch: 'test patch',
|
||||
quote: 'test quote',
|
||||
shortId: 'test shortId',
|
||||
userId: user.id,
|
||||
createdAt: new Date(),
|
||||
labels: [toDeleteLabel],
|
||||
}
|
||||
await addHighlightToPage(page.id, highlight, ctx)
|
||||
})
|
||||
|
||||
it('should update highlight', async () => {
|
||||
await graphqlRequest(query, authToken).expect(200)
|
||||
const updatedHighlight = await getHighlightById(highlightId)
|
||||
|
||||
expect(updatedHighlight?.labels).not.to.include(toDeleteLabel)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
context('when label not exist', () => {
|
||||
|
|
@ -440,4 +468,96 @@ describe('Labels API', () => {
|
|||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Set labels for highlight', () => {
|
||||
let query: string
|
||||
let highlightId: string
|
||||
let labelIds: string[] = []
|
||||
|
||||
beforeEach(() => {
|
||||
query = `
|
||||
mutation {
|
||||
setLabelsForHighlight(
|
||||
input: {
|
||||
highlightId: "${highlightId}",
|
||||
labelIds: [
|
||||
"${labelIds[0]}",
|
||||
"${labelIds[1]}"
|
||||
]
|
||||
}
|
||||
) {
|
||||
... on SetLabelsSuccess {
|
||||
labels {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
... on SetLabelsError {
|
||||
errorCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
})
|
||||
|
||||
context('when labels exists', () => {
|
||||
before(async () => {
|
||||
highlightId = 'highlight-id'
|
||||
const highlight: Highlight = {
|
||||
createdAt: new Date(),
|
||||
id: highlightId,
|
||||
patch: 'test patch',
|
||||
quote: 'test quote',
|
||||
shortId: 'test shortId',
|
||||
userId: user.id,
|
||||
}
|
||||
await addHighlightToPage(page.id, highlight, ctx)
|
||||
labelIds = [labels[0].id, labels[1].id]
|
||||
})
|
||||
|
||||
it('should set labels for highlight', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
expect(
|
||||
res.body.data.setLabelsForHighlight.labels.map((l: any) => l.id)
|
||||
).to.eql(labelIds)
|
||||
})
|
||||
})
|
||||
|
||||
context('when labels not exist', () => {
|
||||
before(async () => {
|
||||
highlightId = 'highlight-id-2'
|
||||
const highlight: Highlight = {
|
||||
createdAt: new Date(),
|
||||
id: highlightId,
|
||||
patch: 'test patch',
|
||||
quote: 'test quote',
|
||||
shortId: 'test shortId',
|
||||
userId: user.id,
|
||||
}
|
||||
await addHighlightToPage(page.id, highlight, ctx)
|
||||
labelIds = [generateFakeUuid(), generateFakeUuid()]
|
||||
})
|
||||
|
||||
it('should return error code NOT_FOUND', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
expect(res.body.data.setLabelsForHighlight.errorCodes).to.eql([
|
||||
'NOT_FOUND',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
context('when highlight not exist', () => {
|
||||
before(() => {
|
||||
highlightId = generateFakeUuid()
|
||||
labelIds = [labels[0].id, labels[1].id]
|
||||
})
|
||||
|
||||
it('should return error code NOT_FOUND', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
expect(res.body.data.setLabelsForHighlight.errorCodes).to.eql([
|
||||
'NOT_FOUND',
|
||||
])
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -90,6 +90,27 @@
|
|||
},
|
||||
"updatedAt": {
|
||||
"type": "date"
|
||||
},
|
||||
"labels": {
|
||||
"type": "nested",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer"
|
||||
},
|
||||
"color": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "date"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue