From 015de51f123e1e5a2214f703f0d2cad6ca7d1f8e Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Wed, 29 Jul 2026 18:42:55 +0200 Subject: [PATCH 1/4] fix: hide comment section if comments are set to disabled --- client/containers/App/app.scss | 19 +++++++++++++++++++ .../Pub/PubDocument/PubBottom/pubBottom.scss | 3 ++- .../Pub/PubDocument/PubDocument.tsx | 10 +++++++++- .../Pub/PubDocument/pubDocument.scss | 7 +++++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/client/containers/App/app.scss b/client/containers/App/app.scss index d03ff45ef9..189f122d3b 100644 --- a/client/containers/App/app.scss +++ b/client/containers/App/app.scss @@ -9,6 +9,25 @@ outline: none; flex-grow: 1; } + /* Let the pub page fill the viewport, so its grey bottom section reaches the footer instead + of leaving a white gap when the pub is shorter than the screen. Every link in the chain + has to be a column flex container for the next one to grow into it: + + #app > #main-content > #pub-container > .pub-document-component > .pub-bottom-component + + .pub-document-component (pubDocument.scss) and .pub-bottom-component (pubBottom.scss) + already declare `flex-grow: 1`; both were inert because #main-content and #pub-container + are plain blocks. These rules connect them. Skipped on the dashboard, which has its own + padded #main-content layout and no growing root. */ + &:not(.dashboard) #main-content { + display: flex; + flex-direction: column; + #pub-container { + display: flex; + flex-direction: column; + flex-grow: 1; + } + } .duqduq-warning { position: fixed; right: 10px; diff --git a/client/containers/Pub/PubDocument/PubBottom/pubBottom.scss b/client/containers/Pub/PubDocument/PubBottom/pubBottom.scss index 024f3bb10c..9b60e0bfec 100644 --- a/client/containers/Pub/PubDocument/PubBottom/pubBottom.scss +++ b/client/containers/Pub/PubDocument/PubBottom/pubBottom.scss @@ -2,7 +2,8 @@ .pub-bottom-component { background: #f6f4f4; - flex-grow: 1; + /* Stay at content height — .pub-grid takes the leftover viewport space instead. */ + flex-grow: 0; overflow: hidden; padding: 2em 0em; margin-top: 2em; diff --git a/client/containers/Pub/PubDocument/PubDocument.tsx b/client/containers/Pub/PubDocument/PubDocument.tsx index 34a4e49ba6..30002b9246 100644 --- a/client/containers/Pub/PubDocument/PubDocument.tsx +++ b/client/containers/Pub/PubDocument/PubDocument.tsx @@ -39,7 +39,7 @@ const PubDocument = () => { const { isViewingHistory } = historyData; const { communityData, scopeData, featureFlags } = usePageContext(); const pubEdgeDisplay = useFacetsQuery((F) => F.PubEdgeDisplay); - const { canEdit, canEditDraft } = scopeData.activePermissions; + const { canEdit, canEditDraft, discussionCreationAccess } = scopeData.activePermissions; const { isReviewingPub } = pubData; const mainContentRef = useRef(null); const sideContentRef = useRef(null); @@ -51,6 +51,13 @@ const PubDocument = () => { const showPubFileImport = (canEdit || canEditDraft) && !isReadOnly; + /* When discussions are disabled and there's nothing to read, the Comments section is just an */ + /* empty box with controls that do nothing. Discussions arrive already sanitized (spam, banned */ + /* authors and draft-vs-release visibility are filtered server-side), so an empty list here */ + /* means there is nothing this reader is allowed to see. */ + const showDiscussions = + discussionCreationAccess !== 'disabled' || !!pubData.discussions?.length; + if (hidePubBody) { return null; } @@ -125,6 +132,7 @@ const PubDocument = () => { Date: Wed, 29 Jul 2026 18:48:34 +0200 Subject: [PATCH 2/4] fix: fix bug disallowing setting discussioncreationaccess to contributors-members --- server/publicPermissions/model.ts | 2 +- utils/api/contracts/publicPermissions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/publicPermissions/model.ts b/server/publicPermissions/model.ts index 5f82c60707..94cd7ee462 100644 --- a/server/publicPermissions/model.ts +++ b/server/publicPermissions/model.ts @@ -33,7 +33,7 @@ export class PublicPermissions extends Model< declare canCreateDiscussions: boolean | null; @Default('public') - @Column(DataType.ENUM('public', 'contributors', 'members', 'disabled')) + @Column(DataType.ENUM('public', 'contributors-members', 'disabled')) declare discussionCreationAccess: CreationOptional; @Column(DataType.BOOLEAN) diff --git a/utils/api/contracts/publicPermissions.ts b/utils/api/contracts/publicPermissions.ts index 68d5062dcf..bf78f9ab28 100644 --- a/utils/api/contracts/publicPermissions.ts +++ b/utils/api/contracts/publicPermissions.ts @@ -11,7 +11,7 @@ export const publicPermissionsRouter = { method: 'PUT', summary: 'Update who is able to create new discussions', body: z.object({ - discussionCreationAccess: z.enum(['public', 'contributors', 'members', 'disabled']), + discussionCreationAccess: z.enum(['public', 'contributors-members', 'disabled']), }), responses: { 200: z.object({ success: z.boolean() }), From 7d35b75c15b6bc95cc21011dcd1018ade15b3de6 Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Wed, 29 Jul 2026 19:42:44 +0200 Subject: [PATCH 3/4] fix: dont show comments for non-members when set to contributor members either --- client/containers/Pub/PubDocument/PubDocument.tsx | 15 ++++++++------- server/publicPermissions/model.ts | 4 +++- types/community.ts | 7 ++++++- utils/api/contracts/publicPermissions.ts | 4 +++- utils/api/schemas/community.ts | 4 +++- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/client/containers/Pub/PubDocument/PubDocument.tsx b/client/containers/Pub/PubDocument/PubDocument.tsx index 30002b9246..94337c0d0b 100644 --- a/client/containers/Pub/PubDocument/PubDocument.tsx +++ b/client/containers/Pub/PubDocument/PubDocument.tsx @@ -39,7 +39,7 @@ const PubDocument = () => { const { isViewingHistory } = historyData; const { communityData, scopeData, featureFlags } = usePageContext(); const pubEdgeDisplay = useFacetsQuery((F) => F.PubEdgeDisplay); - const { canEdit, canEditDraft, discussionCreationAccess } = scopeData.activePermissions; + const { canEdit, canEditDraft, canCreateDiscussions } = scopeData.activePermissions; const { isReviewingPub } = pubData; const mainContentRef = useRef(null); const sideContentRef = useRef(null); @@ -51,12 +51,13 @@ const PubDocument = () => { const showPubFileImport = (canEdit || canEditDraft) && !isReadOnly; - /* When discussions are disabled and there's nothing to read, the Comments section is just an */ - /* empty box with controls that do nothing. Discussions arrive already sanitized (spam, banned */ - /* authors and draft-vs-release visibility are filtered server-side), so an empty list here */ - /* means there is nothing this reader is allowed to see. */ - const showDiscussions = - discussionCreationAccess !== 'disabled' || !!pubData.discussions?.length; + /* Only show the Comments section if there's something to read, or this reader can actually */ + /* post. Otherwise it's an empty box with sort/filter controls that do nothing — which is what */ + /* a logged-out visitor saw on a Community that limits commenting to members and contributors, */ + /* or that disabled it outright. Discussions arrive already sanitized (spam, banned authors */ + /* and draft-vs-release visibility are filtered server-side), so an empty list here means */ + /* there is nothing this reader is allowed to see. */ + const showDiscussions = canCreateDiscussions || !!pubData.discussions?.length; if (hidePubBody) { return null; diff --git a/server/publicPermissions/model.ts b/server/publicPermissions/model.ts index 94cd7ee462..49d8c00baa 100644 --- a/server/publicPermissions/model.ts +++ b/server/publicPermissions/model.ts @@ -12,6 +12,8 @@ import { Table, } from 'sequelize-typescript'; +import { discussionCreationAccessValues } from 'types/community'; + import { Pub } from '../models'; @Table @@ -33,7 +35,7 @@ export class PublicPermissions extends Model< declare canCreateDiscussions: boolean | null; @Default('public') - @Column(DataType.ENUM('public', 'contributors-members', 'disabled')) + @Column(DataType.ENUM(...discussionCreationAccessValues)) declare discussionCreationAccess: CreationOptional; @Column(DataType.BOOLEAN) diff --git a/types/community.ts b/types/community.ts index 873471d058..bdfed45580 100644 --- a/types/community.ts +++ b/types/community.ts @@ -15,4 +15,9 @@ export type CommunityHeaderLink = { export type Community = SerializedModel; -export type DiscussionCreationAccess = 'public' | 'contributors-members' | 'disabled'; +export const discussionCreationAccessValues = [ + 'public', + 'contributors-members', + 'disabled', +] as const; +export type DiscussionCreationAccess = (typeof discussionCreationAccessValues)[number]; diff --git a/utils/api/contracts/publicPermissions.ts b/utils/api/contracts/publicPermissions.ts index bf78f9ab28..3c5b246bef 100644 --- a/utils/api/contracts/publicPermissions.ts +++ b/utils/api/contracts/publicPermissions.ts @@ -3,6 +3,8 @@ import type { AppRouter } from '@ts-rest/core'; import { extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; +import { discussionCreationAccessValues } from 'types/community'; + extendZodWithOpenApi(z); export const publicPermissionsRouter = { @@ -11,7 +13,7 @@ export const publicPermissionsRouter = { method: 'PUT', summary: 'Update who is able to create new discussions', body: z.object({ - discussionCreationAccess: z.enum(['public', 'contributors-members', 'disabled']), + discussionCreationAccess: z.enum(discussionCreationAccessValues), }), responses: { 200: z.object({ success: z.boolean() }), diff --git a/utils/api/schemas/community.ts b/utils/api/schemas/community.ts index 528b0b879f..5c05c2faed 100644 --- a/utils/api/schemas/community.ts +++ b/utils/api/schemas/community.ts @@ -2,6 +2,8 @@ import type * as types from 'types'; import { z } from 'zod'; +import { discussionCreationAccessValues } from 'types/community'; + import { baseSchema } from '../utils/baseSchema'; import { analyticsSettingsSchema } from './analyticsSettings'; @@ -138,5 +140,5 @@ export const communityUpdateSchema = communitySchema }) .extend({ communityId: communitySchema.shape.id, - discussionCreationAccess: z.enum(['public', 'contributors-members', 'disabled']).optional(), + discussionCreationAccess: z.enum(discussionCreationAccessValues).optional(), }); From 84d33c42c4684ab0561e28334ba4a258e18eea8a Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Wed, 29 Jul 2026 20:18:10 +0200 Subject: [PATCH 4/4] fix: robo fix Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- client/containers/App/app.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/containers/App/app.scss b/client/containers/App/app.scss index 189f122d3b..87ca06ae46 100644 --- a/client/containers/App/app.scss +++ b/client/containers/App/app.scss @@ -15,9 +15,9 @@ #app > #main-content > #pub-container > .pub-document-component > .pub-bottom-component - .pub-document-component (pubDocument.scss) and .pub-bottom-component (pubBottom.scss) - already declare `flex-grow: 1`; both were inert because #main-content and #pub-container - are plain blocks. These rules connect them. Skipped on the dashboard, which has its own + .pub-document-component (pubDocument.scss) declares `flex-grow: 1` and is a column flex container; + .pub-grid absorbs leftover space while .pub-bottom-component (pubBottom.scss) stays at content height. + These rules connect that chain by making #main-content and #pub-container flex columns. Skipped on the dashboard, which has its own padded #main-content layout and no growing root. */ &:not(.dashboard) #main-content { display: flex;