From dda0f9e2cabb2f009093cd2b6a298d680503e319 Mon Sep 17 00:00:00 2001 From: Yann Dago Date: Wed, 18 Dec 2024 09:08:42 -0500 Subject: [PATCH] Add enterprise product category field to features --- api/api_specs.py | 1 + api/converters.py | 3 +++ api/converters_test.py | 3 +++ api/legacy_converters.py | 1 + client-src/css/forms-css.js | 10 +++++++ client-src/elements/chromedash-form-field.ts | 2 +- .../chromedash-guide-metadata-page.ts | 1 + .../elements/chromedash-guide-new-page.ts | 18 +++++-------- .../elements/chromedash-ot-creation-page.ts | 10 ------- client-src/elements/form-definition.ts | 5 ++++ client-src/elements/form-field-enums.ts | 27 +++++++++++++++++++ client-src/elements/form-field-specs.ts | 10 +++++++ client-src/elements/queriable-fields.ts | 7 +++++ client-src/elements/utils.ts | 4 +++ client-src/js-src/cs-client.js | 1 + internals/core_enums.py | 5 ++++ internals/core_models.py | 1 + internals/data_types.py | 1 + 18 files changed, 87 insertions(+), 23 deletions(-) diff --git a/api/api_specs.py b/api/api_specs.py index 57f6f1a54a09..f780a626a55e 100644 --- a/api/api_specs.py +++ b/api/api_specs.py @@ -42,6 +42,7 @@ ('doc_links', 'links'), ('editor_emails', 'emails'), ('enterprise_feature_categories', 'split_str'), + ('enterprise_product_category', 'int'), ('ergonomics_risks', 'str'), ('explainer_links', 'links'), ('feature_notes', 'str'), diff --git a/api/converters.py b/api/converters.py index 6af8f81cf62d..57cb03d1435b 100644 --- a/api/converters.py +++ b/api/converters.py @@ -356,6 +356,7 @@ def feature_entry_to_json_verbose( 'category_int': fe.category, 'feature_notes': fe.feature_notes, 'enterprise_feature_categories': fe.enterprise_feature_categories or [], + 'enterprise_product_category': fe.enterprise_product_category or ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE, 'stages': stage_info['all_stages'], 'accurate_as_of': _date_to_str(fe.accurate_as_of), 'creator_email': fe.creator_email, @@ -491,6 +492,7 @@ def feature_entry_to_json_verbose( }, }, 'enterprise_feature_categories': fe.enterprise_feature_categories or [], + 'enterprise_product_category': fe.enterprise_product_category or ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE, 'standards': { 'spec': fe.spec_link, 'maturity': { @@ -532,6 +534,7 @@ def feature_entry_to_json_basic(fe: FeatureEntry, 'summary': fe.summary, 'unlisted': fe.unlisted, 'enterprise_impact': fe.enterprise_impact, + 'enterprise_product_category': fe.enterprise_product_category or ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE, 'breaking_change': fe.breaking_change, 'first_enterprise_notification_milestone': fe.first_enterprise_notification_milestone, 'blink_components': fe.blink_components or [], diff --git a/api/converters_test.py b/api/converters_test.py index 6b438ceffcc5..b02a2e77fa07 100644 --- a/api/converters_test.py +++ b/api/converters_test.py @@ -106,6 +106,7 @@ def test_feature_entry_to_json_basic__normal(self): 'blink_components': ['Blink'], 'first_enterprise_notification_milestone': 100, 'enterprise_impact': ENTERPRISE_IMPACT_NONE, + 'enterprise_product_category': 0, 'breaking_change': False, 'is_released': True, 'milestone': None, @@ -192,6 +193,7 @@ def test_feature_entry_to_json_basic__feature_release(self): 'blink_components': ['Blink'], 'first_enterprise_notification_milestone': 100, 'enterprise_impact': ENTERPRISE_IMPACT_NONE, + 'enterprise_product_category': 0, 'breaking_change': False, 'is_released': True, 'milestone': True, @@ -295,6 +297,7 @@ def test_feature_entry_to_json_verbose__normal(self): 'unlisted': False, 'api_spec': False, 'enterprise_impact': ENTERPRISE_IMPACT_NONE, + 'enterprise_product_category': 0, 'shipping_year': 2024, 'breaking_change': False, 'is_released': True, diff --git a/api/legacy_converters.py b/api/legacy_converters.py index bf16a1a9ed3d..9cca93d907a3 100644 --- a/api/legacy_converters.py +++ b/api/legacy_converters.py @@ -31,6 +31,7 @@ def feature_to_legacy_json(f: Feature) -> dict[str, Any]: d['id'] = None d['category'] = FEATURE_CATEGORIES[f.category] d['enterprise_feature_categories'] = f.enterprise_feature_categories + d['enterprise_product_category'] = f.enterprise_product_category d['category_int'] = f.category if f.feature_type is not None: d['feature_type'] = FEATURE_TYPES[f.feature_type] diff --git a/client-src/css/forms-css.js b/client-src/css/forms-css.js index 288a8f3ff74d..40880d255f60 100644 --- a/client-src/css/forms-css.js +++ b/client-src/css/forms-css.js @@ -275,4 +275,14 @@ export const FORM_STYLES = [ width: 30%; height: 1.5em; } + + .choices label { + font-weight: bold; + } + .choices div { + margin-top: 1em; + } + .choices p { + margin: 0.5em 1.5em 1em; + } `]; diff --git a/client-src/elements/chromedash-form-field.ts b/client-src/elements/chromedash-form-field.ts index b83266389a8c..a6897807a939 100644 --- a/client-src/elements/chromedash-form-field.ts +++ b/client-src/elements/chromedash-form-field.ts @@ -372,7 +372,7 @@ export class ChromedashFormField extends LitElement { id="id_${this.name}_${value}" name="${fieldName}" value="${value}" - .checked="${value === fieldValue}" + .checked="${value === Number(fieldValue)}" type="radio" required @change=${this.handleFieldUpdated} diff --git a/client-src/elements/chromedash-guide-metadata-page.ts b/client-src/elements/chromedash-guide-metadata-page.ts index 1de369dac329..86c23729651e 100644 --- a/client-src/elements/chromedash-guide-metadata-page.ts +++ b/client-src/elements/chromedash-guide-metadata-page.ts @@ -187,6 +187,7 @@ export class ChromedashGuideMetadataPage extends LitElement { .feature=${formattedFeature} ?forEnterprise=${formattedFeature.is_enterprise_feature} @form-field-update="${this.handleFormFieldUpdate}" + class="${field === 'enterprise_product_category' ? 'choices' : ''}" > `; diff --git a/client-src/elements/chromedash-guide-new-page.ts b/client-src/elements/chromedash-guide-new-page.ts index 7e7af5b685dd..0eab53c86b1f 100644 --- a/client-src/elements/chromedash-guide-new-page.ts +++ b/client-src/elements/chromedash-guide-new-page.ts @@ -32,17 +32,6 @@ export class ChromedashGuideNewPage extends LitElement { box-shadow: 0 0 0 var(--sl-focus-ring-width) var(--sl-input-focus-ring-color); } - - .choices label { - font-weight: bold; - } - .choices div { - margin-top: 1em; - } - .choices p { - margin: 0.5em 1.5em 1em; - } - .process-notice { margin: var(--content-padding-half) 0; padding: var(--content-padding-half); @@ -211,7 +200,12 @@ export class ChromedashGuideNewPage extends LitElement { ${!this.isEnterpriseFeature ? renderFormField('feature_type_radio_group', 'choices') : nothing} - ${formFields.map(field => renderFormField(field))} + ${formFields.map(field => + renderFormField( + field, + field === 'enterprise_product_category' ? 'choices' : null + ) + )} parseInt(x).toString()), + enterprise_product_category: feature.enterprise_product_category, feature_type: feature.feature_type_int, intent_stage: feature.intent_stage_int, @@ -177,6 +179,7 @@ export const ENTERPRISE_NEW_FEATURE_FORM_FIELDS = [ 'owner', 'editors', 'enterprise_feature_categories', + 'enterprise_product_category', 'first_enterprise_notification_milestone', 'enterprise_impact', ]; @@ -192,6 +195,7 @@ export const FLAT_METADATA_FIELDS: MetadataFields = { 'name', 'summary', 'unlisted', + 'enterprise_product_category', 'enterprise_impact', 'shipping_year', 'owner', @@ -232,6 +236,7 @@ export const FLAT_ENTERPRISE_METADATA_FIELDS: MetadataFields = { 'owner', 'editors', 'enterprise_feature_categories', + 'enterprise_product_category', 'enterprise_impact', 'first_enterprise_notification_milestone', 'screenshot_links', diff --git a/client-src/elements/form-field-enums.ts b/client-src/elements/form-field-enums.ts index ae9a8719d452..01e57f82e3b8 100644 --- a/client-src/elements/form-field-enums.ts +++ b/client-src/elements/form-field-enums.ts @@ -192,6 +192,33 @@ export const FEATURE_TYPES: Record< ], }; +export const ENTERPRISE_PRODUCT_CATEGORY: Record< + string, + [number, string, string | HTMLTemplateResult] +> = { + ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE: [ + 0, + 'Chrome Browser update', + 'New features, performance improvements, security fixes and minor updates addressing security vulnerabilities and bugs. These features apply to both consumers and enterprises.', + ], + ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_CORE: [ + 1, + 'Chrome Enterprise Core (CEC)', + 'These features allow IT administrators to manage Chrome browser settings, policies, apps and extensions across an organization from a central location (Admin Console).', + ], + ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_PREMIUM: [ + 2, + 'Chrome Enterprise Premium (CEP, paid SKU)', + 'These features add advanced security and enhanced controls for organizations with more demanding needs e.g. data masking functionality.', + ], +}; + +export const ENTERPRISE_PRODUCT_CATEGORY_DISPLAYNAME: Record = { + 0: 'Chrome Browser update', // ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE + 1: 'Chrome Enterprise Core (CEC)', // ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_CORE + 2: 'Chrome Enterprise Premium (CEP, paid SKU)', // ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_PREMIUM +}; + // *********************************************************************** // Stage type values for each process. Even though some of the stages // in these processes are similar to each other, they have distinct enum diff --git a/client-src/elements/form-field-specs.ts b/client-src/elements/form-field-specs.ts index 38f82edaf59b..452a40af2ad0 100644 --- a/client-src/elements/form-field-specs.ts +++ b/client-src/elements/form-field-specs.ts @@ -5,6 +5,7 @@ import { DT_MILESTONE_FIELDS, ENTERPRISE_FEATURE_CATEGORIES, ENTERPRISE_IMPACT, + ENTERPRISE_PRODUCT_CATEGORY, FEATURE_CATEGORIES, FEATURE_TYPES, FEATURE_TYPES_WITHOUT_ENTERPRISE, @@ -491,6 +492,15 @@ export const ALL_FIELDS: Record = { "Miscellaneous".`, }, + enterprise_product_category: { + type: 'radios', + name: 'enterprise_product_category', + choices: ENTERPRISE_PRODUCT_CATEGORY, + label: 'Enterprise product category', + help_text: html` Select the product that this feature affect.`, + check: (_value, getFieldValue) => checkFeatureNameAndType(getFieldValue), + }, + feature_type: { type: 'select', disabled: true, diff --git a/client-src/elements/queriable-fields.ts b/client-src/elements/queriable-fields.ts index 97f7a4ef6cb1..df8ccf1a5e79 100644 --- a/client-src/elements/queriable-fields.ts +++ b/client-src/elements/queriable-fields.ts @@ -3,6 +3,7 @@ import {type HTMLTemplateResult} from 'lit'; import { + ENTERPRISE_PRODUCT_CATEGORY, FEATURE_CATEGORIES, FEATURE_TYPES, IMPLEMENTATION_STATUS, @@ -193,6 +194,12 @@ export const QUERIABLE_FIELDS: QueryField[] = [ doc: 'Feature category', choices: FEATURE_CATEGORIES, }, + { + name: 'enterprise_product_category', + kind: ENUM_KIND, + doc: 'Enterprise product category', + choices: ENTERPRISE_PRODUCT_CATEGORY, + }, { name: 'feature_type', kind: ENUM_KIND, diff --git a/client-src/elements/utils.ts b/client-src/elements/utils.ts index 60f7f10e09fd..1d0d8a465215 100644 --- a/client-src/elements/utils.ts +++ b/client-src/elements/utils.ts @@ -7,6 +7,7 @@ import {FORMS_BY_STAGE_TYPE, FormattedFeature} from './form-definition.js'; import { ENTERPRISE_FEATURE_CATEGORIES_DISPLAYNAME, ENTERPRISE_IMPACT_DISPLAYNAME, + ENTERPRISE_PRODUCT_CATEGORY_DISPLAYNAME, OT_MILESTONE_END_FIELDS, OT_SETUP_STATUS_OPTIONS, PLATFORMS_DISPLAYNAME, @@ -278,6 +279,9 @@ export function getFieldValueFromFeature( value = feature[fieldName]; } + if (fieldName === 'enterprise_product_category' && value !== undefined) { + return ENTERPRISE_PRODUCT_CATEGORY_DISPLAYNAME[value]; + } if (fieldName === 'enterprise_feature_categories' && value) { return value.map( categoryId => ENTERPRISE_FEATURE_CATEGORIES_DISPLAYNAME[categoryId] diff --git a/client-src/js-src/cs-client.js b/client-src/js-src/cs-client.js index 2354472f12af..b2ab99444e6f 100644 --- a/client-src/js-src/cs-client.js +++ b/client-src/js-src/cs-client.js @@ -200,6 +200,7 @@ * @property {string[]} search_tags * @property {string} [feature_notes] * @property {string[]} enterprise_feature_categories + * @property {number} enterprise_product_category * Metadata: Process information * @property {string} feature_type * @property {number} feature_type_int diff --git a/internals/core_enums.py b/internals/core_enums.py index 82fb7eb5545b..95dacbef12ff 100644 --- a/internals/core_enums.py +++ b/internals/core_enums.py @@ -121,6 +121,11 @@ IWA: 'Isolated Web Apps-specific API', } + +ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE = 0 +ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_CORE = 1 +ENTERPRISE_PRODUCT_CATEGORY_CHROME_ENTERPRISE_PREMIUM = 2 + FEATURE_TYPE_INCUBATE_ID = 0 FEATURE_TYPE_EXISTING_ID = 1 FEATURE_TYPE_CODE_CHANGE_ID = 2 diff --git a/internals/core_models.py b/internals/core_models.py index 09a054b6b5f0..15ffbfe9da48 100644 --- a/internals/core_models.py +++ b/internals/core_models.py @@ -88,6 +88,7 @@ class FeatureEntry(ndb.Model): # Copy from Feature name = ndb.StringProperty(required=True) summary = ndb.TextProperty(required=True) category = ndb.IntegerProperty(required=True) + enterprise_product_category = ndb.IntegerProperty(required=True, default=ENTERPRISE_PRODUCT_CATEGORY_CHROME_BROWSER_UPDATE) enterprise_feature_categories = ndb.StringProperty(repeated=True) blink_components = ndb.StringProperty(repeated=True) star_count = ndb.IntegerProperty(default=0) diff --git a/internals/data_types.py b/internals/data_types.py index f3db0d925758..c4c24f9833af 100644 --- a/internals/data_types.py +++ b/internals/data_types.py @@ -204,6 +204,7 @@ class VerboseFeatureDict(TypedDict): search_tags: list[str] feature_notes: str | None enterprise_feature_categories: list[str] + enterprise_product_category: int # Metadata: Process information feature_type: str