Merge "Show Submitted Date in change summary"
diff --git a/WORKSPACE b/WORKSPACE
index fff9235..01decd5 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -211,14 +211,6 @@
     sha1 = "f645ed69d595b24d4cf8b3fbb64cc505bede8829",
 )
 
-load("//lib:guava.bzl", "GUAVA_BIN_SHA1", "GUAVA_VERSION")
-
-maven_jar(
-    name = "guava",
-    artifact = "com.google.guava:guava:" + GUAVA_VERSION,
-    sha1 = GUAVA_BIN_SHA1,
-)
-
 CAFFEINE_VERS = "2.8.5"
 
 maven_jar(
diff --git a/java/com/google/gerrit/extensions/BUILD b/java/com/google/gerrit/extensions/BUILD
index da5dc8b..21949f7 100644
--- a/java/com/google/gerrit/extensions/BUILD
+++ b/java/com/google/gerrit/extensions/BUILD
@@ -1,5 +1,5 @@
 load("@rules_java//java:defs.bzl", "java_binary", "java_library")
-load("//lib:guava.bzl", "GUAVA_DOC_URL")
+load("//tools:nongoogle.bzl", "GUAVA_DOC_URL")
 load("//tools/bzl:javadoc.bzl", "java_doc")
 
 _DOC_VERS = "5.5.0.201909110433-r"
diff --git a/lib/guava.bzl b/lib/guava.bzl
deleted file mode 100644
index 4de39cb..0000000
--- a/lib/guava.bzl
+++ /dev/null
@@ -1,5 +0,0 @@
-GUAVA_VERSION = "29.0-jre"
-
-GUAVA_BIN_SHA1 = "801142b4c3d0f0770dd29abea50906cacfddd447"
-
-GUAVA_DOC_URL = "https://google.github.io/guava/releases/" + GUAVA_VERSION + "/api/docs/"
diff --git a/lib/nongoogle_test.sh b/lib/nongoogle_test.sh
index 8369024..df8ee66 100755
--- a/lib/nongoogle_test.sh
+++ b/lib/nongoogle_test.sh
@@ -21,6 +21,7 @@
 flogger
 flogger-log4j-backend
 flogger-system-backend
+guava
 httpasyncclient
 httpcore-nio
 j2objc
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
index ce3a811..0cf9357 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -219,7 +219,9 @@
             )
           );
 
-    const checkForNewUser = !project && user === 'self';
+    // Checking `this.account` to make sure that the user is logged in.
+    // Otherwise sending a query for 'owner:self' will result in an error.
+    const checkForNewUser = !project && !!this.account && user === 'self';
     return dashboardPromise
       .then(res => {
         if (res && res.title) {
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
index 44f203d..f788e74 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
@@ -21,6 +21,7 @@
 import {GerritNav, GerritView} from '../../core/gr-navigation/gr-navigation.js';
 import {changeIsOpen} from '../../../utils/change-util.js';
 import {ChangeStatus} from '../../../constants/constants.js';
+import {createAccountWithId} from '../../../test/test-data-generators.js';
 
 const basicFixture = fixtureFromElement('gr-dashboard-view');
 
@@ -201,9 +202,23 @@
         user: 'self',
       };
       return paramsChangedPromise.then(() => {
-        assert.isTrue(
-            getChangesStub.calledWith(undefined,
-                ['1', '2', 'owner:self limit:1']));
+        assert.isTrue(getChangesStub.calledWith(undefined, ['1', '2']));
+      });
+    });
+
+    test('viewing dashboard when logged in includes owner:self query', () => {
+      element.account = createAccountWithId(1);
+      element.params = {
+        view: GerritNav.View.DASHBOARD,
+        sections: [
+          {query: '1'},
+          {query: '2', selfOnly: true},
+        ],
+        user: 'self',
+      };
+      return paramsChangedPromise.then(() => {
+        assert.isTrue(getChangesStub.calledWith(undefined,
+            ['1', '2', 'owner:self limit:1']));
       });
     });
 
diff --git a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
index 20fbc32..9473700 100644
--- a/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-actions/gr-change-actions.ts
@@ -954,7 +954,9 @@
     if (
       !result &&
       this.change.labels[CODE_REVIEW] &&
-      this._getLabelStatus(this.change.labels[CODE_REVIEW]) === LabelStatus.OK
+      this._getLabelStatus(this.change.labels[CODE_REVIEW]) ===
+        LabelStatus.OK &&
+      this.change.permitted_labels[CODE_REVIEW]
     ) {
       result = CODE_REVIEW;
     }
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
index 6b04153..d192060 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata.ts
@@ -178,7 +178,7 @@
     type: Object,
     computed: '_computePushCertificateValidation(serverConfig, change)',
   })
-  _pushCertificateValidation: PushCertifacteValidationInfo | null = null;
+  _pushCertificateValidation?: PushCertifacteValidationInfo;
 
   @property({type: Boolean, computed: '_computeShowRequirements(change)'})
   _showRequirements = false;
@@ -222,7 +222,7 @@
 
   @observe('change.labels')
   _labelsChanged(labels?: LabelNameToInfoMap) {
-    this.labels = {...labels} || null;
+    this.labels = {...labels};
   }
 
   @observe('change')
@@ -264,7 +264,7 @@
   }
 
   /**
-   * @return If array is empty, returns null instead so
+   * @return If array is empty, returns undefined instead so
    * an existential check can be used to hide or show the webLinks
    * section.
    */
@@ -272,9 +272,7 @@
     commitInfo?: CommitInfoWithRequiredCommit,
     serverConfig?: ServerInfo
   ) {
-    if (!commitInfo) {
-      return null;
-    }
+    if (!commitInfo) return undefined;
     const weblinks = GerritNav.getChangeWeblinks(
       this.change ? this.change.project : ('' as RepoName),
       commitInfo.commit,
@@ -283,15 +281,11 @@
         config: serverConfig,
       }
     );
-    return weblinks.length ? weblinks : null;
+    return weblinks.length ? weblinks : undefined;
   }
 
   _isAssigneeEnabled(serverConfig?: ServerInfo) {
-    return (
-      serverConfig &&
-      serverConfig.change &&
-      !!serverConfig.change.enable_assignee
-    );
+    return !!serverConfig?.change?.enable_assignee;
   }
 
   _computeStrategy(change?: ParsedChangeInfo) {
@@ -311,18 +305,13 @@
       throw new Error('change must be set');
     }
     const lastTopic = this.change.topic;
-    const topic = e.detail.length ? e.detail : null;
+    const topic = e.detail.length ? e.detail : undefined;
     this._settingTopic = true;
     const topicChangedForChangeNumber = this.change._number;
     this.$.restAPI
       .setChangeTopic(topicChangedForChangeNumber, topic)
       .then(newTopic => {
-        if (
-          !this.change ||
-          this.change._number !== topicChangedForChangeNumber
-        ) {
-          return;
-        }
+        if (this.change?._number !== topicChangedForChangeNumber) return;
         this._settingTopic = false;
         this.set(['change', 'topic'], newTopic);
         if (newTopic !== lastTopic) {
@@ -337,8 +326,7 @@
     changeRecord: ElementPropertyDeepChange<GrChangeMetadata, 'change'>,
     settingTopic?: boolean
   ) {
-    const hasTopic =
-      !!changeRecord && !!changeRecord.base && !!changeRecord.base.topic;
+    const hasTopic = !!changeRecord?.base?.topic;
     return !hasTopic && !settingTopic;
   }
 
@@ -346,8 +334,7 @@
     changeRecord: ElementPropertyDeepChange<GrChangeMetadata, 'change'>,
     settingTopic?: boolean
   ) {
-    const hasTopic =
-      !!changeRecord && !!changeRecord.base && !!changeRecord.base.topic;
+    const hasTopic = !!changeRecord?.base?.topic;
     return hasTopic && !settingTopic;
   }
 
@@ -355,10 +342,8 @@
     changeRecord: ElementPropertyDeepChange<GrChangeMetadata, 'change'>
   ) {
     const hasCherryPickOf =
-      !!changeRecord &&
-      !!changeRecord.base &&
-      !!changeRecord.base.cherry_pick_of_change &&
-      !!changeRecord.base.cherry_pick_of_patch_set;
+      !!changeRecord?.base?.cherry_pick_of_change &&
+      !!changeRecord?.base?.cherry_pick_of_patch_set;
     return hasCherryPickOf;
   }
 
@@ -385,33 +370,15 @@
   }
 
   _computeTopicReadOnly(mutable?: boolean, change?: ParsedChangeInfo) {
-    return (
-      !mutable ||
-      !change ||
-      !change.actions ||
-      !change.actions.topic ||
-      !change.actions.topic.enabled
-    );
+    return !mutable || !change?.actions?.topic?.enabled;
   }
 
   _computeHashtagReadOnly(mutable?: boolean, change?: ParsedChangeInfo) {
-    return (
-      !mutable ||
-      !change ||
-      !change.actions ||
-      !change.actions.hashtags ||
-      !change.actions.hashtags.enabled
-    );
+    return !mutable || !change?.actions?.hashtags?.enabled;
   }
 
   _computeAssigneeReadOnly(mutable?: boolean, change?: ParsedChangeInfo) {
-    return (
-      !mutable ||
-      !change ||
-      !change.actions ||
-      !change.actions.assignee ||
-      !change.actions.assignee.enabled
-    );
+    return !mutable || !change?.actions?.assignee?.enabled;
   }
 
   _computeTopicPlaceholder(_topicReadOnly?: boolean) {
@@ -445,17 +412,11 @@
   _computePushCertificateValidation(
     serverConfig?: ServerInfo,
     change?: ParsedChangeInfo
-  ): PushCertifacteValidationInfo | null {
-    if (
-      !change ||
-      !serverConfig ||
-      !serverConfig.receive ||
-      !serverConfig.receive.enable_signed_push
-    ) {
-      return null;
-    }
+  ): PushCertifacteValidationInfo | undefined {
+    if (!change || !serverConfig?.receive?.enable_signed_push) return undefined;
+
     const rev = change.revisions[change.current_revision];
-    if (!rev.push_certificate || !rev.push_certificate.key) {
+    if (!rev.push_certificate?.key) {
       return {
         class: 'help',
         icon: 'gr-icons:help',
@@ -498,7 +459,7 @@
   }
 
   _problems(msg: string, key: GpgKeyInfo) {
-    if (!key || !key.problems || key.problems.length === 0) {
+    if (!key?.problems || key.problems.length === 0) {
       return msg;
     }
 
@@ -551,7 +512,7 @@
     const target = (dom(e) as EventApi).rootTarget as GrLinkedChip;
     target.disabled = true;
     this.$.restAPI
-      .setChangeTopic(this.change._number, null)
+      .setChangeTopic(this.change._number)
       .then(() => {
         target.disabled = false;
         this.set(['change', 'topic'], '');
@@ -561,7 +522,6 @@
       })
       .catch(() => {
         target.disabled = false;
-        return;
       });
   }
 
@@ -580,12 +540,11 @@
       })
       .catch(() => {
         target.disabled = false;
-        return;
       });
   }
 
   _computeIsWip(change?: ParsedChangeInfo) {
-    return change && !!change.work_in_progress;
+    return !!change?.work_in_progress;
   }
 
   _computeShowRoleClass(change?: ParsedChangeInfo, role?: ChangeRole) {
@@ -622,22 +581,14 @@
   }
 
   /**
-   * Get the user with the specified role on the change. Returns null if the
+   * Get the user with the specified role on the change. Returns undefined if the
    * user with that role is the same as the owner.
    */
   _getNonOwnerRole(change?: ParsedChangeInfo, role?: ChangeRole) {
-    if (
-      !change ||
-      !change.current_revision ||
-      !change.revisions[change.current_revision]
-    ) {
-      return null;
-    }
+    if (!change?.revisions?.[change.current_revision]) return undefined;
 
     const rev = change.revisions[change.current_revision];
-    if (!rev) {
-      return null;
-    }
+    if (!rev) return undefined;
 
     if (
       role === ChangeRole.UPLOADER &&
@@ -666,7 +617,7 @@
       return rev.commit.committer;
     }
 
-    return null;
+    return undefined;
   }
 
   _computeParents(
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.js
index 5bdf105..3ed7dd4 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_test.js
@@ -716,7 +716,7 @@
       MockInteractions.tap(remove);
       assert.isTrue(chip.disabled);
       assert.isTrue(element.$.restAPI.setChangeTopic.calledWith(
-          42, null));
+          42));
       return element.$.restAPI.setChangeTopic.lastCall.returnValue
           .then(() => {
             assert.isFalse(chip.disabled);
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.ts b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.ts
index ddcb0e2..0ec9aaf 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.ts
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.ts
@@ -3085,10 +3085,7 @@
     });
   }
 
-  setChangeTopic(
-    changeNum: NumericChangeId,
-    topic: string | null
-  ): Promise<string> {
+  setChangeTopic(changeNum: NumericChangeId, topic?: string): Promise<string> {
     return (this._getChangeURLAndSend({
       changeNum,
       method: HttpMethod.PUT,
diff --git a/polygerrit-ui/app/services/services/gr-rest-api/gr-rest-api.ts b/polygerrit-ui/app/services/services/gr-rest-api/gr-rest-api.ts
index 19a8dc5..3688e44 100644
--- a/polygerrit-ui/app/services/services/gr-rest-api/gr-rest-api.ts
+++ b/polygerrit-ui/app/services/services/gr-rest-api/gr-rest-api.ts
@@ -828,10 +828,7 @@
     hashtag: HashtagsInput
   ): Promise<Hashtag[]>;
 
-  setChangeTopic(
-    changeNum: NumericChangeId,
-    topic: string | null
-  ): Promise<string>;
+  setChangeTopic(changeNum: NumericChangeId, topic?: string): Promise<string>;
 
   getChangeFiles(
     changeNum: NumericChangeId,
diff --git a/tools/nongoogle.bzl b/tools/nongoogle.bzl
index 459143d..4c65588 100644
--- a/tools/nongoogle.bzl
+++ b/tools/nongoogle.bzl
@@ -1,5 +1,9 @@
 load("//tools/bzl:maven_jar.bzl", "maven_jar")
 
+GUAVA_VERSION = "29.0-jre"
+GUAVA_BIN_SHA1 = "801142b4c3d0f0770dd29abea50906cacfddd447"
+GUAVA_DOC_URL = "https://google.github.io/guava/releases/" + GUAVA_VERSION + "/api/docs/"
+
 def declare_nongoogle_deps():
     """loads dependencies that are not used at Google.
 
@@ -129,6 +133,12 @@
         sha1 = "b66d3bedb14da604828a8693bb24fd78e36b0e9e",
     )
 
+    maven_jar(
+        name = "guava",
+        artifact = "com.google.guava:guava:" + GUAVA_VERSION,
+        sha1 = GUAVA_BIN_SHA1,
+    )
+
     # Test-only dependencies below.
 
     maven_jar(