Yi EungJun 2014-07-24
YobiUpdate: Show a notification bar to site admin
Show a notification bar which has a link to the latest release of Yobi
if update is available. Site Administrator can hide the bar and then
Yobi never shows the bar until itself restarts.

Yobi checks for updates every day basically. You can configure the
interval by modifying application.update.notification.interval.
@59566d492772f4b14a0873e57ff03c0e6581142b
app/Global.java
--- app/Global.java
+++ app/Global.java
@@ -69,6 +69,7 @@
         NotificationMail.onStart();
         NotificationEvent.onStart();
         Attachment.onStart();
+        YobiUpdate.onStart();
     }
 
     private boolean equalsDefaultSecret() {
app/controllers/SiteApp.java
--- app/controllers/SiteApp.java
+++ app/controllers/SiteApp.java
@@ -252,21 +252,28 @@
     }
 
     /**
+     * Hide the notification for Yobi updates.
+     */
+    public static Result unwatchUpdate() {
+        YobiUpdate.isWatched = false;
+        return ok();
+    }
+
+    /**
      * Show the page to update Yobi.
      */
     public static Result update() throws GitAPIException {
         String currentVersion = null;
-        String versionToUpdate = null;
         Exception exception = null;
 
         try {
             currentVersion = Config.getCurrentVersion();
-            versionToUpdate = YobiUpdate.fetchVersionToUpdate();
+            YobiUpdate.refreshVersionToUpdate();
         } catch (Exception e) {
             exception = e;
         }
 
-        return ok(update.render(
-                "title.siteSetting", currentVersion, versionToUpdate, exception));
+        return ok(update.render("title.siteSetting", currentVersion,
+                    YobiUpdate.versionToUpdate, exception));
     }
 }
app/models/YobiUpdate.java
--- app/models/YobiUpdate.java
+++ app/models/YobiUpdate.java
@@ -38,16 +38,53 @@
 import java.util.concurrent.TimeUnit;
 
 public class YobiUpdate {
+    private static final Long UPDATE_NOTIFICATION_INITDELAY_IN_MILLIS = Configuration.root()
+            .getMilliseconds("application.update.notification.initdelay", 5 * 1000L);
+    private static final Long UPDATE_NOTIFICATION_INTERVAL_IN_MILLIS = Configuration.root()
+            .getMilliseconds("application.update.notification.interval", 60 * 60 * 1000L);
     private static final String UPDATE_REPOSITORY_URL = Configuration.root()
             .getString("application.update.repositoryUrl", "http://demo.yobi.io/naver/Yobi");
     private static final String RELEASE_URL_FORMAT = Configuration.root()
             .getString("application.update.releaseUrlFormat",
                     "https://github.com/naver/yobi/releases/tag/v%s");
 
+    public static String versionToUpdate = null;
+
+    public static boolean isWatched = true;
+
+    public static void onStart() {
+        if (UPDATE_NOTIFICATION_INTERVAL_IN_MILLIS <= 0) {
+            return;
+        }
+
+        Akka.system().scheduler().schedule(
+            Duration.create(UPDATE_NOTIFICATION_INITDELAY_IN_MILLIS, TimeUnit.MILLISECONDS),
+            Duration.create(UPDATE_NOTIFICATION_INTERVAL_IN_MILLIS, TimeUnit.MILLISECONDS),
+            new Runnable() {
+                public void run() {
+                    try {
+                        refreshVersionToUpdate();
+                    } catch (Exception e) {
+                        play.Logger.warn("Failed to fetch the latest Yobi version to update", e);
+                    }
+                }
+            },
+            Akka.system().dispatcher()
+        );
+    }
+
+    public static String getReleaseUrl() throws GitAPIException {
+        return getReleaseUrl(versionToUpdate);
+    }
+
     public static String getReleaseUrl(String version) throws GitAPIException {
         return String.format(RELEASE_URL_FORMAT, version);
     }
 
+    public static void refreshVersionToUpdate() throws GitAPIException {
+        versionToUpdate = fetchVersionToUpdate();
+    }
+
     /**
      * Fetch the latest version to update.
      *
app/views/layout.scala.html
--- app/views/layout.scala.html
+++ app/views/layout.scala.html
@@ -40,6 +40,7 @@
 </head>
 
 <body class="@theme">
+@partial_update_notification()
 @content
 @common.scripts()
 </body>
 
app/views/partial_update_notification.scala.html (added)
+++ app/views/partial_update_notification.scala.html
@@ -0,0 +1,29 @@
+@**
+* Yobi, Project Hosting SW
+*
+* Copyright 2014 NAVER Corp.
+* http://yobi.io
+*
+* @Author Yi EungJun
+*
+* 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.
+**@
+
+@import models.YobiUpdate
+
+@if(UserApp.currentUser().isSiteManager() && YobiUpdate.isWatched && YobiUpdate.versionToUpdate != null){
+<p class="center-txt">
+<a href="@YobiUpdate.getReleaseUrl()">@Messages("site.update.notification", YobiUpdate.versionToUpdate)</a>
+<button type="button" data-request-method="post" data-request-uri="@routes.SiteApp.unwatchUpdate()" class="ybtn ybtn-small">@Messages("site.update.notification.hide", YobiUpdate.versionToUpdate)</button>
+</p>
+}
conf/application.conf.default
--- conf/application.conf.default
+++ conf/application.conf.default
@@ -129,6 +129,8 @@
 
 # Software Update
 # ~~~~~~~~~~~~~~~
+# Check for updates of Yobi at this interval if it is grater than 0.
+application.update.notification.interval = 1d
 # A url to the git repository for Yobi releases.
 application.update.repositoryUrl = "https://github.com/naver/yobi"
 # A format to construct the url to latest Yobi release. "%s" is a format
conf/messages
--- conf/messages
+++ conf/messages
@@ -678,6 +678,8 @@
 site.update.isAvailable = Yobi {0} is available
 site.update.isNotNecessary = You are using the latest version
 site.update.error = Failed to check for updates because of the following error:
+site.update.notification = Software update: Yobi {0} is available
+site.update.notification.hide = Hide
 site.user.delete = Delete user
 site.user.deleteConfirm = Are you sure you want this user to leave?
 site.userList.deleteAlert = This user cannot be deleted because this user is the only manager of the project.
conf/messages.ko
--- conf/messages.ko
+++ conf/messages.ko
@@ -678,6 +678,8 @@
 site.update.error = 다음과 같이 에러가 발생하여 업데이트 할 버전을 확인하지 못했습니다.
 site.update.isAvailable = Yobi {0} 버전으로 업데이트 할 수 있습니다
 site.update.isNotNecessary = 현재 최신 버전을 사용중입니다
+site.update.notification = 업데이트 알림: Yobi {0} 버전이 나왔습니다
+site.update.notification.hide = 숨기기
 site.user.delete = 사용자 삭제
 site.user.deleteConfirm = 정말로 해당 사용자를 사이트에서 탈퇴시키겠습니까?
 site.userList.deleteAlert = 프로젝트의 유일한 관리자이므로 사이트에서 삭제할 수 없습니다.
conf/routes
--- conf/routes
+++ conf/routes
@@ -71,6 +71,7 @@
 DELETE         /sites/project/delete/:projectId                                       controllers.SiteApp.deleteProject(projectId:Long)
 POST           /sites/toggleAccountLock                                               controllers.SiteApp.toggleAccountLock(loginId: String, state: String ?= null, query: String ?= null)
 GET            /sites/update                                                          controllers.SiteApp.update()
+POST           /sites/unwatchUpdate                                                   controllers.SiteApp.unwatchUpdate()
 GET            /lostPassword                                                          controllers.PasswordResetApp.lostPassword
 POST           /lostPassword                                                          controllers.PasswordResetApp.requestResetPasswordEmail()
 GET            /resetPassword                                                         controllers.PasswordResetApp.resetPasswordForm(s:String)
Add a comment
List