Skip to content

Commit

Permalink
[Frontend][Update][Version] Lexicon version v2.1.0 (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
starjustice committed Dec 7, 2023
1 parent fdd8930 commit a54e815
Show file tree
Hide file tree
Showing 252 changed files with 11,495 additions and 2,895 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: CI

on:
push:
branches: [master, v2.0.0-beta]
branches: [master]
pull_request:
branches: [master, v2.0.0-beta]
branches: [master]

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
"camelcase-keys": "^6.2.2",
"dotenv": "^8.2.0",
"form-data": "^4.0.0",
"graphql": "^16.5.0",
"graphql": "^16.8.1",
"nexus": "^1.4.0-next.11",
"querystring": "^0.2.0",
"set-cookie-parser": "^2.5.1",
"snakecase-keys": "^3.2.0",
"tough-cookie": "^4.1.3",
"winston": "^3.10.0",
"winston-daily-rotate-file": "^4.7.1",
"zod": "^3.22.0"
"zod": "^3.22.3"
},
"devDependencies": {
"@total-typescript/ts-reset": "^0.4.2",
Expand Down
31 changes: 17 additions & 14 deletions api/src/__tests__/getTopicAuthor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,26 @@ import {
getTopicAuthor,
getTopicAuthorUserId,
} from '../helpers/getTopicAuthor';
import { TopicPoster } from '../types';
import { PosterUnion } from '../types';

function getUserWithId(
userId: number | null,
description: string,
): TopicPoster {
function getUserWithId(userId: number, description: string): PosterUnion {
return {
userId,
description,
extras: null,
user: null,
user: {
id: userId,
name: '',
username: '',
avatarTemplate: '',
},
};
}

function getUserWithObject(userId: number, description: string): TopicPoster {
function getUserWithObject(userId: number, description: string): PosterUnion {
return {
...getUserWithId(null, description),
description,
extras: null,
user: {
id: userId,
username: 'bill',
Expand All @@ -30,7 +33,7 @@ function getUserWithObject(userId: number, description: string): TopicPoster {

describe('getTopicAuthor', () => {
it('returns the author of the topic when present', () => {
const posters: Array<TopicPoster> = [
const posters: Array<PosterUnion> = [
getUserWithId(1, 'Frequent Poster'),
getUserWithId(2, 'Most Recent Poster'),
getUserWithId(3, 'Frequent Poster, Original Poster'),
Expand All @@ -40,7 +43,7 @@ describe('getTopicAuthor', () => {
});

it('returns the first author when multiple are somehow present', () => {
const posters: Array<TopicPoster> = [
const posters: Array<PosterUnion> = [
getUserWithId(1, 'Original Poster'),
getUserWithId(2, 'Most Recent Poster'),
getUserWithId(3, 'Frequent Poster, Original Poster'),
Expand All @@ -50,7 +53,7 @@ describe('getTopicAuthor', () => {
});

it('returns undefined when no author is present', () => {
const posters: Array<TopicPoster> = [
const posters: Array<PosterUnion> = [
getUserWithId(1, 'Frequent Poster'),
getUserWithId(2, 'Frequent Poster'),
getUserWithId(3, 'Frequent Poster, Most Recent Poster'),
Expand All @@ -66,7 +69,7 @@ describe('getTopicAuthor', () => {

describe('getTopicAuthorUserId', () => {
it(`returns the author's userId when present`, () => {
const posters: Array<TopicPoster> = [
const posters: Array<PosterUnion> = [
getUserWithId(1, 'Frequent Poster'),
getUserWithId(2, 'Most Recent Poster'),
getUserWithId(3, 'Frequent Poster, Original Poster'),
Expand All @@ -75,7 +78,7 @@ describe('getTopicAuthorUserId', () => {
});

it(`returns the author's user.id when present`, () => {
const posters: Array<TopicPoster> = [
const posters: Array<PosterUnion> = [
getUserWithId(1, 'Frequent Poster'),
getUserWithId(2, 'Most Recent Poster'),
getUserWithObject(3, 'Frequent Poster, Original Poster'),
Expand All @@ -84,7 +87,7 @@ describe('getTopicAuthorUserId', () => {
});

it(`prefers the author's userId when the user object is set too`, () => {
const posters: Array<TopicPoster> = [
const posters: Array<PosterUnion> = [
getUserWithId(1, 'Frequent Poster'),
getUserWithId(2, 'Most Recent Poster'),
{
Expand Down
16 changes: 11 additions & 5 deletions api/src/helpers/getTopicAuthor.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { TopicPoster } from '../types';
import { PosterUnion } from '../types';

import { getPosterTypeDetails } from './getPosterTypeDetails';

export function getTopicAuthor(
posters: Readonly<Array<TopicPoster>>,
): TopicPoster | undefined {
posters: Readonly<Array<PosterUnion>>,
): PosterUnion | undefined {
return posters.find((poster) => {
const { isAuthor } = getPosterTypeDetails(poster.description);
return isAuthor;
});
}

export function getTopicAuthorUserId(
posters: Readonly<Array<TopicPoster>>,
posters: Readonly<Array<PosterUnion>>,
): number | undefined {
const author = getTopicAuthor(posters);

return author?.userId ?? author?.user?.id;
if (author) {
if ('userId' in author) {
return author.userId;
} else if ('user' in author) {
return author.user.id;
}
}
}
1 change: 1 addition & 0 deletions api/src/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './parseTopicUrl';
export * from './privateMessagesMerger';
export * from './processRawContent';
export * from './topicDetail';
export * from './poll';
56 changes: 56 additions & 0 deletions api/src/helpers/poll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Poll, PollsVotes, PreloaderUnion } from '../types';

/**
* This helper is used for formatting preloadedVoters data
* that is returned in a poll, from a key-value object to an array.
*/
export function formatPreloadedVoters(preloadedVoters: PreloaderUnion) {
if (!preloadedVoters) {
return { preloadedVoters: null };
}

const pollOptionIds = Object.keys(preloadedVoters);
const formattedPreloadedVoters = Array.isArray(preloadedVoters)
? [{ pollOptionId: '', users: preloadedVoters }]
: typeof preloadedVoters === 'object'
? pollOptionIds.map((pollOptionId) => ({
pollOptionId,
users: preloadedVoters[pollOptionId],
}))
: null;

return { preloadedVoters: formattedPreloadedVoters };
}

export function formatPolls(
polls?: Array<Poll> | null,
pollsVotes?: PollsVotes | null,
) {
if (!polls) {
return { formattedPolls: null, formattedPollsVotes: null };
}

const formattedPolls = polls.map((poll) => {
return { ...poll, ...formatPreloadedVoters(poll.preloadedVoters) };
});
const formattedPollsVotes = formatPollsVotes(pollsVotes);

return { formattedPolls, formattedPollsVotes };
}

/**
* This helper is used for formatting pollsVotes data
* that is returned in a post, from a key-value object to an array.
*/
export function formatPollsVotes(pollsVotes?: PollsVotes | null) {
if (!pollsVotes) {
return null;
}
const pollNames = Object.keys(pollsVotes);
const formattedPollVotes = pollNames.map((pollName) => ({
pollName,
pollOptionIds: pollsVotes[pollName],
}));

return formattedPollVotes;
}
27 changes: 22 additions & 5 deletions api/src/helpers/processRawContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { PROSE_DISCOURSE_UPLOAD_HOST } from '../constants';

const imageRegex = /<img.*? src="(\S+(?:jpe?g|png|gif|heic|heif))"/g;
const anchoredImageVideoRegex =
/<a.*? href="(https?:\/\/[^ ]*\.(?:jpe?g|png|gif|heic|heif|mov|mp4|webm|avi|wmv|flv|webp))".*?>/g;
/<a.*? href="((https?:)?\/\/[^ ]*\.(?:jpe?g|png|gif|heic|heif|mov|mp4|webm|avi|wmv|flv|webp))".*?>/g;
const srcSetRegex = /srcset="(.+?)"/g;
const imageUrlRegex = /(https?:\/\/[^ ]*\.(?:jpe?g|png|gif|heic|heif))/g;
const imageUrlRegex = /((https?:)?\/\/[^ ]*\.(?:jpe?g|png|gif|heic|heif))/g;
const mentionRegex = /<a class=\"mention\".*?>@(.*?)<\/a>/g;
const imageMarkdownRegex = /(!\[.*?\]\()(upload:\/\/\S*)(\))/g;
const imageVideoTagRegex =
/(?:<img[^>]*src(?:set)?=")(.+?)"|(?:<a[^>]* href="(https?:\/\/[^ ]*\.(?:jpe?g|png|gif|heic|heif|mov|mp4|webm|avi|wmv|flv|webp))")([^$]+?)<\/a>/g;
/(?:<img[^>]*src(?:set)?=")(.+?)"|(?:<a[^>]* href="((https?:)?\/\/[^ ]*\.(?:jpe?g|png|gif|heic|heif|mov|mp4|webm|avi|wmv|flv|webp))")([^$]+?)<\/a>/g;

const emojiBBCodeRegex = /(?<=^|\s):\w+:(?:t\d+:)?/g;
const emojiImageTagRegex = /<img.*?class="emoji.*? alt="(.*?)">/g;
Expand All @@ -34,14 +34,30 @@ function handleRegexResult(
optimizedUrl.push(url[url.length - 1]);
}
});
return optimizedUrl.map((item) => item.replace(transparantRegex, ''));
return optimizedUrl.map((item) => {
const itemReplace = item.replace(transparantRegex, '');
/**
* This changes is used to handle some image which using local url into https url example :
*
* //kflounge-staging.kfox.io/uploads/default/optimized/1X/1a4ea5cb345d30d4230bdfa3671d1bc1026c772e_2_690x388.jpeg
* into
* https://kflounge-staging.kfox.io/uploads/default/optimized/1X/1a4ea5cb345d30d4230bdfa3671d1bc1026c772e_2_690x388.jpeg
*/

return itemReplace[0] === '/' ? `https:${itemReplace}` : itemReplace;
});
} else if (
regex === anchoredImageVideoRegex ||
regex === imageRegex ||
regex === mentionRegex
) {
result = result.map((item) => item.replace(regex, '$1'));
return result.map((item) => item.replace(transparantRegex, ''));

return result.map((item) => {
const itemReplace = item.replace(transparantRegex, '');

return itemReplace[0] === '/' ? `https:${itemReplace}` : itemReplace;
});
}
}

Expand All @@ -62,6 +78,7 @@ export function getPostImageUrl(
host: string = PROSE_DISCOURSE_UPLOAD_HOST,
): string | undefined {
// Return only the first element of array because only one url is found

let result = content.match(srcSetRegex) ?? undefined;

if (result) {
Expand Down
5 changes: 5 additions & 0 deletions api/src/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ export * from './topics/replyMutation';
export * from './topics/searchQuery';
export * from './topics/searchTagsQuery';
export * from './topics/timingsMutation';
export * from './topics/togglePollStatusMutation';
export * from './topics/topicDetailQuery';
export * from './topics/topicsQuery';
export * from './topics/undoVotePollMutation';
export * from './topics/votePollMutation';

export * from './upload/lookupUrlsQuery';
export * from './upload/uploadMutation';
Expand All @@ -49,5 +52,7 @@ export * from './user/searchUserQuery';
export * from './user/singleBadgeQuery';
export * from './user/userActivityQuery';
export * from './user/userProfileQuery';
export * from './user/editUserStatusMutation';
export * from './user/deleteUserStatusMutation';

export * from './health/healthQuery';
16 changes: 15 additions & 1 deletion api/src/resolvers/site/siteQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { FieldResolver, queryField } from 'nexus';

import { errorHandler } from '../../helpers';
import { Context } from '../../types';
import { UNCATEGORIZED_CATEGORY_ID } from '../../constants';
import {
PROSE_DISCOURSE_HOST,
UNCATEGORIZED_CATEGORY_ID,
} from '../../constants';

let siteResolver: FieldResolver<'Query', 'site'> = async (
_,
Expand Down Expand Up @@ -55,6 +58,11 @@ let siteResolver: FieldResolver<'Query', 'site'> = async (
full_name_required: fullNameRequired = false,
default_composer_category: defaultComposerCategory = '',
allow_uncategorized_topics: allowUncategorizedTopics = false,
enable_user_status: allowUserStatus = false,
external_emoji_url: externalEmojiUrl = '',
emoji_set: emojiSet = '',
poll_enabled: allowPoll = true,
poll_minimum_trust_level_to_create: pollCreateMinimumTrustLevel = 1,
},
} = await context.client.get(siteSettingsUrl);

Expand All @@ -76,6 +84,12 @@ let siteResolver: FieldResolver<'Query', 'site'> = async (
defaultComposerCategory,
allowUncategorizedTopics,
uncategorizedCategoryId,
allowUserStatus,
externalEmojiUrl,
emojiSet,
discourseBaseUrl: PROSE_DISCOURSE_HOST || '',
allowPoll,
pollCreateMinimumTrustLevel,
...camelcaseKey(siteData, { deep: true }),
};
} catch (error) {
Expand Down
15 changes: 13 additions & 2 deletions api/src/resolvers/topics/editPostMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import camelcaseKey from 'camelcase-keys';
import snakecaseKey from 'snakecase-keys';
import { FieldResolver, mutationField, arg, intArg } from 'nexus';

import { errorHandler } from '../../helpers';
import { errorHandler, formatPolls } from '../../helpers';
import { Context } from '../../types';
import { ACCEPTED_LANGUAGE, CONTENT_JSON } from '../../constants';

Expand All @@ -24,7 +24,18 @@ export let editPostResolver: FieldResolver<'Mutation', 'editPost'> = async (
{ post },
config,
);
return camelcaseKey(data.post, { deep: true });

let editPostData = camelcaseKey(data.post, { deep: true });
const { formattedPolls, formattedPollsVotes } = formatPolls(
editPostData.polls,
editPostData.pollsVotes,
);

return {
...editPostData,
polls: formattedPolls,
pollsVotes: formattedPollsVotes,
};
} catch (e) {
errorHandler(e);
}
Expand Down
14 changes: 12 additions & 2 deletions api/src/resolvers/topics/flagPostMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from 'nexus';

import { ACCEPTED_LANGUAGE, CONTENT_FORM_URLENCODED } from '../../constants';
import { errorHandler } from '../../helpers';
import { errorHandler, formatPolls } from '../../helpers';
import { Context } from '../../types';

export let flagPostResolver: FieldResolver<'Mutation', 'flagPost'> = async (
Expand All @@ -34,7 +34,17 @@ export let flagPostResolver: FieldResolver<'Mutation', 'flagPost'> = async (
stringify(body),
config,
);
return camelcaseKeys(data, { deep: true });
let flagPostData = camelcaseKeys(data, { deep: true });
const { formattedPolls, formattedPollsVotes } = formatPolls(
flagPostData.polls,
flagPostData.pollsVotes,
);

return {
...flagPostData,
polls: formattedPolls,
pollsVotes: formattedPollsVotes,
};
} catch (e) {
errorHandler(e);
}
Expand Down
Loading

0 comments on commit a54e815

Please sign in to comment.