Merge "Allow admin to create repository submit requirements"
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
index 1e5736b..17b9e73 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
@@ -459,6 +459,7 @@
<div class="main table breadcrumbs">
<gr-repo-submit-requirements
.repo=${this.repoViewState.repo}
+ .params=${this.repoViewState}
></gr-repo-submit-requirements>
</div>
`;
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-submit-requirements/gr-repo-submit-requirements.ts b/polygerrit-ui/app/elements/admin/gr-repo-submit-requirements/gr-repo-submit-requirements.ts
index 6de8705..ff65e26 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-submit-requirements/gr-repo-submit-requirements.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-submit-requirements/gr-repo-submit-requirements.ts
@@ -3,98 +3,218 @@
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import {RepoName, SubmitRequirementInfo} from '../../../types/common';
+import {
+ RepoName,
+ SubmitRequirementInfo,
+ SubmitRequirementInput,
+} from '../../../types/common';
import {firePageError} from '../../../utils/event-util';
import {getAppContext} from '../../../services/app-context';
import {ErrorCallback} from '../../../api/rest';
import {sharedStyles} from '../../../styles/shared-styles';
import {tableStyles} from '../../../styles/gr-table-styles';
-import {LitElement, css, html, PropertyValues} from 'lit';
-import {customElement, property, state} from 'lit/decorators.js';
+import {LitElement, css, html, PropertyValues, nothing} from 'lit';
+import {customElement, property, state, query} from 'lit/decorators.js';
import {when} from 'lit/directives/when.js';
+import {grFormStyles} from '../../../styles/gr-form-styles';
+import {assertIsDefined} from '../../../utils/common-util';
+import {modalStyles} from '../../../styles/gr-modal-styles';
+import {userModelToken} from '../../../models/user/user-model';
+import {resolve} from '../../../models/dependency';
+import {subscribe} from '../../lit/subscription-controller';
+import '../../shared/gr-list-view/gr-list-view';
+import {
+ createRepoUrl,
+ RepoDetailView,
+ RepoViewState,
+} from '../../../models/views/repo';
+import '@polymer/iron-input/iron-input';
@customElement('gr-repo-submit-requirements')
export class GrRepoSubmitRequirements extends LitElement {
@property({type: String})
repo?: RepoName;
+ @property({type: Object})
+ params?: RepoViewState;
+
+ @query('#createDialog')
+ private readonly createDialog?: HTMLDialogElement;
+
@state()
loading = true;
@state()
submitRequirements?: SubmitRequirementInfo[];
+ @state()
+ showCreateDialog = false;
+
+ @state() isAdmin = false;
+
+ @state()
+ newRequirement: SubmitRequirementInput = this.getEmptyRequirement();
+
+ @state() offset = 0;
+
+ @state() filter = '';
+
+ @state() itemsPerPage = 25;
+
private readonly restApiService = getAppContext().restApiService;
+ private readonly getUserModel = resolve(this, userModelToken);
+
static override get styles() {
return [
sharedStyles,
tableStyles,
+ grFormStyles,
+ modalStyles,
css`
:host {
display: block;
margin-bottom: var(--spacing-xxl);
}
+ .actions {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: var(--spacing-m);
+ padding: var(--spacing-l);
+ }
+ .createButton {
+ margin-left: var(--spacing-m);
+ }
+ div.title-flex,
+ div.value-flex {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ }
+ input {
+ width: 20em;
+ box-sizing: border-box;
+ }
+ div.gr-form-styles section {
+ margin: var(--spacing-m) 0;
+ }
+ div.gr-form-styles span.title {
+ width: 13em;
+ }
+ section .title gr-icon {
+ vertical-align: top;
+ }
+ textarea {
+ width: 20em;
+ min-height: 100px;
+ resize: vertical;
+ box-sizing: border-box;
+ }
+ gr-dialog {
+ width: 36em;
+ }
`,
];
}
+ constructor() {
+ super();
+ subscribe(
+ this,
+ () => this.getUserModel().isAdmin$,
+ x => (this.isAdmin = x)
+ );
+ }
+
override render() {
- return html` <table id="list" class="genericList">
- <tbody>
- <tr class="headerRow">
- <th class="topHeader">Name</th>
- <th class="topHeader">Description</th>
- <th class="topHeader">Applicability Expression</th>
- <th class="topHeader">Submittability Expression</th>
- <th class="topHeader">Override Expression</th>
- <th
- class="topHeader"
- title="Whether override is allowed in child projects"
- >
- Allow Override
- </th>
- </tr>
- </tbody>
- <tbody id="submit-requirements">
- ${when(
- this.loading,
- () => html`<tr id="loadingContainer">
- <td>Loading...</td>
- </tr>`,
- () =>
- html` ${(this.submitRequirements ?? []).map(
- item => html`
- <tr class="table">
- <td class="name">${item.name}</td>
- <td class="desc">${item.description}</td>
- <td class="applicability">
- ${item.applicability_expression}
- </td>
- <td class="submittability">
- ${item.submittability_expression}
- </td>
- <td class="override">${item.override_expression}</td>
- <td class="allowOverride">
- ${this.renderCheckmark(
- item.allow_override_in_child_projects
- )}
- </td>
- </tr>
- `
- )}`
- )}
- </tbody>
- </table>`;
+ return html`
+ <gr-list-view
+ .createNew=${this.isAdmin}
+ .filter=${this.filter}
+ .itemsPerPage=${this.itemsPerPage}
+ .items=${this.submitRequirements}
+ .loading=${this.loading}
+ .offset=${this.offset}
+ .path=${createRepoUrl({
+ repo: this.repo,
+ detail: RepoDetailView.SUBMIT_REQUIREMENTS,
+ })}
+ @create-clicked=${() => this.handleCreateClick()}
+ >
+ <table id="list" class="genericList">
+ <tbody>
+ <tr class="headerRow">
+ <th class="topHeader">Name</th>
+ <th class="topHeader">Description</th>
+ <th class="topHeader">Applicability Expression</th>
+ <th class="topHeader">Submittability Expression</th>
+ <th class="topHeader">Override Expression</th>
+ <th
+ class="topHeader"
+ title="Whether override is allowed in child projects"
+ >
+ Allow Override
+ </th>
+ </tr>
+ </tbody>
+ <tbody id="submit-requirements">
+ ${when(
+ this.loading,
+ () => html`<tr id="loadingContainer">
+ <td>Loading...</td>
+ </tr>`,
+ () =>
+ html` ${(this.submitRequirements ?? []).map(
+ item => html`
+ <tr class="table">
+ <td class="name">${item.name}</td>
+ <td class="desc">${item.description}</td>
+ <td class="applicability">
+ ${item.applicability_expression}
+ </td>
+ <td class="submittability">
+ ${item.submittability_expression}
+ </td>
+ <td class="override">${item.override_expression}</td>
+ <td class="allowOverride">
+ ${this.renderCheckmark(
+ item.allow_override_in_child_projects
+ )}
+ </td>
+ </tr>
+ `
+ )}`
+ )}
+ </tbody>
+ </table>
+ </gr-list-view>
+
+ ${this.renderCreateDialog()}
+ `;
}
override updated(changedProperties: PropertyValues) {
if (changedProperties.has('repo')) {
- this.repoChanged();
+ this.getSubmitRequirements();
}
}
- private repoChanged() {
+ override willUpdate(changedProperties: PropertyValues) {
+ if (changedProperties.has('params')) {
+ this._paramsChanged();
+ }
+ }
+
+ async _paramsChanged() {
+ const params = this.params;
+ this.loading = true;
+ this.filter = params?.filter ?? '';
+ this.offset = Number(params?.offset ?? 0);
+
+ await this.getSubmitRequirements(this.filter, this.offset);
+ }
+
+ private getSubmitRequirements(filter?: string, offset?: number) {
const repo = this.repo;
this.loading = true;
if (!repo) {
@@ -112,7 +232,13 @@
return;
}
- this.submitRequirements = res;
+ this.submitRequirements = res
+ .filter(item =>
+ filter === undefined
+ ? true
+ : item.name.toLowerCase().includes(filter.toLowerCase())
+ )
+ .slice(offset ?? 0, (offset ?? 0) + this.itemsPerPage);
this.loading = false;
});
}
@@ -120,6 +246,208 @@
private renderCheckmark(check?: boolean) {
return check ? '✓' : '';
}
+
+ private handleCreateClick() {
+ assertIsDefined(this.createDialog, 'createDialog');
+ this.createDialog.showModal();
+ }
+
+ private handleCreateCancel() {
+ assertIsDefined(this.createDialog, 'createDialog');
+ this.createDialog.close();
+ this.newRequirement = this.getEmptyRequirement();
+ }
+
+ private handleCreateConfirm() {
+ if (!this.repo) return;
+ if (
+ !this.newRequirement.name ||
+ !this.newRequirement.submittability_expression
+ ) {
+ return;
+ }
+
+ const errFn: ErrorCallback = response => {
+ firePageError(response);
+ };
+
+ this.restApiService
+ .createSubmitRequirement(this.repo, this.newRequirement, errFn)
+ .then(() => {
+ this.createDialog?.close();
+ this.newRequirement = this.getEmptyRequirement();
+ this.getSubmitRequirements(this.filter, this.offset);
+ });
+ }
+
+ private getEmptyRequirement(): SubmitRequirementInput {
+ return {
+ name: '',
+ description: '',
+ applicability_expression: '',
+ submittability_expression: '',
+ override_expression: '',
+ allow_override_in_child_projects: false,
+ };
+ }
+
+ private renderCreateDialog() {
+ if (!this.isAdmin) return nothing;
+
+ return html`
+ <dialog id="createDialog" tabindex="-1">
+ <gr-dialog
+ confirm-label="Create"
+ cancel-label="Cancel"
+ ?disabled=${!this.newRequirement.name ||
+ !this.newRequirement.submittability_expression}
+ @confirm=${this.handleCreateConfirm}
+ @cancel=${this.handleCreateCancel}
+ >
+ <div class="header" slot="header">Create Submit Requirement</div>
+ <div class="main" slot="main">
+ <div class="gr-form-styles">
+ <div id="form">
+ <section>
+ <div class="title-flex">
+ <span class="title">Name</span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <iron-input
+ .bindValue=${this.newRequirement.name}
+ @bind-value-changed=${(e: Event) => {
+ this.newRequirement = {
+ ...this.newRequirement,
+ name: (e as CustomEvent).detail.value,
+ };
+ }}
+ >
+ <input id="name" type="text" required />
+ </iron-input>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">Description</span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <textarea
+ id="description"
+ .value=${this.newRequirement.description}
+ placeholder="Optional"
+ ></textarea>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">Applicability Expression</span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <iron-input
+ .bindValue=${this.newRequirement
+ .applicability_expression}
+ @bind-value-changed=${(e: Event) => {
+ this.newRequirement = {
+ ...this.newRequirement,
+ applicability_expression: (e as CustomEvent).detail
+ .value,
+ };
+ }}
+ >
+ <input
+ id="applicability"
+ type="text"
+ placeholder="Optional"
+ />
+ </iron-input>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">Submittability Expression</span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <iron-input
+ .bindValue=${this.newRequirement
+ .submittability_expression}
+ @bind-value-changed=${(e: Event) => {
+ this.newRequirement = {
+ ...this.newRequirement,
+ submittability_expression: (e as CustomEvent).detail
+ .value,
+ };
+ }}
+ >
+ <input id="submittability" type="text" required />
+ </iron-input>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">Override Expression</span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <iron-input
+ .bindValue=${this.newRequirement.override_expression}
+ @bind-value-changed=${(e: Event) => {
+ this.newRequirement = {
+ ...this.newRequirement,
+ override_expression: (e as CustomEvent).detail
+ .value,
+ };
+ }}
+ >
+ <input
+ id="override"
+ type="text"
+ placeholder="Optional"
+ />
+ </iron-input>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">Allow Override in Child Projects</span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <gr-select
+ id="allowOverride"
+ .bindValue=${this.newRequirement
+ .allow_override_in_child_projects}
+ @bind-value-changed=${(e: Event) => {
+ this.newRequirement = {
+ ...this.newRequirement,
+ allow_override_in_child_projects:
+ (e as CustomEvent).detail.value === 'true',
+ };
+ }}
+ >
+ <select>
+ <option value="true">True</option>
+ <option value="false">False</option>
+ </select>
+ </gr-select>
+ </span>
+ </div>
+ </section>
+ </div>
+ </div>
+ </div>
+ </gr-dialog>
+ </dialog>
+ `;
+ }
}
declare global {
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-submit-requirements/gr-repo-submit-requirements_test.ts b/polygerrit-ui/app/elements/admin/gr-repo-submit-requirements/gr-repo-submit-requirements_test.ts
index f438a68..dd0df37 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-submit-requirements/gr-repo-submit-requirements_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo-submit-requirements/gr-repo-submit-requirements_test.ts
@@ -38,36 +38,7 @@
element.repo = 'test2' as RepoName;
assert.shadowDom.equal(
element,
- /* HTML */ `<table class="genericList" id="list">
- <tbody>
- <tr class="headerRow">
- <th class="topHeader">Name</th>
- <th class="topHeader">Description</th>
- <th class="topHeader">Applicability Expression</th>
- <th class="topHeader">Submittability Expression</th>
- <th class="topHeader">Override Expression</th>
- <th
- class="topHeader"
- title="Whether override is allowed in child projects"
- >
- Allow Override
- </th>
- </tr>
- </tbody>
- <tbody id="submit-requirements">
- <tr id="loadingContainer">
- <td>Loading...</td>
- </tr>
- </tbody>
- </table>`
- );
- });
-
- test('render', async () => {
- await waitEventLoop();
- assert.shadowDom.equal(
- element,
- /* HTML */ `
+ /* HTML */ `<gr-list-view>
<table class="genericList" id="list">
<tbody>
<tr class="headerRow">
@@ -85,20 +56,215 @@
</tr>
</tbody>
<tbody id="submit-requirements">
- <tr class="table">
- <td class="name">Verified</td>
- <td class="desc">
- CI result status for build and tests is passing
- </td>
- <td class="applicability"></td>
- <td class="submittability">
- label:Verified=MAX AND -label:Verified=MIN
- </td>
- <td class="override"></td>
- <td class="allowOverride"></td>
+ <tr id="loadingContainer">
+ <td>Loading...</td>
</tr>
</tbody>
</table>
+ </gr-list-view>`
+ );
+ });
+
+ test('render', async () => {
+ await waitEventLoop();
+ assert.shadowDom.equal(
+ element,
+ /* HTML */ `
+ <gr-list-view>
+ <table class="genericList" id="list">
+ <tbody>
+ <tr class="headerRow">
+ <th class="topHeader">Name</th>
+ <th class="topHeader">Description</th>
+ <th class="topHeader">Applicability Expression</th>
+ <th class="topHeader">Submittability Expression</th>
+ <th class="topHeader">Override Expression</th>
+ <th
+ class="topHeader"
+ title="Whether override is allowed in child projects"
+ >
+ Allow Override
+ </th>
+ </tr>
+ </tbody>
+ <tbody id="submit-requirements">
+ <tr class="table">
+ <td class="name">Verified</td>
+ <td class="desc">
+ CI result status for build and tests is passing
+ </td>
+ <td class="applicability"></td>
+ <td class="submittability">
+ label:Verified=MAX AND -label:Verified=MIN
+ </td>
+ <td class="override"></td>
+ <td class="allowOverride"></td>
+ </tr>
+ </tbody>
+ </table>
+ </gr-list-view>
+ `
+ );
+ });
+
+ test('render as admin', async () => {
+ await waitEventLoop();
+ element.isAdmin = true;
+ await element.updateComplete;
+ assert.shadowDom.equal(
+ element,
+ /* HTML */ `
+ <gr-list-view>
+ <table class="genericList" id="list">
+ <tbody>
+ <tr class="headerRow">
+ <th class="topHeader">Name</th>
+ <th class="topHeader">Description</th>
+ <th class="topHeader">Applicability Expression</th>
+ <th class="topHeader">Submittability Expression</th>
+ <th class="topHeader">Override Expression</th>
+ <th
+ class="topHeader"
+ title="Whether override is allowed in child projects"
+ >
+ Allow Override
+ </th>
+ </tr>
+ </tbody>
+ <tbody id="submit-requirements">
+ <tr class="table">
+ <td class="name">Verified</td>
+ <td class="desc">
+ CI result status for build and tests is passing
+ </td>
+ <td class="applicability"></td>
+ <td class="submittability">
+ label:Verified=MAX AND -label:Verified=MIN
+ </td>
+ <td class="override"></td>
+ <td class="allowOverride"></td>
+ </tr>
+ </tbody>
+ </table>
+ </gr-list-view>
+ <dialog id="createDialog" tabindex="-1">
+ <gr-dialog cancel-label="Cancel" confirm-label="Create" disabled="">
+ <div class="header" slot="header">Create Submit Requirement</div>
+ <div class="main" slot="main">
+ <div class="gr-form-styles">
+ <div id="form">
+ <section>
+ <div class="title-flex">
+ <span class="title">
+ Name
+ </span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <iron-input>
+ <input
+ id="name"
+ required=""
+ type="text"
+ >
+ </iron-input>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">
+ Description
+ </span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <textarea
+ id="description"
+ placeholder="Optional"
+ >
+ </textarea>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">
+ Applicability Expression
+ </span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <iron-input>
+ <input
+ id="applicability"
+ placeholder="Optional"
+ type="text"
+ >
+ </iron-input>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">
+ Submittability Expression
+ </span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <iron-input>
+ <input
+ id="submittability"
+ required=""
+ type="text"
+ >
+ </iron-input>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">
+ Override Expression
+ </span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <iron-input>
+ <input
+ id="override"
+ placeholder="Optional"
+ type="text"
+ >
+ </iron-input>
+ </span>
+ </div>
+ </section>
+ <section>
+ <div class="title-flex">
+ <span class="title">
+ Allow Override in Child Projects
+ </span>
+ </div>
+ <div class="value-flex">
+ <span class="value">
+ <gr-select id="allowOverride">
+ <select>
+ <option value="true">
+ True
+ </option>
+ <option value="false">
+ False
+ </option>
+ </select>
+ </gr-select>
+ </span>
+ </div>
+ </section>
+ </div>
+ </gr-dialog>
+ </dialog>
`
);
});
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
index 9f87d99..87a3e6a 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -167,7 +167,8 @@
// Matches /admin/repos/<repos>,access.
REPO_DASHBOARDS: /^\/admin\/repos\/(.+),dashboards$/,
- REPO_SUBMIT_REQUIREMENTS: /^\/admin\/repos\/(.+),submit-requirements$/,
+ REPO_SUBMIT_REQUIREMENTS:
+ /^\/admin\/repos\/(.+),submit-requirements\/?(?:\/q\/filter:(.*?))?(?:,(\d+))?$/,
// Matches /admin/plugins with optional filter and offset.
PLUGIN_LIST: /^\/admin\/plugins\/?(?:\/q\/filter:(.*?))?(?:,(\d+))?$/,
@@ -1229,6 +1230,8 @@
view: GerritView.REPO,
detail: RepoDetailView.SUBMIT_REQUIREMENTS,
repo,
+ filter: ctx.params[1] ?? null,
+ offset: ctx.params[2] ?? '0',
};
// Note that router model view must be updated before view models.
this.setState(state);
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.ts
index d33fa1d..ec2e48d 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.ts
@@ -734,6 +734,8 @@
...createRepoViewState(),
detail: RepoDetailView.SUBMIT_REQUIREMENTS,
repo: '4321' as RepoName,
+ filter: '',
+ offset: '',
});
});
diff --git a/polygerrit-ui/app/services/gr-rest-api/gr-rest-api-impl.ts b/polygerrit-ui/app/services/gr-rest-api/gr-rest-api-impl.ts
index 4601bd2..bc4bec8 100644
--- a/polygerrit-ui/app/services/gr-rest-api/gr-rest-api-impl.ts
+++ b/polygerrit-ui/app/services/gr-rest-api/gr-rest-api-impl.ts
@@ -107,6 +107,7 @@
ListChangesOption,
ReviewResult,
SubmitRequirementInfo,
+ SubmitRequirementInput,
} from '../../types/common';
import {
DiffInfo,
@@ -1785,6 +1786,24 @@
}) as Promise<SubmitRequirementInfo[] | undefined>;
}
+ createSubmitRequirement(
+ repoName: RepoName,
+ input: SubmitRequirementInput,
+ errFn?: ErrorCallback
+ ): Promise<SubmitRequirementInfo | undefined> {
+ return this._restApiHelper.fetchJSON({
+ url: `/projects/${encodeURIComponent(
+ repoName
+ )}/submit_requirements/${encodeURIComponent(input.name)}`,
+ fetchOptions: getFetchOptions({
+ method: HttpMethod.PUT,
+ body: input,
+ }),
+ errFn,
+ anonymizedUrl: '/projects/*/submit_requirements/*',
+ }) as Promise<SubmitRequirementInfo | undefined>;
+ }
+
getRepoAccessRights(
repoName: RepoName,
errFn?: ErrorCallback
diff --git a/polygerrit-ui/app/services/gr-rest-api/gr-rest-api.ts b/polygerrit-ui/app/services/gr-rest-api/gr-rest-api.ts
index ea6451a..11f8b8c 100644
--- a/polygerrit-ui/app/services/gr-rest-api/gr-rest-api.ts
+++ b/polygerrit-ui/app/services/gr-rest-api/gr-rest-api.ts
@@ -92,6 +92,7 @@
DraftInfo,
ReviewResult,
SubmitRequirementInfo,
+ SubmitRequirementInput,
} from '../../types/common';
import {
DiffInfo,
@@ -291,6 +292,12 @@
errFn?: ErrorCallback
): Promise<SubmitRequirementInfo[] | undefined>;
+ createSubmitRequirement(
+ repoName: RepoName,
+ input: SubmitRequirementInput,
+ errFn?: ErrorCallback
+ ): Promise<SubmitRequirementInfo | undefined>;
+
getRepoAccessRights(
repoName: RepoName,
errFn?: ErrorCallback
diff --git a/polygerrit-ui/app/test/mocks/gr-rest-api_mock.ts b/polygerrit-ui/app/test/mocks/gr-rest-api_mock.ts
index 95f160d..e4abf5e 100644
--- a/polygerrit-ui/app/test/mocks/gr-rest-api_mock.ts
+++ b/polygerrit-ui/app/test/mocks/gr-rest-api_mock.ts
@@ -397,6 +397,9 @@
getRepoSubmitRequirements(): Promise<SubmitRequirementInfo[] | undefined> {
return Promise.resolve([]);
},
+ createSubmitRequirement(): Promise<SubmitRequirementInfo | undefined> {
+ return Promise.resolve(undefined);
+ },
getRepoAccessRights(): Promise<ProjectAccessInfo | undefined> {
return Promise.resolve(undefined);
},
diff --git a/polygerrit-ui/app/types/common.ts b/polygerrit-ui/app/types/common.ts
index 47669f4..02a8cc6 100644
--- a/polygerrit-ui/app/types/common.ts
+++ b/polygerrit-ui/app/types/common.ts
@@ -740,6 +740,19 @@
}
/**
+ * The SubmitRequirementInput entity describes a submit requirement input.
+ * https://gerrit-review.googlesource.com/Documentation/rest-api-projects.html#submit-requirement-input
+ */
+export interface SubmitRequirementInput {
+ name: string;
+ description?: string;
+ applicability_expression?: string;
+ submittability_expression: string;
+ override_expression?: string;
+ allow_override_in_child_projects?: boolean;
+}
+
+/**
* The ProjectAccessInfo entity contains information about the access rights for
* a project.
* https://gerrit-review.googlesource.com/Documentation/rest-api-access.html#project-access-info