Merge branch 'stable-2.16' into stable-3.0
* stable-2.16:
Bump Bazel version to 3.0.0
Change-Id: I92e4f093187db69d36fa99e8f5fe621127ee7d2e
diff --git a/BUILD b/BUILD
index ca6a1cd..ab1c177 100644
--- a/BUILD
+++ b/BUILD
@@ -6,6 +6,7 @@
manifest_entries = [
"Gerrit-PluginName: messageoftheday",
"Gerrit-Module: com.googlesource.gerrit.plugins.messageoftheday.Module",
+ "Gerrit-HttpModule: com.googlesource.gerrit.plugins.messageoftheday.HttpModule",
"Implementation-Title: Plugin messageoftheday",
"Implementation-URL: https://gerrit-review.googlesource.com/#/admin/projects/plugins/messageoftheday",
],
diff --git a/WORKSPACE b/WORKSPACE
index 6d33a6a..27934fa 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
load("//:bazlets.bzl", "load_bazlets")
load_bazlets(
- commit = "9e23df10840ca3976431c842fdada58c7a51c6e3",
+ commit = "97eef86854b0fb68b9287831f3075b6f6218ff41",
#local_path = "/home/<user>/projects/bazlets",
)
diff --git a/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/GetMessage.java b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/GetMessage.java
new file mode 100644
index 0000000..c0181a5
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/GetMessage.java
@@ -0,0 +1,120 @@
+// 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.googlesource.gerrit.plugins.messageoftheday;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Strings;
+import com.google.gerrit.extensions.annotations.PluginData;
+import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.config.ConfigResource;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.inject.Inject;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FS;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GetMessage implements RestReadView<ConfigResource> {
+ private static final String SECTION_MESSAGE = "message";
+ private static final String KEY_ID = "id";
+ private static final String KEY_STARTS_AT = "startsAt";
+ private static final String KEY_EXPIRES_AT = "expiresAt";
+
+ private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd:HHmm");
+
+ private static final Logger log = LoggerFactory.getLogger(GetMessage.class);
+
+ private final File cfgFile;
+ private final Path dataDirPath;
+
+ private volatile FileBasedConfig cfg;
+
+ @Inject
+ public GetMessage(
+ @PluginName String pluginName, @PluginData Path dataDirPath, SitePaths sitePaths) {
+ this.dataDirPath = dataDirPath;
+ this.cfgFile = sitePaths.etc_dir.resolve(pluginName + ".config").toFile();
+ }
+
+ @Override
+ public MessageOfTheDayInfo apply(ConfigResource rsrc) {
+ MessageOfTheDayInfo motd = new MessageOfTheDayInfo();
+ cfg = new FileBasedConfig(cfgFile, FS.DETECTED);
+ try {
+ cfg.load();
+ } catch (ConfigInvalidException | IOException e) {
+ return null;
+ }
+
+ motd.id = cfg.getString(SECTION_MESSAGE, null, KEY_ID);
+ if (Strings.isNullOrEmpty(motd.id)) {
+ log.warn("id not defined, no message will be shown");
+ return null;
+ }
+
+ try {
+ motd.expiresAt = DATE_FORMAT.parse(cfg.getString(SECTION_MESSAGE, null, KEY_EXPIRES_AT));
+ } catch (ParseException | NullPointerException e) {
+ log.warn("expiresAt not defined, no message will be shown");
+ return null;
+ }
+
+ try {
+ motd.html = new String(Files.readAllBytes(dataDirPath.resolve(motd.id + ".html")), UTF_8);
+ } catch (IOException e1) {
+ log.warn(
+ String.format(
+ "No HTML-file was found for message %s, no message will be shown", motd.id));
+ return null;
+ }
+
+ try {
+ String startsAt = cfg.getString(SECTION_MESSAGE, null, KEY_STARTS_AT);
+ motd.startsAt = Strings.isNullOrEmpty(startsAt) ? new Date() : DATE_FORMAT.parse(startsAt);
+ } catch (ParseException e) {
+ motd.startsAt = new Date();
+ }
+
+ if (motd.startsAt.compareTo(new Date()) > 0 || motd.expiresAt.compareTo(new Date()) < 0) {
+ return null;
+ }
+
+ motd.redisplay = getRedisplay();
+
+ return motd;
+ }
+
+ private Date getRedisplay() {
+ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ cal.add(Calendar.DAY_OF_MONTH, 1);
+ return cal.getTime();
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/HttpModule.java
new file mode 100644
index 0000000..d10983a
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/HttpModule.java
@@ -0,0 +1,28 @@
+// 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.googlesource.gerrit.plugins.messageoftheday;
+
+import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.extensions.webui.JavaScriptPlugin;
+import com.google.gerrit.extensions.webui.WebUiPlugin;
+import com.google.inject.AbstractModule;
+
+public class HttpModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ DynamicSet.bind(binder(), WebUiPlugin.class)
+ .toInstance(new JavaScriptPlugin("gr-messageoftheday.html"));
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/MessageOfTheDayImpl.java b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/MessageOfTheDayImpl.java
deleted file mode 100644
index 83adccc..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/MessageOfTheDayImpl.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2016 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.googlesource.gerrit.plugins.messageoftheday;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.common.base.MoreObjects;
-import com.google.common.base.Strings;
-import com.google.gerrit.extensions.annotations.PluginData;
-import com.google.gerrit.extensions.annotations.PluginName;
-import com.google.gerrit.extensions.systemstatus.MessageOfTheDay;
-import com.google.gerrit.server.config.PluginConfigFactory;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.eclipse.jgit.lib.Config;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Singleton
-class MessageOfTheDayImpl extends MessageOfTheDay {
- private static final Logger log = LoggerFactory.getLogger(MessageOfTheDayImpl.class);
-
- private final File data;
- private final String id;
- private final String startsAt;
- private final String expiresAt;
- private final String msg;
-
- @Inject
- public MessageOfTheDayImpl(
- PluginConfigFactory configFactory, @PluginName String myName, @PluginData File data) {
- this.data = data;
- Config cfg = configFactory.getGlobalPluginConfig(myName);
- id = cfg.getString("message", null, "id");
- String configuredStartsAt = Strings.emptyToNull(cfg.getString("message", null, "startsAt"));
- startsAt = MoreObjects.firstNonNull(configuredStartsAt, now());
- expiresAt = cfg.getString("message", null, "expiresAt");
- msg = message();
- }
-
- @Override
- public String getHtmlMessage() {
- if (Strings.isNullOrEmpty(id)) {
- return null;
- }
-
- if (Strings.isNullOrEmpty(expiresAt)) {
- log.warn("expiresAt not defined, no message will be shown");
- return null;
- }
-
- if (now().compareTo(startsAt) < 0 || now().compareTo(expiresAt) > 0) {
- return null;
- }
-
- return msg;
- }
-
- @Override
- public String getMessageId() {
- return id;
- }
-
- private String message() {
- if (Strings.isNullOrEmpty(id)) {
- return null;
- }
-
- Path p = new File(data, id + ".html").toPath();
- try {
- return new String(Files.readAllBytes(p), UTF_8);
- } catch (IOException e) {
- log.warn("Couldn't read content of the mesage with id = " + id, e);
- return null;
- }
- }
-
- private static String now() {
- return new SimpleDateFormat("yyyyMMdd:HHmm").format(new Date());
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/MessageOfTheDayInfo.java b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/MessageOfTheDayInfo.java
new file mode 100644
index 0000000..eed52ce
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/MessageOfTheDayInfo.java
@@ -0,0 +1,31 @@
+// 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.googlesource.gerrit.plugins.messageoftheday;
+
+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 time from which on the message will be displayed. */
+ public Date startsAt;
+ /** The time from which on the message will not be displayed anymore. */
+ public Date expiresAt;
+ /** 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/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/Module.java b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/Module.java
index c9ea760..1164004 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/messageoftheday/Module.java
@@ -14,13 +14,20 @@
package com.googlesource.gerrit.plugins.messageoftheday;
-import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gerrit.extensions.systemstatus.MessageOfTheDay;
+import static com.google.gerrit.server.config.ConfigResource.CONFIG_KIND;
+
+import com.google.gerrit.extensions.restapi.RestApiModule;
import com.google.inject.AbstractModule;
class Module extends AbstractModule {
@Override
protected void configure() {
- DynamicSet.bind(binder(), MessageOfTheDay.class).to(MessageOfTheDayImpl.class);
+ install(
+ new RestApiModule() {
+ @Override
+ protected void configure() {
+ get(CONFIG_KIND, "message").to(GetMessage.class);
+ }
+ });
}
}
diff --git a/src/main/resources/Documentation/rest-api-config.md b/src/main/resources/Documentation/rest-api-config.md
new file mode 100644
index 0000000..86d923c
--- /dev/null
+++ b/src/main/resources/Documentation/rest-api-config.md
@@ -0,0 +1,57 @@
+@PLUGIN@ - /config/ REST API
+============================
+
+This page describes the REST endpoints that are added by the @PLUGIN@
+plugin.
+
+Please also take note of the general information on the
+[REST API](../../../Documentation/rest-api.html).
+
+<a id="config-endpoints"> Config Endpoints
+------------------------------------------
+
+### <a id="get-menus"> Get Menus
+_GET /config/server/@PLUGIN@~message/_
+
+Gets the message of the day.
+
+#### Request
+
+```
+ GET /config/server/@PLUGIN@~message/ HTTP/1.0
+```
+
+As response a [MessageOfTheDayInfo](./rest-api-config.md#MessageOfTheDayInfo) entity
+is returned that contains the message and associated metadata.
+
+#### Response
+
+```
+ HTTP/1.1 200 OK
+ Content-Disposition: attachment
+ Content-Type: application/json;charset=UTF-8
+
+ )]}'
+ {
+ "id": "hello",
+ "starts_at": "Feb 4, 2020 5:53:00 PM",
+ "expires_at": "Dec 30, 2020 6:00:00 PM",
+ "redisplay": "Feb 5, 2020 1:00:00 AM",
+ "html": "hello you!"
+ }
+```
+
+### MessageOfTheDayInfo
+
+The `MessageOfTheDayInfo` entity contains information about the message of the day.
+
+* `id`: ID of the message.
+* `starts_at`: Date, when the message will be first displayed
+* `expires_at`: Date, after which the message will not be displayed anymore
+* `redisplay`: Date, after which will the message be displayed again after dismissal
+* `html`: String, containing the HTML-formatted message
+
+
+[Back to @PLUGIN@ documentation index][index]
+
+[index]: index.html
diff --git a/src/main/resources/static/gr-messageoftheday-banner.html b/src/main/resources/static/gr-messageoftheday-banner.html
new file mode 100644
index 0000000..102645d
--- /dev/null
+++ b/src/main/resources/static/gr-messageoftheday-banner.html
@@ -0,0 +1,38 @@
+<!--
+@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.
+-->
+
+<dom-module id="gr-messageoftheday-banner">
+ <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="gr-messageoftheday-banner.js"></script>
+</dom-module>
diff --git a/src/main/resources/static/gr-messageoftheday-banner.js b/src/main/resources/static/gr-messageoftheday-banner.js
new file mode 100644
index 0000000..536c05d
--- /dev/null
+++ b/src/main/resources/static/gr-messageoftheday-banner.js
@@ -0,0 +1,54 @@
+/**
+ * @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-messageoftheday-banner',
+
+ properties: {
+ _message: Object,
+ _hidden: {
+ type: Boolean,
+ value: true,
+ },
+ },
+
+ attached() {
+ this.plugin.restApi()
+ .get(`/config/server/${this.plugin.getPluginName()}~message`)
+ .then(message => {
+ if (!message || !message.html) {
+ return;
+ }
+ this._message = message;
+ 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/src/main/resources/static/gr-messageoftheday.html b/src/main/resources/static/gr-messageoftheday.html
new file mode 100644
index 0000000..8758502
--- /dev/null
+++ b/src/main/resources/static/gr-messageoftheday.html
@@ -0,0 +1,27 @@
+<!--
+@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="./gr-messageoftheday-banner.html">
+
+<dom-module id="gr-messageoftheday">
+ <script>
+ Gerrit.install(plugin => {
+ plugin.registerCustomComponent("banner", "gr-messageoftheday-banner");
+ });
+ </script>
+</dom-module>