diff options
author | Thomas Draebing <thomas.draebing@sap.com> | 2020-02-03 15:24:13 +0100 |
---|---|---|
committer | Thomas Draebing <thomas.draebing@sap.com> | 2020-02-03 15:40:12 +0100 |
commit | 4fdfa625be4a956d551073fba300cd5b630a238e (patch) | |
tree | 3a7fc7b7dffbbbf1709c859742d5e3d1e54d179c | |
parent | 7b1ba6622568b90509700cc12a34495631600860 (diff) | |
parent | d4ba7fb691edf0a5ff4944be339dfe4941bcf5e3 (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
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', |