From ace0eb186cb8597bb6a21917cc11ee2eb59127f7 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup Date: Fri, 25 Sep 2026 15:52:02 -0400 Subject: [PATCH 1/4] refactor(FeedV...MTC): Reuse publishState to set publish button state. --- .../version/FeedVersionActionsMTC.js | 55 +++++++------------ lib/types/index.js | 1 + 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/lib/manager/components/version/FeedVersionActionsMTC.js b/lib/manager/components/version/FeedVersionActionsMTC.js index 9f8ea0088..584959d75 100644 --- a/lib/manager/components/version/FeedVersionActionsMTC.js +++ b/lib/manager/components/version/FeedVersionActionsMTC.js @@ -8,7 +8,6 @@ import { Link } from 'react-router' import { connect } from 'react-redux' import * as versionsActions from '../../actions/versions' -import { BLOCKING_ERROR_TYPES } from '../../util/version' import type { Feed, FeedVersion, FeedVersionSummary, GtfsPlusValidation, ServerJob } from '../../../types' import type { ManagerUserState } from '../../../types/reducers' @@ -62,18 +61,6 @@ function userCanManageFeed (user: ManagerUserState, version: FeedVersion): boole ) !== null } -/** - * Check that the validation did not encounter any fatal exception or blocking - * errors. - */ -function checkBlockingIssue (version: FeedVersion): boolean { - if (!version.validationResult) return false - if (version.validationResult.fatalException) return true - const errorCounts = version.validationResult.error_counts - return !!errorCounts && - !!(errorCounts.find(ec => BLOCKING_ERROR_TYPES.indexOf(ec.type) !== -1)) -} - class FeedVersionActionsMTC extends Component { _handleMergeVersion: ((versionId: string) => void) = (versionId: string) => { // Note: service period feed merge has only been extensively tested with @@ -92,40 +79,38 @@ class FeedVersionActionsMTC extends Component { user, version } = this.props - const {validationSummary: summary} = version - // We must check the version ID against the feed source in props (not the - // feed source nested underneath version) because this is the only place the - // published version is updated. - const isPublished = version.namespace === feedSource.publishedVersionId - // Version is in the "processing" state if it has been sent to external - // source, but has not been processed yet. - const processing = version.sentToExternalPublisher && - !version.processedByExternalPublisher - const hasBlockingIssue = checkBlockingIssue(version) + + // Use version summaries from FeedSource to get the publish status returned by backend. + const versionSummary = feedSource.feedVersionSummaries?.find(v => v.id === version.id) + // TODO improve this + if (!versionSummary) return
+ + const { publishState, validationSummary: summary } = versionSummary + const isPublished = publishState === 'PUBLISHED' + const processing = publishState === 'PUBLISHING' + const hasGtfsPlusBlockingIssue = gtfsPlusValidation && gtfsPlusValidation.issues.length > 0 const isMergedServicePeriods = version.retrievalMethod === 'SERVICE_PERIOD_MERGE' - // Expiry is computed same as with VersionDateLabel (TODO: refactor and reconcile with versionHasExpired). + // Expiry is computed same as in backend using FeedValidationSummary.startDate/ednDate. const now = +moment().startOf('day') const end = +moment(summary.endDate) + const start = +moment(summary.startDate) const expired = end < now + const future = start > now const jobsProcessingThisVersion = jobs && jobs.some(job => job.feedVersionId === version.id) - const publishButtonDisabled = !gtfsPlusValidation || - hasGtfsPlusBlockingIssue || - !gtfsPlusValidation.published || - expired || - !version.validationResult || - !version.validationResult.error_counts || - hasBlockingIssue || - isPublished || - processing || + const publishButtonDisabled = publishState !== 'READY_TO_PUBLISH' || !userCanManageFeed(user, version) || jobsProcessingThisVersion let publishWarningMessage - if (hasBlockingIssue || hasGtfsPlusBlockingIssue) { + if (expired) { + publishWarningMessage = 'Cannot publish version because it has expired.' + } else if (future) { + publishWarningMessage = 'Cannot publish version because it is in the future.' + } else if (publishState === 'PUBLISH_BLOCKED') { publishWarningMessage = ( Cannot publish version because it has a{' '} @@ -139,8 +124,6 @@ class FeedVersionActionsMTC extends Component { .) ) - } else if (expired) { - publishWarningMessage = 'Cannot publish version because it has expired.' } else if (feedSource.autoPublish) { publishWarningMessage = 'Reminder: this feed is already set to be auto-published after auto-fetch!' } diff --git a/lib/types/index.js b/lib/types/index.js index 1c1ef3693..8d78f78f3 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -547,6 +547,7 @@ export type FeedVersionSummary = { name: string, namespace: string, originNamespace: ?string, + publishState?: 'PUBLISHED' | 'PUBLISHING' | 'PUBLISH_BLOCKED' | 'READY_TO_PUBLISH', retrievalMethod: ?RetrievalMethod, updated: number, // HACK: validationSummary is fully populated in FeedVersion. From eeaa71c582b1e130b7cc9fcdaf614272cfba12b2 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup Date: Fri, 25 Sep 2026 15:59:42 -0400 Subject: [PATCH 2/4] refactor(FeedV...MTC): Remove empty div return --- .../components/version/FeedVersionActionsMTC.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/manager/components/version/FeedVersionActionsMTC.js b/lib/manager/components/version/FeedVersionActionsMTC.js index 584959d75..b351158e1 100644 --- a/lib/manager/components/version/FeedVersionActionsMTC.js +++ b/lib/manager/components/version/FeedVersionActionsMTC.js @@ -79,13 +79,12 @@ class FeedVersionActionsMTC extends Component { user, version } = this.props + const { feedVersionSummaries: summaries } = feedSource // Use version summaries from FeedSource to get the publish status returned by backend. - const versionSummary = feedSource.feedVersionSummaries?.find(v => v.id === version.id) - // TODO improve this - if (!versionSummary) return
+ const versionSummary = summaries && summaries.find(v => v.id === version.id) - const { publishState, validationSummary: summary } = versionSummary + const { publishState = '', validationSummary: summary } = versionSummary || {} const isPublished = publishState === 'PUBLISHED' const processing = publishState === 'PUBLISHING' @@ -96,8 +95,8 @@ class FeedVersionActionsMTC extends Component { const now = +moment().startOf('day') const end = +moment(summary.endDate) const start = +moment(summary.startDate) - const expired = end < now - const future = start > now + const expired = !!versionSummary && end < now + const future = !!versionSummary && start > now const jobsProcessingThisVersion = jobs && jobs.some(job => job.feedVersionId === version.id) @@ -144,7 +143,7 @@ class FeedVersionActionsMTC extends Component { : 'Merge with version' }} version={version} - versions={feedSource.feedVersionSummaries} + versions={summaries} />
) From ff023002f9c52186fa0020fc0ab0c670668bdfca Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup Date: Wed, 30 Sep 2026 15:20:50 -0400 Subject: [PATCH 4/4] refactor(FeedV...MTC): Fix typo, remove eslint exception --- lib/manager/components/version/FeedVersionActionsMTC.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/manager/components/version/FeedVersionActionsMTC.js b/lib/manager/components/version/FeedVersionActionsMTC.js index 1f4c48fdb..b34e50be7 100644 --- a/lib/manager/components/version/FeedVersionActionsMTC.js +++ b/lib/manager/components/version/FeedVersionActionsMTC.js @@ -86,7 +86,7 @@ class FeedVersionActionsMTC extends Component { const hasGtfsPlusBlockingIssue = gtfsPlusValidation && gtfsPlusValidation.issues.length > 0 - // Expiry is computed same as in backend using FeedValidationSummary.startDate/ednDate. + // Expiry is computed same as in backend using FeedValidationSummary.startDate/endDate. const now = +moment().startOf('day') const end = +moment(summary.endDate) const start = +moment(summary.startDate) @@ -116,7 +116,6 @@ class FeedVersionActionsMTC extends Component { } } - // eslint-disable-next-line complexity render (): React$Element<"div"> { const { feedSource,