summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Draebing <thomas.draebing@sap.com>2020-02-03 15:24:13 +0100
committerThomas Draebing <thomas.draebing@sap.com>2020-02-03 15:40:12 +0100
commit4fdfa625be4a956d551073fba300cd5b630a238e (patch)
tree3a7fc7b7dffbbbf1709c859742d5e3d1e54d179c
parent7b1ba6622568b90509700cc12a34495631600860 (diff)
parentd4ba7fb691edf0a5ff4944be339dfe4941bcf5e3 (diff)
Merge branch 'stable-2.16' into stable-3.0
* stable-2.16: Tests: Use helper method for config change Document MessageOfTheDay extension Add UI element to display messages of the day Add MessageOfTheDay-entries to ServerInfo Change-Id: Ifd30e0eb3831373450559efe1759ab72a8e1d292
-rw-r--r--Documentation/dev-plugins.txt34
-rw-r--r--Documentation/rest-api-config.txt21
-rw-r--r--java/com/google/gerrit/extensions/common/MessageOfTheDayInfo.java27
-rw-r--r--java/com/google/gerrit/extensions/common/ServerInfo.java3
-rw-r--r--java/com/google/gerrit/server/restapi/config/GetServerInfo.java24
-rw-r--r--javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java10
-rw-r--r--polygerrit-ui/app/elements/core/gr-message-header/gr-message-header.html41
-rw-r--r--polygerrit-ui/app/elements/core/gr-message-header/gr-message-header.js52
-rw-r--r--polygerrit-ui/app/elements/core/gr-message-header/gr-message-header_test.html60
-rw-r--r--polygerrit-ui/app/elements/gr-app.html7
-rw-r--r--polygerrit-ui/app/elements/gr-app.js4
11 files changed, 273 insertions, 10 deletions
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index e481d40666..3cde444707 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -2766,6 +2766,40 @@ class ApiQpsEnforcer implements QuotaEnforcer {
}
----
+[[message-of-the-day]]
+== Posting Messages (Of The Day) to the UI
+Gerrit provides an extension point that enables plugins to implement a method to
+collect messages that will then be shown below the main header in the Gerrit UI.
+
+[source, java]
+----
+import com.google.gerrit.extensions.systemstatus.MessageOfTheDay;
+
+@Singleton
+class MessageOfTheDayImpl extends MessageOfTheDay {
+
+ private final String id;
+ private final String msg;
+
+ public MessageOfTheDayImpl() {
+ id = "hello";
+ msg = "I just wanted to say <b>hello</b>.";
+ }
+
+ @Override
+ public String getHtmlMessage() {
+ return msg;
+ }
+
+ @Override
+ public String getMessageId() {
+ return id;
+ }
+}
+----
+
+Note, that the message will be added as HTML and parsed into the DOM. Thus,
+plugins using this extension should ensure that the message content is safe.
== SEE ALSO
diff --git a/Documentation/rest-api-config.txt b/Documentation/rest-api-config.txt
index 93591120e7..867016bad3 100644
--- a/Documentation/rest-api-config.txt
+++ b/Documentation/rest-api-config.txt
@@ -1896,6 +1896,22 @@ The maximal memory size. The value is returned with a unit abbreviation
The number of open files.
|============================
+[[message-of-the-day-info]]
+=== MessageOfTheDayInfo
+The `MessageOfTheDayInfo` entity contains information about a message
+that was registered with the
+link:dev-plugins.html#message-of-the-day[MessageOfTheDay]-extension by plugins.
+
+[options="header",cols="1,^1,5"]
+|===========================
+|Field Name ||Description
+|`id` ||ID of the message.
+|`redisplay` ||
+Date and Time, when the message should be displayed again after it was dismissed
+by the user.
+|`html` ||Message in HTML-format.
+|===========================
+
[[plugin-config-info]]
=== PluginConfigInfo
The `PluginConfigInfo` entity contains information about Gerrit
@@ -1949,6 +1965,11 @@ information about Gerrit
Information about the configuration from the
link:config-gerrit.html#gerrit[gerrit] section as link:#gerrit-info[
GerritInfo] entity.
+|`messages` ||
+List of messages registered with the
+link:dev-plugins.html#message-of-the-day[MessageOfTheDay]-extension
+containing link:#message-of-the-day-info[
+MessageOfTheDayInfo] entities.
|`note_db_enabled` |not set if `false`|
Whether the NoteDb storage backend is fully enabled.
|`plugin` ||
diff --git a/java/com/google/gerrit/extensions/common/MessageOfTheDayInfo.java b/java/com/google/gerrit/extensions/common/MessageOfTheDayInfo.java
new file mode 100644
index 0000000000..f752f86a64
--- /dev/null
+++ b/java/com/google/gerrit/extensions/common/MessageOfTheDayInfo.java
@@ -0,0 +1,27 @@
+// Copyright (C) 2020 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.
+
+package com.google.gerrit.extensions.common;
+
+import java.util.Date;
+
+/** REST API representation of a "message of the day". */
+public class MessageOfTheDayInfo {
+ /** The ID of the message. */
+ public String id;
+ /** The date and time the message will be displayed again after being dismissed by the user. */
+ public Date redisplay;
+ /** The message in HTML-format. */
+ public String html;
+}
diff --git a/java/com/google/gerrit/extensions/common/ServerInfo.java b/java/com/google/gerrit/extensions/common/ServerInfo.java
index 82d5bc8061..1d7de26564 100644
--- a/java/com/google/gerrit/extensions/common/ServerInfo.java
+++ b/java/com/google/gerrit/extensions/common/ServerInfo.java
@@ -14,12 +14,15 @@
package com.google.gerrit.extensions.common;
+import java.util.List;
+
public class ServerInfo {
public AccountsInfo accounts;
public AuthInfo auth;
public ChangeConfigInfo change;
public DownloadInfo download;
public GerritInfo gerrit;
+ public List<MessageOfTheDayInfo> messages;
public Boolean noteDbEnabled;
public PluginConfigInfo plugin;
public SshdInfo sshd;
diff --git a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
index aa0e350481..cfd9f580ea 100644
--- a/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
+++ b/java/com/google/gerrit/server/restapi/config/GetServerInfo.java
@@ -26,6 +26,7 @@ import com.google.gerrit.extensions.common.ChangeConfigInfo;
import com.google.gerrit.extensions.common.DownloadInfo;
import com.google.gerrit.extensions.common.DownloadSchemeInfo;
import com.google.gerrit.extensions.common.GerritInfo;
+import com.google.gerrit.extensions.common.MessageOfTheDayInfo;
import com.google.gerrit.extensions.common.PluginConfigInfo;
import com.google.gerrit.extensions.common.ReceiveInfo;
import com.google.gerrit.extensions.common.ServerInfo;
@@ -35,7 +36,9 @@ import com.google.gerrit.extensions.common.UserConfigInfo;
import com.google.gerrit.extensions.config.CloneCommand;
import com.google.gerrit.extensions.config.DownloadCommand;
import com.google.gerrit.extensions.config.DownloadScheme;
+import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.extensions.systemstatus.MessageOfTheDay;
import com.google.gerrit.extensions.webui.WebUiPlugin;
import com.google.gerrit.server.EnableSignedPush;
import com.google.gerrit.server.account.AccountVisibilityProvider;
@@ -65,6 +68,7 @@ import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.Config;
@@ -89,6 +93,7 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
private final AgreementJson agreementJson;
private final ChangeIndexCollection indexes;
private final SitePaths sitePaths;
+ private final DynamicSet<MessageOfTheDay> messages;
@Inject
public GetServerInfo(
@@ -110,7 +115,8 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
ProjectCache projectCache,
AgreementJson agreementJson,
ChangeIndexCollection indexes,
- SitePaths sitePaths) {
+ SitePaths sitePaths,
+ DynamicSet<MessageOfTheDay> motd) {
this.config = config;
this.accountVisibilityProvider = accountVisibilityProvider;
this.authConfig = authConfig;
@@ -130,6 +136,7 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
this.agreementJson = agreementJson;
this.indexes = indexes;
this.sitePaths = sitePaths;
+ this.messages = motd;
}
@Override
@@ -140,6 +147,7 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
info.change = getChangeInfo();
info.download = getDownloadInfo();
info.gerrit = getGerritInfo();
+ info.messages = getMessages();
info.noteDbEnabled = true;
info.plugin = getPluginInfo();
info.defaultTheme = getDefaultTheme();
@@ -301,6 +309,20 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
return CharMatcher.is('/').trimTrailingFrom(docUrl) + '/';
}
+ private List<MessageOfTheDayInfo> getMessages() {
+ return this.messages.stream()
+ .filter(motd -> !Strings.isNullOrEmpty(motd.getHtmlMessage()))
+ .map(
+ motd -> {
+ MessageOfTheDayInfo m = new MessageOfTheDayInfo();
+ m.id = motd.getMessageId();
+ m.redisplay = motd.getRedisplay();
+ m.html = motd.getHtmlMessage();
+ return m;
+ })
+ .collect(toList());
+ }
+
private PluginConfigInfo getPluginInfo() {
PluginConfigInfo info = new PluginConfigInfo();
info.hasAvatars = toBoolean(avatar.hasImplementation());
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index f191e08ec2..a299b9a0c3 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -60,7 +60,6 @@ import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
@@ -569,14 +568,7 @@ public abstract class AbstractSubmit extends AbstractDaemonTest {
// |
// C0 -- Master
//
- try (ProjectConfigUpdate u = updateProject(project)) {
- u.getConfig()
- .getProject()
- .setBooleanConfig(
- BooleanProjectConfig.CREATE_NEW_CHANGE_FOR_ALL_NOT_IN_TARGET,
- InheritableBoolean.TRUE);
- u.save();
- }
+ enableCreateNewChangeForAllNotInTarget();
PushOneCommit push1 =
pushFactory.create(admin.newIdent(), testRepo, PushOneCommit.SUBJECT, "a.txt", "content");
diff --git a/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header.html b/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header.html
new file mode 100644
index 0000000000..b2b382ca50
--- /dev/null
+++ b/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header.html
@@ -0,0 +1,41 @@
+<!--
+@license
+Copyright (C) 2020 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-button/gr-button.html">
+
+<dom-module id="gr-message-header">
+ <template>
+ <style include="shared-styles">
+ #container {
+ background-color: lightyellow;
+ display: flex;
+ height: fit-content;
+ justify-content: space-between;
+ padding: 1em;
+ }
+ </style>
+ <div id="container" hidden$="[[_hidden]]">
+ <div id="message"></div>
+ <gr-button id="dismissMessageBtn"
+ link
+ on-tap="_handleDismissMessage">Dismiss</gr-button>
+ </div>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
+ </template>
+ <script src="../../../scripts/util.js"></script>
+ <script src="gr-message-header.js"></script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header.js b/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header.js
new file mode 100644
index 0000000000..fac4a6a399
--- /dev/null
+++ b/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header.js
@@ -0,0 +1,52 @@
+/**
+ * @license
+ * Copyright (C) 2020 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';
+
+ Polymer({
+ is: 'gr-message-header',
+
+ properties: {
+ message: {
+ type: Object,
+ reflectToAttribute: true,
+ },
+ _hidden: {
+ type: Boolean,
+ value: true,
+ },
+ },
+
+ attached() {
+ if (!this.message || !this.message.html) {
+ return;
+ }
+ this._isHidden();
+ this.$.message.innerHTML = this.message.html;
+ },
+
+ _handleDismissMessage() {
+ document.cookie =
+ `msg-${this.message.id}=1; expires=${this.message.redisplay}`;
+ this._hidden = true;
+ },
+
+ _isHidden() {
+ this._hidden = window.util.getCookie(`msg-${this.message.id}`) === '1';
+ },
+ });
+})();
diff --git a/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header_test.html b/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header_test.html
new file mode 100644
index 0000000000..c275e55345
--- /dev/null
+++ b/polygerrit-ui/app/elements/core/gr-message-header/gr-message-header_test.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<!--
+@license
+Copyright (C) 2020 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-message-header</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-message-header.html">
+
+<script>void(0);</script>
+
+<test-fixture id="basic">
+ <template>
+ <gr-message-header></gr-message-header>
+ </template>
+</test-fixture>
+
+<script>
+ suite('gr-message-header tests', () => {
+ let element;
+
+ setup(() => {
+ element = fixture('basic');
+ });
+
+ test('show message', () => {
+ element.message = {html: 'This is a test message.'};
+ element.attached();
+ assert.equal(element.$.message.innerHTML, element.message.html);
+ });
+
+ test('hide message on dismiss', () => {
+ element.message = {html: 'This is a test message.', id: 'test'};
+ element.attached();
+ MockInteractions.tap(element.$.dismissMessageBtn);
+ assert.isTrue(element.$.container.hidden);
+ assert.isTrue(document.cookie.includes('msg-test=1'));
+
+ element.attached();
+ assert.isTrue(element.$.container.hidden);
+ });
+ });
+</script>
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
index 8c50358992..19965e7e8e 100644
--- a/polygerrit-ui/app/elements/gr-app.html
+++ b/polygerrit-ui/app/elements/gr-app.html
@@ -59,6 +59,7 @@ limitations under the License.
<link rel="import" href="./core/gr-error-manager/gr-error-manager.html">
<link rel="import" href="./core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog.html">
<link rel="import" href="./core/gr-main-header/gr-main-header.html">
+<link rel="import" href="./core/gr-message-header/gr-message-header.html">
<link rel="import" href="./core/gr-navigation/gr-navigation.html">
<link rel="import" href="./core/gr-reporting/gr-reporting.html">
<link rel="import" href="./core/gr-router/gr-router.html">
@@ -164,6 +165,12 @@ limitations under the License.
on-mobile-search="_mobileSearchToggle">
</gr-main-header>
</gr-fixed-panel>
+ <template
+ is="dom-repeat"
+ items="[[_getMessages(_serverConfig)]]"
+ as="message">
+ <gr-message-header message="{{message}}"></gr-message-header>
+ </template>
<main>
<gr-smart-search
id="search"
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index b89d90ede7..0f7e54a32e 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -341,6 +341,10 @@
this.$.header.unfloat();
},
+ _getMessages(config) {
+ return config.messages ? config.messages : [];
+ },
+
_handlePageError(e) {
const props = [
'_showChangeListView',