1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-29 18:19:44 +02:00

Semver based in-app news and update notification

Ignore semver.patch for Whats New notifications.

Use semver.major.minor.patch for Admin notifications.

Changed endpoint to /news.
This commit is contained in:
McMatts 2018-03-23 11:52:19 +00:00
parent 8d65c2d571
commit 0b85657536
8 changed files with 715 additions and 681 deletions

View file

@ -347,11 +347,8 @@ func (h *Handler) GetViewable(w http.ResponseWriter, r *http.Request) {
ctx := domain.GetRequestContext(r) ctx := domain.GetRequestContext(r)
sp, err := h.Store.Space.GetViewable(ctx) sp, err := h.Store.Space.GetViewable(ctx)
if err != nil { if err != nil {
// response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err) h.Runtime.Log.Error(method, err)
return
} }
response.WriteJSON(w, sp) response.WriteJSON(w, sp)
@ -369,15 +366,8 @@ func (h *Handler) GetAll(w http.ResponseWriter, r *http.Request) {
} }
sp, err := h.Store.Space.GetAll(ctx) sp, err := h.Store.Space.GetAll(ctx)
if err != nil {
if err != nil && err != sql.ErrNoRows {
response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err) h.Runtime.Log.Error(method, err)
return
}
if len(sp) == 0 {
sp = []space.Space{}
} }
response.WriteJSON(w, sp) response.WriteJSON(w, sp)

View file

@ -59,10 +59,14 @@ func (s Scope) Get(ctx domain.RequestContext, id string) (sp space.Space, err er
// PublicSpaces returns spaces that anyone can see. // PublicSpaces returns spaces that anyone can see.
func (s Scope) PublicSpaces(ctx domain.RequestContext, orgID string) (sp []space.Space, err error) { func (s Scope) PublicSpaces(ctx domain.RequestContext, orgID string) (sp []space.Space, err error) {
sql := "SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label a where orgid=? AND type=1" qry := "SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label a where orgid=? AND type=1"
err = s.Runtime.Db.Select(&sp, sql, orgID) err = s.Runtime.Db.Select(&sp, qry, orgID)
if err == sql.ErrNoRows {
err = nil
sp = []space.Space{}
}
if err != nil { if err != nil {
err = errors.Wrap(err, fmt.Sprintf("Unable to execute GetPublicFolders for org %s", orgID)) err = errors.Wrap(err, fmt.Sprintf("Unable to execute GetPublicFolders for org %s", orgID))
} }
@ -104,13 +108,17 @@ func (s Scope) GetViewable(ctx domain.RequestContext) (sp []space.Space, err err
// GetAll for admin users! // GetAll for admin users!
func (s Scope) GetAll(ctx domain.RequestContext) (sp []space.Space, err error) { func (s Scope) GetAll(ctx domain.RequestContext) (sp []space.Space, err error) {
sql := ` qry := `
SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label SELECT id,refid,label as name,orgid,userid,type,created,revised FROM label
WHERE orgid=? WHERE orgid=?
ORDER BY name` ORDER BY name`
err = s.Runtime.Db.Select(&sp, sql, ctx.OrgID) err = s.Runtime.Db.Select(&sp, qry, ctx.OrgID)
if err == sql.ErrNoRows {
err = nil
sp = []space.Space{}
}
if err != nil { if err != nil {
err = errors.Wrap(err, fmt.Sprintf("failed space.GetAll org %s", ctx.OrgID)) err = errors.Wrap(err, fmt.Sprintf("failed space.GetAll org %s", ctx.OrgID))
} }

View file

@ -35,7 +35,7 @@ func (s Scope) Add(ctx domain.RequestContext, u user.User) (err error) {
u.Created = time.Now().UTC() u.Created = time.Now().UTC()
u.Revised = time.Now().UTC() u.Revised = time.Now().UTC()
_, err = ctx.Transaction.Exec("INSERT INTO user (refid, firstname, lastname, email, initials, password, salt, reset, lastversion, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", _, err = ctx.Transaction.Exec("INSERT INTO user (refid, firstname, lastname, email, initials, password, salt, reset, lastversion, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
u.RefID, u.Firstname, u.Lastname, strings.ToLower(u.Email), u.Initials, u.Password, u.Salt, "", u.LastVersion, u.Created, u.Revised) u.RefID, u.Firstname, u.Lastname, strings.ToLower(u.Email), u.Initials, u.Password, u.Salt, "", u.LastVersion, u.Created, u.Revised)
if err != nil { if err != nil {

File diff suppressed because one or more lines are too long

View file

@ -25,7 +25,7 @@ export default Component.extend({
let self = this; let self = this;
let cacheBuster = + new Date(); let cacheBuster = + new Date();
$.ajax({ $.ajax({
url: `https://storage.googleapis.com/documize/downloads/updates/summary.html?cb=${cacheBuster}`, url: `https://storage.googleapis.com/documize/news/summary.html?cb=${cacheBuster}`,
type: 'GET', type: 'GET',
dataType: 'html', dataType: 'html',
success: function (response) { success: function (response) {

View file

@ -48,7 +48,7 @@ export default Component.extend(ModalMixin, {
let self = this; let self = this;
let cacheBuster = + new Date(); let cacheBuster = + new Date();
$.ajax({ $.ajax({
url: `https://storage.googleapis.com/documize/downloads/updates/${version}.html?cb=${cacheBuster}`, url: `https://storage.googleapis.com/documize/news/${version}.html?cb=${cacheBuster}`,
type: 'GET', type: 'GET',
dataType: 'html', dataType: 'html',
success: function (response) { success: function (response) {

View file

@ -13,6 +13,7 @@ import $ from 'jquery';
import { htmlSafe } from '@ember/string'; import { htmlSafe } from '@ember/string';
import { resolve } from 'rsvp'; import { resolve } from 'rsvp';
import Service, { inject as service } from '@ember/service'; import Service, { inject as service } from '@ember/service';
import miscUtil from '../utils/misc';
import config from '../config/environment'; import config from '../config/environment';
import constants from '../utils/constants'; import constants from '../utils/constants';
@ -28,6 +29,9 @@ export default Service.extend({
version: '', version: '',
message: '', message: '',
edition: 'Community', edition: 'Community',
// for major.minor semver release detection
// for bugfix releases, only admin is made aware of new release and end users see no Whats New messaging
updateAvailable: false,
valid: true, valid: true,
allowAnonymousAccess: false, allowAnonymousAccess: false,
authProvider: constants.AuthProvider.Documize, authProvider: constants.AuthProvider.Documize,
@ -80,7 +84,7 @@ export default Service.extend({
let self = this; let self = this;
let cacheBuster = + new Date(); let cacheBuster = + new Date();
$.getJSON(`https://storage.googleapis.com/documize/downloads/updates/meta.json?cb=${cacheBuster}`, function (versions) { $.getJSON(`https://storage.googleapis.com/documize/news/meta.json?cb=${cacheBuster}`, function (versions) {
let cv = 'v' + versions.community.version; let cv = 'v' + versions.community.version;
let ev = 'v' + versions.enterprise.version; let ev = 'v' + versions.enterprise.version;
let re = self.get('edition'); let re = self.get('edition');
@ -90,12 +94,11 @@ export default Service.extend({
self.set('enterpriseLatest', ev); self.set('enterpriseLatest', ev);
self.set('updateAvailable', false); // set to true for testing self.set('updateAvailable', false); // set to true for testing
if (re === 'Community' && rv < cv) { let isNewCommunity = miscUtil.isNewVersion(rv, cv, true);
self.set('updateAvailable', true); let isNewEnterprise = miscUtil.isNewVersion(rv, ev, true);
}
if (re === 'Enterprise' && rv < ev) { if (re === 'Community' && isNewCommunity) self.set('updateAvailable', true);
self.set('updateAvailable', true); if (re === 'Enterprise' && isNewEnterprise) self.set('updateAvailable', true);
}
}); });
return response; return response;

View file

@ -61,8 +61,41 @@ function insertAtCursor(myField, myValue) {
} }
} }
// Expects to receive semver version strings like "1.2.3" or "v1.2.3".
function isNewVersion(v1, v2, compareRevision) {
// Remove any "v" from version strings.
v1 = v1.replace('v', '');
v2 = v2.replace('v', '');
// Clean up strings.
v1 = v1.trim().toLowerCase();
v2 = v2.trim().toLowerCase();
// Format expected is "1.2.3".
let v1parts = v1.split('.');
let v2parts = v2.split('.');
// Must be 3+ parts per version string supporting
// v1.2.3 and v.1.2.3.beta1
if (v1parts.length < 3) return false;
if (v2parts.length < 3) return false;
// Compare Major and Minor verson parts.
if (v2parts[0] > v1parts[0]) return true;
if (v2parts[0] === v1parts[0] && v2parts[1] > v1parts[1]) return true;
if (compareRevision) {
if (v2parts[0] === v1parts[0] &&
v2parts[1] === v1parts[1] &&
v2parts[2] > v1parts[2]) return true;
}
return false;
}
export default { export default {
interval, interval,
wrapFunction, wrapFunction,
insertAtCursor insertAtCursor,
isNewVersion
}; };