1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-20 05:39:42 +02:00

Merge code between editions

This commit is contained in:
Harvey Kandola 2018-11-07 15:56:05 +00:00
parent d1b803b246
commit 6a9ad7f540
20 changed files with 365 additions and 110 deletions

View file

@ -0,0 +1,39 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import $ from 'jquery';
import { inject as service } from '@ember/service';
import Notifier from '../../mixins/notifier';
import Component from '@ember/component';
export default Component.extend(Notifier, {
appMeta: service(),
global: service(),
changelog: '',
init() {
this._super(...arguments);
let self = this;
let cacheBuster = + new Date();
$.ajax({
url: `https://storage.googleapis.com/documize/news/summary.html?cb=${cacheBuster}`,
type: 'GET',
dataType: 'html',
success: function (response) {
self.set('changelog', response);
}
});
},
actions: {
}
});

View file

@ -9,7 +9,6 @@
// //
// https://documize.com // https://documize.com
import $ from 'jquery';
import { empty } from '@ember/object/computed'; import { empty } from '@ember/object/computed';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import Notifier from '../../mixins/notifier'; import Notifier from '../../mixins/notifier';
@ -18,20 +17,21 @@ import Component from '@ember/component';
export default Component.extend(Notifier, { export default Component.extend(Notifier, {
appMeta: service(), appMeta: service(),
global: service(), global: service(),
LicenseError: empty('license'), licenseError: empty('license'),
changelog: '', subscription: null,
planCloud: false,
planSelfhost: false,
init() { didReceiveAttrs() {
this._super(...arguments); this._super(...arguments);
this.get('global').getSubscription().then((subs) => {
let self = this; this.set('subscription', subs);
let cacheBuster = + new Date(); if (subs.plan === 'Installed') {
$.ajax({ this.set('planCloud', false);
url: `https://storage.googleapis.com/documize/news/summary.html?cb=${cacheBuster}`, this.set('planSelfhost', true);
type: 'GET', } else {
dataType: 'html', this.set('planCloud', true);
success: function (response) { this.set('planSelfhost', false);
self.set('changelog', response);
} }
}); });
}, },
@ -40,7 +40,7 @@ export default Component.extend(Notifier, {
saveLicense() { saveLicense() {
this.showWait(); this.showWait();
this.get('global').saveLicense(this.get('license')).then(() => { this.get('global').setLicense(this.get('license')).then(() => {
this.showDone(); this.showDone();
window.location.reload(); window.location.reload();
}); });

View file

@ -13,9 +13,10 @@ import $ from 'jquery';
import { notEmpty } from '@ember/object/computed'; import { notEmpty } from '@ember/object/computed';
import { inject as service } from '@ember/service' import { inject as service } from '@ember/service'
import ModalMixin from '../../mixins/modal'; import ModalMixin from '../../mixins/modal';
import TooltipMixin from '../../mixins/tooltip';
import Component from '@ember/component'; import Component from '@ember/component';
export default Component.extend(ModalMixin, { export default Component.extend(ModalMixin, TooltipMixin, {
classNames: ['layout-header', 'non-printable'], classNames: ['layout-header', 'non-printable'],
tagName: 'header', tagName: 'header',
folderService: service('folder'), folderService: service('folder'),
@ -69,6 +70,8 @@ export default Component.extend(ModalMixin, {
this.eventBus.subscribe('pinChange', this, 'setupPins'); this.eventBus.subscribe('pinChange', this, 'setupPins');
this.setupPins(); this.setupPins();
} }
this.renderTooltips();
}, },
setupPins() { setupPins() {
@ -87,6 +90,7 @@ export default Component.extend(ModalMixin, {
willDestroyElement() { willDestroyElement() {
this._super(...arguments); this._super(...arguments);
this.removeTooltips();
this.eventBus.unsubscribe('pinChange'); this.eventBus.unsubscribe('pinChange');
}, },
@ -113,6 +117,14 @@ export default Component.extend(ModalMixin, {
this.get('session').seenNewVersion(); this.get('session').seenNewVersion();
this.set('hasWhatsNew', false); this.set('hasWhatsNew', false);
} }
},
onBilling() {
if (!this.get('session.isAdmin')) {
return;
}
this.get('router').transitionTo('customize.billing');
} }
} }
}); });

View file

@ -0,0 +1,32 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import { helper } from '@ember/component/helper';
export function formattedPrice(params) {
let pence = params[0];
if(is.not.number(pence)) {
return '$0'
}
let p = parseInt(pence);
if(p === 0) {
return '$0'
}
let a = pence / 100;
return `$` + a;
}
export default helper(formattedPrice);

View file

@ -1 +0,0 @@
{{customize/license-key license=model}}

View file

@ -10,8 +10,8 @@
// https://documize.com // https://documize.com
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import Route from '@ember/routing/route';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin'; import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
import Route from '@ember/routing/route';
export default Route.extend(AuthenticatedRouteMixin, { export default Route.extend(AuthenticatedRouteMixin, {
appMeta: service(), appMeta: service(),
@ -19,16 +19,15 @@ export default Route.extend(AuthenticatedRouteMixin, {
global: service(), global: service(),
beforeModel() { beforeModel() {
if (!this.get("session.isGlobalAdmin")) { if (!this.get("session.isAdmin")) {
this.transitionTo('auth.login'); this.transitionTo('auth.login');
} }
}, },
model() { model() {
return this.get('global').getLicense();
}, },
activate() { activate() {
this.get('browser').setTitle('Product Licensing & Updates'); this.get('browser').setTitle('Product Changelog');
} }
}); });

View file

@ -0,0 +1 @@
{{customize/change-log}}

View file

@ -10,27 +10,49 @@
<div id="sidebar" class="sidebar"> <div id="sidebar" class="sidebar">
<h1>Settings</h1> <h1>Settings</h1>
<p>Configure authentication, SMTP, licensing and manage user accounts</p> <p>Configure authentication, SMTP, licensing and manage user accounts</p>
<ul class="tabnav-control tabnav-control-centered w-75"> <ul class="tabnav-control tabnav-control-centered w-75">
{{#link-to 'customize.general' activeClass='selected' class="tab tab-vertical" tagName="li" }}General{{/link-to}} {{#link-to 'customize.general' activeClass='selected' class="tab tab-vertical" tagName="li" }}General{{/link-to}}
{{#link-to 'customize.folders' activeClass='selected' class="tab tab-vertical" tagName="li" }}Spaces{{/link-to}}
{{#link-to 'customize.groups' activeClass='selected' class="tab tab-vertical" tagName="li" }}Groups{{/link-to}}
{{#link-to 'customize.users' activeClass='selected' class="tab tab-vertical" tagName="li" }}Users{{/link-to}}
{{#link-to 'customize.integrations' activeClass='selected' class="tab tab-vertical" tagName="li" }}Integrations{{/link-to}} {{#link-to 'customize.integrations' activeClass='selected' class="tab tab-vertical" tagName="li" }}Integrations{{/link-to}}
{{#if session.isGlobalAdmin}} {{#if session.isGlobalAdmin}}
{{#link-to 'customize.smtp' activeClass='selected' class="tab tab-vertical" tagName="li" }}SMTP{{/link-to}} {{#link-to 'customize.smtp' activeClass='selected' class="tab tab-vertical" tagName="li" }}Mail{{/link-to}}
{{/if}}
</ul>
<div class="mt-4" />
<ul class="tabnav-control tabnav-control-centered w-75">
{{#link-to 'customize.groups' activeClass='selected' class="tab tab-vertical" tagName="li" }}Groups{{/link-to}}
{{#link-to 'customize.users' activeClass='selected' class="tab tab-vertical" tagName="li" }}Users{{/link-to}}
{{#if session.isGlobalAdmin}}
{{#link-to 'customize.auth' activeClass='selected' class="tab tab-vertical" tagName="li" }}Authentication{{/link-to}} {{#link-to 'customize.auth' activeClass='selected' class="tab tab-vertical" tagName="li" }}Authentication{{/link-to}}
{{/if}}
</ul>
<div class="mt-4" />
<ul class="tabnav-control tabnav-control-centered w-75">
{{#link-to 'customize.folders' activeClass='selected' class="tab tab-vertical" tagName="li" }}Spaces{{/link-to}}
{{#if session.isGlobalAdmin}}
{{#link-to 'customize.search' activeClass='selected' class="tab tab-vertical" tagName="li" }}Search{{/link-to}} {{#link-to 'customize.search' activeClass='selected' class="tab tab-vertical" tagName="li" }}Search{{/link-to}}
{{#if (eq appMeta.edition 'Enterprise')}} {{#if (eq appMeta.edition constants.Product.EnterpriseEdition)}}
{{#link-to 'customize.audit' activeClass='selected' class="tab tab-vertical" tagName="li" }}Audit{{/link-to}} {{#link-to 'customize.audit' activeClass='selected' class="tab tab-vertical" tagName="li" }}Audit{{/link-to}}
{{/if}} {{/if}}
{{/if}} {{/if}}
{{#if (eq appMeta.edition 'Enterprise')}} {{#if (eq appMeta.edition constants.Product.EnterpriseEdition)}}
{{#link-to 'customize.archive' activeClass='selected' class="tab tab-vertical" tagName="li" }}Archive{{/link-to}} {{#link-to 'customize.archive' activeClass='selected' class="tab tab-vertical" tagName="li" }}Archive{{/link-to}}
{{/if}} {{/if}}
{{#if session.isGlobalAdmin}} </ul>
{{#link-to 'customize.license' activeClass='selected' class="tab tab-vertical" tagName="li" }}Product{{/link-to}}
<div class="mt-4" />
<ul class="tabnav-control tabnav-control-centered w-75">
{{#link-to 'customize.backup' activeClass='selected' class="tab tab-vertical" tagName="li" }}Backup // Restore{{/link-to}}
</ul>
<div class="mt-4" />
<ul class="tabnav-control tabnav-control-centered w-75">
{{#if (eq appMeta.edition constants.Product.EnterpriseEdition)}}
{{#link-to 'customize.billing' activeClass='selected' class="tab tab-vertical" tagName="li" }}Billing{{/link-to}}
{{/if}} {{/if}}
{{#link-to 'customize.backup' activeClass='selected' class="tab tab-vertical" tagName="li" }}Backup & Restore{{/link-to}} {{#link-to 'customize.product' activeClass='selected' class="tab tab-vertical" tagName="li" }}Changelog{{/link-to}}
</ul> </ul>
</div> </div>
{{/layout/middle-zone-sidebar}} {{/layout/middle-zone-sidebar}}

View file

@ -14,6 +14,11 @@ import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-rout
export default Route.extend(AuthenticatedRouteMixin, { export default Route.extend(AuthenticatedRouteMixin, {
beforeModel() { beforeModel() {
this.transitionTo('folders'); // this.transitionTo('folders');
},
activate: function () {
this._super(...arguments);
this.browser.setTitleWithoutSuffix('Aw, Snap!');
} }
}); });

View file

@ -1,2 +1,7 @@
<h1>Not found</h1> <div class="not-found">
<h1>Oops! That page couldn't be found.</h1>
<p>Maybe the content you're looking for is no longer available?</p>
<p>&nbsp;</p>
<a href="/">Return to Documize home page</a>
</div>
{{outlet}} {{outlet}}

View file

@ -80,8 +80,8 @@ export default Router.map(function () {
this.route('smtp', { this.route('smtp', {
path: 'smtp' path: 'smtp'
}); });
this.route('license', { this.route('product', {
path: 'license' path: 'product'
}); });
this.route('auth', { this.route('auth', {
path: 'auth' path: 'auth'
@ -101,6 +101,9 @@ export default Router.map(function () {
this.route('backup', { this.route('backup', {
path: 'backup' path: 'backup'
}); });
this.route('billing', {
path: 'billing'
});
} }
); );

View file

@ -17,6 +17,7 @@ import AjaxService from 'ember-ajax/services/ajax';
export default AjaxService.extend({ export default AjaxService.extend({
session: service(), session: service(),
localStorage: service(), localStorage: service(),
appMeta: service(),
host: config.apiHost, host: config.apiHost,
namespace: config.apiNamespace, namespace: config.apiNamespace,
@ -34,20 +35,27 @@ export default AjaxService.extend({
handleResponse(status, headers /*, payload*/) { handleResponse(status, headers /*, payload*/) {
try { try {
// Handle user permission changes.
let user = this.get('session.session.content.authenticated.user'); let user = this.get('session.session.content.authenticated.user');
let userUpdate = headers['x-documize-status']; let userUpdate = headers['x-documize-status'];
let appVersion = headers['x-documize-version']; let appVersion = headers['x-documize-version'];
// when unauthorized on local API AJAX calls, redirect to app root // Unauthorized local API AJAX calls redirect to app root.
if (status === 401 && is.not.undefined(appVersion) && is.not.include(window.location.href, '/auth')) { if (status === 401 && is.not.undefined(appVersion) && is.not.include(window.location.href, '/auth')) {
this.get('localStorage').clearAll(); this.get('localStorage').clearAll();
window.location.href = 'auth/login'; window.location.href = 'auth/login';
} }
// Handle billing/licensing issue.
if (status === 402 || headers['x-documize-subscription'] === 'false') {
this.set('appMeta.valid', false);
}
if (this.get('session.authenticated') && is.not.empty(userUpdate) && is.not.undefined(userUpdate)) { if (this.get('session.authenticated') && is.not.empty(userUpdate) && is.not.undefined(userUpdate)) {
let latest = JSON.parse(userUpdate); let latest = JSON.parse(userUpdate);
// Permission change means re-validation.
if (!latest.active || user.editor !== latest.editor || user.admin !== latest.admin || user.analytics !== latest.analytics || user.viewUsers !== latest.viewUsers) { if (!latest.active || user.editor !== latest.editor || user.admin !== latest.admin ||
user.analytics !== latest.analytics || user.viewUsers !== latest.viewUsers) {
this.get('localStorage').clearAll(); this.get('localStorage').clearAll();
window.location.href = 'auth/login'; window.location.href = 'auth/login';
} }

View file

@ -38,15 +38,10 @@ export default Service.extend({
secureMode: false, secureMode: false,
maxTags: 3, maxTags: 3,
storageProvider: '', storageProvider: '',
location: 'selfhost',
// for major.minor semver release detection
// for bugfix releases, only admin is made aware of new release and end users see no What's New messaging // for bugfix releases, only admin is made aware of new release and end users see no What's New messaging
updateAvailable: false, updateAvailable: false,
// invalidLicense() {
// return this.valid === false;
// },
getBaseUrl(endpoint) { getBaseUrl(endpoint) {
return [this.get('endpoint'), endpoint].join('/'); return [this.get('endpoint'), endpoint].join('/');
}, },

View file

@ -41,10 +41,23 @@ export default Service.extend({
} }
}, },
// Returns product subscription.
getSubscription() {
if(this.get('sessionService.isAdmin')) {
return this.get('ajax').request(`subscription`, {
method: 'GET',
dataType: 'JSON'
}).then((response) => {
return response;
});
}
},
// Returns product license. // Returns product license.
getLicense() { getLicense() {
if(this.get('sessionService.isGlobalAdmin')) { if(this.get('sessionService.isAdmin')) {
return this.get('ajax').request(`global/license`, { return this.get('ajax').request(`license`, {
method: 'GET', method: 'GET',
dataType: "text" dataType: "text"
}).then((response) => { }).then((response) => {
@ -53,10 +66,10 @@ export default Service.extend({
} }
}, },
// Saves product license. // Saves product subscription data.
saveLicense(license) { setLicense(license) {
if(this.get('sessionService.isGlobalAdmin')) { if(this.get('sessionService.isAdmin')) {
return this.get('ajax').request(`global/license`, { return this.get('ajax').request(`license`, {
method: 'PUT', method: 'PUT',
dataType: 'text', dataType: 'text',
data: license data: license

File diff suppressed because one or more lines are too long

View file

@ -25,3 +25,10 @@
color: $color-stroke; color: $color-stroke;
} }
} }
.not-found {
text-align: center;
font-size: 2rem;
color: $color-gray;
margin: 5rem 0;
}

View file

@ -0,0 +1,37 @@
<div class="row">
<div class="col">
<div class="view-customize">
<h1 class="admin-heading">{{appMeta.edition}} Edition {{appMeta.version}}</h1>
<h2 class="sub-heading">Enterprise Edition unlocks
<a class="" href="https://documize.com/pricing">premium capabilities and product support</a>
</h2>
</div>
</div>
</div>
<div class="product-update">
<div class="update-summary">
{{#if appMeta.updateAvailable}}
<a href="https://documize.com/downloads" class="caption">New version available</a>
<p class="instructions">
To upgrade, replace existing binary and restart Documize. Migrate between Community and Enterprise editions seamlessly.
</p>
{{else}}
<div class="caption">Release Summary</div>
{{/if}}
<p>
<span class="color-off-black">Community Edition {{appMeta.communityLatest}}</span>&nbsp;&nbsp;&nbsp;
<a href="https://storage.googleapis.com/documize/downloads/documize-community-windows-amd64.exe" class="font-weight-bold">Windows</a>&nbsp;&middot;
<a href="https://storage.googleapis.com/documize/downloads/documize-community-linux-amd64" class="font-weight-bold">Linux</a>&nbsp;&middot;
<a href="https://storage.googleapis.com/documize/downloads/documize-community-darwin-amd64" class="font-weight-bold">macOS</a>&nbsp;
</p>
<p>
<span class="color-off-black">Enterprise Edition {{appMeta.enterpriseLatest}}</span>&nbsp;&nbsp;&nbsp;
<a href="https://storage.googleapis.com/documize/downloads/documize-enterprise-windows-amd64.exe" class="font-weight-bold color-blue">Windows</a>&nbsp;&middot;
<a href="https://storage.googleapis.com/documize/downloads/documize-enterprise-linux-amd64" class="font-weight-bold color-blue">Linux</a>&nbsp;&middot;
<a href="https://storage.googleapis.com/documize/downloads/documize-enterprise-darwin-amd64" class="font-weight-bold color-blue">macOS</a>&nbsp;
</p>
<div class="my-5" />
{{{changelog}}}
</div>
</div>

View file

@ -1,69 +1,132 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div class="view-customize"> <div class="view-customize">
<h1 class="admin-heading">{{appMeta.edition}} Edition {{appMeta.version}}</h1> <h1 class="admin-heading">Product Billing & Subscription</h1>
<h2 class="sub-heading">Enterprise Edition unlocks <h2 class="sub-heading">Active subscription details</h2>
<a class="" href="https://documize.com/pricing">premium capabilities and product support</a>
</h2>
</div> </div>
</div> </div>
</div> </div>
<div class="view-customize"> <div class="view-customize">
<form class="mt-5 "> <form class="my-5 ">
<div class="form-group"> <div class="form-group row">
<label for="product-license-xml">Optional Enterprise Edition License Key</label> <label for="sub-name" class="col-sm-4 col-form-label"></label>
{{textarea id="product-license-xml" value=license rows="18" class=(if LicenseError 'form-control is-invalid' 'form-control')}} <div class="col-sm-7">
{{#if appMeta.valid}} {{#if (eq subscription.status 0)}}
{{#if (eq appMeta.edition constants.Product.EnterpriseEdition)}} <h3 class="text-danger">Enjoy the Documize free plan!</h3>
<p class="mt-2 color-green">Registered to {{appMeta.license.email}} @ {{appMeta.license.name}}</p> <a class="btn btn-success" href="https://documize.com/checkout?ref=app&l={{appMeta.location}}&id={{subscription.id}}&o={{appMeta.orgId}}&u={{subscription.seats}}&a={{subscription.activeUsers}}&e={{subscription.email}}">upgrade now &xrarr;</a>
<p class="mt-2 color-green">{{appMeta.license.package}} package up to {{appMeta.license.seats}} users</p>
{{#if appMeta.license.trial}}
<p class="mt-2 color-red">Trial expiry {{formatted-date appMeta.license.end}}</p>
{{else}}
<p class="mt-2 color-green">Subscribed to {{formatted-date appMeta.license.end}}</p>
{{/if}} {{/if}}
{{else}} {{#if (eq subscription.status 1)}}
<small class="form-text text-muted">License key is XML format and activates Enterprise edition</small> <h3 class="text-success">Nice, you have an active product subscription!</h3>
<a class="btn btn-success" href="https://documize.com/checkout?ref=app&l={{appMeta.location}}&id={{subscription.id}}&o={{appMeta.orgId}}&u={{subscription.seats}}&a={{subscription.activeUsers}}&e={{subscription.email}}">
change plan &xrarr;
</a>
{{/if}} {{/if}}
{{else}} {{#if (eq subscription.status 2)}}
<p class="mt-2 color-red">License is not valid &mdash; check user count and expiry date</p> <h3 class="text-danger">Hmm, your product subscription has expired</h3>
<p class="mt-2 color-gray">Registered to {{appMeta.license.email}} @ {{appMeta.license.name}}</p> <a class="btn btn-success" href="https://documize.com/checkout?ref=app&l={{appMeta.location}}&id={{subscription.id}}&o={{appMeta.orgId}}&u={{subscription.seats}}&a={{subscription.activeUsers}}&e={{subscription.email}}">
<p class="mt-2 color-gray">{{appMeta.license.package}} package up to {{appMeta.license.seats}} users</p> renew &xrarr;
{{#if appMeta.license.trial}} </a>
<p class="mt-2 color-gray">Trial expiry {{formatted-date appMeta.license.end}}</p>
{{else}}
<p class="mt-2 color-gray">Subscribed to {{formatted-date appMeta.license.end}}</p>
{{/if}} {{/if}}
{{#if (eq subscription.status 3)}}
<h3 class="text-danger">Hmm, {{subscription.activeUsers}} active user count exceeds permitted {{subscription.seats}} user limit</h3>
<a class="btn btn-success" href="https://documize.com/checkout?ref=app&l={{appMeta.location}}&id={{subscription.id}}&o={{appMeta.orgId}}&u={{subscription.seats}}&a={{subscription.activeUsers}}&e={{subscription.email}}">
upgrade &xrarr;
</a>
{{/if}} {{/if}}
{{#if (eq subscription.status 4)}}
<h3 class="text-danger">Hmm, your product subscription is not valid</h3>
<a class="btn btn-success" href="https://documize.com/pricing?ref=app">upgrade &xrarr;</a>
{{/if}}
<br/>
<br/>
</div> </div>
<div class="btn btn-success mt-3" {{action 'saveLicense'}}>Save</div> </div>
<div class="form-group row">
<label for="sub-id" class="col-sm-4 col-form-label">Customer ID</label>
<div class="col-sm-7">
{{input id="sub-id" type="text" value=subscription.id class='form-control' readonly=true}}
<small class="form-text text-muted">Quote this ID when contacting us</small>
</div>
</div>
<div class="form-group row">
<label for="sub-name" class="col-sm-4 col-form-label">Customer Name</label>
<div class="col-sm-7">
{{input id="sub-name" type="text" value=subscription.name class='form-control' readonly=true}}
<small class="form-text text-muted">The business or personal name of our customer</small>
</div>
</div>
<div class="form-group row">
<label for="sub-email" class="col-sm-4 col-form-label">Contact Email</label>
<div class="col-sm-7">
{{input id="sub-email" type="email" value=subscription.email class='form-control' readonly=true}}
<small class="form-text text-muted">Where we will send product update and billing notices</small>
</div>
</div>
<div class="form-group row">
<label for="sub-seats" class="col-sm-4 col-form-label">Maximum Users</label>
<div class="col-sm-7">
{{input id="sub-seats" type="number" value=subscription.seats class='form-control' readonly=true}}
<small class="form-text text-muted">Your user pack size &mdash; you have {{subscription.activeUsers}} active users at the moment</small>
</div>
</div>
{{#if (eq appMeta.location 'selfhost')}}
<div class="form-group row">
<label for="sub-start" class="col-sm-4 col-form-label">Start Date</label>
<div class="col-sm-7">
{{input id="sub-start" type="text" value=(formatted-date subscription.start) class='form-control' readonly=true}}
<small class="form-text text-muted">When you (re)signed up</small>
</div>
</div>
<div class="form-group row">
<label for="sub-end" class="col-sm-4 col-form-label">Renewal Date</label>
<div class="col-sm-7">
{{input id="sub-end" type="text" value=(formatted-date subscription.end) class='form-control' readonly=true}}
<small class="form-text text-muted">The renewal date of your annual subscription</small>
</div>
</div>
<div class="form-group row">
<label for="sub-price" class="col-sm-4 col-form-label">Annual Billing</label>
<div class="col-sm-7">
{{input id="sub-price" type="text" value=(formatted-price subscription.price) class='form-control' readonly=true}}
<small class="form-text text-muted">What you pay each year</small>
</div>
</div>
{{else}}
<div class="form-group row">
<label for="sub-start" class="col-sm-4 col-form-label">Start of Billing</label>
<div class="col-sm-7">
{{input id="sub-start" type="text" value=(formatted-date subscription.start) class='form-control' readonly=true}}
<small class="form-text text-muted">When we first charged your credit card &mdash; charged every 30 days thereafter</small>
</div>
</div>
<div class="form-group row">
<label for="sub-price" class="col-sm-4 col-form-label">Monthly Amount</label>
<div class="col-sm-7">
{{input id="sub-price" type="text" value=(formatted-price subscription.price) class='form-control' readonly=true}}
<small class="form-text text-muted">What you pay us each month</small>
</div>
</div>
{{/if}}
{{#if subscription.trial}}
<div class="form-group row">
<label for="sub-trial" class="col-sm-4 col-form-label">Trial?</label>
<div class="col-sm-7">
{{input id="sub-trial" type="text" value="Yes" class='form-control' readonly=true}}
</div>
</div>
{{/if}}
{{#if (eq appMeta.location 'selfhost')}}
<div class="form-group row">
<label for="sub-license" class="col-sm-4 col-form-label">Activation Key</label>
<div class="col-sm-7">
{{focus-textarea id="sub-license" value=license rows="10" class=(if licenseError 'form-control is-invalid' 'form-control')}}
<small class="form-text text-muted">The activation key you received after sign-up</small>
<div class="btn btn-secondary mt-3" {{action 'saveLicense'}}>Activate</div>
</div>
</div>
{{/if}}
</form> </form>
</div> </div>
<div class="product-update">
<div class="update-summary">
{{#if appMeta.updateAvailable}}
<a href="https://documize.com/downloads" class="caption">New version available</a>
<p class="instructions">
To upgrade, replace existing binary and restart Documize. Migrate between Community and Enterprise editions seamlessly.
</p>
{{else}}
<div class="caption">Release Summary</div>
{{/if}}
<p>
<span class="color-off-black">Community Edition {{appMeta.communityLatest}}</span>&nbsp;&nbsp;&nbsp;
<a href="https://storage.googleapis.com/documize/downloads/documize-community-windows-amd64.exe" class="font-weight-bold">Windows</a>&nbsp;&middot;
<a href="https://storage.googleapis.com/documize/downloads/documize-community-linux-amd64" class="font-weight-bold">Linux</a>&nbsp;&middot;
<a href="https://storage.googleapis.com/documize/downloads/documize-community-darwin-amd64" class="font-weight-bold">macOS</a>&nbsp;
</p>
<p>
<span class="color-off-black">Enterprise Edition {{appMeta.enterpriseLatest}}</span>&nbsp;&nbsp;&nbsp;
<a href="https://storage.googleapis.com/documize/downloads/documize-enterprise-windows-amd64.exe" class="font-weight-bold color-blue">Windows</a>&nbsp;&middot;
<a href="https://storage.googleapis.com/documize/downloads/documize-enterprise-linux-amd64" class="font-weight-bold color-blue">Linux</a>&nbsp;&middot;
<a href="https://storage.googleapis.com/documize/downloads/documize-enterprise-darwin-amd64" class="font-weight-bold color-blue">macOS</a>&nbsp;
</p>
<div class="my-5" />
{{{changelog}}}
</div>
</div>

View file

@ -55,12 +55,22 @@
<div class="col col-6 col-md-3"> <div class="col col-6 col-md-3">
<div class="top-bar"> <div class="top-bar">
<div class="buttons d-flex flex-wrap align-items-center"> <div class="buttons d-flex flex-wrap align-items-center">
{{#unless appMeta.valid}}
<div class="btn-group">
<div class="button-icon-gold animated infinite wobble slow delay-2s"
data-toggle="tooltip" data-placement="bottom" title="Please select product plan"
{{action 'onBilling'}}>
<i class="material-icons">report</i>
</div>
</div>
<div class="button-icon-gap" />
{{/unless}}
<div class="btn-group"> <div class="btn-group">
{{#link-to "search" class="button-icon-white" }} {{#link-to "search" class="button-icon-white" }}
<i class="material-icons">search</i> <i class="material-icons">search</i>
{{/link-to}} {{/link-to}}
</div> </div>
{{#if session.authenticated}} {{#if session.authenticated}}
{{#if hasPins}} {{#if hasPins}}
<div class="button-icon-gap" /> <div class="button-icon-gap" />
@ -100,14 +110,17 @@
</div> </div>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="profile-button"> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="profile-button">
{{#if session.isAdmin}} {{#if session.isAdmin}}
{{#link-to 'customize.general' class="dropdown-item" }}Settings{{/link-to}} {{#link-to 'customize.general' class="dropdown-item"}}Settings{{/link-to}}
{{#unless appMeta.valid}}
{{#link-to 'customize.billing' class="dropdown-item font-weight-bold color-red"}}Update Billing{{/link-to}}
{{/unless}}
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
{{/if}} {{/if}}
{{#link-to 'profile' class="dropdown-item" }}Profile{{/link-to}} {{#link-to 'profile' class="dropdown-item" }}Profile{{/link-to}}
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
{{#if session.isGlobalAdmin}} {{#if session.isGlobalAdmin}}
{{#if appMeta.updateAvailable}} {{#if appMeta.updateAvailable}}
{{#link-to 'customize.license' class="dropdown-item font-weight-bold color-orange" }}Update available{{/link-to}} {{#link-to 'customize.product' class="dropdown-item font-weight-bold color-orange" }}Update available{{/link-to}}
{{/if}} {{/if}}
{{/if}} {{/if}}
<a href="#" class="dropdown-item {{if hasWhatsNew 'color-whats-new font-weight-bold'}}" {{action 'onShowWhatsNewModal'}}>What's New</a> <a href="#" class="dropdown-item {{if hasWhatsNew 'color-whats-new font-weight-bold'}}" {{action 'onShowWhatsNewModal'}}>What's New</a>