diff --git a/api/converters.py b/api/converters.py index fc8db83b..bc55d134 100644 --- a/api/converters.py +++ b/api/converters.py @@ -232,6 +232,7 @@ def _prep_stage_gate_info( ot_type = STAGE_TYPES_ORIGIN_TRIAL[fe.feature_type] extend_type = STAGE_TYPES_EXTEND_ORIGIN_TRIAL[fe.feature_type] ship_type = STAGE_TYPES_SHIPPING[fe.feature_type] + rollout_type = STAGE_TYPES_ROLLOUT[fe.feature_type] stages = Stage.query(Stage.feature_id == d['id']) major_stages: dict[str, Optional[Stage]] = { @@ -239,7 +240,8 @@ def _prep_stage_gate_info( 'dev_trial': None, 'ot': None, 'extend': None, - 'ship': None} + 'ship': None, + 'rollout': None} # Write a list of stages and gates associated with the feature d['stages'] = stage_helpers.get_feature_stage_ids_list(d['id']) @@ -258,6 +260,8 @@ def _prep_stage_gate_info( major_stages['extend'] = s elif s.stage_type == ship_type: major_stages['ship'] = s + elif s.stage_type == rollout_type: + major_stages['rollout'] = s return major_stages @@ -359,10 +363,10 @@ def feature_entry_to_json_verbose(fe: FeatureEntry) -> dict[str, Any]: # Ship stage fields. d['intent_to_ship_url'] = _stage_attr(stages['ship'], 'intent_thread_url') d['finch_url'] = _stage_attr(stages['ship'], 'finch_url') - d['rollout_milestone'] = _stage_attr(stages['ship'], 'rollout_milestone') - d['rollout_platforms'] = _stage_attr(stages['ship'], 'rollout_platforms') - d['rollout_details'] = _stage_attr(stages['ship'], 'rollout_details') - d['enterprise_policies'] = _stage_attr(stages['ship'], 'enterprise_policies') + d['rollout_milestone'] = _stage_attr(stages['rollout'], 'rollout_milestone') + d['rollout_platforms'] = _stage_attr(stages['rollout'], 'rollout_platforms') + d['rollout_details'] = _stage_attr(stages['rollout'], 'rollout_details') + d['enterprise_policies'] = _stage_attr(stages['rollout'], 'enterprise_policies') impl_status_chrome = d.pop('impl_status_chrome', None) standard_maturity = d.pop('standard_maturity', None) diff --git a/api/processes_api_test.py b/api/processes_api_test.py index 213929aa..a8034704 100644 --- a/api/processes_api_test.py +++ b/api/processes_api_test.py @@ -68,7 +68,6 @@ class ProcessesAPITest(testing_config.CustomTestCase): self.feature_1.feature_type = 0 self.feature_1.breaking_change = True self.feature_1.put() - self.maxDiff = None with test_app.test_request_context(self.request_path): actual = self.handler.do_get(feature_id=self.feature_id) expected = processes.process_to_dict(processes.BLINK_LAUNCH_PROCESS) @@ -90,7 +89,6 @@ class ProcessesAPITest(testing_config.CustomTestCase): self.feature_1.feature_type = 1 self.feature_1.breaking_change = True self.feature_1.put() - self.maxDiff = None with test_app.test_request_context(self.request_path): actual = self.handler.do_get(feature_id=self.feature_id) expected = processes.process_to_dict(processes.BLINK_FAST_TRACK_PROCESS) @@ -112,7 +110,6 @@ class ProcessesAPITest(testing_config.CustomTestCase): self.feature_1.feature_type = 2 self.feature_1.breaking_change = True self.feature_1.put() - self.maxDiff = None with test_app.test_request_context(self.request_path): actual = self.handler.do_get(feature_id=self.feature_id) expected = processes.process_to_dict(processes.PSA_ONLY_PROCESS) @@ -134,7 +131,6 @@ class ProcessesAPITest(testing_config.CustomTestCase): self.feature_1.feature_type = 3 self.feature_1.breaking_change = True self.feature_1.put() - self.maxDiff = None with test_app.test_request_context(self.request_path): actual = self.handler.do_get(feature_id=self.feature_id) expected = processes.process_to_dict(processes.DEPRECATION_PROCESS) @@ -156,7 +152,6 @@ class ProcessesAPITest(testing_config.CustomTestCase): self.feature_1.feature_type = 4 self.feature_1.breaking_change = True self.feature_1.put() - self.maxDiff = None with test_app.test_request_context(self.request_path): actual = self.handler.do_get(feature_id=self.feature_id) expected = processes.process_to_dict(processes.ENTERPRISE_PROCESS) @@ -206,7 +201,6 @@ class ProgressAPITest(testing_config.CustomTestCase): with test_app.test_request_context(self.request_path): actual = self.handler.do_get(feature_id=self.feature_id) - self.maxDiff = None self.assertEqual({ 'Code in Chromium': 'True', 'Draft API spec': 'fake spec link', diff --git a/client-src/elements/chromedash-guide-editall-page.js b/client-src/elements/chromedash-guide-editall-page.js index 692ae778..d339deec 100644 --- a/client-src/elements/chromedash-guide-editall-page.js +++ b/client-src/elements/chromedash-guide-editall-page.js @@ -3,7 +3,11 @@ import {ref} from 'lit/directives/ref.js'; import {showToastMessage} from './utils.js'; import './chromedash-form-table'; import './chromedash-form-field'; -import {formatFeatureForEdit, FLAT_FORMS_BY_FEATURE_TYPE} from './form-definition'; +import { + formatFeatureForEdit, + FLAT_FORMS_BY_FEATURE_TYPE, + FLAT_ENTERPRISE_PREPARE_TO_SHIP_NAME, + FLAT_ENTERPRISE_PREPARE_TO_SHIP} from './form-definition'; import {SHARED_STYLES} from '../sass/shared-css.js'; import {FORM_STYLES} from '../sass/forms-css.js'; @@ -31,6 +35,7 @@ export class ChromedashGuideEditallPage extends LitElement { super(); this.featureId = 0; this.feature = {}; + this.featureForEdit = {}; this.loading = true; this.appTitle = ''; this.nextPage = ''; @@ -45,6 +50,7 @@ export class ChromedashGuideEditallPage extends LitElement { this.loading = true; window.csClient.getFeature(this.featureId).then((feature) => { this.feature = feature; + this.featureForEdit = formatFeatureForEdit(feature); if (this.feature.name) { document.title = `${this.feature.name} - ${this.appTitle}`; } @@ -85,10 +91,25 @@ export class ChromedashGuideEditallPage extends LitElement { window.location.href = `/guide/edit/${this.featureId}`; } + getForms() { + const forms = JSON.parse(JSON.stringify( + FLAT_FORMS_BY_FEATURE_TYPE[this.featureForEdit.feature_type])); + + // Ensures the rollout field is shown for breaking changes. + if (this.featureForEdit.breaking_change && + !forms.some(([name]) => name === FLAT_ENTERPRISE_PREPARE_TO_SHIP_NAME)) { + forms.splice( + forms.length - 1, + 0, + [FLAT_ENTERPRISE_PREPARE_TO_SHIP_NAME, FLAT_ENTERPRISE_PREPARE_TO_SHIP]); + } + return forms; + } + // get a comma-spearated list of field names - getFormFields(featureType) { + getFormFields() { let fields = []; - FLAT_FORMS_BY_FEATURE_TYPE[featureType].map((form) => { + this.getForms().map((form) => { fields = [...fields, ...form[1]]; }); return fields.join(); @@ -137,20 +158,19 @@ export class ChromedashGuideEditallPage extends LitElement { } renderForm() { - const formattedFeature = formatFeatureForEdit(this.feature); return html`