create new stages on the feature detail page (#2611)

* create new stages on the feature detail page

* comments and spacing

* remove unused import

* changes suggested by @jrobbins

* Update chromedash-feature-detail.js

* change capitalization
This commit is contained in:
Daniel Smith 2023-01-03 10:42:23 -08:00 коммит произвёл GitHub
Родитель cedeeb91b3
Коммит 6b3c5602fa
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 173 добавлений и 1 удалений

Просмотреть файл

@ -115,7 +115,7 @@ class StagesAPI(basehandlers.APIHandler):
if use_stage_type:
if 'stage_type' not in body:
self.abort(404, msg='Stage type not specified.')
stage.stage_type = body['stage_type']
stage.stage_type = int(body['stage_type'])
s_type = stage.stage_type
for field in self.GENERAL_FIELDS:

Просмотреть файл

@ -0,0 +1,125 @@
import {LitElement, css, html} from 'lit';
import {SHARED_STYLES} from '../sass/shared-css.js';
import {CREATEABLE_STAGES, FORMS_BY_STAGE_TYPE} from './form-definition.js';
let addStageDialogEl;
let currentFeatureId;
export async function openAddStageDialog(featureId, featureType) {
if (!addStageDialogEl || currentFeatureId !== featureId) {
addStageDialogEl = document.createElement('chromedash-add-stage-dialog');
addStageDialogEl.featureId = featureId;
addStageDialogEl.featureType = featureType;
document.body.appendChild(addStageDialogEl);
await addStageDialogEl.updateComplete;
}
currentFeatureId = featureId;
addStageDialogEl.show();
}
class ChromedashAddStageDialog extends LitElement {
static get properties() {
return {
featureId: {type: Number},
featureType: {type: Number},
canSubmit: {type: Boolean},
};
}
constructor() {
super();
this.featureId = 0;
this.featureType = 0;
this.canSubmit = false;
}
static get styles() {
return [
...SHARED_STYLES,
css`
#controls {
padding: var(--content-padding);
text-align: right;
display: flex;
justify-content: space-between;
align-items: center;
}
#controls * + * {
padding-left: var(--content-padding);
}
`,
];
}
show() {
this.shadowRoot.querySelector('sl-dialog').show();
}
renderSelectMenuItems() {
const menuItems = [];
for (const stageType of CREATEABLE_STAGES[this.featureType]) {
// Get the name of the stage from the form definition based on the stage type.
const stageInfo = FORMS_BY_STAGE_TYPE[stageType];
menuItems.push(html`
<sl-menu-item value="${stageType}">
${stageInfo.name}
</sl-menu-item>
`);
}
return menuItems;
}
getStageSelectValue() {
const selectEl = this.shadowRoot.querySelector('#stage_create_select');
return selectEl.value;
}
handleStageCreate() {
window.csClient.createStage(this.featureId, this.getStageSelectValue())
.then(() => {
this.shadowRoot.querySelector('sl-dialog').hide();
location.reload();
});
}
checkCanSubmit() {
this.canSubmit = this.getStageSelectValue() !== 0;
}
renderStageSelect() {
return html`
<div id="controls">
<sl-select
placement="top"
value=0
id="stage_create_select"
size="small"
@sl-change=${this.checkCanSubmit}
style="width:16rem"
>
<sl-menu-item value="0" disabled>Select a stage to create</sl-menu-item>
${this.renderSelectMenuItems()}
</sl-select>
<sl-button variant="primary"
@click=${this.handleStageCreate}
?disabled=${!this.canSubmit}
size="small"
>Create stage</sl-button>
</div>
`;
}
render() {
return html`
<sl-dialog label="Create a new stage">
${this.renderStageSelect()}
</sl-dialog>
`;
}
}
customElements.define('chromedash-add-stage-dialog', ChromedashAddStageDialog);

Просмотреть файл

@ -1,4 +1,5 @@
import {LitElement, css, html, nothing} from 'lit';
import {openAddStageDialog} from './chromedash-add-stage-dialog';
import {DISPLAY_FIELDS_IN_STAGES} from './form-field-specs';
import {PLATFORMS_DISPLAYNAME} from './form-field-enums';
import '@polymer/iron-icon';
@ -388,6 +389,18 @@ class ChromedashFeatureDetail extends LitElement {
return this.renderSection(summary, content);
}
renderAddStageButton() {
if (!this.canEdit) {
return nothing;
}
return html`
<sl-button size="small" @click="${
() => openAddStageDialog(this.feature.id, this.feature.feature_type_int)}">
Add stage
</sl-button>`;
}
render() {
return html`
<h2>
@ -397,6 +410,7 @@ class ChromedashFeatureDetail extends LitElement {
${this.renderMetadataSection()}
${this.feature.stages.map(feStage => this.renderProcessStage(feStage))}
${this.renderActivitySection()}
${this.renderAddStageButton()}
`;
}
}

Просмотреть файл

@ -1,4 +1,5 @@
import {
FEATURE_TYPES,
IMPLEMENTATION_STATUS,
} from './form-field-enums';
@ -600,3 +601,29 @@ export const FORMS_BY_STAGE_TYPE = {
[STAGE_ENT_ROLLOUT]: FLAT_ENTERPRISE_PREPARE_TO_SHIP_FIELDS,
[STAGE_ENT_SHIPPED]: FLAT_PREPARE_TO_SHIP_FIELDS,
};
export const CREATEABLE_STAGES = {
[FEATURE_TYPES.FEATURE_TYPE_INCUBATE_ID[0]]: [
STAGE_BLINK_ORIGIN_TRIAL,
STAGE_BLINK_SHIPPING,
STAGE_ENT_ROLLOUT,
],
[FEATURE_TYPES.FEATURE_TYPE_EXISTING_ID[0]]: [
STAGE_FAST_ORIGIN_TRIAL,
STAGE_FAST_SHIPPING,
STAGE_ENT_ROLLOUT,
],
[FEATURE_TYPES.FEATURE_TYPE_CODE_CHANGE_ID[0]]: [
STAGE_PSA_SHIPPING,
STAGE_ENT_ROLLOUT,
],
[FEATURE_TYPES.FEATURE_TYPE_DEPRECATION_ID[0]]: [
STAGE_DEP_DEPRECATION_TRIAL,
STAGE_DEP_SHIPPING,
STAGE_ENT_ROLLOUT,
],
[FEATURE_TYPES.FEATURE_TYPE_ENTERPRISE_ID[0]]: [
STAGE_ENT_ROLLOUT,
STAGE_ENT_SHIPPED,
],
};

Просмотреть файл

@ -317,6 +317,10 @@ class ChromeStatusClient {
return this.doGet(`/features/${featureId}/stages/${stageId}`);
}
createStage(featureId, stageType) {
return this.doPost(`/features/${featureId}/stages`, {stage_type: stageType});
}
// Processes API
getFeatureProcess(featureId) {
return this.doGet(`/features/${featureId}/process`);

Просмотреть файл

@ -117,6 +117,8 @@ api_routes: list[Route] = [
processes_api.ProcessesAPI),
Route(f'{API_BASE}/features/<int:feature_id>/progress',
processes_api.ProgressAPI),
Route(f'{API_BASE}/features/<int:feature_id>/stages',
stages_api.StagesAPI),
Route(f'{API_BASE}/features/<int:feature_id>/stages/<int:stage_id>',
stages_api.StagesAPI),