diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 61a483bd..d4c6ad9c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,5 @@ + + # What kind of change does this PR introduce? eg: Bug fix, feature, docs update, ... @@ -16,5 +18,5 @@ Put a "X" in the boxes below to indicate you have followed the checklist; - [ ] I have read the [CONTRIBUTING](https://github.com/gitroomhq/postiz-app/blob/main/CONTRIBUTING.md) guide. - [ ] I confirm I have not used AI to submit this PR or generate code for it. -- [ ] I checked that there were not similar issues or PRs already open for this. -- [ ] This PR fixes just ONE issue (do not include multiple issues or types of change in the same PR) For example, don't try and fix a UI issue and include new dependencies in the same PR. +- [ ] I checked that there were no similar issues or PRs already open for this. +- [ ] This PR fixes just ONE issue diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ee5c0f84..242c7c88 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,8 @@ name: Build on: push: + merge_group: + pull_request: jobs: build: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 79d64857..0974256d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,5 +1,5 @@ --- -name: "Code Quality Analysis" +name: "Code Quality Analysis" on: push: @@ -9,6 +9,8 @@ on: - apps/** - '!apps/docs/**' - libraries/** + merge_group: + jobs: analyze: diff --git a/.github/workflows/pr-quality.yml b/.github/workflows/pr-quality.yml deleted file mode 100644 index 3fdc958b..00000000 --- a/.github/workflows/pr-quality.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: PR Quality - -permissions: - contents: read - issues: read - pull-requests: write - -on: - pull_request_target: - types: [opened, reopened] - -jobs: - anti-slop: - runs-on: ubuntu-latest - steps: - - uses: peakoss/anti-slop@v0 - with: - # Overall - max-failures: 3 - - # Other - require-maintainer-can-modify: true - max-negative-reactions: 3 - require-conventional-title: true - - # Description - max-emoji-count: 2 - max-code-references: 3 - blocked-terms: "Generated with Claude Code,Generated with Codex" - - # PR Template - require-pr-template: true - strict-pr-template-sections: "What kind of change does this PR introduce?,Why was this change needed?,Checklist:" - optional-pr-template-sections: "Other information:" - max-additional-pr-template-sections: 2 - - # User - detect-spam-usernames: true - min-account-age: 30 - max-daily-forks: 5 - min-profile-completeness: 4 - - # Exemptions - exempt-author-association: "OWNER,MEMBER,COLLABORATOR" - exempt-users: "nevo-david,egelhaus" - exempt-bots: "postiz-agent[bot]" - - # Actions - exempt-label: "exempt" - close-pr: true - failure-add-pr-labels: "spam" - failure-pr-message: "This PR has been marked as Spam, please re-open if this is a mistake." diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 960e6f34..071994c2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,6 +6,10 @@ Contributions are welcome - code, docs, whatever it might be! If this is your fi The main documentation site has a [developer guide](https://docs.postiz.com/developer-guide) . That guide provides you a good understanding of the project structure, and how to setup your development environment. Read this document after you have read that guide. This document is intended to provide you a good understanding of how to submit your first contribution. +## Apply via the contribution form + +To submit your contribution, please fill out the [contribution form](https://contribute.postiz.com/p/postiz). This helps us evaluate whether your contribution is a good fit for the project. We will review your submission and get back to you as soon as possible. + ## Write code with others This is an open source project, with an open and welcoming community that is always keen to welcome new contributors. We recommend the two best ways to interact with the community are: diff --git a/apps/backend/src/services/auth/auth.service.ts b/apps/backend/src/services/auth/auth.service.ts index 32b43f3b..187c08ed 100644 --- a/apps/backend/src/services/auth/auth.service.ts +++ b/apps/backend/src/services/auth/auth.service.ts @@ -43,6 +43,9 @@ export class AuthService { if (process.env.DISALLOW_PLUS && body.email.includes('+')) { throw new Error('Email with plus sign is not allowed'); } + if (body instanceof CreateOrgUserDto) { + body.email = body.email.toLowerCase(); + } const user = await this._userService.getUserByEmail(body.email); if (body instanceof CreateOrgUserDto) { if (user) { diff --git a/apps/frontend/src/components/launches/import-debug-post.modal.tsx b/apps/frontend/src/components/launches/import-debug-post.modal.tsx index 65c28593..14fed8dd 100644 --- a/apps/frontend/src/components/launches/import-debug-post.modal.tsx +++ b/apps/frontend/src/components/launches/import-debug-post.modal.tsx @@ -147,7 +147,7 @@ export const ImportDebugPostModal: FC<{ close: () => void }> = ({ close }) => {
{t('debug_info', 'Debug Info')}
-
+
{t('provider', 'Provider')}: @@ -175,7 +175,7 @@ export const ImportDebugPostModal: FC<{ close: () => void }> = ({ close }) => { {t('error_details', 'Error Details')}: -
+
{parsed._debug.errors.map((err, i) => (
[{err.platform}] {err.message} diff --git a/apps/frontend/src/components/layout/impersonate.tsx b/apps/frontend/src/components/layout/impersonate.tsx index 4cc6bdad..e81d0429 100644 --- a/apps/frontend/src/components/layout/impersonate.tsx +++ b/apps/frontend/src/components/layout/impersonate.tsx @@ -433,6 +433,7 @@ const ImportDebugPost = () => { const handleClick = useCallback(() => { openModal({ title: t('import_debug_post', 'Import Debug Post'), + maxSize: 800, children: (close) => , }); }, []); diff --git a/apps/frontend/src/components/layout/new-modal.tsx b/apps/frontend/src/components/layout/new-modal.tsx index fdc3704a..090f4366 100644 --- a/apps/frontend/src/components/layout/new-modal.tsx +++ b/apps/frontend/src/components/layout/new-modal.tsx @@ -31,6 +31,7 @@ interface OpenModalInterface { modal?: string; }; size?: string | number; + maxSize?: string | number; height?: string | number; id?: string; } @@ -200,10 +201,11 @@ export const Component: FC<{ modal.size ? '' : 'min-w-[600px]', modal.fullScreen && 'h-full' )} - {...((!!modal.size || !!modal.height) && { + {...((!!modal.size || !!modal.height || !!modal.maxSize) && { style: { ...(modal.size ? { width: modal.size } : {}), ...(modal.height ? { height: modal.height } : {}), + ...(modal.maxSize ? { maxWidth: modal.maxSize } : {}), }, })} onClick={(e) => e.stopPropagation()} diff --git a/apps/frontend/src/components/layout/set.timezone.tsx b/apps/frontend/src/components/layout/set.timezone.tsx index f37b4f0f..ac5b74a5 100644 --- a/apps/frontend/src/components/layout/set.timezone.tsx +++ b/apps/frontend/src/components/layout/set.timezone.tsx @@ -3,8 +3,10 @@ import dayjs, { ConfigType } from 'dayjs'; import { FC, useEffect } from 'react'; import timezone from 'dayjs/plugin/timezone'; import utc from 'dayjs/plugin/utc'; +import relativeTime from 'dayjs/plugin/relativeTime'; dayjs.extend(timezone); dayjs.extend(utc); +dayjs.extend(relativeTime); const { utc: originalUtc } = dayjs; diff --git a/apps/frontend/src/components/notifications/notification.component.tsx b/apps/frontend/src/components/notifications/notification.component.tsx index 4b890706..731b80f9 100644 --- a/apps/frontend/src/components/notifications/notification.component.tsx +++ b/apps/frontend/src/components/notifications/notification.component.tsx @@ -4,6 +4,7 @@ import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import useSWR from 'swr'; import { FC, useCallback, useState } from 'react'; import clsx from 'clsx'; +import dayjs from 'dayjs'; import { useClickAway } from '@uidotdev/usehooks'; import ReactLoading from '@gitroom/frontend/components/layout/loading'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; @@ -26,16 +27,29 @@ export const ShowNotification: FC<{ const [newNotification] = useState( new Date(notification.createdAt) > new Date(props.lastReadNotification) ); + const createdAt = dayjs(notification.createdAt); + const isWithin24h = dayjs().diff(createdAt, 'hour') < 24; + const fullDate = createdAt.format('MMM D, YYYY h:mm A'); return (
+ > +
+
+ {isWithin24h ? createdAt.fromNow() : fullDate} +
+
); }; export const NotificationOpenComponent = () => { @@ -57,7 +71,7 @@ export const NotificationOpenComponent = () => { {t('notifications', 'Notifications')}
-
+
{isLoading && (
diff --git a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts index 81b2fded..978b237b 100644 --- a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts @@ -478,14 +478,13 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider { private async prepareMediaBuffer(mediaUrl: string): Promise { const isVideo = mediaUrl.indexOf('mp4') > -1; + const isGif = lookup(mediaUrl) === 'image/gif'; - if (isVideo) { + if (isVideo || isGif) { return Buffer.from(await readOrFetch(mediaUrl)); } - return await sharp(await readOrFetch(mediaUrl), { - animated: lookup(mediaUrl) === 'image/gif', - }) + return await sharp(await readOrFetch(mediaUrl), { animated: false }) .toFormat('jpeg') .resize({ width: 1000 }) .toBuffer();