From 39d2dc74d8e4a7b2634bfbc924859f8cebbfbbb0 Mon Sep 17 00:00:00 2001 From: dblatcher Date: Wed, 22 Jan 2025 09:52:23 +0000 Subject: [PATCH 1/7] add display hint to stub modelling --- common-lib/src/main/scala/models/Stub.scala | 3 ++- public/lib/model/stub.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/common-lib/src/main/scala/models/Stub.scala b/common-lib/src/main/scala/models/Stub.scala index 4d595f448..183e058ab 100644 --- a/common-lib/src/main/scala/models/Stub.scala +++ b/common-lib/src/main/scala/models/Stub.scala @@ -52,7 +52,8 @@ case class ExternalData( rightsSyndicationAggregate: Option[Boolean] = None, rightsSubscriptionDatabases: Option[Boolean] = None, rightsDeveloperCommunity: Option[Boolean] = None, - byline: Option[String] = None) { + byline: Option[String] = None, + displayHint: Option[String] = None) { } object ExternalData { diff --git a/public/lib/model/stub.ts b/public/lib/model/stub.ts index fbdc4ba67..e95b8e930 100644 --- a/public/lib/model/stub.ts +++ b/public/lib/model/stub.ts @@ -25,5 +25,6 @@ export type Stub = { priority?: number; prodOffice?: string; note?: string; + displayHint?: string; }; From e228919e93d444006adbcf17c71f3973a28507a8 Mon Sep 17 00:00:00 2001 From: dblatcher Date: Wed, 22 Jan 2025 09:55:26 +0000 Subject: [PATCH 2/7] add display hint to filter modelling, populate on the data before posting to backend --- public/components/stub-modal/stub-modal.js | 15 ++++++++++++++- public/lib/content-service.js | 3 ++- public/lib/filters-service.js | 3 ++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/public/components/stub-modal/stub-modal.js b/public/components/stub-modal/stub-modal.js index 56f905ad6..c22911820 100644 --- a/public/components/stub-modal/stub-modal.js +++ b/public/components/stub-modal/stub-modal.js @@ -344,7 +344,20 @@ function StubModalInstanceCtrl($rootScope, $scope, $modalInstance, $window, conf }; $scope.ok = function (addToComposer, addToAtomEditor) { - const stub = $scope.stub; + const stub = {...$scope.stub}; + + switch (stub.contentType){ + case 'keyTakeaways': + case 'qAndA': + case "timeline": + case "miniProfiles": + case "multiByline": + stub.displayHint = stub.contentType + break; + default: + break; + } + function createItemPromise() { if ($scope.contentName === 'Atom') { stub.contentType = $scope.stub.contentType.toLowerCase(); diff --git a/public/lib/content-service.js b/public/lib/content-service.js index 4753735c4..02537b7ea 100644 --- a/public/lib/content-service.js +++ b/public/lib/content-service.js @@ -284,6 +284,7 @@ angular.module('wfContentService', ['wfHttpSessionService', 'wfVisibilityService 'hasPrintInfo': modelParams['hasPrintInfo'] || null, 'hasMainMedia': modelParams['hasMainMedia'] || null, 'rights': modelParams['rights'] || null, + 'display-hint': modelParams["display-hint"], }; return params; @@ -362,7 +363,7 @@ angular.module('wfContentService', ['wfHttpSessionService', 'wfVisibilityService const localSearch = this._paramsProvider() this.currentSearch = localSearch - + return wfContentService.get(localSearch) .then((cb) => { const localSearchIsStale = localSearch !== this.currentSearch diff --git a/public/lib/filters-service.js b/public/lib/filters-service.js index 7f27dea73..9f89f5b90 100644 --- a/public/lib/filters-service.js +++ b/public/lib/filters-service.js @@ -200,7 +200,8 @@ angular.module('wfFiltersService', ['wfDateService', 'wfTrustedHtml']) 'editorId' : params['editorId'], 'hasPrintInfo' : params['hasPrintInfo'], 'hasMainMedia' : params['hasMainMedia'], - 'hasAnyRights' : params['rights'] + 'hasAnyRights' : params['rights'], + 'display-hint' : params['display-hint'], }; $rootScope.currentlySelectedStatusFilters = self.transformStatusList(self.filters['status']); From aad9db67227c0d37f90b62f1fc0f9ec58e64b014 Mon Sep 17 00:00:00 2001 From: dblatcher Date: Wed, 22 Jan 2025 11:23:59 +0000 Subject: [PATCH 3/7] add a list of formats andsome ts helpers --- public/components/stub-modal/stub-modal.js | 57 ++-------------------- public/lib/composer-service.js | 37 ++------------ public/lib/model/special-formats.ts | 52 ++++++++++++++++++++ public/lib/model/stub.ts | 13 ++++- 4 files changed, 73 insertions(+), 86 deletions(-) create mode 100644 public/lib/model/special-formats.ts diff --git a/public/components/stub-modal/stub-modal.js b/public/components/stub-modal/stub-modal.js index c22911820..9e5c0a838 100644 --- a/public/components/stub-modal/stub-modal.js +++ b/public/components/stub-modal/stub-modal.js @@ -17,6 +17,7 @@ import 'lib/prodoffice-service'; import 'lib/telemetry-service'; import { punters } from 'components/punters/punters'; import { generateErrorMessages, doesContentTypeRequireCommissionedLength, useNativeFormFeedback } from '../../lib/stub-form-validation.ts'; +import { getStubArticleFormat, setDisplayHintForFormat } from 'lib/model/special-formats.js'; const wfStubModal = angular.module('wfStubModal', [ 'ui.bootstrap', 'articleFormatService', 'legalStatesService', 'pictureDeskStatesService', 'wfComposerService', 'wfContentService', 'wfDateTimePicker', 'wfProdOfficeService', 'wfFiltersService', 'wfCapiAtomService', 'wfTelemetryService']) @@ -31,20 +32,8 @@ function StubModalInstanceCtrl($rootScope, $scope, $modalInstance, $window, conf (wfContentService.getAtomTypes())[stub.contentType] ? "Atom" : (types[stub.contentType] || "News item"); - $scope.stubFormat = '' - if (stub.contentType === 'article') { - $scope.stubFormat = "Standard Article" - } else if (stub.contentType === 'keyTakeaways') { - $scope.stubFormat = "Key Takeaways" - } else if (stub.contentType === 'qAndA') { - $scope.stubFormat = "Q&A Explainer" - } else if (stub.contentType === 'timeline') { - $scope.stubFormat = "Timeline" - } else if (stub.contentType === 'miniProfiles') { - $scope.stubFormat = "Mini profiles" - } else if (stub.contentType === 'multiByline') { - $scope.stubFormat = "Multi-byline" - } + $scope.stubFormat = getStubArticleFormat(stub.contentType); + $scope.$watch('stub.articleFormat', (newValue) => { $scope.stubFormat = newValue; }) @@ -344,20 +333,8 @@ function StubModalInstanceCtrl($rootScope, $scope, $modalInstance, $window, conf }; $scope.ok = function (addToComposer, addToAtomEditor) { - const stub = {...$scope.stub}; + const stub = setDisplayHintForFormat ($scope.stub); - switch (stub.contentType){ - case 'keyTakeaways': - case 'qAndA': - case "timeline": - case "miniProfiles": - case "multiByline": - stub.displayHint = stub.contentType - break; - default: - break; - } - function createItemPromise() { if ($scope.contentName === 'Atom') { stub.contentType = $scope.stub.contentType.toLowerCase(); @@ -509,32 +486,8 @@ wfStubModal.run([ function setUpPreferredStub (contentType) { function createStubData (contentType, sectionName) { - let chosenArticleFormat = "" - switch (contentType) { - case "article": - chosenArticleFormat = "Standard Article" - break; - case "keyTakeaways": - chosenArticleFormat = "Key Takeaways" - break; - case "qAndA": - chosenArticleFormat = "Q&A Explainer" - break; - case "timeline": - chosenArticleFormat = "Timeline" - break; - case "miniProfiles": - chosenArticleFormat = "Mini profiles" - break; - case "multiByline": - chosenArticleFormat = "Multi-byline" - break; - default: - break; - } - return { - articleFormat: chosenArticleFormat, + articleFormat: getStubArticleFormat(contentType), contentType: contentType === "atom" ? defaultAtomType : contentType, // Only send through a section if one is found in the prefs section: sectionName === null ? sectionName : sections.filter((section) => section.name === sectionName)[0], diff --git a/public/lib/composer-service.js b/public/lib/composer-service.js index 967fadea5..05d822926 100644 --- a/public/lib/composer-service.js +++ b/public/lib/composer-service.js @@ -1,5 +1,6 @@ import angular from 'angular'; import './telemetry-service'; +import { getFormatFromLabel, contentTypeToComposerContentType } from './model/special-formats'; angular.module('wfComposerService', ['wfTelemetryService']) .service('wfComposerService', ['$http', '$q', 'config', '$log', 'wfHttpSessionService', 'wfTelemetryService', wfComposerService]); @@ -92,42 +93,12 @@ function wfComposerService($http, $q, config, $log, wfHttpSessionService, wfTele this.getComposerContent = getComposerContent; this.parseComposerData = parseComposerData; - - const getDisplayHint = (articleFormat) => { - switch (articleFormat){ - case "Key Takeaways": - return "keyTakeaways" - case "Q&A Explainer": - return "qAndA" - case "Timeline": - return "timeline" - case "Mini profiles": - return "miniProfiles" - case "Multi-byline": - return "multiByline" - default: - return undefined - } - } - const getType = (type) => { - switch (type){ - case 'keyTakeaways': - case 'qAndA': - case "timeline": - case "miniProfiles": - case "multiByline": - return "article" - default: - return type - } - } - this.create = function createInComposer(type, commissioningDesks, commissionedLength, prodOffice, template, articleFormat, priority, missingCommissionedLengthReason) { - var selectedDisplayHint = getDisplayHint(articleFormat); + var selectedDisplayHint = getFormatFromLabel(articleFormat)?.value; var params = { - 'type': getType(type), + 'type': contentTypeToComposerContentType(type), 'tracking': commissioningDesks, 'productionOffice': prodOffice, 'displayHint': selectedDisplayHint, @@ -158,7 +129,7 @@ function wfComposerService($http, $q, config, $log, wfHttpSessionService, wfTele } const tags = { - contentType: getType(type), + contentType: contentTypeToComposerContentType(type), productionOffice: prodOffice, priority: getPriorityName(priority), } diff --git a/public/lib/model/special-formats.ts b/public/lib/model/special-formats.ts new file mode 100644 index 000000000..38d37a328 --- /dev/null +++ b/public/lib/model/special-formats.ts @@ -0,0 +1,52 @@ +import { ComposerContentType, ContentType, SpecialArticleFormat, Stub } from "./stub"; + +const specialFormats: SpecialArticleFormat[] = [ + { label: 'Key Takeaways', value: 'keyTakeaways', iconId: 'keyTakeaways' }, + { label: 'Q&A Explainer', value: 'qAndA', iconId: 'qAndA' }, + { label: 'Timeline', value: 'timeline', iconId: 'timeline' }, + { label: 'Mini profiles', value: 'miniProfiles', iconId: 'miniProfiles' }, + { label: 'Multi-byline', value: 'multiByline', iconId: 'multiByline', hidden: true }, +] + +const setDisplayHintForFormat = (stub: Stub): Stub => { + const maybeMatchingFormat = specialFormats.find(format => format.value === stub.contentType) + if (maybeMatchingFormat) { + stub.displayHint = maybeMatchingFormat.value + } + return stub +} + +/** + * return "Standard Article" for normal articles, the label for special article formats + * or empty string for non-article stubs + */ +const getStubArticleFormat = (contentType:ContentType): string => { + const maybeMatchingFormat = specialFormats.find(format => format.value === contentType) + if (maybeMatchingFormat) { + return maybeMatchingFormat.label + } + if (contentType === 'article') { + return "Standard Article" + } + return '' +} + +const getFormatFromLabel = (label: string): SpecialArticleFormat | undefined => + specialFormats.find(format => format.label === label) + +const contentTypeToComposerContentType = (type: ContentType): ComposerContentType => { + switch (type) { + case "article": + case "liveblog": + case "gallery": + case "interactive": + case "picture": + case "video": + case "audio": + return type; + default: + return 'article' + } +} + +export { specialFormats, setDisplayHintForFormat, getFormatFromLabel, contentTypeToComposerContentType, getStubArticleFormat } \ No newline at end of file diff --git a/public/lib/model/stub.ts b/public/lib/model/stub.ts index e95b8e930..3b6785374 100644 --- a/public/lib/model/stub.ts +++ b/public/lib/model/stub.ts @@ -1,4 +1,4 @@ -export type ContentType = +export type ComposerContentType = | "article" | "liveblog" | "gallery" @@ -6,12 +6,16 @@ export type ContentType = | "picture" | "video" | "audio" + +export type SpecialFormatContentType = | "keyTakeaways" | "qAndA" | "timeline" | "miniProfiles" | "multiByline"; +export type ContentType = ComposerContentType | SpecialFormatContentType; + type FlagValue = "NA" | "REQUIRED" | "COMPLETE"; export type Stub = { @@ -28,3 +32,10 @@ export type Stub = { displayHint?: string; }; +export type SpecialArticleFormat = { + label: string, + value: SpecialFormatContentType, + iconId: string, + hidden?: boolean, +} + From f1eb8499d72868259a2dc53b706e788bc3f0a4d1 Mon Sep 17 00:00:00 2001 From: dblatcher Date: Wed, 22 Jan 2025 11:45:03 +0000 Subject: [PATCH 4/7] ts files need to be named as such when importing --- public/components/stub-modal/stub-modal.js | 2 +- public/lib/composer-service.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/components/stub-modal/stub-modal.js b/public/components/stub-modal/stub-modal.js index 9e5c0a838..8a0e6535e 100644 --- a/public/components/stub-modal/stub-modal.js +++ b/public/components/stub-modal/stub-modal.js @@ -17,7 +17,7 @@ import 'lib/prodoffice-service'; import 'lib/telemetry-service'; import { punters } from 'components/punters/punters'; import { generateErrorMessages, doesContentTypeRequireCommissionedLength, useNativeFormFeedback } from '../../lib/stub-form-validation.ts'; -import { getStubArticleFormat, setDisplayHintForFormat } from 'lib/model/special-formats.js'; +import { getStubArticleFormat, setDisplayHintForFormat } from 'lib/model/special-formats.ts'; const wfStubModal = angular.module('wfStubModal', [ 'ui.bootstrap', 'articleFormatService', 'legalStatesService', 'pictureDeskStatesService', 'wfComposerService', 'wfContentService', 'wfDateTimePicker', 'wfProdOfficeService', 'wfFiltersService', 'wfCapiAtomService', 'wfTelemetryService']) diff --git a/public/lib/composer-service.js b/public/lib/composer-service.js index 05d822926..683310a3a 100644 --- a/public/lib/composer-service.js +++ b/public/lib/composer-service.js @@ -1,6 +1,6 @@ import angular from 'angular'; import './telemetry-service'; -import { getFormatFromLabel, contentTypeToComposerContentType } from './model/special-formats'; +import { getFormatFromLabel, contentTypeToComposerContentType } from './model/special-formats.ts'; angular.module('wfComposerService', ['wfTelemetryService']) .service('wfComposerService', ['$http', '$q', 'config', '$log', 'wfHttpSessionService', 'wfTelemetryService', wfComposerService]); From d085e094956f75e6807fd3a09f559b0599ac5fc9 Mon Sep 17 00:00:00 2001 From: dblatcher Date: Wed, 22 Jan 2025 12:05:11 +0000 Subject: [PATCH 5/7] use helper to control whether to show the format dropdown --- public/components/stub-modal/stub-modal.html | 2 +- public/components/stub-modal/stub-modal.js | 6 +++++- public/lib/composer-service.js | 4 ++-- public/lib/model/special-formats.ts | 12 +++++++++--- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/public/components/stub-modal/stub-modal.html b/public/components/stub-modal/stub-modal.html index 86b7b16d7..bd0537754 100644 --- a/public/components/stub-modal/stub-modal.html +++ b/public/components/stub-modal/stub-modal.html @@ -13,7 +13,7 @@
-
+
diff --git a/public/components/stub-modal/stub-modal.js b/public/components/stub-modal/stub-modal.js index 8a0e6535e..7fe561e4d 100644 --- a/public/components/stub-modal/stub-modal.js +++ b/public/components/stub-modal/stub-modal.js @@ -17,7 +17,7 @@ import 'lib/prodoffice-service'; import 'lib/telemetry-service'; import { punters } from 'components/punters/punters'; import { generateErrorMessages, doesContentTypeRequireCommissionedLength, useNativeFormFeedback } from '../../lib/stub-form-validation.ts'; -import { getStubArticleFormat, setDisplayHintForFormat } from 'lib/model/special-formats.ts'; +import { getStubArticleFormat, isFormatLabel, setDisplayHintForFormat } from 'lib/model/special-formats.ts'; const wfStubModal = angular.module('wfStubModal', [ 'ui.bootstrap', 'articleFormatService', 'legalStatesService', 'pictureDeskStatesService', 'wfComposerService', 'wfContentService', 'wfDateTimePicker', 'wfProdOfficeService', 'wfFiltersService', 'wfCapiAtomService', 'wfTelemetryService']) @@ -47,6 +47,10 @@ function StubModalInstanceCtrl($rootScope, $scope, $modalInstance, $window, conf })[mode]; }); + $scope.stubFormatIsCorrectlyPopulated = function() { + return isFormatLabel($scope.stubFormat) + } + $scope.loadingTemplates = true; wfComposerService.loadTemplates().then(templates => { diff --git a/public/lib/composer-service.js b/public/lib/composer-service.js index 683310a3a..7f617ea09 100644 --- a/public/lib/composer-service.js +++ b/public/lib/composer-service.js @@ -1,6 +1,6 @@ import angular from 'angular'; import './telemetry-service'; -import { getFormatFromLabel, contentTypeToComposerContentType } from './model/special-formats.ts'; +import { getSpecialFormatFromLabel, contentTypeToComposerContentType } from './model/special-formats.ts'; angular.module('wfComposerService', ['wfTelemetryService']) .service('wfComposerService', ['$http', '$q', 'config', '$log', 'wfHttpSessionService', 'wfTelemetryService', wfComposerService]); @@ -95,7 +95,7 @@ function wfComposerService($http, $q, config, $log, wfHttpSessionService, wfTele this.parseComposerData = parseComposerData; this.create = function createInComposer(type, commissioningDesks, commissionedLength, prodOffice, template, articleFormat, priority, missingCommissionedLengthReason) { - var selectedDisplayHint = getFormatFromLabel(articleFormat)?.value; + var selectedDisplayHint = getSpecialFormatFromLabel(articleFormat)?.value; var params = { 'type': contentTypeToComposerContentType(type), diff --git a/public/lib/model/special-formats.ts b/public/lib/model/special-formats.ts index 38d37a328..796c6488c 100644 --- a/public/lib/model/special-formats.ts +++ b/public/lib/model/special-formats.ts @@ -1,5 +1,7 @@ import { ComposerContentType, ContentType, SpecialArticleFormat, Stub } from "./stub"; +const STANDARD_ARTICLE_FORMAT_LABEL = "Standard Article"; + const specialFormats: SpecialArticleFormat[] = [ { label: 'Key Takeaways', value: 'keyTakeaways', iconId: 'keyTakeaways' }, { label: 'Q&A Explainer', value: 'qAndA', iconId: 'qAndA' }, @@ -26,12 +28,16 @@ const getStubArticleFormat = (contentType:ContentType): string => { return maybeMatchingFormat.label } if (contentType === 'article') { - return "Standard Article" + return STANDARD_ARTICLE_FORMAT_LABEL } return '' } -const getFormatFromLabel = (label: string): SpecialArticleFormat | undefined => +const isFormatLabel = (value:string):boolean => { + return value === STANDARD_ARTICLE_FORMAT_LABEL || specialFormats.some(format => format.label === value) +} + +const getSpecialFormatFromLabel = (label: string): SpecialArticleFormat | undefined => specialFormats.find(format => format.label === label) const contentTypeToComposerContentType = (type: ContentType): ComposerContentType => { @@ -49,4 +55,4 @@ const contentTypeToComposerContentType = (type: ContentType): ComposerContentTyp } } -export { specialFormats, setDisplayHintForFormat, getFormatFromLabel, contentTypeToComposerContentType, getStubArticleFormat } \ No newline at end of file +export { specialFormats, setDisplayHintForFormat, getSpecialFormatFromLabel, contentTypeToComposerContentType, getStubArticleFormat, isFormatLabel } \ No newline at end of file From 625032c61de7c52aab58787a024351ce53510463 Mon Sep 17 00:00:00 2001 From: dblatcher Date: Wed, 22 Jan 2025 13:25:36 +0000 Subject: [PATCH 6/7] add helpers to get lists of formats accounting for feature switches --- public/lib/article-format-service.js | 35 ++++++----------- public/lib/content-service.js | 36 +++-------------- public/lib/model/format-helpers.ts | 58 ++++++++++++++++++++++++++++ public/lib/model/special-formats.ts | 18 ++++----- public/lib/model/stub.ts | 3 +- 5 files changed, 85 insertions(+), 65 deletions(-) create mode 100644 public/lib/model/format-helpers.ts diff --git a/public/lib/article-format-service.js b/public/lib/article-format-service.js index 456628f4a..58bbc3ebd 100644 --- a/public/lib/article-format-service.js +++ b/public/lib/article-format-service.js @@ -1,27 +1,14 @@ -define(['angular'], function (angular) { - 'use strict'; +import angular from 'angular'; +import { provideArticleFormatsForDropDown } from './model/format-helpers.ts'; - var articleFormatService = angular.module('articleFormatService', []); - articleFormatService.factory('articleFormatService',['wfPreferencesService', function (wfPreferencesService) { - function getArticleFormats() { - const featureSwitches = wfPreferencesService.preferences.featureSwitches; - - const articleFormats = [ - {name: 'Standard Article', value: 'Standard Article'}, - {name: 'Key Takeaways', value: 'Key Takeaways'}, - {name: 'Q&A Explainer', value: 'Q&A Explainer'}, - {name: 'Timeline', value: 'Timeline'}, - {name: 'Mini profiles', value: 'Mini profiles'}, - ] - if (featureSwitches && featureSwitches.multiByline){ - articleFormats.push({name: 'Multi-byline', value: 'Multi-byline'}) - } - return articleFormats - }; +angular.module('articleFormatService', []) + .factory('articleFormatService', ['wfPreferencesService', function (wfPreferencesService) { + function getArticleFormats() { + const featureSwitches = wfPreferencesService.preferences?.featureSwitches; + return provideArticleFormatsForDropDown(featureSwitches) + }; return { - getArticleFormats: getArticleFormats - }; - }]); - return articleFormatService; -}); + getArticleFormats: getArticleFormats + }; + }]); diff --git a/public/lib/content-service.js b/public/lib/content-service.js index 02537b7ea..e539fe21a 100644 --- a/public/lib/content-service.js +++ b/public/lib/content-service.js @@ -6,6 +6,7 @@ import './atom-workshop-service' import './http-session-service'; import './user'; import './visibility-service'; +import { provideFormats } from './model/format-helpers.ts' angular.module('wfContentService', ['wfHttpSessionService', 'wfVisibilityService', 'wfDateService', 'wfFiltersService', 'wfUser', 'wfComposerService', 'wfMediaAtomMakerService', 'wfAtomWorkshopService', 'wfPreferencesService']) .factory('wfContentService', ['$rootScope', '$log', 'wfHttpSessionService', 'wfDateParser', 'wfFormatDateTimeFilter', 'wfFiltersService', 'wfComposerService', 'wfMediaAtomMakerService', 'wfAtomWorkshopService', 'wfPreferencesService', 'config', @@ -15,37 +16,12 @@ angular.module('wfContentService', ['wfHttpSessionService', 'wfVisibilityService class ContentService { - provideFormats(featureSwitches){ - const articleFormats = { - "article": "Article", - "keyTakeaways": "Key Takeaways", - "qAndA": "Q&A Explainer", - "timeline": "Timeline", - "miniProfiles": "Mini profiles" - } - - if (featureSwitches && featureSwitches.multiByline){ - articleFormats.multiByline = "Multi-byline" - } - - const nonArticleFormats = { - "liveblog": "Live blog", - "gallery": "Gallery", - "interactive": "Interactive", - "picture": "Picture", - "audio": "Audio", - "atom": "Video/Atom" - } - // Assembling the object this way preserves the existing order in the UI - return Promise.resolve({...articleFormats, ...nonArticleFormats}); - } - getTypes() { return wfPreferencesService.getPreference('featureSwitches') - .then((featureSwitches) => { - return this.provideFormats(featureSwitches) - }) - .catch((err) => {return this.provideFormats()}) + .then((featureSwitches) => { + return provideFormats(featureSwitches) + }) + .catch((err) => { return provideFormats() }) } /* what types of stub should be treated as atoms? */ @@ -363,7 +339,7 @@ angular.module('wfContentService', ['wfHttpSessionService', 'wfVisibilityService const localSearch = this._paramsProvider() this.currentSearch = localSearch - + return wfContentService.get(localSearch) .then((cb) => { const localSearchIsStale = localSearch !== this.currentSearch diff --git a/public/lib/model/format-helpers.ts b/public/lib/model/format-helpers.ts new file mode 100644 index 000000000..a137d4606 --- /dev/null +++ b/public/lib/model/format-helpers.ts @@ -0,0 +1,58 @@ +import { specialFormats, STANDARD_ARTICLE_FORMAT_LABEL } from './special-formats' +import { ContentType } from './stub' + + +const nonArticleFormats = { + "liveblog": "Live blog", + "gallery": "Gallery", + "interactive": "Interactive", + "picture": "Picture", + "audio": "Audio", + "atom": "Video/Atom" +} + +const provideFormats = (featureSwitches?: Record): Partial> => { + const articleFormats: Record = { + "article": "Article", + } + + specialFormats.forEach(format => { + if (format.behindFeatureSwitch) { + if (featureSwitches?.[format.behindFeatureSwitch]) { + articleFormats[format.value] = format.label + } + } else { + articleFormats[format.value] = format.label + } + }) + + + // Assembling the object this way preserves the existing order in the UI + return { ...articleFormats, ...nonArticleFormats }; +} + +/** + * Returns a list of objects describing the available article formats + * that can be used to as a model for a select input in an angular template + */ +const provideArticleFormatsForDropDown = (featureSwitches?: Record): { name: string; value: string }[] => { + + const list = [STANDARD_ARTICLE_FORMAT_LABEL] + + specialFormats.forEach(format => { + if (format.behindFeatureSwitch) { + if (featureSwitches && featureSwitches[format.behindFeatureSwitch]) { + list.push(format.label) + } + } else { + list.push(format.label) + } + }) + + return list.map(label => ({ name: label, value: label })) +} + + + + +export { provideFormats, provideArticleFormatsForDropDown } \ No newline at end of file diff --git a/public/lib/model/special-formats.ts b/public/lib/model/special-formats.ts index 796c6488c..fb2de6491 100644 --- a/public/lib/model/special-formats.ts +++ b/public/lib/model/special-formats.ts @@ -1,13 +1,13 @@ import { ComposerContentType, ContentType, SpecialArticleFormat, Stub } from "./stub"; -const STANDARD_ARTICLE_FORMAT_LABEL = "Standard Article"; +const STANDARD_ARTICLE_FORMAT_LABEL = "Standard Article"; const specialFormats: SpecialArticleFormat[] = [ - { label: 'Key Takeaways', value: 'keyTakeaways', iconId: 'keyTakeaways' }, - { label: 'Q&A Explainer', value: 'qAndA', iconId: 'qAndA' }, - { label: 'Timeline', value: 'timeline', iconId: 'timeline' }, - { label: 'Mini profiles', value: 'miniProfiles', iconId: 'miniProfiles' }, - { label: 'Multi-byline', value: 'multiByline', iconId: 'multiByline', hidden: true }, + { label: 'Key Takeaways', value: 'keyTakeaways' }, + { label: 'Q&A Explainer', value: 'qAndA' }, + { label: 'Timeline', value: 'timeline' }, + { label: 'Mini profiles', value: 'miniProfiles' }, + { label: 'Multi-byline', value: 'multiByline', behindFeatureSwitch: 'multiByline' }, ] const setDisplayHintForFormat = (stub: Stub): Stub => { @@ -22,7 +22,7 @@ const setDisplayHintForFormat = (stub: Stub): Stub => { * return "Standard Article" for normal articles, the label for special article formats * or empty string for non-article stubs */ -const getStubArticleFormat = (contentType:ContentType): string => { +const getStubArticleFormat = (contentType: ContentType): string => { const maybeMatchingFormat = specialFormats.find(format => format.value === contentType) if (maybeMatchingFormat) { return maybeMatchingFormat.label @@ -33,7 +33,7 @@ const getStubArticleFormat = (contentType:ContentType): string => { return '' } -const isFormatLabel = (value:string):boolean => { +const isFormatLabel = (value: string): boolean => { return value === STANDARD_ARTICLE_FORMAT_LABEL || specialFormats.some(format => format.label === value) } @@ -55,4 +55,4 @@ const contentTypeToComposerContentType = (type: ContentType): ComposerContentTyp } } -export { specialFormats, setDisplayHintForFormat, getSpecialFormatFromLabel, contentTypeToComposerContentType, getStubArticleFormat, isFormatLabel } \ No newline at end of file +export { STANDARD_ARTICLE_FORMAT_LABEL, specialFormats, setDisplayHintForFormat, getSpecialFormatFromLabel, contentTypeToComposerContentType, getStubArticleFormat, isFormatLabel } \ No newline at end of file diff --git a/public/lib/model/stub.ts b/public/lib/model/stub.ts index 3b6785374..e864656ba 100644 --- a/public/lib/model/stub.ts +++ b/public/lib/model/stub.ts @@ -35,7 +35,6 @@ export type Stub = { export type SpecialArticleFormat = { label: string, value: SpecialFormatContentType, - iconId: string, - hidden?: boolean, + behindFeatureSwitch?: string, } From bf370850e4bf46ab14469c37ca649ae98897842e Mon Sep 17 00:00:00 2001 From: dblatcher Date: Wed, 22 Jan 2025 14:02:19 +0000 Subject: [PATCH 7/7] refactor the helper files --- public/components/stub-modal/stub-modal.js | 7 +++-- public/lib/model/format-helpers.ts | 32 ++++++++++++++++++++-- public/lib/model/special-formats.ts | 23 +--------------- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/public/components/stub-modal/stub-modal.js b/public/components/stub-modal/stub-modal.js index 7fe561e4d..1b73a0fbe 100644 --- a/public/components/stub-modal/stub-modal.js +++ b/public/components/stub-modal/stub-modal.js @@ -17,7 +17,8 @@ import 'lib/prodoffice-service'; import 'lib/telemetry-service'; import { punters } from 'components/punters/punters'; import { generateErrorMessages, doesContentTypeRequireCommissionedLength, useNativeFormFeedback } from '../../lib/stub-form-validation.ts'; -import { getStubArticleFormat, isFormatLabel, setDisplayHintForFormat } from 'lib/model/special-formats.ts'; +import { setDisplayHintForFormat } from 'lib/model/special-formats.ts'; +import { getArticleFormatLabel, isFormatLabel } from 'lib/model/format-helpers.ts'; const wfStubModal = angular.module('wfStubModal', [ 'ui.bootstrap', 'articleFormatService', 'legalStatesService', 'pictureDeskStatesService', 'wfComposerService', 'wfContentService', 'wfDateTimePicker', 'wfProdOfficeService', 'wfFiltersService', 'wfCapiAtomService', 'wfTelemetryService']) @@ -32,7 +33,7 @@ function StubModalInstanceCtrl($rootScope, $scope, $modalInstance, $window, conf (wfContentService.getAtomTypes())[stub.contentType] ? "Atom" : (types[stub.contentType] || "News item"); - $scope.stubFormat = getStubArticleFormat(stub.contentType); + $scope.stubFormat = getArticleFormatLabel(stub.contentType); $scope.$watch('stub.articleFormat', (newValue) => { $scope.stubFormat = newValue; @@ -491,7 +492,7 @@ wfStubModal.run([ function createStubData (contentType, sectionName) { return { - articleFormat: getStubArticleFormat(contentType), + articleFormat: getArticleFormatLabel(contentType), contentType: contentType === "atom" ? defaultAtomType : contentType, // Only send through a section if one is found in the prefs section: sectionName === null ? sectionName : sections.filter((section) => section.name === sectionName)[0], diff --git a/public/lib/model/format-helpers.ts b/public/lib/model/format-helpers.ts index a137d4606..8b7598689 100644 --- a/public/lib/model/format-helpers.ts +++ b/public/lib/model/format-helpers.ts @@ -1,6 +1,8 @@ -import { specialFormats, STANDARD_ARTICLE_FORMAT_LABEL } from './special-formats' +import { specialFormats } from './special-formats' import { ContentType } from './stub' +const STANDARD_ARTICLE_FORMAT_LABEL = "Standard Article"; +const STANDARD_ARTICLE_FORMAT_SHORT_LABEL = "Article"; const nonArticleFormats = { "liveblog": "Live blog", @@ -11,9 +13,13 @@ const nonArticleFormats = { "atom": "Video/Atom" } +/** + * Returns an object mapping ContentType to user facings labels, excluding any + * special formats that that behind a feature switch in the 'off' state. + */ const provideFormats = (featureSwitches?: Record): Partial> => { const articleFormats: Record = { - "article": "Article", + "article": STANDARD_ARTICLE_FORMAT_SHORT_LABEL, } specialFormats.forEach(format => { @@ -52,7 +58,27 @@ const provideArticleFormatsForDropDown = (featureSwitches?: Record ({ name: label, value: label })) } +/** + * returns "Standard Article" for normal articles, the label for special article formats + * or empty string for non-article content types + */ +const getArticleFormatLabel = (contentType: ContentType): string => { + const maybeMatchingFormat = specialFormats.find(format => format.value === contentType) + if (maybeMatchingFormat) { + return maybeMatchingFormat.label + } + if (contentType === 'article') { + return STANDARD_ARTICLE_FORMAT_LABEL + } + return '' +} +/** + * true if the value is the label of a special format or the "Standard Article" label + */ +const isFormatLabel = (value: string): boolean => { + return value === STANDARD_ARTICLE_FORMAT_LABEL || specialFormats.some(format => format.label === value) +} -export { provideFormats, provideArticleFormatsForDropDown } \ No newline at end of file +export { provideFormats, provideArticleFormatsForDropDown, getArticleFormatLabel, isFormatLabel } \ No newline at end of file diff --git a/public/lib/model/special-formats.ts b/public/lib/model/special-formats.ts index fb2de6491..fa4baf5db 100644 --- a/public/lib/model/special-formats.ts +++ b/public/lib/model/special-formats.ts @@ -1,7 +1,5 @@ import { ComposerContentType, ContentType, SpecialArticleFormat, Stub } from "./stub"; -const STANDARD_ARTICLE_FORMAT_LABEL = "Standard Article"; - const specialFormats: SpecialArticleFormat[] = [ { label: 'Key Takeaways', value: 'keyTakeaways' }, { label: 'Q&A Explainer', value: 'qAndA' }, @@ -18,25 +16,6 @@ const setDisplayHintForFormat = (stub: Stub): Stub => { return stub } -/** - * return "Standard Article" for normal articles, the label for special article formats - * or empty string for non-article stubs - */ -const getStubArticleFormat = (contentType: ContentType): string => { - const maybeMatchingFormat = specialFormats.find(format => format.value === contentType) - if (maybeMatchingFormat) { - return maybeMatchingFormat.label - } - if (contentType === 'article') { - return STANDARD_ARTICLE_FORMAT_LABEL - } - return '' -} - -const isFormatLabel = (value: string): boolean => { - return value === STANDARD_ARTICLE_FORMAT_LABEL || specialFormats.some(format => format.label === value) -} - const getSpecialFormatFromLabel = (label: string): SpecialArticleFormat | undefined => specialFormats.find(format => format.label === label) @@ -55,4 +34,4 @@ const contentTypeToComposerContentType = (type: ContentType): ComposerContentTyp } } -export { STANDARD_ARTICLE_FORMAT_LABEL, specialFormats, setDisplayHintForFormat, getSpecialFormatFromLabel, contentTypeToComposerContentType, getStubArticleFormat, isFormatLabel } \ No newline at end of file +export { specialFormats, setDisplayHintForFormat, getSpecialFormatFromLabel, contentTypeToComposerContentType } \ No newline at end of file