Provide in-dashboard help for creating changes
When an authenticated user's "Outgoing Changes" section is empty,
provide a message and dialogs with step-by-step instructions and command
samples for how to create a new change.
Change-Id: Id8f05a3b6bec399dd8ad3f226185f03d8663cc80
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
index 4ebe027..372e6be 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.html
@@ -67,13 +67,18 @@
</td>
</tr>
</template>
- <template is="dom-if" if="[[!changeSection.results.length]]">
+ <template is="dom-if" if="[[_isEmpty(changeSection)]]">
<tr class="noChanges">
<td class="leftPadding"></td>
<td class="star" hidden$="[[!showStar]]" hidden></td>
<td class="cell"
colspan$="[[_computeColspan(changeTableColumns, labelNames)]]">
- No changes
+ <template is="dom-if" if="[[_isOutgoing(changeSection)]]">
+ <slot name="empty-outgoing"></slot>
+ </template>
+ <template is="dom-if" if="[[!_isOutgoing(changeSection)]]">
+ No changes
+ </template>
</td>
</tr>
</template>
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
index eb916c1..ba768d9 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
@@ -347,5 +347,13 @@
this.$.cursor.stops = this._getListItems();
this.$.cursor.moveToStart();
},
+
+ _isOutgoing(section) {
+ return !!section.isOutgoing;
+ },
+
+ _isEmpty(section) {
+ return !section.results.length;
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
index 3cf5f9a..bb904b5 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list_test.html
@@ -270,6 +270,32 @@
assert.equal(noChangesMsg.length, 2);
});
+ suite('empty outgoing', () => {
+ test('not shown on empty non-outgoing sections', () => {
+ const section = {results: []};
+ assert.isTrue(element._isEmpty(section));
+ assert.isFalse(element._isOutgoing(section));
+ });
+
+ test('shown on empty outgoing sections', () => {
+ const section = {results: [], isOutgoing: true};
+ assert.isTrue(element._isEmpty(section));
+ assert.isTrue(element._isOutgoing(section));
+ });
+
+ test('not shown on non-empty outgoing sections', () => {
+ const section = {isOutgoing: true, results: [
+ {_number: 0, labels: {Verified: {approved: {}}}}]};
+ assert.isFalse(element._isEmpty(section));
+ assert.isTrue(element._isOutgoing(section));
+ });
+ });
+
+ test('_isOutgoing', () => {
+ assert.isTrue(element._isOutgoing({results: [], isOutgoing: true}));
+ assert.isFalse(element._isOutgoing({results: []}));
+ });
+
suite('empty column preference', () => {
let element;
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.html b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.html
new file mode 100644
index 0000000..bf17b911
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.html
@@ -0,0 +1,87 @@
+<!--
+@license
+Copyright (C) 2018 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<link rel="import" href="../../../bower_components/polymer/polymer.html">
+<link rel="import" href="../../shared/gr-dialog/gr-dialog.html">
+<link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
+<link rel="import" href="../../shared/gr-shell-command/gr-shell-command.html">
+
+<dom-module id="gr-create-commands-dialog">
+ <template>
+ <style include="shared-styles">
+ ol {
+ list-style: decimal;
+ margin-left: 1em;
+ }
+ p {
+ margin-bottom: .75em;
+ }
+ #commandsDialog {
+ max-width: 40em;
+ }
+ </style>
+ <gr-overlay id="commandsOverlay" with-backdrop>
+ <gr-dialog
+ id="commandsDialog"
+ confirm-label="Done"
+ cancel-label=""
+ confirm-on-enter
+ on-confirm="_handleClose">
+ <div class="header" slot="header">
+ Create change commands
+ </div>
+ <div class="main" slot="main">
+ <ol>
+ <li>
+ <p>
+ Make the changes to the files on your machine
+ </p>
+ </li>
+ <li>
+ <p>
+ If you are making a new commit use
+ </p>
+ <gr-shell-command command="[[_createNewCommitCommand]]"></gr-shell-command>
+ <p>
+ Or to amend an existing commit use
+ </p>
+ <gr-shell-command command="[[_amendExistingCommitCommand]]"></gr-shell-command>
+ <p>
+ Please make sure you add a commit message as it becomes the
+ description for your change.
+ </p>
+ </li>
+ <li>
+ <p>
+ Push the change for code review
+ </p>
+ <gr-shell-command command="[[_pushCommand]]"></gr-shell-command>
+ </li>
+ <li>
+ <p>
+ Close this dialog and you should be able to see your recently
+ created change in ``Outgoing changes'' section on
+ ``Your changes'' page.
+ </p>
+ </li>
+ </ol>
+ </div>
+ </gr-dialog>
+ </gr-overlay>
+ </template>
+ <script src="gr-create-commands-dialog.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js
new file mode 100644
index 0000000..0e71f1c
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js
@@ -0,0 +1,58 @@
+/**
+ * @license
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function() {
+ 'use strict';
+
+ const Commands = {
+ CREATE: 'git commit',
+ AMEND: 'git commit --amend',
+ PUSH_PREFIX: 'git push origin HEAD:refs/for/',
+ };
+
+ Polymer({
+ is: 'gr-create-commands-dialog',
+ properties: {
+ branch: String,
+ _createNewCommitCommand: {
+ type: String,
+ readonly: true,
+ value: Commands.CREATE,
+ },
+ _amendExistingCommitCommand: {
+ type: String,
+ readonly: true,
+ value: Commands.AMEND,
+ },
+ _pushCommand: {
+ type: String,
+ computed: '_computePushCommand(branch)',
+ },
+ },
+
+ open() {
+ this.$.commandsOverlay.open();
+ },
+
+ _handleClose() {
+ this.$.commandsOverlay.close();
+ },
+
+ _computePushCommand(branch) {
+ return Commands.PUSH_PREFIX + branch;
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html
new file mode 100644
index 0000000..e00037d
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!--
+@license
+Copyright (C) 2018 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
+<title>gr-create-commands-dialog</title>
+
+<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
+<script src="../../../bower_components/web-component-tester/browser.js"></script>
+<link rel="import" href="../../../test/common-test-setup.html"/>
+<link rel="import" href="gr-create-commands-dialog.html">
+
+<script>void(0);</script>
+
+<test-fixture id="basic">
+ <template>
+ <gr-create-commands-dialog></gr-create-commands-dialog>
+ </template>
+</test-fixture>
+
+<script>
+ suite('gr-create-commands-dialog tests', () => {
+ let element;
+
+ setup(() => {
+ element = fixture('basic');
+ });
+
+ test('_computePushCommand', () => {
+ element.branch = 'master';
+ assert.equal(element._pushCommand,
+ 'git push origin HEAD:refs/for/master');
+
+ element.branch = 'stable-2.15';
+ assert.equal(element._pushCommand,
+ 'git push origin HEAD:refs/for/stable-2.15');
+ });
+ });
+</script>
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.html b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.html
new file mode 100644
index 0000000..d12d84b
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.html
@@ -0,0 +1,48 @@
+<!--
+@license
+Copyright (C) 2018 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<link rel="import" href="../../../bower_components/polymer/polymer.html">
+<link rel="import" href="../../shared/gr-dialog/gr-dialog.html">
+<link rel="import" href="../../shared/gr-overlay/gr-overlay.html">
+<link rel="import" href="../../shared/gr-repo-branch-picker/gr-repo-branch-picker.html">
+
+<dom-module id="gr-create-destination-dialog">
+ <template>
+ <style include="shared-styles">
+ </style>
+ <gr-overlay id="createOverlay" with-backdrop>
+ <gr-dialog
+ confirm-label="View commands"
+ on-confirm="_pickerConfirm"
+ on-cancel="_handleClose"
+ disabled="[[!_repoAndBranchSelected]]">
+ <div class="header" slot="header">
+ Create change
+ </div>
+ <div class="main" slot="main">
+ <gr-repo-branch-picker
+ repo="{{_repo}}"
+ branch="{{_branch}}"></gr-repo-branch-picker>
+ <p>
+ If you haven't done so, you will need to clone the repository.
+ </p>
+ </div>
+ </gr-dialog>
+ </gr-overlay>
+ </template>
+ <script src="gr-create-destination-dialog.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js
new file mode 100644
index 0000000..4d2802e
--- /dev/null
+++ b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js
@@ -0,0 +1,58 @@
+/**
+ * @license
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function() {
+ 'use strict';
+
+ /**
+ * Fired when a destination has been picked. Event details contain the repo
+ * name and the branch name.
+ *
+ * @event confirm
+ */
+
+ Polymer({
+ is: 'gr-create-destination-dialog',
+ properties: {
+ _repo: String,
+ _branch: String,
+ _repoAndBranchSelected: {
+ type: Boolean,
+ value: false,
+ computed: '_computeRepoAndBranchSelected(_repo, _branch)',
+ },
+ },
+ open() {
+ this._repo = '';
+ this._branch = '';
+ this.$.createOverlay.open();
+ },
+
+ _handleClose() {
+ this.$.createOverlay.close();
+ },
+
+ _pickerConfirm() {
+ this.$.createOverlay.close();
+ const detail = {repo: this._repo, branch: this._branch};
+ this.dispatchEvent(new CustomEvent('confirm', {detail, bubbles: false}));
+ },
+
+ _computeRepoAndBranchSelected(repo, branch) {
+ return !!(repo && branch);
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.html b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.html
index b18e8cd..1edb8ea 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.html
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.html
@@ -21,6 +21,8 @@
<link rel="import" href="../../change-list/gr-change-list/gr-change-list.html">
<link rel="import" href="../../core/gr-reporting/gr-reporting.html">
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
+<link rel="import" href="../gr-create-commands-dialog/gr-create-commands-dialog.html">
+<link rel="import" href="../gr-create-destination-dialog/gr-create-destination-dialog.html">
<link rel="import" href="../gr-user-header/gr-user-header.html">
<dom-module id="gr-dashboard-view">
@@ -43,10 +45,42 @@
gr-user-header {
border-bottom: 1px solid var(--border-color);
}
+ #emptyOutgoing {
+ display: block;
+ }
+ #emptyOutgoing #graphic,
+ #emptyOutgoing #help {
+ display: inline-block;
+ margin: .5em;
+ }
+ #emptyOutgoing #graphic {
+ fill: var(--deemphasized-text-color);
+ max-width: 12em;
+ }
+ #emptyOutgoing #graphic svg {
+ display: block;
+ margin: 0 auto;
+ max-width: 100px;
+ }
+ #emptyOutgoing #graphic p {
+ text-align: center;
+ }
+ #emptyOutgoing #help {
+ vertical-align: top;
+ }
+ #emptyOutgoing #help h1 {
+ font-size: var(--font-size-large);
+ }
+ #emptyOutgoing #help p {
+ max-width: 35em;
+ }
@media only screen and (max-width: 50em) {
.loading {
padding: 0 var(--default-horizontal-margin);
}
+ #emptyOutgoing #graphic {
+ display: none;
+ }
}
</style>
<div class="loading" hidden$="[[!_loading]]">Loading...</div>
@@ -62,8 +96,32 @@
selected-index="{{viewState.selectedChangeIndex}}"
sections="[[_results]]"
on-toggle-star="_handleToggleStar"
- on-toggle-reviewed="_handleToggleReviewed"></gr-change-list>
+ on-toggle-reviewed="_handleToggleReviewed">
+ <div id="emptyOutgoing" slot="empty-outgoing">
+ <div id="graphic">
+ <svg width="150" height="100">
+ <circle cx="50" cy="50" r="50"></circle>
+ </svg>
+ <p>
+ No outgoing changes yet
+ </p>
+ </div>
+ <div id="help">
+ <h1>Push your first changes for code review</h1>
+ <p>
+ Pushing a change for review is easy, but a little different from
+ other git code review tools. Click on the `Create Change' button
+ and follow the step by step instructions.
+ </p>
+ <gr-button on-tap="_createChangeTap">Create Change</gr-button>
+ </div>
+ </div>
+ </gr-change-list>
</div>
+ <gr-create-destination-dialog
+ id="destinationDialog"
+ on-confirm="_handleDestinationConfirm"></gr-create-destination-dialog>
+ <gr-create-commands-dialog id="commandsDialog"></gr-create-commands-dialog>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
<gr-reporting id="reporting"></gr-reporting>
</template>
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
index d84dec5..6dec1a6 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
@@ -45,6 +45,7 @@
// by the viewing user.
name: 'Outgoing reviews',
query: 'is:open owner:${user} -is:wip -is:ignored',
+ isOutgoing: true,
},
{
// Non-WIP open changes not owned by the viewed user, that the viewed user
@@ -249,6 +250,7 @@
sectionName: res.sections[i].name,
query: res.sections[i].query,
results,
+ isOutgoing: res.sections[i].isOutgoing,
})).filter((section, i) => !res.sections[i].hideIfEmpty ||
section.results.length);
});
@@ -267,5 +269,14 @@
this.$.restAPI.saveChangeReviewed(e.detail.change._number,
e.detail.reviewed);
},
+
+ _createChangeTap() {
+ this.$.destinationDialog.open();
+ },
+
+ _handleDestinationConfirm(e) {
+ this.$.commandsDialog.branch = e.detail.branch;
+ this.$.commandsDialog.open();
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
index cac2627..21e917a 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.html
@@ -257,6 +257,22 @@
});
});
+ test('preserve isOutgoing sections', () => {
+ const sections = [
+ {name: 'test1', query: 'test1', isOutgoing: true},
+ {name: 'test2', query: 'test2'},
+ ];
+ getChangesStub.restore();
+ sandbox.stub(element.$.restAPI, 'getChanges')
+ .returns(Promise.resolve([[], []]));
+
+ return element._fetchDashboardChanges({sections}).then(() => {
+ assert.equal(element._results.length, 2);
+ assert.isTrue(element._results[0].isOutgoing);
+ assert.isNotOk(element._results[1].isOutgoing);
+ });
+ });
+
test('_computeUserHeaderClass', () => {
assert.equal(element._computeUserHeaderClass(undefined), '');
assert.equal(element._computeUserHeaderClass(''), '');
diff --git a/polygerrit-ui/app/styles/gr-change-list-styles.html b/polygerrit-ui/app/styles/gr-change-list-styles.html
index 37e8bdc..51a3fe9 100644
--- a/polygerrit-ui/app/styles/gr-change-list-styles.html
+++ b/polygerrit-ui/app/styles/gr-change-list-styles.html
@@ -207,6 +207,10 @@
.size {
max-width: none;
}
+ .noChanges .cell {
+ display: block;
+ height: auto;
+ }
}
@media only screen and (min-width: 1450px) {
:host {
diff --git a/polygerrit-ui/app/test/index.html b/polygerrit-ui/app/test/index.html
index a489627..6a6fef0 100644
--- a/polygerrit-ui/app/test/index.html
+++ b/polygerrit-ui/app/test/index.html
@@ -56,6 +56,7 @@
'change-list/gr-change-list-item/gr-change-list-item_test.html',
'change-list/gr-change-list-view/gr-change-list-view_test.html',
'change-list/gr-change-list/gr-change-list_test.html',
+ 'change-list/gr-create-commands-dialog/gr-create-commands-dialog_test.html',
'change-list/gr-dashboard-view/gr-dashboard-view_test.html',
'change-list/gr-user-header/gr-user-header_test.html',
'change/gr-account-entry/gr-account-entry_test.html',