Родитель
85367d43ec
Коммит
2ad5ef3166
|
@ -1,6 +1,7 @@
|
|||
import {LitElement, css, html, nothing} from 'lit';
|
||||
import {LitElement, TemplateResult, css, html, nothing} from 'lit';
|
||||
import {ref} from 'lit/directives/ref.js';
|
||||
import {
|
||||
FieldInfo,
|
||||
formatFeatureChanges,
|
||||
getStageValue,
|
||||
parseRawQuery,
|
||||
|
@ -14,6 +15,7 @@ import {
|
|||
FLAT_TRIAL_EXTENSION_FIELDS,
|
||||
formatFeatureForEdit,
|
||||
FORMS_BY_STAGE_TYPE,
|
||||
MetadataFields,
|
||||
} from './form-definition';
|
||||
import {
|
||||
IMPLEMENTATION_STATUS,
|
||||
|
@ -23,42 +25,43 @@ import {
|
|||
import {ALL_FIELDS} from './form-field-specs';
|
||||
import {SHARED_STYLES} from '../css/shared-css.js';
|
||||
import {FORM_STYLES} from '../css/forms-css.js';
|
||||
import {customElement, property, state} from 'lit/decorators.js';
|
||||
import {Feature, StageDict} from '../js-src/cs-client.js';
|
||||
|
||||
@customElement('chromedash-guide-stage-page')
|
||||
export class ChromedashGuideStagePage extends LitElement {
|
||||
static get styles() {
|
||||
return [...SHARED_STYLES, ...FORM_STYLES, css``];
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
stageId: {type: Number},
|
||||
stageName: {type: String},
|
||||
featureId: {type: Number},
|
||||
feature: {type: Object},
|
||||
isActiveStage: {type: Boolean},
|
||||
featureFormFields: {type: Array},
|
||||
implStatusFormFields: {type: Array},
|
||||
implStatusOffered: {type: String},
|
||||
loading: {type: Boolean},
|
||||
appTitle: {type: String},
|
||||
fieldValues: {type: Array},
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.stageId = 0;
|
||||
this.stageName = '';
|
||||
this.featureId = 0;
|
||||
this.feature = {};
|
||||
this.isActiveStage = false;
|
||||
this.featureFormFields = [];
|
||||
this.implStatusFormFields = [];
|
||||
this.implStatusOffered = '';
|
||||
this.loading = true;
|
||||
this.appTitle = '';
|
||||
this.fieldValues = [];
|
||||
}
|
||||
@property({attribute: false})
|
||||
stageId = 0;
|
||||
@property({attribute: false})
|
||||
featureId = 0;
|
||||
@property({attribute: false})
|
||||
intentStage = 0;
|
||||
@property({type: Array})
|
||||
implStatusFormFields: MetadataFields[] = [];
|
||||
@property({type: String})
|
||||
implStatusOffered = '';
|
||||
@property({type: String})
|
||||
appTitle = '';
|
||||
@state()
|
||||
stageName = '';
|
||||
@state()
|
||||
feature = {} as Feature;
|
||||
@state()
|
||||
stage!: StageDict;
|
||||
@state()
|
||||
isActiveStage = false;
|
||||
@state()
|
||||
featureFormFields!: MetadataFields;
|
||||
@state()
|
||||
loading = true;
|
||||
@state()
|
||||
fieldValues: FieldInfo[] & {feature?: Feature} = [];
|
||||
@state()
|
||||
gateId!: number;
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
@ -133,8 +136,10 @@ export class ChromedashGuideStagePage extends LitElement {
|
|||
/* Add the form's event listener after Shoelace event listeners are attached
|
||||
* see more at https://github.com/GoogleChrome/chromium-dashboard/issues/2014 */
|
||||
await el.updateComplete;
|
||||
const hiddenTokenField = this.shadowRoot.querySelector('input[name=token]');
|
||||
hiddenTokenField.form.addEventListener('submit', event => {
|
||||
const hiddenTokenField = this.renderRoot.querySelector(
|
||||
'input[name=token]'
|
||||
) as HTMLInputElement;
|
||||
hiddenTokenField.form?.addEventListener('submit', event => {
|
||||
this.handleFormSubmit(event, hiddenTokenField);
|
||||
});
|
||||
|
||||
|
@ -151,7 +156,7 @@ export class ChromedashGuideStagePage extends LitElement {
|
|||
.ensureTokenIsValid()
|
||||
.then(() => {
|
||||
hiddenTokenField.value = window.csClient.token;
|
||||
return csClient.updateFeature(submitBody);
|
||||
return window.csClient.updateFeature(submitBody);
|
||||
})
|
||||
.then(() => {
|
||||
// If we have a set gate ID, we need to redirect the user to finish
|
||||
|
@ -172,11 +177,11 @@ export class ChromedashGuideStagePage extends LitElement {
|
|||
miscSetup() {
|
||||
// Allow editing if there was already a value specified in this
|
||||
// deprecated field.
|
||||
const timelineField = this.shadowRoot.querySelector(
|
||||
const timelineField = this.renderRoot.querySelector(
|
||||
'#id_experiment_timeline'
|
||||
);
|
||||
) as HTMLInputElement;
|
||||
if (timelineField && timelineField.value) {
|
||||
timelineField.disabled = '';
|
||||
timelineField.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,7 +191,7 @@ export class ChromedashGuideStagePage extends LitElement {
|
|||
|
||||
// get a comma-spearated list of field names
|
||||
getFormFields() {
|
||||
const fields = this.featureFormFields.sections.reduce(
|
||||
const fields = this.featureFormFields.sections.reduce<string[]>(
|
||||
(combined, section) => [...combined, ...section.fields],
|
||||
[]
|
||||
);
|
||||
|
@ -229,7 +234,7 @@ export class ChromedashGuideStagePage extends LitElement {
|
|||
`;
|
||||
}
|
||||
|
||||
renderFields(formattedFeature, section, feStage) {
|
||||
renderFields(formattedFeature, section, feStage?) {
|
||||
if (!feStage) {
|
||||
feStage = this.stage;
|
||||
}
|
||||
|
@ -276,7 +281,7 @@ export class ChromedashGuideStagePage extends LitElement {
|
|||
}
|
||||
|
||||
renderSections(formattedFeature, stageSections) {
|
||||
const formSections = [];
|
||||
const formSections: (typeof nothing | TemplateResult)[] = [];
|
||||
if (!formattedFeature.is_enterprise_feature) {
|
||||
// Add the field to this component's stage before creating the field component.
|
||||
const index = this.fieldValues.length;
|
||||
|
@ -433,5 +438,3 @@ export class ChromedashGuideStagePage extends LitElement {
|
|||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('chromedash-guide-stage-page', ChromedashGuideStagePage);
|
|
@ -116,9 +116,9 @@ describe('chromedash-guide-stage-page', () => {
|
|||
|
||||
// invalid feature requests would trigger the toast to show message
|
||||
const toastEl = document.querySelector('chromedash-toast');
|
||||
const toastMsgSpan = toastEl.shadowRoot.querySelector('span#msg');
|
||||
const toastMsgSpan = toastEl?.shadowRoot?.querySelector('span#msg');
|
||||
assert.include(
|
||||
toastMsgSpan.innerHTML,
|
||||
toastMsgSpan?.innerHTML,
|
||||
'Some errors occurred. Please refresh the page or try again later.'
|
||||
);
|
||||
});
|
||||
|
@ -143,14 +143,14 @@ describe('chromedash-guide-stage-page', () => {
|
|||
assert.exists(component);
|
||||
assert.instanceOf(component, ChromedashGuideStagePage);
|
||||
|
||||
const subheaderDiv = component.shadowRoot.querySelector('div#subheader');
|
||||
const subheaderDiv = component.renderRoot.querySelector('div#subheader');
|
||||
assert.exists(subheaderDiv);
|
||||
// subheader title is correct and clickable
|
||||
assert.include(subheaderDiv.innerHTML, 'href="/feature/123456"');
|
||||
assert.include(subheaderDiv.innerHTML, 'Edit feature:');
|
||||
|
||||
// feature form, hidden token field, and submit/cancel buttons exist
|
||||
const form = component.shadowRoot.querySelector(
|
||||
const form = component.renderRoot.querySelector(
|
||||
'form[name="feature_form"]'
|
||||
);
|
||||
assert.exists(form);
|
|
@ -47,7 +47,7 @@ interface Section {
|
|||
implStatusValue?: number | null;
|
||||
}
|
||||
|
||||
interface MetadataFields {
|
||||
export interface MetadataFields {
|
||||
name: string;
|
||||
sections: Section[];
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче