` this repository
+* change into the new directory
+* `npm install`
+* `bower install`
+
+## Running / Development
+
+* `ember server`
+* Visit your app at [http://localhost:4200](http://localhost:4200).
+
+### Code Generators
+
+Make use of the many generators for code, try `ember help generate` for more details
+
+### Running Tests
+
+* `ember test`
+* `ember test --server`
+
+### Building
+
+* `ember build` (development)
+* `ember build --environment production` (production)
+
+### Deploying
+
+Specify what it takes to deploy your app.
+
+## Further Reading / Useful Links
+
+* [ember.js](http://emberjs.com/)
+* [ember-cli](http://www.ember-cli.com/)
+* Development Browser Extensions
+* [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
+* [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/)
+
+Install Bootstrap
+ bower install bootstrap --save
+Afterwards add following two lines to your ember-cli-build.js
+ app.import(app.bowerDirectory + '/bootstrap/dist/js/bootstrap.js');
+ app.import(app.bowerDirectory + '/bootstrap/dist/css/bootstrap.css');
+
+Install Moment
+ ember install ember-moment
+Install Colorbox
+ bower install jquery-colorbox --save
+ app.import(app.bowerDirectory + '/jquery-colorbox/jquery.colorbox-min.js');
+
+Install Bootbox
+ bower install bootbox --save
+Afterwards add following two lines to your ember-cli-build.js
+ app.import(app.bowerDirectory + '/bootstrap/dist/js/bootstrap.js');
+ app.import(app.bowerDirectory + '/bootstrap/dist/css/bootstrap.css');
+
+Install validate
+ bower install validate --save
+
+Install ember-select-2
+ ember install ember-select-2
+
+Install js-cookie
+ bower install js-cookie --save
+ app.import(app.bowerDirectory + '/js-cookie/src/js.cookie.js');
+
+Install jQuery-Storage-API
+ bower install jQuery-Storage-API --save
+ app.import(app.bowerDirectory + '/jquery-storage-api/jquery.storageapi.min.js');
+
+Install Font Awesome
+ bower install font-awesome --save
+ app.import(app.bowerDirectory + '/font-awesome/css/font-awesome.min.css');
+
+npm install broccoli-funnel --save-dev
+
+npm install valid-url --save-dev
+
+Install Bootstrap Color Picker
+ bower install bootstrap-colorpicker --save
+
+Install Route Action Helper
+ ember install ember-route-action-helper
+
+Install EmberX Select
+ ember install emberx-select
+
+Install fuelux
+bower install fuelux --save
+
+This is an example for using the npm package dexie within an Ember CLI app.
+
+Install browserify: npm install ember-browserify --save-dev
+
+Install dexie (or whatever module you need): npm install dexie --save-dev
+
+Import the module like this: import Dexie from 'npm:dexie';
+
+Install JQuery HotKeys
+ bower install jquery.hotkeys
+
+Install Bootstrap WYSIWYG
+ bower install bootstrap-wysiwyg
+
+bower install bootstrap-treeview
\ No newline at end of file
diff --git a/web/app/app.js b/web/app/app.js
new file mode 100644
index 0000000..62f00d1
--- /dev/null
+++ b/web/app/app.js
@@ -0,0 +1,25 @@
+import Ember from 'ember';
+import Resolver from './resolver';
+import loadInitializers from 'ember-load-initializers';
+import config from './config/environment';
+
+let App;
+
+// Ember.MODEL_FACTORY_INJECTIONS = true;
+
+App = Ember.Application.extend({
+ modulePrefix: config.modulePrefix,
+ podModulePrefix: config.podModulePrefix,
+ Resolver
+});
+
+if (config.environment === 'production') {
+ Ember.$.ajaxSetup({
+ beforeSend(jqXHR, opt) {
+ opt.url = '/api/' + opt.url;
+ }
+ });
+}
+loadInitializers(App, config.modulePrefix);
+
+export default App;
diff --git a/web/app/components/ace-login.js b/web/app/components/ace-login.js
new file mode 100644
index 0000000..59746e2
--- /dev/null
+++ b/web/app/components/ace-login.js
@@ -0,0 +1,57 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['container-fluid'],
+ errors: {},
+ model: {
+ rememberMe: false
+ },
+ constraints: {
+ loginId: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ password: {
+ presence: true,
+ length: {
+ minimum: 4
+ }
+ }
+ },
+ didInsertElement() {
+ let me = this;
+ Ember.$('body').removeClass().addClass('login-layout blur-login');
+ },
+ willDestroy() {
+ Ember.$('body').removeClass('login-layout blur-login').addClass('no-skin');
+ },
+ actions: {
+ login() {
+ let me = this;
+ me.validate() || me.get('onLogin')(me.get('model'));
+ },
+ loginIdInsertNewline(loginId) {
+ Ember.Logger.info('Login Id Insert Newline', loginId);
+ this.send('login');
+ },
+ loginIdKeyPress(loginId) {
+ loginId && this.set('errors.loginId', null);
+ },
+ passwordInsertNewline(password) {
+ // Ember.Logger.info('Password Insert Newline', password);
+ this.send('login');
+ },
+ passwordKeyPress(password) {
+ password && this.set('errors.password', null);
+ },
+ },
+ validate() {
+ let me = this;
+ let vr = validate(me.get('model'), me.get('constraints'));
+ vr && me.set('errors', vr);
+ return vr;
+ }
+});
diff --git a/web/app/components/app/app-manage.js b/web/app/components/app/app-manage.js
new file mode 100644
index 0000000..bad856a
--- /dev/null
+++ b/web/app/components/app/app-manage.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ page: 1
+});
diff --git a/web/app/components/app/manage-sidebar.js b/web/app/components/app/manage-sidebar.js
new file mode 100644
index 0000000..2b223a9
--- /dev/null
+++ b/web/app/components/app/manage-sidebar.js
@@ -0,0 +1,33 @@
+import Ember from 'ember';
+
+import BaseComponent from '../base-component';
+
+export default BaseComponent.extend({
+ classNames: ['sidebar'],
+ didReceiveAttrs() {
+ let me = this;
+ if (!me.get('appId')) {
+ let routeName = me.get('routeName');
+ let parentRouteName = null;
+ let appId = null;
+ while (parentRouteName !== routeName) {
+ appId = me.getRouteParams(routeName).appId;
+ if (appId) {
+ Ember.Logger.info(`App Id [${appId}] Found In Route [${routeName}]`);
+ break;
+ }
+ if (!parentRouteName) {
+ parentRouteName = me.getParentRouteName(routeName);
+ }
+ routeName = parentRouteName;
+ parentRouteName = me.getParentRouteName(routeName);
+ }
+ if (appId) {
+ me.set('appId', appId);
+ }
+ else {
+ Ember.Logger.error('No App Id');
+ }
+ }
+ }
+});
diff --git a/web/app/components/base-component.js b/web/app/components/base-component.js
new file mode 100644
index 0000000..87a0d74
--- /dev/null
+++ b/web/app/components/base-component.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+import BaseComponentMixin from '../mixins/components/base-component';
+
+export default Ember.Component.extend(BaseComponentMixin, {});
diff --git a/web/app/components/base-form-input.js b/web/app/components/base-form-input.js
new file mode 100644
index 0000000..69cd91b
--- /dev/null
+++ b/web/app/components/base-form-input.js
@@ -0,0 +1,17 @@
+import Ember from 'ember';
+import BaseComponent from './base-component';
+
+export default BaseComponent.extend({
+ classNameBindings: ['hasError:has-error'],
+ model: Ember.computed.alias('route.controller.model'),
+ errors: Ember.computed.alias('route.controller.errors'),
+ hasError: Ember.computed('errors', function() {
+ return this.get('errors.' + this.get('name'));
+ }),
+ getVal() {
+ return this.get('model.' + this.get('name'));
+ },
+ setVal(val) {
+ this.set('model.' + this.get('name'), val);
+ }
+});
diff --git a/web/app/components/breadcrumbs-bar.js b/web/app/components/breadcrumbs-bar.js
new file mode 100644
index 0000000..6b6671a
--- /dev/null
+++ b/web/app/components/breadcrumbs-bar.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['breadcrumbs']
+});
diff --git a/web/app/components/date-cell.js b/web/app/components/date-cell.js
new file mode 100644
index 0000000..e815f7a
--- /dev/null
+++ b/web/app/components/date-cell.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ tagName: 'span'
+});
diff --git a/web/app/components/editable-cell.js b/web/app/components/editable-cell.js
new file mode 100644
index 0000000..c5eec5d
--- /dev/null
+++ b/web/app/components/editable-cell.js
@@ -0,0 +1,72 @@
+import Ember from 'ember';
+import BaseComponent from './base-component';
+
+export default BaseComponent.extend({
+ allowBlank: true,
+ actions: {
+ doEdit() {
+ var me = this;
+ me.set('oldValue', me.getFieldValue());
+ me.set('isEditing', true)
+ Ember.run.later(() => {
+ Ember.$('input[type="text"][name="' + me.get('model.id') + '"]').focus();
+ }, 128);
+ },
+ doUpdate() {
+ let me = this;
+ if (me.get('isUpdating')) {
+ Ember.Logger.info('Cell Is Updating, Ignore.');
+ return;
+ }
+ me.set('isUpdating', true);
+ let newValue = me.getFieldValue();
+ if (me.get('oldValue') !== newValue) {
+ if (!me.get('allowBlank') && !newValue) {
+ me.get('message').warn('属性不能为空');
+ // reset field value
+ me.resetValue();
+ me.set('isUpdating', false);
+ }
+ else {
+ let service = me.get('service');
+ let model = me.get('model');
+ let vr = service.updateValidate(model);
+ if (vr) {
+ Ember.Logger.info('Validate Result: ', vr);
+ me.get('message').warn(Object.keys(vr).map((e)=> {
+ return vr[e];
+ }).reduce((msg, e)=> {
+ return (msg ? msg + ' ' : '') + e.join(' ');
+ }, ''));
+ // reset field value
+ me.resetValue();
+ me.set('isUpdating', false);
+ }
+ else {
+ me.dialog.confirm('确认要更新吗?', () => {
+ service.update(model, true);
+ me.set('isUpdating', false);
+ },
+ () => {
+ // reset field value
+ me.resetValue();
+ me.set('isUpdating', false);
+ });
+ }
+ }
+ }
+ else {
+ Ember.Logger.info('Field Value Not Changed.')
+ me.set('isUpdating', false);
+ }
+ me.set('isEditing', false);
+ }
+ },
+ getFieldValue() {
+ return this.get('model.' + this.get('field'));
+ },
+ resetValue() {
+ let me = this;
+ me.set('model.' + me.get('field'), me.get('oldValue'));
+ }
+});
diff --git a/web/app/components/form-content.js b/web/app/components/form-content.js
new file mode 100644
index 0000000..7b9fd51
--- /dev/null
+++ b/web/app/components/form-content.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['page-content']
+});
diff --git a/web/app/components/form-footer-buttons.js b/web/app/components/form-footer-buttons.js
new file mode 100644
index 0000000..2bb94c6
--- /dev/null
+++ b/web/app/components/form-footer-buttons.js
@@ -0,0 +1,90 @@
+import Ember from 'ember';
+import BaseComponent from './base-component';
+
+export default BaseComponent.extend({
+ classNames: ['form-actions', 'center', 'no-margin-bottom'],
+ type: 'create',
+ form: true,
+ didReceiveAttrs() {
+ const me = this;
+ let backRouteName = me.get('backRouteName');
+ if (Ember.isNone(backRouteName)) {
+ let listRouteName = me.get('routeName').replace(/[^.]+$/, 'list');
+ // find route
+ if (!me.getRoute(listRouteName)) {
+ // no list route found, find parent
+ listRouteName = listRouteName.replace(/[^.]+\.[^.]+$/, 'list');
+ }
+ me.set('backRouteName', listRouteName);
+ // list route params
+ Ember.isNone(me.get('backRouteParams'))
+ && me.set('backRouteParams', 1);
+ }
+ },
+ actions: {
+ goback() {
+ let me = this;
+ let router = me.get('router');
+ let routeName = me.get('backRouteName');
+ let routeParams = me.get('backRouteParams');
+ let queryParams = me.get('backRouteQueryParams');
+ let params = [routeName];
+ if (!Ember.isNone(routeParams)) {
+ if (Ember.isArray(routeParams)) {
+ params = params.concat(routeParams);
+ }
+ else if (routeParams !== false) {
+ params.push(routeParams);
+ }
+ }
+ Ember.isNone(queryParams) ||
+ params.push({queryParams: queryParams});
+ router.transitionTo(...params);
+ },
+ save() {
+ let me = this;
+ if (!me.validate()) {
+ me.dialog.confirm('确认要提交吗?', () => {
+ me.postData().then((m) => {
+ Ember.Logger.info('Post Model Result: ', m);
+ // write back
+ // TODO write update back
+ Ember.setProperties(me.getModel(), m);
+ me.alertMessage();
+ me.send('goback');
+ });
+ });
+ }
+ }
+ },
+ isCreate() {
+ return this.get('type') === 'create';
+ },
+ validate() {
+ let me = this;
+ let vr = me.get('service').validate(
+ me.getModel(), me.get('type') + 'Constraints');
+ me.set('route.controller.errors', vr || {});
+ return vr;
+ },
+ postData() {
+ let me = this;
+ let data = me.get('form') ?
+ new FormData(me.$().closest('form')[0]) :
+ me.getModel();
+ let postUrl = me.get('postUrl');
+ if (postUrl) {
+ return me.get('store').ajaxPost(postUrl, data);
+ }
+ let service = me.get('service');
+ return me.isCreate() ? service.create(data) : service.update(data);
+ },
+ alertMessage() {
+ let me = this;
+ me.message.alert(me.get('sucessMsg') ||
+ (me.isCreate() ? '创建成功' : '更新成功'));
+ },
+ getModel() {
+ return this.get('route.controller.model');
+ }
+});
diff --git a/web/app/components/form-input-checkbox.js b/web/app/components/form-input-checkbox.js
new file mode 100644
index 0000000..16e1a7a
--- /dev/null
+++ b/web/app/components/form-input-checkbox.js
@@ -0,0 +1,13 @@
+import Ember from 'ember';
+import BaseFormInput from './base-form-input';
+
+export default BaseFormInput.extend({
+ label: '状态',
+ name: 'enabled',
+ classNames: ['form-group'],
+ didReceiveAttrs() {
+ let me = this;
+ me._super(...arguments);
+ Ember.isNone(me.getVal()) && me.setVal(false);
+ }
+});
diff --git a/web/app/components/form-input-color.js b/web/app/components/form-input-color.js
new file mode 100644
index 0000000..f849b5b
--- /dev/null
+++ b/web/app/components/form-input-color.js
@@ -0,0 +1,82 @@
+import Ember from 'ember';
+import BaseFormInput from './base-form-input';
+
+export default BaseFormInput.extend({
+ classNames: ['form-group'],
+ didReceiveAttrs() {
+ let me = this;
+ me._super(...arguments);
+
+ Ember.addObserver(me, me.getFieldPath(), me, 'colorChanged');
+ me.colorChanged();
+ },
+ didInsertElement() {
+ let me = this;
+ me._super(...arguments);
+ me.getInputEl().colorpicker({format: 'rgba'}).on('changeColor', function(e) {
+ if (!me.get('lockColor')) {
+ me.set(me.getFieldPath(), e.color.toString());
+ }
+ });
+ },
+ colorChanged() {
+ let me = this;
+ let color = me.get(me.getFieldPath());
+ if (!me.get('lockColor')) {
+ me.set('lockHexColor', true);
+ me.set('hexColor', me.rgbaStr2hex(color));
+ me.set('lockHexColor', false);
+ }
+ let el = me.getInputEl();
+ if (el) {
+ me.set('lockColor', true);
+ el.colorpicker('setValue', color);
+ me.set('lockColor', false);
+ }
+ },
+ hexColorObserver: Ember.observer('hexColor', function() {
+ let me = this;
+ if (!me.get('lockHexColor')) {
+ let hexColor = me.get('hexColor');
+ if (hexColor && (hexColor = hexColor.trim())) {
+ let rgb = me.hexToRgb(hexColor);
+ if (rgb) {
+ Ember.Logger.info('Hex Color Changed.', rgb);
+ me.set('lockColor', true);
+ me.set(me.getFieldPath(), `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 1)`);
+ me.set('lockColor', false);
+ }
+ }
+ }
+ }),
+ getFieldPath() {
+ return 'model.' + this.get('name');
+ },
+ getInputEl() {
+ return this.$('.colorpicker-component');
+ },
+ rgbaRegex: /\s*rgba\s*\(\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*(0(?:\.\d+)?|1(?:\.0+)?)\s*\)\s*/i,
+ rgbaStr2hex(rgba) {
+ let me = this;
+ if (rgba) {
+ let m = rgba.match(me.rgbaRegex);
+ return me.rgb2hex(m[1], m[2], m[3]);
+ }
+ },
+ rgb2hex(red, green, blue) {
+ return '#' + (0x1000000 + (blue | (green << 8) | (red << 16))).toString(16).slice(1);
+ },
+ hexToRgb(hex) {
+ // #rgb -> #rrggbb
+ hex = hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, function(m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+
+ let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ } : null;
+ }
+});
diff --git a/web/app/components/form-input-errors-msg.js b/web/app/components/form-input-errors-msg.js
new file mode 100644
index 0000000..590fc4c
--- /dev/null
+++ b/web/app/components/form-input-errors-msg.js
@@ -0,0 +1,6 @@
+import Ember from 'ember';
+import BaseFormInput from './base-form-input';
+
+export default BaseFormInput.extend({
+ classNames: ['inline']
+});
diff --git a/web/app/components/form-input-modal-select.js b/web/app/components/form-input-modal-select.js
new file mode 100644
index 0000000..0b8194a
--- /dev/null
+++ b/web/app/components/form-input-modal-select.js
@@ -0,0 +1,12 @@
+import Ember from 'ember';
+import BaseFormInput from './base-form-input';
+
+export default BaseFormInput.extend({
+ classNames: ['form-group'],
+ classNameBindings: ['hasError:has-error'],
+ hasError: Ember.computed('route.controller.errors', function() {
+ return this.get('errors.' + this.get('idField'));
+ }),
+ btnIcon: 'fa-server',
+ isFaBtnIcon: Ember.computed.match('btnIcon', /^fa-/)
+});
diff --git a/web/app/components/form-input-select.js b/web/app/components/form-input-select.js
new file mode 100644
index 0000000..0a89b0f
--- /dev/null
+++ b/web/app/components/form-input-select.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseFormInput from './base-form-input';
+
+export default BaseFormInput.extend({
+ classNames: ['form-group'],
+ classNameBindings: ['hasError:has-error'],
+ colWidth: 6
+});
diff --git a/web/app/components/form-input-spinner.js b/web/app/components/form-input-spinner.js
new file mode 100644
index 0000000..6009ea3
--- /dev/null
+++ b/web/app/components/form-input-spinner.js
@@ -0,0 +1,26 @@
+import Ember from 'ember';
+import BaseFormInput from './base-form-input';
+
+export default BaseFormInput.extend({
+ classNames: ['form-group'],
+ min: 0,
+ max: 64,
+ step: 1,
+ didReceiveAttrs() {
+ this.getVal() || this.setVal(0);
+ },
+ didInsertElement() {
+ let me = this;
+ me.$('input[type=text]').ace_spinner({
+ value: me.getVal(),
+ min: me.get('min'),
+ max: me.get('max'),
+ step: me.get('step'),
+ btn_up_class: 'btn-info',
+ btn_down_class: 'btn-info'})
+ .closest('.ace-spinner')
+ .on('changed.fu.spinbox', function() {
+ me.setVal(me.$('input[type=text]').val());
+ });
+ }
+});
diff --git a/web/app/components/form-input.js b/web/app/components/form-input.js
new file mode 100644
index 0000000..fa97f35
--- /dev/null
+++ b/web/app/components/form-input.js
@@ -0,0 +1,45 @@
+import Ember from 'ember';
+import BaseFormInput from './base-form-input';
+
+export default BaseFormInput.extend({
+ classNames: ['form-group'],
+ type: 'text',
+ setFilename(filename) {
+ let me = this;
+ Ember.set(me.get('model'), me.get('name'), filename);
+ },
+ didReceiveAttrs() {
+ let me = this;
+ let isFile = me.get('type') === 'file';
+ !me.get('inputClass') &&
+ me.set('inputClass', isFile ? 'col-xs-3' : 'col-xs-4');
+ let image = me.get('image');
+ if (isFile && image) {
+ me.set('imageUrl', me.get('model.' + image));
+ }
+ },
+ didInsertElement() {
+ let me = this;
+ me.get('type') === 'file' &&
+ me.$('input[type=file]').ace_file_input({
+ no_file: '没有选择文件...',
+ btn_choose: '选择',
+ btn_change: '更换',
+ droppable: true,
+ before_change: function() {
+ let filename = Ember.$(this).val();
+ Ember.Logger.info('Before File [' + filename + '] Changed.');
+ me.setFilename(filename);
+ return true;
+ },
+ before_remove: function() {
+ let filename = Ember.$(this).val();
+ Ember.Logger.info('Before File [' + filename + '] Removed.');
+ me.setFilename(null);
+ return true;
+ },
+ thumbnail: false, //| true | large
+ blacklist: 'exe|php|jsp'
+ });
+ }
+});
diff --git a/web/app/components/gender-cell.js b/web/app/components/gender-cell.js
new file mode 100644
index 0000000..e815f7a
--- /dev/null
+++ b/web/app/components/gender-cell.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ tagName: 'span'
+});
diff --git a/web/app/components/grid-header.js b/web/app/components/grid-header.js
new file mode 100644
index 0000000..7a8566c
--- /dev/null
+++ b/web/app/components/grid-header.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['widget-header']
+});
diff --git a/web/app/components/image-previews.js b/web/app/components/image-previews.js
new file mode 100644
index 0000000..27022d5
--- /dev/null
+++ b/web/app/components/image-previews.js
@@ -0,0 +1,50 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ tagName: 'span',
+ classNames: ['inline'],
+ didReceiveAttrs() {
+ let me = this;
+ let previews = me.get('previews');
+ if (Ember.$.type(previews) === 'string') {
+ let sep = me.get('separator');
+ me.set('previews', sep ? previews.split(sep) : [previews]);
+ }
+ },
+ imageHeight: 22,
+ imageStyle: 'border-radius: 8%; border: 1px solid #DCDCDC; max-width: 32px;',
+ didInsertElement() {
+ let me = this;
+ let rel = me.get('elementId') + '_preview';
+ let $overflow = '';
+
+ me.$('a[data-rel="' + rel + '"]').colorbox({
+ rel: rel,
+ reposition: true,
+ // scalePhotos: true,
+ scrolling: false,
+ photo: true,
+ previous: ' ',
+ next: ' ',
+ close: '×',
+ current: '{current} of {total}',
+ maxWidth: '100%',
+ maxHeight: '100%',
+ onOpen: function() {
+ $overflow = document.body.style.overflow;
+ document.body.style.overflow = 'hidden';
+ },
+ onClosed: function() {
+ document.body.style.overflow = $overflow;
+ },
+ onComplete: function() {
+ Ember.$.colorbox.resize();
+ }
+ });
+
+ Ember.run.once(() => {
+ // add a custom loading icon
+ $('#cboxLoadingGraphic').html(' ');
+ });
+ }
+});
diff --git a/web/app/components/list-select-checkbox.js b/web/app/components/list-select-checkbox.js
new file mode 100644
index 0000000..2c4e824
--- /dev/null
+++ b/web/app/components/list-select-checkbox.js
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+import BaseComponentMixin from '../mixins/components/base-component';
+
+export default Ember.Component.extend(BaseComponentMixin, {
+ tagName: 'label',
+ selectedId: Ember.computed.alias('route.controller.selectedId'),
+ selectedModel: Ember.computed.alias('route.controller.selectedModel'),
+ classNames: ['pos-rel']
+});
diff --git a/web/app/components/main-container.js b/web/app/components/main-container.js
new file mode 100644
index 0000000..04bb492
--- /dev/null
+++ b/web/app/components/main-container.js
@@ -0,0 +1,430 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ elementId: 'main-container',
+ classNames: ['main-container'],
+ didInsertElement() {
+ let me = this;
+ // Ember.$('body').removeClass().addClass('login-layout blur-login');
+ (function($) {
+ basics();
+ enableSidebar();
+
+ enableDemoAjax();
+ handleScrollbars();
+
+ dropdownAutoPos();
+
+ navbarHelpers();
+ sidebarTooltips();
+
+ scrollTopBtn();
+
+ someBrowserFix();
+
+ bsCollapseToggle();
+ smallDeviceDropdowns();
+
+ ////////////////////////////
+
+ function basics() {
+ // for android and ios we don't use "top:auto" when breadcrumbs is fixed
+ if(ace.vars['non_auto_fixed']) {
+ $('body').addClass('mob-safari');
+ }
+
+ ace.vars['transition'] = !!$.support.transition.end
+ }
+
+ function enableSidebar() {
+ //initiate sidebar function
+ var $sidebar = $('.sidebar');
+ if($.fn.ace_sidebar) $sidebar.ace_sidebar();
+ if($.fn.ace_sidebar_scroll) $sidebar.ace_sidebar_scroll({
+ //for other options please see documentation
+ 'include_toggle': false || ace.vars['safari'] || ace.vars['ios_safari'] //true = include toggle button in the scrollbars
+ });
+ if($.fn.ace_sidebar_hover) $sidebar.ace_sidebar_hover({
+ 'sub_hover_delay': 750,
+ 'sub_scroll_style': 'no-track scroll-thin scroll-margin scroll-visible'
+ });
+ }
+
+
+ //Load content via ajax
+ function enableDemoAjax() {
+ if(!$.fn.ace_ajax) return;
+
+ if(window.Pace) {
+ window.paceOptions = {
+ ajax: true,
+ document: true,
+ eventLag: false // disabled
+ //elements: {selectors: ['.page-content-area']}
+ }
+ }
+
+ var demo_ajax_options = {
+ 'close_active': true,
+
+ 'default_url': 'page/index',//default hash
+ 'content_url': function(hash) {
+ //***NOTE***
+ //this is for Ace demo only, you should change it to return a valid URL
+ //please refer to documentation for more info
+
+ if( !hash.match(/^page\//) ) return false;
+ var path = document.location.pathname;
+
+ //for example in Ace HTML demo version we convert /ajax/index.html#page/gallery to > /ajax/content/gallery.html and load it
+ if(path.match(/(\/ajax\/)(index\.html)?/))
+ return path.replace(/(\/ajax\/)(index\.html)?/, '/ajax/content/'+hash.replace(/^page\//, '')+'.html') ;
+
+ //for example in Ace PHP demo version we convert "ajax.php#page/dashboard" to "ajax.php?page=dashboard" and load it
+ return path + "?" + hash.replace(/\//, "=");
+ }
+ }
+
+ //for IE9 and below we exclude PACE loader (using conditional IE comments)
+ //for other browsers we use the following extra ajax loader options
+ if(window.Pace) {
+ demo_ajax_options['loading_overlay'] = 'body';//the opaque overlay is applied to 'body'
+ }
+
+ //initiate ajax loading on this element( which is .page-content-area[data-ajax-content=true] in Ace's demo)
+ $('[data-ajax-content=true]').ace_ajax(demo_ajax_options)
+
+ //if general error happens and ajax is working, let's stop loading icon & PACE
+ $(window).on('error.ace_ajax', function() {
+ $('[data-ajax-content=true]').each(function() {
+ var $this = $(this);
+ if( $this.ace_ajax('working') ) {
+ if(window.Pace && Pace.running) Pace.stop();
+ $this.ace_ajax('stopLoading', true);
+ }
+ })
+ })
+ }
+
+ /////////////////////////////
+
+ function handleScrollbars() {
+ //add scrollbars for navbar dropdowns
+ var has_scroll = !!$.fn.ace_scroll;
+ if(has_scroll) $('.dropdown-content').ace_scroll({reset: false, mouseWheelLock: true})
+
+ //reset scrolls bars on window resize
+ if(has_scroll && !ace.vars['old_ie']) {//IE has an issue with widget fullscreen on ajax?!!!
+ $(window).on('resize.reset_scroll', function() {
+ $('.ace-scroll:not(.scroll-disabled)').not(':hidden').ace_scroll('reset');
+ });
+ if(has_scroll) $(document).on('settings.ace.reset_scroll', function(e, name) {
+ if(name == 'sidebar_collapsed') $('.ace-scroll:not(.scroll-disabled)').not(':hidden').ace_scroll('reset');
+ });
+ }
+ }
+
+
+ function dropdownAutoPos() {
+ //change a dropdown to "dropup" depending on its position
+ $(document).on('click.dropdown.pos', '.dropdown-toggle[data-position="auto"]', function() {
+ var offset = $(this).offset();
+ var parent = $(this.parentNode);
+
+ if ( parseInt(offset.top + $(this).height()) + 50
+ >
+ (ace.helper.scrollTop() + ace.helper.winHeight() - parent.find('.dropdown-menu').eq(0).height())
+ ) parent.addClass('dropup');
+ else parent.removeClass('dropup');
+ });
+ }
+
+
+ function navbarHelpers() {
+ //prevent dropdowns from hiding when a from is clicked
+ /**$(document).on('click', '.dropdown-navbar form', function(e){
+ e.stopPropagation();
+ });*/
+
+
+ //disable navbar icon animation upon click
+ $('.ace-nav [class*="icon-animated-"]').closest('a').one('click', function(){
+ var icon = $(this).find('[class*="icon-animated-"]').eq(0);
+ var $match = icon.attr('class').match(/icon\-animated\-([\d\w]+)/);
+ icon.removeClass($match[0]);
+ });
+
+
+ //prevent dropdowns from hiding when a tab is selected
+ $(document).on('click', '.dropdown-navbar .nav-tabs', function(e){
+ e.stopPropagation();
+ var $this , href
+ var that = e.target
+ if( ($this = $(e.target).closest('[data-toggle=tab]')) && $this.length > 0) {
+ $this.tab('show');
+ e.preventDefault();
+ $(window).triggerHandler('resize.navbar.dropdown')
+ }
+ });
+ }
+
+
+ function sidebarTooltips() {
+ //tooltip in sidebar items
+ $('.sidebar .nav-list .badge[title],.sidebar .nav-list .badge[title]').each(function() {
+ var tooltip_class = $(this).attr('class').match(/tooltip\-(?:\w+)/);
+ tooltip_class = tooltip_class ? tooltip_class[0] : 'tooltip-error';
+ $(this).tooltip({
+ 'placement': function (context, source) {
+ var offset = $(source).offset();
+
+ if( parseInt(offset.left) < parseInt(document.body.scrollWidth / 2) ) return 'right';
+ return 'left';
+ },
+ container: 'body',
+ template: ''
+ });
+ });
+ /*
+ //or something like this if items are dynamically inserted
+ $('.sidebar').tooltip({
+ 'placement': function (context, source) {
+ let offset = $(source).offset();
+ return parseInt(offset.left) < parseInt(document.body.scrollWidth / 2) ? 'right' : 'left';
+ },
+ selector: '.nav-list .badge[title],.nav-list .label[title]',
+ container: 'body',
+ template: ''
+ });
+ */
+ }
+
+ function scrollTopBtn() {
+ //the scroll to top button
+ var scroll_btn = $('.btn-scroll-up');
+ if(scroll_btn.length > 0) {
+ var is_visible = false;
+ $(window).on('scroll.scroll_btn', function() {
+ var scroll = ace.helper.scrollTop();
+ var h = ace.helper.winHeight();
+ var body_sH = document.body.scrollHeight;
+ if(scroll > parseInt(h / 4) || (scroll > 0 && body_sH >= h && h + scroll >= body_sH - 1)) {//|| for smaller pages, when reached end of page
+ if(!is_visible) {
+ scroll_btn.addClass('display');
+ is_visible = true;
+ }
+ } else {
+ if(is_visible) {
+ scroll_btn.removeClass('display');
+ is_visible = false;
+ }
+ }
+ }).triggerHandler('scroll.scroll_btn');
+
+ scroll_btn.on(ace.click_event, function(){
+ var duration = Math.min(500, Math.max(100, parseInt(ace.helper.scrollTop() / 3)));
+ $('html,body').animate({scrollTop: 0}, duration);
+ return false;
+ });
+ }
+ }
+
+ function someBrowserFix() {
+ //chrome and webkit have a problem here when resizing from 479px to more
+ //we should force them redraw the navbar!
+ if( ace.vars['webkit'] ) {
+ var ace_nav = $('.ace-nav').get(0);
+ if( ace_nav ) $(window).on('resize.webkit_fix' , function(){
+ ace.helper.redraw(ace_nav);
+ });
+ }
+
+
+ //fix an issue with ios safari, when an element is fixed and an input receives focus
+ if(ace.vars['ios_safari']) {
+ $(document).on('ace.settings.ios_fix', function(e, event_name, event_val) {
+ if(event_name != 'navbar_fixed') return;
+
+ $(document).off('focus.ios_fix blur.ios_fix', 'input,textarea,.wysiwyg-editor');
+ if(event_val == true) {
+ $(document).on('focus.ios_fix', 'input,textarea,.wysiwyg-editor', function() {
+ $(window).on('scroll.ios_fix', function() {
+ var navbar = $('#navbar').get(0);
+ if(navbar) ace.helper.redraw(navbar);
+ });
+ }).on('blur.ios_fix', 'input,textarea,.wysiwyg-editor', function() {
+ $(window).off('scroll.ios_fix');
+ })
+ }
+ }).triggerHandler('ace.settings.ios_fix', ['navbar_fixed', $('#navbar').css('position') == 'fixed']);
+ }
+ }
+
+
+
+ function bsCollapseToggle() {
+ //bootstrap collapse component icon toggle
+ $(document).on('hide.bs.collapse show.bs.collapse', function (ev) {
+ var panel_id = ev.target.getAttribute('id')
+ var panel = $('a[href*="#'+ panel_id+'"]');
+ if(panel.length == 0) panel = $('a[data-target*="#'+ panel_id+'"]');
+ if(panel.length == 0) return;
+
+ panel.find(ace.vars['.icon']).each(function(){
+ var $icon = $(this)
+
+ var $match
+ var $icon_down = null
+ var $icon_up = null
+ if( ($icon_down = $icon.attr('data-icon-show')) ) {
+ $icon_up = $icon.attr('data-icon-hide')
+ }
+ else if( $match = $icon.attr('class').match(/fa\-(.*)\-(up|down)/) ) {
+ $icon_down = 'fa-'+$match[1]+'-down'
+ $icon_up = 'fa-'+$match[1]+'-up'
+ }
+
+ if($icon_down) {
+ if(ev.type == 'show') $icon.removeClass($icon_down).addClass($icon_up)
+ else $icon.removeClass($icon_up).addClass($icon_down)
+
+ return false;//ignore other icons that match, one is enough
+ }
+
+ });
+ })
+ }
+
+
+
+ //in small devices display navbar dropdowns like modal boxes
+ function smallDeviceDropdowns() {
+ if(ace.vars['old_ie']) return;
+
+ $('.ace-nav > li')
+ .on('shown.bs.dropdown.navbar', function(e) {
+ adjustNavbarDropdown.call(this);
+ })
+ .on('hidden.bs.dropdown.navbar', function(e) {
+ $(window).off('resize.navbar.dropdown');
+ resetNavbarDropdown.call(this);
+ })
+
+ function adjustNavbarDropdown() {
+ var $sub = $(this).find('> .dropdown-menu');
+
+ if( $sub.css('position') == 'fixed' ) {
+ var win_width = parseInt($(window).width());
+ var offset_w = win_width > 320 ? 60 : (win_width > 240 ? 40 : 30);
+ var avail_width = parseInt(win_width) - offset_w;
+ var avail_height = parseInt($(window).height()) - 30;
+
+ var width = parseInt(Math.min(avail_width , 320));
+ //we set 'width' here for text wrappings and spacings to take effect before calculating scrollHeight
+ $sub.css('width', width);
+
+ var tabbed = false;
+ var extra_parts = 0;
+ var dropdown_content = $sub.find('.tab-pane.active .dropdown-content.ace-scroll');
+ if(dropdown_content.length == 0) dropdown_content = $sub.find('.dropdown-content.ace-scroll');
+ else tabbed = true;
+
+ var parent_menu = dropdown_content.closest('.dropdown-menu');
+ var scrollHeight = $sub[0].scrollHeight;
+ if(dropdown_content.length == 1) {
+ //sometimes there's no scroll-content, for example in detached scrollbars
+ var content = dropdown_content.find('.scroll-content')[0];
+ if(content) {
+ scrollHeight = content.scrollHeight;
+ }
+
+ extra_parts += parent_menu.find('.dropdown-header').outerHeight();
+ extra_parts += parent_menu.find('.dropdown-footer').outerHeight();
+
+ var tab_content = parent_menu.closest('.tab-content');
+ if( tab_content.length != 0 ) {
+ extra_parts += tab_content.siblings('.nav-tabs').eq(0).height();
+ }
+ }
+
+
+
+ var height = parseInt(Math.min(avail_height , 480, scrollHeight + extra_parts));
+ var left = parseInt(Math.abs((avail_width + offset_w - width)/2));
+ var top = parseInt(Math.abs((avail_height + 30 - height)/2));
+
+
+ var zindex = parseInt($sub.css('z-index')) || 0;
+
+ $sub.css({'height': height, 'left': left, 'right': 'auto', 'top': top - (!tabbed ? 1 : 3)});
+ if(dropdown_content.length == 1) {
+ if(!ace.vars['touch']) {
+ dropdown_content.ace_scroll('update', {size: height - extra_parts}).ace_scroll('enable').ace_scroll('reset');
+ }
+ else {
+ dropdown_content
+ .ace_scroll('disable').css('max-height', height - extra_parts).addClass('overflow-scroll');
+ }
+ }
+ $sub.css('height', height + (!tabbed ? 2 : 7));//for bottom border adjustment and tab content paddings
+
+
+ if($sub.hasClass('user-menu')) {
+ $sub.css('height', '');//because of user-info hiding/showing at different widths, which changes above 'scrollHeight', so we remove it!
+
+ //user menu is re-positioned in small widths
+ //but we need to re-position again in small heights as well (modal mode)
+ var user_info = $(this).find('.user-info');
+ if(user_info.length == 1 && user_info.css('position') == 'fixed') {
+ user_info.css({'left': left, 'right': 'auto', 'top': top, 'width': width - 2, 'max-width': width - 2, 'z-index': zindex + 1});
+ }
+ else user_info.css({'left': '', 'right': '', 'top': '', 'width': '', 'max-width': '', 'z-index': ''});
+ }
+
+ //dropdown's z-index is limited by parent .navbar's z-index (which doesn't make sense because dropdowns are fixed!)
+ //so for example when in 'content-slider' page, fixed modal toggle buttons go above are dropdowns
+ //so we increase navbar's z-index to fix this!
+ $(this).closest('.navbar.navbar-fixed-top').css('z-index', zindex);
+ }
+ else {
+ if($sub.length != 0) resetNavbarDropdown.call(this, $sub);
+ }
+
+ var self = this;
+ $(window)
+ .off('resize.navbar.dropdown')
+ .one('resize.navbar.dropdown', function() {
+ $(self).triggerHandler('shown.bs.dropdown.navbar');
+ })
+ }
+
+ //reset scrollbars and user menu
+ function resetNavbarDropdown($sub) {
+ $sub = $sub || $(this).find('> .dropdown-menu');
+
+ if($sub.length > 0) {
+ $sub
+ .css({'width': '', 'height': '', 'left': '', 'right': '', 'top': ''})
+ .find('.dropdown-content').each(function() {
+ if(ace.vars['touch']) {
+ $(this).css('max-height', '').removeClass('overflow-scroll');
+ }
+
+ var size = parseInt($(this).attr('data-size') || 0) || $.fn.ace_scroll.defaults.size;
+ $(this).ace_scroll('update', {size: size}).ace_scroll('enable').ace_scroll('reset');
+ })
+
+ if( $sub.hasClass('user-menu') ) {
+ var user_info =
+ $(this).find('.user-info')
+ .css({'left': '', 'right': '', 'top': '', 'width': '', 'max-width': '', 'z-index': ''});
+ }
+ }
+
+ $(this).closest('.navbar').css('z-index', '');
+ }
+ }
+
+ })(Ember.$); //jQuery document ready
+ },
+});
diff --git a/web/app/components/main-content.js b/web/app/components/main-content.js
new file mode 100644
index 0000000..dd1a7b8
--- /dev/null
+++ b/web/app/components/main-content.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['main-content']
+});
diff --git a/web/app/components/modal-dialog.js b/web/app/components/modal-dialog.js
new file mode 100644
index 0000000..6e705e6
--- /dev/null
+++ b/web/app/components/modal-dialog.js
@@ -0,0 +1,3 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({});
diff --git a/web/app/components/modal-frame.js b/web/app/components/modal-frame.js
new file mode 100644
index 0000000..5b4a4a4
--- /dev/null
+++ b/web/app/components/modal-frame.js
@@ -0,0 +1,24 @@
+import Ember from 'ember';
+import BaseComponent from './base-component';
+
+export default BaseComponent.extend({
+ classNames: ['modal', 'fade'],
+ initModal: true,
+ transitionToParentRouteAfterClose: true,
+ didInsertElement() {
+ let me = this;
+ if (me.get('initModal')) {
+ me.$().modal().on('hidden.bs.modal', ()=> {
+ me.$() && me.get('transitionToParentRouteAfterClose') &&
+ me.get('router').transitionTo(
+ me.get('parentRouteName') ||
+ me.get('routeName').replace(/\.[^.]+$/, ''));
+ let onClose = me.get('onClose');
+ onClose && onClose();
+ });
+ }
+ },
+ willDestroyElement() {
+ this.$().modal('hide');
+ }
+});
diff --git a/web/app/components/modal-list-select.js b/web/app/components/modal-list-select.js
new file mode 100644
index 0000000..926b613
--- /dev/null
+++ b/web/app/components/modal-list-select.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
diff --git a/web/app/components/op-detail.js b/web/app/components/op-detail.js
new file mode 100644
index 0000000..964a77c
--- /dev/null
+++ b/web/app/components/op-detail.js
@@ -0,0 +1,18 @@
+import Ember from 'ember';
+import BaseComponentMixin from '../mixins/components/base-component';
+
+export default Ember.LinkComponent.extend(BaseComponentMixin, {
+ classNames: ['btn', 'btn-xs', 'btn-info2'],
+ role: 'button',
+ rel: 'tooltip',
+ title: '操作详情',
+ activeClass: '',
+ willRender() {
+ let me = this;
+ let params = me.get('params');
+ params.unshift(me.get('service.modelName'));
+ params.unshift('op-detail');
+ params.unshift('操作详情');
+ me._super(...arguments);
+ }
+});
diff --git a/web/app/components/pagination-bar.js b/web/app/components/pagination-bar.js
new file mode 100644
index 0000000..18e0756
--- /dev/null
+++ b/web/app/components/pagination-bar.js
@@ -0,0 +1,43 @@
+import Ember from 'ember';
+import BaseComponent from './base-component';
+
+export default BaseComponent.extend({
+ classNames: ['widget-toolbox', 'clearfix'],
+ total: Ember.computed.alias('route.controller.model.total'),
+ prevPage: Ember.computed('currPage', function() {
+ return this.get('currPage') - 1 || 1;
+ }),
+ nextPage: Ember.computed('currPage', function() {
+ let me = this;
+ let page = me.get('currPage');
+ return page + 1 <= me.get('totalPage') ? page + 1 : page;
+ }),
+ currPage: Ember.computed('params.page', function() {
+ let me = this;
+ let currPage = parseInt(me.get('params.page'));
+ Ember.Logger.info('Get Curr Page [' + currPage + ']');
+ return currPage;
+ }),
+ pages: Ember.computed('total', function() {
+ let i = 0;
+ let pages = [];
+ while (i++ < this.get('totalPage')) {
+ pages.push(i);
+ }
+ return pages;
+ }),
+ totalPage: Ember.computed('total', function() {
+ let me = this;
+ let pageSize = me.get('service.pageSize') || 16;
+ return parseInt((me.get('total') + pageSize - 1) / pageSize);
+ }),
+ actions: {
+ gotoPage(page) {
+ let me = this;
+ let router = me.get('router');
+ let params = me.get('params');
+ Ember.Logger.info('To Page [' + page + '], Params: ', params);
+ router.transitionTo(me.get('routeName'), page, {queryParams: params});
+ }
+ }
+});
diff --git a/web/app/components/qr-code.js b/web/app/components/qr-code.js
new file mode 100644
index 0000000..1f0610e
--- /dev/null
+++ b/web/app/components/qr-code.js
@@ -0,0 +1,78 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['btn-group'],
+ didReceiveAttrs() {
+ let me = this;
+ let iconUrl = me.get('iconUrl');
+ let iconImg;
+ if (iconUrl) {
+ iconImg = new Image();
+ iconImg.src = iconUrl;
+ me.set('iconImg', iconImg);
+ }
+ // let label = me.get('label');
+ let label = null;
+ me.set('qrConfigMerged', Ember.$.extend({
+ // render method: 'canvas', 'image' or 'div'
+ render: 'canvas',
+
+ // version range somewhere in 1 .. 40
+ minVersion: 1,
+ maxVersion: 40,
+
+ // error correction level: 'L', 'M', 'Q' or 'H'
+ ecLevel: 'Q',
+
+ // size in pixel
+ size: 320,
+
+ // code color or image element
+ fill: '#333',
+
+ // background color or image element, null for transparent background
+ background: null,
+
+ // content
+ text: me.get('text'),
+
+ // corner radius relative to module width: 0.0 .. 0.5
+ radius: 0.1,
+
+ // quiet zone in modules
+ quiet: 4,
+
+ // modes
+ // 0: normal
+ // 1: label strip
+ // 2: label box
+ // 3: image strip
+ // 4: image box
+ mode: iconUrl ? 4 : label ? 2 : 0,
+
+ label: label,
+ fontname: 'sans',
+ fontcolor: '#ff9818',
+
+ mSize: 0.13,
+ mPosX: 0.5,
+ mPosY: 0.5,
+ image: iconImg
+ }, me.get('qrConfig')));
+ },
+ didInsertElement() {
+ let me = this;
+ let iconImg = me.get('iconImg');
+ if (iconImg) {
+ iconImg.onload = function() {
+ me.renderQrCode();
+ };
+ }
+ else {
+ me.renderQrCode();
+ }
+ },
+ renderQrCode() {
+ this.$('.qr-code').qrcode(this.get('qrConfigMerged'));
+ }
+});
diff --git a/web/app/components/reload-btn.js b/web/app/components/reload-btn.js
new file mode 100644
index 0000000..2f7eb89
--- /dev/null
+++ b/web/app/components/reload-btn.js
@@ -0,0 +1,12 @@
+import Ember from 'ember';
+import BaseComponent from './base-component';
+
+export default BaseComponent.extend({
+ tagName: 'a',
+ attributeBindings: ['href', 'title'],
+ title: '刷新',
+ href: 'javascript:;',
+ click() {
+ this.get('route').refresh();
+ }
+});
diff --git a/web/app/components/search-box.js b/web/app/components/search-box.js
new file mode 100644
index 0000000..61eafe2
--- /dev/null
+++ b/web/app/components/search-box.js
@@ -0,0 +1,18 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['widget-toolbar', 'no-border'],
+ searchText: function() {
+ let me = this;
+ let routeName = me.get('router.currentRouteName');
+ return Ember.getOwner(me).lookup('route:' + routeName).paramsFor(routeName).search;
+ }.property('router.location'),
+ actions: {
+ search() {
+ let me = this;
+ let router = me.get('router');
+ let routeName = router.get('currentRouteName');
+ router.transitionTo(routeName, 1, {queryParams: {search: me.get('searchText')}});
+ }
+ }
+});
diff --git a/web/app/components/sortable-list-item.js b/web/app/components/sortable-list-item.js
new file mode 100644
index 0000000..2679646
--- /dev/null
+++ b/web/app/components/sortable-list-item.js
@@ -0,0 +1,33 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ tagName: 'li',
+ classNames: ['clearfix'],
+ classNameBindings: ['selected:selected'],
+ attributeBindings: ['itemId:data-item-id'],
+ selected: false,
+ index: 0,
+ didReceiveAttrs() {
+ let me = this;
+ me._super(...arguments);
+ let cc = me.get('colorClasses');
+ me.get('classNames').push(cc.objectAt(me.get('index') % cc.length));
+ },
+ colorClasses: [
+ 'item-orange',
+ 'item-orange2',
+ 'item-red',
+ 'item-red2',
+ 'item-green',
+ 'item-green2',
+ 'item-blue',
+ 'item-blue2',
+ 'item-blue3',
+ 'item-pink',
+ 'item-purple',
+ 'item-black',
+ 'item-grey',
+ 'item-brown',
+ 'item-default'
+ ],
+});
diff --git a/web/app/components/sortable-list.js b/web/app/components/sortable-list.js
new file mode 100644
index 0000000..b530352
--- /dev/null
+++ b/web/app/components/sortable-list.js
@@ -0,0 +1,39 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ tagName: 'ul',
+ classNames: ['item-list'],
+ didInsertElement() {
+ let me = this;
+ me.set('prevIds', me.get('model').mapBy('id'));
+ me.$().sortable({
+ opacity: 0.8,
+ revert: true,
+ forceHelperSize: true,
+ placeholder: 'draggable-placeholder',
+ forcePlaceholderSize: true,
+ tolerance: 'pointer',
+ stop: function (event, ui) {
+ // just for Chrome!!!! so that dropdowns on items don't appear below other items after being moved
+ $(ui.item).css('z-index', 'auto');
+
+ if (me.get('onSortStopped')) {
+ let prevIds = me.get('prevIds');
+ let changed = false;
+ let ids = Array.prototype.map.call(me.$('li'), (li, i) => {
+ let id = Ember.$(li).data('item-id');
+ if (id !== prevIds[i] && !changed) {
+ changed = true;
+ }
+ return id;
+ });
+ if (changed) {
+ me.set('prevIds', ids);
+ me.sendAction('onSortStopped', ids);
+ }
+ }
+ }
+ });
+ }
+});
+
diff --git a/web/app/components/status-cell.js b/web/app/components/status-cell.js
new file mode 100644
index 0000000..87f53e7
--- /dev/null
+++ b/web/app/components/status-cell.js
@@ -0,0 +1,23 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ tagName: 'span',
+ classNames: ['label', 'label-sm'],
+ classNameBindings: ['enabled:label-success:label-warning'],
+ field: 'enabled',
+ name: Ember.computed.alias('field'),
+ didReceiveAttrs() {
+ let me = this;
+ me._super(...arguments);
+ me.set('enabled', me.get(me.getFieldPath()));
+ Ember.addObserver(me, me.getFieldPath(), function() {
+ me.set('enabled', me.get(me.getFieldPath()));
+ });
+ },
+ enabledText: '启用',
+ disabledText: '禁用',
+ getFieldPath() {
+ let me = this;
+ return 'model.' + (me.get('field') || 'enabled');
+ },
+});
diff --git a/web/app/components/status-toggle-button.js b/web/app/components/status-toggle-button.js
new file mode 100644
index 0000000..eaf5acc
--- /dev/null
+++ b/web/app/components/status-toggle-button.js
@@ -0,0 +1,38 @@
+import Ember from 'ember';
+import BaseComponent from './base-component';
+
+export default BaseComponent.extend({
+ tagName: 'a',
+ attributeBindings: ['title', 'href', 'role', 'rel'],
+ role: 'button',
+ rel: 'tooltip',
+ href: 'javascript:;',
+ enabled: Ember.computed.alias('model.enabled'),
+ title: Ember.computed('enabled', function() {
+ return this.get('enabled') ? '禁用' : '启用';
+ }),
+ iconSizeClass: 'bigger-120',
+ didReceiveAttrs() {
+ let me = this;
+ if (me.get('iconOnly')) {
+ me.set('iconSizeClass', 'bigger-130');
+ me.set('classNameBindings', ['enabled:orange:light-green']);
+ }
+ else {
+ me.set('classNameBindings',
+ ['enabled:btn-warning:btn-success',
+ 'iconOnly::btn',
+ 'iconOnly::btn-xs']);
+ }
+ },
+ click() {
+ let me = this;
+ me.dialog.confirm('确认要' + me.get('title') + '状态么?', () => {
+ let model = me.get('model');
+ Ember.set(model, 'enabled', !me.get('enabled'));
+ let params = me.get('params');
+ me.get('service').update(params ?
+ Ember.merge(params, model) : model, true);
+ });
+ }
+});
diff --git a/web/app/components/top-navbar.js b/web/app/components/top-navbar.js
new file mode 100644
index 0000000..d55a3b8
--- /dev/null
+++ b/web/app/components/top-navbar.js
@@ -0,0 +1,35 @@
+import Ember from 'ember';
+import BaseComponent from './base-component';
+
+export default BaseComponent.extend({
+ classNames: ['navbar', 'navbar-default', 'navbar-collapse'],
+ user: Ember.computed.alias('ajax.user'),
+ didReceiveAttrs() {
+ let me = this;
+ let user = me.get('user');
+ if (!user) {
+ user = Ember.$.sessionStorage.get('user');
+ if (user) {
+ me.set('ajax.user', user);
+ }
+ else {
+ Ember.Logger.info('No User Found In Session Storage, Try To Load From Cloud');
+ me.ajax.doGet(false, 'auth/info', (u) => {
+ me.set('ajax.user', u);
+ Ember.$.sessionStorage.set('user', u);
+ });
+ }
+ }
+ },
+ actions: {
+ logout() {
+ let me = this;
+ me.ajax.doPost(false, 'auth/logout', () => {
+ me.set('ajax.user', null);
+ Ember.$.sessionStorage.set('user', null);
+ me.get('message').alert('注销成功');
+ me.get('router').transitionTo('login');
+ });
+ }
+ }
+});
diff --git a/web/app/components/tree-view.js b/web/app/components/tree-view.js
new file mode 100644
index 0000000..f7f6591
--- /dev/null
+++ b/web/app/components/tree-view.js
@@ -0,0 +1,15 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ classNames: ['widget-box', 'widget-color-blue2'],
+ didReceiveAttrs() {
+ let me = this;
+ },
+ didInsertElement() {
+ let me = this;
+ console.log(me.get('data'));
+ me.$('div.widget-main > div').treeview({
+ data: me.get('data')
+ });
+ }
+});
diff --git a/web/app/components/wysiwyg-editor.js b/web/app/components/wysiwyg-editor.js
new file mode 100644
index 0000000..f46b811
--- /dev/null
+++ b/web/app/components/wysiwyg-editor.js
@@ -0,0 +1,28 @@
+import Ember from 'ember';
+import BaseFormInput from './base-form-input';
+
+export default BaseFormInput.extend({
+ didInsertElement() {
+ let me = this;
+ //intialize wysiwyg editor
+ me.$('.wysiwyg-editor').ace_wysiwyg({
+ toolbar: [
+ 'bold',
+ 'italic',
+ 'strikethrough',
+ 'underline',
+ null,
+ 'justifyleft',
+ 'justifycenter',
+ 'justifyright',
+ null,
+ 'createLink',
+ 'unlink',
+ null,
+ 'undo',
+ 'redo'
+ ]}).on('DOMSubtreeModified propertychange', function() {
+ me.setVal(Ember.$(this).html());
+ }).html(me.getVal()).prev().addClass('wysiwyg-style1');
+ }
+});
diff --git a/web/app/helpers/array.js b/web/app/helpers/array.js
new file mode 100644
index 0000000..c7c35e1
--- /dev/null
+++ b/web/app/helpers/array.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export function array(params/*, hash*/) {
+ return params;
+}
+
+export default Ember.Helper.helper(array);
diff --git a/web/app/helpers/loose-eq.js b/web/app/helpers/loose-eq.js
new file mode 100644
index 0000000..9e394f7
--- /dev/null
+++ b/web/app/helpers/loose-eq.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export function looseEq(params) {
+ return params[0] == params[1];
+}
+
+export default Ember.Helper.helper(looseEq);
diff --git a/web/app/helpers/obj-merge.js b/web/app/helpers/obj-merge.js
new file mode 100644
index 0000000..eae2edf
--- /dev/null
+++ b/web/app/helpers/obj-merge.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export function objMerge(params) {
+ return Ember.$.extend(true, {}, ...params);
+}
+
+export default Ember.Helper.helper(objMerge);
diff --git a/web/app/helpers/obj-query-params.js b/web/app/helpers/obj-query-params.js
new file mode 100644
index 0000000..b69c8dd
--- /dev/null
+++ b/web/app/helpers/obj-query-params.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+
+export function objQueryParams(params, hash) {
+ Ember.Logger.debug('Obj Query Params: ', params, hash);
+ return Ember.Object.create({
+ isQueryParams: true,
+ values: hash.length > 0 ? hash : params[0]
+ });
+}
+
+export default Ember.Helper.helper(objQueryParams);
diff --git a/web/app/index.html b/web/app/index.html
new file mode 100644
index 0000000..a1f1b9d
--- /dev/null
+++ b/web/app/index.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+ Ambition CRM
+
+
+ {{content-for 'head'}}
+
+
+
+
+
+
+
+
+ {{content-for 'head-footer'}}
+
+
+
+ {{content-for 'body'}}
+
+
+
+ {{content-for 'body-footer'}}
+
+
diff --git a/web/app/initializers/application.js b/web/app/initializers/application.js
new file mode 100644
index 0000000..90c447c
--- /dev/null
+++ b/web/app/initializers/application.js
@@ -0,0 +1,32 @@
+export function initialize(app) {
+ // route
+ app.inject('route', 'ajax', 'service:ajax');
+ app.inject('route', 'store', 'service:store');
+ app.inject('route', 'message', 'service:message');
+ app.inject('route', 'dialog', 'service:dialog');
+ app.inject('route', 'router', 'router:main');
+ // controller
+ app.inject('controller', 'ajax', 'service:ajax');
+ app.inject('controller', 'store', 'service:store');
+ app.inject('controller', 'message', 'service:message');
+ app.inject('controller', 'dialog', 'service:dialog');
+ app.inject('controller', 'router', 'router:main');
+ // component
+ app.inject('component', 'ajax', 'service:ajax');
+ app.inject('component', 'store', 'service:store');
+ app.inject('component', 'message', 'service:message');
+ app.inject('component', 'dialog', 'service:dialog');
+ app.inject('component', 'router', 'router:main');
+ // store
+ app.inject('service:store', 'message', 'service:message');
+ app.inject('service:store', 'dialog', 'service:dialog');
+ app.inject('service:store', 'ajax', 'service:ajax');
+ // ajax
+ app.inject('service:ajax', 'message', 'service:message');
+ app.inject('service:ajax', 'dialog', 'service:dialog');
+}
+
+export default {
+ name: 'application',
+ initialize: initialize
+};
diff --git a/web/app/mixins/components/base-component.js b/web/app/mixins/components/base-component.js
new file mode 100644
index 0000000..5c43832
--- /dev/null
+++ b/web/app/mixins/components/base-component.js
@@ -0,0 +1,32 @@
+import Ember from 'ember';
+
+export default Ember.Mixin.create({
+ toolService: Ember.inject.service('tool-service'),
+ routeName: Ember.computed.alias('router.currentRouteName'),
+ route: Ember.computed('routeName', function() {
+ return this.getRoute();
+ }),
+ service: Ember.computed('routeName', function() {
+ return this.getService();
+ }),
+ params: Ember.computed('router.location.lastSetURL', function() {
+ let me = this;
+ return me.getRouteParams(me.get('routeName'));
+ }),
+ getRouteParams(routeName) {
+ return this.get('route').paramsFor(routeName);
+ },
+ getRoute(routeName) {
+ return Ember.getOwner(this).lookup(
+ 'route:' + (routeName || this.get('routeName')));
+ },
+ getParentRouteName(routeName) {
+ return routeName.replace(/\.[^\.]+$/, '');
+ },
+ getService(name) {
+ let me = this;
+ return name ? me.get('toolService').getServiceByRouteName(name) :
+ me.getRoute().get('service') ||
+ me.get('toolService').getServiceByRouteName(me.get('routeName'));
+ }
+});
diff --git a/web/app/mixins/services/base-service.js b/web/app/mixins/services/base-service.js
new file mode 100644
index 0000000..bfd36ef
--- /dev/null
+++ b/web/app/mixins/services/base-service.js
@@ -0,0 +1,87 @@
+import Ember from 'ember';
+
+export default Ember.Mixin.create({
+ store: Ember.inject.service(),
+ message: Ember.inject.service(),
+ pageSize: 10,
+ constraints: {},
+ createConstraints: null,
+ updateConstraints: null,
+ find(params) {
+ Ember.Logger.debug('Find Model: ', params);
+ return this._getStore().find(this.get('modelName'), params);
+ },
+ list(start, limit, params) {
+ Ember.Logger.debug('List Models Start: ', start, ', Limit: ', limit, ", Search: ", params);
+ return this._getStore().list(this.get('modelName'), start, limit, params);
+ },
+ listPage(page, params) {
+ page > 0 || (page = 1);
+ let me = this;
+ let pageSize = me.get('pageSize');
+ return me.list((page - 1) * pageSize, pageSize, params);
+ },
+ create(model) {
+ Ember.Logger.debug('Create Model: ', model);
+ return this._getStore().create(this.get('modelName'), model);
+ },
+ update(model, defaultPromise) {
+ Ember.Logger.debug('Update Model: ', model);
+ let me = this;
+ let p = me._getStore().update(me.get('modelName'), model);
+ if (defaultPromise) {
+ p.then((m) => {
+ Ember.Logger.debug('After Update: ', m);
+ !(model instanceof FormData) &&
+ Object.keys(m).forEach((prop) => {
+ Ember.set(model, prop, m[prop]);
+ });
+ me.get('message').alert('更新成功');
+ })
+ }
+ return p;
+ },
+ del(params) {
+ Ember.Logger.debug('Update Model: ', params);
+ return this._getStore().del(this.get('modelName'), params);
+ },
+ ajaxGet(path, params) {
+ return this._getStore().modelAjaxGet(this.get('modelName'), path, params);
+ },
+ ajaxPost(path, params) {
+ return this._getStore().modelAjaxPost(this.get('modelName'), path, params);
+ },
+ validate(model, constraints) {
+ let me = this;
+ Ember.Logger.debug('Validate Model: ', model);
+ if (constraints) {
+ if (Ember.$.type(constraints) === 'string') {
+ constraints = me.get(constraints);
+ }
+ else if (Ember.$.type(constraints) !== 'object') {
+ validation = me.get('constraints');
+ }
+ }
+ else {
+ constraints = me.get('constraints');
+ }
+ return validate(model, constraints || me.get('constraints'));
+ },
+ createValidate(model) {
+ Ember.Logger.debug('Create Validate Model: ', model);
+ let me = this;
+ let constraints = me.get('createConstraints') || me.get('constraints') || null;
+ return constraints && validate(model, constraints);
+ },
+ updateValidate(model) {
+ Ember.Logger.debug('Update Validate Model: ', model);
+ let me = this;
+ let constraints = me.get('updateConstraints') || me.get('constraints') || null;
+ return constraints && validate(model, constraints);
+ },
+ _getStore() {
+ return this.get('store');
+ }
+});
+
+
diff --git a/web/app/resolver.js b/web/app/resolver.js
new file mode 100644
index 0000000..2fb563d
--- /dev/null
+++ b/web/app/resolver.js
@@ -0,0 +1,3 @@
+import Resolver from 'ember-resolver';
+
+export default Resolver;
diff --git a/web/app/router.js b/web/app/router.js
new file mode 100644
index 0000000..57fe85d
--- /dev/null
+++ b/web/app/router.js
@@ -0,0 +1,250 @@
+import Ember from 'ember';
+import config from './config/environment';
+
+const Router = Ember.Router.extend({
+ location: config.locationType
+});
+
+Router.map(function() {
+ this.route('login');
+ this.route('app', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create', {path: '/create'}, function() {
+ this.route('api-group-select', {path: '/api-group-select/:page'});
+ this.route('app-config-select', {path: '/app-config-select/:page'});
+ this.route('splash-select', {path: '/splash-select/:page'});
+ this.route('theme-select', {path: '/theme-select/:page'});
+ });
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('api-group-select', {path: '/api-group-select/:page'});
+ this.route('app-config-select', {path: '/app-config-select/:page'});
+ this.route('splash-select', {path: '/splash-select/:page'});
+ this.route('theme-select', {path: '/theme-select/:page'});
+ });
+ this.route('version', {path: '/:appId/:platform/version'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('api-group-select', {path: '/api-group-select/:page'});
+ this.route('app-config-select', {path: '/app-config-select/:page'});
+ this.route('splash-select', {path: '/splash-select/:page'});
+ this.route('theme-select', {path: '/theme-select/:page'});
+ this.route('version-select', {path: '/version-select/:page'});
+ });
+ });
+
+ this.route('release', {path: '/:appId/:platform/release'}, function() {
+ this.route('show');
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('version-select', {path: '/version-select/:page'});
+ });
+ });
+
+ this.route('appoint', {path: '/:appId/:platform/appoint'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create', function() {
+ this.route('version-select', {path: '/version-select/:page'});
+ });
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('version-select', {path: '/version-select/:page'});
+ });
+ });
+
+ this.route('version-group', {path: '/:appId/version-group'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create', function() {
+ this.route('version-select', {path: '/version-select/:page'});
+ });
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('version-select', {path: '/version-select/:page'});
+ });
+ });
+ });
+
+ this.route('api-group', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ this.route('api', {path: '/:apiGroupId/api'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ this.route('import');
+ this.route('substitute');
+ });
+ });
+
+ this.route('splash', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+
+ this.route('theme', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+ this.route('app-config', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ this.route('manage', {path: '/:id/manage'});
+
+ this.route('footer-item', {path: '/:appConfigId/footer-item'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+ });
+
+ this.route('role', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+
+ this.route('user', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create', function() {
+ this.route('role-select');
+ });
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('role-select');
+ });
+ this.route('profile', function() {
+ this.route('upload-avatar');
+ });
+ this.route('show', {path: '/:id/show'});
+ });
+
+ this.route('corp', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create', {path: '/create'}, function() {
+ this.route('api-group-select', {path: '/api-group-select/:page'});
+ this.route('app-config-select', {path: '/app-config-select/:page'});
+ this.route('splash-select', {path: '/splash-select/:page'});
+ this.route('theme-select', {path: '/theme-select/:page'});
+ });
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('tiny-app-group-select', {path: '/tiny-app-group-select/:page'});
+ this.route('api-group-select', {path: '/api-group-select/:page'});
+ this.route('app-config-select', {path: '/app-config-select/:page'});
+ this.route('splash-select', {path: '/splash-select/:page'});
+ this.route('theme-select', {path: '/theme-select/:page'});
+ });
+
+ // employee
+ this.route('employee', {path: '/:corpId/employee'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+
+ // tiny app group
+ this.route('tiny-app-group', {path: '/:corpId/tiny-app-group'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+
+ // tiny app
+ this.route('tiny-app', {path: '/:corpId/tiny-app'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create', {path: '/create'}, function() {
+ this.route('tiny-app-group-select', {path: '/tiny-app-group-select/:page'});
+ });
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('tiny-app-group-select', {path: '/tiny-app-group-select/:page'});
+ });
+ });
+ this.route('dept', {path: '/:corpId/dept'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ this.route('tree');
+ });
+ this.route('contact', {path: '/:corpId/contact'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+ });
+
+ this.route('admin', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create', function() {
+ this.route('role-select');
+ });
+ this.route('edit', {path: '/:id/edit'}, function() {
+ this.route('role-select');
+ });
+ this.route('profile', function() {
+ this.route('upload-avatar');
+ });
+ this.route('show', {path: '/:id/show'});
+ });
+
+ this.route('cloud', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+
+ this.route('corp', {path: '/:cloudId/corp'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('manage', {path: '/:corpId/manage'}, function() {
+ this.route('app-select', {path: '/app-select/:page'});
+ this.route('splash-select', {path: '/splash-select/:page'});
+ this.route('app-config-select', {path: '/app-config-select/:page'});
+ this.route('theme-select', {path: '/theme-select/:page'});
+ this.route('version-select', {path: '/version-select/:page'});
+ this.route('app-select-for-version-select',
+ {path: '/app-select-for-version-select/:page'});
+ this.route('app-select-for-version-group-select',
+ {path: '/app-select-for-version-group-select/:page'});
+ this.route('version-group-select',
+ {path: '/version-group-select/:page'});
+ });
+
+ this.route('member', function() {
+ this.route('list');
+ });
+ this.route('biz-manage', {path: '/:corpId/biz-manage'});
+
+ this.route('biz-group', {path: '/:corpId/biz-group'}, function() {
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+
+ this.route('biz', {path: '/:corpId/biz'}, function() {
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+ });
+
+ this.route('ad-slide', {path: '/:cloudId/ad-slide'}, function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create', function() {
+ this.route('app-select', {path: '/app-select/:page'});
+ this.route('app-select-for-version-select', {path: '/app-select-for-version-select/:page'});
+ this.route('version-select', {path: '/version-select/:page'});
+ this.route('corp-select', {path: '/corp-select/:page'});
+ });
+ this.route('edit', {path: '/:id/edit'});
+ this.route('manage');
+ });
+ });
+
+ this.route('app-alias', function() {
+ this.route('list', {path: '/list/:page'});
+ });
+
+ this.route('app-version-alias', function() {
+ this.route('list', {path: '/list/:page'});
+ this.route('create');
+ this.route('edit', {path: '/:id/edit'});
+ });
+ this.route('op-detail', {path: '/:model/:id/op-detail'});
+});
+
+export default Router;
diff --git a/web/app/routes/admin/create.js b/web/app/routes/admin/create.js
new file mode 100644
index 0000000..498fe18
--- /dev/null
+++ b/web/app/routes/admin/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {};
+ }
+});
diff --git a/web/app/routes/admin/create/role-select.js b/web/app/routes/admin/create/role-select.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/admin/create/role-select.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/admin/edit.js b/web/app/routes/admin/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/admin/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/admin/edit/role-select.js b/web/app/routes/admin/edit/role-select.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/admin/edit/role-select.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/admin/list.js b/web/app/routes/admin/list.js
new file mode 100644
index 0000000..a848ee3
--- /dev/null
+++ b/web/app/routes/admin/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from './../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/admin/profile.js b/web/app/routes/admin/profile.js
new file mode 100644
index 0000000..cee591e
--- /dev/null
+++ b/web/app/routes/admin/profile.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return this.get('store').ajaxGet('user/profile');
+ }
+});
diff --git a/web/app/routes/admin/profile/upload-avatar.js b/web/app/routes/admin/profile/upload-avatar.js
new file mode 100644
index 0000000..96a9fa6
--- /dev/null
+++ b/web/app/routes/admin/profile/upload-avatar.js
@@ -0,0 +1,43 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ actions: {
+ didTransition() {
+ var me = this;
+ me.set('working', false)
+ Ember.run.later(function() {
+ Ember.$('input[type=file]').ace_file_input({
+ style: 'well',
+ btn_choose: 'Click to choose new avatar',
+ btn_change: null,
+ no_icon: 'ace-icon fa fa-picture-o',
+ thumbnail: 'small',
+ before_remove: function() {
+ //don't remove/reset files while being uploaded
+ return !me.get('working')
+ },
+ allowExt: ['jpg', 'jpeg', 'png', 'gif'],
+ allowMime: ['image/jpg', 'image/jpeg', 'image/png', 'image/gif']
+ });
+ }, 48);
+ // Bubble the didTransition event
+ return true;
+ },
+ submit() {
+ let me = this;
+ if (!Ember.$('input[type=file]').val()) {
+ me.get('message').warn('请选择文件');
+ }
+ else {
+ me.get('dialog').confirm('确认要更新头像吗?', () => {
+ me.get('store').ajaxPost('user/upload-avatar',
+ new FormData(Ember.$('#form_upload_avatar')[0])).then((user) => {
+ me.get('message').alert('头像更新成功');
+ Ember.getOwner(me).lookup('route:user.profile').set('controller.model.avatar', user.avatar);
+ me.transitionTo('user.profile');
+ });
+ });
+ }
+ }
+ }
+});
diff --git a/web/app/routes/admin/show.js b/web/app/routes/admin/show.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/admin/show.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/api-group/api/create.js b/web/app/routes/api-group/api/create.js
new file mode 100644
index 0000000..90d74d8
--- /dev/null
+++ b/web/app/routes/api-group/api/create.js
@@ -0,0 +1,10 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {
+ apiGroupId: this.paramsFor('api-group.api').apiGroupId
+ };
+ }
+});
diff --git a/web/app/routes/api-group/api/edit.js b/web/app/routes/api-group/api/edit.js
new file mode 100644
index 0000000..eaac598
--- /dev/null
+++ b/web/app/routes/api-group/api/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/api-group/api/import.js b/web/app/routes/api-group/api/import.js
new file mode 100644
index 0000000..064fc30
--- /dev/null
+++ b/web/app/routes/api-group/api/import.js
@@ -0,0 +1,10 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ model() {
+ return {
+ apiGroupId: this.paramsFor('api-group.api').apiGroupId,
+ override: false
+ };
+ }
+});
diff --git a/web/app/routes/api-group/api/list.js b/web/app/routes/api-group/api/list.js
new file mode 100644
index 0000000..45ea8d5
--- /dev/null
+++ b/web/app/routes/api-group/api/list.js
@@ -0,0 +1,23 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['api-group.api'];
+ },
+ actions: {
+ remove(it) {
+ Ember.Logger.info('Remove Api: ', it);
+ let me = this;
+ me.get('dialog').confirm(`确认要删除Api[${it.name}]吗?`,()=> {
+ me.get('ajax').doPost('api/delete', {
+ id: it.id
+ }, ()=> {
+ me.get('message').alert('删除成功');
+ me.get('controller.model.data').removeObject(it);
+ me.set('controller.model.total', me.get('controller.model.total') - 1);
+ });
+ });
+ }
+ }
+});
diff --git a/web/app/routes/api-group/api/substitute.js b/web/app/routes/api-group/api/substitute.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/api-group/api/substitute.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/api-group/create.js b/web/app/routes/api-group/create.js
new file mode 100644
index 0000000..498fe18
--- /dev/null
+++ b/web/app/routes/api-group/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {};
+ }
+});
diff --git a/web/app/routes/api-group/edit.js b/web/app/routes/api-group/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/api-group/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/api-group/list-select.js b/web/app/routes/api-group/list-select.js
new file mode 100644
index 0000000..9302677
--- /dev/null
+++ b/web/app/routes/api-group/list-select.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../base-list-select';
+
+export default BaseListSelectRoute.extend({
+ templateName: 'api-group/list-select',
+ service: Ember.inject.service('api-group.service')
+});
diff --git a/web/app/routes/api-group/list.js b/web/app/routes/api-group/list.js
new file mode 100644
index 0000000..a964d56
--- /dev/null
+++ b/web/app/routes/api-group/list.js
@@ -0,0 +1,32 @@
+import Ember from 'ember';
+import BaseListRoute from '../base-list';
+
+export default BaseListRoute.extend({
+ actions: {
+ duplicate(it) {
+ Ember.Logger.info('Duplicate Api Group: ', it);
+ let me = this;
+ me.get('dialog').confirm(`确认要复制Api组[${it.name}]吗?`,()=> {
+ me.get('ajax').doPost('api-group/duplicate', {
+ id: it.id
+ }, (m)=> {
+ me.get('message').alert('复制成功');
+ me.get('controller.model.data').pushObject(m);
+ });
+ });
+ },
+ remove(it) {
+ Ember.Logger.info('Remove Api Group: ', it);
+ let me = this;
+ me.get('dialog').confirm(`确认要删除API组[${it.name}]吗?`,()=> {
+ me.get('ajax').doPost('api-group/delete', {
+ id: it.id
+ }, ()=> {
+ me.get('message').alert('删除成功');
+ me.get('controller.model.data').removeObject(it);
+ me.set('controller.model.total', me.get('controller.model.total') - 1);
+ });
+ });
+ }
+ }
+});
diff --git a/web/app/routes/app-alias/list.js b/web/app/routes/app-alias/list.js
new file mode 100644
index 0000000..a848ee3
--- /dev/null
+++ b/web/app/routes/app-alias/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from './../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/app-config/app-config-preview-action.js b/web/app/routes/app-config/app-config-preview-action.js
new file mode 100644
index 0000000..757b093
--- /dev/null
+++ b/web/app/routes/app-config/app-config-preview-action.js
@@ -0,0 +1,41 @@
+import Ember from 'ember';
+
+export default function(it) {
+ let me = this;
+ let id = it.id;
+ console.log('Preview: ', id);
+ let iframeId = 'iframe_preview_' + id;
+ me.get('dialog').dialog({
+ title: `App配置[${it.name}]预览`,
+ message: `
+
+ `,
+ backdrop: true,
+ onEscape: true,
+ buttons: {
+ success: {
+ label: '确定',
+ className: 'btn-success'
+ }
+ }
+ });
+ me.get('service').ajaxGet('preview', id).then((m) => {
+ Ember.Logger.debug('App Config Preview: ', m)
+ let iframeEl = document.getElementById(iframeId);
+ let iframeWindow =
+ iframeEl.contentWindow ||
+ iframeEl.contentDocument.parentWindow;
+ iframeWindow.onload = function() {
+ iframeWindow.postMessage(JSON.stringify(m), '*');
+ };
+ });
+};
diff --git a/web/app/routes/app-config/create.js b/web/app/routes/app-config/create.js
new file mode 100644
index 0000000..67ad7b7
--- /dev/null
+++ b/web/app/routes/app-config/create.js
@@ -0,0 +1,14 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {
+ themeColor: 'rgba(23, 143, 221, 1)',
+ headerBgColor: 'rgba(23, 143, 221, 1)',
+ headerTextColor: 'rgba(255, 255, 255, 1)',
+ footerTopBorderColor: 'rgba(0, 0, 0, 1)',
+ footerBgColor: 'rgba(249, 249, 249, 1)'
+ };
+ }
+});
diff --git a/web/app/routes/app-config/edit.js b/web/app/routes/app-config/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/app-config/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/app-config/footer-item/abservers.js b/web/app/routes/app-config/footer-item/abservers.js
new file mode 100644
index 0000000..511cf14
--- /dev/null
+++ b/web/app/routes/app-config/footer-item/abservers.js
@@ -0,0 +1,34 @@
+import Ember from 'ember';
+
+export default {
+ actionInputOrTypeChanged: function() {
+ let me = this;
+ let action = null;
+ let actionType = Ember.get(me, 'actionType');
+ Ember.Logger.debug(`Action Type ${actionType} Changed.`);
+ if (actionType === 'MESSSAGE') {
+ action = 'ph://view/room-list';
+ }
+ else if (actionType === 'WORKBENCH') {
+ action = 'ph://view/workbench';
+ }
+ else if (actionType === 'CONTACTS') {
+ action = 'ph://view/contacts';
+ }
+ else if (actionType === 'ALERT') {
+ action = 'ph://view/alert-list';
+ }
+ else if (actionType === 'ME') {
+ action = 'ph://view/me';
+ }
+ else if (actionType === 'CUSTOM') {
+ action = Ember.get(me, 'actionInput');
+ }
+ action && Ember.set(me, 'action', action);
+ },
+ // set enabled when model active
+ activeChangeUpdateStatus: function() {
+ let me = this;
+ Ember.get(me, 'active') && Ember.set(me, 'enabled', true);
+ }
+};
diff --git a/web/app/routes/app-config/footer-item/create.js b/web/app/routes/app-config/footer-item/create.js
new file mode 100644
index 0000000..41e48c8
--- /dev/null
+++ b/web/app/routes/app-config/footer-item/create.js
@@ -0,0 +1,26 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+import Abservers from './abservers';
+
+export default BaseRoute.extend({
+ queryParams: {
+ firstItem: {
+ refreshModel: true
+ }
+ },
+ model(params) {
+ return Ember.Object.extend({
+ appConfigId: this.paramsFor('app-config.footer-item').appConfigId,
+ textColorNormal: 'rgba(124, 124, 124, 1)',
+ textColorActive: 'rgba(0, 122, 255, 1)',
+ actionType: 'MESSAGE',
+ action: 'ph://view/room-list',
+ active: 'true' === params.firstItem,
+ enabled: true,
+ actionInputOrTypeChanged: Ember.observer('actionInput',
+ 'actionType', Abservers.actionInputOrTypeChanged),
+ activeChangeUpdateStatus: Ember.observer('active',
+ Abservers.activeChangeUpdateStatus)
+ }).create();
+ }
+});
diff --git a/web/app/routes/app-config/footer-item/edit.js b/web/app/routes/app-config/footer-item/edit.js
new file mode 100644
index 0000000..40b033c
--- /dev/null
+++ b/web/app/routes/app-config/footer-item/edit.js
@@ -0,0 +1,42 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+import Abservers from './abservers';
+
+export default BaseEditRoute.extend({
+ afterModel: function(model) {
+ Ember.Logger.debug('Footer Item After Model: ', model);
+ let action = Ember.get(model, 'action');
+ let actionType = null;
+ if (action.startsWith('ph://view/room-list')) {
+ actionType = 'MESSAGE';
+ }
+ else if (action.startsWith('ph://view/workbench')) {
+ actionType = 'WORKBENCH';
+ }
+ else if (action.startsWith('ph://view/contacts')) {
+ actionType = 'CONTACTS';
+ }
+ else if (action.startsWith('ph://view/alert-list')) {
+ actionType = 'ALERT';
+ }
+ else if (action.startsWith('ph://view/me')) {
+ actionType = 'ME';
+ }
+ else {
+ actionType = 'CUSTOM';
+ Ember.set(model, 'actionInput', action);
+ }
+ Ember.set(model, 'actionType', actionType);
+
+ Ember.addObserver(model,
+ 'actionInput',
+ Abservers.actionInputOrTypeChanged);
+ Ember.addObserver(model,
+ 'actionType',
+ Abservers.actionInputOrTypeChanged);
+ // mark model is active
+ Ember.set(model, 'activeItem', Ember.get(model, 'active') === true);
+ Ember.addObserver(model, 'active',
+ Abservers.activeChangeUpdateStatus);
+ }
+});
diff --git a/web/app/routes/app-config/footer-item/list.js b/web/app/routes/app-config/footer-item/list.js
new file mode 100644
index 0000000..3eedcdf
--- /dev/null
+++ b/web/app/routes/app-config/footer-item/list.js
@@ -0,0 +1,46 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app-config.footer-item'];
+ },
+ actions: {
+ moveUp(it) {
+ let me = this;
+ let data = me.get('controller.model.data');
+ if (data && data.length > 1) {
+ let index = data.indexOf(it);
+ data.removeObject(it);
+ data.insertAt(index - 1, it);
+ me.updateSort();
+ }
+ },
+ moveDown(it) {
+ let me = this;
+ let data = me.get('controller.model.data');
+ if (data && data.length > 1) {
+ let index = data.indexOf(it);
+ data.removeObject(it);
+ data.insertAt(index + 1, it);
+ me.updateSort();
+ }
+ },
+ remove(it) {
+ let me = this;
+ me.get('dialog').confirm('确认要删除[' + it.name + ']吗?', ()=> {
+ me.get('service').del({id: it.id}).then(()=> {
+ me.get('message').alert('删除成功');
+ me.get('controller.model.data').removeObject(it);
+ me.set('controller.model.total', me.get('controller.model.total') - 1);
+ });
+ });
+ }
+ },
+ updateSort() {
+ let me = this;
+ me.get('ajax').doPost('app-config-footer-item/update-sort', {
+ ids: JSON.stringify(me.get('controller.model.data').mapBy('id'))
+ }, false);
+ }
+});
diff --git a/web/app/routes/app-config/list-select.js b/web/app/routes/app-config/list-select.js
new file mode 100644
index 0000000..1619fc0
--- /dev/null
+++ b/web/app/routes/app-config/list-select.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../base-list-select';
+import PreviewAction from './app-config-preview-action';
+
+export default BaseListSelectRoute.extend({
+ templateName: 'app-config/list-select',
+ service: Ember.inject.service('app-config.service'),
+ actions: {
+ preview: PreviewAction
+ }
+});
diff --git a/web/app/routes/app-config/list.js b/web/app/routes/app-config/list.js
new file mode 100644
index 0000000..3a7589e
--- /dev/null
+++ b/web/app/routes/app-config/list.js
@@ -0,0 +1,20 @@
+import Ember from 'ember';
+import BaseListRoute from '../base-list';
+import PreviewAction from './app-config-preview-action';
+
+export default BaseListRoute.extend({
+ actions: {
+ preview: PreviewAction,
+ duplicate(it) {
+ let me = this;
+ me.get('dialog').confirm(`确认要复制App配置[${it.name}]吗?`,()=> {
+ me.get('ajax').doPost('app-config/duplicate', {
+ id: it.id
+ }, (m)=> {
+ me.get('message').alert('复制成功');
+ me.get('controller.model.data').pushObject(m);
+ });
+ });
+ }
+ }
+});
diff --git a/web/app/routes/app-config/manage.js b/web/app/routes/app-config/manage.js
new file mode 100644
index 0000000..f97a2ac
--- /dev/null
+++ b/web/app/routes/app-config/manage.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from './../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/app-version-alias/list.js b/web/app/routes/app-version-alias/list.js
new file mode 100644
index 0000000..a848ee3
--- /dev/null
+++ b/web/app/routes/app-version-alias/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from './../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/app/appoint.js b/web/app/routes/app/appoint.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/app/appoint.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/app/appoint/create.js b/web/app/routes/app/appoint/create.js
new file mode 100644
index 0000000..1945149
--- /dev/null
+++ b/web/app/routes/app/appoint/create.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ model() {
+ return this.paramsFor('app.appoint');
+ }
+});
diff --git a/web/app/routes/app/appoint/create/version-select.js b/web/app/routes/app/appoint/create/version-select.js
new file mode 100644
index 0000000..8517c08
--- /dev/null
+++ b/web/app/routes/app/appoint/create/version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../version/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/appoint/edit.js b/web/app/routes/app/appoint/edit.js
new file mode 100644
index 0000000..4911510
--- /dev/null
+++ b/web/app/routes/app/appoint/edit.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app.appoint'];
+ }
+});
diff --git a/web/app/routes/app/appoint/edit/version-select.js b/web/app/routes/app/appoint/edit/version-select.js
new file mode 100644
index 0000000..8517c08
--- /dev/null
+++ b/web/app/routes/app/appoint/edit/version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../version/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/appoint/list.js b/web/app/routes/app/appoint/list.js
new file mode 100644
index 0000000..378d47f
--- /dev/null
+++ b/web/app/routes/app/appoint/list.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app.appoint'];
+ }
+});
diff --git a/web/app/routes/app/create.js b/web/app/routes/app/create.js
new file mode 100644
index 0000000..498fe18
--- /dev/null
+++ b/web/app/routes/app/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {};
+ }
+});
diff --git a/web/app/routes/app/create/api-group-select.js b/web/app/routes/app/create/api-group-select.js
new file mode 100644
index 0000000..6448440
--- /dev/null
+++ b/web/app/routes/app/create/api-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../api-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/create/app-config-select.js b/web/app/routes/app/create/app-config-select.js
new file mode 100644
index 0000000..a67c92b
--- /dev/null
+++ b/web/app/routes/app/create/app-config-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../app-config/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/create/splash-select.js b/web/app/routes/app/create/splash-select.js
new file mode 100644
index 0000000..5f7b981
--- /dev/null
+++ b/web/app/routes/app/create/splash-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../splash/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/create/theme-select.js b/web/app/routes/app/create/theme-select.js
new file mode 100644
index 0000000..151c61c
--- /dev/null
+++ b/web/app/routes/app/create/theme-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../theme/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/edit.js b/web/app/routes/app/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/app/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/app/edit/api-group-select.js b/web/app/routes/app/edit/api-group-select.js
new file mode 100644
index 0000000..6448440
--- /dev/null
+++ b/web/app/routes/app/edit/api-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../api-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/edit/app-config-select.js b/web/app/routes/app/edit/app-config-select.js
new file mode 100644
index 0000000..a67c92b
--- /dev/null
+++ b/web/app/routes/app/edit/app-config-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../app-config/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/edit/splash-select.js b/web/app/routes/app/edit/splash-select.js
new file mode 100644
index 0000000..5f7b981
--- /dev/null
+++ b/web/app/routes/app/edit/splash-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../splash/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/edit/theme-select.js b/web/app/routes/app/edit/theme-select.js
new file mode 100644
index 0000000..151c61c
--- /dev/null
+++ b/web/app/routes/app/edit/theme-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../theme/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/list-select-for-subitem-select.js b/web/app/routes/app/list-select-for-subitem-select.js
new file mode 100644
index 0000000..996fbbb
--- /dev/null
+++ b/web/app/routes/app/list-select-for-subitem-select.js
@@ -0,0 +1,32 @@
+import Ember from 'ember';
+import BaseListRoute from '../base-list';
+
+export default BaseListRoute.extend({
+ queryParams: {
+ search: {
+ refreshModel: true
+ },
+ selectedId: {
+ refreshModel: false
+ },
+ idField: {
+ refreshModel: false
+ },
+ nameField: {
+ refreshModel: false
+ },
+ platform: {
+ refreshModel: false
+ },
+ subitemRouteName: {
+ refreshModel: false
+ }
+ },
+ templateName: 'app/list-select-for-subitem-select',
+ service: Ember.inject.service('app.service'),
+ setupController(controller) {
+ controller.set('parentRouteName',
+ this.get('routeName').replace(/\.[^\.]+$/, ''));
+ this._super(...arguments);
+ }
+});
diff --git a/web/app/routes/app/list-select-for-version-select.js b/web/app/routes/app/list-select-for-version-select.js
new file mode 100644
index 0000000..b3384a0
--- /dev/null
+++ b/web/app/routes/app/list-select-for-version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from './list-select-for-subitem-select';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/app/list-select.js b/web/app/routes/app/list-select.js
new file mode 100644
index 0000000..04b58a9
--- /dev/null
+++ b/web/app/routes/app/list-select.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../base-list-select';
+
+export default BaseListSelectRoute.extend({
+ templateName: 'app/list-select',
+ service: Ember.inject.service('app.service')
+});
diff --git a/web/app/routes/app/list.js b/web/app/routes/app/list.js
new file mode 100644
index 0000000..0031280
--- /dev/null
+++ b/web/app/routes/app/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from '../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/app/release.js b/web/app/routes/app/release.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/app/release.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/app/release/edit.js b/web/app/routes/app/release/edit.js
new file mode 100644
index 0000000..30f9f0c
--- /dev/null
+++ b/web/app/routes/app/release/edit.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app.release'];
+ }
+});
diff --git a/web/app/routes/app/release/edit/version-select.js b/web/app/routes/app/release/edit/version-select.js
new file mode 100644
index 0000000..8517c08
--- /dev/null
+++ b/web/app/routes/app/release/edit/version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../version/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/release/show.js b/web/app/routes/app/release/show.js
new file mode 100644
index 0000000..30f9f0c
--- /dev/null
+++ b/web/app/routes/app/release/show.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app.release'];
+ }
+});
diff --git a/web/app/routes/app/version-group/create.js b/web/app/routes/app/version-group/create.js
new file mode 100644
index 0000000..c9a9c54
--- /dev/null
+++ b/web/app/routes/app/version-group/create.js
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ model() {
+ return {
+ appId: this.paramsFor('app.version-group').appId
+ };
+ }
+});
diff --git a/web/app/routes/app/version-group/create/version-select.js b/web/app/routes/app/version-group/create/version-select.js
new file mode 100644
index 0000000..8517c08
--- /dev/null
+++ b/web/app/routes/app/version-group/create/version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../version/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/version-group/edit.js b/web/app/routes/app/version-group/edit.js
new file mode 100644
index 0000000..693d84a
--- /dev/null
+++ b/web/app/routes/app/version-group/edit.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app.version-group'];
+ }
+});
diff --git a/web/app/routes/app/version-group/edit/version-select.js b/web/app/routes/app/version-group/edit/version-select.js
new file mode 100644
index 0000000..8517c08
--- /dev/null
+++ b/web/app/routes/app/version-group/edit/version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../version/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/version-group/list-select.js b/web/app/routes/app/version-group/list-select.js
new file mode 100644
index 0000000..4854e79
--- /dev/null
+++ b/web/app/routes/app/version-group/list-select.js
@@ -0,0 +1,24 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../../base-list-select';
+
+export default BaseListSelectRoute.extend({
+ queryParams: {
+ appId: {
+ refreshModel: true
+ },
+ search: {
+ refreshModel: true
+ },
+ selectedId: {
+ refreshModel: false
+ },
+ idField: {
+ refreshModel: false
+ },
+ nameField: {
+ refreshModel: false
+ }
+ },
+ templateName: 'app/version-group/list-select',
+ service: Ember.inject.service('app.version-group.service')
+});
diff --git a/web/app/routes/app/version-group/list.js b/web/app/routes/app/version-group/list.js
new file mode 100644
index 0000000..080ea81
--- /dev/null
+++ b/web/app/routes/app/version-group/list.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app.version-group'];
+ }
+});
diff --git a/web/app/routes/app/version.js b/web/app/routes/app/version.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/app/version.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/app/version/create.js b/web/app/routes/app/version/create.js
new file mode 100644
index 0000000..6a9fd3a
--- /dev/null
+++ b/web/app/routes/app/version/create.js
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ model() {
+ return Ember.$.extend({
+ override: false
+ }, this.paramsFor('app.version'));
+ }
+});
diff --git a/web/app/routes/app/version/edit.js b/web/app/routes/app/version/edit.js
new file mode 100644
index 0000000..10d9d9c
--- /dev/null
+++ b/web/app/routes/app/version/edit.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app.version'];
+ }
+});
diff --git a/web/app/routes/app/version/edit/api-group-select.js b/web/app/routes/app/version/edit/api-group-select.js
new file mode 100644
index 0000000..64f18ab
--- /dev/null
+++ b/web/app/routes/app/version/edit/api-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../api-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/version/edit/app-config-select.js b/web/app/routes/app/version/edit/app-config-select.js
new file mode 100644
index 0000000..748ee0f
--- /dev/null
+++ b/web/app/routes/app/version/edit/app-config-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app-config/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/version/edit/splash-select.js b/web/app/routes/app/version/edit/splash-select.js
new file mode 100644
index 0000000..fb3d905
--- /dev/null
+++ b/web/app/routes/app/version/edit/splash-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../splash/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/version/edit/theme-select.js b/web/app/routes/app/version/edit/theme-select.js
new file mode 100644
index 0000000..ea4fa1d
--- /dev/null
+++ b/web/app/routes/app/version/edit/theme-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../theme/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/version/edit/version-select.js b/web/app/routes/app/version/edit/version-select.js
new file mode 100644
index 0000000..1569321
--- /dev/null
+++ b/web/app/routes/app/version/edit/version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/app/version/list-select.js b/web/app/routes/app/version/list-select.js
new file mode 100644
index 0000000..141d8ae
--- /dev/null
+++ b/web/app/routes/app/version/list-select.js
@@ -0,0 +1,56 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../../base-list-select';
+
+export default BaseListSelectRoute.extend({
+ queryParams: {
+ appId: {
+ refreshModel: true
+ },
+ platform: {
+ refreshModel: true
+ },
+ search: {
+ refreshModel: true
+ },
+ selectedId: {
+ refreshModel: false
+ },
+ idField: {
+ refreshModel: false
+ },
+ nameField: {
+ refreshModel: false
+ }
+ },
+ templateName: 'app/version/list-select',
+ service: Ember.inject.service('app.version.service'),
+ extraParams(params, transition) {
+ let appId = params.appId;
+ let platform = params.platform;
+ if (!appId || !platform) {
+ Object.keys(transition.params).some((k) => {
+ let props = transition.params[k];
+ if (!appId && props.appId) {
+ appId = props.appId;
+ }
+ if (!platform && props.platform) {
+ platform = props.platform;
+ }
+ if (appId && platform) {
+ return true;
+ }
+ });
+ }
+ let eParams = {
+ appId: appId,
+ platform: platform
+ };
+ this.set('eParams', eParams);
+ return eParams;
+ },
+ setupController(controller) {
+ let me = this;
+ me._super(...arguments);
+ controller.setProperties(me.get('eParams'));
+ }
+});
diff --git a/web/app/routes/app/version/list.js b/web/app/routes/app/version/list.js
new file mode 100644
index 0000000..1783a3c
--- /dev/null
+++ b/web/app/routes/app/version/list.js
@@ -0,0 +1,23 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['app.version'];
+ },
+ actions: {
+ hide(av) {
+ Ember.Logger.info('Remove App Version: ', av);
+ let me = this;
+ me.get('dialog').confirm(`确认要删除App版本[${av.name}]吗?`,()=> {
+ me.get('ajax').doPost('app-version/hide', {
+ id: av.id
+ }, ()=> {
+ me.get('message').alert('删除成功');
+ me.get('controller.model.data').removeObject(av);
+ me.set('controller.model.total', me.get('controller.model.total') - 1);
+ });
+ });
+ }
+ }
+});
diff --git a/web/app/routes/application.js b/web/app/routes/application.js
new file mode 100644
index 0000000..1e3bd2b
--- /dev/null
+++ b/web/app/routes/application.js
@@ -0,0 +1,42 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ getLoginRoute() {
+ return Ember.getOwner(this).lookup('route:login');
+ },
+ transitionIntercept(transition) {
+ if (transition.targetName !== 'login') {
+ this.getLoginRoute().set('prevTransition', transition);
+ }
+ },
+ beforeModel: function(transition) {
+ Ember.Logger.info('Before Application Model.', transition);
+ this.transitionIntercept(transition);
+ },
+ activate() {
+ Ember.Logger.info('Application Activate.');
+ Ember.$('body').addClass('no-skin');
+ try{ace.settings.check('navbar', 'fixed');}catch(e){console.log(e)}
+ try{ace.settings.check('main-container', 'fixed');}catch(e){console.log(e)}
+ },
+ actions: {
+ loading(transition, originRoute) {
+ Ember.Logger.info('Application Loading...');
+ // var appCtrl = this.controllerFor('application');
+ this.router.one('didTransition', function() {
+ // appCtrl.set('loading', false);
+ });
+ return true;
+ },
+ willTransition(transition) {
+ Ember.Logger.info('Application Will Transition.', transition);
+ this.transitionIntercept(transition);
+ },
+ goback() {
+ history.back();
+ },
+ reload() {
+ this.refresh();
+ }
+ }
+});
diff --git a/web/app/routes/base-edit.js b/web/app/routes/base-edit.js
new file mode 100644
index 0000000..23961b4
--- /dev/null
+++ b/web/app/routes/base-edit.js
@@ -0,0 +1,18 @@
+import Ember from 'ember';
+import BaseRoute from './base';
+
+export default BaseRoute.extend({
+ model(params, transition) {
+ let me = this;
+ let extParams = null;
+ if (Ember.$.type(me.extraParams) === 'function') {
+ extParams = me.extraParams(params, transition);
+ }
+ if (Object.getOwnPropertyNames(params).length === 0 &&
+ /\.index$/.test(me.routeName)) {
+ params = transition.params[me.routeName.replace(/\.index$/, '')];
+ }
+ return me.get('service').find(
+ extParams ? Ember.$.extend(true, params, extParams) : params);
+ }
+});
diff --git a/web/app/routes/base-list-select.js b/web/app/routes/base-list-select.js
new file mode 100644
index 0000000..840f13e
--- /dev/null
+++ b/web/app/routes/base-list-select.js
@@ -0,0 +1,61 @@
+import Ember from 'ember';
+import BaseListRoute from './base-list';
+
+export default BaseListRoute.extend({
+ queryParams: {
+ search: {
+ refreshModel: true
+ },
+ selectedId: {
+ refreshModel: false
+ },
+ idField: {
+ refreshModel: false
+ },
+ nameField: {
+ refreshModel: false
+ }
+ },
+ setupController(controller) {
+ controller.set('selectedModel', null);
+ this._super(...arguments);
+ },
+ actions: {
+ select(it, selected) {
+ let me = this;
+ Ember.Logger.info('select: ', it, selected);
+ if (selected) {
+ me.set('controller.selectedId', it.id);
+ me.set('controller.selectedModel', it);
+ }
+ else {
+ me.set('controller.selectedId', '');
+ me.set('controller.selectedModel', null);
+ }
+ },
+ submit() {
+ let me = this;
+ let parentRouteName = me.getParentRouteName();
+ const parentModel = me.modelFor(parentRouteName);
+ let itId = me.get('controller.selectedId');
+ if (itId) {
+ let it = me.get('controller.selectedModel');
+ if (it) {
+ Ember.Logger.info('select: ', it);
+ Ember.set(parentModel, me.get('controller.idField'), itId);
+ Ember.set(parentModel, me.get('controller.nameField'), it.name);
+ }
+ }
+ // not select
+ else {
+ Ember.set(parentModel, me.get('controller.idField'), '');
+ Ember.set(parentModel, me.get('controller.nameField'), '');
+ }
+ me.transitionTo(parentRouteName);
+ }
+ },
+ getParentRouteName() {
+ return this.get('parentRouteName') ||
+ this.get('routeName').replace(/\.[^.]+$/, '');
+ }
+});
diff --git a/web/app/routes/base-list.js b/web/app/routes/base-list.js
new file mode 100644
index 0000000..bf909ff
--- /dev/null
+++ b/web/app/routes/base-list.js
@@ -0,0 +1,26 @@
+import Ember from 'ember';
+import BaseRoute from './base';
+
+export default BaseRoute.extend({
+ queryParams: {
+ search: {
+ refreshModel: true
+ }
+ },
+ model(params, transition) {
+ let me = this;
+ let extParams = null;
+ if (Ember.$.type(me.extraParams) === 'function') {
+ extParams = me.extraParams(params, transition);
+ }
+ let page = params.page;
+ if (!Number.isInteger(page)) {
+ page = parseInt(page);
+ }
+ if (page < 1) {
+ page = 1;
+ }
+ return me.get('service').listPage(page,
+ extParams ? Ember.$.extend(true, params, extParams) : params);
+ }
+});
diff --git a/web/app/routes/base.js b/web/app/routes/base.js
new file mode 100644
index 0000000..89a710b
--- /dev/null
+++ b/web/app/routes/base.js
@@ -0,0 +1,37 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ toolService: Ember.inject.service('tool-service'),
+ beforeModel(transition) {
+ let me = this;
+ let service = me.get('service');
+ if (!service) {
+ const routeName = me.get('routeName');
+ let service = me.get('toolService').getServiceByRouteName(routeName);
+ if (service) {
+ Ember.Logger.info(`Set Route [${routeName}] Service [${service}]`);
+ me.set('service', service);
+ }
+ else {
+ Ember.Logger.info(`No Service Found For Route [${routeName}]`);
+ }
+ }
+ me._super(...arguments);
+ },
+ setupController(controller) {
+ let me = this;
+ controller.set('service', me.get('service'));
+ me._super(...arguments);
+ },
+ findParam(transition, name) {
+ let param = null
+ Object.keys(transition.params).some((k) => {
+ let props = transition.params[k];
+ if (props[name]) {
+ param = props[name];
+ return true;
+ }
+ });
+ return param;
+ }
+});
diff --git a/web/app/routes/cloud/ad-slide/create.js b/web/app/routes/cloud/ad-slide/create.js
new file mode 100644
index 0000000..902b7d1
--- /dev/null
+++ b/web/app/routes/cloud/ad-slide/create.js
@@ -0,0 +1,16 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ queryParams: {
+ corpId: {
+ refreshModel: true
+ }
+ },
+ model(params, transition) {
+ return this.get('store').ajaxGet('ad-slide/find-for-create', {
+ cloudId: this.findParam(transition, 'cloudId'),
+ corpId: params.corpId
+ });
+ }
+});
diff --git a/web/app/routes/cloud/ad-slide/create/app-select-for-version-select.js b/web/app/routes/cloud/ad-slide/create/app-select-for-version-select.js
new file mode 100644
index 0000000..3f5f1ad
--- /dev/null
+++ b/web/app/routes/cloud/ad-slide/create/app-select-for-version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app/list-select-for-version-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/ad-slide/create/app-select.js b/web/app/routes/cloud/ad-slide/create/app-select.js
new file mode 100644
index 0000000..516045d
--- /dev/null
+++ b/web/app/routes/cloud/ad-slide/create/app-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/ad-slide/create/corp-select.js b/web/app/routes/cloud/ad-slide/create/corp-select.js
new file mode 100644
index 0000000..72d4197
--- /dev/null
+++ b/web/app/routes/cloud/ad-slide/create/corp-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../corp/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/ad-slide/create/version-select.js b/web/app/routes/cloud/ad-slide/create/version-select.js
new file mode 100644
index 0000000..3bb64a3
--- /dev/null
+++ b/web/app/routes/cloud/ad-slide/create/version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app/version/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/ad-slide/edit.js b/web/app/routes/cloud/ad-slide/edit.js
new file mode 100644
index 0000000..e605678
--- /dev/null
+++ b/web/app/routes/cloud/ad-slide/edit.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+ model(params, transition) {
+ return this.get('store').ajaxGet('ad-slide/find-for-edit', {
+ cloudId: this.findParam(transition, 'cloudId'),
+ id: params.id
+ });
+ }
+});
diff --git a/web/app/routes/cloud/ad-slide/list.js b/web/app/routes/cloud/ad-slide/list.js
new file mode 100644
index 0000000..68dcaf2
--- /dev/null
+++ b/web/app/routes/cloud/ad-slide/list.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['cloud.ad-slide'];
+ }
+});
diff --git a/web/app/routes/cloud/ad-slide/manage.js b/web/app/routes/cloud/ad-slide/manage.js
new file mode 100644
index 0000000..9bc1a87
--- /dev/null
+++ b/web/app/routes/cloud/ad-slide/manage.js
@@ -0,0 +1,37 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ queryParams: {
+ corpId: {
+ refreshModel: true
+ },
+ appId: {
+ refreshModel: true
+ },
+ platform: {
+ refreshModel: true
+ },
+ appVersion: {
+ refreshModel: true
+ }
+ },
+ model(params, transition) {
+ let me = this;
+ let cloudId = me.findParam(transition, 'cloudId');
+ me.set('cloudId', cloudId);
+ return me.get('store').ajaxGet('ad-slide/list-for-manage',
+ Ember.merge(params, {
+ cloudId: cloudId
+ }));
+ },
+ actions: {
+ adSlideSortStopped(ids) {
+ let me = this;
+ ids && ids.length && me.get('ajax').doPost('ad-slide/update-sort', {
+ cloudId: me.get('cloudId'),
+ ids: JSON.stringify(ids)
+ }, false);
+ }
+ }
+});
diff --git a/web/app/routes/cloud/corp/biz-group/create.js b/web/app/routes/cloud/corp/biz-group/create.js
new file mode 100644
index 0000000..fd7fe6f
--- /dev/null
+++ b/web/app/routes/cloud/corp/biz-group/create.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+import BaseRoute from '../../../base';
+
+export default BaseRoute.extend({
+ model() {
+ return this.get('store').ajaxGet('corp/find-for-subitem', {
+ cloudId: this.paramsFor('cloud.corp').cloudId,
+ corpId: this.paramsFor('cloud.corp.biz-group').corpId
+ });
+ }
+});
diff --git a/web/app/routes/cloud/corp/biz-group/edit.js b/web/app/routes/cloud/corp/biz-group/edit.js
new file mode 100644
index 0000000..a424d64
--- /dev/null
+++ b/web/app/routes/cloud/corp/biz-group/edit.js
@@ -0,0 +1,12 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../../base-edit';
+
+export default BaseEditRoute.extend({
+ model(params) {
+ return this.get('store').ajaxGet('biz-group/find-for-edit', {
+ cloudId: this.paramsFor('cloud.corp').cloudId,
+ corpId: this.paramsFor('cloud.corp.biz-group').corpId,
+ id: params.id
+ });
+ }
+});
diff --git a/web/app/routes/cloud/corp/biz-manage.js b/web/app/routes/cloud/corp/biz-manage.js
new file mode 100644
index 0000000..35e5b8d
--- /dev/null
+++ b/web/app/routes/cloud/corp/biz-manage.js
@@ -0,0 +1,91 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ queryParams: {
+ selected: {
+ refreshModel: true
+ },
+ showDisabled: {
+ refreshModel: true,
+ replace: false
+ }
+ },
+ model(params) {
+ return this.get('store').ajaxGet('biz-group/list', {
+ cloudId: this.paramsFor('cloud.corp').cloudId,
+ corpId: params.corpId,
+ selectedId: params.selected,
+ showDisabled: params.showDisabled
+ });
+ },
+ setupController(controller, model, transition) {
+ let me = this;
+ controller.set('showDisabled',
+ transition.queryParams.showDisabled ?
+ JSON.parse(transition.queryParams.showDisabled) : false)
+ me._super(...arguments);
+ },
+ actions: {
+ bizGroupSortStopped(ids) {
+ let me = this;
+ ids && ids.length && me.get('ajax').doPost('biz-group/update-sort', {
+ cloudId: me.paramsFor('cloud.corp').cloudId,
+ ids: JSON.stringify(ids)
+ }, false);
+ },
+ bizSortStopped(ids) {
+ let me = this;
+ ids && ids.length && me.get('ajax').doPost('biz/update-sort', {
+ cloudId: me.paramsFor('cloud.corp').cloudId,
+ groupId: me.get('controller.selected'),
+ ids: JSON.stringify(ids)
+ }, false);
+ },
+ deleteBizGroup(bizGroup) {
+ let me = this;
+ me.get('dialog').confirm('确认要删除业务分组[' + bizGroup.name + ']吗?', () => {
+ me.get('ajax').doPost('biz-group/delete', {
+ cloudId: this.paramsFor('cloud.corp').cloudId,
+ id: bizGroup.id
+ }, () => {
+ me.get('message').alert('删除成功');
+ me.get('controller.model.bizGroups').removeObject(bizGroup);
+ });
+ });
+ },
+ selectGroup(biz) {
+ let me = this;
+ me.set('controller.isEditing', true);
+ me.set('controller.isEditingBiz', biz);
+ me.set('controller.isEditingBiz', biz);
+ me.set('controller.selectedGroupId', me.get('controller.selected'));
+ },
+ cancelSelectGroup() {
+ let me = this;
+ me.set('controller.isEditing', false);
+ me.set('controller.isEditingBiz', null);
+ },
+ saveSelectGroup(biz) {
+ let me = this;
+ let groupId = me.get('controller.selectedGroupId');
+ if (groupId !== me.get('controller.selected')) {
+ let model = me.get('controller.model');
+ me.get('dialog').confirm('确认要更新业务分组吗?', ()=> {
+ let params = Ember.merge({
+ cloudId: model.cloud.id,
+ corpId: model.corp.id
+ }, biz);
+ params.groupId = groupId;
+ params.icon = null;
+ me.get('ajax').doPost('biz/update', params, ()=> {
+ me.get('message').alert('更新成功');
+ me.refresh();
+ });
+ });
+ }
+ me.set('controller.isEditing', false);
+ me.set('controller.isEditingBiz', null);
+ }
+ }
+});
diff --git a/web/app/routes/cloud/corp/biz/create.js b/web/app/routes/cloud/corp/biz/create.js
new file mode 100644
index 0000000..a144b0b
--- /dev/null
+++ b/web/app/routes/cloud/corp/biz/create.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+import BaseRoute from '../../../base';
+
+export default BaseRoute.extend({
+ model() {
+ return this.get('store').ajaxGet('biz/find-for-create', {
+ cloudId: this.paramsFor('cloud.corp').cloudId,
+ corpId: this.paramsFor('cloud.corp.biz').corpId
+ });
+ }
+});
diff --git a/web/app/routes/cloud/corp/biz/edit.js b/web/app/routes/cloud/corp/biz/edit.js
new file mode 100644
index 0000000..cbf9560
--- /dev/null
+++ b/web/app/routes/cloud/corp/biz/edit.js
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../../base-edit';
+
+export default BaseEditRoute.extend({
+ extraParams(params, transition) {
+ return Ember.merge(transition.params['cloud.corp'],
+ transition.params['cloud.corp.biz']);
+ }
+});
diff --git a/web/app/routes/cloud/corp/list-select.js b/web/app/routes/cloud/corp/list-select.js
new file mode 100644
index 0000000..43ae16b
--- /dev/null
+++ b/web/app/routes/cloud/corp/list-select.js
@@ -0,0 +1,13 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../../base-list-select';
+
+export default BaseListSelectRoute.extend({
+ templateName: 'cloud/corp/list-select',
+ service: Ember.inject.service('cloud.corp.service'),
+ extraParams(params, transition) {
+ return {
+ cloudId: params.cloudId ||
+ this.findParam(transition, 'cloudId')
+ };
+ }
+});
diff --git a/web/app/routes/cloud/corp/list.js b/web/app/routes/cloud/corp/list.js
new file mode 100644
index 0000000..5ab0ecc
--- /dev/null
+++ b/web/app/routes/cloud/corp/list.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return {cloudId: params.cloudId || this.findParam(transition, 'cloudId')};
+ }
+});
diff --git a/web/app/routes/cloud/corp/manage.js b/web/app/routes/cloud/corp/manage.js
new file mode 100644
index 0000000..fe4e4c2
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ model(params) {
+ return this.get('store').ajaxGet('corp/find-for-edit', {
+ cloudId: this.paramsFor('cloud.corp').cloudId,
+ corpId: params.corpId
+ });
+ }
+});
diff --git a/web/app/routes/cloud/corp/manage/app-config-select.js b/web/app/routes/cloud/corp/manage/app-config-select.js
new file mode 100644
index 0000000..748ee0f
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage/app-config-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app-config/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/corp/manage/app-select-for-version-group-select.js b/web/app/routes/cloud/corp/manage/app-select-for-version-group-select.js
new file mode 100644
index 0000000..0ddadc8
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage/app-select-for-version-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app/list-select-for-subitem-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/corp/manage/app-select-for-version-select.js b/web/app/routes/cloud/corp/manage/app-select-for-version-select.js
new file mode 100644
index 0000000..3f5f1ad
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage/app-select-for-version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app/list-select-for-version-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/corp/manage/app-select.js b/web/app/routes/cloud/corp/manage/app-select.js
new file mode 100644
index 0000000..516045d
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage/app-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/corp/manage/splash-select.js b/web/app/routes/cloud/corp/manage/splash-select.js
new file mode 100644
index 0000000..fb3d905
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage/splash-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../splash/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/corp/manage/theme-select.js b/web/app/routes/cloud/corp/manage/theme-select.js
new file mode 100644
index 0000000..ea4fa1d
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage/theme-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../theme/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/corp/manage/version-group-select.js b/web/app/routes/cloud/corp/manage/version-group-select.js
new file mode 100644
index 0000000..b1daa7c
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage/version-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app/version-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/corp/manage/version-select.js b/web/app/routes/cloud/corp/manage/version-select.js
new file mode 100644
index 0000000..3bb64a3
--- /dev/null
+++ b/web/app/routes/cloud/corp/manage/version-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../../app/version/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/cloud/corp/member/list.js b/web/app/routes/cloud/corp/member/list.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/cloud/corp/member/list.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/cloud/create.js b/web/app/routes/cloud/create.js
new file mode 100644
index 0000000..498fe18
--- /dev/null
+++ b/web/app/routes/cloud/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {};
+ }
+});
diff --git a/web/app/routes/cloud/edit.js b/web/app/routes/cloud/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/cloud/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/cloud/list.js b/web/app/routes/cloud/list.js
new file mode 100644
index 0000000..0031280
--- /dev/null
+++ b/web/app/routes/cloud/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from '../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/corp/contact.js b/web/app/routes/corp/contact.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/corp/contact.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/corp/contact/create.js b/web/app/routes/corp/contact/create.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/corp/contact/create.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/corp/contact/edit.js b/web/app/routes/corp/contact/edit.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/corp/contact/edit.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/corp/contact/list.js b/web/app/routes/corp/contact/list.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/corp/contact/list.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/corp/create.js b/web/app/routes/corp/create.js
new file mode 100644
index 0000000..498fe18
--- /dev/null
+++ b/web/app/routes/corp/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {};
+ }
+});
diff --git a/web/app/routes/corp/create/api-group-select.js b/web/app/routes/corp/create/api-group-select.js
new file mode 100644
index 0000000..6448440
--- /dev/null
+++ b/web/app/routes/corp/create/api-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../api-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/create/app-config-select.js b/web/app/routes/corp/create/app-config-select.js
new file mode 100644
index 0000000..a67c92b
--- /dev/null
+++ b/web/app/routes/corp/create/app-config-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../app-config/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/create/splash-select.js b/web/app/routes/corp/create/splash-select.js
new file mode 100644
index 0000000..5f7b981
--- /dev/null
+++ b/web/app/routes/corp/create/splash-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../splash/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/create/theme-select.js b/web/app/routes/corp/create/theme-select.js
new file mode 100644
index 0000000..151c61c
--- /dev/null
+++ b/web/app/routes/corp/create/theme-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../theme/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/dept.js b/web/app/routes/corp/dept.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/corp/dept.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/corp/dept/create.js b/web/app/routes/corp/dept/create.js
new file mode 100644
index 0000000..34ff2fc
--- /dev/null
+++ b/web/app/routes/corp/dept/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ model() {
+ return Ember.$.extend({}, this.paramsFor('corp.dept'));
+ }
+});
diff --git a/web/app/routes/corp/dept/edit.js b/web/app/routes/corp/dept/edit.js
new file mode 100644
index 0000000..eaac598
--- /dev/null
+++ b/web/app/routes/corp/dept/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/corp/dept/list.js b/web/app/routes/corp/dept/list.js
new file mode 100644
index 0000000..7c0729f
--- /dev/null
+++ b/web/app/routes/corp/dept/list.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['corp.dept'];
+ }
+});
diff --git a/web/app/routes/corp/dept/tree.js b/web/app/routes/corp/dept/tree.js
new file mode 100644
index 0000000..a52e4eb
--- /dev/null
+++ b/web/app/routes/corp/dept/tree.js
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ model(params, transition) {
+ let me = this;
+ return me.get('store').ajaxGet('dept/tree', transition.params['corp.dept']);
+ }
+});
diff --git a/web/app/routes/corp/edit.js b/web/app/routes/corp/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/corp/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/corp/edit/api-group-select.js b/web/app/routes/corp/edit/api-group-select.js
new file mode 100644
index 0000000..6448440
--- /dev/null
+++ b/web/app/routes/corp/edit/api-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../api-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/edit/app-config-select.js b/web/app/routes/corp/edit/app-config-select.js
new file mode 100644
index 0000000..a67c92b
--- /dev/null
+++ b/web/app/routes/corp/edit/app-config-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../app-config/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/edit/splash-select.js b/web/app/routes/corp/edit/splash-select.js
new file mode 100644
index 0000000..5f7b981
--- /dev/null
+++ b/web/app/routes/corp/edit/splash-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../splash/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/edit/theme-select.js b/web/app/routes/corp/edit/theme-select.js
new file mode 100644
index 0000000..151c61c
--- /dev/null
+++ b/web/app/routes/corp/edit/theme-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../theme/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/edit/tiny-app-group-select.js b/web/app/routes/corp/edit/tiny-app-group-select.js
new file mode 100644
index 0000000..c212581
--- /dev/null
+++ b/web/app/routes/corp/edit/tiny-app-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../tiny-app-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/employee/create.js b/web/app/routes/corp/employee/create.js
new file mode 100644
index 0000000..e69e27c
--- /dev/null
+++ b/web/app/routes/corp/employee/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ model() {
+ return Ember.$.extend({}, this.paramsFor('corp.employee'));
+ }
+});
diff --git a/web/app/routes/corp/employee/edit.js b/web/app/routes/corp/employee/edit.js
new file mode 100644
index 0000000..eaac598
--- /dev/null
+++ b/web/app/routes/corp/employee/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/corp/employee/list.js b/web/app/routes/corp/employee/list.js
new file mode 100644
index 0000000..1827848
--- /dev/null
+++ b/web/app/routes/corp/employee/list.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['corp.employee'];
+ }
+});
diff --git a/web/app/routes/corp/employee/show.js b/web/app/routes/corp/employee/show.js
new file mode 100644
index 0000000..eaac598
--- /dev/null
+++ b/web/app/routes/corp/employee/show.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/corp/list.js b/web/app/routes/corp/list.js
new file mode 100644
index 0000000..0031280
--- /dev/null
+++ b/web/app/routes/corp/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from '../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/corp/show.js b/web/app/routes/corp/show.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/corp/show.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/corp/tiny-app-group/create.js b/web/app/routes/corp/tiny-app-group/create.js
new file mode 100644
index 0000000..9d07d56
--- /dev/null
+++ b/web/app/routes/corp/tiny-app-group/create.js
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ model() {
+ return Ember.$.extend({}, this.paramsFor('corp.tiny-app-group'));
+ }
+});
+
diff --git a/web/app/routes/corp/tiny-app-group/edit.js b/web/app/routes/corp/tiny-app-group/edit.js
new file mode 100644
index 0000000..fdf1f49
--- /dev/null
+++ b/web/app/routes/corp/tiny-app-group/edit.js
@@ -0,0 +1,6 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+});
+
diff --git a/web/app/routes/corp/tiny-app-group/list-select.js b/web/app/routes/corp/tiny-app-group/list-select.js
new file mode 100644
index 0000000..fc9ab36
--- /dev/null
+++ b/web/app/routes/corp/tiny-app-group/list-select.js
@@ -0,0 +1,24 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../../base-list-select';
+
+export default BaseListSelectRoute.extend({
+ queryParams: {
+ corpId: {
+ refreshModel: true
+ },
+ search: {
+ refreshModel: true
+ },
+ selectedId: {
+ refreshModel: false
+ },
+ idField: {
+ refreshModel: false
+ },
+ nameField: {
+ refreshModel: false
+ }
+ },
+ templateName: 'corp/tiny-app-group/list-select',
+ service: Ember.inject.service('corp.tiny-app-group.service')
+});
diff --git a/web/app/routes/corp/tiny-app-group/list.js b/web/app/routes/corp/tiny-app-group/list.js
new file mode 100644
index 0000000..154b0a8
--- /dev/null
+++ b/web/app/routes/corp/tiny-app-group/list.js
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['corp.tiny-app-group'];
+ }
+});
+
diff --git a/web/app/routes/corp/tiny-app/create.js b/web/app/routes/corp/tiny-app/create.js
new file mode 100644
index 0000000..55f918f
--- /dev/null
+++ b/web/app/routes/corp/tiny-app/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../../base';
+
+export default BaseRoute.extend({
+ model() {
+ return Ember.$.extend({}, this.paramsFor('corp.tiny-app'));
+ }
+});
diff --git a/web/app/routes/corp/tiny-app/create/tiny-app-group-select.js b/web/app/routes/corp/tiny-app/create/tiny-app-group-select.js
new file mode 100644
index 0000000..7ab025c
--- /dev/null
+++ b/web/app/routes/corp/tiny-app/create/tiny-app-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../tiny-app-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/tiny-app/edit.js b/web/app/routes/corp/tiny-app/edit.js
new file mode 100644
index 0000000..eaac598
--- /dev/null
+++ b/web/app/routes/corp/tiny-app/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/corp/tiny-app/edit/tiny-app-group-select.js b/web/app/routes/corp/tiny-app/edit/tiny-app-group-select.js
new file mode 100644
index 0000000..7ab025c
--- /dev/null
+++ b/web/app/routes/corp/tiny-app/edit/tiny-app-group-select.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import SelectRoute from '../../tiny-app-group/list-select';
+
+export default SelectRoute.extend({
+});
diff --git a/web/app/routes/corp/tiny-app/list.js b/web/app/routes/corp/tiny-app/list.js
new file mode 100644
index 0000000..7e3e218
--- /dev/null
+++ b/web/app/routes/corp/tiny-app/list.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseListRoute from '../../base-list';
+
+export default BaseListRoute.extend({
+ extraParams(params, transition) {
+ return transition.params['corp.tiny-app'];
+ }
+});
diff --git a/web/app/routes/corp/tiny-app/show.js b/web/app/routes/corp/tiny-app/show.js
new file mode 100644
index 0000000..eaac598
--- /dev/null
+++ b/web/app/routes/corp/tiny-app/show.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/index.js b/web/app/routes/index.js
new file mode 100644
index 0000000..012ab7c
--- /dev/null
+++ b/web/app/routes/index.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ beforeModel() {
+ // this.transitionTo('app.list', 1);
+ }
+});
diff --git a/web/app/routes/login.js b/web/app/routes/login.js
new file mode 100644
index 0000000..6c7d1ed
--- /dev/null
+++ b/web/app/routes/login.js
@@ -0,0 +1,34 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ activate() {
+ this.controllerFor('application').set('login', true);
+ },
+ deactivate() {
+ this.controllerFor('application').set('login', false);
+ },
+ actions: {
+ doLogin(model) {
+ let me = this;
+ me.get('ajax').doPost('auth/login', model,
+ function(user) {
+ Ember.Logger.debug(`User ${user} Loggedin`);
+ Ember.$.sessionStorage.set('user', user);
+ me.set('ajax.user', user);
+ me.message.alert('登录成功');
+ // Log the user in, then reattempt previous transition if it exists.
+ let prevTransition = me.get('prevTransition');
+ if (prevTransition) {
+ me.set('prevTransition', null);
+ prevTransition.retry();
+ }
+ else {
+ // Default back to app list
+ me.transitionTo('index');
+ }
+ }, function(msg) {
+ me.get('message').warn('Login Fail [' + msg + ']');
+ });
+ }
+ }
+});
diff --git a/web/app/routes/op-detail.js b/web/app/routes/op-detail.js
new file mode 100644
index 0000000..593fc85
--- /dev/null
+++ b/web/app/routes/op-detail.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ model(params) {
+ return this.get('store').find(params.model, params.id);
+ }
+});
diff --git a/web/app/routes/role/create.js b/web/app/routes/role/create.js
new file mode 100644
index 0000000..8fd2a04
--- /dev/null
+++ b/web/app/routes/role/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {type: 'U'};
+ }
+});
diff --git a/web/app/routes/role/edit.js b/web/app/routes/role/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/role/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/role/list.js b/web/app/routes/role/list.js
new file mode 100644
index 0000000..a848ee3
--- /dev/null
+++ b/web/app/routes/role/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from './../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/splash/create.js b/web/app/routes/splash/create.js
new file mode 100644
index 0000000..bab50c4
--- /dev/null
+++ b/web/app/routes/splash/create.js
@@ -0,0 +1,10 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {
+ duration: 1000
+ };
+ }
+});
diff --git a/web/app/routes/splash/edit.js b/web/app/routes/splash/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/splash/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/splash/list-select.js b/web/app/routes/splash/list-select.js
new file mode 100644
index 0000000..f19e707
--- /dev/null
+++ b/web/app/routes/splash/list-select.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../base-list-select';
+
+export default BaseListSelectRoute.extend({
+ templateName: 'splash/list-select',
+ service: Ember.inject.service('splash.service')
+});
diff --git a/web/app/routes/splash/list.js b/web/app/routes/splash/list.js
new file mode 100644
index 0000000..a848ee3
--- /dev/null
+++ b/web/app/routes/splash/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from './../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/theme/create.js b/web/app/routes/theme/create.js
new file mode 100644
index 0000000..498fe18
--- /dev/null
+++ b/web/app/routes/theme/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {};
+ }
+});
diff --git a/web/app/routes/theme/edit.js b/web/app/routes/theme/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/theme/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/theme/list-select.js b/web/app/routes/theme/list-select.js
new file mode 100644
index 0000000..3b9310b
--- /dev/null
+++ b/web/app/routes/theme/list-select.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+import BaseListSelectRoute from '../base-list-select';
+
+export default BaseListSelectRoute.extend({
+ templateName: 'theme/list-select',
+ service: Ember.inject.service('theme.service')
+});
diff --git a/web/app/routes/theme/list.js b/web/app/routes/theme/list.js
new file mode 100644
index 0000000..a848ee3
--- /dev/null
+++ b/web/app/routes/theme/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from './../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/user/create.js b/web/app/routes/user/create.js
new file mode 100644
index 0000000..498fe18
--- /dev/null
+++ b/web/app/routes/user/create.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return {};
+ }
+});
diff --git a/web/app/routes/user/create/role-select.js b/web/app/routes/user/create/role-select.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/user/create/role-select.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/user/edit.js b/web/app/routes/user/edit.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/user/edit.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/routes/user/edit/role-select.js b/web/app/routes/user/edit/role-select.js
new file mode 100644
index 0000000..26d9f31
--- /dev/null
+++ b/web/app/routes/user/edit/role-select.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+});
diff --git a/web/app/routes/user/list.js b/web/app/routes/user/list.js
new file mode 100644
index 0000000..a848ee3
--- /dev/null
+++ b/web/app/routes/user/list.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseListRoute from './../base-list';
+
+export default BaseListRoute.extend({
+});
diff --git a/web/app/routes/user/profile.js b/web/app/routes/user/profile.js
new file mode 100644
index 0000000..cee591e
--- /dev/null
+++ b/web/app/routes/user/profile.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import BaseRoute from '../base';
+
+export default BaseRoute.extend({
+ model() {
+ return this.get('store').ajaxGet('user/profile');
+ }
+});
diff --git a/web/app/routes/user/profile/upload-avatar.js b/web/app/routes/user/profile/upload-avatar.js
new file mode 100644
index 0000000..b40562b
--- /dev/null
+++ b/web/app/routes/user/profile/upload-avatar.js
@@ -0,0 +1,43 @@
+import Ember from 'ember';
+
+export default Ember.Route.extend({
+ actions: {
+ didTransition() {
+ var me = this;
+ me.set('working', false)
+ Ember.run.later(function() {
+ Ember.$('input[type=file]').ace_file_input({
+ style: 'well',
+ btn_choose: 'Click to choose new avatar',
+ btn_change: null,
+ no_icon: 'ace-icon fa fa-picture-o',
+ thumbnail: 'small',
+ before_remove: function() {
+ //don't remove/reset files while being uploaded
+ return !me.get('working')
+ },
+ allowExt: ['jpg', 'jpeg', 'png', 'gif'],
+ allowMime: ['image/jpg', 'image/jpeg', 'image/png', 'image/gif']
+ });
+ }, 48);
+ // Bubble the didTransition event
+ return true;
+ },
+ submit() {
+ let me = this;
+ if (!Ember.$('input[type=file]').val()) {
+ me.get('message').warn('请选择文件');
+ }
+ else {
+ me.get('dialog').confirm('确认要更新头像吗?', () => {
+ me.get('store').ajaxPost('admin/upload-avatar',
+ new FormData(Ember.$('#form_upload_avatar')[0])).then((admin) => {
+ me.get('message').alert('头像更新成功');
+ Ember.getOwner(me).lookup('route:admin.profile').set('controller.model.avatar', admin.avatar);
+ me.transitionTo('admin.profile');
+ });
+ });
+ }
+ }
+ }
+});
diff --git a/web/app/routes/user/show.js b/web/app/routes/user/show.js
new file mode 100644
index 0000000..7c73c90
--- /dev/null
+++ b/web/app/routes/user/show.js
@@ -0,0 +1,5 @@
+import Ember from 'ember';
+import BaseEditRoute from '../base-edit';
+
+export default BaseEditRoute.extend({
+});
diff --git a/web/app/services/admin/service.js b/web/app/services/admin/service.js
new file mode 100644
index 0000000..afe8edc
--- /dev/null
+++ b/web/app/services/admin/service.js
@@ -0,0 +1,36 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'Admin',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ password: {
+ presence: true,
+ length: {
+ minimum: 4,
+ maximum: 36
+ }
+ },
+ confirmPassword: {
+ equality: 'password'
+ }
+ },
+ updateConstraints: {
+ password: {
+ length: {
+ minimum: 4,
+ maximum: 36
+ }
+ },
+ confirmPassword: {
+ equality: 'password'
+ }
+ }
+});
diff --git a/web/app/services/ajax.js b/web/app/services/ajax.js
new file mode 100644
index 0000000..fe0d7db
--- /dev/null
+++ b/web/app/services/ajax.js
@@ -0,0 +1,167 @@
+import Ember from 'ember';
+
+export default Ember.Service.extend({
+ /**
+ * Ajax.doGet('url.get',
+ * {id: 001, name: 'foo'},
+ * function(data) {
+ * // success
+ * }, function(msg) {
+ * // fail
+ * });
+ * no params
+ * Ajax.doGet('url.get',
+ * function(data) {
+ * // success
+ * }, function(msg){
+ * // fail
+ * });
+ * @param {Boolean} [loadmask], option
+ * @param {String} url
+ * @param {Object} [params]
+ * @param {Function} [fnSucc]
+ * @param {Function} [fnFail]
+ */
+ doGet() {
+ this._process_request(arguments, 'GET');
+ },
+ /**
+ * @see #get
+ */
+ doPost() {
+ this._process_request(arguments, 'POST');
+ },
+ /**
+ * @see #get
+ */
+ doPut() {
+ this._process_request(arguments, 'PUT');
+ },
+ /**
+ * @see #get
+ */
+ doDel() {
+ this._process_request(arguments, 'DELETE');
+ },
+ /**
+ * private
+ */
+ _request(p) {
+ var me = this;
+ p.loadmask && me.set('loading', true);
+ var formDataCfg;
+ if (p.params instanceof FormData) {
+ formDataCfg = false;
+ }
+
+ Ember.$.ajax({
+ url: p.url,
+ data: p.params,
+ type: (/get/i).test(p.method) ? 'GET' : 'POST',
+ contentType: formDataCfg,
+ processData: formDataCfg,
+ success(r, status, resp) {
+ if (r.success) {
+ // ignore success callback
+ if (p.fnSucc !== false) {
+ let keys = Object.keys(r);
+ me._isFunc(p.fnSucc) ?
+ p.fnSucc(keys.length === 3 &&
+ keys.includes('data') ? r.data : r) :
+ me.message.alert(r.data || 'Ajax Request Successfully');
+ }
+ }
+ else if (r.errcode === 4011) {
+ Ember.getOwner(me).lookup('route:application').transitionTo('login');
+ }
+ // ignore fail callback
+ else if (p.fnFail !== false) {
+ me._isFunc(p.fnFail) ? p.fnFail(r.errmsg, r) :
+ me.dialog.error(r.errmsg || 'Ajax Request Error Caused');
+ }
+ else {
+ me.dialog.error(r.errmsg || 'Ajax Request Error Caused');
+ }
+ p.loadmask && me.set('loading', false);
+ },
+ error(jqXHR, textStatus) {
+ Ember.Logger.error('Ajax Request Error Caused', arguments);
+ if (textStatus === 'timeout') {
+ me.dialog.error('Ajax Request Timeout Error Caused.');
+ }
+ else if (textStatus === 'abort') {
+ me.dialog.error('Ajax Request Client Abort Error Caused.');
+ }
+ else {
+ me.dialog.error('Ajax Request Error Caused.');
+ }
+ p.loadmask && me.set('loading', false);
+ }
+ });
+ },
+ /**
+ * {
+ * [lm], [url], [params], [fnSucc], [fnFail]
+ * }
+ */
+ _process_request(args, method) {
+ var me = this;
+ if (args && args.length) {
+ // args to array
+ args = Array.prototype.slice.call(args);
+ var lm = args.shift(), // loadmask
+ url,
+ p,
+ fnSucc,
+ fnFail;
+ // loadmask
+ if (Ember.$.type(lm) === 'boolean') {
+ url = args.shift();
+ }
+ else {
+ url = lm;
+ // default loadmask
+ lm = true;
+ }
+ me._parse_params_and_callbacks(args);
+ // params
+ p = args.shift();
+ // callbacks
+ fnSucc = args.shift();
+ fnFail = args.shift();
+ // Ajax Request
+ me._request({
+ loadmask: lm,
+ method: method || 'GET',
+ url: url,
+ params: p,
+ fnSucc: fnSucc,
+ fnFail: fnFail
+ });
+ }
+ else {
+ console.error('Ajax No Args Given.');
+ }
+ },
+ /**
+ * params, fnSucc, fnFail
+ * fnSucc, fnFail
+ * fnFail
+ */
+ _parse_params_and_callbacks(args) {
+ // has callbacks
+ if (this._isFunc(args[1]) && this._isFunc(args[2])) {
+ this._isFunc(args[0]) && (args[0] = args[0]());
+ }
+ // no params, params is success callback
+ else if (this._isFunc(args[0])) {
+ args[2] = args[1];
+ args[1] = args[0];
+ args[0] = null;
+ }
+ },
+ _isFunc(f) {
+ return Ember.$.type(f) === 'function';
+ }
+});
+
diff --git a/web/app/services/api-group/api/service.js b/web/app/services/api-group/api/service.js
new file mode 100644
index 0000000..1b49d39
--- /dev/null
+++ b/web/app/services/api-group/api/service.js
@@ -0,0 +1,27 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'Api',
+ constraints: {
+ name: {
+ presence: true
+ },
+ api: {
+ presence: true,
+ url: {
+ allowLocal: true
+ }
+ }
+ },
+ importConstraints: {
+ apiFile: {
+ presence: true
+ }
+ },
+ substituteConstraints: {
+ target: {
+ presence: true
+ }
+ }
+});
diff --git a/web/app/services/api-group/service.js b/web/app/services/api-group/service.js
new file mode 100644
index 0000000..7fd7bf6
--- /dev/null
+++ b/web/app/services/api-group/service.js
@@ -0,0 +1,14 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'ApiGroup',
+ constraints: {
+ name: {
+ presence: true
+ },
+ loginType: {
+ presence: true
+ }
+ }
+});
diff --git a/web/app/services/app-alias/service.js b/web/app/services/app-alias/service.js
new file mode 100644
index 0000000..253679a
--- /dev/null
+++ b/web/app/services/app-alias/service.js
@@ -0,0 +1,15 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'AppAlias',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ }
+});
diff --git a/web/app/services/app-config/footer-item/service.js b/web/app/services/app-config/footer-item/service.js
new file mode 100644
index 0000000..227f8f0
--- /dev/null
+++ b/web/app/services/app-config/footer-item/service.js
@@ -0,0 +1,91 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+import ValidUrl from 'npm:valid-url';
+
+export default BaseService.extend({
+ modelName: 'AppConfigFooterItem',
+ createConstraints: {
+ name: {
+ presence: true,
+ length: {
+ maximum: 36
+ }
+ },
+ text: {
+ presence: true,
+ length: {
+ maximum: 4
+ }
+ },
+ action: {
+ presence: true,
+ equality: {
+ attribute: 'actionType',
+ message: 'should be a URL or [ph] protocal',
+ comparator: function(action, actionType) {
+ let rtn = true;
+ if (actionType === 'CUSTOM') {
+ if (/^ph\:\/\/(action|view|data|webview)\/[a-zA-z][0-9a-zA-z]*(\-\w+)*/.test(action)) {
+ rtn = ValidUrl.isWebUri(action.replace(/^umsapp/, 'http'));
+ }
+ else {
+ rtn = ValidUrl.isWebUri(action);
+ }
+ }
+ return rtn;
+ }
+ }
+ },
+ textColorNormal: {
+ presence: true
+ },
+ textColorActive: {
+ presence: true
+ },
+ iconNormal: {
+ presence: true
+ },
+ iconActive: {
+ presence: true
+ }
+ },
+ updateConstraints: {
+ name: {
+ presence: true,
+ length: {
+ maximum: 36
+ }
+ },
+ text: {
+ presence: true,
+ length: {
+ maximum: 4
+ }
+ },
+ action: {
+ presence: true,
+ equality: {
+ attribute: 'actionType',
+ message: 'should be a URL or UmsApp protocal',
+ comparator: function(action, actionType) {
+ let rtn = true;
+ if (actionType === 'CUSTOM') {
+ if (/^ph\:\/\/(action|view|data|webview)\/[a-zA-z][0-9a-zA-z]*(\-\w+)*/.test(action)) {
+ rtn = ValidUrl.isWebUri(action.replace(/^umsapp/, 'http'));
+ }
+ else {
+ rtn = ValidUrl.isWebUri(action);
+ }
+ }
+ return rtn;
+ }
+ }
+ },
+ textColorNormal: {
+ presence: true
+ },
+ textColorActive: {
+ presence: true
+ }
+ },
+});
diff --git a/web/app/services/app-config/service.js b/web/app/services/app-config/service.js
new file mode 100644
index 0000000..b772f39
--- /dev/null
+++ b/web/app/services/app-config/service.js
@@ -0,0 +1,24 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'AppConfig',
+ createConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ },
+ updateConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ }
+});
diff --git a/web/app/services/app-version-alias/service.js b/web/app/services/app-version-alias/service.js
new file mode 100644
index 0000000..aec66a8
--- /dev/null
+++ b/web/app/services/app-version-alias/service.js
@@ -0,0 +1,15 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'AppVersionAlias',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ }
+});
diff --git a/web/app/services/app/appoint/service.js b/web/app/services/app/appoint/service.js
new file mode 100644
index 0000000..e5a8556
--- /dev/null
+++ b/web/app/services/app/appoint/service.js
@@ -0,0 +1,21 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'AppVersionAppoint',
+ constraints: {
+ name: {
+ presence: true,
+ },
+ mobile: {
+ presence: true,
+ format: {
+ pattern: /^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/,
+ message: 'Invalid mobile'
+ }
+ },
+ versionId: {
+ presence: true,
+ }
+ }
+});
diff --git a/web/app/services/app/release/service.js b/web/app/services/app/release/service.js
new file mode 100644
index 0000000..a4baefd
--- /dev/null
+++ b/web/app/services/app/release/service.js
@@ -0,0 +1,35 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'AppRelease',
+ constraints: {
+ versionId: {
+ presence: true,
+ equality: {
+ attribute: 'minVersionName',
+ message: '发布版本不能低于最低版本',
+ comparator: function(versionId, minVersionName, constraints, attr, model) {
+ if (minVersionName) {
+ let av1 = model.versionName.split('.');
+ let av2 = minVersionName.split('.');
+
+ for (let i = 0; i < (Math.max(av1.length, av2.length)); ++i) {
+ av1[i] = typeof av1[i] === 'undefined' ? 0 : Number(av1[i]);
+ av2[i] = typeof av2[i] === 'undefined' ? 0 : Number(av2[i]);
+
+ if (av1[i] > av2[i]) {
+ return true;
+ }
+ if (av1[i] < av2[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return true;
+ }
+ }
+ }
+ },
+});
diff --git a/web/app/services/app/service.js b/web/app/services/app/service.js
new file mode 100644
index 0000000..9fc75cf
--- /dev/null
+++ b/web/app/services/app/service.js
@@ -0,0 +1,39 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'App',
+ createConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ icon: {
+ presence: true
+ },
+ apiGroupId: {
+ presence: true
+ },
+ appConfigId: {
+ presence: true
+ }
+ },
+ updateConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ apiGroupId: {
+ presence: true
+ },
+ appConfigId: {
+ presence: true
+ }
+ }
+});
diff --git a/web/app/services/app/version-group/service.js b/web/app/services/app/version-group/service.js
new file mode 100644
index 0000000..ac933ac
--- /dev/null
+++ b/web/app/services/app/version-group/service.js
@@ -0,0 +1,20 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'AppVersionGroup',
+ constraints: {
+ appId: {
+ presence: true
+ },
+ name: {
+ presence: true
+ },
+ androidPhoneVersionId: {
+ presence: true
+ },
+ iphoneVersionId: {
+ presence: true
+ }
+ }
+});
diff --git a/web/app/services/app/version/service.js b/web/app/services/app/version/service.js
new file mode 100644
index 0000000..465a66b
--- /dev/null
+++ b/web/app/services/app/version/service.js
@@ -0,0 +1,35 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'AppVersion',
+ createConstraints: {
+ appId: {
+ presence: true
+ },
+ platform: {
+ presence: true
+ },
+ pkg: {
+ presence: true
+ }
+ },
+ updateConstraints: {
+ metaData: function(value, attributes, attributeName, options, constraints) {
+ if (value) {
+ try {
+ JSON.parse(value);
+ }
+ catch (e) {
+ return {
+ format: {
+ pattern: '^{}$',
+ message: '无效JSONObject格式'
+ }
+ };
+ }
+ }
+ return null;
+ }
+ }
+});
diff --git a/web/app/services/cloud/ad-slide/service.js b/web/app/services/cloud/ad-slide/service.js
new file mode 100644
index 0000000..b7ab00c
--- /dev/null
+++ b/web/app/services/cloud/ad-slide/service.js
@@ -0,0 +1,24 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'AdSlide',
+ pageSize: 64,
+ createConstraints: {
+ url: {
+ url: {
+ allowLocal: true
+ }
+ },
+ image: {
+ presence: true,
+ }
+ },
+ updateConstraints: {
+ url: {
+ url: {
+ allowLocal: true
+ }
+ }
+ }
+});
diff --git a/web/app/services/cloud/corp/biz-group/service.js b/web/app/services/cloud/corp/biz-group/service.js
new file mode 100644
index 0000000..62eff89
--- /dev/null
+++ b/web/app/services/cloud/corp/biz-group/service.js
@@ -0,0 +1,15 @@
+import Ember from 'ember';
+import BaseService from '../../../service';
+
+export default BaseService.extend({
+ modelName: 'BizGroup',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ }
+});
diff --git a/web/app/services/cloud/corp/biz/service.js b/web/app/services/cloud/corp/biz/service.js
new file mode 100644
index 0000000..e621c43
--- /dev/null
+++ b/web/app/services/cloud/corp/biz/service.js
@@ -0,0 +1,39 @@
+import Ember from 'ember';
+import BaseService from '../../../service';
+
+export default BaseService.extend({
+ modelName: 'Biz',
+ createConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ url: {
+ presence: true,
+ url: {
+ allowLocal: true
+ }
+ },
+ icon: {
+ presence: true,
+ }
+ },
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ url: {
+ presence: true,
+ url: {
+ allowLocal: true
+ }
+ }
+ }
+});
diff --git a/web/app/services/cloud/corp/service.js b/web/app/services/cloud/corp/service.js
new file mode 100644
index 0000000..429f3cc
--- /dev/null
+++ b/web/app/services/cloud/corp/service.js
@@ -0,0 +1,7 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'Corp',
+ pageSize: 64
+});
diff --git a/web/app/services/cloud/service.js b/web/app/services/cloud/service.js
new file mode 100644
index 0000000..f2cb9bb
--- /dev/null
+++ b/web/app/services/cloud/service.js
@@ -0,0 +1,21 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'Cloud',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ dataApiUrl: {
+ presence: true,
+ url: {
+ allowLocal: true
+ }
+ }
+ }
+});
diff --git a/web/app/services/corp/contact/service.js b/web/app/services/corp/contact/service.js
new file mode 100644
index 0000000..d986a4b
--- /dev/null
+++ b/web/app/services/corp/contact/service.js
@@ -0,0 +1,14 @@
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'Contact',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ }
+});
diff --git a/web/app/services/corp/dept/service.js b/web/app/services/corp/dept/service.js
new file mode 100644
index 0000000..a492bdb
--- /dev/null
+++ b/web/app/services/corp/dept/service.js
@@ -0,0 +1,14 @@
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'Dept',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ }
+});
diff --git a/web/app/services/corp/employee/service.js b/web/app/services/corp/employee/service.js
new file mode 100644
index 0000000..fe937eb
--- /dev/null
+++ b/web/app/services/corp/employee/service.js
@@ -0,0 +1,22 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'Employee',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ mobile: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ }
+});
diff --git a/web/app/services/corp/service.js b/web/app/services/corp/service.js
new file mode 100644
index 0000000..dbe697b
--- /dev/null
+++ b/web/app/services/corp/service.js
@@ -0,0 +1,22 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'Corp',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 2,
+ maximum: 36
+ }
+ },
+ shortName: {
+ presence: true,
+ length: {
+ minimum: 2,
+ maximum: 36
+ }
+ }
+ }
+});
diff --git a/web/app/services/corp/tiny-app-group/service.js b/web/app/services/corp/tiny-app-group/service.js
new file mode 100644
index 0000000..6a4c0a4
--- /dev/null
+++ b/web/app/services/corp/tiny-app-group/service.js
@@ -0,0 +1,16 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'TinyAppGroup',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ }
+});
+
diff --git a/web/app/services/corp/tiny-app/service.js b/web/app/services/corp/tiny-app/service.js
new file mode 100644
index 0000000..f5b1bfa
--- /dev/null
+++ b/web/app/services/corp/tiny-app/service.js
@@ -0,0 +1,39 @@
+import Ember from 'ember';
+import BaseService from '../../service';
+
+export default BaseService.extend({
+ modelName: 'TinyApp',
+ createConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ url: {
+ presence: true,
+ url: {
+ allowLocal: true
+ }
+ },
+ icon: {
+ presence: true,
+ }
+ },
+ updateConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ url: {
+ presence: true,
+ url: {
+ allowLocal: true
+ }
+ }
+ }
+});
diff --git a/web/app/services/dialog.js b/web/app/services/dialog.js
new file mode 100644
index 0000000..af17de9
--- /dev/null
+++ b/web/app/services/dialog.js
@@ -0,0 +1,39 @@
+import Ember from 'ember';
+
+export default Ember.Service.extend({
+ alert(msg) {
+ bootbox.alert(msg);
+ },
+ error(msg, fnClose) {
+ bootbox.dialog({
+ message: msg,
+ buttons: {
+ danger: {
+ label: '关闭',
+ className: 'btn-danger',
+ callback: fnClose || Ember.$.noop
+ }
+ }
+ });
+ },
+ confirm(msg, fnYes, fnNo) {
+ bootbox.dialog({
+ message: msg,
+ buttons: {
+ success: {
+ label: '确定',
+ className: 'btn-success',
+ callback: fnYes
+ },
+ danger: {
+ label: '取消',
+ className: 'btn-danger',
+ callback: fnNo || Ember.$.noop
+ }
+ }
+ });
+ },
+ dialog(config) {
+ bootbox.dialog(config);
+ }
+});
diff --git a/web/app/services/message.js b/web/app/services/message.js
new file mode 100644
index 0000000..8331463
--- /dev/null
+++ b/web/app/services/message.js
@@ -0,0 +1,30 @@
+import Ember from 'ember';
+
+export default Ember.Service.extend({
+ alert(msg) {
+ this._show_alert_(msg);
+ },
+ warn(msg) {
+ this._show_alert_(msg, '#F6F0F0');
+ },
+ _show_alert_(msg, bg) {
+ Ember.$([
+ ''
+ ].join(''))
+ .prependTo(Ember.$('body'))
+ .animate({'top': '12px' }, 'slow')
+ .fadeOut(2000, function() {
+ Ember.$(this).remove();
+ });
+ }
+});
diff --git a/web/app/services/role/service.js b/web/app/services/role/service.js
new file mode 100644
index 0000000..a21bea3
--- /dev/null
+++ b/web/app/services/role/service.js
@@ -0,0 +1,15 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'Role',
+ constraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ }
+ }
+});
diff --git a/web/app/services/service.js b/web/app/services/service.js
new file mode 100644
index 0000000..e5a0751
--- /dev/null
+++ b/web/app/services/service.js
@@ -0,0 +1,4 @@
+import Ember from 'ember';
+import BaseServiceMixin from '../mixins/services/base-service';
+
+export default Ember.Service.extend(BaseServiceMixin, {});
diff --git a/web/app/services/splash/service.js b/web/app/services/splash/service.js
new file mode 100644
index 0000000..6ca3737
--- /dev/null
+++ b/web/app/services/splash/service.js
@@ -0,0 +1,43 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'Splash',
+ createConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ duration: {
+ presence: true,
+ numericality: {
+ strict: true,
+ onlyInteger: true,
+ greaterThan: 0
+ }
+ },
+ image: {
+ presence: true,
+ }
+ },
+ updateConstraints: {
+ name: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ duration: {
+ presence: true,
+ numericality: {
+ strict: true,
+ onlyInteger: true,
+ greaterThan: 0
+ }
+ }
+ }
+});
diff --git a/web/app/services/store.js b/web/app/services/store.js
new file mode 100644
index 0000000..9c3bf66
--- /dev/null
+++ b/web/app/services/store.js
@@ -0,0 +1,65 @@
+import Ember from 'ember';
+
+export default Ember.Service.extend({
+ list(modelName, start, limit, params) {
+ var p = {
+ start: start,
+ limit: limit
+ };
+ if (Ember.$.type(params) === 'string') {
+ p.search = params;
+ }
+ else {
+ Ember.$.extend(true, p, params);
+ }
+ return this.ajaxGet(this._pathForType(modelName, '/list'), p);
+ },
+ find(modelName, params) {
+ return this.ajaxGet(this._pathForType(modelName, '/find'), params);
+ },
+ count(modelName) {
+ return this.ajaxGet(this._pathForType(modelName, '/count'));
+ },
+ create(modelName, model) {
+ return this.ajaxPost(this._pathForType(modelName, '/create'), model);
+ },
+ update(modelName, model) {
+ return this.ajaxPost(this._pathForType(modelName, '/update'), model);
+ },
+ del(modelName, model) {
+ return this.ajaxPost(this._pathForType(modelName, '/delete'), model);
+ },
+ modelAjaxGet: function(modelName, path, params) {
+ return this.ajaxGet(this._pathForType(modelName, path), params);
+ },
+ modelAjaxPost(modelName, path, params) {
+ return this.ajaxPost(this._pathForType(modelName, path), params);
+ },
+ ajaxGet(url, params) {
+ return this._ajax_request('doGet', url, params);
+ },
+ ajaxPost(url, params) {
+ return this._ajax_request('doPost', url, params);
+ },
+ _ajax_request(method, url, params) {
+ let me = this;
+ return new Ember.RSVP.Promise((resolve, reject) => {
+ let paramsType = Ember.$.type(params);
+ me.ajax[method ? method : 'doGet'](url,
+ paramsType === 'string' ||
+ paramsType === 'number' ?
+ {id: params} : params,
+ (data) => {
+ Ember.run(null, resolve, data);
+ }, (msg, r) => {
+ reject(msg);
+ me.dialog.error(msg || 'Ajax request erorr caused');
+ });
+ }, 'Ambition: Store#ajax request [' + url + ']');
+ },
+ _pathForType(modelName, path) {
+ return (/^[a-zA-Z_][a-zA-Z0-9_]+$/.test(modelName) ?
+ Ember.String.dasherize(modelName) : modelName) +
+ (/^\//.test(path) ? path : '/' + path);
+ }
+});
diff --git a/web/app/services/theme/service.js b/web/app/services/theme/service.js
new file mode 100644
index 0000000..14fb81f
--- /dev/null
+++ b/web/app/services/theme/service.js
@@ -0,0 +1,11 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'Theme',
+ createConstraints: {
+ pkg: {
+ presence: true
+ }
+ }
+});
diff --git a/web/app/services/tool-service.js b/web/app/services/tool-service.js
new file mode 100644
index 0000000..ff29955
--- /dev/null
+++ b/web/app/services/tool-service.js
@@ -0,0 +1,48 @@
+import Ember from 'ember';
+import BaseService from './service';
+import Ajax from './ajax';
+import Store from './store';
+
+export default Ember.Service.extend({
+ getServiceByRouteName: function(routeName) {
+ let me = this;
+ let container = Ember.getOwner(me);
+ let service = container.lookup('service:' + routeName);
+ Ember.Logger.debug(`No Route Service [${routeName}] Found, Try To Find Model Service`);
+ let indexTrimmedRouteName = null;
+ if (/\.index$/.test(routeName)) {
+ Ember.Logger.debug(`Route [${routeName}] Is Index, Try To Trim index Find Model Service`);
+ indexTrimmedRouteName = routeName.replace(/\.index$/, '');
+ service = container.lookup('service:' + indexTrimmedRouteName);
+ if (!service) {
+ Ember.Logger.debug(`Route [${indexTrimmedRouteName}] Is Trimed Index, But No Service Found Still.`);
+ service = container.lookup('service:' + indexTrimmedRouteName + '.service');
+ }
+ }
+ else {
+ service = container.lookup('service:' + routeName + '.service');
+ }
+
+ if (!service) {
+ let parentRouteName = (indexTrimmedRouteName || routeName).replace(/\.[^\.]+$/, '');
+ Ember.Logger.debug(`No Route Model Service [${routeName}.service] Found, Try To Find Parent Service [${parentRouteName}.service]`);
+ if (parentRouteName) {
+ Ember.Logger.debug(`Route [${parentRouteName}] Service Found`);
+ service = container.lookup('service:' + parentRouteName + '.service');
+ }
+
+ if (!service) {
+ Ember.Logger.info('No Service Found, Create Default');
+ let ajax = Ajax.create();
+ service = BaseService.create({
+ modelName: parentRouteName.match(/\.?([^\.]+)$/)[1],
+ store: Store.create({
+ ajax: ajax
+ }),
+ ajax: ajax
+ });
+ }
+ }
+ return service;
+ }
+});
diff --git a/web/app/services/user/service.js b/web/app/services/user/service.js
new file mode 100644
index 0000000..1f9aa59
--- /dev/null
+++ b/web/app/services/user/service.js
@@ -0,0 +1,25 @@
+import Ember from 'ember';
+import BaseService from '../service';
+
+export default BaseService.extend({
+ modelName: 'User',
+ createConstraints: {
+ mobile: {
+ presence: true,
+ length: {
+ minimum: 1,
+ maximum: 36
+ }
+ },
+ password: {
+ presence: true,
+ length: {
+ minimum: 4,
+ maximum: 36
+ }
+ },
+ confirmPassword: {
+ equality: 'password'
+ }
+ }
+});
diff --git a/web/app/styles/app.css b/web/app/styles/app.css
new file mode 100644
index 0000000..b5dc211
--- /dev/null
+++ b/web/app/styles/app.css
@@ -0,0 +1,31 @@
+.umsapp-logo {
+ width: 24px;
+ height: 24px;
+ background: url(../images/umsapp-logo-24x24.png) no-repeat;
+ display: inline-block;
+}
+
+.device {
+ margin: 0 auto;
+ width: 230px;
+ height: 480px;
+ background: url('../images/device-sprite-iPhone-5s.png') no-repeat;
+ background-size: contain;
+}
+
+.device-content {
+ padding: 31% 0 0 0;
+ margin: 0 0 0 8.6%;
+ width: 83%;
+ height: 85.6%;
+ overflow: hidden;
+}
+
+.spinbox-up {
+ border-top-left-radius: 0 !important;
+}
+
+.desktop {
+ background: url('../images/desktop.jpg') no-repeat center center;
+ background-size: contain;
+}
diff --git a/web/app/templates/admin/create.hbs b/web/app/templates/admin/create.hbs
new file mode 100644
index 0000000..ebbd6b4
--- /dev/null
+++ b/web/app/templates/admin/create.hbs
@@ -0,0 +1,28 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'user.list' 1}}
+ 用户列表
+ {{/link-to}}
+
+ 新建用户
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input name='name' label='姓名'}}
+ {{form-input type='file' name='avatar' label='头像'}}
+
+ {{#form-input-select label='性别' name='gender' as |xs|}}
+ {{#xs.option value='M'}}男{{/xs.option}}
+ {{#xs.option value='F'}}女{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input name='loginId' label='账号'}}
+ {{form-input name='mobile' label='手机号'}}
+ {{form-input name='email' label='邮箱'}}
+ {{form-input type='password' name='password' label='登录密码'}}
+ {{form-input type='password' name='confirmPassword' label='重复密码'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/admin/edit.hbs b/web/app/templates/admin/edit.hbs
new file mode 100644
index 0000000..614f761
--- /dev/null
+++ b/web/app/templates/admin/edit.hbs
@@ -0,0 +1,30 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'admin.list' 1}}
+ 用户列表
+ {{/link-to}}
+
+ 编辑用户[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='姓名'}}
+ {{form-input type='file' name='avatar' label='头像' image='avatar'}}
+
+ {{#form-input-select label='性别' name='gender' as |xs|}}
+ {{#xs.option value='M'}}男{{/xs.option}}
+ {{#xs.option value='F'}}女{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input name='loginId' label='账号'}}
+ {{form-input name='mobile' label='手机号'}}
+ {{form-input name='email' label='邮箱'}}
+ {{form-input type='password' name='password' label='登录密码'}}
+ {{form-input type='password' name='confirmPassword' label='重复密码'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/admin/list.hbs b/web/app/templates/admin/list.hbs
new file mode 100644
index 0000000..b9b9668
--- /dev/null
+++ b/web/app/templates/admin/list.hbs
@@ -0,0 +1,82 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 用户列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/admin/profile.hbs b/web/app/templates/admin/profile.hbs
new file mode 100644
index 0000000..7e5a0d0
--- /dev/null
+++ b/web/app/templates/admin/profile.hbs
@@ -0,0 +1,97 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 用户信息[{{model.name}}]
+ {{/breadcrumbs-bar}}
+
+
+
+
+
+
+
+
+
+
+ {{#link-to 'admin.profile.upload-avatar'}}
+
+
+
+ {{/link-to}}
+
+
+
+
+
+
+
账户
+
+
+ {{model.loginId}}
+
+
+
+
+
姓名
+
+
+ {{model.name}}
+
+
+
+
+
性别
+
+
+ {{if (eq 'M' model.gender) '男' '女'}}
+
+
+
+
+
手机号
+
+
+ {{model.mobile}}
+
+
+
+
+
邮箱
+
+
+ {{model.email}}
+
+
+
+
+
+
+
+
+
+ {{#form-content class="no-padding"}}
+ {{input name='id' type='hidden' value=model.id}}
+ {{form-input type='password' name='password' label='登录密码'}}
+ {{form-input type='password' name='confirmPassword' label='重复密码'}}
+ {{form-footer-buttons backRouteName='index' type='update' postUrl='user/update-password'}}
+ {{/form-content}}
+
+
+
+
+
+{{/main-content}}
+{{outlet}}
+
diff --git a/web/app/templates/admin/profile/upload-avatar.hbs b/web/app/templates/admin/profile/upload-avatar.hbs
new file mode 100644
index 0000000..1d8eb25
--- /dev/null
+++ b/web/app/templates/admin/profile/upload-avatar.hbs
@@ -0,0 +1,8 @@
+{{#modal-dialog title='上传头像'}}
+
+{{/modal-dialog}}
diff --git a/web/app/templates/admin/show.hbs b/web/app/templates/admin/show.hbs
new file mode 100644
index 0000000..b1e52f0
--- /dev/null
+++ b/web/app/templates/admin/show.hbs
@@ -0,0 +1,42 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 用户详情
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/api-group/api/create.hbs b/web/app/templates/api-group/api/create.hbs
new file mode 100644
index 0000000..767edce
--- /dev/null
+++ b/web/app/templates/api-group/api/create.hbs
@@ -0,0 +1,24 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'api-group.list' 1}}
+ API组列表
+ {{/link-to}}
+
+
+ {{#link-to 'api-group.api.list' 1}}
+ API列表
+ {{/link-to}}
+
+ 创建API
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='apiGroupId' value=model.apiGroupId}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='api' label='API'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/api-group/api/edit.hbs b/web/app/templates/api-group/api/edit.hbs
new file mode 100644
index 0000000..fba0ac5
--- /dev/null
+++ b/web/app/templates/api-group/api/edit.hbs
@@ -0,0 +1,25 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'api-group.list' 1}}
+ API组列表
+ {{/link-to}}
+
+
+ {{#link-to 'api-group.api.list' 1}}
+ API列表
+ {{/link-to}}
+
+ 编辑API[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+
+ {{form-input name='name' label='名称' readonly="readonly"}}
+ {{form-input name='api' label='API'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/api-group/api/import.hbs b/web/app/templates/api-group/api/import.hbs
new file mode 100644
index 0000000..2dfa1ab
--- /dev/null
+++ b/web/app/templates/api-group/api/import.hbs
@@ -0,0 +1,24 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'api-group.list' 1}}
+ API组列表
+ {{/link-to}}
+
+
+ {{#link-to 'api-group.api.list' 1}}
+ API列表
+ {{/link-to}}
+
+ 导入API
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='apiGroupId' value=model.apiGroupId}}
+ {{form-input type='file' name='apiFile' label='API JSON 文件'}}
+ {{form-input-checkbox name='override' booleanValue=true label='强制覆盖'}}
+ {{form-input name='note' label='备注'}}
+
+ {{! use service#importConstraints to validate}}
+ {{form-footer-buttons type='import' postUrl='api/import' successMsg='导入成功'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/api-group/api/list.hbs b/web/app/templates/api-group/api/list.hbs
new file mode 100644
index 0000000..dc426d2
--- /dev/null
+++ b/web/app/templates/api-group/api/list.hbs
@@ -0,0 +1,86 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'api-group.list' 1}}
+ API组列表
+ {{/link-to}}
+
+ [{{model.apiGroup.name}}]API列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/api-group/api/substitute.hbs b/web/app/templates/api-group/api/substitute.hbs
new file mode 100644
index 0000000..dc75c1e
--- /dev/null
+++ b/web/app/templates/api-group/api/substitute.hbs
@@ -0,0 +1,24 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'api-group.list' 1}}
+ API组列表
+ {{/link-to}}
+
+
+ {{#link-to 'api-group.api.list' 1}}
+ API列表
+ {{/link-to}}
+
+ 替换API
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='apiGroupId' value=model.apiGroupId}}
+ {{form-input name='target' label='查找'}}
+ {{form-input-checkbox name='regexp' label='正则表达式' booleanValue=true}}
+ {{form-input name='replacement' label='替换为'}}
+
+ {{! use service#substituteConstraints to validate}}
+ {{form-footer-buttons type='substitute' postUrl='api/substitute' successMsg='替换成功'}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/api-group/create.hbs b/web/app/templates/api-group/create.hbs
new file mode 100644
index 0000000..ed1138a
--- /dev/null
+++ b/web/app/templates/api-group/create.hbs
@@ -0,0 +1,24 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'api-group.list' 1}}
+ API组列表
+ {{/link-to}}
+
+ 创建API组
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input name='name' label='名称'}}
+
+ {{#form-input-select label='登录方式' name='loginType' as |xs|}}
+ {{#xs.option value='PASSWORD'}}密码{{/xs.option}}
+ {{#xs.option value='SMS_CODE'}}验证码{{/xs.option}}
+ {{#xs.option value='NONE'}}无{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/api-group/edit.hbs b/web/app/templates/api-group/edit.hbs
new file mode 100644
index 0000000..5263734
--- /dev/null
+++ b/web/app/templates/api-group/edit.hbs
@@ -0,0 +1,25 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'api-group.list' 1}}
+ API组列表
+ {{/link-to}}
+
+ 编辑API组[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type="hidden" name="id" value=model.id}}
+ {{form-input name='name' label='名称'}}
+
+ {{#form-input-select label='登录方式' name='loginType' as |xs|}}
+ {{#xs.option value='PASSWORD'}}密码{{/xs.option}}
+ {{#xs.option value='SMS_CODE'}}验证码{{/xs.option}}
+ {{#xs.option value='NONE'}}无{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/api-group/list-select.hbs b/web/app/templates/api-group/list-select.hbs
new file mode 100644
index 0000000..25314c7
--- /dev/null
+++ b/web/app/templates/api-group/list-select.hbs
@@ -0,0 +1,48 @@
+{{#modal-list-select title='API组列表'}}
+
+
+
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ 状态
+
+
+
+ 创建时间
+
+
+
+ 更新时间
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+ {{status-cell model=it}}
+
+ {{date-cell model=it.dateCreated}}
+ {{date-cell model=it.dateUpdated}}
+
+ {{/each}}
+
+{{/modal-list-select}}
diff --git a/web/app/templates/api-group/list.hbs b/web/app/templates/api-group/list.hbs
new file mode 100644
index 0000000..bb0faf0
--- /dev/null
+++ b/web/app/templates/api-group/list.hbs
@@ -0,0 +1,81 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ API组列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/app-alias/list.hbs b/web/app/templates/app-alias/list.hbs
new file mode 100644
index 0000000..ad4499f
--- /dev/null
+++ b/web/app/templates/app-alias/list.hbs
@@ -0,0 +1,66 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ App别名列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/app-config/create.hbs b/web/app/templates/app-config/create.hbs
new file mode 100644
index 0000000..7483d1d
--- /dev/null
+++ b/web/app/templates/app-config/create.hbs
@@ -0,0 +1,29 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'app-config.list' 1}}
+ App配置列表
+ {{/link-to}}
+
+ 新建App配置
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input name='name' label='名称'}}
+
+ {{!form-input-color name='themeColor' label='主题色'}}
+ {{input type='hidden' name='themeColor' value=model.themeColor}}
+
+ {{form-input-color name='headerBgColor' label='顶部导航背景色'}}
+ {{form-input-color name='headerTextColor' label='顶部导航文本色'}}
+ {{form-input type='file' name='headerBgImg' label='顶部导航背景图'}}
+
+ {{form-input-color name='footerTopBorderColor' label='底部菜单上边框颜色'}}
+ {{form-input-color name='footerBgColor' label='底部菜单背景色'}}
+ {{form-input type='file' name='footerBgImg' label='底部菜单背景图'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/app-config/edit.hbs b/web/app/templates/app-config/edit.hbs
new file mode 100644
index 0000000..201b3e4
--- /dev/null
+++ b/web/app/templates/app-config/edit.hbs
@@ -0,0 +1,36 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'app-config.list' 1}}
+ App配置列表
+ {{/link-to}}
+
+ 编辑App配置[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+
+ {{!form-input-color name='themeColor' label='主题色'}}
+ {{input type='hidden' name='themeColor' value=model.themeColor}}
+
+ {{form-input-color name='headerBgColor' label='顶部导航背景色'}}
+ {{form-input-color name='headerTextColor' label='顶部导航文本色'}}
+ {{form-input type='file' name='headerBgImg' label='顶部导航背景图' image='headerBgImgUrl'}}
+ {{#if model.headerBgImgUrl}}
+ {{form-input-checkbox name='deleteHeaderBgImg' label='删除顶部导航背景图' booleanValue=true}}
+ {{/if}}
+
+ {{form-input-color name='footerTopBorderColor' label='底部菜单上边框颜色'}}
+ {{form-input-color name='footerBgColor' label='底部菜单背景色'}}
+ {{form-input type='file' name='footerBgImg' label='底部菜单背景图' image='footerBgImgUrl'}}
+ {{#if model.footerBgImgUrl}}
+ {{form-input-checkbox name='deleteFooterBgImg' label='删除底部菜单背景图' booleanValue=true}}
+ {{/if}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/app-config/footer-item/create.hbs b/web/app/templates/app-config/footer-item/create.hbs
new file mode 100644
index 0000000..638bb3b
--- /dev/null
+++ b/web/app/templates/app-config/footer-item/create.hbs
@@ -0,0 +1,19 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'app-config.list' 1}}
+ App配置列表
+ {{/link-to}}
+
+
+ {{#link-to 'app-config.footer-item.list' 1}}
+ App配置底部项列表
+ {{/link-to}}
+
+ 创建App配置底部项
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{partial 'app-config/footer-item/form'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/app-config/footer-item/edit.hbs b/web/app/templates/app-config/footer-item/edit.hbs
new file mode 100644
index 0000000..92fe098
--- /dev/null
+++ b/web/app/templates/app-config/footer-item/edit.hbs
@@ -0,0 +1,20 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'app-config.list' 1}}
+ App配置列表
+ {{/link-to}}
+
+
+ {{#link-to 'app-config.footer-item.list' 1}}
+ App配置底部项列表
+ {{/link-to}}
+
+ 编辑App配置底部项[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{partial 'app-config/footer-item/form'}}
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/app-config/footer-item/form.hbs b/web/app/templates/app-config/footer-item/form.hbs
new file mode 100644
index 0000000..1d1dcdc
--- /dev/null
+++ b/web/app/templates/app-config/footer-item/form.hbs
@@ -0,0 +1,53 @@
+{{input type='hidden' name='appConfigId' value=model.appConfigId}}
+{{form-input name='name' label='名称'}}
+{{form-input name='text' label='文本'}}
+{{#form-input name='action' label='点击动作' inputClass='col-xs-4 no-padding-right'}}
+
+
+ {{#x-select class='form-control' value=model.actionType as |xs|}}
+ {{#xs.option value='MESSAGE'}}消息{{/xs.option}}
+ {{#xs.option value='WORKBENCH'}}工作台{{/xs.option}}
+ {{#xs.option value='CONTACTS'}}通讯录{{/xs.option}}
+ {{#xs.option value='ALERT'}}提醒{{/xs.option}}
+ {{#xs.option value='ME'}}我{{/xs.option}}
+ {{#xs.option value='CUSTOM'}}自定义{{/xs.option}}
+ {{/x-select}}
+
+ {{#if (eq 'CUSTOM' model.actionType)}}
+
+ {{input class='form-control'
+ type='text'
+ value=model.actionInput
+ placeholder='https://admin.pudonghot.com'
+ }}
+
+ {{/if}}
+ {{input name='action' type='hidden' value=model.action}}
+
+{{/form-input}}
+{{form-input-color name='textColorNormal' label='常规文本颜色'}}
+{{form-input-color name='textColorActive' label='活动文本颜色'}}
+{{form-input type='file' name='iconNormal' label='常规图标' image='iconNormalUrl'}}
+{{#if model.iconNormalSvg}}
+ {{form-input-checkbox name='applyColorToIconNormalSvg' booleanValue=true label='应用常规颜色到图标'}}
+{{/if}}
+{{form-input type='file' name='iconActive' label='活动图标' image='iconActiveUrl'}}
+{{#if model.iconActiveSvg}}
+ {{form-input-checkbox name='applyColorToIconActiveSvg' booleanValue=true label='应用活动颜色到图标'}}
+{{/if}}
+{{form-input-spinner name='sort' label='排序'}}
+{{form-input-checkbox name='noHeader' label='隐藏顶部导航'}}
+{{form-input-checkbox name='noFooter' label='隐藏底部菜单'}}
+
+{{#if (or model.activeItem (eq 'true' firstItem))}}
+ {{input type='hidden' name='active' value=model.active}}
+ {{input type='hidden' name='status' value=model.status}}
+{{else}}
+ {{form-input-checkbox name='active' label='默认选中'}}
+ {{#if model.active}}
+ {{input type='hidden' name='status' value=model.status}}
+ {{else}}
+ {{form-input-checkbox}}
+ {{/if}}
+{{/if}}
+{{form-input name='note' label='备注'}}
diff --git a/web/app/templates/app-config/footer-item/list.hbs b/web/app/templates/app-config/footer-item/list.hbs
new file mode 100644
index 0000000..daaa11f
--- /dev/null
+++ b/web/app/templates/app-config/footer-item/list.hbs
@@ -0,0 +1,117 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'app-config.list' 1}}
+ App配置列表
+ {{/link-to}}
+
+ App配置[{{model.appConfig.name}}]底部项列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/app-config/list-select.hbs b/web/app/templates/app-config/list-select.hbs
new file mode 100644
index 0000000..0267292
--- /dev/null
+++ b/web/app/templates/app-config/list-select.hbs
@@ -0,0 +1,52 @@
+{{#modal-list-select title='App配置列表'}}
+
+
+
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ 预览
+
+
+
+ 状态
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it selectedModel=selectedModel selectedId=selectedId}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+
+
+
+
+
+
+
+ {{status-cell model=it}}
+
+
+ {{/each}}
+
+{{/modal-list-select}}
\ No newline at end of file
diff --git a/web/app/templates/app-config/list.hbs b/web/app/templates/app-config/list.hbs
new file mode 100644
index 0000000..8e0dc7c
--- /dev/null
+++ b/web/app/templates/app-config/list.hbs
@@ -0,0 +1,91 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ App配置列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/app-config/manage.hbs b/web/app/templates/app-config/manage.hbs
new file mode 100644
index 0000000..61e838a
--- /dev/null
+++ b/web/app/templates/app-config/manage.hbs
@@ -0,0 +1,29 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'app-config.list' 1}}
+ App配置列表
+ {{/link-to}}
+
+ 管理App配置[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input model=model errors=errors name='name' label='名称' placeholder='名称'}}
+
+ {{form-input-color model=model errors=errors name='themeColor' label='主题色' placeholder='主题色'}}
+
+ {{form-input-color model=model errors=errors name='headerBgColor' label='顶部导航背景色' placeholder='顶部导航背景色'}}
+ {{form-input-color model=model errors=errors name='headerTextColor' label='顶部导航字体色' placeholder='顶部导航字体色'}}
+ {{form-input type='file' model=model errors=errors name='headerBgImg' label='顶部导航背景图'}}
+
+ {{form-input-color model=model errors=errors name='footerTopBorderColor' label='底部菜单上边框颜色' placeholder='底部菜单上边框颜色'}}
+ {{form-input-color model=model errors=errors name='footerBgColor' label='底部菜单背景色' placeholder='底部菜单背景色'}}
+ {{form-input type='file' model=model errors=errors name='footerBgImg' label='底部菜单背景图'}}
+
+ {{form-input-checkbox model=model}}
+ {{form-input model=model errors=errors name='note' label='备注' placeholder='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/app-version-alias/list.hbs b/web/app/templates/app-version-alias/list.hbs
new file mode 100644
index 0000000..89800a5
--- /dev/null
+++ b/web/app/templates/app-version-alias/list.hbs
@@ -0,0 +1,84 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ App版本别名列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/app/appoint.hbs b/web/app/templates/app/appoint.hbs
new file mode 100644
index 0000000..9acd596
--- /dev/null
+++ b/web/app/templates/app/appoint.hbs
@@ -0,0 +1,8 @@
+{{#app/app-manage
+ category='appoint'
+ pageTitle=(concat 'App[' model.appId ']指定发布管理')
+ tabLinkRouteName='app.appoint.list'
+ appId=model.appId
+ platform=model.platform}}
+ {{outlet}}
+{{/app/app-manage}}
\ No newline at end of file
diff --git a/web/app/templates/app/appoint/create.hbs b/web/app/templates/app/appoint/create.hbs
new file mode 100644
index 0000000..54b5cc8
--- /dev/null
+++ b/web/app/templates/app/appoint/create.hbs
@@ -0,0 +1,20 @@
+{{#form-content}}
+
+ {{input type='hidden' name='appId' value=model.appId}}
+ {{input type='hidden' name='platform' value=model.platform}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='mobile' label='手机号'}}
+
+ {{form-input-modal-select
+ listRoute='app.appoint.create.version-select'
+ idField='versionId'
+ nameField='versionName'
+ params=model
+ label='App版本'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons}}
+{{/form-content}}
+{{outlet}}
\ No newline at end of file
diff --git a/web/app/templates/app/appoint/edit.hbs b/web/app/templates/app/appoint/edit.hbs
new file mode 100644
index 0000000..3835ba9
--- /dev/null
+++ b/web/app/templates/app/appoint/edit.hbs
@@ -0,0 +1,21 @@
+{{#form-content}}
+
+ {{input type='hidden' name='appId' value=model.appId}}
+ {{input type='hidden' name='platform' value=model.platform}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='mobile' label='手机号' readonly='readonly'}}
+
+ {{form-input-modal-select
+ listRoute='app.appoint.edit.version-select'
+ idField='versionId'
+ nameField='versionName'
+ params=model
+ label='App版本'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+{{/form-content}}
+{{outlet}}
\ No newline at end of file
diff --git a/web/app/templates/app/appoint/list.hbs b/web/app/templates/app/appoint/list.hbs
new file mode 100644
index 0000000..2b569df
--- /dev/null
+++ b/web/app/templates/app/appoint/list.hbs
@@ -0,0 +1,68 @@
+
\ No newline at end of file
diff --git a/web/app/templates/app/create.hbs b/web/app/templates/app/create.hbs
new file mode 100644
index 0000000..8320272
--- /dev/null
+++ b/web/app/templates/app/create.hbs
@@ -0,0 +1,49 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'app.list' 1}}
+ App列表
+ {{/link-to}}
+
+ 新建App
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+
+ {{form-input name='name' label='名称'}}
+ {{form-input type='file' name='icon' label='图标(512x512)'}}
+
+ {{form-input-modal-select
+ listRoute='app.create.api-group-select'
+ idField='apiGroupId'
+ nameField='apiGroupName'
+ btnIcon='fa-plug'
+ label='API组'}}
+
+ {{form-input-modal-select
+ listRoute='app.create.splash-select'
+ idField='splashId'
+ nameField='splashName'
+ btnIcon='fa-file-image-o'
+ label='启动图'}}
+
+ {{form-input-modal-select
+ listRoute='app.create.app-config-select'
+ idField='appConfigId'
+ nameField='appConfigName'
+ btnIcon='fa-bars'
+ label='App配置'}}
+
+ {{form-input-modal-select
+ listRoute='app.create.theme-select'
+ idField='themeId'
+ nameField='themeName'
+ btnIcon='fa-suitcase'
+ label='主题包'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
diff --git a/web/app/templates/app/edit.hbs b/web/app/templates/app/edit.hbs
new file mode 100644
index 0000000..a0605eb
--- /dev/null
+++ b/web/app/templates/app/edit.hbs
@@ -0,0 +1,51 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'app.list' 1}}
+ App列表
+ {{/link-to}}
+
+ 编辑App[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+
+ {{form-input name='id' label='App ID' readonly='readonly'}}
+
+ {{form-input name='name' label='名称'}}
+ {{form-input type='file' name='icon' label='图标(512x512)' image='iconUrl'}}
+
+ {{form-input-modal-select
+ listRoute='app.edit.api-group-select'
+ idField='apiGroupId'
+ nameField='apiGroupName'
+ btnIcon='fa-plug'
+ label='API组'}}
+
+ {{form-input-modal-select
+ listRoute='app.edit.splash-select'
+ idField='splashId'
+ nameField='splashName'
+ btnIcon='fa-file-image-o'
+ label='启动图'}}
+
+ {{form-input-modal-select
+ listRoute='app.edit.app-config-select'
+ idField='appConfigId'
+ nameField='appConfigName'
+ btnIcon='fa-bars'
+ label='App配置'}}
+
+ {{form-input-modal-select
+ listRoute='app.edit.theme-select'
+ idField='themeId'
+ nameField='themeName'
+ btnIcon='fa-suitcase'
+ label='主题包'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/app/list-select-for-subitem-select.hbs b/web/app/templates/app/list-select-for-subitem-select.hbs
new file mode 100644
index 0000000..dde3113
--- /dev/null
+++ b/web/app/templates/app/list-select-for-subitem-select.hbs
@@ -0,0 +1,77 @@
+{{#modal-frame title='App列表'}}
+
+
+
+
+
+
+
+ App ID
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ 状态
+
+
+
+ 选择
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{it.id}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+ {{status-cell model=it}}
+
+
+ {{#link-to (concat parentRouteName '.' (if subitemRouteName subitemRouteName 'version-select')) 1
+ (query-params
+ appId=it.id
+ platform=platform
+ idField=idField
+ nameField=nameField
+ selectedId=selectedId)
+ activeClass=''
+ class='btn btn-sm btn-purple'
+ rel='tooltip'
+ title=selectText}}
+
+ 选择
+ {{/link-to}}
+
+
+ {{/each}}
+
+
+
+ {{pagination-bar}}
+
+
+{{/modal-frame}}
diff --git a/web/app/templates/app/list-select-for-version-select.hbs b/web/app/templates/app/list-select-for-version-select.hbs
new file mode 100644
index 0000000..0ce13cd
--- /dev/null
+++ b/web/app/templates/app/list-select-for-version-select.hbs
@@ -0,0 +1,77 @@
+{{#modal-frame title='App列表'}}
+
+
+
+
+
+
+
+ App ID
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ 状态
+
+
+
+ 版本
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{it.id}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+ {{status-cell model=it}}
+
+
+ {{#link-to versionRouteName 1
+ (query-params
+ appId=it.id
+ platform=platform
+ idField=idField
+ nameField=nameField
+ selectedId=selectedId)
+ activeClass=''
+ class='btn btn-sm btn-purple'
+ rel='tooltip'
+ title=selectText}}
+
+ 选择
+ {{/link-to}}
+
+
+ {{/each}}
+
+
+
+ {{pagination-bar}}
+
+
+{{/modal-frame}}
diff --git a/web/app/templates/app/list-select.hbs b/web/app/templates/app/list-select.hbs
new file mode 100644
index 0000000..6d50a38
--- /dev/null
+++ b/web/app/templates/app/list-select.hbs
@@ -0,0 +1,44 @@
+{{#modal-list-select title='App列表'}}
+
+
+
+
+
+ ID
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ 状态
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it selectedModel=selectedModel selectedId=selectedId}}
+
+
+ {{it.id}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+ {{status-cell model=it}}
+
+
+ {{/each}}
+
+{{/modal-list-select}}
\ No newline at end of file
diff --git a/web/app/templates/app/list.hbs b/web/app/templates/app/list.hbs
new file mode 100644
index 0000000..378bba5
--- /dev/null
+++ b/web/app/templates/app/list.hbs
@@ -0,0 +1,90 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ App列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/app/release.hbs b/web/app/templates/app/release.hbs
new file mode 100644
index 0000000..6c54faa
--- /dev/null
+++ b/web/app/templates/app/release.hbs
@@ -0,0 +1,9 @@
+{{#app/app-manage
+ category='release'
+ pageTitle=(concat 'App[' model.appId ']发布管理')
+ tabLinkRouteName='app.release.show'
+ page=false
+ appId=model.appId
+ platform=model.platform}}
+ {{outlet}}
+{{/app/app-manage}}
diff --git a/web/app/templates/app/release/edit.hbs b/web/app/templates/app/release/edit.hbs
new file mode 100644
index 0000000..96ad62d
--- /dev/null
+++ b/web/app/templates/app/release/edit.hbs
@@ -0,0 +1,28 @@
+{{#form-content}}
+
+ {{input type='hidden' name='appId' value=model.appId}}
+ {{input type='hidden' name='platform' value=model.platform}}
+ {{input type='hidden' name='id' value=model.id}}
+
+ {{form-input-modal-select
+ listRoute='app.release.edit.version-select'
+ idField='versionId'
+ nameField='versionName'
+ params=model
+ label='发布版本'}}
+
+ {{form-input-modal-select
+ listRoute='app.release.edit.version-select'
+ idField='minVersionId'
+ nameField='minVersionName'
+ params=model
+ label='最低版本'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'
+ backRouteName='app.release.show'
+ backRouteParams=(hash appId=model.appId platform=model.platform)}}
+{{/form-content}}
+{{outlet}}
\ No newline at end of file
diff --git a/web/app/templates/app/release/show.hbs b/web/app/templates/app/release/show.hbs
new file mode 100644
index 0000000..8b36067
--- /dev/null
+++ b/web/app/templates/app/release/show.hbs
@@ -0,0 +1,51 @@
+
diff --git a/web/app/templates/app/version-group/create.hbs b/web/app/templates/app/version-group/create.hbs
new file mode 100644
index 0000000..3b82395
--- /dev/null
+++ b/web/app/templates/app/version-group/create.hbs
@@ -0,0 +1,54 @@
+{{#breadcrumbs-bar}}
+
+ {{#link-to 'app.version-group.list' 1}}
+ 版本组列表
+ {{/link-to}}
+
+ 新建版本组
+{{/breadcrumbs-bar}}
+{{app/manage-sidebar appId=model.appId category='versionGroup'}}
+
+{{#main-content}}
+ {{#form-content}}
+ {{input type='hidden' name='appId' value=model.appId}}
+ {{form-input name='name' label='名称'}}
+
+ {{form-input-modal-select
+ listRoute='app.version-group.create.version-select'
+ idField='androidPhoneVersionId'
+ nameField='androidPhoneVersionName'
+ params=(hash platform='AndroidPhone')
+ btnIcon='fa-code-fork'
+ label='Android Phone 版本'}}
+
+ {{form-input-modal-select
+ listRoute='app.version-group.create.version-select'
+ idField='iphoneVersionId'
+ nameField='iphoneVersionName'
+ params=(hash platform='iPhone')
+ btnIcon='fa-code-fork'
+ label='iPhone 版本'}}
+
+ {{form-input-modal-select
+ listRoute='app.version-group.create.version-select'
+ idField='androidPadVersionId'
+ nameField='androidPadVersionName'
+ params=(hash platform='AndroidPad')
+ btnIcon='fa-code-fork'
+ label='Android Pad 版本'}}
+
+ {{form-input-modal-select
+ listRoute='app.version-group.create.version-select'
+ idField='ipadVersionId'
+ nameField='ipadVersionName'
+ params=(hash platform='iPad')
+ btnIcon='fa-code-fork'
+ label='iPad 版本'}}
+
+ {{form-input type='file' name='icon' label='图标'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
+{{outlet}}
diff --git a/web/app/templates/app/version-group/edit.hbs b/web/app/templates/app/version-group/edit.hbs
new file mode 100644
index 0000000..9f80d24
--- /dev/null
+++ b/web/app/templates/app/version-group/edit.hbs
@@ -0,0 +1,60 @@
+{{#breadcrumbs-bar}}
+
+ {{#link-to 'app.list' 1}}
+ App列表
+ {{/link-to}}
+
+
+ {{#link-to 'app.version-group.list' 1}}
+ 版本组列表
+ {{/link-to}}
+
+ 新建版本组
+{{/breadcrumbs-bar}}
+{{app/manage-sidebar appId=model.appId category='versionGroup'}}
+
+{{#main-content}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+
+ {{form-input-modal-select
+ listRoute='app.version-group.edit.version-select'
+ idField='androidPhoneVersionId'
+ nameField='androidPhoneVersionName'
+ params=(hash platform='AndroidPhone')
+ btnIcon='fa-code-fork'
+ label='Android Phone 版本'}}
+
+ {{form-input-modal-select
+ listRoute='app.version-group.edit.version-select'
+ idField='iphoneVersionId'
+ nameField='iphoneVersionName'
+ params=(hash platform='iPhone')
+ btnIcon='fa-code-fork'
+ label='iPhone 版本'}}
+
+ {{form-input-modal-select
+ listRoute='app.version-group.edit.version-select'
+ idField='androidPadVersionId'
+ nameField='androidPadVersionName'
+ params=(hash platform='AndroidPad')
+ btnIcon='fa-code-fork'
+ label='Android Pad 版本'}}
+
+ {{form-input-modal-select
+ listRoute='app.version-group.edit.version-select'
+ idField='ipadVersionId'
+ nameField='ipadVersionName'
+ params=(hash platform='iPad')
+ btnIcon='fa-code-fork'
+ label='iPad 版本'}}
+
+ {{form-input type='file' name='icon' label='图标' image='icon'}}
+ {{form-input-checkbox name='deleteIcon' booleanValue=true label='删除图标'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
+{{outlet}}
diff --git a/web/app/templates/app/version-group/list-select.hbs b/web/app/templates/app/version-group/list-select.hbs
new file mode 100644
index 0000000..8318506
--- /dev/null
+++ b/web/app/templates/app/version-group/list-select.hbs
@@ -0,0 +1,47 @@
+{{#modal-list-select title=(concat 'App[' appId ']版本组列表')}}
+
+
+
+
+
+ 名称
+
+
+ Android Phone 版本
+
+
+ iPhone 版本
+
+ 图标
+
+
+ 状态
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it selectedModel=selectedModel selectedId=selectedId}}
+
+
+ {{it.name}}
+
+
+ {{it.androidPhoneVersionName}}
+
+
+ {{it.iphoneVersionName}}
+
+
+ {{image-previews previews=it.icon}}
+
+
+ {{status-cell model=it}}
+
+
+ {{/each}}
+
+{{/modal-list-select}}
diff --git a/web/app/templates/app/version-group/list.hbs b/web/app/templates/app/version-group/list.hbs
new file mode 100644
index 0000000..b7b54f5
--- /dev/null
+++ b/web/app/templates/app/version-group/list.hbs
@@ -0,0 +1,91 @@
+{{#breadcrumbs-bar}}
+
+ {{#link-to 'app.list' 1}}
+ App列表
+ {{/link-to}}
+
+ 版本组列表
+{{/breadcrumbs-bar}}
+{{app/manage-sidebar category='versionGroup'}}
+
+{{#main-content}}
+
+{{/main-content}}
diff --git a/web/app/templates/app/version.hbs b/web/app/templates/app/version.hbs
new file mode 100644
index 0000000..7016b17
--- /dev/null
+++ b/web/app/templates/app/version.hbs
@@ -0,0 +1,8 @@
+{{#app/app-manage
+ category='version'
+ pageTitle=(concat 'App[' model.appId ']版本管理')
+ tabLinkRouteName='app.version.list'
+ appId=model.appId
+ platform=model.platform}}
+ {{outlet}}
+{{/app/app-manage}}
\ No newline at end of file
diff --git a/web/app/templates/app/version/create.hbs b/web/app/templates/app/version/create.hbs
new file mode 100644
index 0000000..cd7afe2
--- /dev/null
+++ b/web/app/templates/app/version/create.hbs
@@ -0,0 +1,20 @@
+{{#form-content}}
+ {{input type='hidden' name='appId' value=model.appId}}
+ {{input type='hidden' name='platform' value=model.platform}}
+ {{#if (or (eq 'AndroidPhone' model.platform) (eq 'AndroidPad' model.platform))}}
+ {{form-input name='appName' label='App名称' placeholder='程序名称,二维码名称'}}
+ {{form-input name='downloadName' label='App下载文件名'}}
+ {{/if}}
+ {{form-input type='file' name='pkg' label='安装包'}}
+ {{form-input type='file' name='icon' label='安装图标(512x512)'}}
+ {{form-input-checkbox}}
+ {{form-input-checkbox name='override' label='覆盖已存在版本' booleanValue=true}}
+ {{#form-input label='发布说明' inputClass='col-xs-8'}}
+ {{wysiwyg-editor name='releaseNote'}}
+ {{/form-input}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons
+ backRouteName='app.version.edit'
+ backRouteParams=model}}
+{{/form-content}}
diff --git a/web/app/templates/app/version/edit.hbs b/web/app/templates/app/version/edit.hbs
new file mode 100644
index 0000000..d9086e9
--- /dev/null
+++ b/web/app/templates/app/version/edit.hbs
@@ -0,0 +1,64 @@
+{{#form-content}}
+
+ {{input type='hidden' name='appId' value=model.appId}}
+ {{input type='hidden' name='platform' value=model.platform}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{#if (or (eq 'AndroidPhone' model.platform) (eq 'AndroidPad' model.platform))}}
+ {{form-input name='appName' label='App名称'}}
+ {{/if}}
+ {{form-input name='name' label='版本名称' readonly='readonly'}}
+ {{form-input type='file' name='icon' label='安装图标(512x512)' image='icon'}}
+
+ {{form-input-modal-select
+ listRoute='app.version.edit.api-group-select'
+ idField='apiGroupId'
+ nameField='apiGroupName'
+ btnIcon='fa-plug'
+ label='API组'}}
+
+ {{form-input-modal-select
+ listRoute='app.version.edit.splash-select'
+ idField='splashId'
+ nameField='splashName'
+ btnIcon='fa-file-image-o'
+ label='启动图'}}
+
+ {{form-input-modal-select
+ listRoute='app.version.edit.app-config-select'
+ idField='appConfigId'
+ nameField='appConfigName'
+ btnIcon='fa-bars'
+ label='App配置'}}
+
+ {{form-input-modal-select
+ listRoute='app.version.edit.theme-select'
+ idField='themeId'
+ nameField='themeName'
+ btnIcon='fa-suitcase'
+ label='主题包'}}
+
+ {{form-input-modal-select
+ listRoute='app.version.edit.version-select'
+ idField='updateToVersionId'
+ nameField='updateToVersionName'
+ params=model
+ btnIcon='fa-code-fork'
+ label='升级版本'}}
+
+ {{form-input-checkbox name='disableUpdate' label='禁止升级'}}
+ {{form-input-checkbox}}
+ {{form-input type='textarea'
+ name='metaData'
+ label='元数据(JSONObject)'
+ placeholder='{"corpId": "5736da7888c24e4c24a7db45"}'
+ }}
+
+ {{#form-input label='发布说明' inputClass='col-xs-8'}}
+ {{wysiwyg-editor name='releaseNote'}}
+ {{/form-input}}
+
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+{{/form-content}}
+{{outlet}}
diff --git a/web/app/templates/app/version/list-select.hbs b/web/app/templates/app/version/list-select.hbs
new file mode 100644
index 0000000..1b2c75b
--- /dev/null
+++ b/web/app/templates/app/version/list-select.hbs
@@ -0,0 +1,54 @@
+{{#modal-list-select title=(concat 'App[' appId '][' platform ']版本列表')}}
+
+
+
+
+
+ App名称
+
+
+ 版本名称
+
+
+
+ 备注
+
+
+
+ 升级版本
+
+
+
+ 禁止升级
+
+
+
+ 状态
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it selectedModel=selectedModel selectedId=selectedId}}
+
+
+ {{it.appName}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+ {{it.updateToVersionName}}
+ {{status-cell name='disableUpdate' model=it enabledText='是' disabledText='否'}}
+
+ {{status-cell model=it}}
+
+
+ {{/each}}
+
+{{/modal-list-select}}
diff --git a/web/app/templates/app/version/list.hbs b/web/app/templates/app/version/list.hbs
new file mode 100644
index 0000000..a07d4f8
--- /dev/null
+++ b/web/app/templates/app/version/list.hbs
@@ -0,0 +1,90 @@
+
diff --git a/web/app/templates/application.hbs b/web/app/templates/application.hbs
new file mode 100644
index 0000000..94a4f74
--- /dev/null
+++ b/web/app/templates/application.hbs
@@ -0,0 +1,19 @@
+{{#if ajax.loading}}
+
+{{/if}}
+
+{{#if login}}
+ {{outlet}}
+{{else}}
+ {{top-navbar}}
+ {{#main-container}}
+ {{outlet}}
+ {{/main-container}}
+{{/if}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/ad-slide/create.hbs b/web/app/templates/cloud/ad-slide/create.hbs
new file mode 100644
index 0000000..1c08369
--- /dev/null
+++ b/web/app/templates/cloud/ad-slide/create.hbs
@@ -0,0 +1,71 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+ {{#if corpId}}
+
+ {{#link-to 'cloud.ad-slide.manage' (query-params corpId=corpId)}}
+ 企业[{{model.corp.name}}]广告页列表
+ {{/link-to}}
+ {{else}}
+
+ {{#link-to 'cloud.ad-slide.list' 1}}
+ 云端[{{model.cloud.name}}]广告页列表
+ {{/link-to}}
+ {{/if}}
+
+ 新建广告页
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='cloudId' value=model.cloud.id}}
+ {{#if corpId}}
+ {{input type='hidden' name='corpId' value=corpId}}
+ {{else}}
+ {{form-input-modal-select
+ listRoute='cloud.ad-slide.create.corp-select'
+ idField='corpId'
+ nameField='corpName'
+ btnIcon='glyphicon-registration-mark'
+ label='企业'}}
+ {{/if}}
+
+ {{form-input name='url' label='链接URL'}}
+ {{form-input type='file' name='image' label='图片'}}
+
+ {{form-input-modal-select
+ listRoute='cloud.ad-slide.create.app-select'
+ idField='appId'
+ nameField='appName'
+ btnIcon='fa-cube'
+ label='App'}}
+
+ {{#form-input-select label='平台' name='platform' as |xs|}}
+ {{#xs.option value='AndroidPhone'}}Android Phone{{/xs.option}}
+ {{#xs.option value='iPhone'}}iPhone{{/xs.option}}
+ {{#xs.option value='AndroidPad'}}Android Pad{{/xs.option}}
+ {{#xs.option value='iPad'}}iPad{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input-modal-select
+ listRoute=(if model.appId 'cloud.ad-slide.create.version-select' 'cloud.ad-slide.create.app-select-for-version-select')
+ idField='appVersionId'
+ nameField='appVersionName'
+ params=(hash appId=model.appId platform=model.platform)
+ btnIcon=(if (or (eq model.platform 'AndroidPhone') (eq model.platform 'AndroidPad')) 'fa-android' 'fa-apple')
+ label='App 版本'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons
+ backRouteName=(if corpId 'cloud.ad-slide.manage')
+ backRouteParams=(if corpId false)
+ backRouteQueryParams=(if corpId (hash corpId=corpId))
+ }}
+ {{/form-content}}
+{{/main-content}}
+{{outlet}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/ad-slide/edit.hbs b/web/app/templates/cloud/ad-slide/edit.hbs
new file mode 100644
index 0000000..018ef7e
--- /dev/null
+++ b/web/app/templates/cloud/ad-slide/edit.hbs
@@ -0,0 +1,41 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.ad-slide.list' 1}}
+ 云端[{{model.cloud.name}}]广告页列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.ad-slide.manage'
+ (query-params
+ appId=model.appId
+ platform=model.platform
+ appVersion=model.appVersion)}}
+ 广告页管理
+ {{/link-to}}
+
+ 编辑广告页
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='cloudId' value=model.cloud.id}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='url' label='链接URL'}}
+ {{form-input type='file' name='image' label='图片' image='image'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons type='update'
+ backRouteName='cloud.ad-slide.manage'
+ backRouteParams=(array model.cloud.id)
+ backRouteQueryParams=(hash appId=model.appId platform=model.platform appVersion=model.appVersion)}}
+ }}
+ {{/form-content}}
+{{/main-content}}
+{{outlet}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/ad-slide/list.hbs b/web/app/templates/cloud/ad-slide/list.hbs
new file mode 100644
index 0000000..aceba8d
--- /dev/null
+++ b/web/app/templates/cloud/ad-slide/list.hbs
@@ -0,0 +1,87 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ 云端[{{model.cloud.name}}]广告页列表
+
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/ad-slide/manage.hbs b/web/app/templates/cloud/ad-slide/manage.hbs
new file mode 100644
index 0000000..9ada145
--- /dev/null
+++ b/web/app/templates/cloud/ad-slide/manage.hbs
@@ -0,0 +1,78 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+ {{#if corpId}}
+
+ {{#link-to 'cloud.corp.list' 1}}
+ 云端[{{model.cloud.name}}]企业列表
+ {{/link-to}}
+ {{else}}
+
+ {{#link-to 'cloud.ad-slide.list' 1}}
+ 云端[{{model.cloud.name}}]广告页列表
+ {{/link-to}}
+ {{/if}}
+
+
+
+ {{#if model.corp}}
+ [{{model.corp.name}}]
+ {{else}}
+ [{{appId}}][{{platform}}][{{appVersion}}]
+ {{/if}}
+ 广告页管理
+
+ {{/breadcrumbs-bar}}
+
+
+ {{outlet}}
+{{/main-content}}
diff --git a/web/app/templates/cloud/corp/biz-group/create.hbs b/web/app/templates/cloud/corp/biz-group/create.hbs
new file mode 100644
index 0000000..b5d4ad1
--- /dev/null
+++ b/web/app/templates/cloud/corp/biz-group/create.hbs
@@ -0,0 +1,34 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.list' 1}}
+ 云端[{{model.cloud.name}}]企业列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.biz-manage' model.corp.id (query-params selected=model.corp.id)}}
+ 企业[{{model.corp.name}}]业务管理
+ {{/link-to}}
+
+ 创建业务分组
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='cloudId' value=model.cloud.id}}
+ {{input type='hidden' name='corpId' value=model.corp.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons
+ backRouteName='cloud.corp.biz-manage'
+ backRouteParams=(array model.cloud.id model.corp.id)
+ backRouteQueryParams=(hash selected=model.corp.id)}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/corp/biz-group/edit.hbs b/web/app/templates/cloud/corp/biz-group/edit.hbs
new file mode 100644
index 0000000..cd7e9cd
--- /dev/null
+++ b/web/app/templates/cloud/corp/biz-group/edit.hbs
@@ -0,0 +1,36 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.list' 1}}
+ 云端[{{model.cloud.name}}]企业列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.biz-manage' model.corp.id (query-params selected=model.corp.id)}}
+ 企业[{{model.corp.name}}]业务管理
+ {{/link-to}}
+
+ 编辑业务分组[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='cloudId' value=model.cloud.id}}
+ {{input type='hidden' name='corpId' value=model.corp.id}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{input type='hidden' name='sort' value=model.sort}}
+ {{form-input name='name' label='名称'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons type='update'
+ backRouteName='cloud.corp.biz-manage'
+ backRouteParams=(array model.cloud.id model.corp.id)
+ backRouteQueryParams=(hash selected=model.corp.id)}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/corp/biz-manage.hbs b/web/app/templates/cloud/corp/biz-manage.hbs
new file mode 100644
index 0000000..0d6d7fb
--- /dev/null
+++ b/web/app/templates/cloud/corp/biz-manage.hbs
@@ -0,0 +1,156 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.list' 1}}
+ 云端[{{model.cloud.name}}]企业列表
+ {{/link-to}}
+
+
+
+ 企业[{{model.corp.name}}]业务管理
+
+ {{/breadcrumbs-bar}}
+
+
+
+ {{outlet}}
+{{/main-content}}
diff --git a/web/app/templates/cloud/corp/biz/create.hbs b/web/app/templates/cloud/corp/biz/create.hbs
new file mode 100644
index 0000000..9966b53
--- /dev/null
+++ b/web/app/templates/cloud/corp/biz/create.hbs
@@ -0,0 +1,43 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.list' 1}}
+ 云端[{{model.cloud.name}}]企业列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.biz-manage' model.corp.id (query-params selected=model.corp.id)}}
+ 企业[{{model.corp.name}}]业务管理
+ {{/link-to}}
+
+ 创建业务
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='cloudId' value=model.cloud.id}}
+ {{input type='hidden' name='corpId' value=model.corp.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='url' label='URL'}}
+ {{form-input type='file' name='icon' label='图标'}}
+
+ {{#form-input-select label='业务分组' name='groupId' as |xs|}}
+ {{#each model.bizGroups as |bg|}}
+ {{#xs.option value=bg.id}}{{bg.name}}{{/xs.option}}
+ {{/each}}
+ {{/form-input-select}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons
+ backRouteName='cloud.corp.biz-manage'
+ backRouteParams=(array model.cloud.id model.corp.id)
+ backRouteQueryParams=(hash selected=model.corp.id)}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/corp/biz/edit.hbs b/web/app/templates/cloud/corp/biz/edit.hbs
new file mode 100644
index 0000000..7ddd414
--- /dev/null
+++ b/web/app/templates/cloud/corp/biz/edit.hbs
@@ -0,0 +1,46 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.list' 1}}
+ 云端[{{model.cloud.name}}]企业列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.biz-manage' model.corp.id (query-params selected=model.corp.id)}}
+ 企业[{{model.corp.name}}]业务管理
+ {{/link-to}}
+
+ 编辑业务[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='cloudId' value=model.cloud.id}}
+ {{input type='hidden' name='corpId' value=model.corp.id}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='url'
+ label='URL'
+ readonly=(if (eq model.origin 'External') 'readonly')}}
+ {{form-input type='file' name='icon' label='图标' image='icon'}}
+
+ {{#form-input-select label='业务分组' name='groupId' as |xs|}}
+ {{#each model.bizGroups as |bg|}}
+ {{#xs.option value=bg.id}}{{bg.name}}{{/xs.option}}
+ {{/each}}
+ {{/form-input-select}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons type='update'
+ backRouteName='cloud.corp.biz-manage'
+ backRouteParams=(array model.cloud.id model.corp.id)
+ backRouteQueryParams=(hash selected=model.corp.id)}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/corp/list-select.hbs b/web/app/templates/cloud/corp/list-select.hbs
new file mode 100644
index 0000000..aec4457
--- /dev/null
+++ b/web/app/templates/cloud/corp/list-select.hbs
@@ -0,0 +1,45 @@
+{{#modal-list-select title=(concat '云端[' model.cloud.name ']企业列表')}}
+
+
+
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ Logo
+
+
+
+ 状态
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it selectedModel=selectedModel selectedId=selectedId}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+ {{image-previews previews=it.icon}}
+
+
+ {{status-cell model=it}}
+
+
+ {{/each}}
+
+{{/modal-list-select}}
diff --git a/web/app/templates/cloud/corp/list.hbs b/web/app/templates/cloud/corp/list.hbs
new file mode 100644
index 0000000..e9d24de
--- /dev/null
+++ b/web/app/templates/cloud/corp/list.hbs
@@ -0,0 +1,83 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ 云端[{{model.cloud.name}}]企业列表
+
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/corp/manage.hbs b/web/app/templates/cloud/corp/manage.hbs
new file mode 100644
index 0000000..25ccae1
--- /dev/null
+++ b/web/app/templates/cloud/corp/manage.hbs
@@ -0,0 +1,88 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+
+
+ {{#link-to 'cloud.corp.list' 1}}
+ 云端[{{model.cloud.name}}]企业列表
+ {{/link-to}}
+
+
+
+ 企业[{{model.corp.name}}]管理
+
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='cloudId' value=model.cloud.id}}
+ {{input type='hidden' name='corpId' value=model.corp.id}}
+
+ {{form-input type='file' name='icon' label='图标' image='corp.icon'}}
+
+ {{form-input-modal-select
+ name='appId'
+ listRoute='cloud.corp.manage.app-select'
+ idField='corpExt.appId'
+ nameField='corpExt.appName'
+ btnIcon='fa-cube'
+ label='App'}}
+
+ {{form-input-modal-select
+ name='appVersionGroupId'
+ listRoute='cloud.corp.manage.app-select-for-version-group-select'
+ idField='corpExt.appVersionGroupId'
+ nameField='corpExt.appVersionGroupName'
+ params=(hash subitemRouteName='version-group-select')
+ btnIcon='fa-object-group'
+ label='App版本组'}}
+
+ {{!form-input-modal-select
+ name='androidPhoneVersionId'
+ listRoute='cloud.corp.manage.app-select-for-version-select'
+ idField='corpExt.androidPhoneVersionId'
+ nameField='corpExt.androidPhoneVersionName'
+ params=(hash platform='AndroidPhone')
+ btnIcon='fa-android'
+ label='Android Phone 版本'}}
+
+ {{!form-input-modal-select
+ name='iPhoneVersionId'
+ listRoute='cloud.corp.manage.app-select-for-version-select'
+ idField='corpExt.iPhoneVersionId'
+ nameField='corpExt.iPhoneVersionName'
+ params=(hash platform='iPhone')
+ btnIcon='fa-apple'
+ label='iPhone 版本'}}
+
+ {{form-input-modal-select
+ name='splashId'
+ listRoute='cloud.corp.manage.splash-select'
+ idField='corpExt.splashId'
+ nameField='corpExt.splashName'
+ btnIcon='fa-file-image-o'
+ label='启动图'}}
+
+ {{form-input-modal-select
+ name='appConfigId'
+ listRoute='cloud.corp.manage.app-config-select'
+ idField='corpExt.appConfigId'
+ nameField='corpExt.appConfigName'
+ btnIcon='fa-bars'
+ label='App配置'}}
+
+ {{form-input-modal-select
+ name='themeId'
+ listRoute='cloud.corp.manage.theme-select'
+ idField='corpExt.themeId'
+ nameField='corpExt.themeName'
+ btnIcon='fa-suitcase'
+ label='主题包'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/corp/member/list.hbs b/web/app/templates/cloud/corp/member/list.hbs
new file mode 100644
index 0000000..c24cd68
--- /dev/null
+++ b/web/app/templates/cloud/corp/member/list.hbs
@@ -0,0 +1 @@
+{{outlet}}
diff --git a/web/app/templates/cloud/create.hbs b/web/app/templates/cloud/create.hbs
new file mode 100644
index 0000000..a5ad5c0
--- /dev/null
+++ b/web/app/templates/cloud/create.hbs
@@ -0,0 +1,19 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+ 新建云端
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='dataApiUrl' label='数据接口地址'}}
+ {{form-input name='authKey' label='认证Key'}}
+ {{form-input name='authSecret' label='认证Secret'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/edit.hbs b/web/app/templates/cloud/edit.hbs
new file mode 100644
index 0000000..9ba108b
--- /dev/null
+++ b/web/app/templates/cloud/edit.hbs
@@ -0,0 +1,20 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'cloud.list' 1}}
+ 云端列表
+ {{/link-to}}
+
+ 编辑云端[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='dataApiUrl' label='数据接口地址'}}
+ {{form-input name='authKey' label='认证Key'}}
+ {{form-input name='authSecret' label='认证Secret'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/cloud/list.hbs b/web/app/templates/cloud/list.hbs
new file mode 100644
index 0000000..de7cb32
--- /dev/null
+++ b/web/app/templates/cloud/list.hbs
@@ -0,0 +1,80 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+
+ 云端列表
+
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/components/ace-login.hbs b/web/app/templates/components/ace-login.hbs
new file mode 100644
index 0000000..82a5299
--- /dev/null
+++ b/web/app/templates/components/ace-login.hbs
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+ PudongHot
+ Ambition
+
+ © Shanghai PudongHot Information Technology Co.,Ltd.
+
+
+
+
+
+
+
+
diff --git a/web/app/templates/components/app/app-manage.hbs b/web/app/templates/components/app/app-manage.hbs
new file mode 100644
index 0000000..6a8f013
--- /dev/null
+++ b/web/app/templates/components/app/app-manage.hbs
@@ -0,0 +1,88 @@
+{{#breadcrumbs-bar}}
+
+ {{#link-to 'app.list' 1}}
+ App列表
+ {{/link-to}}
+
+ {{pageTitle}}
+{{/breadcrumbs-bar}}
+{{app/manage-sidebar appId=appId category=category}}
+
+
+
+
+
+
+
+
+
+
+
+ {{#if page}}
+ {{#link-to tabLinkRouteName appId 'AndroidPhone' page}}
+
+ Android Phone
+ {{/link-to}}
+ {{else}}
+ {{#link-to tabLinkRouteName appId 'AndroidPhone'}}
+
+ Android Phone
+ {{/link-to}}
+ {{/if}}
+
+
+
+ {{#if page}}
+ {{#link-to tabLinkRouteName appId 'iPhone' page}}
+
+ iPhone
+ {{/link-to}}
+ {{else}}
+ {{#link-to tabLinkRouteName appId 'iPhone'}}
+
+ iPhone
+ {{/link-to}}
+ {{/if}}
+
+
+
+ {{#if page}}
+ {{#link-to tabLinkRouteName appId 'AndroidPad' page}}
+
+ Android Pad
+ {{/link-to}}
+ {{else}}
+ {{#link-to tabLinkRouteName appId 'AndroidPad'}}
+
+ Android Pad
+ {{/link-to}}
+ {{/if}}
+
+
+
+ {{#if page}}
+ {{#link-to tabLinkRouteName appId 'iPad' page}}
+
+ iPad
+ {{/link-to}}
+ {{else}}
+ {{#link-to tabLinkRouteName appId 'iPad'}}
+
+ iPad
+ {{/link-to}}
+ {{/if}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/app/templates/components/app/manage-sidebar.hbs b/web/app/templates/components/app/manage-sidebar.hbs
new file mode 100644
index 0000000..b713088
--- /dev/null
+++ b/web/app/templates/components/app/manage-sidebar.hbs
@@ -0,0 +1,33 @@
+
+
+
+ {{#link-to 'app.version.list' appId 'AndroidPhone' 1}}
+
+
+ {{/link-to}}
+
+
+
+ {{#link-to 'app.release.show' appId 'AndroidPhone'}}
+
+
+ {{/link-to}}
+
+
+
+ {{#link-to 'app.version-group.list' appId 1}}
+
+
+ {{/link-to}}
+
+
+
+ {{#link-to 'app.appoint.list' appId 'AndroidPhone' 1}}
+
+
+ {{/link-to}}
+
+
+
diff --git a/web/app/templates/components/breadcrumbs-bar.hbs b/web/app/templates/components/breadcrumbs-bar.hbs
new file mode 100644
index 0000000..5d7a742
--- /dev/null
+++ b/web/app/templates/components/breadcrumbs-bar.hbs
@@ -0,0 +1,7 @@
+
diff --git a/web/app/templates/components/date-cell.hbs b/web/app/templates/components/date-cell.hbs
new file mode 100644
index 0000000..fe00ee7
--- /dev/null
+++ b/web/app/templates/components/date-cell.hbs
@@ -0,0 +1,3 @@
+{{#if model}}
+{{moment-format model 'YYYY-MM-DD H:mm:ss'}}
+{{/if}}
diff --git a/web/app/templates/components/editable-cell.hbs b/web/app/templates/components/editable-cell.hbs
new file mode 100644
index 0000000..d18442e
--- /dev/null
+++ b/web/app/templates/components/editable-cell.hbs
@@ -0,0 +1,14 @@
+{{#if isEditing}}
+ {{input type="text"
+ name=model.id
+ placeholder=placeholder
+ class="col-xs-12"
+ value=(mut (get model field))
+ focus-out='doUpdate'
+ insert-newline='doUpdate'
+ }}
+{{else}}
+
+ {{get model field}}
+
+{{/if}}
diff --git a/web/app/templates/components/form-content.hbs b/web/app/templates/components/form-content.hbs
new file mode 100644
index 0000000..9174e00
--- /dev/null
+++ b/web/app/templates/components/form-content.hbs
@@ -0,0 +1,13 @@
+
diff --git a/web/app/templates/components/form-footer-buttons.hbs b/web/app/templates/components/form-footer-buttons.hbs
new file mode 100644
index 0000000..17270b5
--- /dev/null
+++ b/web/app/templates/components/form-footer-buttons.hbs
@@ -0,0 +1,9 @@
+
+
+ 返回
+
+
+
+ 提交
+
+
diff --git a/web/app/templates/components/form-input-checkbox.hbs b/web/app/templates/components/form-input-checkbox.hbs
new file mode 100644
index 0000000..def733d
--- /dev/null
+++ b/web/app/templates/components/form-input-checkbox.hbs
@@ -0,0 +1,9 @@
+ {{label}}
+
+
+ {{input type='hidden' name=name value=(mut (get model name))}}
+ {{input type='checkbox' class='ace ace-switch ace-switch-5' checked=(mut (get model name))}}
+
+
+ {{yield}}
+
diff --git a/web/app/templates/components/form-input-color.hbs b/web/app/templates/components/form-input-color.hbs
new file mode 100644
index 0000000..649e96d
--- /dev/null
+++ b/web/app/templates/components/form-input-color.hbs
@@ -0,0 +1,17 @@
+ {{label}}
+
+
+
+ {{input class='form-control col-xs-12'
+ readonly='readonly'
+ placeholder=(if placeholder placeholder label)
+ name=name
+ value=(mut (get model name))}}
+
+
+
+
+ {{input class='form-control' placeholder=placeholder value=hexColor}}
+
+
+{{form-input-errors-msg name=name}}
\ No newline at end of file
diff --git a/web/app/templates/components/form-input-errors-msg.hbs b/web/app/templates/components/form-input-errors-msg.hbs
new file mode 100644
index 0000000..80fd5b8
--- /dev/null
+++ b/web/app/templates/components/form-input-errors-msg.hbs
@@ -0,0 +1,3 @@
+{{#each (get errors name) as |msg|}}
+ {{msg}}
+{{/each}}
\ No newline at end of file
diff --git a/web/app/templates/components/form-input-modal-select.hbs b/web/app/templates/components/form-input-modal-select.hbs
new file mode 100644
index 0000000..609cc2c
--- /dev/null
+++ b/web/app/templates/components/form-input-modal-select.hbs
@@ -0,0 +1,27 @@
+ {{label}}
+
+
+ {{input type='hidden' name=(if name name idField) value=(mut (get model idField))}}
+ {{input type='text'
+ class='form-control col-xs-12'
+ readonly='readonly'
+ value=(mut (get model nameField))
+ placeholder=(if placeholder (concat '选择' label))}}
+
+ {{#link-to listRoute 1
+ (obj-query-params
+ (obj-merge params
+ (hash idField=idField
+ nameField=nameField
+ selectedId=(get model idField))))
+ activeClass=''
+ class='btn btn-sm btn-primary'
+ rel="tooltip"
+ title=selectText}}
+
+ 选择
+ {{/link-to}}
+
+
+
+{{form-input-errors-msg name=idField}}
\ No newline at end of file
diff --git a/web/app/templates/components/form-input-select.hbs b/web/app/templates/components/form-input-select.hbs
new file mode 100644
index 0000000..0201be1
--- /dev/null
+++ b/web/app/templates/components/form-input-select.hbs
@@ -0,0 +1,11 @@
+ {{label}}
+
+
+
+ {{#x-select class='form-control' name=name value=(mut (get model name)) as |xs|}}
+ {{yield xs}}
+ {{/x-select}}
+
+
+
+{{form-input-errors-msg name=name}}
\ No newline at end of file
diff --git a/web/app/templates/components/form-input-spinner.hbs b/web/app/templates/components/form-input-spinner.hbs
new file mode 100644
index 0000000..ce0fe79
--- /dev/null
+++ b/web/app/templates/components/form-input-spinner.hbs
@@ -0,0 +1,8 @@
+ {{label}}
+
+ {{input class='col-xs-12'
+ type='text'
+ name=name
+ value=(mut (get model name))}}
+
+{{form-input-errors-msg name=name}}
\ No newline at end of file
diff --git a/web/app/templates/components/form-input.hbs b/web/app/templates/components/form-input.hbs
new file mode 100644
index 0000000..303157a
--- /dev/null
+++ b/web/app/templates/components/form-input.hbs
@@ -0,0 +1,29 @@
+ {{label}}
+
+ {{#if hasBlock}}
+ {{yield}}
+ {{else}}
+ {{#if (eq 'file' type)}}
+ {{input class='col-xs-12' type='file' name=name}}
+ {{else if (eq 'textarea' type)}}
+ {{textarea class='col-xs-12'
+ name=name
+ value=(mut (get model name))
+ class='form-control'
+ placeholder=(if placeholder placeholder label)}}
+ {{else}}
+ {{input class='col-xs-12'
+ type=type
+ readonly=readonly
+ name=name
+ placeholder=(if placeholder placeholder label)
+ value=(mut (get model name))}}
+ {{/if}}
+ {{/if}}
+
+{{#if imageUrl}}
+
+ {{image-previews previews=imageUrl}}
+
+{{/if}}
+{{form-input-errors-msg name=name}}
\ No newline at end of file
diff --git a/web/app/templates/components/gender-cell.hbs b/web/app/templates/components/gender-cell.hbs
new file mode 100644
index 0000000..6ccbeba
--- /dev/null
+++ b/web/app/templates/components/gender-cell.hbs
@@ -0,0 +1,7 @@
+{{#if (eq 'M' model.gender)}}
+ {{! }}
+ 男
+{{else}}
+ {{! }}
+ 女
+{{/if}}
diff --git a/web/app/templates/components/grid-header.hbs b/web/app/templates/components/grid-header.hbs
new file mode 100644
index 0000000..98c5bb7
--- /dev/null
+++ b/web/app/templates/components/grid-header.hbs
@@ -0,0 +1,14 @@
+
+ {{#if hasBlock}}
+
+ {{/if}}
+ {{reload-btn}}
+
+{{search-box}}
diff --git a/web/app/templates/components/image-previews.hbs b/web/app/templates/components/image-previews.hbs
new file mode 100644
index 0000000..72ce668
--- /dev/null
+++ b/web/app/templates/components/image-previews.hbs
@@ -0,0 +1,12 @@
+{{#if previews}}
+
+
+
+
+{{/if}}
\ No newline at end of file
diff --git a/web/app/templates/components/list-select-checkbox.hbs b/web/app/templates/components/list-select-checkbox.hbs
new file mode 100644
index 0000000..04d0252
--- /dev/null
+++ b/web/app/templates/components/list-select-checkbox.hbs
@@ -0,0 +1,5 @@
+
+
diff --git a/web/app/templates/components/main-container.hbs b/web/app/templates/components/main-container.hbs
new file mode 100644
index 0000000..81c0e5d
--- /dev/null
+++ b/web/app/templates/components/main-container.hbs
@@ -0,0 +1,674 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/app/templates/components/main-content.hbs b/web/app/templates/components/main-content.hbs
new file mode 100644
index 0000000..afa9db2
--- /dev/null
+++ b/web/app/templates/components/main-content.hbs
@@ -0,0 +1,3 @@
+
+ {{yield}}
+
diff --git a/web/app/templates/components/modal-dialog.hbs b/web/app/templates/components/modal-dialog.hbs
new file mode 100644
index 0000000..e137763
--- /dev/null
+++ b/web/app/templates/components/modal-dialog.hbs
@@ -0,0 +1,15 @@
+{{#modal-frame title=title}}
+
+ {{yield}}
+
+
+
+{{/modal-frame}}
diff --git a/web/app/templates/components/modal-frame.hbs b/web/app/templates/components/modal-frame.hbs
new file mode 100644
index 0000000..56512b4
--- /dev/null
+++ b/web/app/templates/components/modal-frame.hbs
@@ -0,0 +1,11 @@
+
diff --git a/web/app/templates/components/modal-list-select.hbs b/web/app/templates/components/modal-list-select.hbs
new file mode 100644
index 0000000..3cd0f7d
--- /dev/null
+++ b/web/app/templates/components/modal-list-select.hbs
@@ -0,0 +1,15 @@
+{{#modal-dialog title=title}}
+
+
+
+ {{pagination-bar}}
+{{/modal-dialog}}
diff --git a/web/app/templates/components/op-detail.hbs b/web/app/templates/components/op-detail.hbs
new file mode 100644
index 0000000..0ba5b4e
--- /dev/null
+++ b/web/app/templates/components/op-detail.hbs
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/app/templates/components/pagination-bar.hbs b/web/app/templates/components/pagination-bar.hbs
new file mode 100644
index 0000000..7eb815a
--- /dev/null
+++ b/web/app/templates/components/pagination-bar.hbs
@@ -0,0 +1,24 @@
+
+ 总共:{{total}}条记录
+
+
diff --git a/web/app/templates/components/qr-code.hbs b/web/app/templates/components/qr-code.hbs
new file mode 100644
index 0000000..e6ef8f5
--- /dev/null
+++ b/web/app/templates/components/qr-code.hbs
@@ -0,0 +1,16 @@
+
+
+
+
+{{yield}}
diff --git a/web/app/templates/components/reload-btn.hbs b/web/app/templates/components/reload-btn.hbs
new file mode 100644
index 0000000..186ba24
--- /dev/null
+++ b/web/app/templates/components/reload-btn.hbs
@@ -0,0 +1 @@
+
diff --git a/web/app/templates/components/search-box.hbs b/web/app/templates/components/search-box.hbs
new file mode 100644
index 0000000..e25a19a
--- /dev/null
+++ b/web/app/templates/components/search-box.hbs
@@ -0,0 +1,9 @@
+
+{{input type="text"
+ class="form-control search-query small"
+ placeholder="Search ..."
+ value=searchText
+ insert-newline='search'
+}}
+
+
\ No newline at end of file
diff --git a/web/app/templates/components/sortable-list-item.hbs b/web/app/templates/components/sortable-list-item.hbs
new file mode 100644
index 0000000..889d9ee
--- /dev/null
+++ b/web/app/templates/components/sortable-list-item.hbs
@@ -0,0 +1 @@
+{{yield}}
diff --git a/web/app/templates/components/sortable-list.hbs b/web/app/templates/components/sortable-list.hbs
new file mode 100644
index 0000000..458e532
--- /dev/null
+++ b/web/app/templates/components/sortable-list.hbs
@@ -0,0 +1,5 @@
+{{#each model as |it i|}}
+ {{#sortable-list-item index=i selected=(eq selected it.id) itemId=it.id}}
+ {{yield it}}
+ {{/sortable-list-item}}
+{{/each}}
diff --git a/web/app/templates/components/status-cell.hbs b/web/app/templates/components/status-cell.hbs
new file mode 100644
index 0000000..37e0516
--- /dev/null
+++ b/web/app/templates/components/status-cell.hbs
@@ -0,0 +1 @@
+{{if (get model field) enabledText disabledText}}
diff --git a/web/app/templates/components/status-toggle-button.hbs b/web/app/templates/components/status-toggle-button.hbs
new file mode 100644
index 0000000..0ab5259
--- /dev/null
+++ b/web/app/templates/components/status-toggle-button.hbs
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/web/app/templates/components/top-navbar.hbs b/web/app/templates/components/top-navbar.hbs
new file mode 100644
index 0000000..5d7c406
--- /dev/null
+++ b/web/app/templates/components/top-navbar.hbs
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/app/templates/components/tree-view.hbs b/web/app/templates/components/tree-view.hbs
new file mode 100644
index 0000000..6bf4582
--- /dev/null
+++ b/web/app/templates/components/tree-view.hbs
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/web/app/templates/components/wysiwyg-editor.hbs b/web/app/templates/components/wysiwyg-editor.hbs
new file mode 100644
index 0000000..44eec82
--- /dev/null
+++ b/web/app/templates/components/wysiwyg-editor.hbs
@@ -0,0 +1,3 @@
+
+{{input type='hidden' name=name value=(get model name)}}
+{{form-input-errors-msg name=name}}
\ No newline at end of file
diff --git a/web/app/templates/corp/contact.hbs b/web/app/templates/corp/contact.hbs
new file mode 100644
index 0000000..c24cd68
--- /dev/null
+++ b/web/app/templates/corp/contact.hbs
@@ -0,0 +1 @@
+{{outlet}}
diff --git a/web/app/templates/corp/contact/create.hbs b/web/app/templates/corp/contact/create.hbs
new file mode 100644
index 0000000..c24cd68
--- /dev/null
+++ b/web/app/templates/corp/contact/create.hbs
@@ -0,0 +1 @@
+{{outlet}}
diff --git a/web/app/templates/corp/contact/edit.hbs b/web/app/templates/corp/contact/edit.hbs
new file mode 100644
index 0000000..c24cd68
--- /dev/null
+++ b/web/app/templates/corp/contact/edit.hbs
@@ -0,0 +1 @@
+{{outlet}}
diff --git a/web/app/templates/corp/contact/list.hbs b/web/app/templates/corp/contact/list.hbs
new file mode 100644
index 0000000..c24cd68
--- /dev/null
+++ b/web/app/templates/corp/contact/list.hbs
@@ -0,0 +1 @@
+{{outlet}}
diff --git a/web/app/templates/corp/create.hbs b/web/app/templates/corp/create.hbs
new file mode 100644
index 0000000..7a47748
--- /dev/null
+++ b/web/app/templates/corp/create.hbs
@@ -0,0 +1,50 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+ 新建企业
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='shortName' label='简称'}}
+ {{form-input type='file' name='icon' label='图标'}}
+
+ {{form-input-modal-select
+ listRoute='corp.create.api-group-select'
+ idField='apiGroupId'
+ nameField='apiGroupName'
+ btnIcon='fa-plug'
+ label='API组'}}
+
+ {{form-input-modal-select
+ listRoute='corp.create.splash-select'
+ idField='splashId'
+ nameField='splashName'
+ btnIcon='fa-file-image-o'
+ label='启动图'}}
+
+ {{form-input-modal-select
+ listRoute='corp.create.app-config-select'
+ idField='appConfigId'
+ nameField='appConfigName'
+ btnIcon='fa-bars'
+ label='App配置'}}
+
+ {{form-input-modal-select
+ listRoute='corp.create.theme-select'
+ idField='themeId'
+ nameField='themeName'
+ btnIcon='fa-suitcase'
+ label='主题包'}}
+
+ {{form-input-checkbox name='useTinyAppGroup' label='使用轻应用分组'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
diff --git a/web/app/templates/corp/dept.hbs b/web/app/templates/corp/dept.hbs
new file mode 100644
index 0000000..c24cd68
--- /dev/null
+++ b/web/app/templates/corp/dept.hbs
@@ -0,0 +1 @@
+{{outlet}}
diff --git a/web/app/templates/corp/dept/create.hbs b/web/app/templates/corp/dept/create.hbs
new file mode 100644
index 0000000..a88fff4
--- /dev/null
+++ b/web/app/templates/corp/dept/create.hbs
@@ -0,0 +1,36 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+
+ {{#link-to 'corp.dept.list' 1}}
+ 部门列表
+ {{/link-to}}
+
+ 新建部门
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='corpId' value=model.corpId}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='url' label='URL'}}
+ {{!form-input type='file' name='icon' label='图标'}}
+
+ {{!form-input-modal-select
+ listRoute='corp.tiny-app.create.tiny-app-group-select'
+ idField='groupId'
+ nameField='groupName'
+ params=(hash corpId=model.corpId)
+ btnIcon='fa-object-group'
+ label='轻应用分组'}}
+
+ {{form-input-spinner name='sort' label='排序'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
+
diff --git a/web/app/templates/corp/dept/edit.hbs b/web/app/templates/corp/dept/edit.hbs
new file mode 100644
index 0000000..a64f31b
--- /dev/null
+++ b/web/app/templates/corp/dept/edit.hbs
@@ -0,0 +1,35 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+
+ {{#link-to 'corp.tiny-app.list' 1}}
+ 部门列表
+ {{/link-to}}
+
+ 编辑部门[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+ {{!--{{form-input name='url' label='URL'}}--}}
+ {{!form-input type='file' name='icon' label='图标' image='icon'}}
+ {{!form-input-modal-select
+ listRoute='corp.tiny-app.edit.tiny-app-group-select'
+ idField='groupId'
+ nameField='groupName'
+ params=(hash corpId=model.corpId)
+ btnIcon='fa-object-group'
+ label='轻应用分组'}}
+
+ {{form-input-spinner name='sort' label='排序'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
diff --git a/web/app/templates/corp/dept/list.hbs b/web/app/templates/corp/dept/list.hbs
new file mode 100644
index 0000000..cdf7716
--- /dev/null
+++ b/web/app/templates/corp/dept/list.hbs
@@ -0,0 +1,87 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+ [{{model.corp.name}}]部门列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/corp/dept/tree.hbs b/web/app/templates/corp/dept/tree.hbs
new file mode 100644
index 0000000..c33af4a
--- /dev/null
+++ b/web/app/templates/corp/dept/tree.hbs
@@ -0,0 +1,53 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+ [{{model.corp.name}}]部门树
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/corp/edit.hbs b/web/app/templates/corp/edit.hbs
new file mode 100644
index 0000000..b0ef556
--- /dev/null
+++ b/web/app/templates/corp/edit.hbs
@@ -0,0 +1,59 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+ 编辑企业[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='shortName' label='简称'}}
+ {{form-input type='file' name='icon' label='图标' image='icon'}}
+
+ {{form-input-modal-select
+ listRoute='corp.edit.tiny-app-group-select'
+ idField='defaultTinyAppGroupId'
+ nameField='defaultTinyAppGroupName'
+ params=(hash corpId=model.id)
+ btnIcon='fa-object-group'
+ label='默认轻应用分组'}}
+
+ {{form-input-modal-select
+ listRoute='corp.edit.api-group-select'
+ idField='apiGroupId'
+ nameField='apiGroupName'
+ btnIcon='fa-plug'
+ label='API组'}}
+
+ {{form-input-modal-select
+ listRoute='corp.edit.splash-select'
+ idField='splashId'
+ nameField='splashName'
+ btnIcon='fa-file-image-o'
+ label='启动图'}}
+
+ {{form-input-modal-select
+ listRoute='corp.edit.app-config-select'
+ idField='appConfigId'
+ nameField='appConfigName'
+ btnIcon='fa-bars'
+ label='App配置'}}
+
+ {{form-input-modal-select
+ listRoute='corp.edit.theme-select'
+ idField='themeId'
+ nameField='themeName'
+ btnIcon='fa-suitcase'
+ label='主题包'}}
+
+ {{form-input-checkbox name='useTinyAppGroup' label='使用轻应用分组'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
diff --git a/web/app/templates/corp/employee/create.hbs b/web/app/templates/corp/employee/create.hbs
new file mode 100644
index 0000000..c690a98
--- /dev/null
+++ b/web/app/templates/corp/employee/create.hbs
@@ -0,0 +1,30 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+
+ {{#link-to 'corp.employee.list' 1}}
+ 雇员列表
+ {{/link-to}}
+
+ 新建雇员
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='corpId' value=model.corpId}}
+ {{form-input name='name' label='姓名'}}
+ {{form-input name='mobile' label='手机号'}}
+ {{form-input type='file' name='avatar' label='头像'}}
+
+ {{#form-input-select label='性别' name='gender' as |xs|}}
+ {{#xs.option value='M'}}男{{/xs.option}}
+ {{#xs.option value='F'}}女{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/corp/employee/edit.hbs b/web/app/templates/corp/employee/edit.hbs
new file mode 100644
index 0000000..ba97b4c
--- /dev/null
+++ b/web/app/templates/corp/employee/edit.hbs
@@ -0,0 +1,31 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+
+ {{#link-to 'corp.employee.list' 1}}
+ 雇员列表
+ {{/link-to}}
+
+ 编辑雇员[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='姓名'}}
+ {{form-input name='mobile' label='手机号'}}
+ {{form-input type='file' name='avatar' label='头像' image='avatar'}}
+
+ {{#form-input-select label='性别' name='gender' as |xs|}}
+ {{#xs.option value='M'}}男{{/xs.option}}
+ {{#xs.option value='F'}}女{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/corp/employee/list.hbs b/web/app/templates/corp/employee/list.hbs
new file mode 100644
index 0000000..c46c674
--- /dev/null
+++ b/web/app/templates/corp/employee/list.hbs
@@ -0,0 +1,99 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+ [{{model.corp.name}}]雇员列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/corp/employee/show.hbs b/web/app/templates/corp/employee/show.hbs
new file mode 100644
index 0000000..b1e52f0
--- /dev/null
+++ b/web/app/templates/corp/employee/show.hbs
@@ -0,0 +1,42 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 用户详情
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/corp/list.hbs b/web/app/templates/corp/list.hbs
new file mode 100644
index 0000000..333e491
--- /dev/null
+++ b/web/app/templates/corp/list.hbs
@@ -0,0 +1,188 @@
+
diff --git a/web/app/templates/corp/show.hbs b/web/app/templates/corp/show.hbs
new file mode 100644
index 0000000..492a549
--- /dev/null
+++ b/web/app/templates/corp/show.hbs
@@ -0,0 +1,42 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 企业详情
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/corp/tiny-app-group/create.hbs b/web/app/templates/corp/tiny-app-group/create.hbs
new file mode 100644
index 0000000..477c1e0
--- /dev/null
+++ b/web/app/templates/corp/tiny-app-group/create.hbs
@@ -0,0 +1,24 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+
+ {{#link-to 'corp.tiny-app-group.list' 1}}
+ 轻应用分组列表
+ {{/link-to}}
+
+ 新建轻应用分组
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='corpId' value=model.corpId}}
+ {{form-input name='name' label='名称'}}
+ {{form-input-spinner name='sort' label='排序'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/corp/tiny-app-group/edit.hbs b/web/app/templates/corp/tiny-app-group/edit.hbs
new file mode 100644
index 0000000..cf2bf1e
--- /dev/null
+++ b/web/app/templates/corp/tiny-app-group/edit.hbs
@@ -0,0 +1,25 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+
+ {{#link-to 'corp.tiny-app-group.list' 1}}
+ 轻应用分组列表
+ {{/link-to}}
+
+ 编辑轻应用分组[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input-spinner name='sort' label='排序'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/corp/tiny-app-group/list-select.hbs b/web/app/templates/corp/tiny-app-group/list-select.hbs
new file mode 100644
index 0000000..457adf2
--- /dev/null
+++ b/web/app/templates/corp/tiny-app-group/list-select.hbs
@@ -0,0 +1,48 @@
+{{#modal-list-select title='轻应用分组列表'}}
+
+
+
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ 状态
+
+
+
+ 创建时间
+
+
+
+ 更新时间
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+ {{status-cell model=it}}
+
+ {{date-cell model=it.dateCreated}}
+ {{date-cell model=it.dateUpdated}}
+
+ {{/each}}
+
+{{/modal-list-select}}
diff --git a/web/app/templates/corp/tiny-app-group/list.hbs b/web/app/templates/corp/tiny-app-group/list.hbs
new file mode 100644
index 0000000..5bd7f7b
--- /dev/null
+++ b/web/app/templates/corp/tiny-app-group/list.hbs
@@ -0,0 +1,88 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+ [{{model.corp.name}}]轻应用分组列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
+
diff --git a/web/app/templates/corp/tiny-app/create.hbs b/web/app/templates/corp/tiny-app/create.hbs
new file mode 100644
index 0000000..3a2c8e7
--- /dev/null
+++ b/web/app/templates/corp/tiny-app/create.hbs
@@ -0,0 +1,34 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+
+ {{#link-to 'corp.tiny-app.list' 1}}
+ 轻应用列表
+ {{/link-to}}
+
+ 新建轻应用
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='corpId' value=model.corpId}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='url' label='URL'}}
+ {{form-input type='file' name='icon' label='图标'}}
+ {{form-input-modal-select
+ listRoute='corp.tiny-app.create.tiny-app-group-select'
+ idField='groupId'
+ nameField='groupName'
+ params=(hash corpId=model.corpId)
+ btnIcon='fa-object-group'
+ label='轻应用分组'}}
+
+ {{form-input-spinner name='sort' label='排序'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
diff --git a/web/app/templates/corp/tiny-app/edit.hbs b/web/app/templates/corp/tiny-app/edit.hbs
new file mode 100644
index 0000000..17dccce
--- /dev/null
+++ b/web/app/templates/corp/tiny-app/edit.hbs
@@ -0,0 +1,35 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+
+ {{#link-to 'corp.tiny-app.list' 1}}
+ 轻应用列表
+ {{/link-to}}
+
+ 编辑轻应用[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input name='url' label='URL'}}
+ {{form-input type='file' name='icon' label='图标' image='icon'}}
+ {{form-input-modal-select
+ listRoute='corp.tiny-app.edit.tiny-app-group-select'
+ idField='groupId'
+ nameField='groupName'
+ params=(hash corpId=model.corpId)
+ btnIcon='fa-object-group'
+ label='轻应用分组'}}
+
+ {{form-input-spinner name='sort' label='排序'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+ {{outlet}}
+{{/main-content}}
diff --git a/web/app/templates/corp/tiny-app/list.hbs b/web/app/templates/corp/tiny-app/list.hbs
new file mode 100644
index 0000000..ceb7121
--- /dev/null
+++ b/web/app/templates/corp/tiny-app/list.hbs
@@ -0,0 +1,112 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'corp.list' 1}}
+ 企业列表
+ {{/link-to}}
+
+ [{{model.corp.name}}]轻应用列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/corp/tiny-app/show.hbs b/web/app/templates/corp/tiny-app/show.hbs
new file mode 100644
index 0000000..b1e52f0
--- /dev/null
+++ b/web/app/templates/corp/tiny-app/show.hbs
@@ -0,0 +1,42 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 用户详情
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/index.hbs b/web/app/templates/index.hbs
new file mode 100644
index 0000000..c846c91
--- /dev/null
+++ b/web/app/templates/index.hbs
@@ -0,0 +1 @@
+Index
diff --git a/web/app/templates/login.hbs b/web/app/templates/login.hbs
new file mode 100644
index 0000000..7724ae5
--- /dev/null
+++ b/web/app/templates/login.hbs
@@ -0,0 +1 @@
+{{ace-login onLogin=(route-action 'doLogin')}}
\ No newline at end of file
diff --git a/web/app/templates/op-detail.hbs b/web/app/templates/op-detail.hbs
new file mode 100644
index 0000000..59e40d3
--- /dev/null
+++ b/web/app/templates/op-detail.hbs
@@ -0,0 +1,50 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 操作详情
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/role/create.hbs b/web/app/templates/role/create.hbs
new file mode 100644
index 0000000..99a2658
--- /dev/null
+++ b/web/app/templates/role/create.hbs
@@ -0,0 +1,22 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'role.list' 1}}
+ 角色列表
+ {{/link-to}}
+
+ 新建角色
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input name='name' label='名称'}}
+
+ {{#form-input-select label='类型' name='type' as |xs|}}
+ {{#xs.option value='U'}}普通用户{{/xs.option}}
+ {{#xs.option value='A'}}管理员{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/role/edit.hbs b/web/app/templates/role/edit.hbs
new file mode 100644
index 0000000..e7b04b7
--- /dev/null
+++ b/web/app/templates/role/edit.hbs
@@ -0,0 +1,24 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'role.list' 1}}
+ 角色列表
+ {{/link-to}}
+
+ 编辑角色[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+
+ {{#form-input-select label='类型' name='type' as |xs|}}
+ {{#xs.option value='U'}}普通用户{{/xs.option}}
+ {{#xs.option value='A'}}管理员{{/xs.option}}
+ {{/form-input-select}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/role/list-select.hbs b/web/app/templates/role/list-select.hbs
new file mode 100644
index 0000000..29e1180
--- /dev/null
+++ b/web/app/templates/role/list-select.hbs
@@ -0,0 +1,61 @@
+{{#modal-list-select title='主题包列表'}}
+
+
+
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ 预览图
+
+
+ 作者
+
+
+
+ 状态
+
+
+
+ 创建时间
+
+
+
+ 更新时间
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it selectedModel=selectedModel selectedId=selectedId}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+ {{image-previews previews=it.previews}}
+
+
+ {{it.author}}
+
+
+ {{status-cell model=it}}
+
+ {{date-cell model=it.dateCreated}}
+ {{date-cell model=it.dateUpdated}}
+
+ {{/each}}
+
+{{/modal-list-select}}
\ No newline at end of file
diff --git a/web/app/templates/role/list.hbs b/web/app/templates/role/list.hbs
new file mode 100644
index 0000000..f978d77
--- /dev/null
+++ b/web/app/templates/role/list.hbs
@@ -0,0 +1,70 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 角色列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/splash/create.hbs b/web/app/templates/splash/create.hbs
new file mode 100644
index 0000000..3428acf
--- /dev/null
+++ b/web/app/templates/splash/create.hbs
@@ -0,0 +1,19 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'splash.list' 1}}
+ 启动图列表
+ {{/link-to}}
+
+ 新建启动图
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input name='name' label='名称'}}
+ {{form-input type='file' name='image' label='图片'}}
+ {{form-input name='duration' label='持续时间(ms)'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/splash/edit.hbs b/web/app/templates/splash/edit.hbs
new file mode 100644
index 0000000..5182512
--- /dev/null
+++ b/web/app/templates/splash/edit.hbs
@@ -0,0 +1,20 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'splash.list' 1}}
+ 启动图列表
+ {{/link-to}}
+
+ 编辑启动图[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称'}}
+ {{form-input type='file' name='image' label='图片' image='imageUrl'}}
+ {{form-input name='duration' label='持续时间(ms)'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/splash/list-select.hbs b/web/app/templates/splash/list-select.hbs
new file mode 100644
index 0000000..7ceed7b
--- /dev/null
+++ b/web/app/templates/splash/list-select.hbs
@@ -0,0 +1,52 @@
+{{#modal-list-select title='启动图列表'}}
+
+
+
+
+
+ 名称
+
+
+
+ 持续时间(ms)
+
+
+
+ 备注
+
+
+
+ 预览图
+
+
+
+ 状态
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it selectedModel=selectedModel selectedId=selectedId}}
+
+
+ {{it.name}}
+
+
+ {{it.duration}}
+
+
+ {{it.note}}
+
+
+ {{image-previews previews=it.imageUrl}}
+
+
+ {{status-cell model=it}}
+
+
+ {{/each}}
+
+{{/modal-list-select}}
diff --git a/web/app/templates/splash/list.hbs b/web/app/templates/splash/list.hbs
new file mode 100644
index 0000000..eeffbeb
--- /dev/null
+++ b/web/app/templates/splash/list.hbs
@@ -0,0 +1,84 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 启动图列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/theme/create.hbs b/web/app/templates/theme/create.hbs
new file mode 100644
index 0000000..c551849
--- /dev/null
+++ b/web/app/templates/theme/create.hbs
@@ -0,0 +1,15 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'theme.list' 1}}
+ 主题包列表
+ {{/link-to}}
+
+ 新建主题包
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input type='file' name='pkg' label='主题包'}}
+ {{form-input-checkbox}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/theme/edit.hbs b/web/app/templates/theme/edit.hbs
new file mode 100644
index 0000000..5aec17c
--- /dev/null
+++ b/web/app/templates/theme/edit.hbs
@@ -0,0 +1,19 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'theme.list' 1}}
+ 主题包列表
+ {{/link-to}}
+
+ 编辑主题包[{{model.name}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='name' label='名称' readonly="readonly"}}
+ {{form-input type='file' name='pkg' label='主题包'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/theme/list-select.hbs b/web/app/templates/theme/list-select.hbs
new file mode 100644
index 0000000..0680353
--- /dev/null
+++ b/web/app/templates/theme/list-select.hbs
@@ -0,0 +1,68 @@
+{{#modal-list-select title='主题包列表'}}
+
+
+
+
+
+ 名称
+
+
+
+ 备注
+
+
+
+ 封面图
+
+
+
+ 预览图
+
+
+ 作者
+
+
+
+ 状态
+
+
+
+ 创建时间
+
+
+
+ 更新时间
+
+
+
+
+
+ {{#each model.data as |it|}}
+
+
+ {{list-select-checkbox model=it selectedModel=selectedModel selectedId=selectedId}}
+
+
+ {{it.name}}
+
+
+ {{it.note}}
+
+
+ {{image-previews previews=it.coverImage}}
+
+
+ {{image-previews previews=it.previews}}
+
+
+ {{it.author}}
+
+
+ {{status-cell model=it}}
+
+ {{date-cell model=it.dateCreated}}
+ {{date-cell model=it.dateUpdated}}
+
+ {{/each}}
+
+{{/modal-list-select}}
\ No newline at end of file
diff --git a/web/app/templates/theme/list.hbs b/web/app/templates/theme/list.hbs
new file mode 100644
index 0000000..2bed770
--- /dev/null
+++ b/web/app/templates/theme/list.hbs
@@ -0,0 +1,90 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 主题包列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/app/templates/user/create.hbs b/web/app/templates/user/create.hbs
new file mode 100644
index 0000000..2cddb54
--- /dev/null
+++ b/web/app/templates/user/create.hbs
@@ -0,0 +1,18 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'user.list' 1}}
+ 用户列表
+ {{/link-to}}
+
+ 新建用户
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{form-input name='mobile' label='手机号'}}
+ {{form-input type='password' name='password' label='登录密码'}}
+ {{form-input type='password' name='confirmPassword' label='重复密码'}}
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+ {{form-footer-buttons}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/user/edit.hbs b/web/app/templates/user/edit.hbs
new file mode 100644
index 0000000..94e21bb
--- /dev/null
+++ b/web/app/templates/user/edit.hbs
@@ -0,0 +1,21 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+
+ {{#link-to 'user.list' 1}}
+ 用户列表
+ {{/link-to}}
+
+ 编辑用户[{{model.mobile}}]
+ {{/breadcrumbs-bar}}
+ {{#form-content}}
+ {{input type='hidden' name='id' value=model.id}}
+ {{form-input name='mobile' label='手机号' readonly='readonly'}}
+ {{form-input type='password' name='password' label='登录密码'}}
+ {{form-input type='password' name='confirmPassword' label='重复密码'}}
+
+ {{form-input-checkbox}}
+ {{form-input name='note' label='备注'}}
+
+ {{form-footer-buttons type='update'}}
+ {{/form-content}}
+{{/main-content}}
diff --git a/web/app/templates/user/list.hbs b/web/app/templates/user/list.hbs
new file mode 100644
index 0000000..04f9ec7
--- /dev/null
+++ b/web/app/templates/user/list.hbs
@@ -0,0 +1,76 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 用户列表
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
diff --git a/web/app/templates/user/show.hbs b/web/app/templates/user/show.hbs
new file mode 100644
index 0000000..b1e52f0
--- /dev/null
+++ b/web/app/templates/user/show.hbs
@@ -0,0 +1,42 @@
+{{#main-content}}
+ {{#breadcrumbs-bar}}
+ 用户详情
+ {{/breadcrumbs-bar}}
+
+
+{{/main-content}}
\ No newline at end of file
diff --git a/web/bower.json b/web/bower.json
new file mode 100644
index 0000000..507fda2
--- /dev/null
+++ b/web/bower.json
@@ -0,0 +1,25 @@
+{
+ "name": "ambition-crm",
+ "dependencies": {
+ "ember": "~2.13.0",
+ "ember-cli-shims": "0.1.1",
+ "ember-cli-test-loader": "0.2.2",
+ "ember-qunit-notifications": "0.1.0",
+ "bootstrap": "~3.3.5",
+ "bootbox": "~4.4.0",
+ "moment": ">= 2.8.0",
+ "moment-timezone": ">= 0.1.0",
+ "validate": "~0.9.0",
+ "jquery-storage-api": "jQuery-Storage-API#^1.9.1",
+ "font-awesome": "^4.6.3",
+ "mjolnic-bootstrap-colorpicker": "bootstrap-colorpicker#^2.3.3",
+ "jquery-colorbox": "^1.6.4",
+ "fuelux": "^3.15.4",
+ "jquery.hotkeys": "*",
+ "bootstrap-wysiwyg": "*",
+ "bootstrap-treeview": "^1.2.0"
+ },
+ "resolutions": {
+ "ember": "release"
+ }
+}
diff --git a/web/build b/web/build
new file mode 100755
index 0000000..368b0fd
--- /dev/null
+++ b/web/build
@@ -0,0 +1,4 @@
+rm -rf tmp dist admin-web admin-web.tgz
+ember b -o admin-web -prod
+tar czf admin-web.tgz admin-web
+rm -rf admin-web
diff --git a/web/config/environment.js b/web/config/environment.js
new file mode 100644
index 0000000..0c1281b
--- /dev/null
+++ b/web/config/environment.js
@@ -0,0 +1,45 @@
+/* jshint node: true */
+
+module.exports = function(environment) {
+ var ENV = {
+ modulePrefix: 'ambition-crm',
+ environment: environment,
+ baseURL: '/',
+ locationType: 'hash',
+ EmberENV: {
+ FEATURES: {
+ // Here you can enable experimental features on an ember canary build
+ // e.g. 'with-controller': true
+ }
+ },
+
+ APP: {
+ // Here you can pass flags/options to your application instance
+ // when it is created
+ }
+ };
+
+ if (environment === 'development') {
+ // ENV.APP.LOG_RESOLVER = true;
+ // ENV.APP.LOG_ACTIVE_GENERATION = true;
+ // ENV.APP.LOG_TRANSITIONS = true;
+ // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
+ // ENV.APP.LOG_VIEW_LOOKUPS = true;
+ }
+
+ if (environment === 'test') {
+ // Testem prefers this...
+ ENV.baseURL = '/';
+ ENV.locationType = 'none';
+
+ // keep test console output quieter
+ ENV.APP.LOG_ACTIVE_GENERATION = false;
+ ENV.APP.LOG_VIEW_LOOKUPS = false;
+
+ ENV.APP.rootElement = '#ember-testing';
+ }
+
+ if (environment === 'production') {
+ }
+ return ENV;
+};
diff --git a/web/deploy b/web/deploy
new file mode 100755
index 0000000..1eab4f4
--- /dev/null
+++ b/web/deploy
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+targetServer="pudonghot@101.37.82.164"
+projName="admin-web"
+targetPath="/data/program/ambition"
+tgzFile="${projName}.tgz"
+backupDir="${projName}_prev"
+
+ember b -prod -o "${projName}"
+
+# package dist
+echo "tar czf ${tgzFile} ${projName}"
+tar czf "${tgzFile}" "${projName}"
+
+# remove backup
+echo "ssh ${targetServer} rm -rf ${targetPath}/${backupDir} && mv ${targetPath}/${projName} ${targetPath}/${backupDir}"
+ssh "${targetServer}" "rm -rf ${targetPath}/${backupDir} && mv ${targetPath}/${projName} ${targetPath}/${backupDir}"
+
+# copy pakage to server
+echo "scp ${tgzFile} pudonghot@101.37.82.164:${targetPath}/"
+scp "${tgzFile}" "pudonghot@101.37.82.164:${targetPath}/"
+
+# extract package
+ssh "${targetServer}" "tar xzf ${targetPath}/${tgzFile} -C ${targetPath} && rm -rf ${targetPath}/${tgzFile}"
+
+# clean up
+echo "rm -rf ${projName} ${tgzFile}"
+rm -rf "${projName}" "${tgzFile}"
+
diff --git a/web/ember-cli-build.js b/web/ember-cli-build.js
new file mode 100644
index 0000000..60840fe
--- /dev/null
+++ b/web/ember-cli-build.js
@@ -0,0 +1,157 @@
+/* global require, module */
+const EmberApp = require('ember-cli/lib/broccoli/ember-app');
+const Funnel = require('broccoli-funnel');
+// Babel transpiler
+const BabelTranspiler = require('broccoli-babel-transpiler');
+
+module.exports = function(defaults) {
+ const app = new EmberApp(defaults, {
+ sourcemaps: {
+ enabled: EmberApp.env() !== 'production',
+ extensions: ['js', 'coffee']
+ },
+ outputPaths: {
+ app: {
+ html: 'index.html',
+ css: {
+ app: '/assets/css/main.css'
+ },
+ js: '/assets/js/main.js'
+ },
+ // only emberjs core
+ vendor: {
+ css: '/assets/css/emberjs.css',
+ js: '/assets/js/emberjs.js'
+ }
+ }
+ });
+
+ // Use `app.import` to add additional libraries to the generated
+ // output files.
+ //
+ // If you need to use different assets in different
+ // environments, specify an object as the first parameter. That
+ // object's keys should be the environment name and the values
+ // should be the asset to use in that environment.
+ //
+ // If the library that you are including contains AMD or ES6
+ // modules that you would like to import into your application
+ // please specify an object with the list of modules as keys
+ // along with the exports of each module as its value.
+
+ function importVendor(app, resource, outputFile) {
+ if (/\.js$/.test(resource)) {
+ app.import(resource, { outputFile: outputFile || 'assets/js/vendor.js'});
+ }
+ else if (/\.css$/.test(resource)) {
+ app.import(resource, { outputFile: outputFile || 'assets/css/vendor.css'});
+ }
+ }
+
+ let bd = app.bowerDirectory;
+ importVendor(app, 'bower_components/bootstrap/dist/css/bootstrap.css');
+ // importVendor(app, 'bower_components/bootstrap/dist/css/bootstrap-theme.css');
+ importVendor(app, 'bower_components/bootstrap/dist/js/bootstrap.js');
+ let bootstrapAssets = new Funnel('bower_components/bootstrap/dist/fonts', {
+ include: ['*.*'],
+ destDir: '/assets/fonts'
+ });
+
+ importVendor(app, 'bower_components/bootbox/bootbox.js');
+ importVendor(app, 'bower_components/validate/validate.js');
+ importVendor(app, 'bower_components/jquery-storage-api/jquery.storageapi.min.js');
+ // FueUX
+ importVendor(app, 'bower_components/fuelux/js/spinbox.js');
+ importVendor(app, 'bower_components/fuelux/js/tree.js');
+
+ // for image previews
+ importVendor(app, 'bower_components/jquery-colorbox/jquery.colorbox-min.js');
+ importVendor(app, 'bower_components/jquery-colorbox/example1/colorbox.css');
+ let jqColorboxAssets = new Funnel('bower_components/jquery-colorbox/example1/images', {
+ include: ['*.*'],
+ destDir: '/assets/css/images'
+ });
+
+ // font awesome
+ importVendor(app, 'bower_components/font-awesome/css/font-awesome.min.css');
+ let faAssets = new Funnel('bower_components/font-awesome/fonts', {
+ include: ['*.*'],
+ destDir: '/assets/fonts'
+ });
+
+ // bootstrap color picker
+ importVendor(app, 'bower_components/mjolnic-bootstrap-colorpicker/dist/css/bootstrap-colorpicker.min.css');
+ importVendor(app, 'bower_components/mjolnic-bootstrap-colorpicker/dist/js/bootstrap-colorpicker.min.js');
+ let bcpAssets = new Funnel('bower_components/mjolnic-bootstrap-colorpicker/dist/img', {
+ include: ['bootstrap-colorpicker/*.*'],
+ destDir: '/assets/img'
+ });
+
+ // JQuery HotKeys
+ // importVendor(app, 'bower_components/jquery.hotkeys/jquery.hotkeys.js');
+ // Bootstrap WYSIWYG
+ importVendor(app, 'bower_components/bootstrap-wysiwyg/bootstrap-wysiwyg.js');
+
+ // Bootstrap TreeView
+ importVendor(app, 'bower_components/bootstrap-treeview/src/css/bootstrap-treeview.css');
+ importVendor(app, 'bower_components/bootstrap-treeview/src/js/bootstrap-treeview.js');
+
+ // ACE CSS
+ importVendor(app, 'vendor/ace/css/ace.css');
+ importVendor(app, 'vendor/ace/css/ace-fonts.css');
+ let aceFonts = new Funnel('vendor/ace/fonts', {
+ include: ['*.*'],
+ destDir: '/assets/fonts'
+ });
+ let aceImages = new Funnel('vendor/ace/css/images', {
+ include: ['**/*.*'],
+ destDir: '/assets/css/images'
+ });
+
+ // ACE JS
+ // start up
+ importVendor(app, 'vendor/ace/js/ace/ace.js');
+ importVendor(app, 'vendor/ace/js/ace-extra.js');
+ importVendor(app, 'vendor/ace/js/ace-elements.js');
+
+ // importVendor(app, 'vendor/ace/js/ace/elements.fileinput.js');
+ // importVendor(app, 'vendor/ace/js/ace/elements.spinner.js');
+ // importVendor(app, 'vendor/ace/js/ace/elements.treeview.js');
+ // importVendor(app, 'vendor/ace/js/ace/elements.wysiwyg.js');
+
+ // importVendor(app, 'vendor/ace/js/jquery-ui.custom.js');
+
+ importVendor(app, 'vendor/ace/js/ace/ace.touch-drag.js');
+
+ importVendor(app, 'vendor/ace/js/ace/ace.sidebar.js');
+ importVendor(app, 'vendor/ace/js/ace/ace.sidebar-scroll-1.js');
+ importVendor(app, 'vendor/ace/js/ace/ace.submenu-hover.js');
+
+ importVendor(app, 'vendor/ace/js/ace/ace.settings.js');
+ importVendor(app, 'vendor/ace/js/ace/ace.settings-rtl.js');
+ importVendor(app, 'vendor/ace/js/ace/ace.settings-skin.js');
+
+ importVendor(app, 'vendor/ace/js/ace/ace.widget-box.js');
+ importVendor(app, 'vendor/ace/js/ace/ace.widget-on-reload.js');
+ importVendor(app, 'vendor/ace/js/ace/ace.searchbox-autocomplete.js');
+
+ // JQuery Qr Code
+ importVendor(app, 'vendor/jquery-qrcode/js/jquery-qrcode.js');
+ // JQuery Hot Keys
+ importVendor(app, 'vendor/jquery-hotkeys/js/jquery.hotkeys.min.js');
+
+ // compile public es6
+ const publicJs = BabelTranspiler('public', {
+ browserPolyfill: true,
+ filterExtensions: ['js']
+ });
+
+ return app.toTree([bootstrapAssets,
+ jqColorboxAssets,
+ faAssets,
+ bcpAssets,
+ aceFonts,
+ aceImages,
+ publicJs
+ ]);
+};
diff --git a/web/package.json b/web/package.json
new file mode 100644
index 0000000..e23695c
--- /dev/null
+++ b/web/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "ambition-crm",
+ "version": "0.0.1",
+ "description": "Ambition CRM",
+ "private": true,
+ "directories": {
+ "doc": "doc",
+ "test": "tests"
+ },
+ "scripts": {
+ "build": "ember build",
+ "start": "ember server",
+ "test": "ember test"
+ },
+ "repository": "",
+ "engines": {
+ "node": ">= 0.10.0"
+ },
+ "author": "Shaun Chyxion",
+ "license": "MIT",
+ "devDependencies": {
+ "broccoli-asset-rev": "^2.4.2",
+ "broccoli-funnel": "^1.0.1",
+ "ember-ajax": "0.7.1",
+ "ember-browserify": "^1.1.11",
+ "ember-cli": "2.5.0",
+ "ember-cli-app-version": "^1.0.0",
+ "ember-cli-babel": "^5.1.6",
+ "ember-cli-dependency-checker": "^1.2.0",
+ "ember-cli-htmlbars": "^1.0.3",
+ "ember-cli-htmlbars-inline-precompile": "^0.3.1",
+ "ember-cli-inject-live-reload": "^1.4.0",
+ "ember-cli-jshint": "^1.0.0",
+ "ember-cli-moment-shim": "1.2.0",
+ "ember-cli-qunit": "^1.4.0",
+ "ember-cli-release": "0.2.8",
+ "ember-cli-sri": "^2.1.0",
+ "ember-cli-uglify": "^1.2.0",
+ "ember-export-application-global": "^1.0.5",
+ "ember-load-initializers": "^0.5.1",
+ "ember-moment": "6.1.0",
+ "ember-resolver": "^2.0.3",
+ "ember-route-action-helper": "2.0.3",
+ "ember-truth-helpers": "1.1.0",
+ "emberx-select": "3.0.1",
+ "glob": "^4.5.3",
+ "loader.js": "^4.0.1",
+ "morgan": "^1.7.0",
+ "valid-url": "^1.0.9"
+ },
+ "dependencies": {}
+}
diff --git a/web/public/assets/css/ace-ie.css b/web/public/assets/css/ace-ie.css
new file mode 100644
index 0000000..e691a7e
--- /dev/null
+++ b/web/public/assets/css/ace-ie.css
@@ -0,0 +1,389 @@
+/* a few ie8/9 specific changes */
+.navbar .navbar-inner , .navbar .btn-navbar {
+ filter:progid:DXImageTransform.Microsoft.gradient(enabled=false) !important;
+}
+.dropdown-menu li > a,
+.dropdown-submenu > a {
+ filter:progid:DXImageTransform.Microsoft.gradient(enabled=false) !important;
+}
+.btn {
+ filter:progid:DXImageTransform.Microsoft.gradient(enabled=false) !important;
+}
+.progress , .progress .bar {
+ filter:progid:DXImageTransform.Microsoft.gradient(enabled=false) !important;
+}
+
+
+
+
+#cboxLoadingGraphic > .ace-icon, #cboxLoadingGraphic > .fa , #cboxLoadingGraphic > .glyphicon {
+ display:inline-block;
+ background:#FFF url('images/loading.gif') no-repeat center;
+}
+#cboxLoadingGraphic > .ace-icon:before, #cboxLoadingGraphic > .fa:before, #cboxLoadingGraphic > .glyphicon:before {
+ display:none;
+}
+
+.widget-box-overlay > .loading-icon {
+ display:inline-block;
+ width:24px;
+ height:24px;
+ background:transparent url('images/loading.gif') no-repeat center;
+}
+.widget-box-overlay > .loading-icon:before {
+ display:none;
+}
+
+
+@media (max-width: 991px) {
+ .sidebar.responsive {
+ display: none;
+ }
+ .sidebar.responsive.display {
+ display: block;
+ }
+}
+
+.profile-user-info { width: 98%; }
+.wysiwyg-toolbar .dropdown-menu { min-width: 260px; }
+
+.modal.modal-contained {
+ position: absolute !important;
+}
+
+
+/* IE9 and below have an issue with left & right borders and RTL */
+.rtl .sidebar .nav-list li.active > a:before, .rtl .sidebar .nav-list li.active > a:after {
+ direction: ltr;
+ text-align: left;
+}
+.rtl .sidebar .nav-list li > .arrow {
+ direction: ltr;
+ text-align: left;
+}
+
+
+
+
+/* following is for ie8 only */
+@media \0screen {
+
+html {
+ /* to fix it when inside iframe */
+ position: absolute;
+ width: 100%;
+}
+
+body {
+ background-color: #E9E9E9;
+}
+
+.sidebar-fixed:before {
+ left: 0;
+}
+/* it doesn't show up in ie8, so let's make it visible at least when inside .container */
+.sidebar .nav-list > li:before {
+ z-index: 4444;
+ left: -3px;
+}
+
+
+
+.nav-list > li > .submenu li.open > a > .menu-icon {
+ display: inline-block;
+}
+
+.ace-nav > li.white-opaque {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#CCFFFFFF', endColorstr='#CCFFFFFF',GradientType=0 );
+}
+.ace-nav > li.dark-opaque {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33000000', endColorstr='#33000000',GradientType=0 );
+}
+
+.ace-nav > li.transparent > a:hover,
+.ace-nav > li.transparent > a:focus,
+.ace-nav > li.open.transparent > a {
+ background-color: transparent !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#19000000', endColorstr='#19000000',GradientType=0 );
+}
+
+.ace-nav > li.light-10 > a {
+ background-color: transparent !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#19FFFFFF', endColorstr='#19FFFFFF',GradientType=0 );
+}
+.ace-nav > li.light-10 > a:hover, .ace-nav > li.light-10 > a:focus, .ace-nav > li.open.light-10 > a {
+ background-color: transparent !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#CCFFFFFF', endColorstr='#CCFFFFFF',GradientType=0 ) !important;
+}
+
+.ace-nav > li.dark-10 > a {
+ background-color: transparent !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#19000000', endColorstr='#19000000',GradientType=0 );
+}
+.ace-nav > li.dark-10 > a:hover, .ace-nav > li.dark-10 > a:focus, .ace-nav > li.open.dark-10 > a {
+ background-color: transparent !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33000000', endColorstr='#33000000',GradientType=0 );
+}
+
+
+
+.navbar .navbar-nav > li > a:hover,
+.navbar .navbar-nav > li > a:focus,
+.navbar .navbar-nav > li.open > a {
+ background-color: transparent !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#19000000', endColorstr='#19000000',GradientType=0 ) !important;
+}
+
+
+
+.infobox-dark > .badge {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#33FFFFFF', endColorstr='#33FFFFFF',GradientType=0 ) !important;
+}
+.widget-box-overlay {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#55000000', endColorstr='#55000000',GradientType=0 ) !important;
+}
+.widget-toolbar-light {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#D8FFFFFF', endColorstr='#D8FFFFFF',GradientType=0 ) !important;
+}
+
+input[type=checkbox].ace , input[type=radio].ace,
+label input[type=checkbox].ace , label input[type=radio].ace,
+input[type=checkbox].ace.ace-switch , input[type=radio].ace.ace-switch,
+label input[type=checkbox].ace.ace-switch , label input[type=radio].ace.ace-switch
+ {
+ position: static !important;
+ width: auto !important;
+ height: auto !important;
+ z-index: auto !important;
+}
+
+input[type=checkbox].ace + .lbl, input[type=radio].ace + .lbl,
+input[type=checkbox].ace ~ .lbl, input[type=radio].ace ~ .lbl {
+ min-height: auto !important;
+ min-width: auto !important;
+ width: auto !important;
+ height: auto !important;
+ position: static !important;
+}
+input[type=checkbox].ace.ace-switch {
+ width: auto !important;
+}
+input[type=checkbox].ace.ace-switch + .lbl,
+input[type=checkbox].ace.ace-switch ~ .lbl {
+ margin: 0 !important;
+ min-height: auto !important;
+}
+.checkbox label input.ace[type="checkbox"] + .lbl,
+.radio label input.ace[type="radio"] + .lbl,
+.checkbox label input.ace[type="checkbox"] ~ .lbl,
+.radio label input.ace[type="radio"] ~ .lbl {
+ margin-left: auto;
+}
+
+
+[class*="input-"] {
+ max-width: none !important;
+}
+
+
+
+.wizard-steps li:first-child:before {
+ max-width:100%;
+ left:0;
+}
+
+.login-layout .widget-box {
+ display:none;
+ visibility:visible;
+ position:static;
+}
+
+.login-layout .widget-box.visible {
+ display:block;
+}
+.pricing-box-small:hover {
+ left:-1px;
+ top:-3px;
+}
+
+
+.ace-thumbnails > li > a > img{
+ width:auto !important;
+}
+.ace-thumbnails > li > :first-child > .text{
+ display:none;
+}
+.ace-thumbnails > li:hover > :first-child > .text{
+ display:block;
+}
+.ace-thumbnails > li > .tools{
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#8C000000', endColorstr='#8C000000', GradientType=0) !important;
+}
+.ace-thumbnails > li > :first-child > .text{
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#8C000000', endColorstr='#8C000000', GradientType=0) !important;
+}
+
+
+
+.btn.btn-app.btn-light {
+ border: 1px solid #D9D9D9;
+}
+.btn.btn-app.btn-yellow {
+ border: 1px solid #FEE188;
+}
+
+
+.widget-box-overlay {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#55000000', endColorstr='#55000000',GradientType=0 ) !important;
+}
+.ace-file-overlay {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#7F000000', endColorstr='#7F000000',GradientType=0 ) !important;
+}
+.ace-file-overlay > .ace-icon, .ace-file-overlay > .fa, .ace-file-overlay > .glyphicon {
+ display: inline-block;
+ width: 32px;
+ height: 32px;
+ background: transparent url('images/loading.gif') no-repeat center;
+}
+.ace-file-overlay > .ace-icon:before, .ace-file-overlay > .fa:before, .ace-file-overlay > .glyphicon:before {
+ display: none;
+}
+
+
+.grid3 {
+ width:31%;
+}
+.grid4 {
+ width:23%;
+}
+
+.itemdiv.dialogdiv > .body:before{
+ display:none;
+}
+
+.fc-event-hori, .fc-event-vert {
+ border-width: 0 !important;
+}
+
+
+[class*="tab-color-"] .nav-tabs > li > a > .ace-icon:first-child,
+[class*="tab-color-"] .nav-tabs > li > a > .fa:first-child
+ {
+ color: #666 !important;
+}
+
+
+.dropdown-preview > .dropdown-menu {
+ *width: 180px;
+}
+
+/*jquery ui*/
+.ui-datepicker , .ui-autocomplete , .ui-menu{
+ border:1px solid #CCC;
+}
+.ui-widget-overlay {
+ filter:alpha(opacity=100) !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#44000000', endColorstr='#44000000',GradientType=0 ) !important;
+}
+
+
+.message-content {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#CCFFFFFF', endColorstr='#CCFFFFFF',GradientType=0 ) !important;
+}
+
+
+
+/* semi transparent gritter backgrounds */
+.gritter-item-wrapper {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EA323232', endColorstr='#EA323232',GradientType=0 ) !important; /* IE6-9 */
+}
+.gritter-item-wrapper.gritter-info {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EA315185', endColorstr='#EA315185',GradientType=0 ) !important; /* IE6-9 */
+}
+.gritter-item-wrapper.gritter-error {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EA992812', endColorstr='#EA992812',GradientType=0 ) !important; /* IE6-9 */
+}
+.gritter-item-wrapper.gritter-success {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EA59834B', endColorstr='#EA59834B',GradientType=0 ) !important; /* IE6-9 */
+}
+.gritter-item-wrapper.gritter-warning {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#EABE701F', endColorstr='#EABE701F',GradientType=0 ) !important; /* IE6-9 */
+}
+
+.gritter-item-wrapper.gritter-light {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F2F5F5F5', endColorstr='#F2F5F5F5',GradientType=0 ) !important; /* IE6-9 */
+}
+.gritter-info.gritter-light {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F2E8F2FF', endColorstr='#F2E8F2FF',GradientType=0 ) !important; /* IE6-9 */
+}
+.gritter-error.gritter-light {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F2FFEBEB', endColorstr='#F2FFEBEB',GradientType=0 ) !important; /* IE6-9 */
+}
+.gritter-success.gritter-light {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F2EFFAE3', endColorstr='#F2EFFAE3',GradientType=0 ) !important; /* IE6-9 */
+}
+.gritter-warning.gritter-light {
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#F2FCF8E3', endColorstr='#F2FCF8E3',GradientType=0 ) !important; /* IE6-9 */
+}
+
+
+
+
+.widget-header .wysiwyg-toolbar .btn-group > .btn , .widget-body .md-header .btn {
+ background:transparent none !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#40FFFFFF', endColorstr='#40FFFFFF',GradientType=0 ) !important;
+}
+.widget-header .wysiwyg-toolbar .btn-group > .btn.active , .widget-body .md-header .btn-inverse {
+ background:transparent none !important;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#40000000', endColorstr='#40000000',GradientType=0 ) !important;
+}
+.widget-body .md-header .btn , .widget-body .md-header .btn-inverse {
+ display:none;
+}
+
+
+.scroller-bar , .scroller-active .scroller-bar {
+ display: none;
+}
+.scroller-active:hover .scroller-bar,
+.scroller-active .scroller-bar.active,
+.scroller-active .scroller-bar:active,
+.nav-wrap:hover + .scroller-active .scroller-bar {
+ display: block;
+}
+
+
+
+.ace-settings-box {
+ display: none;
+}
+.ace-settings-box.open {
+ display: block;
+}
+
+[data-toggle="buttons"] > .btn > input[type="radio"],
+[data-toggle="buttons"] > .btn > input[type="checkbox"] {
+ display: none;
+}
+
+
+
+.aside.aside-hidden.aside-vc .modal-dialog {
+ width: 0;
+}
+.aside.aside-hidden.aside-hz .modal-dialog {
+ height: 0;
+}
+
+ .btn-group > .btn-app:first-child {
+ margin-right: 24px;
+ }
+ .btn-group > .btn-app.dropdown-toggle:first-child {
+ margin-right: auto;
+ }
+
+
+ .sidebar .submenu.sub-scroll {
+ overflow-y: auto;
+ }
+}
\ No newline at end of file
diff --git a/web/public/assets/css/ace-part2.css b/web/public/assets/css/ace-part2.css
new file mode 100644
index 0000000..4da02fa
--- /dev/null
+++ b/web/public/assets/css/ace-part2.css
@@ -0,0 +1,5715 @@
+.timeline-style2 .timeline-info {
+ width: 100px;
+}
+.timeline-style2 .timeline-indicator {
+ font-size: 0;
+ height: 12px;
+ line-height: 12px;
+ width: 12px;
+ border-width: 1px !important;
+ background-color: #FFFFFF !important;
+ position: absolute;
+ left: 85px;
+ top: 3px;
+ opacity: 1;
+ border-radius: 100%;
+ display: inline-block;
+ padding: 0;
+}
+.timeline-style2 .timeline-date {
+ display: inline-block;
+ width: 72px;
+ text-align: right;
+ margin-right: 25px;
+ color: #777;
+}
+.timeline-style2 .timeline-item .widget-box {
+ margin-left: 112px;
+}
+.timeline-style2 .timeline-label {
+ width: 75px;
+ text-align: center;
+ margin-left: 0;
+ margin-bottom: 10px;
+ text-align: right;
+ color: #666;
+ font-size: 14px;
+}
+.timeline-time {
+ text-align: center;
+ position: static;
+}
+.dataTables_length select {
+ width: 70px;
+ height: 25px;
+ padding: 2px 3px;
+}
+.dataTables_length label {
+ font-weight: normal;
+}
+.dataTables_filter {
+ text-align: right;
+}
+.dataTables_filter input[type=text],
+.dataTables_filter input[type=search] {
+ width: 125px;
+ height: 18px;
+ line-height: 18px;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ padding: 4px 6px;
+}
+.dataTables_filter label {
+ font-weight: normal;
+}
+.dataTables_info {
+ font-size: 14px;
+}
+.dataTables_paginate {
+ text-align: right;
+}
+.dataTables_paginate .pagination {
+ margin: 0 12px;
+}
+.dataTables_wrapper label {
+ display: inline-block;
+ font-size: 13px;
+}
+.dataTables_wrapper input[type=text],
+.dataTables_wrapper input[type=search],
+.dataTables_wrapper select {
+ margin-bottom: 0 !important;
+ margin: 0 4px;
+}
+.dataTables_wrapper .row {
+ margin: 0 !important;
+}
+.dataTables_wrapper .row:first-child {
+ padding-top: 12px;
+ padding-bottom: 12px;
+ background-color: #EFF3F8;
+}
+.dataTables_wrapper .row:first-child + .dataTable {
+ border-top: 1px solid #dddddd;
+ border-bottom: 1px solid #dddddd;
+}
+.dataTables_wrapper .row:last-child {
+ border-bottom: 1px solid #e0e0e0;
+ padding-top: 12px;
+ padding-bottom: 12px;
+ background-color: #EFF3F8;
+}
+.dataTables_wrapper .dataTables_scroll + .row {
+ border-top: 1px solid #e0e0e0;
+}
+.dataTable {
+ margin-bottom: 0;
+}
+.dataTable > thead > tr > th[class*=sort] {
+ cursor: pointer;
+}
+.dataTable > thead > tr > th[class*=sort]:after {
+ float: right;
+ display: inline;
+ content: "\f0dc";
+ font-family: FontAwesome;
+ font-size: 13px;
+ font-weight: normal;
+ color: #555;
+}
+.dataTable > thead > tr > th[class*=sort]:hover {
+ color: #547ea8;
+}
+.dataTable > thead > tr > th[class*=sorting_] {
+ color: #307ecc;
+}
+.dataTable > thead > tr > th.sorting_desc,
+.dataTable > thead > tr > th.sorting_asc {
+ background-image: -webkit-linear-gradient(top, #eff3f8 0%, #e3e7ed 100%);
+ background-image: -o-linear-gradient(top, #eff3f8 0%, #e3e7ed 100%);
+ background-image: linear-gradient(to bottom, #eff3f8 0%, #e3e7ed 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeff3f8', endColorstr='#ffe3e7ed', GradientType=0);
+}
+.dataTable > thead > tr > th.sorting_desc:after {
+ content: "\f0dd";
+ top: -6px;
+ color: #307ecc;
+}
+.dataTable > thead > tr > th.sorting_asc:after {
+ content: "\f0de";
+ top: 4px;
+ color: #307ecc;
+}
+.dataTable > thead > tr > th.sorting_disabled {
+ cursor: inherit;
+}
+.dataTable > thead > tr > th.sorting_disabled:after {
+ display: none;
+}
+.dataTables_scrollHead + .dataTables_scrollBody > .dataTable > thead > tr > th:after {
+ display: none;
+}
+.dataTables_scrollHeadInner {
+ width: auto !important;
+}
+.dataTables_scrollHeadInner > .dataTable > thead > tr > th {
+ border-bottom-width: 0 !important;
+}
+.dataTables_borderWrap .dataTables_scrollBody,
+.dataTables_borderWrap .dataTables_scrollHead {
+ border: 1px solid #dddddd !important;
+ border-width: 0 1px !important;
+}
+.dataTables_borderWrap .dataTables_scrollBody .table-bordered,
+.dataTables_borderWrap .dataTables_scrollHead .table-bordered {
+ border-left-width: 0;
+ border-right-width: 0;
+}
+.dataTables_borderWrap .dataTables_scrollBody .table-bordered > thead > tr > th:first-child,
+.dataTables_borderWrap .dataTables_scrollHead .table-bordered > thead > tr > th:first-child,
+.dataTables_borderWrap .dataTables_scrollBody .table-bordered > tbody > tr > td:first-child,
+.dataTables_borderWrap .dataTables_scrollHead .table-bordered > tbody > tr > td:first-child {
+ border-left-width: 0;
+}
+.dataTables_borderWrap .dataTables_scrollBody .table-bordered > thead > tr > th:last-child,
+.dataTables_borderWrap .dataTables_scrollHead .table-bordered > thead > tr > th:last-child,
+.dataTables_borderWrap .dataTables_scrollBody .table-bordered > tbody > tr > td:last-child,
+.dataTables_borderWrap .dataTables_scrollHead .table-bordered > tbody > tr > td:last-child {
+ border-right-width: 0;
+}
+table.dataTable {
+ clear: both;
+ max-width: none !important;
+}
+table.dataTable th:active {
+ outline: none;
+}
+div.dataTables_scrollHead table {
+ margin-bottom: 0 !important;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+}
+div.dataTables_scrollHead table thead tr:last-child th:first-child,
+div.dataTables_scrollHead table thead tr:last-child td:first-child {
+ border-bottom-left-radius: 0 !important;
+ border-bottom-right-radius: 0 !important;
+}
+div.dataTables_scrollBody table {
+ border-top: none;
+ margin-top: 0 !important;
+ margin-bottom: 0 !important;
+}
+div.dataTables_scrollBody tbody tr:first-child th,
+div.dataTables_scrollBody tbody tr:first-child td {
+ border-top: none;
+}
+div.dataTables_scrollFoot table {
+ margin-top: 0 !important;
+ border-top: none;
+}
+.DTTT_Print .main-content {
+ margin-left: 0 !important;
+ margin-right: 0 !important;
+}
+.DTTT_Print .navbar-fixed-top + .main-container {
+ padding-top: 0;
+}
+.tableTools-container {
+ margin-bottom: 8px;
+}
+.tableTools-alert.gritter-item-wrapper {
+ padding: 12px 11px 8px;
+ z-index: 1999;
+}
+ul.ColVis_collection {
+ z-index: 2002;
+}
+ul.ColVis_collection > li > a {
+ padding: 0;
+}
+ul.ColVis_collection > li > a:focus {
+ outline: none;
+}
+ul.ColVis_collection > li.ColVis_Special {
+ border-top: 1px solid #DDD;
+}
+ul.ColVis_collection > li.ColVis_Special > a {
+ padding: 6px 11px 7px;
+ text-align: center;
+}
+ul.ColVis_collection label {
+ margin: auto;
+ padding: 6px 11px 7px;
+ display: block;
+ cursor: pointer;
+}
+div.ColVis_catcher {
+ position: absolute;
+ z-index: 1101;
+}
+div.ColVis_collectionBackground {
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ background-color: black;
+ z-index: 1100;
+}
+.fc-toolbar h2 {
+ font-size: 22px;
+ color: #65A0CE;
+}
+.fc-unthemed th,
+.fc-unthemed td,
+.fc-unthemed hr,
+.fc-unthemed thead,
+.fc-unthemed tbody,
+.fc-unthemed .fc-row,
+.fc-unthemed .fc-popover {
+ border-color: #BCD4E5;
+}
+.fc-unthemed .fc-today {
+ background: #FFC;
+}
+.fc-event {
+ border-width: 0;
+ color: #ffffff;
+ padding: 1px 1px 2px 2px;
+ border-radius: 0;
+}
+.fc-event:not([class*="label-"]) {
+ background-color: #abbac3;
+}
+.fc-event.label-yellow {
+ color: #996633;
+}
+.fc-event.label-light {
+ color: #888888;
+}
+.label-yellow .fc-event {
+ color: #996633;
+}
+.label-light .fc-event {
+ color: #888;
+}
+[class*="label-"] > .fc-event,
+[class*="label-"] > .fc-event > .fc-event-skin.fc-event-head {
+ background-color: inherit;
+}
+.fc-event.ui-draggable-dragging {
+ cursor: move;
+}
+.fc-event.fc-event-vert,
+.fc-event-vert > .fc-event {
+ padding: 0 0 1px;
+}
+.fc-day-number {
+ color: #2E6589;
+ opacity: 1;
+ filter: alpha(opacity=100);
+}
+.fc-widget-header,
+.fc .fc-axis {
+ background: #ECF2F7;
+ color: #8090A0;
+}
+.fc-event-hori,
+.fc-event-vert {
+ border-radius: 0 !important;
+ border-color: transparent;
+}
+.fc-event-vert .fc-event-content {
+ padding-left: 1px;
+ padding-right: 1px;
+}
+.fc-event-vert .fc-event-time {
+ padding: 0;
+}
+.fc-state-default {
+ border: none;
+}
+.fc-state-default,
+.fc-state-default .fc-button-inner {
+ border: none;
+ background-color: #abbac3;
+ color: #FFF;
+ background-image: none;
+ box-shadow: none;
+ text-shadow: none;
+ border-radius: 0 !important;
+ margin-left: 2px;
+}
+.fc-state-default .fc-button-effect {
+ display: none;
+}
+.fc-state-disabled,
+.fc-state-disabled .fc-button-inner {
+ opacity: 0.75;
+ filter: alpha(opacity=75);
+ color: #DDD;
+}
+.fc-state-active,
+.fc-state-active .fc-button-inner {
+ border-color: #4F99C6;
+ background-color: #6FB3E0;
+}
+.fc-state-hover,
+.fc-state-hover .fc-button-inner {
+ background-color: #8B9AA3;
+}
+.fc .fc-button-group > * {
+ margin: 0 1px 0 0;
+}
+.external-event {
+ margin: 6px 0;
+ padding: 0;
+ cursor: default;
+ display: block;
+ font-size: 13px;
+ line-height: 28px;
+ color: #ffffff;
+}
+.external-event:not([class*="label-"]) {
+ background-color: #abbac3;
+}
+.external-event:hover {
+ opacity: 1;
+ filter: alpha(opacity=100);
+}
+.external-event.ui-draggable-dragging {
+ cursor: move;
+}
+.external-event.label-yellow {
+ color: #996633;
+}
+.external-event.label-light {
+ color: #888888;
+}
+.external-event > .ace-icon:first-child {
+ display: inline-block;
+ height: 32px;
+ width: 32px;
+ text-align: center;
+ line-height: 30px;
+ margin-right: 5px;
+ font-size: 15px;
+ border-right: 1px solid #FFF;
+}
+/**
+.widget-main {
+ .fc {
+ position:relative;
+ top:-40px;
+
+ > .fc-header {
+ position:relative;
+ z-index:10;
+ }
+
+ .fc-header-space {
+ padding-left:2px;
+ }
+ }
+
+ .fc-header-title > h2 {
+ font-size: floor(@base-font-size * 1.4);
+ line-height: 36px;
+ }
+
+ .fc-content {
+ top:-14px;
+ z-index:11;
+ }
+
+ .fc-button-content {
+ height:37px;
+ line-height:36px;
+ }
+
+}
+*/
+@media only screen and (max-width: 480px) {
+ .fc-header td {
+ display: block;
+ width: auto;
+ text-align: left;
+ }
+}
+.chosen-container + .help-inline {
+ vertical-align: middle;
+}
+/**
+.chosen-select {
+ display: inline !important; //for validation plugin to work it must be displayed
+ visibility: hidden;
+ opacity: 0;
+ position: absolute;
+ z-index: -1;
+ width: 0;
+ height: 0;
+ border-width: 0;
+}
+*/
+.chosen-container,
+[class*="chosen-container"] {
+ vertical-align: middle;
+}
+.chosen-container > .chosen-single,
+[class*="chosen-container"] > .chosen-single {
+ line-height: 28px;
+ height: 32px;
+ box-shadow: none;
+ background: #FAFAFA;
+}
+.chosen-choices {
+ box-shadow: none !important;
+}
+.chosen-container-single .chosen-single abbr {
+ background: none;
+}
+.chosen-container-single .chosen-single abbr:after {
+ content: "\f00d";
+ display: inline-block;
+ color: #888;
+ font-family: FontAwesome;
+ font-size: 13px;
+ position: absolute;
+ right: 0;
+ top: -7px;
+}
+.chosen-container-single .chosen-single abbr:hover:after {
+ color: #464646;
+}
+.chosen-container-single.chosen-disabled .chosen-single abbr:hover:after {
+ color: #464646;
+}
+.chosen-single div b {
+ background: none !important;
+}
+.chosen-single div b:before {
+ content: "\f0d7";
+ display: inline-block;
+ color: #888;
+ font-family: FontAwesome;
+ font-size: 12px;
+ position: relative;
+ top: -1px;
+ left: 1px;
+}
+.chosen-container-active.chosen-with-drop .chosen-single div b:before {
+ content: "\f0d8";
+}
+.chosen-container-single .chosen-search {
+ position: relative;
+}
+.chosen-container-single .chosen-search input[type="text"] {
+ background: none;
+ border-radius: 0;
+ line-height: 28px;
+ height: 28px;
+}
+.chosen-container-single .chosen-search:after {
+ content: "\f002";
+ display: inline-block;
+ color: #888;
+ font-family: FontAwesome;
+ font-size: 14px;
+ position: absolute;
+ top: 8px;
+ right: 12px;
+}
+.chosen-container-multi .chosen-choices li.search-field input[type="text"] {
+ height: 25px;
+}
+.chosen-container-multi .chosen-choices li.search-choice {
+ line-height: 16px;
+ padding-bottom: 4px;
+}
+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
+ background: none;
+}
+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before {
+ content: "\f00d";
+ display: inline-block;
+ color: #888;
+ font-family: FontAwesome;
+ font-size: 13px;
+ position: absolute;
+ right: 2px;
+ top: -1px;
+}
+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
+ text-decoration: none;
+}
+.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover:before {
+ color: #464646;
+}
+.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close:before {
+ color: #464646;
+}
+.chosen-container .chosen-results-scroll-down span,
+.chosen-container .chosen-results-scroll-up span {
+ background: none;
+}
+.chosen-container .chosen-results-scroll-down span:before,
+.chosen-container .chosen-results-scroll-up span:before {
+ content: "\f0d7";
+ display: inline-block;
+ color: #888;
+ font-family: FontAwesome;
+ font-size: 12px;
+ position: relative;
+ top: -1px;
+ left: 1px;
+}
+.chosen-container .chosen-results-scroll-up span:before {
+ content: "\f0d8";
+}
+.chosen-container-active .chosen-single-with-drop div b:before {
+ content: "\f0d8";
+}
+.chosen-rtl .chosen-search input[type="text"] {
+ background: none;
+}
+.chosen-rtl .chosen-search:after {
+ content: "";
+ display: none;
+}
+.chosen-rtl .chosen-search:before {
+ content: "\f002";
+ display: inline-block;
+ color: #888;
+ font-family: FontAwesome;
+ font-size: 14px;
+ position: absolute;
+ top: 9px;
+ left: 12px;
+}
+/** chosen - etc */
+.chosen-container-single .chosen-single {
+ border-radius: 0;
+}
+.chosen-container .chosen-results li.highlighted {
+ background: #316AC5;
+ color: #FFF;
+}
+.chosen-container-single .chosen-drop {
+ border-radius: 0;
+ border-bottom: 3px solid #4492C9;
+ border-color: #4492C9;
+}
+.chosen-single.chosen-single-with-drop,
+.chosen-container-active .chosen-single {
+ border-color: #4492C9;
+}
+.form-group.has-error .chosen-single {
+ border-color: #f2a696 !important;
+}
+.form-group.has-info .chosen-single {
+ border-color: #72aec2 !important;
+}
+.form-group.has-warning .chosen-single {
+ border-color: #e3c94c !important;
+}
+.form-group.has-success .chosen-single {
+ border-color: #9cc573 !important;
+}
+.chosen-container-active.chosen-with-drop .chosen-single {
+ border-color: #4492C9;
+}
+.chosen-container .chosen-drop {
+ display: none;
+}
+.chosen-container.chosen-with-drop .chosen-drop {
+ left: auto;
+ right: auto;
+ display: block;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
+ .chosen-rtl .chosen-search input[type="text"],
+ .chosen-container-single .chosen-single abbr,
+ .chosen-container-single .chosen-single div b,
+ .chosen-container-single .chosen-search input[type="text"],
+ .chosen-container-multi .chosen-choices li.search-choice .search-choice-close,
+ .chosen-container .chosen-results-scroll-down span,
+ .chosen-container .chosen-results-scroll-up span {
+ background-image: none !important;
+ background-repeat: no-repeat !important;
+ background-size: auto !important;
+ }
+}
+.tag-input-style + .chosen-container-multi .chosen-choices li.search-choice {
+ background-image: none;
+ background-color: #91b8d0;
+ color: #FFFFFF;
+ display: inline-block;
+ font-size: 13px;
+ font-weight: normal;
+ margin-bottom: 3px;
+ margin-right: 3px;
+ padding: 6px 22px 7px 9px;
+ position: relative;
+ text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.15);
+ transition: all 0.2s ease 0s;
+ vertical-align: baseline;
+ white-space: nowrap;
+ border: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ border-radius: 0;
+}
+.tag-input-style + .chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ width: 18px;
+ height: auto;
+ line-height: 25px;
+ text-align: center;
+}
+.tag-input-style + .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before {
+ color: #FFF;
+ position: static;
+ font-size: 11px;
+}
+.tag-input-style + .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
+ background-color: rgba(0, 0, 0, 0.2);
+}
+.tag-input-style + .chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover:before {
+ color: #FFF;
+}
+.tag-input-style + .chosen-container-multi.chosen-rtl .chosen-choices li.search-choice {
+ padding: 6px 9px 7px 22px;
+ margin-left: 0;
+ margin-right: 3px !important;
+}
+.tag-input-style + .chosen-container-multi.chosen-rtl .chosen-choices li.search-choice .search-choice-close {
+ right: auto;
+ left: 0;
+}
+.select2-container .select2-choice {
+ border-radius: 0;
+ height: 32px;
+ line-height: 28px;
+}
+.select2-container.select2-drop-above .select2-choice {
+ border-radius: 0;
+}
+.select2-container[class*="input-"] {
+ max-width: none;
+}
+.select2-container.input-mini {
+ min-width: 100px;
+}
+.select2-container .select2-choice abbr,
+.select2-search-choice-close {
+ background: none;
+}
+.select2-container .select2-choice abbr:before,
+.select2-search-choice-close:before {
+ font-family: FontAwesome;
+ font-size: 12px;
+ display: inline;
+ content: "\f00d";
+ color: #888;
+ position: relative;
+ top: -1px;
+}
+.select2-container .select2-choice abbr:hover:before,
+.select2-search-choice-close:hover:before {
+ color: #555;
+}
+.select2-container .select2-choice abbr:before {
+ top: -7px;
+}
+.select2-search-choice-close:hover {
+ text-decoration: none !important;
+}
+.select2-drop {
+ border-radius: 0;
+ border: 1px solid #4492C9;
+ border-width: 0 1px 3px;
+}
+.select2-drop.select2-drop-above {
+ border-radius: 0;
+}
+.select2-container .select2-choice {
+ background: #FAFAFA none;
+}
+.select2-container-active .select2-choice,
+.select2-container-active .select2-choices,
+.select2-dropdown-open.select2-drop-above .select2-choice,
+.select2-dropdown-open.select2-drop-above .select2-choices,
+.select2-container-multi.select2-container-active .select2-choices {
+ border-color: #4492C9;
+}
+.select2-results .select2-highlighted {
+ background: #316AC5;
+}
+.select2-container .select2-choice .select2-arrow {
+ border-radius: 0;
+ background: transparent none;
+ border: none;
+}
+.select2-container .select2-choice .select2-arrow b {
+ background: none;
+}
+.select2-container .select2-choice .select2-arrow b:before {
+ font-family: FontAwesome;
+ font-size: 12px;
+ display: inline;
+ content: "\f0d7";
+ color: #888;
+ position: relative;
+ left: 5px;
+}
+.select2-dropdown-open .select2-choice .select2-arrow b:before {
+ content: "\f0d8";
+}
+.select2-search .select2-input {
+ background: #fff none;
+ margin-top: 4px;
+}
+.select2-search:after {
+ font-family: FontAwesome;
+ font-size: 14px;
+ display: inline;
+ content: "\f002";
+ color: #777;
+ position: relative;
+ top: 0;
+ left: -20px;
+ z-index: 0;
+}
+.select2-dropdown-open.select2-drop-above .select2-choice,
+.select2-dropdown-open.select2-drop-above .select2-choices {
+ background-image: none;
+ background-color: #F6F6F6;
+}
+.select2-container-multi .select2-choices .select2-search-field input {
+ border: none !important;
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+ background: none !important;
+ font-size: 14px;
+}
+.select2-container-multi .select2-choices .select2-search-choice {
+ line-height: 16px;
+ padding-bottom: 4px;
+}
+.select2-container-active .select2-choice,
+.select2-container-active .select2-choices,
+.select2-container-multi.select2-container-active .select2-choices,
+.select2-dropdown-open.select2-drop-above .select2-choice,
+.select2-dropdown-open.select2-drop-above .select2-choices {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.select2-search input.select2-active {
+ background-color: #FFF;
+ position: relative;
+ z-index: 1;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
+ .select2-search input,
+ .select2-search-choice-close,
+ .select2-container .select2-choice abbr,
+ .select2-container .select2-choice div b {
+ background-image: none !important;
+ background-size: auto !important;
+ }
+ .select2-search input {
+ background-position: auto !important;
+ }
+}
+.select2-container-active.select2-dropdown-open .select2-choice {
+ background-image: -webkit-linear-gradient(top, #eeeeee 0%, #ffffff 100%);
+ background-image: -o-linear-gradient(top, #eeeeee 0%, #ffffff 100%);
+ background-image: linear-gradient(to bottom, #eeeeee 0%, #ffffff 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeeeeee', endColorstr='#ffffffff', GradientType=0);
+}
+.select2-container-active.select2-drop-above .select2-choice {
+ background-image: -webkit-linear-gradient(top, #ffffff 0%, #eeeeee 100%);
+ background-image: -o-linear-gradient(top, #ffffff 0%, #eeeeee 100%);
+ background-image: linear-gradient(to bottom, #ffffff 0%, #eeeeee 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);
+}
+.form-group.has-error .select2-choice,
+.form-group.has-error .select2-choices {
+ border-color: #f2a696 !important;
+}
+.form-group.has-info .select2-choice,
+.form-group.has-info .select2-choices {
+ border-color: #72aec2 !important;
+}
+.form-group.has-warning .select2-choice,
+.form-group.has-warning .select2-choices {
+ border-color: #e3c94c !important;
+}
+.form-group.has-success .select2-choice,
+.form-group.has-success .select2-choices {
+ border-color: #9cc573 !important;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
+ .select2-search input,
+ .select2-search-choice-close,
+ .select2-container .select2-choice abbr,
+ .select2-container .select2-choice .select2-arrow b {
+ background-image: none !important;
+ background-repeat: no-repeat !important;
+ background-size: auto !important;
+ }
+ .select2-search input {
+ background-position: auto !important;
+ }
+}
+.select2-container-multi.tag-input-style .select2-choices .select2-search-choice {
+ background-image: none;
+ background-color: #91b8d0;
+ color: #FFFFFF;
+ display: inline-block;
+ font-size: 13px;
+ font-weight: normal;
+ margin-bottom: 3px;
+ margin-right: 0;
+ padding: 6px 22px 7px 9px;
+ position: relative;
+ text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.15);
+ transition: all 0.2s ease 0s;
+ vertical-align: baseline;
+ white-space: nowrap;
+ border: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ border-radius: 0;
+}
+.select2-container-multi.tag-input-style .select2-choices .select2-search-choice .select2-search-choice-close {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ left: auto;
+ width: 18px;
+ height: auto;
+ line-height: 25px;
+ text-align: center;
+}
+.select2-container-multi.tag-input-style .select2-choices .select2-search-choice .select2-search-choice-close:before {
+ color: #FFF;
+ position: static;
+ font-size: 11px;
+}
+.select2-container-multi.tag-input-style .select2-choices .select2-search-choice .select2-search-choice-close:hover {
+ background-color: rgba(0, 0, 0, 0.2);
+}
+.select2-container-multi.tag-input-style .select2-choices .select2-search-choice .select2-search-choice-close:hover:before {
+ color: #FFF;
+}
+#colorbox:focus,
+#colorbox:active {
+ outline: none;
+}
+#cboxTopLeft,
+#cboxTopCenter,
+#cboxTopRight,
+#cboxMiddleLeft,
+#cboxMiddleRight,
+#cboxBottomLeft,
+#cboxBottomCenter,
+#cboxBottomRight {
+ background: none !important;
+ opacity: 0;
+}
+#cboxContent {
+ border: 12px solid #000;
+ background-color: #FFF;
+ padding: 7px;
+}
+#cboxOverlay {
+ background: rgba(0, 0, 0, 0.95);
+ background: #000;
+}
+#cboxCurrent {
+ left: 64px;
+ margin-bottom: 4px;
+ font-size: 14px;
+}
+#cboxTitle {
+ margin-bottom: 4px;
+ font-size: 14px;
+ color: #777;
+}
+#cboxNext,
+#cboxPrevious,
+#cboxClose {
+ background: none;
+ text-indent: 0;
+ width: 26px;
+ height: 26px;
+ line-height: 22px;
+ padding: 0 4px;
+ text-align: center;
+ border: 2px solid #999;
+ border-radius: 16px;
+ color: #666;
+ font-size: 12px;
+ margin-left: 5px;
+ margin-bottom: 5px;
+}
+#cboxNext:hover,
+#cboxPrevious:hover {
+ color: #333;
+ border-color: #666;
+}
+#cboxContent {
+ overflow: visible;
+}
+#cboxClose {
+ background-color: #000;
+ border: 2px solid #FFF;
+ border-radius: 32px;
+ color: #FFF;
+ font-size: 21px;
+ height: 28px;
+ width: 28px;
+ padding-bottom: 2px;
+ margin-left: 0;
+ right: -14px;
+ top: -14px;
+}
+#cboxLoadingOverlay {
+ background: none !important;
+}
+#cboxLoadingGraphic {
+ background: #FFF none !important;
+ text-align: center;
+}
+#cboxLoadingGraphic > .ace-icon {
+ display: inline-block;
+ background-color: #FFF;
+ border-radius: 8px;
+ width: 32px;
+ height: 32px;
+ position: relative;
+ top: 48%;
+ text-align: center;
+ vertical-align: middle;
+ font-size: 24px;
+ color: #FE7E3E;
+}
+.ace-spinner {
+ display: inline-block;
+}
+.ace-spinner .spinbox-buttons.btn-group-vertical {
+ min-width: 18px;
+}
+.ace-spinner .spinbox-buttons.btn-group-vertical > .btn {
+ font-size: 10px;
+ padding: 0;
+ width: 22px;
+ height: 16px;
+ line-height: 8px;
+ margin-left: 0;
+}
+.ace-spinner .spinbox-buttons.btn-group-vertical > .btn:first-child {
+ margin-top: 0;
+}
+.ace-spinner .spinbox-buttons.btn-group-vertical > .btn > .ace-icon {
+ margin: 0;
+ padding: 0;
+}
+.ace-spinner .spinbox-buttons.btn-group-vertical > .btn + .btn {
+ margin-top: 2px;
+}
+.ace-spinner .spinbox-buttons.btn-group-vertical > .btn-xs {
+ height: 14px;
+ line-height: 7px;
+}
+.ace-spinner .spinbox-buttons.btn-group-vertical > .btn-lg {
+ height: 22px;
+ line-height: 10px;
+ width: 22px;
+}
+.ace-spinner .spinbox-buttons > button.btn.spinbox-up:active {
+ top: -1px;
+}
+.ace-spinner:not(.touch-spinner) .spinbox-buttons > .btn > .ace-icon {
+ margin-top: -1px;
+}
+.ace-spinner.touch-spinner .spinbox-buttons {
+ margin: 0;
+ font-size: 0;
+}
+.ace-spinner.touch-spinner .spinbox-buttons .btn-sm {
+ width: 32px;
+}
+.ace-spinner.touch-spinner .spinbox-buttons .btn-xs {
+ width: 24px;
+}
+.ace-spinner.touch-spinner .spinbox-buttons .btn-lg {
+ width: 40px;
+}
+.ace-spinner.touch-spinner .spinbox-buttons > .btn {
+ margin: 0 1px !important;
+}
+.ace-spinner.touch-spinner .spinbox-buttons > .btn-xs {
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+.ace-spinner.touch-spinner .spinbox-buttons > .btn > .ace-icon {
+ vertical-align: middle;
+ display: inline-block;
+}
+.steps {
+ list-style: none;
+ display: table;
+ width: 100%;
+ padding: 0;
+ margin: 0;
+ position: relative;
+}
+.steps li {
+ display: table-cell;
+ text-align: center;
+ width: 1%;
+}
+.steps li .step {
+ border: 5px solid #ced1d6;
+ color: #546474;
+ font-size: 15px;
+ border-radius: 100%;
+ background-color: #FFF;
+ position: relative;
+ z-index: 2;
+ display: inline-block;
+ width: 40px;
+ height: 40px;
+ line-height: 30px;
+ text-align: center;
+}
+.steps li:before {
+ display: block;
+ content: "";
+ width: 100%;
+ height: 1px;
+ font-size: 0;
+ overflow: hidden;
+ border-top: 4px solid #CED1D6;
+ position: relative;
+ top: 21px;
+ z-index: 1;
+}
+.steps li.last-child:before {
+ max-width: 50%;
+ width: 50%;
+}
+.steps li:last-child:before {
+ max-width: 50%;
+ width: 50%;
+}
+.steps li:first-child:before {
+ max-width: 51%;
+ left: 50%;
+}
+.steps li.active:before,
+.steps li.complete:before,
+.steps li.active .step,
+.steps li.complete .step {
+ border-color: #5293c4;
+}
+.steps li.complete .step {
+ cursor: default;
+ color: #FFF;
+ -webkit-transition: transform ease 0.1s;
+ -o-transition: transform ease 0.1s;
+ transition: transform ease 0.1s;
+}
+.steps li.complete .step:before {
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ line-height: 30px;
+ text-align: center;
+ border-radius: 100%;
+ content: "\f00c";
+ background-color: #FFF;
+ z-index: 3;
+ font-family: FontAwesome;
+ font-size: 17px;
+ color: #87ba21;
+}
+.steps li.complete:hover .step {
+ -moz-transform: scale(1.1);
+ -webkit-transform: scale(1.1);
+ -o-transform: scale(1.1);
+ -ms-transform: scale(1.1);
+ transform: scale(1.1);
+ border-color: #80afd4;
+}
+.steps li.complete:hover:before {
+ border-color: #80afd4;
+}
+.steps li .title {
+ display: block;
+ margin-top: 4px;
+ max-width: 100%;
+ color: #949ea7;
+ font-size: 14px;
+ z-index: 104;
+ text-align: center;
+ table-layout: fixed;
+ word-wrap: break-word;
+}
+.steps li.complete .title,
+.steps li.active .title {
+ color: #2b3d53;
+}
+.step-content {
+ position: relative;
+}
+.step-content .step-pane {
+ display: none;
+ min-height: 200px;
+ padding: 4px 8px 12px;
+}
+.step-content .step-pane.active {
+ display: block;
+}
+.wizard-actions {
+ text-align: right;
+}
+@media only screen and (max-width: 767px) {
+ .steps li .step {
+ width: 30px;
+ height: 30px;
+ line-height: 24px;
+ border-width: 3px;
+ }
+ .steps li:before,
+ .steps li:after {
+ border-width: 3px;
+ }
+ .steps li.complete .step:before {
+ line-height: 24px;
+ font-size: 13px;
+ }
+ .steps li:before {
+ top: 16px;
+ }
+ .step-content .step-pane {
+ padding: 4px 4px 6px;
+ min-height: 150px;
+ }
+}
+.tree {
+ margin: auto;
+ padding: 0 0 0 9px;
+ overflow-x: hidden;
+ overflow-y: auto;
+ position: relative;
+}
+.tree:before {
+ display: inline-block;
+ content: "";
+ position: absolute;
+ top: -20px;
+ bottom: 16px;
+ left: 0;
+ z-index: 1;
+ border: 1px dotted #67b2dd;
+ border-width: 0 0 0 1px;
+}
+.tree .tree-branch-name,
+.tree .tree-item-name {
+ cursor: pointer;
+}
+.tree .tree-branch {
+ width: auto;
+ min-height: 20px;
+ cursor: pointer;
+}
+.tree .tree-branch .tree-branch-header {
+ position: relative;
+ height: 20px;
+ line-height: 20px;
+}
+.tree .tree-branch .tree-branch-header:hover {
+ background-color: #F0F7FC;
+}
+.tree .tree-branch .tree-branch-header .tree-branch-name,
+.tree .tree-item .tree-item-name {
+ display: inline;
+ z-index: 2;
+}
+.tree .tree-branch .tree-branch-header > .tree-branch-name > .ace-icon:first-child,
+.tree .tree-item > .tree-item-name > .ace-icon:first-child {
+ display: inline-block;
+ position: relative;
+ z-index: 2;
+ top: -1px;
+}
+.tree .tree-branch > .tree-branch-header > .tree-branch-name > .tree-label {
+ margin-left: 2px;
+}
+.tree .tree-branch > .tree-branch-header > .tree-branch-name > .ace-icon:first-child {
+ margin: -2px 0 0 -2px;
+}
+.tree .tree-branch:last-child:after {
+ display: inline-block;
+ content: "";
+ position: absolute;
+ z-index: 1;
+ top: 15px;
+ bottom: 0;
+ left: -15px;
+ border-left: 1px solid #FFF;
+}
+.tree .tree-branch .tree-branch-children {
+ margin: 0 0 0 23px;
+ padding: 0;
+ position: relative;
+}
+.tree .tree-branch .tree-branch-children:before {
+ display: inline-block;
+ content: "";
+ position: absolute;
+ z-index: 1;
+ top: -14px;
+ bottom: 16px;
+ left: -14px;
+ border: 1px dotted #67b2dd;
+ border-width: 0 0 0 1px;
+}
+.tree .tree-item {
+ position: relative;
+ height: 20px;
+ line-height: 20px;
+ cursor: pointer;
+}
+.tree .tree-item:hover {
+ background-color: #F0F7FC;
+}
+.tree .tree-item > .tree-item-name > .ace-icon:first-child {
+ margin-right: 3px;
+}
+.tree .tree-item > .tree-item-name > .tree-label > .ace-icon:first-child {
+ margin-left: 3px;
+ margin-right: 3px;
+}
+.tree .tree-item > .ace-icon:first-child {
+ margin-top: -1px;
+}
+.tree .tree-branch,
+.tree .tree-item {
+ position: relative;
+ list-style: none;
+}
+.tree .tree-branch:before,
+.tree .tree-item:before {
+ display: inline-block;
+ content: "";
+ position: absolute;
+ top: 14px;
+ left: -13px;
+ width: 18px;
+ height: 0;
+ border-top: 1px dotted #67b2dd;
+ z-index: 1;
+}
+.tree .tree-selected {
+ background-color: rgba(98, 168, 209, 0.1);
+ color: #6398B0;
+}
+.tree .tree-selected:hover {
+ background-color: rgba(98, 168, 209, 0.1);
+}
+.tree .tree-item,
+.tree .tree-branch {
+ border: 1px solid #FFF;
+}
+.tree .tree-branch .tree-branch-header {
+ border-radius: 0;
+}
+.tree .tree-item,
+.tree .tree-branch .tree-branch-header {
+ margin: 0;
+ padding: 5px;
+ color: #4D6878;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+.tree .tree-item > .tree-item-name > .ace-icon:first-child {
+ color: #F9E8CE;
+ width: 13px;
+ height: 13px;
+ line-height: 13px;
+ font-size: 11px;
+ text-align: center;
+ border-radius: 3px;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ background-color: #FAFAFA;
+ border: 1px solid #CCC;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+.tree .tree-selected > .tree-item-name > .ace-icon:first-child {
+ background-color: #F9A021;
+ border-color: #F9A021;
+ color: #FFF;
+}
+.tree .tree-plus.ace-icon:first-child,
+.tree .tree-minus.ace-icon:first-child {
+ display: inline-block;
+ font-style: normal;
+ border: 1px solid #DDD;
+ vertical-align: middle;
+ height: 11px;
+ width: 11px;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ text-align: center;
+ border: 1px solid #8BAEBF;
+ line-height: 10px;
+ background-color: #FFF;
+ position: relative;
+ z-index: 2;
+}
+.tree .tree-plus.ace-icon:first-child:before,
+.tree .tree-minus.ace-icon:first-child:before {
+ content: "";
+ display: block;
+ width: 7px;
+ height: 0;
+ border-top: 1px solid #4D6878;
+ position: absolute;
+ top: 5px;
+ left: 2px;
+}
+.tree .tree-plus.ace-icon:first-child:after {
+ content: "";
+ display: block;
+ height: 7px;
+ width: 0;
+ border-left: 1px solid #4D6878;
+ position: absolute;
+ top: 2px;
+ left: 5px;
+}
+.tree .tree-unselectable .tree-item > .tree-item-name > .tree-label > .ace-icon:first-child {
+ color: #5084A0;
+ width: 13px;
+ height: 13px;
+ line-height: 13px;
+ font-size: 10px;
+ text-align: center;
+ border-radius: 0;
+ background-color: transparent;
+ border: none;
+ box-shadow: none;
+}
+.tree .ace-icon[class*="-down"] {
+ transform: rotate(-45deg);
+}
+.tree .ace-icon[class*="-download"] {
+ transform: none;
+}
+.tree .fa-spin {
+ height: auto;
+}
+.tree .tree-loading {
+ margin-left: 36px;
+}
+.tree img {
+ display: inline;
+ veritcal-align: middle;
+}
+.gritter-item-wrapper {
+ background-image: none !important;
+ box-shadow: 0 2px 10px rgba(50, 50, 50, 0.5);
+ background: rgba(50, 50, 50, 0.92);
+}
+.gritter-item-wrapper.gritter-info {
+ background: rgba(49, 81, 133, 0.92);
+}
+.gritter-item-wrapper.gritter-error {
+ background: rgba(153, 40, 18, 0.92);
+}
+.gritter-item-wrapper.gritter-success {
+ background: rgba(89, 131, 75, 0.92);
+}
+.gritter-item-wrapper.gritter-warning {
+ background: rgba(190, 112, 31, 0.92);
+}
+.gritter-item-wrapper.gritter-light {
+ background: rgba(245, 245, 245, 0.95);
+ border: 1px solid #BBB;
+}
+.gritter-item-wrapper.gritter-light.gritter-info {
+ background: rgba(232, 242, 255, 0.95);
+}
+.gritter-item-wrapper.gritter-light.gritter-info .gritter-item {
+ color: #4A577D;
+}
+.gritter-item-wrapper.gritter-light.gritter-error {
+ background: rgba(255, 235, 235, 0.95);
+}
+.gritter-item-wrapper.gritter-light.gritter-error .gritter-item {
+ color: #894A38;
+}
+.gritter-item-wrapper.gritter-light.gritter-success {
+ background: rgba(239, 250, 227, 0.95);
+}
+.gritter-item-wrapper.gritter-light.gritter-success .gritter-item {
+ color: #416131;
+}
+.gritter-item-wrapper.gritter-light.gritter-warning {
+ background: rgba(252, 248, 227, 0.95);
+}
+.gritter-item-wrapper.gritter-light.gritter-warning .gritter-item {
+ color: #946446;
+}
+.gritter-item p {
+ line-height: 1.8;
+}
+.gritter-top,
+.gritter-bottom,
+.gritter-item {
+ background-image: none;
+}
+.gritter-close {
+ left: auto;
+ right: 3px;
+ background-image: none;
+ width: 18px;
+ height: 18px;
+ line-height: 17px;
+ text-align: center;
+ border: 2px solid transparent;
+ border-radius: 16px;
+ color: #E17B67;
+}
+.gritter-close:before {
+ font-family: FontAwesome;
+ font-size: 16px;
+ content: "\f00d";
+}
+.gritter-info .gritter-close {
+ color: #FFA500;
+}
+.gritter-error .gritter-close,
+.gritter-success .gritter-close,
+.gritter-warning .gritter-close {
+ color: #FFEA07;
+}
+.gritter-close:hover {
+ color: #FFF !important;
+}
+.gritter-title {
+ text-shadow: none;
+}
+.gritter-light .gritter-item,
+.gritter-light .gritter-bottom,
+.gritter-light .gritter-top,
+.gritter-light .gritter-close {
+ background-image: none;
+ color: #444;
+}
+.gritter-light .gritter-title {
+ text-shadow: none;
+}
+.gritter-light .gritter-close:hover {
+ color: #8A3104 !important;
+}
+.gritter-center {
+ position: fixed;
+ left: 33%;
+ right: 33%;
+ top: 33%;
+}
+@media only screen and (max-width: 767px) {
+ .gritter-center {
+ left: 16%;
+ right: 16%;
+ top: 30%;
+ }
+}
+@media only screen and (max-width: 480px) {
+ .gritter-center {
+ left: 30px;
+ right: 30px;
+ }
+}
+@media only screen and (max-width: 320px) {
+ .gritter-center {
+ left: 10px;
+ right: 10px;
+ }
+}
+.wysiwyg-editor {
+ max-height: 250px;
+ height: 250px;
+ background-color: #F7F8FA;
+ border-collapse: separate;
+ border: 1px solid #BBC0CA;
+ padding: 4px;
+ box-sizing: content-box;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ outline: none;
+}
+.wysiwyg-editor:focus {
+ background-color: #FFF;
+}
+.wysiwyg-toolbar {
+ line-height: 33px;
+ margin: 0 !important;
+ position: relative;
+}
+.wysiwyg-toolbar .dropdown-menu {
+ text-align: left;
+}
+.wysiwyg-toolbar .btn-group {
+ float: none !important;
+ font-size: 0;
+}
+.wysiwyg-toolbar .btn-group > .btn {
+ float: none;
+ padding-left: 0;
+ padding-right: 0;
+ text-align: center;
+ margin-left: 1px;
+ /**
+ &.active:after {
+ border-color: transparent;
+ border-style: solid;
+ border-top-color: inherit;
+ border-width: 6px 14px;
+ bottom: -13px;
+ left: 0;
+ right: 0;
+ }
+ */
+}
+.wysiwyg-toolbar .btn-group > .btn > .ace-icon:first-child {
+ font-size: 14px;
+ width: 25px;
+ max-width: 25px;
+ display: inline-block;
+ border-width: 1px !important;
+}
+.wysiwyg-toolbar .btn-group > .btn.dropdown-toggle > .ace-icon:last-child {
+ margin-right: 4px;
+}
+.wysiwyg-style1 .btn-group > .btn,
+.wysiwyg-style2 .btn-group > .btn,
+.wysiwyg-style1 .btn-group > .inline > .btn,
+.wysiwyg-style2 .btn-group > .inline > .btn {
+ margin: 0 !important;
+ background: #FFF !important;
+ border-width: 0 !important;
+ color: #ADB3BE !important;
+ text-shadow: none !important;
+}
+.wysiwyg-style1 .btn-group > .btn.active,
+.wysiwyg-style2 .btn-group > .btn.active,
+.wysiwyg-style1 .btn-group > .inline > .btn.active,
+.wysiwyg-style2 .btn-group > .inline > .btn.active {
+ color: #5B80CE !important;
+}
+.wysiwyg-style1 .btn-group > .btn.active:after,
+.wysiwyg-style2 .btn-group > .btn.active:after,
+.wysiwyg-style1 .btn-group > .inline > .btn.active:after,
+.wysiwyg-style2 .btn-group > .inline > .btn.active:after {
+ display: none;
+}
+.wysiwyg-style1 .btn-group,
+.wysiwyg-style2 .btn-group {
+ position: relative;
+}
+.wysiwyg-style1 .btn-group:after,
+.wysiwyg-style2 .btn-group:after {
+ display: block;
+ content: "";
+ position: absolute;
+ left: -2px;
+ top: 6px;
+ bottom: 6px;
+ width: 0;
+ max-width: 0;
+ border-left: 1px solid #E1E6EA;
+}
+.wysiwyg-style1 .btn-group:first-child:after,
+.wysiwyg-style2 .btn-group:first-child:after {
+ display: none;
+}
+.wysiwyg-style2 {
+ background-color: #E5E5E5;
+}
+.wysiwyg-style2 + .wysiwyg-editor {
+ border-color: #DDD;
+ background-color: #FFF;
+ border-top: none;
+}
+.wysiwyg-style2 .btn-group > .btn,
+.wysiwyg-style2 .btn-group > .inline > .btn {
+ margin: 0 1px 0 0 !important;
+ background: #FFF !important;
+ border: none !important;
+ color: #8D939E !important;
+ text-shadow: none !important;
+}
+.wysiwyg-style2 .btn-group > .btn.active,
+.wysiwyg-style2 .btn-group > .inline > .btn.active {
+ color: #FFF !important;
+ background: #6AAEDF !important;
+}
+.wysiwyg-style2 .btn-group:after {
+ display: none;
+}
+.wysiwyg-toolbar .btn-colorpicker {
+ width: 24px;
+ height: 24px;
+ position: relative;
+ background: #87B87F;
+ /* Old browsers */
+ background: -moz-linear-gradient(top, #cf3e73 10%, #ffffff 20%, #2283c5 30%, #ffffff 40%, #87b87f 50%, #ffffff 60%, #ffb752 70%, #ffffff 80%, #d15b47 90%, #ffffff 100%);
+ /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(10%, #cf3e73), color-stop(20%, #ffffff), color-stop(30%, #2283c5), color-stop(40%, #ffffff), color-stop(50%, #87b87f), color-stop(60%, #ffffff), color-stop(70%, #ffb752), color-stop(80%, #ffffff), color-stop(90%, #d15b47), color-stop(100%, #ffffff));
+ /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, #cf3e73 10%, #ffffff 20%, #2283c5 30%, #ffffff 40%, #87b87f 50%, #ffffff 60%, #ffb752 70%, #ffffff 80%, #d15b47 90%, #ffffff 100%);
+ /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, #cf3e73 10%, #ffffff 20%, #2283c5 30%, #ffffff 40%, #87b87f 50%, #ffffff 60%, #ffb752 70%, #ffffff 80%, #d15b47 90%, #ffffff 100%);
+ /* Opera11.10+ */
+ background: -ms-linear-gradient(top, #cf3e73 10%, #ffffff 20%, #2283c5 30%, #ffffff 40%, #87b87f 50%, #ffffff 60%, #ffb752 70%, #ffffff 80%, #d15b47 90%, #ffffff 100%);
+ /* IE10+ */
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#CF3E73', endColorstr='#FFB752', GradientType=0);
+ /* IE6-9 */
+ background: linear-gradient(top, #cf3e73 10%, #ffffff 20%, #2283c5 30%, #ffffff 40%, #87b87f 50%, #ffffff 60%, #ffb752 70%, #ffffff 80%, #d15b47 90%, #ffffff 100%);
+ /* W3C */
+}
+.wysiwyg-toolbar .dropdown-colorpicker > .dropdown-menu {
+ top: auto;
+}
+.wysiwyg-toolbar input[type=file] {
+ position: fixed;
+ z-index: -10;
+ opacity: 0;
+ max-width: 0;
+ max-height: 0;
+ display: block;
+}
+.wysiwyg-toolbar .wysiwyg-choose-file {
+ display: inline-block;
+ width: auto;
+ margin: 4px auto 0;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+.wysiwyg-toolbar .dropdown-menu input[type=text] {
+ margin-left: 8px;
+ margin-bottom: 0;
+}
+.wysiwyg-toolbar .dropdown-menu input[type=text].form-control {
+ min-width: 150px;
+}
+.wysiwyg-toolbar .dropdown-menu .btn {
+ margin-right: 8px;
+ margin-left: 8px;
+}
+.wysiwyg-style1 .btn-colorpicker {
+ width: 20px;
+ height: 20px;
+ margin-left: 4px;
+}
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ /* for adding image resize functionality in chrome and safari */
+ .wysiwyg-editor img {
+ display: inline !important;
+ }
+ .wysiwyg-editor .ui-wrapper {
+ border: 1px dotted #D00;
+ overflow: visible !important;
+ /* because it's image only, so it's ok */
+ display: inline-block !important;
+ vertical-align: middle;
+ }
+ .wysiwyg-editor .ui-wrapper:after {
+ content: "";
+ display: block;
+ position: absolute;
+ right: -3px;
+ bottom: -3px;
+ width: 7px;
+ height: 7px;
+ border: 1px solid #D00;
+ background-color: #FFF;
+ z-index: 1;
+ }
+}
+/* inside widget */
+.widget-header .wysiwyg-toolbar {
+ background-color: transparent;
+}
+.widget-header .wysiwyg-toolbar .btn-group > .btn,
+.widget-header .wysiwyg-toolbar .btn-group > .inline > .btn {
+ border-color: transparent;
+ background: rgba(255, 255, 255, 0.25) !important;
+ color: #FFF !important;
+ min-width: 32px;
+ border-width: 1px !important;
+ border-radius: 4px !important;
+ padding: 2px 1px 4px;
+}
+.widget-header .wysiwyg-toolbar .btn-group > .btn.active,
+.widget-header .wysiwyg-toolbar .btn-group > .inline > .btn.active {
+ background: rgba(0, 0, 0, 0.25) !important;
+}
+.widget-body .wysiwyg-editor {
+ border-width: 0;
+}
+.wysiwyg-speech-input {
+ width: 20px !important;
+ color: transparent !important;
+ background: transparent none !important;
+ border-width: 0 !important;
+ -moz-transform: scale(2.0, 2.0);
+ -webkit-transform: scale(2.0, 2.0);
+ -o-transform: scale(2.0, 2.0);
+ -ms-transform: scale(2.0, 2.0);
+ transform: scale(2.0, 2.0);
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+ position: absolute;
+ right: 0;
+ top: -10px;
+ cursor: pointer;
+}
+.wysiwyg-speech-input:focus {
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+}
+.widget-body .md-header {
+ margin-top: -30px;
+ margin-left: 9px;
+}
+.widget-body .md-header .btn {
+ border-color: transparent;
+ background: rgba(255, 255, 255, 0.25) !important;
+ color: #FFF !important;
+ text-align: center;
+ min-width: 32px;
+ border-width: 1px !important;
+ border-radius: 4px !important;
+ padding: 2px 4px 4px;
+}
+.widget-body .md-header .btn > .ace-icon {
+ font-size: 14px;
+ width: 25px;
+ max-width: 25px;
+ display: inline-block;
+}
+.widget-body .md-header .btn-inverse {
+ background: rgba(0, 0, 0, 0.25) !important;
+ padding-right: 5px;
+ margin-left: 4px;
+}
+.md-fullscreen-controls {
+ display: none;
+}
+.widget-body .md-preview {
+ padding: 8px;
+ min-height: 200px;
+}
+.widget-body .md-input {
+ border: none !important;
+ box-shadow: none !important;
+ display: block;
+ margin-bottom: 0;
+ background-color: rgba(48, 126, 204, 0.07);
+ padding: 8px;
+ width: 100%;
+}
+.widget-body .md-input:focus {
+ background-color: #FFF;
+ box-shadow: none !important;
+}
+.editable-container .popover-title {
+ color: #438EB9;
+}
+.editable-click {
+ border-bottom: 1px dashed #BBB;
+ cursor: pointer;
+ font-weight: normal;
+}
+img.editable-click {
+ border: 1px dotted #BBB;
+}
+.editable-click:hover {
+ border-color: #0088CC;
+ color: #0088CC;
+}
+img.editable-click:hover {
+ opacity: 0.75;
+ filter: alpha(opacity=75);
+}
+.editable-buttons,
+.editable-input {
+ display: inline-block;
+}
+.editable-buttons {
+ margin-left: 1px;
+}
+.editable-buttons .btn {
+ padding: 0;
+ width: 28px;
+ line-height: 24px;
+ border-width: 3px;
+ font-size: 12px;
+ margin: 0 1px 0 0;
+}
+.editable-buttons .btn > .ace-icon {
+ margin: 0;
+}
+.editable-clear-x {
+ cursor: pointer;
+ color: #888;
+ background: none;
+}
+.editable-clear-x:hover {
+ color: #D15B47;
+}
+.editable-clear-x:before {
+ display: inline-block;
+ content: "\f057";
+ font-family: FontAwesome;
+ font-size: 15px;
+ position: absolute;
+ margin-top: -9px;
+ width: 16px;
+ height: 30px;
+ line-height: 30px;
+ text-align: center;
+}
+.editable-input .ace-spinner {
+ margin-right: 8px;
+}
+.editable-input .ace-spinner .spinner-input {
+ width: 100%;
+}
+.editable-inline .editable-slider {
+ margin-top: 10px;
+ margin-right: 4px;
+}
+.editable-popup .editable-slider {
+ display: block;
+ margin-bottom: 16px;
+ margin-top: 4px;
+}
+.editable-slider input[type=text] {
+ display: none;
+}
+.editable-slider input[type=range] {
+ outline: none !important;
+}
+.editable-input .ace-file-input {
+ display: block;
+}
+.editable-image .ace-file-multiple .ace-file-container.selected {
+ border-color: transparent;
+}
+.editable-image + .editable-buttons,
+.editable-wysiwyg + .editable-buttons {
+ display: block;
+ text-align: center;
+ margin-top: 8px;
+}
+.editable-wysiwyg {
+ width: 95%;
+}
+.editable-wysiwyg .wysiwyg-editor {
+ height: auto;
+ overflow-y: hidden;
+}
+.editableform .input-append.dropdown-menu {
+ display: none;
+}
+.editableform .open .input-append.dropdown-menu {
+ display: block;
+}
+.editable-container .editableform {
+ margin-bottom: 10px;
+}
+.editable-inline .editableform {
+ margin-bottom: 0;
+}
+.editableform .control-group {
+ display: block;
+}
+.editableform-loading {
+ background: none;
+}
+.editableform-loading .ace-icon,
+.editableform-loading .progress {
+ position: relative;
+ top: 35%;
+}
+.input-group.date .input-group-addon {
+ cursor: pointer;
+}
+.datepicker td,
+.daterangepicker td,
+.datepicker th,
+.daterangepicker th {
+ border-radius: 0 !important;
+ font-size: 13px;
+}
+.datepicker td.active,
+.daterangepicker td.active,
+.datepicker td.active:hover,
+.daterangepicker td.active:hover {
+ background: #2283c5 !important;
+}
+.datepicker td.active.disabled,
+.daterangepicker td.active.disabled,
+.datepicker td.active.disabled:hover,
+.daterangepicker td.active.disabled:hover {
+ background: #8b9aa3 !important;
+}
+.datepicker td,
+.datepicker th {
+ min-width: 32px;
+}
+.datepicker-dropdown.datepicker-orient-bottom:after,
+.datepicker-dropdown.datepicker-orient-bottom:before {
+ top: auto;
+}
+.daterangepicker .calendar-date {
+ border-radius: 0;
+}
+.datepicker-months .month,
+.datepicker-years .year {
+ border-radius: 0 !important;
+}
+.datepicker-months .month.active,
+.datepicker-years .year.active,
+.datepicker-months .month.active:hover,
+.datepicker-years .year.active:hover,
+.datepicker-months .month.active:focus,
+.datepicker-years .year.active:focus,
+.datepicker-months .month.active:active,
+.datepicker-years .year.active:active {
+ background-image: none !important;
+ background-color: #2283c5 !important;
+}
+.bootstrap-timepicker-widget table td input {
+ width: 32px;
+}
+.well .datepicker table tr td.day:hover {
+ background-color: #7d8893;
+ color: #FFF;
+}
+.bootstrap-timepicker-widget table td a:hover {
+ border-radius: 0;
+}
+.daterangepicker.opensleft:before,
+.daterangepicker.opensright:before {
+ -moz-border-bottom-colors: rgba(0, 0, 0, 0.2);
+}
+.daterangepicker.opensleft:after,
+.daterangepicker.opensright:after {
+ -moz-border-bottom-colors: #fff;
+}
+.datepicker-dropdown:before {
+ -moz-border-bottom-colors: rgba(0, 0, 0, 0.2);
+}
+.datepicker-dropdown:after {
+ -moz-border-bottom-colors: #fff;
+}
+.datepicker-dropdown.datepicker-orient-bottom:before {
+ -moz-border-top-colors: #999;
+}
+.datepicker-dropdown.datepicker-orient-bottom:after {
+ -moz-border-top-colors: #FFF;
+}
+.bootstrap-timepicker-widget.dropdown-menu:before {
+ -moz-border-bottom-colors: rgba(0, 0, 0, 0.2);
+}
+.bootstrap-timepicker-widget.dropdown-menu:after {
+ -moz-border-bottom-colors: #FFF;
+}
+.bootstrap-timepicker-widget.timepicker-orient-bottom:before {
+ -moz-border-top-colors: #999;
+}
+.bootstrap-timepicker-widget.timepicker-orient-bottom:after {
+ -moz-border-top-colors: #FFF;
+}
+.bootstrap-datetimepicker-widget [class=btn] {
+ border-width: 0 !important;
+ background-color: transparent !important;
+ color: #7399b8 !important;
+ text-shadow: none !important;
+}
+.bootstrap-datetimepicker-widget [class=btn]:hover {
+ color: #1B6AAA !important;
+}
+.bootstrap-datetimepicker-widget .btn.btn-primary {
+ border-width: 3px !important;
+}
+.bootstrap-datetimepicker-widget .picker-switch {
+ margin-bottom: 2px;
+}
+.bootstrap-datetimepicker-widget .picker-switch .btn {
+ width: 90% !important;
+ background-color: #EEE !important;
+ color: #478fca !important;
+ font-size: 16px;
+}
+.bootstrap-datetimepicker-widget .picker-switch .btn:hover {
+ background-color: #e3edf5 !important;
+}
+.bootstrap-datetimepicker-widget td span {
+ border-radius: 0;
+}
+.bootstrap-datetimepicker-widget .timepicker-hour,
+.bootstrap-datetimepicker-widget .timepicker-minute,
+.bootstrap-datetimepicker-widget .timepicker-second {
+ color: #555 !important;
+}
+.ui-slider {
+ background-color: #D5D5D5;
+}
+.ui-slider-horizontal {
+ height: 9px;
+}
+.ui-slider-vertical {
+ width: 9px;
+}
+.ui-slider .ui-slider-handle {
+ border-radius: 0;
+ width: 1.45em;
+ height: 1.45em;
+ background-color: #F8F8F8;
+ border: 1px solid;
+}
+.ui-slider .ui-slider-handle:before,
+.ui-slider .ui-slider-handle:after {
+ display: block;
+ content: "";
+ position: absolute;
+ top: 4px;
+ left: 5px;
+ width: 4px;
+ height: 8px;
+ border: 1px solid;
+ border-width: 0 1px;
+ border-color: inherit;
+}
+.ui-slider .ui-slider-handle:after {
+ left: 8px;
+ border-width: 0 1px 0 0;
+}
+.ui-slider .ui-slider-handle:hover {
+ background-color: #FFF;
+}
+.ui-slider .ui-slider-handle:hover,
+.ui-slider .ui-slider-handle:focus,
+.ui-slider .ui-slider-handle:active {
+ outline: none;
+ -webkit-box-shadow: 1px 1px 1px 0px rgba(0,0,0,.3);
+ box-shadow: 1px 1px 1px 0px rgba(0,0,0,.3);
+}
+.ui-slider-horizontal .ui-slider-handle {
+ margin-left: -0.725em;
+ top: -0.4em;
+}
+.ui-slider-vertical .ui-slider-handle {
+ left: -0.35em;
+ margin-bottom: -0.65em;
+}
+.ui-slider-small.ui-slider-horizontal {
+ height: 5px;
+}
+.ui-slider-small.ui-slider-vertical {
+ width: 5px;
+}
+.ui-slider-small .ui-slider-handle {
+ border-radius: 100%;
+ width: 17px;
+ height: 17px;
+ margin-bottom: -0.45em;
+ left: -0.35em;
+}
+.ui-slider-small .ui-slider-handle:before,
+.ui-slider-small .ui-slider-handle:after {
+ height: 7px;
+ left: 5px;
+ width: 3px;
+}
+.ui-slider-small .ui-slider-handle:after {
+ left: 7px;
+}
+.ui-slider-simple .ui-slider-handle:after,
+.ui-slider-simple .ui-slider-handle:before {
+ display: none;
+}
+/* colors */
+.ui-slider-range {
+ background-color: #4aa4ce;
+}
+.ui-slider-handle {
+ outline: none !important;
+ border-color: #4aa4ce !important;
+}
+.ui-state-disabled.ui-slider {
+ background-color: #E5E5E5;
+}
+.ui-state-disabled .ui-slider-range {
+ background-color: #8daebe;
+}
+.ui-state-disabled .ui-slider-handle {
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+ border-color: #8daebe !important;
+}
+.ui-slider-green .ui-slider-range {
+ background-color: #8bbc67;
+}
+.ui-slider-green .ui-slider-handle {
+ border-color: #8bbc67 !important;
+}
+.ui-slider-green.ui-state-disabled .ui-slider-range {
+ background-color: #aab0a6;
+}
+.ui-slider-green.ui-state-disabled .ui-slider-handle {
+ border-color: #aab0a6 !important;
+}
+.ui-slider-red .ui-slider-range {
+ background-color: #d36e6e;
+}
+.ui-slider-red .ui-slider-handle {
+ border-color: #d36e6e !important;
+}
+.ui-slider-red.ui-state-disabled .ui-slider-range {
+ background-color: #c8acac;
+}
+.ui-slider-red.ui-state-disabled .ui-slider-handle {
+ border-color: #c8acac !important;
+}
+.ui-slider-purple .ui-slider-range {
+ background-color: #ac68ba;
+}
+.ui-slider-purple .ui-slider-handle {
+ border-color: #ac68ba !important;
+}
+.ui-slider-purple.ui-state-disabled .ui-slider-range {
+ background-color: #ada7ae;
+}
+.ui-slider-purple.ui-state-disabled .ui-slider-handle {
+ border-color: #ada7ae !important;
+}
+.ui-slider-orange .ui-slider-range {
+ background-color: #efad62;
+}
+.ui-slider-orange .ui-slider-handle {
+ border-color: #efad62 !important;
+}
+.ui-slider-orange.ui-state-disabled .ui-slider-range {
+ background-color: #e0c4a4;
+}
+.ui-slider-orange.ui-state-disabled .ui-slider-handle {
+ border-color: #e0c4a4 !important;
+}
+.ui-slider-dark .ui-slider-range {
+ background-color: #606060;
+}
+.ui-slider-dark .ui-slider-handle {
+ border-color: #606060 !important;
+}
+.ui-slider-dark.ui-state-disabled .ui-slider-range {
+ background-color: #7a7a7a;
+}
+.ui-slider-dark.ui-state-disabled .ui-slider-handle {
+ border-color: #7a7a7a !important;
+}
+.ui-slider-pink .ui-slider-range {
+ background-color: #d6487e;
+}
+.ui-slider-pink .ui-slider-handle {
+ border-color: #d6487e !important;
+}
+.ui-slider-pink.ui-state-disabled .ui-slider-range {
+ background-color: #c38ea2;
+}
+.ui-slider-pink.ui-state-disabled .ui-slider-handle {
+ border-color: #c38ea2 !important;
+}
+.ui-datepicker {
+ background-color: #FFF;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+.ui-datepicker .ui-datepicker-prev,
+.ui-datepicker .ui-datepicker-next {
+ height: 26px;
+ min-width: 32px;
+ max-width: 32px;
+ text-align: center;
+ cursor: pointer;
+ color: transparent;
+ line-height: 26px;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+.ui-datepicker .ui-datepicker-prev .ui-icon,
+.ui-datepicker .ui-datepicker-next .ui-icon {
+ color: transparent;
+ visibility: hidden;
+}
+.ui-datepicker .ui-datepicker-prev:hover,
+.ui-datepicker .ui-datepicker-next:hover {
+ background-color: #EEE;
+ text-decoration: none;
+}
+.ui-datepicker .ui-datepicker-prev:before,
+.ui-datepicker .ui-datepicker-next:before {
+ display: inline;
+ font-family: FontAwesome;
+ font-size: 14px;
+ content: "\f060";
+ color: #393939;
+}
+.ui-datepicker .ui-datepicker-prev-hover,
+.ui-datepicker .ui-datepicker-next-hover {
+ top: 2px;
+}
+.ui-datepicker .ui-datepicker-next:before {
+ content: "\f061";
+}
+.ui-datepicker .ui-datepicker-prev-hover {
+ left: 2px;
+}
+.ui-datepicker .ui-datepicker-next-hover {
+ right: 2px;
+}
+.ui-datepicker td {
+ padding: 0;
+}
+.ui-datepicker td > a,
+.ui-datepicker td > span {
+ display: inline-block;
+ height: 22px;
+ min-width: 24px;
+ max-width: 24px;
+ text-align: center;
+ color: #393939;
+ font-size: 13px;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+.ui-datepicker td > a:hover {
+ background-color: #EEE;
+}
+.ui-datepicker td > a.ui-state-highlight {
+ background-color: #D5E5EF;
+}
+.ui-datepicker td > a.ui-state-active {
+ background-color: #2283c5;
+ color: #FFF;
+}
+.ui-datepicker td > a.ui-priority-secondary {
+ color: #888;
+}
+.ui-datepicker td > span {
+ color: #999;
+}
+.ui-datepicker td .ui-datepicker-title select {
+ height: 24px;
+ line-height: 24px;
+ padding: 2px 3px;
+}
+.ui-datepicker td .ui-datepicker-buttonpane {
+ background-color: #DDD;
+ height: 1px;
+}
+/* dialog */
+.ui-widget-overlay {
+ background: rgba(0, 0, 0, 0.25);
+ opacity: 1 !important;
+ filter: alpha(opacity=100) !important;
+ z-index: 1039 !important;
+}
+.ui-dialog,
+.ui-jqdialog {
+ z-index: 1040 !important;
+ background-color: #FFF;
+ padding: 0;
+ border: 1px solid #DDD;
+ -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+.ui-dialog .ui-dialog-titlebar,
+.ui-jqdialog .ui-dialog-titlebar,
+.ui-dialog .ui-jqdialog-titlebar,
+.ui-jqdialog .ui-jqdialog-titlebar {
+ background-color: #F1F1F1;
+ font-size: 16px;
+ color: #669fc7;
+ padding: 0;
+}
+.ui-dialog .ui-dialog-title,
+.ui-jqdialog .ui-dialog-title,
+.ui-dialog .ui-jqdialog-title,
+.ui-jqdialog .ui-jqdialog-title {
+ float: none !important;
+ width: auto;
+}
+.ui-dialog .widget-header,
+.ui-jqdialog .widget-header {
+ margin: 0;
+ border-width: 0 0 1px 0;
+}
+.ui-dialog .ui-dialog-buttonpane,
+.ui-jqdialog .ui-dialog-buttonpane,
+.ui-dialog .ui-jqdialog-buttonpane,
+.ui-jqdialog .ui-jqdialog-buttonpane {
+ background-color: #eff3f8;
+ border-top: 1px solid #e4e9ee;
+}
+.ui-dialog .ui-dialog-buttonpane button,
+.ui-jqdialog .ui-dialog-buttonpane button,
+.ui-dialog .ui-jqdialog-buttonpane button,
+.ui-jqdialog .ui-jqdialog-buttonpane button {
+ font-size: 14px;
+}
+.ui-dialog .ui-dialog-titlebar-close,
+.ui-jqdialog .ui-dialog-titlebar-close,
+.ui-dialog .ui-jqdialog-titlebar-close,
+.ui-jqdialog .ui-jqdialog-titlebar-close {
+ border: none;
+ background: transparent;
+ opacity: 0.4;
+ color: #d15b47;
+ padding: 0;
+ top: 50%;
+ right: 8px !important;
+ text-align: center;
+}
+.ui-dialog .ui-dialog-titlebar-close:before,
+.ui-jqdialog .ui-dialog-titlebar-close:before,
+.ui-dialog .ui-jqdialog-titlebar-close:before,
+.ui-jqdialog .ui-jqdialog-titlebar-close:before {
+ content: "\f00d";
+ display: inline;
+ font-family: FontAwesome;
+ font-size: 16px;
+}
+.ui-dialog .ui-dialog-titlebar-close:hover,
+.ui-jqdialog .ui-dialog-titlebar-close:hover,
+.ui-dialog .ui-jqdialog-titlebar-close:hover,
+.ui-jqdialog .ui-jqdialog-titlebar-close:hover {
+ opacity: 1;
+ text-decoration: none;
+ padding: 0;
+}
+.ui-dialog .ui-dialog-titlebar-close .ui-button-text,
+.ui-jqdialog .ui-dialog-titlebar-close .ui-button-text,
+.ui-dialog .ui-jqdialog-titlebar-close .ui-button-text,
+.ui-jqdialog .ui-jqdialog-titlebar-close .ui-button-text {
+ text-indent: 0;
+ visibility: hidden;
+}
+.ui-dialog .widget-header .ui-dialog-titlebar-close,
+.ui-jqdialog .widget-header .ui-dialog-titlebar-close,
+.ui-dialog .widget-header .ui-jqdialog-titlebar-close,
+.ui-jqdialog .widget-header .ui-jqdialog-titlebar-close {
+ right: 10px !important;
+}
+/* accordion */
+.ui-accordion .ui-accordion-header {
+ color: #478fca;
+ font-weight: normal;
+ background-color: #F9F9F9;
+ border: 1px solid #cdd8e3;
+ padding: 8px 8px 9px 24px;
+}
+.ui-accordion .ui-accordion-header:hover {
+ color: #6ea6cc;
+ background-color: #f1f8fd;
+}
+.ui-accordion .ui-accordion-header.ui-state-active {
+ color: #4c8fbd;
+ background-color: #eef4f9;
+ position: relative;
+ font-weight: bold;
+}
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon {
+ text-indent: 0;
+ margin-top: 0;
+ position: absolute;
+ left: 10px;
+ top: 7px;
+}
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon:before {
+ display: inline;
+ font-family: FontAwesome;
+ font-size: 15px;
+ content: "\f0da";
+}
+.ui-accordion .ui-accordion-header.ui-state-active .ui-accordion-header-icon:before {
+ content: "\f0d7";
+ font-weight: normal;
+}
+.ui-accordion .ui-accordion-content {
+ border: 1px solid #cdd8e3;
+ border-top-width: 0;
+ padding: 11px 16px;
+}
+/* tabs */
+.ui-tabs .ui-tabs-nav {
+ padding: 0;
+ border-bottom: 1px solid #C5D0DC;
+}
+.ui-tabs .ui-tabs-nav li.ui-state-default > a {
+ background-color: #F9F9F9;
+ border: 1px solid #C5D0DC;
+ border-bottom-width: 0;
+ color: #999;
+ line-height: 16px;
+ margin-right: -1px;
+ z-index: 11;
+ padding: 8px 12px;
+ position: relative;
+ top: 2px;
+}
+.ui-tabs .ui-tabs-nav li > a:focus {
+ outline: none;
+}
+.ui-tabs .ui-tabs-nav li.ui-tabs-active > a {
+ background-color: #FFF;
+ border: 1px solid;
+ border-color: #4C8FBD #C5D0DC transparent;
+ border-top-width: 2px;
+ -webkit-box-shadow: 0 -2px 3px 0 rgba(0, 0, 0, 0.15);
+ box-shadow: 0 -2px 3px 0 rgba(0, 0, 0, 0.15);
+ color: #576373;
+ position: relative;
+ top: 1px;
+}
+.ui-tabs .ui-tabs-panel {
+ border: 1px solid #C5D0DC;
+ border-top-width: 0;
+ margin: 0;
+ left: auto;
+ right: auto;
+ top: auto;
+ bottom: auto;
+}
+/* menu */
+.ui-menu {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ width: 150px;
+ -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ background-color: #FFF;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ padding: 3px;
+}
+.ui-menu .ui-state-focus,
+.ui-menu .ui-state-active {
+ margin: auto;
+}
+.ui-menu .ui-menu-item {
+ padding: 5px 10px 6px;
+ color: #444;
+ cursor: pointer;
+ display: block;
+ -webkit-box-sizing: inherit;
+ -moz-box-sizing: inherit;
+ box-sizing: inherit;
+}
+.ui-menu .ui-menu-item .ui-menu-icon {
+ float: right;
+ position: relative;
+ left: auto;
+ right: 4px;
+ bottom: auto;
+ text-indent: 0;
+}
+.ui-menu .ui-menu-item .ui-menu-icon:before {
+ content: "\f105";
+ font-family: FontAwesome;
+ font-size: 14px;
+ display: inline;
+}
+.ui-menu .ui-menu-item:hover,
+.ui-menu .ui-state-focus,
+.ui-menu .ui-state-active,
+.ui-menu .ui-menu-item:hover > .ui-menu-icon,
+.ui-menu .ui-state-focus > .ui-menu-icon,
+.ui-menu .ui-state-active > .ui-menu-icon {
+ text-decoration: none;
+ background-color: #4f99c6;
+ color: #FFF;
+ margin: auto;
+ font-weight: normal;
+}
+.ui-menu .ui-menu-item:hover .ui-menu-icon,
+.ui-menu .ui-state-focus .ui-menu-icon,
+.ui-menu .ui-state-active .ui-menu-icon,
+.ui-menu .ui-menu-item:hover > .ui-menu-icon .ui-menu-icon,
+.ui-menu .ui-state-focus > .ui-menu-icon .ui-menu-icon,
+.ui-menu .ui-state-active > .ui-menu-icon .ui-menu-icon {
+ color: #FFF;
+}
+.ui-menu .ui-state-disabled,
+.ui-menu .ui-state-disabled .ui-menu-icon {
+ color: #999;
+ cursor: default;
+}
+.ui-menu .ui-state-disabled:hover,
+.ui-menu .ui-state-disabled.ui-state-focus,
+.ui-menu .ui-state-disabled.ui-state-active,
+.ui-menu .ui-state-disabled:hover .ui-menu-icon,
+.ui-menu .ui-state-disabled.ui-state-focus .ui-menu-icon,
+.ui-menu .ui-state-disabled.ui-state-active .ui-menu-icon {
+ background-color: #FFF;
+ color: #999;
+}
+/* auto complete */
+.ui-autocomplete {
+ background-color: #FFF;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+.ui-autocomplete-category {
+ padding: 6px;
+ position: relative;
+ background-color: #eef4f9;
+ color: #478fca;
+ font-weight: bolder;
+ border: 1px solid #DAE6ED;
+ border-width: 1px 0;
+}
+.ui-spinner-button {
+ border-width: 0 !important;
+ font-size: 10px;
+ height: 16px;
+ line-height: 16px;
+ width: 18px;
+ color: #FFFFFF !important;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25) !important;
+ display: inline-block;
+ position: absolute;
+ text-align: center;
+ padding: 0;
+}
+.ui-spinner-button > .ace-icon {
+ width: 18px;
+ display: inline-block;
+}
+.ui-spinner-up {
+ top: 0;
+ right: 5px;
+}
+.ui-spinner-down {
+ bottom: 3px;
+ right: 5px;
+}
+.ui-spinner-input {
+ margin-top: 0;
+ padding: 5px;
+ max-width: 100px;
+ font-size: 14px;
+}
+.ui-tooltip {
+ background-color: #444;
+ color: #FFF;
+}
+.ui-progressbar {
+ background-color: #f5f5f5;
+ height: 22px;
+}
+.ui-progressbar .ui-progressbar-value {
+ margin: 0;
+}
+.ui-progressbar .ui-progressbar-value[class="progress-bar"] {
+ background-color: #2a91d8;
+}
+.ui-selectmenu-button {
+ border: 1px solid #aaa;
+}
+.ui-selectmenu-button[aria-expanded=true] {
+ border-color: #4492C9;
+}
+.ui-selectmenu-button span.ui-icon {
+ text-indent: 0;
+ margin-top: -10px;
+}
+.ui-selectmenu-button .ui-icon:before {
+ content: "\f0d7";
+ display: inline-block;
+ color: #888;
+ font-family: FontAwesome;
+ font-size: 14px;
+}
+.ui-jqgrid .ui-jqgrid-view,
+.ui-jqgrid .ui-paging-info,
+.ui-jqgrid .ui-pg-table,
+.ui-jqgrid .ui-pg-selbox {
+ font-size: 13px;
+}
+.ui-jqgrid .ui-jqgrid-title {
+ float: left;
+ margin: 8px;
+}
+.ui-jqgrid .ui-jqgrid-title-rtl {
+ float: right;
+ margin: 8px;
+}
+.ui-jqgrid-view > .ui-jqgrid-titlebar {
+ height: 40px;
+ line-height: 24px;
+ color: #FFF;
+ background: #307ecc;
+ padding: 0;
+ font-size: 15px;
+}
+.ui-jqgrid tr.jqgrow.ui-row-rtl td:last-child {
+ border-right: none;
+ border-left: 1px solid #E1E1E1;
+}
+.ui-jqgrid .ui-jqgrid-hdiv {
+ background-color: #eff3f8;
+ border: 1px solid #D3D3D3;
+ border-width: 1px 0 0 1px;
+ line-height: 15px;
+ font-weight: bold;
+ color: #777;
+ text-shadow: none;
+}
+.ui-jqgrid .ui-jqgrid-htable thead {
+ background-color: #eff3f8;
+}
+.ui-jqgrid .ui-jqgrid-htable th span.ui-jqgrid-resize {
+ height: 45px !important;
+}
+.ui-jqgrid .ui-jqgrid-htable th div {
+ padding-top: 12px;
+ padding-bottom: 12px;
+}
+.ui-jqgrid-hdiv .ui-jqgrid-htable {
+ border-top: none;
+}
+.ui-jqgrid-hdiv .ui-jqgrid-htable {
+ border-top: 1px solid #E1E1E1;
+}
+.ui-jqgrid-titlebar {
+ position: relative;
+ top: 1px;
+ z-index: 1;
+}
+.ui-jqgrid tr.jqgrow,
+.ui-jqgrid tr.ui-row-ltr,
+.ui-jqgrid tr.ui-row-rtl {
+ border: none;
+}
+.ui-jqgrid tr.ui-row-ltr td,
+.ui-jqgrid tr.ui-row-rtl td {
+ border-bottom: 1px solid #E1E1E1;
+ padding: 6px 4px;
+ border-color: #E1E1E1;
+}
+.ui-jqgrid tr.ui-state-highlight.ui-row-ltr td {
+ border-right-color: #C7D3A9;
+}
+.ui-jqgrid tr.ui-state-highlight.ui-row-rtl td {
+ border-left-color: #C7D3A9;
+}
+.ui-jqgrid-btable .ui-widget-content.ui-priority-secondary {
+ background-image: none;
+ background-color: #F9F9F9;
+ opacity: 1;
+}
+.ui-jqgrid-btable .ui-widget-content.ui-state-hover {
+ background-image: none;
+ background-color: #EFF4F7;
+ opacity: 1;
+}
+.ui-jqgrid-btable .ui-widget-content.ui-state-highlight {
+ background-color: #E4EFC9;
+}
+.ui-jqgrid .ui-jqgrid-pager {
+ line-height: 15px;
+ height: 55px;
+ padding-top: 3px !important;
+ padding-bottom: 5px !important;
+ background-color: #eff3f8 !important;
+ border-bottom: 1px solid #E1E1E1 !important;
+ border-top: 1px solid #E1E1E1 !important;
+}
+.ui-jqgrid .ui-pg-input {
+ font-size: inherit;
+ width: 24px;
+ height: 20px;
+ line-height: 16px;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ text-align: center;
+ padding-top: 1px;
+ padding-bottom: 1px;
+}
+.ui-jqgrid .ui-pg-selbox {
+ display: block;
+ height: 24px;
+ width: 60px;
+ margin: 0;
+ padding: 1px;
+ line-height: normal;
+}
+.ui-jqgrid .ui-jqgrid-htable th div {
+ overflow: visible;
+}
+.ui-jqgrid .ui-pager-control {
+ height: 50px;
+ position: relative;
+ padding-left: 9px;
+ padding-right: 9px;
+}
+.ui-jqgrid .ui-jqgrid-toppager {
+ height: auto !important;
+ background-color: #eff3f8;
+ border-bottom: 1px solid #E1E1E1 !important;
+}
+.ui-jqgrid .jqgrow .editable {
+ max-width: 90%;
+ max-width: calc(92%) !important;
+}
+.ui-pg-table .navtable .ui-corner-all {
+ border-radius: 0;
+}
+.ui-jqgrid .ui-pg-button:hover {
+ padding: 1px;
+}
+.ui-jqgrid .ui-pg-button .ui-separator {
+ margin-left: 4px;
+ margin-right: 4px;
+ border-color: #C9D4DB;
+}
+.ui-jqgrid .ui-jqgrid-btable {
+ border-left: 1px solid #E1E1E1;
+}
+.ui-jqgrid .ui-jqgrid-bdiv {
+ border-top: 1px solid #E1E1E1;
+}
+.ui-jqgrid .loading {
+ position: absolute;
+ top: 45%;
+ left: 45%;
+ width: auto;
+ height: auto;
+ z-index: 101;
+ padding: 6px;
+ margin: 5px;
+ text-align: center;
+ font-weight: bold;
+ font-size: 12px;
+ background-color: #FFF;
+ border: 2px solid #8EB8D1;
+ color: #E2B018;
+}
+.ui-jqgrid .ui-search-toolbar {
+ border-top: 1px solid #E1E1E1;
+}
+.ui-jqgrid .ui-jqgrid-labels {
+ border-bottom: none;
+ background: #F2F2F2;
+ background-image: -webkit-linear-gradient(top, #f8f8f8 0%, #ececec 100%);
+ background-image: -o-linear-gradient(top, #f8f8f8 0%, #ececec 100%);
+ background-image: linear-gradient(to bottom, #f8f8f8 0%, #ececec 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff8f8f8', endColorstr='#ffececec', GradientType=0);
+ padding: 0 !important;
+ border-left: 1px solid #E1E1E1 !important;
+}
+.ui-jqgrid .ui-jqgrid-labels th {
+ border-right: 1px solid #E1E1E1 !important;
+ text-align: left !important;
+}
+/* checkbox container */
+.ui-jqgrid-labels th[id*="_cb"]:first-child > div {
+ padding-top: 0;
+ text-align: center !important;
+}
+.ui-jqgrid-sortable {
+ padding-left: 4px;
+ font-size: 13px;
+ color: #777;
+ font-weight: bold;
+}
+.ui-jqgrid-sortable:hover {
+ color: #547ea8;
+}
+th[aria-selected=true] {
+ background-image: -webkit-linear-gradient(top, #eff3f8 0%, #e3e7ed 100%);
+ background-image: -o-linear-gradient(top, #eff3f8 0%, #e3e7ed 100%);
+ background-image: linear-gradient(to bottom, #eff3f8 0%, #e3e7ed 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffeff3f8', endColorstr='#ffe3e7ed', GradientType=0);
+}
+th[aria-selected=true] .ui-jqgrid-sortable {
+ color: #307ecc;
+}
+.ui-jqgrid .ui-icon {
+ text-indent: 0;
+ color: #307ecc;
+ float: none;
+ right: 2px;
+}
+.rtl .ui-jqgrid .ui-icon {
+ right: auto;
+ left: 2px;
+}
+.ui-jqgrid .ui-icon.ui-state-disabled {
+ color: #BBB;
+}
+.ui-jqgrid .ui-icon.ui-state-disabled:hover {
+ padding: 0;
+}
+.ui-grid-ico-sort:before {
+ display: inline;
+ content: "\f0d7";
+ font-family: FontAwesome;
+ font-size: 12px;
+}
+.ui-icon-asc:before {
+ content: "\f0d8";
+}
+.ui-pg-table > tbody > tr > .ui-pg-button > .ui-icon {
+ display: inline-block;
+ padding: 0;
+ width: 24px;
+ height: 24px;
+ line-height: 22px;
+ text-align: center;
+ position: static;
+ float: none;
+ margin: 0 2px !important;
+ color: #808080;
+ border: 1px solid #CCC;
+ background-color: #FFF;
+ border-radius: 100%;
+}
+.ui-pg-table > tbody > tr > .ui-pg-button > .ui-icon:hover {
+ color: #699AB5;
+ border-color: #699AB5;
+}
+.ui-pg-table > tbody > tr > .ui-pg-button > .ui-icon:before {
+ width: 20px;
+ text-align: center;
+ display: inline-block;
+}
+.ui-pg-table > tbody > tr > .ui-pg-button.ui-state-disabled .ui-icon {
+ color: #B0B0B0;
+ background-color: #F7F7F7;
+ border-color: #DDD;
+ -moz-transform: scale(0.9);
+ -webkit-transform: scale(0.9);
+ -o-transform: scale(0.9);
+ -ms-transform: scale(0.9);
+ transform: scale(0.9);
+}
+.ui-jqgrid-btable input,
+.ui-jqgrid-btable textarea,
+.ui-jqgrid-btable select {
+ padding: 2px;
+ width: auto;
+ max-width: 100%;
+ margin-bottom: 0;
+}
+.ui-jqgrid-btable select {
+ padding: 1px;
+ height: 25px;
+ line-height: 25px;
+}
+.ui-pg-div .ui-icon {
+ display: inline-block;
+ width: 18px;
+ float: none;
+ position: static;
+ text-align: center;
+ opacity: 0.85;
+ -webkit-transition: all 0.12s;
+ -o-transition: all 0.12s;
+ transition: all 0.12s;
+ margin: 0 1px;
+ vertical-align: middle;
+ cursor: pointer;
+ font-size: 17px;
+}
+.ui-pg-div .ui-icon:hover {
+ -moz-transform: scale(1.2);
+ -webkit-transform: scale(1.2);
+ -o-transform: scale(1.2);
+ -ms-transform: scale(1.2);
+ transform: scale(1.2);
+ opacity: 1;
+ position: static;
+ margin: 0 1px;
+}
+.ui-pg-div .ui-icon:before {
+ font-family: FontAwesome;
+ display: inline;
+}
+.ui-jqgrid .ui-icon-pencil {
+ color: #478FCA;
+}
+.ui-jqgrid .ui-icon-pencil:before {
+ content: "\f040";
+}
+.ui-jqgrid .ui-icon-trash {
+ color: #DD5A43;
+}
+.ui-jqgrid .ui-icon-trash:before {
+ content: "\f014";
+}
+.ui-jqgrid .ui-icon-disk {
+ color: #69AA46;
+}
+.ui-jqgrid .ui-icon-disk:before {
+ content: "\f00c";
+}
+.ui-jqgrid .ui-icon-cancel {
+ color: #DD5A43;
+}
+.ui-jqgrid .ui-icon-cancel:before {
+ content: "\f00d";
+}
+.ui-jqdialog-content,
+.ui-jqdialog .ui-jqdialog-content {
+ font-size: 13px;
+ padding: 4px 0 0;
+}
+.ui-jqdialog-content .formdata,
+.ui-jqdialog .ui-jqdialog-content .formdata {
+ font-size: 13px;
+ padding: 6px 12px;
+}
+.ui-jqdialog-content .form-view-data,
+.ui-jqdialog .ui-jqdialog-content .form-view-data {
+ vertical-align: middle;
+ font-size: 13px;
+}
+.ui-jqdialog-content[id*="alertcnt_"],
+.ui-jqdialog .ui-jqdialog-content[id*="alertcnt_"] {
+ padding: 8px 11px;
+}
+.ui-jqdialog-content .CaptionTD {
+ font-size: 12px;
+ text-align: right;
+ color: #666;
+}
+.ui-jqdialog-content .FormData {
+ border-bottom: 1px dotted #E8E8E8;
+}
+.ui-jqdialog-content .FormData:last-child {
+ border-bottom: none;
+}
+.ui-jqdialog-content .FormData > td {
+ padding-top: 6px;
+ padding-bottom: 6px;
+}
+.ui-jqdialog-content input.FormElement {
+ width: auto;
+}
+.ui-jqdialog-content select.FormElement {
+ padding: 1px;
+ height: 25px;
+ line-height: 25px;
+ width: auto;
+}
+.ui-jqdialog-content td.EditButton {
+ padding: 8px;
+}
+.EditTable {
+ background-color: #eff3f8;
+ border-top: 1px solid #D6E1EA !important;
+ padding: 8px;
+}
+.EditTable tr:first-child {
+ display: none;
+}
+.EditTable .navButton .fm-button {
+ float: none !important;
+ width: auto !important;
+ margin: 1px 1px 2px !important;
+ background-color: transparent;
+ border-radius: 100%;
+}
+.EditTable .navButton .fm-button:hover {
+ background-color: transparent;
+}
+.EditTable .navButton .fm-button:focus {
+ outline: none;
+}
+.EditTable .navButton .fm-button .ace-icon {
+ display: inline-block;
+ color: #999;
+ border: 1px solid #AAA;
+ width: 26px;
+ height: 26px;
+ line-height: 26px;
+ text-align: center;
+ border-radius: 100%;
+ background-color: #FFF;
+}
+.EditTable .navButton .fm-button:hover .ace-icon {
+ color: #699AB5;
+ border-color: #699AB5;
+}
+.EditTable .navButton .fm-button.ui-state-disabled .ace-icon,
+.EditTable .navButton .fm-button.ui-state-disabled:hover .ace-icon {
+ color: #BBB;
+ border-color: #CCC;
+ -moz-transform: scale(0.88);
+ -webkit-transform: scale(0.88);
+ -o-transform: scale(0.88);
+ -ms-transform: scale(0.88);
+ transform: scale(0.88);
+}
+.FormGrid .EditTable {
+ background-color: #FFF;
+ border-top: none !important;
+ padding: 0;
+}
+.FormGrid .EditTable tr:first-child {
+ display: none;
+}
+.ui-jqgrid .ui-jqgrid-view input,
+.ui-jqgrid .ui-jqgrid-view select,
+.ui-jqgrid .ui-jqgrid-view textarea,
+.ui-jqgrid .ui-jqgrid-view button {
+ font-size: 13px;
+}
+.ui-jqdialog-content .searchFilter select {
+ padding: 1px;
+ height: 26px;
+ line-height: 26px;
+ width: auto;
+ max-width: 95%;
+ margin-bottom: 0;
+}
+.ui-jqdialog-content .searchFilter .input-elm {
+ margin-bottom: 0;
+ height: 18px;
+ line-height: 18px;
+ width: 95% !important;
+ padding-left: 1px;
+ padding-right: 1px;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+.ui-jqdialog-content .searchFilter table {
+ margin-left: 4px;
+}
+.ui-jqdialog-content .searchFilter tr td {
+ padding: 5px 0;
+}
+.ui-jqdialog-content .searchFilter .add-group,
+.ui-jqdialog-content .searchFilter .add-rule,
+.ui-jqdialog-content .searchFilter .delete-group {
+ margin-left: 4px !important;
+ font-size: 15px !important;
+}
+.ui-jqdialog-content .searchFilter .delete-rule {
+ border: none;
+ background-color: #FFF;
+ color: #D15B47;
+ font-size: 20px;
+ width: 22px;
+ line-height: 10px;
+ padding: 0;
+ text-shadow: none !important;
+ display: inline-block;
+ -webkit-transition: all 0.1s;
+ -o-transition: all 0.1s;
+ transition: all 0.1s;
+ opacity: 0.85;
+}
+.ui-jqdialog-content .searchFilter .delete-rule:hover {
+ -moz-transform: scale(1.1);
+ -webkit-transform: scale(1.1);
+ -o-transform: scale(1.1);
+ -ms-transform: scale(1.1);
+ transform: scale(1.1);
+ color: #B74635;
+ opacity: 1;
+}
+.ui-jqdialog-content .searchFilter .queryresult {
+ margin-bottom: 11px;
+}
+.ui-jqdialog-content .searchFilter .queryresult td.query {
+ padding: 6px 11px;
+ border: 1px solid #E1E1E1;
+ background-color: #EEEEEE;
+}
+.ui-jqdialog-content .searchFilter .queryresult td.query:empty {
+ display: none;
+}
+.ui-state-error {
+ background-color: #f2dede;
+ border: 1px solid #ebccd1;
+ color: #a94442;
+ margin: 4px 4px 8px;
+ padding: 6px 10px;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+ font-size: 13px;
+}
+.ui-jqdialog .ui-widget-header {
+ background-image: -webkit-linear-gradient(top, #ffffff 0%, #eeeeee 100%);
+ background-image: -o-linear-gradient(top, #ffffff 0%, #eeeeee 100%);
+ background-image: linear-gradient(to bottom, #ffffff 0%, #eeeeee 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffeeeeee', GradientType=0);
+ border-image: none;
+ border-bottom: 1px solid solid;
+ color: #669FC7;
+ min-height: 38px;
+ position: relative;
+}
+.ui-jqdialog .ui-widget-header .ui-jqdialog-title {
+ line-height: 38px;
+ margin: 0;
+ padding: 0;
+ padding-left: 12px;
+ text-align: left;
+}
+.widget-header .ui-jqdialog-title {
+ padding-left: 0 !important;
+ padding-right: 0 !important;
+}
+.ui-jqdialog .ui-widget-header .widget-header {
+ border-bottom: none;
+}
+.ui-jqdialog .ui-jqdialog-titlebar {
+ border-bottom: 1px solid #DDD !important;
+}
+.fm-button {
+ margin: 0 4px;
+}
+.fm-button:not(.btn) {
+ background-color: #abbac3;
+ border-radius: 0 ;
+ box-shadow: none;
+ color: #FFFFFF ;
+ cursor: pointer;
+ display: inline-block;
+ font-size: 13px;
+ line-height: 28px;
+ padding: 0 12px 1px;
+ margin: 0 8px;
+ position: relative;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ -webkit-transition: all 0.15s;
+ -o-transition: all 0.15s;
+ transition: all 0.15s;
+ vertical-align: middle;
+}
+.fm-button.ui-state-default:hover {
+ background-color: #8b9aa3;
+}
+.ui-jqgrid .ui-jqgrid-htable .ui-search-toolbar th {
+ height: 30px;
+ padding-top: 2px;
+ white-space: normal;
+}
+.ui-jqgrid .ui-jqgrid-htable .ui-search-toolbar th div {
+ padding-top: 0;
+ padding-bottom: 0;
+ height: 30px;
+ line-height: 26px;
+}
+.ui-jqgrid .ui-jqgrid-titlebar-close {
+ top: 10%;
+ height: auto;
+ padding: 0;
+ margin: 2px 8px 0 0;
+ text-align: center;
+ border-radius: 4px;
+}
+.ui-jqgrid .ui-jqgrid-titlebar-close:hover {
+ background-color: rgba(255, 255, 255, 0.2);
+}
+.ui-jqgrid .ui-jqgrid-titlebar-close .ui-icon:before {
+ display: inline-block;
+ font-family: FontAwesome;
+ content: "\f077";
+ color: #FFF;
+}
+.ui-jqgrid .ui-jqgrid-titlebar-close .ui-icon-circle-triangle-s:before {
+ content: "\f078";
+}
+.ui-jqgrid .tree-wrap-ltr {
+ margin: 0 4px;
+ float: none;
+ display: inline;
+}
+.ui-jqgrid .tree-wrap-rtl {
+ margin: 2px 4px 0;
+}
+.ui-jqgrid .ui-subgrid {
+ border-bottom: 1px solid #E1E1E1;
+ background-color: #F6FAFF;
+}
+.ui-jqgrid .ui-subgrid .ui-jqgrid-btable {
+ background-color: #FFF;
+}
+.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv {
+ background-color: transparent;
+ margin-top: 4px;
+}
+.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable .ui-jqgrid-labels {
+ border-bottom: 1px solid #E1E1E1;
+ background: #F1F1F1;
+}
+.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable th[aria-selected="true"] {
+ background: #E5E9EF;
+}
+.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable th .ui-jqgrid-sortable {
+ font-size: 12px;
+}
+.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable th div {
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-hdiv .ui-jqgrid-htable th span.ui-jqgrid-resize {
+ height: 36px !important;
+}
+.ui-jqgrid .ui-subgrid .ui-jqgrid .ui-jqgrid-bdiv {
+ height: auto !important;
+ max-height: 150px;
+ margin-bottom: 4px;
+ border-top-width: 0;
+ border-bottom: 1px solid #E1E1E1;
+}
+.ui-jqgrid .ui-sgcollapsed > a:hover {
+ text-decoration: none;
+}
+@media only screen and (max-width: 767px) {
+ .ui-jqgrid .ui-jqgrid-pager {
+ height: 90px;
+ }
+ .ui-jqgrid .ui-jqgrid-pager > .ui-pager-control {
+ height: 85px;
+ padding-top: 9px;
+ }
+ .ui-jqgrid .ui-jqgrid-pager > .ui-pager-control > .ui-pg-table > tbody > tr > td {
+ vertical-align: top;
+ }
+ .ui-jqgrid .ui-jqgrid-pager > .ui-pager-control > .ui-pg-table > tbody > tr > td#grid-pager_center {
+ width: 0 !important;
+ position: static;
+ }
+ .ui-jqgrid .ui-jqgrid-pager > .ui-pager-control > .ui-pg-table > tbody > tr > td#grid-pager_center > .ui-pg-table {
+ margin: 36px auto 0;
+ position: absolute;
+ right: 0;
+ left: 0;
+ text-align: center;
+ }
+}
+@media only screen and (max-width: 767px) and (-webkit-min-device-pixel-ratio: 0) {
+ .ui-jqgrid .ui-jqgrid-pager > .ui-pager-control > .ui-pg-table > tbody > tr > td#grid-pager_center > .ui-pg-table {
+ width: 300px;
+ }
+}
+.dd {
+ position: relative;
+ display: block;
+ margin: 0;
+ padding: 0;
+ max-width: 600px;
+ list-style: none;
+ line-height: 20px;
+}
+.dd-list {
+ display: block;
+ position: relative;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+.dd-list .dd-list {
+ padding-left: 30px;
+}
+.dd-collapsed .dd-list {
+ display: none;
+}
+.dd-item,
+.dd-empty,
+.dd-placeholder {
+ display: block;
+ position: relative;
+ margin: 0;
+ padding: 0;
+ min-height: 20px;
+ line-height: 20px;
+}
+.dd-handle,
+.dd2-content {
+ display: block;
+ min-height: 38px;
+ margin: 5px 0;
+ padding: 8px 12px;
+ background: #F8FAFF;
+ border: 1px solid #DAE2EA;
+ color: #7C9EB2;
+ text-decoration: none;
+ font-weight: bold;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.dd-handle:hover,
+.dd2-content:hover {
+ color: #438EB9;
+ background: #F4F6F7;
+ border-color: #DCE2E8;
+}
+.dd-handle[class*="btn-"],
+.dd2-content[class*="btn-"] {
+ color: #FFF;
+ border: none;
+ padding: 9px 12px;
+}
+.dd-handle[class*="btn-"]:hover,
+.dd2-content[class*="btn-"]:hover {
+ opacity: 0.85;
+ color: #FFF;
+}
+.dd2-handle + .dd2-content,
+.dd2-handle + .dd2-content[class*="btn-"] {
+ padding-left: 44px;
+}
+.dd-handle[class*="btn-"]:hover,
+.dd2-content[class*="btn-"] .dd2-handle[class*="btn-"]:hover + .dd2-content[class*="btn-"] {
+ color: #FFF;
+}
+.dd-item > button:hover ~ .dd-handle,
+.dd-item > button:hover ~ .dd2-content {
+ color: #438EB9;
+ background: #F4F6F7;
+ border-color: #DCE2E8;
+}
+.dd-item > button:hover ~ .dd-handle[class*="btn-"],
+.dd-item > button:hover ~ .dd2-content[class*="btn-"] {
+ opacity: 0.85;
+ color: #FFF;
+}
+.dd2-handle:hover ~ .dd2-content {
+ color: #438EB9;
+ background: #F4F6F7;
+ border-color: #DCE2E8;
+}
+.dd2-handle:hover ~ .dd2-content[class*="btn-"] {
+ opacity: 0.85;
+ color: #FFF;
+}
+.dd2-item.dd-item > button {
+ margin-left: 34px;
+}
+.dd-item > button {
+ display: block;
+ position: relative;
+ z-index: 1;
+ cursor: pointer;
+ float: left;
+ width: 25px;
+ height: 20px;
+ margin: 5px 1px 5px 5px;
+ padding: 0;
+ text-indent: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ border: 0;
+ background: transparent;
+ font-size: 12px;
+ line-height: 1;
+ text-align: center;
+ font-weight: bold;
+ top: 4px;
+ left: 1px;
+ color: #707070;
+}
+.dd-item > button:before {
+ font-family: FontAwesome;
+ content: '\f067';
+ display: block;
+ position: absolute;
+ width: 100%;
+ text-align: center;
+ text-indent: 0;
+ font-weight: normal;
+ font-size: 14px;
+}
+.dd-item > button[data-action="collapse"]:before {
+ content: '\f068';
+}
+.dd-item > button:hover {
+ color: #707070;
+}
+.dd-item.dd-colored > button,
+.dd-item.dd-colored > button:hover {
+ color: #EEE;
+}
+.dd-placeholder,
+.dd-empty {
+ margin: 5px 0;
+ padding: 0;
+ min-height: 30px;
+ background: #F0F9FF;
+ border: 2px dashed #BED2DB;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.dd-empty {
+ border-color: #AAA;
+ border-style: solid;
+ background-color: #e5e5e5;
+}
+.dd-dragel {
+ position: absolute;
+ pointer-events: none;
+ z-index: 999;
+ opacity: 0.8;
+}
+.dd-dragel > li > .dd-handle {
+ color: #4B92BE;
+ background: #F1F5FA;
+ border-color: #D6E1EA;
+ border-left: 2px solid #777;
+ position: relative;
+}
+.dd-dragel > li > .dd-handle[class*="btn-"] {
+ color: #FFF;
+}
+.dd-dragel > .dd-item > .dd-handle {
+ margin-top: 0;
+}
+.dd-list > li[class*="item-"] {
+ border-width: 0;
+ padding: 0;
+}
+.dd-list > li[class*="item-"] > .dd-handle {
+ border-left: 2px solid;
+ border-left-color: inherit;
+}
+.dd-list > li > .dd-handle .sticker {
+ position: absolute;
+ right: 0;
+ top: 0;
+}
+.dd2-handle,
+.dd-dragel > li > .dd2-handle {
+ left: 0;
+ top: 0;
+ width: 36px;
+ margin: 0;
+ border-width: 1px 1px 0 0;
+ text-align: center;
+ padding: 0 !important;
+ line-height: 38px;
+ height: 38px;
+ background: #EBEDF2;
+ border: 1px solid #DEE4EA;
+ cursor: pointer;
+ overflow: hidden;
+ position: absolute;
+ z-index: 1;
+}
+.dd2-handle:hover,
+.dd-dragel > li > .dd2-handle {
+ background: #E3E8ED;
+}
+.dd2-content[class*="btn-"] {
+ text-shadow: none !important;
+}
+.dd2-handle[class*="btn-"] {
+ text-shadow: none !important;
+ background: rgba(0, 0, 0, 0.1) !important;
+ border-right: 1px solid #EEE;
+}
+.dd2-handle[class*="btn-"]:hover {
+ background: rgba(0, 0, 0, 0.08) !important;
+}
+.dd-dragel .dd2-handle[class*="btn-"] {
+ border-color: transparent;
+ border-right-color: #EEE;
+}
+.dd2-handle.btn-yellow {
+ text-shadow: none !important;
+ background: rgba(0, 0, 0, 0.05) !important;
+ border-right: 1px solid #FFF;
+}
+.dd2-handle.btn-yellow:hover {
+ background: rgba(0, 0, 0, 0.08) !important;
+}
+.dd-dragel .dd2-handle.btn-yellow {
+ border-color: transparent;
+ border-right-color: #FFF;
+}
+.dd-item > .dd2-handle .drag-icon {
+ display: none;
+}
+.dd-dragel > .dd-item > .dd2-handle .drag-icon {
+ display: inline;
+}
+.dd-dragel > .dd-item > .dd2-handle .normal-icon {
+ display: none;
+}
+.dropzone {
+ border-radius: 0;
+ border: 1px solid rgba(0, 0, 0, 0.06);
+}
+.dropzone .dz-default.dz-message {
+ background-image: none;
+ font-size: 24px;
+ text-align: center;
+ line-height: 32px;
+ left: 0;
+ width: 100%;
+ margin-left: auto;
+}
+.dropzone .dz-default.dz-message span {
+ display: inline;
+ color: #555;
+}
+.dropzone .dz-default.dz-message span .upload-icon {
+ opacity: 0.7;
+ filter: alpha(opacity=70);
+ margin-top: 8px;
+ cursor: pointer;
+}
+.dropzone .dz-default.dz-message span .upload-icon:hover {
+ opacity: 1;
+ filter: alpha(opacity=100);
+}
+.dropzone .dz-preview .dz-error-mark,
+.dropzone-previews .dz-preview .dz-error-mark,
+.dropzone .dz-preview .dz-success-mark,
+.dropzone-previews .dz-preview .dz-success-mark {
+ background-image: none;
+ background-color: rgba(255, 255, 255, 0.8);
+ border-radius: 100%;
+ text-align: center;
+ line-height: 35px;
+}
+.dropzone .dz-preview .dz-error-mark:before,
+.dropzone-previews .dz-preview .dz-error-mark:before {
+ font-family: FontAwesome;
+ font-size: 30px;
+ color: #DB6262;
+ content: "\f00d";
+}
+.dropzone .dz-preview .dz-success-mark:before,
+.dropzone-previews .dz-preview .dz-success-mark:before {
+ font-family: FontAwesome;
+ font-size: 30px;
+ color: #6DA552;
+ content: "\f00c";
+}
+.dropzone a.dz-remove,
+.dropzone-previews a.dz-remove {
+ border: none;
+ border-radius: 0;
+ color: #FFF;
+ background: #D15B47;
+ cursor: pointer;
+}
+.dropzone a.dz-remove:hover,
+.dropzone-previews a.dz-remove:hover {
+ color: #FFF;
+ background: #B74635;
+}
+.dropzone .progress,
+.dropzone-previews .progress {
+ margin-bottom: 0;
+}
+.dropzone .dz-preview.dz-success .progress,
+.dropzone-previews .dz-preview.dz-success .progress,
+.dropzone .dz-preview.dz-error .progress,
+.dropzone-previews .dz-preview.dz-error .progress {
+ display: none;
+}
+input.typeahead,
+input.tt-query,
+input.tt-hint {
+ min-width: 175px;
+ font-size: 16px;
+ line-height: 24px;
+ border: 1px solid #CCC;
+ border-radius: 0;
+ outline: none;
+}
+input.tt-hint,
+.form-group input.tt-hint {
+ background-color: #FFF !important;
+ color: #B0B0B0 !important;
+}
+.tt-dropdown-menu {
+ text-align: left;
+ position: absolute;
+ left: 0 !important;
+ right: 0 !important;
+ min-width: 175px;
+ margin-top: 2px;
+ padding: 8px 0;
+ background-color: #FFF;
+ border: 1px solid #D0D0D0;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 0;
+ -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+}
+.tt-suggestion {
+ padding: 3px 12px 4px;
+ font-size: 16px;
+ line-height: 24px;
+}
+.tt-suggestion.tt-cursor {
+ color: #FFF;
+ background-color: #4F99C6;
+ cursor: pointer;
+}
+.tt-suggestion p {
+ margin: 0;
+}
+input.typeahead.scrollable ~ .tt-dropdown-menu {
+ max-height: 200px;
+ overflow-y: auto;
+}
+.btn-group > .btn.moveall:first-child,
+.btn-group > .btn.remove:first-child {
+ margin: 0;
+}
+.btn-group > .btn.moveall:first-child + .btn.move,
+.btn-group > .btn.remove:first-child + .btn.removeall {
+ margin: 0;
+}
+.bootstrap-duallistbox-container .info {
+ font-size: 12px;
+}
+.bootstrap-duallistbox-container .clear1,
+.bootstrap-duallistbox-container .clear2 {
+ font-size: 12px;
+}
+.multiselect-container > li > a {
+ padding: 0;
+}
+.multiselect-container > li > a > label {
+ padding: 7px 10px 7px 20px;
+}
+.cancel-on-png,
+.cancel-off-png,
+.star-on-png,
+.star-off-png,
+.star-half-png {
+ font-size: 2em;
+}
+.cancel-on-png,
+.cancel-off-png,
+.star-on-png,
+.star-off-png,
+.star-half-png {
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ font-family: "FontAwesome";
+ font-style: normal;
+ font-variant: normal;
+ font-weight: normal;
+ line-height: 1;
+ speak: none;
+ text-transform: none;
+ color: #777777;
+}
+.cancel-on-png {
+ color: #dd5a43;
+}
+.cancel-on-png:before {
+ content: "\f057";
+}
+.cancel-off-png {
+ color: #e08374;
+}
+.cancel-off-png:before {
+ content: "\f05c";
+}
+.star-on-png {
+ color: #feb902;
+}
+.star-on-png:before {
+ content: "\f005";
+}
+.star-off-png {
+ color: #777777;
+}
+.star-off-png:before {
+ content: "\f006";
+}
+.star-half-png {
+ color: #feb902;
+}
+.star-half-png:before {
+ content: "\f123";
+}
+/* custom animated icons */
+.icon-animated-bell {
+ display: inline-block;
+ -moz-animation: ringing 2.0s 5 ease 1.0s;
+ -webkit-animation: ringing 2.0s 5 ease 1.0s;
+ -o-animation: ringing 2.0s 5 ease 1.0s;
+ -ms-animation: ringing 2.0s 5 ease 1.0s;
+ animation: ringing 2.0s 5 ease 1.0s;
+ -moz-transform-origin: 50% 0%;
+ -webkit-transform-origin: 50% 0%;
+ -o-transform-origin: 50% 0%;
+ -ms-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@-moz-keyframes ringing {
+ 0% {
+ -moz-transform: rotate(-15deg);
+ }
+ 2% {
+ -moz-transform: rotate(15deg);
+ }
+ 4% {
+ -moz-transform: rotate(-18deg);
+ }
+ 6% {
+ -moz-transform: rotate(18deg);
+ }
+ 8% {
+ -moz-transform: rotate(-22deg);
+ }
+ 10% {
+ -moz-transform: rotate(22deg);
+ }
+ 12% {
+ -moz-transform: rotate(-18deg);
+ }
+ 14% {
+ -moz-transform: rotate(18deg);
+ }
+ 16% {
+ -moz-transform: rotate(-12deg);
+ }
+ 18% {
+ -moz-transform: rotate(12deg);
+ }
+ 20% {
+ -moz-transform: rotate(0deg);
+ }
+}
+@-webkit-keyframes ringing {
+ 0% {
+ -webkit-transform: rotate(-15deg);
+ }
+ 2% {
+ -webkit-transform: rotate(15deg);
+ }
+ 4% {
+ -webkit-transform: rotate(-18deg);
+ }
+ 6% {
+ -webkit-transform: rotate(18deg);
+ }
+ 8% {
+ -webkit-transform: rotate(-22deg);
+ }
+ 10% {
+ -webkit-transform: rotate(22deg);
+ }
+ 12% {
+ -webkit-transform: rotate(-18deg);
+ }
+ 14% {
+ -webkit-transform: rotate(18deg);
+ }
+ 16% {
+ -webkit-transform: rotate(-12deg);
+ }
+ 18% {
+ -webkit-transform: rotate(12deg);
+ }
+ 20% {
+ -webkit-transform: rotate(0deg);
+ }
+}
+@-ms-keyframes ringing {
+ 0% {
+ -ms-transform: rotate(-15deg);
+ }
+ 2% {
+ -ms-transform: rotate(15deg);
+ }
+ 4% {
+ -ms-transform: rotate(-18deg);
+ }
+ 6% {
+ -ms-transform: rotate(18deg);
+ }
+ 8% {
+ -ms-transform: rotate(-22deg);
+ }
+ 10% {
+ -ms-transform: rotate(22deg);
+ }
+ 12% {
+ -ms-transform: rotate(-18deg);
+ }
+ 14% {
+ -ms-transform: rotate(18deg);
+ }
+ 16% {
+ -ms-transform: rotate(-12deg);
+ }
+ 18% {
+ -ms-transform: rotate(12deg);
+ }
+ 20% {
+ -ms-transform: rotate(0deg);
+ }
+}
+@keyframes ringing {
+ 0% {
+ transform: rotate(-15deg);
+ }
+ 2% {
+ transform: rotate(15deg);
+ }
+ 4% {
+ transform: rotate(-18deg);
+ }
+ 6% {
+ transform: rotate(18deg);
+ }
+ 8% {
+ transform: rotate(-22deg);
+ }
+ 10% {
+ transform: rotate(22deg);
+ }
+ 12% {
+ transform: rotate(-18deg);
+ }
+ 14% {
+ transform: rotate(18deg);
+ }
+ 16% {
+ transform: rotate(-12deg);
+ }
+ 18% {
+ transform: rotate(12deg);
+ }
+ 20% {
+ transform: rotate(0deg);
+ }
+}
+.icon-animated-vertical {
+ display: inline-block;
+ -moz-animation: vertical 2.0s 5 ease 2.0s;
+ -webkit-animation: vertical 2.0s 5 ease 2.0s;
+ -o-animation: vertical 2.0s 5 ease 2.0s;
+ -ms-animation: vertical 2.0s 5 ease 2.0s;
+ animation: vertical 2.0s 5 ease 2.0s;
+}
+@-moz-keyframes vertical {
+ 0% {
+ -moz-transform: translate(0, -3px);
+ }
+ 4% {
+ -moz-transform: translate(0, 3px);
+ }
+ 8% {
+ -moz-transform: translate(0, -3px);
+ }
+ 12% {
+ -moz-transform: translate(0, 3px);
+ }
+ 16% {
+ -moz-transform: translate(0, -3px);
+ }
+ 20% {
+ -moz-transform: translate(0, 3px);
+ }
+ 22% {
+ -moz-transform: translate(0, 0);
+ }
+}
+@-webkit-keyframes vertical {
+ 0% {
+ -webkit-transform: translate(0, -3px);
+ }
+ 4% {
+ -webkit-transform: translate(0, 3px);
+ }
+ 8% {
+ -webkit-transform: translate(0, -3px);
+ }
+ 12% {
+ -webkit-transform: translate(0, 3px);
+ }
+ 16% {
+ -webkit-transform: translate(0, -3px);
+ }
+ 20% {
+ -webkit-transform: translate(0, 3px);
+ }
+ 22% {
+ -webkit-transform: translate(0, 0);
+ }
+}
+@-ms-keyframes vertical {
+ 0% {
+ -ms-transform: translate(0, -3px);
+ }
+ 4% {
+ -ms-transform: translate(0, 3px);
+ }
+ 8% {
+ -ms-transform: translate(0, -3px);
+ }
+ 12% {
+ -ms-transform: translate(0, 3px);
+ }
+ 16% {
+ -ms-transform: translate(0, -3px);
+ }
+ 20% {
+ -ms-transform: translate(0, 3px);
+ }
+ 22% {
+ -ms-transform: translate(0, 0);
+ }
+}
+@keyframes vertical {
+ 0% {
+ transform: translate(0, -3px);
+ }
+ 4% {
+ transform: translate(0, 3px);
+ }
+ 8% {
+ transform: translate(0, -3px);
+ }
+ 12% {
+ transform: translate(0, 3px);
+ }
+ 16% {
+ transform: translate(0, -3px);
+ }
+ 20% {
+ transform: translate(0, 3px);
+ }
+ 22% {
+ transform: translate(0, 0);
+ }
+}
+.icon-animated-hand-pointer {
+ display: inline-block;
+ -moz-animation: hand-pointer 2.0s 4 ease 2.0s;
+ -webkit-animation: hand-pointer 2.0s 4 ease 2.0s;
+ -o-animation: hand-pointer 2.0s 4 ease 2.0s;
+ -ms-animation: hand-pointer 2.0s 4 ease 2.0s;
+ animation: hand-pointer 2.0s 4 ease 2.0s;
+}
+@-moz-keyframes hand-pointer {
+ 0% {
+ -moz-transform: translate(0, 0);
+ }
+ 6% {
+ -moz-transform: translate(5px, 0);
+ }
+ 12% {
+ -moz-transform: translate(0, 0);
+ }
+ 18% {
+ -moz-transform: translate(5px, 0);
+ }
+ 24% {
+ -moz-transform: translate(0, 0);
+ }
+ 30% {
+ -moz-transform: translate(5px, 0);
+ }
+ 36% {
+ -moz-transform: translate(0, 0);
+ }
+}
+.icon-animated-wrench {
+ display: inline-block;
+ -moz-animation: wrenching 2.5s 4 ease;
+ -webkit-animation: wrenching 2.5s 4 ease;
+ -o-animation: wrenching 2.5s 4 ease;
+ -ms-animation: wrenching 2.5s 4 ease;
+ animation: wrenching 2.5s 4 ease;
+ -moz-transform-origin: 90% 35%;
+ -webkit-transform-origin: 90% 35%;
+ -o-transform-origin: 90% 35%;
+ -ms-transform-origin: 90% 35%;
+ transform-origin: 90% 35%;
+}
+@-moz-keyframes wrenching {
+ 0% {
+ -moz-transform: rotate(-12deg);
+ }
+ 8% {
+ -moz-transform: rotate(12deg);
+ }
+ 10% {
+ -moz-transform: rotate(24deg);
+ }
+ 18% {
+ -moz-transform: rotate(-24deg);
+ }
+ 20% {
+ -moz-transform: rotate(-24deg);
+ }
+ 28% {
+ -moz-transform: rotate(24deg);
+ }
+ 30% {
+ -moz-transform: rotate(24deg);
+ }
+ 38% {
+ -moz-transform: rotate(-24deg);
+ }
+ 40% {
+ -moz-transform: rotate(-24deg);
+ }
+ 48% {
+ -moz-transform: rotate(24deg);
+ }
+ 50% {
+ -moz-transform: rotate(24deg);
+ }
+ 58% {
+ -moz-transform: rotate(-24deg);
+ }
+ 60% {
+ -moz-transform: rotate(-24deg);
+ }
+ 68% {
+ -moz-transform: rotate(24deg);
+ }
+ 75% {
+ -moz-transform: rotate(0deg);
+ }
+}
+@-webkit-keyframes wrenching {
+ 0% {
+ -webkit-transform: rotate(-12deg);
+ }
+ 8% {
+ -webkit-transform: rotate(12deg);
+ }
+ 10% {
+ -webkit-transform: rotate(24deg);
+ }
+ 18% {
+ -webkit-transform: rotate(-24deg);
+ }
+ 20% {
+ -webkit-transform: rotate(-24deg);
+ }
+ 28% {
+ -webkit-transform: rotate(24deg);
+ }
+ 30% {
+ -webkit-transform: rotate(24deg);
+ }
+ 38% {
+ -webkit-transform: rotate(-24deg);
+ }
+ 40% {
+ -webkit-transform: rotate(-24deg);
+ }
+ 48% {
+ -webkit-transform: rotate(24deg);
+ }
+ 50% {
+ -webkit-transform: rotate(24deg);
+ }
+ 58% {
+ -webkit-transform: rotate(-24deg);
+ }
+ 60% {
+ -webkit-transform: rotate(-24deg);
+ }
+ 68% {
+ -webkit-transform: rotate(24deg);
+ }
+ 75% {
+ -webkit-transform: rotate(0deg);
+ }
+}
+@-o-keyframes wrenching {
+ 0% {
+ -o-transform: rotate(-12deg);
+ }
+ 8% {
+ -o-transform: rotate(12deg);
+ }
+ 10% {
+ -o-transform: rotate(24deg);
+ }
+ 18% {
+ -o-transform: rotate(-24deg);
+ }
+ 20% {
+ -o-transform: rotate(-24deg);
+ }
+ 28% {
+ -o-transform: rotate(24deg);
+ }
+ 30% {
+ -o-transform: rotate(24deg);
+ }
+ 38% {
+ -o-transform: rotate(-24deg);
+ }
+ 40% {
+ -o-transform: rotate(-24deg);
+ }
+ 48% {
+ -o-transform: rotate(24deg);
+ }
+ 50% {
+ -o-transform: rotate(24deg);
+ }
+ 58% {
+ -o-transform: rotate(-24deg);
+ }
+ 60% {
+ -o-transform: rotate(-24deg);
+ }
+ 68% {
+ -o-transform: rotate(24deg);
+ }
+ 75% {
+ -o-transform: rotate(0deg);
+ }
+}
+@-ms-keyframes wrenching {
+ 0% {
+ -ms-transform: rotate(-12deg);
+ }
+ 8% {
+ -ms-transform: rotate(12deg);
+ }
+ 10% {
+ -ms-transform: rotate(24deg);
+ }
+ 18% {
+ -ms-transform: rotate(-24deg);
+ }
+ 20% {
+ -ms-transform: rotate(-24deg);
+ }
+ 28% {
+ -ms-transform: rotate(24deg);
+ }
+ 30% {
+ -ms-transform: rotate(24deg);
+ }
+ 38% {
+ -ms-transform: rotate(-24deg);
+ }
+ 40% {
+ -ms-transform: rotate(-24deg);
+ }
+ 48% {
+ -ms-transform: rotate(24deg);
+ }
+ 50% {
+ -ms-transform: rotate(24deg);
+ }
+ 58% {
+ -ms-transform: rotate(-24deg);
+ }
+ 60% {
+ -ms-transform: rotate(-24deg);
+ }
+ 68% {
+ -ms-transform: rotate(24deg);
+ }
+ 75% {
+ -ms-transform: rotate(0deg);
+ }
+}
+@keyframes wrenching {
+ 0% {
+ transform: rotate(-12deg);
+ }
+ 8% {
+ transform: rotate(12deg);
+ }
+ 10% {
+ transform: rotate(24deg);
+ }
+ 18% {
+ transform: rotate(-24deg);
+ }
+ 20% {
+ transform: rotate(-24deg);
+ }
+ 28% {
+ transform: rotate(24deg);
+ }
+ 30% {
+ transform: rotate(24deg);
+ }
+ 38% {
+ transform: rotate(-24deg);
+ }
+ 40% {
+ transform: rotate(-24deg);
+ }
+ 48% {
+ transform: rotate(24deg);
+ }
+ 50% {
+ transform: rotate(24deg);
+ }
+ 58% {
+ transform: rotate(-24deg);
+ }
+ 60% {
+ transform: rotate(-24deg);
+ }
+ 68% {
+ transform: rotate(24deg);
+ }
+ 75% {
+ transform: rotate(0deg);
+ }
+}
+@-moz-keyframes blinking {
+ 0% {
+ opacity: 1;
+ }
+ 40% {
+ opacity: 0;
+ }
+ 80% {
+ opacity: 1;
+ }
+}
+@-webkit-keyframes blinking {
+ 0% {
+ opacity: 1;
+ }
+ 40% {
+ opacity: 0;
+ }
+ 80% {
+ opacity: 1;
+ }
+}
+@-ms-keyframes blinking {
+ 0% {
+ opacity: 1;
+ }
+ 40% {
+ opacity: 0;
+ }
+ 80% {
+ opacity: 1;
+ }
+}
+@keyframes blinking {
+ 0% {
+ opacity: 1;
+ }
+ 40% {
+ opacity: 0;
+ }
+ 80% {
+ opacity: 1;
+ }
+}
+@-moz-keyframes pulsating {
+ 0% {
+ -moz-transform: scale(1);
+ }
+ 5% {
+ -moz-transform: scale(0.75);
+ }
+ 10% {
+ -moz-transform: scale(1);
+ }
+ 15% {
+ -moz-transform: scale(1.25);
+ }
+ 20% {
+ -moz-transform: scale(1);
+ }
+ 25% {
+ -moz-transform: scale(0.75);
+ }
+ 30% {
+ -moz-transform: scale(1);
+ }
+ 35% {
+ -moz-transform: scale(1.25);
+ }
+ 40% {
+ -moz-transform: scale(1);
+ }
+}
+@-webkit-keyframes pulsating {
+ 0% {
+ -webkit-transform: scale(1);
+ }
+ 5% {
+ -webkit-transform: scale(0.75);
+ }
+ 10% {
+ -webkit-transform: scale(1);
+ }
+ 15% {
+ -webkit-transform: scale(1.25);
+ }
+ 20% {
+ -webkit-transform: scale(1);
+ }
+ 25% {
+ -webkit-transform: scale(0.75);
+ }
+ 30% {
+ -webkit-transform: scale(1);
+ }
+ 35% {
+ -webkit-transform: scale(1.25);
+ }
+ 40% {
+ -webkit-transform: scale(1);
+ }
+}
+@-ms-keyframes pulsating {
+ 0% {
+ -ms-transform: scale(1);
+ }
+ 5% {
+ -ms-transform: scale(0.75);
+ }
+ 10% {
+ -ms-transform: scale(1);
+ }
+ 15% {
+ -ms-transform: scale(1.25);
+ }
+ 20% {
+ -ms-transform: scale(1);
+ }
+ 25% {
+ -ms-transform: scale(0.75);
+ }
+ 30% {
+ -ms-transform: scale(1);
+ }
+ 35% {
+ -ms-transform: scale(1.25);
+ }
+ 40% {
+ -ms-transform: scale(1);
+ }
+}
+@keyframes pulsating {
+ 0% {
+ transform: scale(1);
+ }
+ 5% {
+ transform: scale(0.75);
+ }
+ 10% {
+ transform: scale(1);
+ }
+ 15% {
+ transform: scale(1.25);
+ }
+ 20% {
+ transform: scale(1);
+ }
+ 25% {
+ transform: scale(0.75);
+ }
+ 30% {
+ transform: scale(1);
+ }
+ 35% {
+ transform: scale(1.25);
+ }
+ 40% {
+ transform: scale(1);
+ }
+}
+.btn-scroll-up {
+ border-width: 0;
+ position: fixed;
+ right: 2px;
+ z-index: 99;
+ -webkit-transition-duration: 0.3s;
+ transition-duration: 0.3s;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ bottom: -24px;
+ visibility: hidden;
+}
+.btn-scroll-up.display {
+ opacity: 0.7;
+ filter: alpha(opacity=70);
+ bottom: 2px;
+ visibility: visible;
+}
+.btn-scroll-up:hover {
+ opacity: 1;
+ filter: alpha(opacity=100);
+}
+.btn-scroll-up:focus {
+ outline: none;
+}
+@media (min-width: 768px) {
+ .main-container.container > .btn-scroll-up {
+ right: auto;
+ margin-left: 714px;
+ }
+}
+@media (min-width: 992px) {
+ .main-container.container > .btn-scroll-up {
+ right: auto;
+ margin-left: 934px;
+ }
+}
+@media (min-width: 1200px) {
+ .main-container.container > .btn-scroll-up {
+ right: auto;
+ margin-left: 1134px;
+ }
+}
+.ace-settings-container {
+ position: absolute;
+ right: 0;
+ top: auto;
+ z-index: 12;
+}
+.btn.btn-app.ace-settings-btn {
+ float: left;
+ display: block;
+ text-align: center;
+ border-radius: 6px 0 0 6px;
+ opacity: 0.55;
+ vertical-align: top;
+ margin: 0;
+}
+.btn.btn-app.ace-settings-btn:hover,
+.btn.btn-app.ace-settings-btn.open {
+ opacity: 1;
+}
+.btn.btn-app.ace-settings-btn.btn-xs {
+ width: 42px;
+}
+.ace-settings-box {
+ display: block;
+ float: left;
+ max-width: 0;
+ max-height: 0;
+ overflow: hidden;
+ padding: 0;
+ -moz-transform: translate(0,0);
+ -webkit-transform: translate(0,0);
+ -o-transform: translate(0,0);
+ -ms-transform: translate(0,0);
+ transform: translate(0,0);
+ background-color: #FFF;
+ border: 0 solid #ffb34b;
+ -webkit-transition: max-width 0.25s linear 0s, max-height 0s linear 0.25s, padding 0s linear 0.25s, border-width 0s linear 0.25s;
+ -o-transition: max-width 0.25s linear 0s, max-height 0s linear 0.25s, padding 0s linear 0.25s, border-width 0s linear 0.25s;
+ transition: max-width 0.25s linear 0s, max-height 0s linear 0.25s, padding 0s linear 0.25s, border-width 0s linear 0.25s;
+}
+.ace-settings-box.open {
+ max-width: 320px;
+ max-height: 1000px;
+ padding: 0 14px;
+ border-width: 2px;
+ -webkit-transition-delay: 0s;
+ -moz-transition-delay: 0s;
+ -o-transition-delay: 0s;
+ transition-delay: 0s;
+}
+.ace-settings-box.open .ace-settings-item {
+ z-index: auto;
+ min-width: 140px;
+}
+.ace-settings-box .ace-settings-item {
+ margin: 6px 0;
+ color: #444;
+ max-height: 24px;
+ position: relative;
+ z-index: -1;
+ white-space: nowrap;
+}
+.ace-settings-box .ace-settings-item > label.lbl {
+ font-size: 13px;
+}
+@media (max-width: 480px) {
+ .ace-settings-container {
+ text-align: right;
+ }
+ .ace-settings-box {
+ float: none !important;
+ text-align: left;
+ }
+ .btn.ace-settings-btn {
+ float: none !important;
+ display: inline-block;
+ }
+}
+@media (max-width: 320px) {
+ .ace-settings-box > .clearfix > .pull-left,
+ .ace-settings-box > .clearfix > .pull-right {
+ float: none !important;
+ }
+}
+.grid2,
+.grid3,
+.grid4 {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ display: block;
+ margin: 0 1%;
+ padding: 0 2%;
+ float: left;
+ border-left: 1px solid #E3E3E3;
+}
+.grid2:first-child,
+.grid3:first-child,
+.grid4:first-child {
+ border-left: none;
+}
+.grid2 {
+ width: 48%;
+}
+.grid3 {
+ width: 31.33%;
+}
+.grid4 {
+ width: 23%;
+ padding: 0 1%;
+}
+.draggable-placeholder {
+ border: 2px dashed #D9D9D9 !important;
+ background-color: #F7F7F7 !important;
+}
+.easyPieChart,
+.easy-pie-chart {
+ position: relative;
+ text-align: center;
+}
+.easyPieChart canvas,
+.easy-pie-chart canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+.knob-container {
+ direction: ltr;
+ text-align: left;
+}
+.tags {
+ display: inline-block;
+ padding: 4px 6px;
+ color: #777777;
+ vertical-align: middle;
+ background-color: #FFF;
+ border: 1px solid #d5d5d5;
+ width: 206px;
+}
+.tags:hover {
+ border-color: #b5b5b5;
+}
+.tags-hover,
+.tags-hover:hover {
+ border-color: #f59942;
+ outline: 0;
+}
+.tags[class*="span"] {
+ float: none;
+ margin-left: 0;
+}
+.tags input[type="text"],
+.tags input[type="text"]:focus {
+ border: none;
+ display: inline;
+ outline: 0;
+ margin: 0;
+ padding: 0;
+ line-height: 18px;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ width: 100%;
+}
+.tags .tag {
+ display: inline-block;
+ position: relative;
+ font-size: 13px;
+ font-weight: normal;
+ vertical-align: baseline;
+ white-space: nowrap;
+ background-color: #91b8d0;
+ color: #FFF;
+ text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.15);
+ padding: 4px 22px 5px 9px;
+ margin-bottom: 3px;
+ margin-right: 3px;
+ -webkit-transition: all 0.2s;
+ -o-transition: all 0.2s;
+ transition: all 0.2s;
+ /**
+ &:nth-child(5n+1) {
+ background-color:#48A2E0;
+ }
+ &:nth-child(5n+2) {
+ background-color:#34C896;
+ }
+ &:nth-child(5n+3) {
+ background-color:#B57BB3;
+ }
+ &:nth-child(5n+4) {
+ background-color:#CC7DA8;
+ }
+ &:nth-child(5n+5) {
+ background-color:#666;
+ }
+*/
+}
+.tags .tag:empty {
+ display: none;
+}
+.tags .tag-important {
+ background-color: #d15b47;
+}
+.tags .tag-warning {
+ background-color: #ffb752;
+}
+.tags .tag-success {
+ background-color: #87b87f;
+}
+.tags .tag-info {
+ background-color: #6fb3e0;
+}
+.tags .tag-inverse {
+ background-color: #555555;
+}
+.tags .tag .close {
+ font-size: 15px;
+ line-height: 20px;
+ opacity: 1;
+ filter: alpha(opacity=100);
+ color: #FFF;
+ text-shadow: none;
+ float: none;
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 18px;
+ text-align: center;
+}
+.tags .tag .close:hover {
+ background-color: rgba(0, 0, 0, 0.2);
+}
+.page-content > .row .col-xs-12,
+.page-content > .row .col-sm-12,
+.page-content > .row .col-md-12,
+.page-content > .row .col-lg-12 {
+ float: left;
+ max-width: 100%;
+}
+.col-xs-reset {
+ width: auto;
+ padding-left: 0;
+ padding-right: 0;
+ float: none !important;
+}
+@media (min-width: 768px) {
+ .col-sm-reset {
+ width: auto;
+ padding-left: 0;
+ padding-right: 0;
+ float: none !important;
+ }
+}
+@media (min-width: 992px) {
+ .col-md-reset {
+ width: auto;
+ padding-left: 0;
+ padding-right: 0;
+ float: none !important;
+ }
+}
+@media (min-width: 1200px) {
+ .col-lg-reset {
+ width: auto;
+ padding-left: 0;
+ padding-right: 0;
+ float: none !important;
+ }
+}
+.jqstooltip,
+.legendColorBox div {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+.legendLabel {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 22px;
+ padding-left: 2px;
+ font-size: 10px;
+}
+@media only screen and (max-width: 991px) {
+ body {
+ overflow-x: hidden;
+ }
+}
+.navbar-fixed-top + .main-container {
+ padding-top: 45px;
+}
+@media (max-width: 479px) {
+ .navbar-fixed-top + .main-container {
+ padding-top: 90px;
+ }
+ .navbar-fixed-top.navbar-collapse + .main-container {
+ padding-top: 45px;
+ }
+}
+@media only screen and (max-width: 360px) {
+ .grid2,
+ .grid3,
+ .grid4 {
+ float: none;
+ display: block;
+ width: 96%;
+ border-left-width: 0;
+ position: relative;
+ margin-bottom: 11px;
+ border-bottom: 1px solid #E3E3E3;
+ padding-bottom: 4px;
+ }
+ .grid2 > [class*="pull-"],
+ .grid3 > [class*="pull-"],
+ .grid4 > [class*="pull-"] {
+ float: none !important;
+ display: inline-block;
+ position: absolute;
+ right: 11px;
+ top: 0;
+ margin-top: 0;
+ }
+ .grid2:last-child,
+ .grid3:last-child,
+ .grid4:last-child {
+ border-bottom-width: 0;
+ }
+}
+@media only screen and (max-width: 480px) {
+ .hidden-480 {
+ display: none !important;
+ }
+}
+@media only screen and (max-width: 320px) {
+ .hidden-320 {
+ display: none !important;
+ }
+}
+.no-skin {
+ /**
+ .nav-list > li.disabled.active:after {
+ border-color: #999;
+ }
+ .nav-list li.disabled li.active > a:after,
+ .nav-list li.active.disabled > a:after {
+ -moz-border-right-colors: #999 !important;
+ border-right-color: #999 !important;
+ }
+ */
+}
+.no-skin .navbar .navbar-toggle {
+ background-color: #75B3D7;
+}
+.no-skin .navbar .navbar-toggle:focus {
+ background-color: #75B3D7;
+ border-color: transparent;
+}
+.no-skin .navbar .navbar-toggle:hover {
+ background-color: #61a8d1;
+ border-color: rgba(255, 255, 255, 0.1);
+}
+.no-skin .navbar .navbar-toggle.display,
+.no-skin .navbar .navbar-toggle[data-toggle=collapse]:not(.collapsed) {
+ background-color: #4d9dcc;
+ box-shadow: inset 1px 1px 2px 0 rgba(0, 0, 0, 0.25);
+ border-color: rgba(255, 255, 255, 0.35);
+}
+.no-skin .sidebar {
+ background-color: #f2f2f2;
+ border-style: solid;
+ border-color: #cccccc;
+ border-width: 0 1px 0 0;
+}
+.no-skin .nav-list .open > a,
+.no-skin .nav-list .open > a:hover,
+.no-skin .nav-list .open > a:focus {
+ background-color: #fafafa;
+}
+.no-skin .nav-list > li {
+ border-color: #e5e5e5;
+}
+.no-skin .nav-list > li > a {
+ background-color: #f8f8f8;
+ color: #585858;
+}
+.no-skin .nav-list > li > a:focus {
+ background-color: #f8f8f8;
+ color: #1963aa;
+}
+.no-skin .nav-list > li:hover > a {
+ background-color: #ffffff;
+ color: #266cad;
+}
+.no-skin .nav-list > li.open > a {
+ background-color: #fafafa;
+ color: #1963aa;
+}
+.no-skin .nav-list > li.active > a {
+ font-weight: bold;
+ color: #2b7dbc;
+}
+.no-skin .nav-list > li.active > a,
+.no-skin .nav-list > li.active > a:hover,
+.no-skin .nav-list > li.active > a:focus {
+ background-color: #ffffff;
+}
+.no-skin .nav-list > li .submenu {
+ background-color: #ffffff;
+ border-color: #e5e5e5;
+}
+.no-skin .nav-list > li .submenu > li > a {
+ border-top-color: #e4e4e4;
+ background-color: #ffffff;
+ color: #616161;
+}
+.no-skin .nav-list > li .submenu > li > a:hover {
+ color: #4b88b7;
+ background-color: #f1f5f9;
+}
+.no-skin .nav-list > li .submenu > li.active > a {
+ color: #2b7dbc;
+}
+.no-skin .nav-list > li .submenu > li.active > a > .menu-icon {
+ color: #c86139;
+}
+.no-skin .nav-list > li .submenu > li.active.open > a > .menu-icon {
+ color: inherit;
+}
+@media only screen and (min-width: 992px) {
+ .no-skin .nav-list > li .submenu > li.active.hover > a.dropdown-toggle > .menu-icon {
+ color: inherit;
+ }
+}
+.no-skin .nav-list > li .submenu > li.active:not(.open) > a {
+ background-color: #f5f7fa;
+}
+.no-skin .nav-list > li .submenu > li.active:not(.open) > a:hover {
+ background-color: #f1f5f9;
+}
+.no-skin .nav-list > li > .submenu .open > a,
+.no-skin .nav-list > li > .submenu .open > a:hover,
+.no-skin .nav-list > li > .submenu .open > a:focus {
+ border-color: #e4e4e4;
+}
+.no-skin .nav-list > li > .submenu li > .submenu > li a {
+ color: #757575;
+}
+.no-skin .nav-list > li > .submenu li > .submenu > li a:hover {
+ color: #4b88b7;
+ background-color: #f1f5f9;
+}
+.no-skin .nav-list > li > .submenu li.open > a {
+ color: #4b88b7;
+}
+.no-skin .nav-list > li > .submenu li > .submenu li.open > a,
+.no-skin .nav-list > li > .submenu li > .submenu li.active > a {
+ color: #4b88b7;
+}
+.no-skin .nav-list > li > .submenu:before,
+.no-skin .nav-list > li > .submenu > li:before {
+ border-color: #9dbdd6;
+}
+.no-skin .nav-list > li.active > .submenu:before,
+.no-skin .nav-list > li.active > .submenu > li:before {
+ border-color: #8eb3d0;
+}
+.no-skin .sidebar-toggle {
+ background-color: #f3f3f3;
+ border-color: #e0e0e0;
+}
+.no-skin .sidebar-toggle > .ace-icon {
+ border-color: #bbbbbb;
+ color: #aaaaaa;
+ background-color: #ffffff;
+}
+.no-skin .sidebar-shortcuts {
+ background-color: #fafafa;
+}
+.no-skin .sidebar-fixed .sidebar-shortcuts {
+ border-color: #dddddd;
+}
+.no-skin .sidebar-shortcuts-mini {
+ background-color: #ffffff;
+}
+.no-skin .nav-list li > .arrow:before {
+ border-right-color: #B8B8B8;
+ -moz-border-right-colors: #B8B8B8;
+ border-width: 10px 10px 10px 0;
+ left: -11px;
+}
+.no-skin .nav-list li > .arrow:after {
+ border-right-color: #ffffff;
+ -moz-border-right-colors: #ffffff;
+ border-width: 10px 10px 10px 0;
+ left: -10px;
+}
+.no-skin .nav-list > li.pull_up > .arrow:after {
+ border-right-color: #ffffff !important;
+ -moz-border-right-colors: #ffffff !important;
+ border-width: 10px 10px 10px 0 !important;
+ left: -10px !important;
+}
+.no-skin .nav-list > li.pull_up > .arrow:before {
+ border-width: 10px 10px 10px 0 !important;
+ left: -11px !important;
+}
+.no-skin .nav-list li.active > a:after {
+ border-right-color: #2b7dbc;
+ -moz-border-right-colors: #2b7dbc;
+}
+.no-skin .nav-list > li.active:after {
+ display: block;
+ content: "";
+ position: absolute;
+ right: -2px;
+ top: -1px;
+ bottom: 0;
+ z-index: 1;
+ border: 2px solid;
+ border-width: 0 2px 0 0;
+ border-color: #2b7dbc;
+}
+.no-skin .sidebar-scroll .nav-list > li.active:after {
+ right: 0;
+}
+@media only screen and (max-width: 991px) {
+ .no-skin .sidebar.responsive .nav-list > li.active.open > a:after,
+ .no-skin .sidebar.responsive-max .nav-list > li.active.open > a:after {
+ display: block;
+ }
+ .no-skin .sidebar.responsive .nav-list li li.active > a:after,
+ .no-skin .sidebar.responsive-max .nav-list li li.active > a:after {
+ display: none;
+ }
+ .no-skin .sidebar.responsive .nav-list > li.active:after,
+ .no-skin .sidebar.responsive-max .nav-list > li.active:after {
+ height: 41px;
+ }
+}
+.no-skin .sidebar.menu-min .nav-list > li > a > .menu-text {
+ background-color: #f5f5f5;
+ -webkit-box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ border-color: #cccccc;
+}
+.no-skin .sidebar.menu-min .nav-list > li > a.dropdown-toggle > .menu-text {
+ -webkit-box-shadow: 2px 2px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 2px 2px 0 rgba(0,0,0,0.1);
+}
+.no-skin .sidebar.menu-min .nav-list > li.active > .submenu {
+ border-left-color: #83b6d1;
+}
+.no-skin .sidebar.menu-min .nav-list > li > .submenu {
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ border-top-color: #e6e6e6;
+ -webkit-box-shadow: 2px 2px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 2px 2px 0 rgba(0,0,0,0.1);
+}
+.no-skin .sidebar.menu-min .nav-list > li > .arrow:after {
+ border-right-color: #f5f5f5;
+ -moz-border-right-colors: #f5f5f5;
+ border-width: 8px 8px 8px 0;
+ left: -8px;
+}
+.no-skin .sidebar.menu-min .nav-list > li > .arrow:before {
+ border-width: 8px 8px 8px 0;
+ left: -9px;
+}
+.no-skin .sidebar.menu-min .nav-list > li.active > .arrow:before {
+ border-right-color: #5a9ec2;
+ -moz-border-right-colors: #5a9ec2;
+}
+.no-skin .sidebar.menu-min .nav-list > li.active > a > .menu-text {
+ border-left-color: #83b6d1;
+}
+.no-skin .sidebar.menu-min .sidebar-shortcuts-large {
+ background-color: #ffffff;
+ -webkit-box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ border-color: #cccccc;
+}
+.no-skin .sidebar.menu-min .sidebar-toggle > .ace-icon {
+ border-color: #b1b1b1;
+}
+@media (max-width: 991px) {
+ .no-skin .sidebar.responsive-min .nav-list > li > a > .menu-text {
+ background-color: #f5f5f5;
+ -webkit-box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ border-color: #cccccc;
+ }
+ .no-skin .sidebar.responsive-min .nav-list > li > a.dropdown-toggle > .menu-text {
+ -webkit-box-shadow: 2px 2px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 2px 2px 0 rgba(0,0,0,0.1);
+ }
+ .no-skin .sidebar.responsive-min .nav-list > li.active > .submenu {
+ border-left-color: #83b6d1;
+ }
+ .no-skin .sidebar.responsive-min .nav-list > li > .submenu {
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ border-top-color: #e6e6e6;
+ -webkit-box-shadow: 2px 2px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 2px 2px 0 rgba(0,0,0,0.1);
+ }
+ .no-skin .sidebar.responsive-min .nav-list > li > .arrow:after {
+ border-right-color: #f5f5f5;
+ -moz-border-right-colors: #f5f5f5;
+ border-width: 8px 8px 8px 0;
+ left: -8px;
+ }
+ .no-skin .sidebar.responsive-min .nav-list > li > .arrow:before {
+ border-width: 8px 8px 8px 0;
+ left: -9px;
+ }
+ .no-skin .sidebar.responsive-min .nav-list > li.active > .arrow:before {
+ border-right-color: #5a9ec2;
+ -moz-border-right-colors: #5a9ec2;
+ }
+ .no-skin .sidebar.responsive-min .nav-list > li.active > a > .menu-text {
+ border-left-color: #83b6d1;
+ }
+ .no-skin .sidebar.responsive-min .sidebar-shortcuts-large {
+ background-color: #ffffff;
+ -webkit-box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ border-color: #cccccc;
+ }
+ .no-skin .sidebar.responsive-min .sidebar-toggle > .ace-icon {
+ border-color: #b1b1b1;
+ }
+}
+@media only screen and (min-width: 992px) {
+ .no-skin .nav-list li.hover > .submenu {
+ -webkit-box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ border-color: #cccccc;
+ }
+ .no-skin .nav-list li.hover > .submenu > li.active > a {
+ background-color: #f5f5f5;
+ }
+ .no-skin .nav-list li.hover > .submenu > li:hover > a {
+ background-color: #eef3f7;
+ color: #2e7db4;
+ }
+}
+@media only screen and (min-width: 992px) and (max-width: 991px) {
+ .no-skin .sidebar.navbar-collapse .nav-list li li.hover.active.open > a {
+ background-color: #ffffff;
+ }
+ .no-skin .sidebar.navbar-collapse .nav-list li li.hover:hover > a {
+ background-color: #ffffff;
+ }
+ .no-skin .sidebar.navbar-collapse .nav-list li li.hover > a:hover,
+ .no-skin .sidebar.navbar-collapse .nav-list li li.hover.open > a:hover,
+ .no-skin .sidebar.navbar-collapse .nav-list li li.hover.open.active > a:hover {
+ background-color: #f1f5f9;
+ }
+ .no-skin .sidebar.navbar-collapse .nav-list > li .submenu > li.active.hover > a.dropdown-toggle > .menu-icon {
+ color: #c86139;
+ }
+ .no-skin .sidebar.navbar-collapse .nav-list > li .submenu > li.active.open.hover > a.dropdown-toggle > .menu-icon {
+ color: inherit;
+ }
+}
+@media only screen and (min-width: 992px) {
+ .no-skin .sidebar.navbar-collapse .nav-list > li.open.hover:not(:hover):not(:focus):not(.active) > a {
+ color: #585858;
+ }
+ .no-skin .sidebar.navbar-collapse .nav-list > li.open.hover:not(:hover):not(:focus):not(.active) > a > .arrow {
+ color: inherit;
+ }
+ .no-skin .sidebar.navbar-collapse .nav-list > li.open.hover:hover > a {
+ background-color: #ffffff;
+ }
+ .no-skin .sidebar.navbar-collapse .nav-list > li > .submenu li.open.hover:not(:hover):not(:focus):not(.active) > a {
+ color: #616161;
+ }
+ .no-skin .sidebar.navbar-collapse .nav-list > li > .submenu li.open.hover:not(:hover):not(:focus):not(.active) > a > .arrow {
+ color: inherit;
+ }
+}
+@media only screen and (min-width: 992px) and (max-width: 991px) {
+ .no-skin .sidebar.navbar-collapse .nav-list li.hover > .submenu {
+ border-top-color: #e5e5e5;
+ background-color: #ffffff;
+ }
+ .no-skin .nav-list li.hover > .submenu > li.active:not(.open) > a {
+ background-color: #f5f7fa;
+ }
+ .no-skin .nav-list li.hover > .submenu > li.active:not(.open) > a:hover {
+ background-color: #f1f5f9;
+ }
+}
+@media only screen and (min-width: 992px) {
+ .no-skin .sidebar.h-sidebar {
+ background-color: #f8f8f8;
+ }
+ .no-skin .sidebar.h-sidebar:before {
+ background-color: #e4e4e4;
+ -webkit-box-shadow: 0 -1px 1px 0 rgba(0, 0, 0, 0.05) inset;
+ box-shadow: 0 -1px 1px 0 rgba(0, 0, 0, 0.05) inset;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li:hover,
+ .no-skin .sidebar.h-sidebar .nav-list > li:hover + li {
+ border-left-color: #cedde5;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li:last-child:hover {
+ border-right-color: #cedde5;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.active,
+ .no-skin .sidebar.h-sidebar .nav-list > li.active + li,
+ .no-skin .sidebar.h-sidebar .nav-list > li:hover + li.active {
+ border-left-color: #79b0ce;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.active:last-child {
+ border-right-color: #79b0ce;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.active:before {
+ background-color: #2b7dbc;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.active > a:after {
+ border-width: 0 0 2px 0;
+ border-color: transparent;
+ border-bottom-color: #FFF;
+ left: 0;
+ right: 0;
+ top: auto;
+ bottom: -2px;
+ }
+ .no-skin .sidebar.h-sidebar .sidebar-shortcuts-large {
+ background-color: #FFF;
+ border-color: #cccccc;
+ -webkit-box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ box-shadow: 2px 1px 2px 0 rgba(0,0,0,0.1);
+ }
+ .no-skin .sidebar.h-sidebar .sidebar-shortcuts-large:after {
+ border-bottom-color: #FFF;
+ -moz-border-bottom-colors: #FFF;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.hover > .submenu {
+ border-color: #cccccc;
+ }
+ .no-skin .sidebar.h-sidebar.menu-min .nav-list > li.hover > .submenu {
+ border-top-color: #e6e6e6;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.hover > .arrow:after {
+ border-color: transparent;
+ -moz-border-right-colors: none;
+ -moz-border-top-colors: none;
+ -moz-border-left-colors: none;
+ border-bottom-color: #FFF;
+ -moz-border-bottom-colors: #FFF;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.hover > .arrow:before {
+ border-color: transparent;
+ -moz-border-right-colors: none;
+ -moz-border-top-colors: none;
+ -moz-border-left-colors: none;
+ -moz-border-bottom-colors: #B8B8B8;
+ border-bottom-color: #B8B8B8;
+ }
+ .no-skin .sidebar.h-sidebar.menu-min .nav-list > li.hover > .arrow:after {
+ -moz-border-bottom-colors: #F5F5F5;
+ border-bottom-color: #F5F5F5;
+ }
+ .no-skin .sidebar.h-sidebar.menu-min .nav-list > li.active > a > .menu-text {
+ border-left-color: #cccccc;
+ }
+}
+@media only screen and (max-width: 991px) {
+ .no-skin .sidebar {
+ border-width: 0 1px 1px 0;
+ border-top-color: #d6d6d6;
+ }
+ .no-skin .menu-toggler + .sidebar.responsive {
+ border-top-width: 1px;
+ }
+ .no-skin .sidebar.responsive-min {
+ border-width: 0 1px 0 0;
+ }
+ .no-skin .sidebar.navbar-collapse {
+ border-width: 0;
+ border-bottom-width: 1px !important;
+ border-bottom-color: #cccccc;
+ -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1) !important;
+ box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1) !important;
+ }
+ .no-skin .sidebar.navbar-collapse.menu-min .nav-list > li > .submenu {
+ background-color: #ffffff;
+ }
+}
+.no-skin .sidebar-scroll .sidebar-shortcuts {
+ border-bottom-color: #dddddd;
+}
+.no-skin .sidebar-scroll .sidebar-toggle {
+ border-top-color: #dddddd;
+}
+.no-skin .main-container .menu-toggler {
+ background-color: #444444;
+}
+.no-skin .main-container .menu-toggler:before {
+ border-top-color: #87b87f;
+ border-bottom-color: #6fb3e0;
+}
+.no-skin .main-container .menu-toggler:after {
+ border-top-color: #ffa24d;
+ border-bottom-color: #d15b47;
+}
+.no-skin .main-container .menu-toggler > .toggler-text {
+ border-top-color: #444444;
+ -moz-border-top-colors: #444444;
+}
+.no-skin .nav-list > li.disabled:before {
+ display: none !important;
+}
+.no-skin .nav-list > li.disabled > a {
+ background-color: #ebebeb !important;
+ color: #656565 !important;
+}
+.no-skin .nav-list li .submenu > li.disabled > a,
+.no-skin .nav-list li.disabled .submenu > li > a {
+ background-color: #f2f2f2 !important;
+ color: #7a7a7a !important;
+ cursor: not-allowed !important;
+}
+.no-skin .nav-list li .submenu > li.disabled > a > .menu-icon,
+.no-skin .nav-list li.disabled .submenu > li > a > .menu-icon {
+ display: none;
+}
+.nav-list li.highlight li.active > a:after,
+.nav-list li li.highlight.active > a:after,
+.nav-list li.highlight li.active > a:before,
+.nav-list li li.highlight.active > a:before {
+ display: none;
+}
+.nav-list > li.highlight.active > a:after,
+.nav-list > li.highlight.active > a:before {
+ display: block;
+}
+.no-skin .nav-list > li.highlight:hover,
+.no-skin .nav-list > li.highlight.active {
+ border-color: #c8d8e2;
+}
+.no-skin .nav-list > li.highlight:hover + li,
+.no-skin .nav-list > li.highlight.active + li {
+ border-top-color: #c8d8e2;
+}
+.no-skin .nav-list > li.highlight:hover > a,
+.no-skin .nav-list > li.highlight.active > a {
+ background-color: #FFF;
+}
+.no-skin .nav-list > li.highlight.active:after {
+ display: none;
+}
+.no-skin .nav-list > li.highlight.active:before {
+ display: block;
+ background-color: #4f90c2;
+}
+.no-skin .nav-list > li.highlight.active > a {
+ background-color: #f2f6f9 !important;
+}
+.no-skin .nav-list > li.highlight.active > a:before,
+.no-skin .nav-list > li.highlight.active > a:after {
+ display: block;
+ content: "";
+ position: absolute;
+ top: -1px;
+ right: -10px;
+ bottom: auto;
+ z-index: 1;
+ border-style: solid;
+ border-width: 20px 0 21px 10px;
+ border-color: transparent;
+}
+.no-skin .nav-list > li.highlight.active > a:before {
+ border-left-color: #a0bccd;
+ -moz-border-left-colors: #a0bccd;
+ right: -11px;
+}
+.no-skin .nav-list > li.highlight.active > a:after {
+ border-left-color: #f2f6f9;
+ -moz-border-left-colors: #f2f6f9;
+}
+.no-skin .nav-list li li.highlight.active > a {
+ background-color: #f2f6f9;
+}
+.no-skin .nav-list li li.highlight.active.open > a {
+ background-color: #FFF;
+}
+.no-skin .nav-list li li.highlight.active.open > a:hover {
+ background-color: #f1f5f9;
+}
+@media (min-width: 992px) {
+ .no-skin .sidebar.h-sidebar .nav-list > li.highlight.active > a:after {
+ display: block;
+ content: "";
+ position: absolute;
+ left: 0;
+ top: auto;
+ right: auto;
+ bottom: -2px;
+ left: 50%;
+ margin-left: -7px;
+ border-color: transparent;
+ -moz-border-right-colors: none;
+ -moz-border-left-colors: none;
+ -moz-border-top-colors: none;
+ border-width: 8px 7px;
+ border-bottom-color: #FFF;
+ -moz-border-bottom-colors: #FFF;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.highlight.active > a:before {
+ content: "";
+ position: absolute;
+ display: block;
+ left: 0;
+ top: auto;
+ right: auto;
+ bottom: -1px;
+ left: 50%;
+ margin-left: -7px;
+ border-width: 8px;
+ border-color: transparent;
+ -moz-border-right-colors: none;
+ -moz-border-left-colors: none;
+ -moz-border-top-colors: none;
+ border-bottom-color: #74add7;
+ -moz-border-bottom-colors: #74add7;
+ }
+ .no-skin .sidebar.h-sidebar .nav-list > li.highlight.active:hover > a:after,
+ .no-skin .sidebar.h-sidebar .nav-list > li.highlight.active.hover-show > a:after,
+ .no-skin .sidebar.h-sidebar .nav-list > li.highlight.active:hover > a:before,
+ .no-skin .sidebar.h-sidebar .nav-list > li.highlight.active.hover-show > a:before {
+ display: none;
+ }
+}
+@media (min-width: 992px) {
+ .sidebar.compact .nav-list li.highlight.active > a:after,
+ .sidebar.compact .nav-list li.highlight.active > a:before {
+ display: none;
+ }
+ .sidebar.compact.menu-min .nav-list li.highlight.active > a:after,
+ .sidebar.compact.menu-min .nav-list li.highlight.active > a:before {
+ display: block;
+ }
+}
+@media (min-width: 992px) {
+ .sidebar.h-sidebar .nav-list li.highlight.active > a:after,
+ .sidebar.h-sidebar .nav-list li.highlight.active > a:before {
+ display: block;
+ border-width: 8px !important;
+ -moz-border-left-colors: none !important;
+ -moz-border-right-colors: none !important;
+ border-left-color: transparent !important;
+ border-right-color: transparent !important;
+ }
+ .sidebar.h-sidebar .nav-list > li.highlight.active:hover > a:after,
+ .sidebar.h-sidebar .nav-list > li.highlight.active:hover > a:before {
+ display: none !important;
+ }
+}
+.sidebar-scroll .nav-list > li.active.highlight > a:after,
+.sidebar-scroll .nav-list > li.active.highlight > a:before {
+ display: none !important;
+}
+.onpage-help-backdrop {
+ position: absolute;
+ z-index: 99990;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: #000;
+ filter: alpha(opacity=5);
+ background-color: rgba(0, 0, 0, 0.05);
+}
+.onpage-help-section {
+ display: block;
+ position: absolute;
+ z-index: 100000;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#4DFFFFFF', endColorstr='#4DFFFFFF', GradientType=0);
+ background-color: rgba(255, 255, 255, 0.3);
+ border: 1px dashed #8BBCD3;
+ border-radius: 4px;
+ transition: background-color 0.2s, border-color 0.2s;
+ -webkit-transition: background-color 0.2s, border-color 0.2s;
+ text-align: center;
+ vertical-align: middle;
+ outline: none !important;
+}
+.onpage-help-section > .ie-hover-fix {
+ /* ie8-9 fix*/
+ display: block;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: #FFF;
+ filter: alpha(opacity=1);
+}
+.onpage-help-section:focus,
+.onpage-help-section:active {
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#33C9D8EA', endColorstr='#33C9D8EA', GradientType=0);
+ background-color: rgba(201, 216, 234, 0.2);
+ border-color: #77ACC4;
+}
+.onpage-help-section:hover {
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#66C9D8EA', endColorstr='#66C9D8EA', GradientType=0);
+ background-color: rgba(201, 216, 234, 0.4);
+ border-color: #77ACC4;
+ border-style: solid;
+}
+.onpage-help-section > .help-icon-1 {
+ font-size: 18px;
+ display: inline-block;
+ position: absolute;
+ z-index: 1;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ -webkit-transform: translate(-50%, -50%);
+ opacity: 0;
+ filter: alpha(opacity=0);
+ color: #FFF;
+ text-shadow: 0 0 2px black;
+ background-color: #85B8DB;
+ border: 2px solid #FFF;
+ border-radius: 100%;
+ box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.4);
+ width: 48px;
+ height: 48px;
+ line-height: 46px;
+ transition: opacity 0.2s;
+ -webkit-transition: opacity 0.2s;
+}
+.onpage-help-section:focus > .help-icon-1,
+.onpage-help-section:active > .help-icon-1 {
+ opacity: 0.5;
+}
+.onpage-help-section:hover > .help-icon-1 {
+ opacity: 1;
+ filter: alpha(opacity=100);
+}
+.onpage-help-section.help-section-small > .help-icon-1 {
+ font-size: 18px;
+ width: 28px;
+ height: 28px;
+ line-height: 26px;
+ border-radius: 12px;
+}
+.onpage-help-section.help-section-smaller > .help-icon-1 {
+ font-size: 14px;
+ width: 20px;
+ height: 20px;
+ line-height: 17px;
+ border-radius: 8px;
+}
+.onpage-help-section > .help-icon-2 {
+ position: absolute;
+ z-index: 2;
+ left: -4px;
+ top: -4px;
+ width: 18px;
+ height: 18px;
+ line-height: 16px;
+ display: block;
+ font-size: 16px;
+ color: orange;
+ background-color: #FFF;
+ border: 1px solid orange;
+ border-radius: 4px;
+ opacity: 1;
+ transition: all 0.2s;
+ -webkit-transition: all 0.2s;
+}
+.onpage-help-section:hover > .help-icon-2 {
+ color: #59A34E;
+ border-color: #59A34E;
+ transform: scale(1.25);
+ -webkit-transform: scale(1.25);
+}
+.onpage-help-modal {
+ z-index: 100010;
+}
+.onpage-help-modal + .modal-backdrop {
+ z-index: 100009;
+}
+.onpage-help-modal-buttons button {
+ border-radius: 100%;
+ border-width: 2px !important;
+}
+.onpage-help-modal-buttons button:focus {
+ outline: none !important;
+}
+.onpage-help-modal-buttons button.disabled {
+ transform: scale(0.9);
+ -webkit-transform: scale(0.9);
+}
+.onpage-help-content {
+ max-width: 800px;
+ margin: 0 auto;
+}
+.code-modal.onpage-help-modal .modal-dialog {
+ margin-top: 6px;
+ margin-bottom: 6px;
+}
+.code-modal.onpage-help-modal .modal-header {
+ padding-top: 6px;
+ padding-bottom: 6px;
+}
+.code-modal.onpage-help-modal .modal-body {
+ padding: 10px 12px;
+}
+.onpage-help-modal pre {
+ border-width: 0;
+ box-shadow: none;
+ border-radius: 0;
+ margin-top: 8px;
+}
+.onpage-help-modal .modal-title code {
+ font-size: 13px;
+}
+.onpage-help-modal .modal-body {
+ font-size: 14px;
+}
+@media print {
+ .navbar {
+ display: none !important;
+ /**
+ background: transparent none !important;
+ border-bottom: 1px solid #DDD;
+
+ .navbar-brand {
+ color: @text-color !important;
+ }
+
+ .ace-nav {
+ display: none !important;
+ }
+ */
+ }
+ .sidebar {
+ display: none !important;
+ }
+ .main-content {
+ margin-left: 0 !important;
+ margin-right: 0 !important;
+ }
+ .main-content .nav-search {
+ display: none !important;
+ }
+ .main-content .breadcrumbs {
+ float: right;
+ border-width: 0 !important;
+ }
+ .main-content .breadcrumbs .breadcrumb > li + li:before {
+ content: "/";
+ }
+ .main-content .breadcrumbs .breadcrumb .home-icon {
+ display: none;
+ }
+ .ace-settings-container {
+ display: none !important;
+ }
+ .footer {
+ width: 100%;
+ height: auto;
+ position: relative;
+ }
+ .footer .footer-inner,
+ .footer .footer-inner .footer-content {
+ width: 100%;
+ }
+ .btn-scroll-up {
+ display: none !important;
+ }
+ .btn,
+ .btn.btn-app {
+ background: transparent none !important;
+ border-width: 1px !important;
+ border-radius: 0 !important;
+ color: #555 !important;
+ }
+ .label {
+ border: 1px solid #666 !important;
+ }
+ .label[class*=arrowed]:before,
+ .label[class*=arrowed]:after {
+ display: none !important;
+ }
+}
diff --git a/web/public/assets/css/app-preview.css b/web/public/assets/css/app-preview.css
new file mode 100644
index 0000000..c0af011
--- /dev/null
+++ b/web/public/assets/css/app-preview.css
@@ -0,0 +1,25 @@
+.footer-tab-item {
+ width: 28px;
+ height: 24px;
+ background-size: contain;
+ background-repeat: no-repeat;
+}
+.middle-content {
+ background-size: contain;
+ background-repeat: no-repeat;
+}
+.middle-content-contacts {
+ background-image: url('../images/app-preview/contacts.png');
+}
+.middle-content-message {
+ background-image: url('../images/app-preview/message.png');
+}
+.middle-content-workbench {
+ background-image: url('../images/app-preview/workbench.png');
+}
+.middle-content-alert {
+ background-image: url('../images/app-preview/alert.png');
+}
+.middle-content-me {
+ background-image: url('../images/app-preview/me.png');
+}
\ No newline at end of file
diff --git a/web/public/assets/css/sm.css b/web/public/assets/css/sm.css
new file mode 100644
index 0000000..960a0a1
--- /dev/null
+++ b/web/public/assets/css/sm.css
@@ -0,0 +1,4685 @@
+/*!
+ * =====================================================
+ * SUI Mobile - http://m.sui.taobao.org/
+ *
+ * =====================================================
+ */
+
+/*.transition(@d) {
+ -webkit-transition-duration: @d;
+ transition-duration: @d;
+}
+.delay(@d) {
+ -webkit-transition-delay: @d;
+ transition-delay: @d;
+}
+.transform(@t) {
+ -webkit-transform: @t;
+ transform: @t;
+}
+.transform-origin(@to) {
+ -webkit-transform-origin: @to;
+ transform-origin: @to;
+}
+.translate3d(@x:0, @y:0, @z:0) {
+ -webkit-transform: translate3d(@x,@y,@z);
+ transform: translate3d(@x,@y,@z);
+}
+.animation(@a) {
+ -webkit-animation: @a;
+ animation: @a;
+}
+.border-box(){
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.box-shadow(@bs) {
+ -webkit-box-shadow: @bs;
+ box-shadow: @bs;
+}
+.animation-name(@name) {
+ -webkit-animation-name: @name;
+ -moz-animation-name: @name;
+ animation-name: @name;
+}
+.animation-duration(@duration) {
+ -webkit-animation-duration: @duration;
+ -moz-animation-duration: @duration;
+ animation-duration: @duration;
+}
+.animation-direction(@direction) {
+ -webkit-animation-direction: @direction;
+ -moz-animation-direction: @direction;
+ animation-direction: @direction;
+}
+*/
+html {
+ font-size: 20px;
+}
+@media only screen and (min-width: 400px) {
+ html {
+ font-size: 21.33333333px !important;
+ }
+}
+@media only screen and (min-width: 414px) {
+ html {
+ font-size: 22.08px !important;
+ }
+}
+@media only screen and (min-width: 480px) {
+ html {
+ font-size: 25.6px !important;
+ }
+}
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+html {
+ font-family: sans-serif;
+ -ms-text-size-adjust: 100%;
+ -webkit-text-size-adjust: 100%;
+}
+body {
+ margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+audio,
+canvas,
+progress,
+video {
+ display: inline-block;
+ vertical-align: baseline;
+}
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+[hidden],
+template {
+ display: none;
+}
+a {
+ background-color: transparent;
+}
+a:active,
+a:hover {
+ outline: 0;
+}
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+b,
+strong {
+ font-weight: bold;
+}
+dfn {
+ font-style: italic;
+}
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+mark {
+ background: #ff0;
+ color: #000;
+}
+small {
+ font-size: 80%;
+}
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+sup {
+ top: -0.5em;
+}
+sub {
+ bottom: -0.25em;
+}
+img {
+ border: 0;
+}
+svg:not(:root) {
+ overflow: hidden;
+}
+figure {
+ margin: 1em 40px;
+}
+hr {
+ box-sizing: content-box;
+ height: 0;
+}
+pre {
+ overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit;
+ font: inherit;
+ margin: 0;
+}
+button {
+ overflow: visible;
+}
+button,
+select {
+ text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button;
+ cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+input {
+ line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box;
+ padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: textfield;
+ box-sizing: content-box;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+legend {
+ border: 0;
+ padding: 0;
+}
+textarea {
+ overflow: auto;
+}
+optgroup {
+ font-weight: bold;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+td,
+th {
+ padding: 0;
+}
+* {
+ box-sizing: border-box;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+ -webkit-touch-callout: none;
+}
+body {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ font-family: "Helvetica Neue", Helvetica, sans-serif;
+ font-size: 0.85rem;
+ line-height: 1.5;
+ color: #3d4145;
+ background: #eeeeee;
+ overflow: hidden;
+}
+a,
+input,
+textarea,
+select,
+button {
+ outline: 0;
+}
+p {
+ margin: 1em 0;
+}
+a {
+ color: #0894ec;
+ text-decoration: none;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+a:active {
+ color: #0a8ddf;
+}
+.page {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: #eeeeee;
+ z-index: 2000;
+}
+.content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+}
+.bar-nav ~ .content {
+ top: 2.2rem;
+}
+.bar-header-secondary ~ .content {
+ top: 4.4rem;
+}
+.bar-footer ~ .content {
+ bottom: 2.2rem;
+}
+.bar-footer-secondary ~ .content {
+ bottom: 4.4rem;
+}
+.bar-tab ~ .content {
+ bottom: 2.5rem;
+}
+.bar-footer-secondary-tab ~ .content {
+ bottom: 4.7rem;
+}
+.content-padded {
+ margin: 0.5rem;
+}
+.text-center {
+ text-align: center;
+}
+.pull-left {
+ float: left;
+}
+.pull-right {
+ float: right;
+}
+.clearfix:before,
+.clearfix:after {
+ content: " ";
+ display: table;
+}
+.clearfix:after {
+ clear: both;
+}
+/* === Content Block === */
+.content-block {
+ margin: 1.75rem 0;
+ padding: 0 0.75rem;
+ color: #6d6d72;
+}
+.content-block-title {
+ position: relative;
+ overflow: hidden;
+ margin: 0;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ font-size: 0.7rem;
+ text-transform: uppercase;
+ line-height: 1;
+ color: #6d6d72;
+ margin: 1.75rem 0.75rem 0.5rem;
+}
+.content-block-title + .list-block,
+.content-block-title + .content-block,
+.content-block-title + .card {
+ margin-top: 0.5rem;
+}
+.content-block-inner {
+ background: #fff;
+ padding: 0.5rem 0.75rem;
+ margin-left: -0.75rem;
+ width: 100%;
+ position: relative;
+ color: #3d4145;
+}
+.content-block-inner:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #c8c7cc;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .content-block-inner:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .content-block-inner:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.content-block-inner:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #c8c7cc;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .content-block-inner:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .content-block-inner:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.content-block.inset {
+ margin-left: 0.75rem;
+ margin-right: 0.75rem;
+ border-radius: 0.35rem;
+}
+.content-block.inset .content-block-inner {
+ border-radius: 0.35rem;
+}
+.content-block.inset .content-block-inner:before {
+ display: none;
+}
+.content-block.inset .content-block-inner:after {
+ display: none;
+}
+@media all and (min-width: 768px) {
+ .content-block.tablet-inset {
+ margin-left: 0.75rem;
+ margin-right: 0.75rem;
+ border-radius: 0.35rem;
+ }
+ .content-block.tablet-inset .content-block-inner {
+ border-radius: 0.35rem;
+ }
+ .content-block.tablet-inset .content-block-inner:before {
+ display: none;
+ }
+ .content-block.tablet-inset .content-block-inner:after {
+ display: none;
+ }
+}
+/* === Grid === */
+.row {
+ overflow: hidden;
+ margin-left: -4%;
+}
+.row > [class*="col-"],
+.row > [class*="tablet-"] {
+ box-sizing: border-box;
+ float: left;
+}
+.row.no-gutter {
+ margin-left: 0;
+}
+.row .col-100 {
+ width: 96%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-100 {
+ width: 100%;
+ margin: 0;
+}
+.row .col-95 {
+ width: 91%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-95 {
+ width: 95%;
+ margin: 0;
+}
+.row .col-90 {
+ width: 86%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-90 {
+ width: 90%;
+ margin: 0;
+}
+.row .col-85 {
+ width: 81%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-85 {
+ width: 85%;
+ margin: 0;
+}
+.row .col-80 {
+ width: 76%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-80 {
+ width: 80%;
+ margin: 0;
+}
+.row .col-75 {
+ width: 71.00000000000001%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-75 {
+ width: 75%;
+ margin: 0;
+}
+.row .col-66 {
+ width: 62.66666666666666%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-66 {
+ width: 66.66666666666666%;
+ margin: 0;
+}
+.row .col-60 {
+ width: 55.99999999999999%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-60 {
+ width: 60%;
+ margin: 0;
+}
+.row .col-50 {
+ width: 46%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-50 {
+ width: 50%;
+ margin: 0;
+}
+.row .col-40 {
+ width: 36%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-40 {
+ width: 40%;
+ margin: 0;
+}
+.row .col-33 {
+ width: 29.333333333333332%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-33 {
+ width: 33.333333333333336%;
+ margin: 0;
+}
+.row .col-25 {
+ width: 21%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-25 {
+ width: 25%;
+ margin: 0;
+}
+.row .col-20 {
+ width: 16%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-20 {
+ width: 20%;
+ margin: 0;
+}
+.row .col-15 {
+ width: 10.999999999999998%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-15 {
+ width: 15%;
+ margin: 0;
+}
+.row .col-10 {
+ width: 6%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-10 {
+ width: 10%;
+ margin: 0;
+}
+.row .col-5 {
+ width: 1%;
+ margin-left: 4%;
+}
+.row.no-gutter .col-5 {
+ width: 5%;
+ margin: 0;
+}
+@media all and (min-width: 768px) {
+ .row {
+ margin-left: -2%;
+ }
+ .row .col-100 {
+ width: 98%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-100 {
+ width: 100%;
+ margin: 0;
+ }
+ .row .col-95 {
+ width: 93%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-95 {
+ width: 95%;
+ margin: 0;
+ }
+ .row .col-90 {
+ width: 87.99999999999999%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-90 {
+ width: 90%;
+ margin: 0;
+ }
+ .row .col-85 {
+ width: 82.99999999999999%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-85 {
+ width: 85%;
+ margin: 0;
+ }
+ .row .col-80 {
+ width: 78%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-80 {
+ width: 80%;
+ margin: 0;
+ }
+ .row .col-75 {
+ width: 73%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-75 {
+ width: 75%;
+ margin: 0;
+ }
+ .row .col-66 {
+ width: 64.66666666666666%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-66 {
+ width: 66.66666666666666%;
+ margin: 0;
+ }
+ .row .col-60 {
+ width: 58%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-60 {
+ width: 60%;
+ margin: 0;
+ }
+ .row .col-50 {
+ width: 48%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-50 {
+ width: 50%;
+ margin: 0;
+ }
+ .row .col-40 {
+ width: 38%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-40 {
+ width: 40%;
+ margin: 0;
+ }
+ .row .col-33 {
+ width: 31.333333333333332%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-33 {
+ width: 33.333333333333336%;
+ margin: 0;
+ }
+ .row .col-25 {
+ width: 23%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-25 {
+ width: 25%;
+ margin: 0;
+ }
+ .row .col-20 {
+ width: 18%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-20 {
+ width: 20%;
+ margin: 0;
+ }
+ .row .col-15 {
+ width: 13%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-15 {
+ width: 15%;
+ margin: 0;
+ }
+ .row .col-10 {
+ width: 8%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-10 {
+ width: 10%;
+ margin: 0;
+ }
+ .row .col-5 {
+ width: 3%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .col-5 {
+ width: 5%;
+ margin: 0;
+ }
+ .row .tablet-100 {
+ width: 98%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-100 {
+ width: 100%;
+ margin: 0;
+ }
+ .row .tablet-95 {
+ width: 93%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-95 {
+ width: 95%;
+ margin: 0;
+ }
+ .row .tablet-90 {
+ width: 87.99999999999999%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-90 {
+ width: 90%;
+ margin: 0;
+ }
+ .row .tablet-85 {
+ width: 82.99999999999999%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-85 {
+ width: 85%;
+ margin: 0;
+ }
+ .row .tablet-80 {
+ width: 78%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-80 {
+ width: 80%;
+ margin: 0;
+ }
+ .row .tablet-75 {
+ width: 73%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-75 {
+ width: 75%;
+ margin: 0;
+ }
+ .row .tablet-66 {
+ width: 64.66666666666666%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-66 {
+ width: 66.66666666666666%;
+ margin: 0;
+ }
+ .row .tablet-60 {
+ width: 58%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-60 {
+ width: 60%;
+ margin: 0;
+ }
+ .row .tablet-50 {
+ width: 48%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-50 {
+ width: 50%;
+ margin: 0;
+ }
+ .row .tablet-40 {
+ width: 38%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-40 {
+ width: 40%;
+ margin: 0;
+ }
+ .row .tablet-33 {
+ width: 31.333333333333332%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-33 {
+ width: 33.333333333333336%;
+ margin: 0;
+ }
+ .row .tablet-25 {
+ width: 23%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-25 {
+ width: 25%;
+ margin: 0;
+ }
+ .row .tablet-20 {
+ width: 18%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-20 {
+ width: 20%;
+ margin: 0;
+ }
+ .row .tablet-15 {
+ width: 13%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-15 {
+ width: 15%;
+ margin: 0;
+ }
+ .row .tablet-10 {
+ width: 8%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-10 {
+ width: 10%;
+ margin: 0;
+ }
+ .row .tablet-5 {
+ width: 3%;
+ margin-left: 2%;
+ }
+ .row.no-gutter .tablet-5 {
+ width: 5%;
+ margin: 0;
+ }
+}
+.color-default {
+ color: #3d4145;
+}
+.color-gray {
+ color: #999;
+}
+.color-primary {
+ color: #0894ec;
+}
+.color-success {
+ color: #4cd964;
+}
+.color-danger {
+ color: #f6383a;
+}
+.color-warning {
+ color: #ff6600;
+}
+.text-center {
+ text-align: center;
+}
+.bar {
+ position: absolute;
+ right: 0;
+ left: 0;
+ z-index: 10;
+ height: 2.2rem;
+ padding-right: 0.5rem;
+ padding-left: 0.5rem;
+ background-color: #f7f7f8;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+.bar:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .bar:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .bar:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.bar-header-secondary {
+ top: 2.2rem;
+}
+.bar-footer {
+ bottom: 0;
+}
+.bar-footer-secondary {
+ bottom: 2.2rem;
+}
+.bar-footer-secondary-tab {
+ bottom: 2.5rem;
+}
+.bar-footer:before,
+.bar-footer-secondary:before,
+.bar-footer-secondary-tab:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .bar-footer:before,
+ .bar-footer-secondary:before,
+ .bar-footer-secondary-tab:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .bar-footer:before,
+ .bar-footer-secondary:before,
+ .bar-footer-secondary-tab:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.bar-footer:after,
+.bar-footer-secondary:after,
+.bar-footer-secondary-tab:after {
+ display: none;
+}
+.bar-nav {
+ top: 0;
+}
+.title {
+ position: absolute;
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin: 0 -0.5rem;
+ font-size: 0.85rem;
+ font-weight: 500;
+ line-height: 2.2rem;
+ color: #3d4145;
+ text-align: center;
+ white-space: nowrap;
+}
+.title a {
+ color: inherit;
+}
+.bar-tab {
+ bottom: 0;
+ width: 100%;
+ height: 2.5rem;
+ padding: 0;
+ table-layout: fixed;
+}
+.bar-tab:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .bar-tab:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .bar-tab:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.bar-tab:after {
+ display: none;
+}
+.bar-tab .tab-item {
+ position: relative;
+ display: table-cell;
+ width: 1%;
+ height: 2.5rem;
+ color: #929292;
+ text-align: center;
+ vertical-align: middle;
+}
+.bar-tab .tab-item.active,
+.bar-tab .tab-item:active {
+ color: #0894ec;
+}
+.bar-tab .tab-item .badge {
+ position: absolute;
+ top: .1rem;
+ left: 50%;
+ z-index: 100;
+ height: .8rem;
+ min-width: .8rem;
+ padding: 0 .2rem;
+ font-size: .6rem;
+ line-height: .8rem;
+ color: white;
+ vertical-align: top;
+ background: red;
+ border-radius: .5rem;
+ margin-left: .1rem;
+}
+.bar-tab .tab-item .icon {
+ top: 0.05rem;
+ height: 1.2rem;
+ font-size: 1.2rem;
+ line-height: 1.2rem;
+ padding-top: 0;
+ padding-bottom: 0;
+}
+.bar-tab .tab-item .icon ~ .tab-label {
+ display: block;
+ font-size: 0.55rem;
+ position: relative;
+ top: 0.15rem;
+}
+.bar .button {
+ position: relative;
+ top: 0.35rem;
+ z-index: 20;
+ margin-top: 0;
+ font-weight: 400;
+}
+.bar .button.pull-right {
+ margin-left: 0.5rem;
+}
+.bar .button.pull-left {
+ margin-right: 0.5rem;
+}
+.bar .button-link {
+ top: 0;
+ padding: 0;
+ font-size: 0.8rem;
+ line-height: 2.2rem;
+ height: 2.2rem;
+ color: #0894ec;
+ border: 0;
+}
+.bar .button-link:active,
+.bar .button-link.active {
+ color: #0675bb;
+}
+.bar .button-block {
+ top: 0.35rem;
+ font-size: 0.8rem;
+ width: 100%;
+}
+.bar .button-nav.pull-left {
+ margin-left: -0.25rem;
+}
+.bar .button-nav.pull-left .icon-left-nav {
+ margin-right: -0.15rem;
+}
+.bar .button-nav.pull-right {
+ margin-right: -0.25rem;
+}
+.bar .button-nav.pull-right .icon-right-nav {
+ margin-left: -0.15rem;
+}
+.bar .icon {
+ position: relative;
+ z-index: 20;
+ padding: .5rem .1rem;
+ font-size: 1rem;
+ line-height: 1.2rem;
+}
+.bar .button .icon {
+ padding: 0;
+}
+.bar .title .icon {
+ padding: 0;
+}
+.bar .title .icon.icon-caret {
+ top: 0.2rem;
+ margin-left: -0.25rem;
+}
+.bar-footer .icon {
+ font-size: 1.2rem;
+ line-height: 1.2rem;
+}
+.bar input[type="search"] {
+ height: 1.45rem;
+ margin: 0.3rem 0;
+}
+.badge {
+ display: inline-block;
+ padding: 0.1rem 0.45rem 0.15rem;
+ font-size: 0.6rem;
+ line-height: 1;
+ color: #3d4145;
+ background-color: rgba(0, 0, 0, 0.15);
+ border-radius: 5rem;
+}
+.badge.badge-inverted {
+ padding: 0 0.25rem 0 0;
+ background-color: transparent;
+}
+/* === Lists === */
+.list-block {
+ margin: 1.75rem 0;
+ font-size: 0.85rem;
+ /*
+ .swipeout {
+ overflow: hidden;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d;
+ }
+ .swipeout.deleting {
+ transition-duration: 300ms;
+ .swipeout-content {
+ transform: translateX(-100%);
+ }
+ }
+ .swipeout.transitioning {
+ .swipeout-content, .swipeout-actions-right a, .swipeout-actions-left a, .swipeout-overswipe {
+ -webkit-transition: 300ms;
+ transition: 300ms;
+ }
+ }
+ .swipeout-content {
+ position: relative;
+ z-index: 10;
+ }
+ .swipeout-overswipe {
+ -webkit-transition: 200ms left;
+ transition: 200ms left;
+ }
+ .swipeout-actions-left, .swipeout-actions-right {
+ position: absolute;
+ top: 0;
+ height: 100%;
+ .flexbox();
+ a {
+ padding: 0 1.5rem;
+ color:#fff;
+ background: #c7c7cc;
+ .flexbox();
+ .align-items(center);
+ position: relative;
+ left: 0;
+ &:after {
+ content:'';
+ position: absolute;
+ top: 0;
+ width: 600%;
+ height: 100%;
+ background: inherit;
+ z-index: -1;
+ }
+ }
+ a.swipeout-delete {
+ background: @color-danger;
+ }
+ }
+ .swipeout-actions-right {
+ right: 0%;
+ transform: translateX(100%);
+ a:after {
+ left: 100%;
+ margin-left: -1px;
+ }
+ }
+ .swipeout-actions-left {
+ left: 0%;
+ transform: translateX(-100%);
+ a:after {
+ right: 100%;
+ margin-right: -1px;
+ }
+ }
+ */
+ /*
+ .sortable-handler {
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 1px;
+ z-index: 10;
+ background-repeat: no-repeat;
+ background-size: 0.9rem 0.6rem;
+ background-image: url("@{imgBaseUrl}/i-sortable-handler.png");
+ background-position: center;
+ width: 1.75rem;
+ opacity: 0;
+ visibility: hidden;
+ right: 0;
+ }
+ &.sortable {
+ .item-inner {
+ transition-duration: 300ms;
+ }
+ }
+ &.sortable-opened {
+ .sortable-handler {
+ visibility: visible;
+ opacity: 1;
+ }
+ .item-inner, .item-link .item-inner {
+ padding-right: 1.5rem;
+ }
+ .item-link .item-inner, .item-link .item-title-row {
+ background-image: none;
+ }
+ }
+ &.sortable-sorting {
+ li {
+ transition-duration: 300ms;
+ }
+ }
+ li.sorting {
+ z-index: 50;
+ background: rgba(255,255,255,0.8);
+ box-shadow: 0 0.1rem 0.4rem rgba(0,0,0,0.6);
+ transition-duration: 0ms;
+ .item-inner {
+ .hairline-remove(bottom);
+ }
+ }
+ */
+}
+.list-block ul {
+ background: #ffffff;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ position: relative;
+}
+.list-block ul:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .list-block ul:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .list-block ul:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.list-block ul:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .list-block ul:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .list-block ul:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.list-block ul ul {
+ padding-left: 2.25rem;
+}
+.list-block ul ul:before {
+ display: none;
+}
+.list-block ul ul:after {
+ display: none;
+}
+.list-block .align-top,
+.list-block .align-top .item-content,
+.list-block .align-top .item-inner {
+ -webkit-box-align: start;
+ -webkit-align-items: flex-start;
+ align-items: flex-start;
+}
+.list-block.inset {
+ margin-left: 0.75rem;
+ margin-right: 0.75rem;
+ border-radius: 0.35rem;
+}
+.list-block.inset .content-block-title {
+ margin-left: 0;
+ margin-right: 0;
+}
+.list-block.inset ul {
+ border-radius: 0.35rem;
+}
+.list-block.inset ul:before {
+ display: none;
+}
+.list-block.inset ul:after {
+ display: none;
+}
+.list-block.inset li:first-child > a {
+ border-radius: 0.35rem 0.35rem 0 0;
+}
+.list-block.inset li:last-child > a {
+ border-radius: 0 0 0.35rem 0.35rem;
+}
+.list-block.inset li:first-child:last-child > a {
+ border-radius: 0.35rem;
+}
+@media all and (min-width: 768px) {
+ .list-block.tablet-inset {
+ margin-left: 0.75rem;
+ margin-right: 0.75rem;
+ border-radius: 0.35rem;
+ }
+ .list-block.tablet-inset .content-block-title {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .list-block.tablet-inset ul {
+ border-radius: 0.35rem;
+ }
+ .list-block.tablet-inset ul:before {
+ display: none;
+ }
+ .list-block.tablet-inset ul:after {
+ display: none;
+ }
+ .list-block.tablet-inset li:first-child > a {
+ border-radius: 0.35rem 0.35rem 0 0;
+ }
+ .list-block.tablet-inset li:last-child > a {
+ border-radius: 0 0 0.35rem 0.35rem;
+ }
+ .list-block.tablet-inset li:first-child:last-child > a {
+ border-radius: 0.35rem;
+ }
+ .list-block.tablet-inset .content-block-title {
+ margin-left: 0;
+ margin-right: 0;
+ }
+ .list-block.tablet-inset ul {
+ border-radius: 0.35rem;
+ }
+ .list-block.tablet-inset ul:before {
+ display: none;
+ }
+ .list-block.tablet-inset ul:after {
+ display: none;
+ }
+ .list-block.tablet-inset li:first-child > a {
+ border-radius: 0.35rem 0.35rem 0 0;
+ }
+ .list-block.tablet-inset li:last-child > a {
+ border-radius: 0 0 0.35rem 0.35rem;
+ }
+ .list-block.tablet-inset li:first-child:last-child > a {
+ border-radius: 0.35rem;
+ }
+}
+.list-block li {
+ box-sizing: border-box;
+ position: relative;
+}
+.list-block .item-media {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-shrink: 0;
+ -ms-flex: 0 0 auto;
+ -webkit-flex-shrink: 0;
+ flex-shrink: 0;
+ -webkit-box-lines: single;
+ -moz-box-lines: single;
+ -webkit-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ box-sizing: border-box;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ padding-top: 0.35rem;
+ padding-bottom: 0.4rem;
+}
+.list-block .item-media i + i {
+ margin-left: 0.25rem;
+}
+.list-block .item-media i + img {
+ margin-left: 0.25rem;
+}
+.list-block .item-media + .item-inner {
+ margin-left: 0.75rem;
+}
+.list-block .item-inner {
+ padding-right: 0.75rem;
+ position: relative;
+ width: 100%;
+ padding-top: 0.4rem;
+ padding-bottom: 0.35rem;
+ min-height: 2.2rem;
+ overflow: hidden;
+ box-sizing: border-box;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-flex: 1;
+ -ms-flex: 1;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+}
+.list-block .item-inner:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .list-block .item-inner:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .list-block .item-inner:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.list-block .item-title {
+ -webkit-flex-shrink: 1;
+ -ms-flex: 0 1 auto;
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ white-space: nowrap;
+ position: relative;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 100%;
+}
+.list-block .item-title.label {
+ width: 35%;
+ -webkit-flex-shrink: 0;
+ -ms-flex: 0 0 auto;
+ -webkit-flex-shrink: 0;
+ flex-shrink: 0;
+ margin: 4px 0;
+}
+.list-block .item-input {
+ width: 100%;
+ margin-top: -0.4rem;
+ margin-bottom: -0.35rem;
+ -webkit-box-flex: 1;
+ -ms-flex: 1;
+ -webkit-flex-shrink: 1;
+ -ms-flex: 0 1 auto;
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+}
+.list-block .item-after {
+ white-space: nowrap;
+ color: #5f646e;
+ -webkit-flex-shrink: 0;
+ -ms-flex: 0 0 auto;
+ -webkit-flex-shrink: 0;
+ flex-shrink: 0;
+ margin-left: 0.25rem;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ max-height: 1.4rem;
+}
+.list-block .smart-select .item-after {
+ max-width: 70%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ position: relative;
+}
+.list-block .item-link {
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+ display: block;
+ color: inherit;
+}
+.list-block .item-link .item-inner {
+ padding-right: 1.5rem;
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUM0QzFDNzMyREM0MTFFNUJDNTI4OTMzMEE0RjBENzMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUM0QzFDNzQyREM0MTFFNUJDNTI4OTMzMEE0RjBENzMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1QzRDMUM3MTJEQzQxMUU1QkM1Mjg5MzMwQTRGMEQ3MyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1QzRDMUM3MjJEQzQxMUU1QkM1Mjg5MzMwQTRGMEQ3MyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pjs2Bb4AAAItSURBVHjazJhbK0RRGIb3DIOU/AG5kUTOgxmHceFGKf6BO+Vf+E8KKYcYg3FuMpNIDhFJXJAcp/GtvKumrzVs+zBrvfU2u689q6d3rb33+lYgl8tZvymZ3JOX7eQp8gT50fJA0Wj4z3tKbY5VR14hV5ObyWLkZ6sICtq4p4V8CjihevIWucoUQJFUmtUayTvkShMAL5DiGqs3IMlK3YBSgwrIZkBWmAAoIRMKyG2/IIMO/hMjbygepCS53ARAoQHyOqu1YbrLTADMAXJbASmSDOkGlOpTQHaQN72CdAuYBeQuq4cBWaIbUEJGC0Am3UIGPVoqMsk9Vu/CwxTQDSj0iSQPWD2C6Q7oBhT6AmRKAZkwAVDoowBkn+LdqQVQ6A2QhwrIuAmAEjKi2KrF/jPdfgIKveI7Pcfq/eSMCYBSD4pakymA0+RxVrsn15oAOEMeY7Vbcif5ys4ApT7CzZJHWO2G3I1fSyfgPHmY1a7x6bvT/ZpZUMBdOoHzI8El8pCiK+wq8CQXNcFlBdw51tyD00G9SnAVHV++zgDn6hzHiwTjCrgTTKvrQya3Ca5jA5CvY3IP+UlnTxJEb8zhjpDck1cL20mCAcBFWD2D2ovOvjiERojDpTGtnsL9N8EQegt+LJrC5vRN59lMORp0DrePNH2BswvYivXVzuoHSO7dz+2QHcAa6+eMOl87WHOffm8m7QCK7foog+tFi2mZACg3npPkRUxrtkitgvUtwAA5A3LWdzPizwAAAABJRU5ErkJggg==);
+ background-size: 0.7rem;
+ background-repeat: no-repeat;
+ background-position: 97% center;
+ background-position: -webkit-calc(100% - .5rem) center;
+ background-position: calc(100% - .5rem) center;
+}
+html:not(.watch-active-state) .list-block .item-link:active,
+.list-block .item-link.active-state {
+ -webkit-transition-duration: 0ms;
+ transition-duration: 0ms;
+ background-color: #d9d9d9;
+}
+html:not(.watch-active-state) .list-block .item-link:active .item-inner:after,
+.list-block .item-link.active-state .item-inner:after {
+ background-color: transparent;
+}
+.list-block .item-link.list-button {
+ padding: 0 0.75rem;
+ text-align: center;
+ color: #0894ec;
+ display: block;
+ line-height: 2.15rem;
+}
+.list-block .item-link.list-button:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .list-block .item-link.list-button:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .list-block .item-link.list-button:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.list-block .item-content {
+ box-sizing: border-box;
+ padding-left: 0.75rem;
+ min-height: 2.2rem;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+}
+.list-block .list-block-label {
+ margin: 0.5rem 0 1.75rem;
+ padding: 0 0.75rem;
+ font-size: 0.7rem;
+ color: #5f646e;
+}
+.list-block .item-subtitle {
+ font-size: 0.75rem;
+ position: relative;
+ overflow: hidden;
+ white-space: nowrap;
+ max-width: 100%;
+ text-overflow: ellipsis;
+}
+.list-block .item-text {
+ font-size: 0.75rem;
+ color: #5f646e;
+ line-height: 1.05rem;
+ position: relative;
+ overflow: hidden;
+ height: 2.1rem;
+ text-overflow: ellipsis;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ display: -webkit-box;
+}
+.list-block.media-list .item-title {
+ font-weight: 500;
+}
+.list-block.media-list .item-inner {
+ display: block;
+ padding-top: 0.5rem;
+ padding-bottom: 0.45rem;
+ -webkit-align-self: stretch;
+ align-self: stretch;
+}
+.list-block.media-list .item-media {
+ padding-top: 0.45rem;
+ padding-bottom: 0.5rem;
+}
+.list-block.media-list .item-media img {
+ display: block;
+}
+.list-block.media-list .item-title-row {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+}
+.list-block .list-group ul:after,
+.list-block .list-group ul:before {
+ z-index: 11;
+}
+.list-block .list-group + .list-group ul:before {
+ display: none;
+}
+.list-block .item-divider,
+.list-block .list-group-title {
+ background: #f7f7f7;
+ margin-top: -1px;
+ padding: 0.2rem 0.75rem;
+ white-space: nowrap;
+ position: relative;
+ max-width: 100%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ color: #e7e7e7;
+}
+.list-block .item-divider:before,
+.list-block .list-group-title:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .list-block .item-divider:before,
+ .list-block .list-group-title:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .list-block .item-divider:before,
+ .list-block .list-group-title:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.list-block .list-group-title {
+ position: relative;
+ position: -webkit-sticky;
+ position: -moz-sticky;
+ position: sticky;
+ top: 0;
+ z-index: 20;
+ margin-top: 0;
+}
+.list-block .list-group-title:before {
+ display: none;
+}
+.list-block li:last-child .list-button:after {
+ display: none;
+}
+.list-block li:last-child .item-inner:after,
+.list-block li:last-child li:last-child .item-inner:after {
+ display: none;
+}
+.list-block li li:last-child .item-inner:after,
+.list-block li:last-child li .item-inner:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e7e7e7;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .list-block li li:last-child .item-inner:after,
+ .list-block li:last-child li .item-inner:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .list-block li li:last-child .item-inner:after,
+ .list-block li:last-child li .item-inner:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+/* === Forms === */
+.list-block input[type="text"],
+.list-block input[type="password"],
+.list-block input[type="search"],
+.list-block input[type="email"],
+.list-block input[type="tel"],
+.list-block input[type="url"],
+.list-block input[type="date"],
+.list-block input[type="datetime-local"],
+.list-block input[type="time"],
+.list-block input[type="number"],
+.list-block select,
+.list-block textarea {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+ box-sizing: border-box;
+ border: none;
+ background: none;
+ border-radius: 0 0 0 0;
+ box-shadow: none;
+ display: block;
+ padding: 0 0 0 0.25rem;
+ margin: 0;
+ width: 100%;
+ height: 2.15rem;
+ color: #3d4145;
+ font-size: 0.85rem;
+ font-family: inherit;
+}
+.list-block input[type="date"],
+.list-block input[type="datetime-local"] {
+ line-height: 2.2rem;
+}
+.list-block select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+}
+.list-block .label {
+ vertical-align: top;
+}
+.list-block textarea {
+ height: 5rem;
+ resize: none;
+ line-height: 1.4;
+ padding-top: 0.4rem;
+ padding-bottom: 0.35rem;
+}
+.label-switch {
+ display: inline-block;
+ vertical-align: middle;
+ width: 2.6rem;
+ border-radius: 0.8rem;
+ box-sizing: border-box;
+ height: 1.6rem;
+ position: relative;
+ cursor: pointer;
+ -webkit-align-self: center;
+ align-self: center;
+}
+.label-switch .checkbox {
+ width: 2.6rem;
+ border-radius: 0.8rem;
+ box-sizing: border-box;
+ height: 1.6rem;
+ background: #e5e5e5;
+ z-index: 0;
+ margin: 0;
+ padding: 0;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+ border: none;
+ cursor: pointer;
+ position: relative;
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+}
+.label-switch .checkbox:before {
+ content: ' ';
+ position: absolute;
+ left: 0.1rem;
+ top: 0.1rem;
+ width: 2.4rem;
+ border-radius: 0.8rem;
+ box-sizing: border-box;
+ height: 1.4rem;
+ background: #fff;
+ z-index: 1;
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+ -webkit-transform: scale(1);
+ transform: scale(1);
+}
+.label-switch .checkbox:after {
+ content: ' ';
+ height: 1.4rem;
+ width: 1.4rem;
+ border-radius: 1.4rem;
+ background: #fff;
+ position: absolute;
+ z-index: 2;
+ top: 0.1rem;
+ left: 0.1rem;
+ box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.4);
+ -webkit-transform: translateX(0px);
+ transform: translateX(0px);
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+}
+.label-switch input[type="checkbox"] {
+ display: none;
+}
+.label-switch input[type="checkbox"]:checked + .checkbox {
+ background: #4cd964;
+}
+.label-switch input[type="checkbox"]:checked + .checkbox:before {
+ -webkit-transform: scale(0);
+ transform: scale(0);
+}
+.label-switch input[type="checkbox"]:checked + .checkbox:after {
+ -webkit-transform: translateX(1.1rem);
+ transform: translateX(1.1rem);
+}
+html.android .label-switch input[type="checkbox"] + .checkbox {
+ -webkit-transition-duration: 0;
+ transition-duration: 0;
+}
+html.android .label-switch input[type="checkbox"] + .checkbox:after,
+html.android .label-switch input[type="checkbox"] + .checkbox:before {
+ -webkit-transition-duration: 0;
+ transition-duration: 0;
+}
+.range-slider {
+ width: 100%;
+ position: relative;
+ overflow: hidden;
+ padding-left: 0.15rem;
+ padding-right: 0.15rem;
+ margin-left: -1px;
+ -webkit-align-self: center;
+ align-self: center;
+}
+.range-slider input[type="range"] {
+ position: relative;
+ height: 1.4rem;
+ width: 100%;
+ margin: 0.2rem 0 0.25rem 0;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+ background: -webkit-gradient(linear, 50% 0, 50% 100%, color-stop(0, #b7b8b7), color-stop(100%, #b7b8b7));
+ background: -webkit-linear-gradient(left, #b7b8b7 0, #b7b8b7 100%);
+ background: linear-gradient(to right, #b7b8b7 0, #b7b8b7 100%);
+ background-position: center;
+ background-size: 100% 0.1rem;
+ background-repeat: no-repeat;
+ outline: 0;
+}
+.range-slider input[type="range"]:after {
+ height: 0.1rem;
+ background: #fff;
+ content: ' ';
+ width: 0.25rem;
+ top: 50%;
+ margin-top: -1px;
+ left: -0.25rem;
+ z-index: 1;
+ position: absolute;
+}
+.range-slider input[type="range"]::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+ border: none;
+ height: 1.4rem;
+ width: 1.4rem;
+ position: relative;
+ background: none;
+}
+.range-slider input[type="range"]::-webkit-slider-thumb:after {
+ height: 1.4rem;
+ width: 1.4rem;
+ border-radius: 1.4rem;
+ background: #fff;
+ z-index: 10;
+ box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.4);
+ position: absolute;
+ left: 0;
+ top: 0;
+ content: ' ';
+}
+.range-slider input[type="range"]::-webkit-slider-thumb:before {
+ position: absolute;
+ top: 50%;
+ right: 100%;
+ width: 100rem;
+ height: 0.1rem;
+ margin-top: -1px;
+ z-index: 1;
+ background: #0894ec;
+ content: ' ';
+}
+label.label-checkbox {
+ cursor: pointer;
+}
+label.label-checkbox i.icon-form-checkbox {
+ width: 1.1rem;
+ height: 1.1rem;
+ position: relative;
+ border-radius: 1.1rem;
+ border: 1px solid #c7c7cc;
+ box-sizing: border-box;
+}
+label.label-checkbox i.icon-form-checkbox:after {
+ content: ' ';
+ position: absolute;
+ left: 50%;
+ margin-left: -0.3rem;
+ top: 50%;
+ margin-top: -0.2rem;
+ width: 0.6rem;
+ height: 0.45rem;
+}
+label.label-checkbox input[type="checkbox"],
+label.label-checkbox input[type="radio"] {
+ display: none;
+}
+label.label-checkbox input[type="checkbox"]:checked + .item-media i.icon-form-checkbox,
+label.label-checkbox input[type="radio"]:checked + .item-media i.icon-form-checkbox {
+ border: none;
+ background-color: #0894ec;
+}
+label.label-checkbox input[type="checkbox"]:checked + .item-media i.icon-form-checkbox:after,
+label.label-checkbox input[type="radio"]:checked + .item-media i.icon-form-checkbox:after {
+ background: no-repeat center;
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20x%3D'0px'%20y%3D'0px'%20viewBox%3D'0%200%2012%209'%20xml%3Aspace%3D'preserve'%3E%3Cpolygon%20fill%3D'%23ffffff'%20points%3D'12%2C0.7%2011.3%2C0%203.9%2C7.4%200.7%2C4.2%200%2C4.9%203.9%2C8.8%203.9%2C8.8%203.9%2C8.8%20'%2F%3E%3C%2Fsvg%3E");
+ background-size: 0.6rem 0.45rem;
+}
+label.label-checkbox {
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+}
+html:not(.watch-active-state) label.label-checkbox:active,
+label.label-checkbox.active-state {
+ -webkit-transition: 0ms;
+ transition: 0ms;
+ background-color: #d9d9d9;
+}
+html:not(.watch-active-state) label.label-checkbox:active .item-inner:after,
+label.label-checkbox.active-state .item-inner:after {
+ background-color: transparent;
+}
+.smart-select select {
+ display: none;
+}
+/* === Search Bar === */
+.searchbar {
+ padding: 8px 0;
+ overflow: hidden;
+ height: 2.2rem;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+}
+.searchbar .searchbar-cancel {
+ margin-right: -3rem;
+ width: 2.2rem;
+ float: right;
+ height: 1.4rem;
+ line-height: 1.4rem;
+ text-align: center;
+ -webkit-transition: all .3s;
+ transition: all .3s;
+ opacity: 0;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.searchbar .search-input {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ margin-right: 0;
+ -webkit-transition: all .3s;
+ transition: all .3s;
+}
+.searchbar .search-input input {
+ margin: 0;
+ height: 1.4rem;
+}
+.searchbar.searchbar-active .searchbar-cancel {
+ margin-right: 0;
+ opacity: 1;
+}
+.searchbar.searchbar-active .searchbar-cancel + .search-input {
+ margin-right: 2.5rem;
+}
+.search-input {
+ position: relative;
+}
+.search-input input {
+ box-sizing: border-box;
+ width: 100%;
+ height: 1.4rem;
+ display: block;
+ border: none;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ border-radius: 0.25rem;
+ font-family: inherit;
+ color: #3d4145;
+ font-size: 0.7rem;
+ font-weight: normal;
+ padding: 0 0.5rem;
+ background-color: #fff;
+ border: 1px solid #b4b4b4;
+}
+.search-input input::-webkit-input-placeholder {
+ color: #cccccc;
+ opacity: 1;
+}
+.search-input .icon {
+ position: absolute;
+ font-size: 0.9rem;
+ color: #b4b4b4;
+ top: 50%;
+ left: 0.3rem;
+ -webkit-transform: translate3D(0, -50%, 0);
+ transform: translate3D(0, -50%, 0);
+}
+.search-input label + input {
+ padding-left: 1.4rem;
+}
+.bar .searchbar {
+ margin: 0 -0.5rem;
+ padding: 0.4rem 0.5rem;
+ background: rgba(0, 0, 0, 0.1);
+}
+.bar .searchbar .search-input input {
+ border: 0;
+}
+.bar .searchbar .searchbar-cancel {
+ color: #5f646e;
+}
+.button {
+ border: 1px solid #0894ec;
+ color: #0894ec;
+ text-decoration: none;
+ text-align: center;
+ display: block;
+ border-radius: 0.25rem;
+ line-height: 1.25rem;
+ box-sizing: border-box;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+ background: none;
+ padding: 0 0.5rem;
+ margin: 0;
+ height: 1.35rem;
+ white-space: nowrap;
+ position: relative;
+ text-overflow: ellipsis;
+ font-size: 0.7rem;
+ font-family: inherit;
+ cursor: pointer;
+}
+input[type="submit"].button,
+input[type="button"].button {
+ width: 100%;
+}
+.button:active {
+ color: #0a8ddf;
+ border-color: #0a8ddf;
+}
+.button.button-round {
+ border-radius: 1.25rem;
+}
+.button.active,
+.button.active:active {
+ color: #0a8ddf;
+ border-color: #0a8ddf;
+}
+.button.button-big {
+ font-size: 0.85rem;
+ height: 2.4rem;
+ line-height: 2.3rem;
+}
+.button.button-fill {
+ color: #fff;
+ background: #0894ec;
+ border: none;
+ line-height: 1.35rem;
+}
+.button.button-fill.active,
+.button.button-fill:active {
+ background: #0a8ddf;
+}
+.button.button-fill.button-big {
+ line-height: 2.4rem;
+}
+.button .button-link {
+ padding-top: 0.3rem;
+ padding-bottom: 0.3rem;
+ color: #0894ec;
+ background-color: transparent;
+ border: 0;
+}
+.button i.icon:first-child {
+ margin-right: 0.5rem;
+}
+.button i.icon:last-child {
+ margin-left: 0.5rem;
+}
+.button i.icon:first-child:last-child {
+ margin-left: 0;
+ margin-right: 0;
+}
+.button-light {
+ border-color: #cccccc;
+ color: #cccccc;
+ color: #5f646e;
+}
+.button-light:active {
+ border-color: #0a8ddf;
+ color: #0a8ddf;
+}
+.button-light.button-fill {
+ color: white;
+ background-color: #cccccc;
+}
+.button-light.button-fill:active {
+ background-color: #0a8ddf;
+}
+.button-dark {
+ border-color: #6e727b;
+ color: #6e727b;
+ color: #5f646e;
+}
+.button-dark:active {
+ border-color: #0a8ddf;
+ color: #0a8ddf;
+}
+.button-dark.button-fill {
+ color: white;
+ background-color: #6e727b;
+}
+.button-dark.button-fill:active {
+ background-color: #0a8ddf;
+}
+.button-success {
+ border-color: #4cd964;
+ color: #4cd964;
+}
+.button-success:active {
+ border-color: #2ac845;
+ color: #2ac845;
+}
+.button-success.button-fill {
+ color: white;
+ background-color: #4cd964;
+}
+.button-success.button-fill:active {
+ background-color: #2ac845;
+}
+.button-danger {
+ border-color: #f6383a;
+ color: #f6383a;
+}
+.button-danger:active {
+ border-color: #f00b0d;
+ color: #f00b0d;
+}
+.button-danger.button-fill {
+ color: white;
+ background-color: #f6383a;
+}
+.button-danger.button-fill:active {
+ background-color: #f00b0d;
+}
+.button-warning {
+ border-color: #ff6600;
+ color: #ff6600;
+}
+.button-warning:active {
+ border-color: #cc5200;
+ color: #cc5200;
+}
+.button-warning.button-fill {
+ color: white;
+ background-color: #ff6600;
+}
+.button-warning.button-fill:active {
+ background-color: #cc5200;
+}
+.button.disabled,
+.button.button-primary.disabled,
+.button.button-success.disabled,
+.button.button-danger.disabled,
+.button.button-warning.disabled {
+ border-color: #c8c9cb;
+ color: #c8c9cb;
+ cursor: not-allowed;
+}
+.button.disabled:active,
+.button.button-primary.disabled:active,
+.button.button-success.disabled:active,
+.button.button-danger.disabled:active,
+.button.button-warning.disabled:active {
+ border-color: #c8c9cb;
+ color: #c8c9cb;
+}
+.button.disabled.button-fill,
+.button.button-primary.disabled.button-fill,
+.button.button-success.disabled.button-fill,
+.button.button-danger.disabled.button-fill,
+.button.button-warning.disabled.button-fill {
+ color: white;
+ background-color: #c8c9cb;
+}
+.button.disabled.button-fill:active,
+.button.button-primary.disabled.button-fill:active,
+.button.button-success.disabled.button-fill:active,
+.button.button-danger.disabled.button-fill:active,
+.button.button-warning.disabled.button-fill:active {
+ background-color: #c8c9cb;
+}
+.buttons-row,
+.buttons-tab {
+ -webkit-align-self: center;
+ align-self: center;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-lines: single;
+ -moz-box-lines: single;
+ -webkit-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+}
+.buttons-row .button {
+ border-radius: 0 0 0 0;
+ margin-left: -1px;
+ width: 100%;
+ -webkit-box-flex: 1;
+ -ms-flex: 1;
+ border-color: #0894ec;
+ color: #0894ec;
+}
+.buttons-row .button.active {
+ background-color: #0894ec;
+ color: white;
+ z-index: 90;
+}
+.buttons-row .button:first-child {
+ border-radius: 0.25rem 0 0 0.25rem;
+ margin-left: 0;
+ border-left-width: 1px;
+ border-left-style: solid;
+}
+.buttons-row .button:last-child {
+ border-radius: 0 0.25rem 0.25rem 0;
+}
+.buttons-row .button.button-round:first-child {
+ border-radius: 1.35rem 0 0 1.35rem;
+}
+.buttons-row .button.button-round:last-child {
+ border-radius: 0 1.35rem 1.35rem 0;
+}
+.buttons-tab {
+ background: white;
+ position: relative;
+}
+.buttons-tab:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #d0d0d0;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .buttons-tab:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .buttons-tab:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.buttons-tab .button {
+ color: #5f646e;
+ font-size: 0.8rem;
+ width: 100%;
+ height: 2rem;
+ line-height: 2rem;
+ -webkit-box-flex: 1;
+ -ms-flex: 1;
+ border: 0;
+ border-bottom: 2px solid transparent;
+ border-radius: 0;
+}
+.buttons-tab .button.active {
+ color: #0894ec;
+ border-color: #0894ec;
+ z-index: 100;
+}
+.buttons-fixed {
+ position: fixed;
+ z-index: 99;
+ width: 100%;
+}
+/* === Tabs === */
+.tabs .tab {
+ display: none;
+}
+.tabs .tab.active {
+ display: block;
+}
+.tabs-animated-wrap {
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+ height: 100%;
+}
+.tabs-animated-wrap > .tabs {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ height: 100%;
+ -webkit-transition: 300ms;
+ transition: 300ms;
+}
+.tabs-animated-wrap > .tabs > .tab {
+ width: 100%;
+ display: block;
+ -webkit-flex-shrink: 0;
+ -ms-flex: 0 0 auto;
+ -webkit-flex-shrink: 0;
+ flex-shrink: 0;
+}
+/* === Pages === */
+.page,
+.page-group {
+ box-sizing: border-box;
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background: #efeff4;
+ display: none;
+ overflow: hidden;
+}
+.page.page-current,
+.page-group.page-current,
+.page.page-visible,
+.page-group.page-visible,
+.page.page-from-center-to-left,
+.page-group.page-from-center-to-left,
+.page.page-from-center-to-right,
+.page-group.page-from-center-to-right,
+.page.page-from-right-to-center,
+.page-group.page-from-right-to-center,
+.page.page-from-left-to-center,
+.page-group.page-from-left-to-center {
+ display: block;
+}
+.page.page-current,
+.page-group.page-current {
+ overflow: hidden;
+}
+.page-group {
+ display: block;
+}
+.page-transitioning,
+.page-transitioning .swipeback-page-shadow {
+ -webkit-transition: 400ms;
+ transition: 400ms;
+}
+.page-from-right-to-center {
+ -webkit-animation: pageFromRightToCenter 400ms forwards;
+ animation: pageFromRightToCenter 400ms forwards;
+ z-index: 2002;
+}
+.page-from-center-to-right {
+ -webkit-animation: pageFromCenterToRight 400ms forwards;
+ animation: pageFromCenterToRight 400ms forwards;
+ z-index: 2002;
+}
+@-webkit-keyframes pageFromRightToCenter {
+ from {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ opacity: .9;
+ }
+ to {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ opacity: 1;
+ }
+}
+@keyframes pageFromRightToCenter {
+ from {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ opacity: .9;
+ }
+ to {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ opacity: 1;
+ }
+}
+@-webkit-keyframes pageFromCenterToRight {
+ from {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ opacity: 1;
+ }
+ to {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ opacity: .9;
+ }
+}
+@keyframes pageFromCenterToRight {
+ from {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ opacity: 1;
+ }
+ to {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ opacity: .9;
+ }
+}
+.page-from-center-to-left {
+ -webkit-animation: pageFromCenterToLeft 400ms forwards;
+ animation: pageFromCenterToLeft 400ms forwards;
+}
+.page-from-left-to-center {
+ -webkit-animation: pageFromLeftToCenter 400ms forwards;
+ animation: pageFromLeftToCenter 400ms forwards;
+}
+@-webkit-keyframes pageFromCenterToLeft {
+ from {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ }
+ to {
+ opacity: 0.5;
+ -webkit-transform: translate3d(-20%, 0, 0);
+ transform: translate3d(-20%, 0, 0);
+ }
+}
+@keyframes pageFromCenterToLeft {
+ from {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ }
+ to {
+ opacity: 0.5;
+ -webkit-transform: translate3d(-20%, 0, 0);
+ transform: translate3d(-20%, 0, 0);
+ }
+}
+@-webkit-keyframes pageFromLeftToCenter {
+ from {
+ opacity: .5;
+ -webkit-transform: translate3d(-20%, 0, 0);
+ transform: translate3d(-20%, 0, 0);
+ }
+ to {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ }
+}
+@keyframes pageFromLeftToCenter {
+ from {
+ opacity: .5;
+ -webkit-transform: translate3d(-20%, 0, 0);
+ transform: translate3d(-20%, 0, 0);
+ }
+ to {
+ opacity: 1;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ }
+}
+.content-inner {
+ box-sizing: border-box;
+ border-top: 1px solid transparent;
+ margin-top: -1px;
+ padding-bottom: 0.5rem;
+}
+.javascript-scroll {
+ overflow: hidden;
+}
+/* === Pull To Refresh === */
+.pull-to-refresh-layer {
+ position: relative;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 2.2rem;
+}
+.pull-to-refresh-layer .preloader {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ margin-left: -0.5rem;
+ margin-top: -0.5rem;
+ visibility: hidden;
+}
+.pull-to-refresh-layer .pull-to-refresh-arrow {
+ width: 0.65rem;
+ height: 1rem;
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ margin-left: -0.15rem;
+ margin-top: -0.5rem;
+ background: no-repeat center;
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2026%2040'%3E%3Cpolygon%20points%3D'9%2C22%209%2C0%2017%2C0%2017%2C22%2026%2C22%2013.5%2C40%200%2C22'%20fill%3D'%238c8c8c'%2F%3E%3C%2Fsvg%3E");
+ background-size: 0.65rem 1rem;
+ z-index: 10;
+ -webkit-transform: rotate(0deg) translate3d(0, 0, 0);
+ transform: rotate(0deg) translate3d(0, 0, 0);
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+}
+.pull-to-refresh-content {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.pull-to-refresh-content.transitioning,
+.pull-to-refresh-content.refreshing {
+ -webkit-transition: -webkit-transform 400ms;
+ transition: transform 400ms;
+}
+.pull-to-refresh-content:not(.refreshing) .pull-to-refresh-layer .preloader {
+ -webkit-animation: none;
+ animation: none;
+}
+.pull-to-refresh-content.refreshing .pull-to-refresh-arrow {
+ visibility: hidden;
+ -webkit-transition-duration: 0ms;
+ transition-duration: 0ms;
+}
+.pull-to-refresh-content.refreshing .preloader {
+ visibility: visible;
+}
+.pull-to-refresh-content.pull-up .pull-to-refresh-arrow {
+ -webkit-transform: rotate(180deg) translate3d(0, 0, 0);
+ transform: rotate(180deg) translate3d(0, 0, 0);
+}
+.pull-to-refresh-content {
+ top: -2.2rem;
+}
+.pull-to-refresh-content.refreshing {
+ -webkit-transform: translate3d(0, 2.2rem, 0);
+ transform: translate3d(0, 2.2rem, 0);
+}
+.bar-nav ~ .pull-to-refresh-content,
+.bar-footer ~ .pull-to-refresh-content,
+.bar-tab ~ .pull-to-refresh-content {
+ top: 0;
+}
+.bar-nav ~ .pull-to-refresh-content.refreshing,
+.bar-footer ~ .pull-to-refresh-content.refreshing,
+.bar-tab ~ .pull-to-refresh-content.refreshing {
+ -webkit-transform: translate3d(0, 2.2rem, 0);
+ transform: translate3d(0, 2.2rem, 0);
+}
+.bar-header-secondary ~ .pull-to-refresh-content,
+.bar-footer-secondary ~ .pull-to-refresh-content {
+ top: 2.2rem;
+}
+.infinite-scroll-preloader {
+ margin: 0.5rem;
+ text-align: center;
+}
+.infinite-scroll-preloader .preloader {
+ width: 1.5rem;
+ height: 1.5rem;
+}
+.infinite-scroll-top .infinite-scroll-preloader {
+ position: absolute;
+ width: 100%;
+ top: 0;
+ margin: 0;
+}
+/* === Modals === */
+.modal-overlay,
+.preloader-indicator-overlay,
+.popup-overlay {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.4);
+ z-index: 10600;
+ visibility: hidden;
+ opacity: 0;
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms;
+}
+.modal-overlay.modal-overlay-visible,
+.preloader-indicator-overlay.modal-overlay-visible,
+.popup-overlay.modal-overlay-visible {
+ visibility: visible;
+ opacity: 1;
+}
+.popup-overlay {
+ z-index: 10200;
+}
+.modal {
+ width: 13.5rem;
+ position: absolute;
+ z-index: 11000;
+ left: 50%;
+ margin-left: -6.75rem;
+ margin-top: 0;
+ top: 50%;
+ text-align: center;
+ border-radius: 0.35rem;
+ opacity: 0;
+ -webkit-transform: translate3d(0, 0, 0) scale(1.185);
+ transform: translate3d(0, 0, 0) scale(1.185);
+ -webkit-transition-property: -webkit-transform, opacity;
+ transition-property: transform, opacity;
+ color: #3d4145;
+ display: none;
+}
+.modal.modal-in {
+ opacity: 1;
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms;
+ -webkit-transform: translate3d(0, 0, 0) scale(1);
+ transform: translate3d(0, 0, 0) scale(1);
+}
+.modal.modal-out {
+ opacity: 0;
+ z-index: 10999;
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms;
+ -webkit-transform: translate3d(0, 0, 0) scale(0.815);
+ transform: translate3d(0, 0, 0) scale(0.815);
+}
+.modal-inner {
+ padding: 0.75rem;
+ border-radius: 0.35rem 0.35rem 0 0;
+ position: relative;
+ background: #e8e8e8;
+}
+.modal-inner:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #b5b5b5;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .modal-inner:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .modal-inner:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.modal-title {
+ font-weight: 500;
+ font-size: 0.9rem;
+ text-align: center;
+}
+.modal-title + .modal-text {
+ margin-top: 0.25rem;
+}
+.modal-buttons {
+ height: 2.2rem;
+ overflow: hidden;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ justify-content: center;
+}
+.modal-buttons.modal-buttons-vertical {
+ display: block;
+ height: auto;
+}
+.modal-button {
+ width: 100%;
+ padding: 0 0.25rem;
+ height: 2.2rem;
+ font-size: 0.85rem;
+ line-height: 2.2rem;
+ text-align: center;
+ color: #0894ec;
+ background: #e8e8e8;
+ display: block;
+ position: relative;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ cursor: pointer;
+ box-sizing: border-box;
+ -webkit-box-flex: 1;
+ -ms-flex: 1;
+}
+.modal-button:after {
+ content: '';
+ position: absolute;
+ right: 0;
+ top: 0;
+ left: auto;
+ bottom: auto;
+ width: 1px;
+ height: 100%;
+ background-color: #b5b5b5;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 100% 50%;
+ transform-origin: 100% 50%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .modal-button:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .modal-button:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.modal-button:first-child {
+ border-radius: 0 0 0 0.35rem;
+}
+.modal-button:last-child {
+ border-radius: 0 0 0.35rem 0;
+}
+.modal-button:last-child:after {
+ display: none;
+}
+.modal-button:first-child:last-child {
+ border-radius: 0 0 0.35rem 0.35rem;
+}
+.modal-button.modal-button-bold {
+ font-weight: 500;
+}
+html:not(.watch-active-state) .modal-button:active,
+.modal-button.active-state {
+ background: #d4d4d4;
+}
+.modal-buttons-vertical .modal-button {
+ border-radius: 0;
+}
+.modal-buttons-vertical .modal-button:after {
+ display: none;
+}
+.modal-buttons-vertical .modal-button:before {
+ display: none;
+}
+.modal-buttons-vertical .modal-button:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #b5b5b5;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .modal-buttons-vertical .modal-button:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .modal-buttons-vertical .modal-button:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.modal-buttons-vertical .modal-button:last-child {
+ border-radius: 0 0 0.35rem 0.35rem;
+}
+.modal-buttons-vertical .modal-button:last-child:after {
+ display: none;
+}
+.modal-no-buttons .modal-inner {
+ border-radius: 0.35rem;
+}
+.modal-no-buttons .modal-inner:after {
+ display: none;
+}
+.modal-no-buttons .modal-buttons {
+ display: none;
+}
+.actions-modal {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ z-index: 11000;
+ width: 100%;
+ -webkit-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0);
+}
+.actions-modal.modal-in {
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.actions-modal.modal-out {
+ z-index: 10999;
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+ -webkit-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0);
+}
+.actions-modal-group {
+ margin: 0.4rem;
+}
+.actions-modal-button,
+.actions-modal-label {
+ width: 100%;
+ text-align: center;
+ font-weight: normal;
+ margin: 0;
+ background: rgba(243, 243, 243, 0.95);
+ box-sizing: border-box;
+ display: block;
+ position: relative;
+}
+.actions-modal-button:after,
+.actions-modal-label:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #d2d2d6;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .actions-modal-button:after,
+ .actions-modal-label:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .actions-modal-button:after,
+ .actions-modal-label:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.actions-modal-button a,
+.actions-modal-label a {
+ text-decoration: none;
+ color: inherit;
+}
+.actions-modal-button b,
+.actions-modal-label b {
+ font-weight: 500;
+}
+.actions-modal-button.actions-modal-button-bold,
+.actions-modal-label.actions-modal-button-bold {
+ font-weight: 500;
+}
+.actions-modal-button.actions-modal-button-danger,
+.actions-modal-label.actions-modal-button-danger {
+ color: #f6383a;
+}
+.actions-modal-button.color-danger,
+.actions-modal-label.color-danger {
+ color: #f6383a;
+}
+.actions-modal-button.bg-danger,
+.actions-modal-label.bg-danger {
+ background: #f6383a;
+ color: white;
+}
+.actions-modal-button.bg-danger:active,
+.actions-modal-label.bg-danger:active {
+ background: #f00b0d;
+}
+.actions-modal-button:first-child,
+.actions-modal-label:first-child {
+ border-radius: 0.2rem 0.2rem 0 0;
+}
+.actions-modal-button:last-child,
+.actions-modal-label:last-child {
+ border-radius: 0 0 0.2rem 0.2rem;
+}
+.actions-modal-button:last-child:after,
+.actions-modal-label:last-child:after {
+ display: none;
+}
+.actions-modal-button:first-child:last-child,
+.actions-modal-label:first-child:last-child {
+ border-radius: 0.2rem;
+}
+.actions-modal-button.disabled,
+.actions-modal-label.disabled {
+ opacity: 0.95;
+ color: #8e8e93;
+}
+.actions-modal-button {
+ cursor: pointer;
+ line-height: 2.15rem;
+ font-size: 1rem;
+ color: #0894ec;
+}
+.actions-modal-button:active,
+.actions-modal-button.active-state {
+ background: #dcdcdc;
+}
+.actions-modal-label {
+ font-size: 0.7rem;
+ line-height: 1.3;
+ min-height: 2.2rem;
+ padding: 0.4rem 0.5rem;
+ color: #5f646e;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ justify-content: center;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+}
+input.modal-text-input {
+ box-sizing: border-box;
+ height: 1.5rem;
+ background: #fff;
+ margin: 0;
+ margin-top: 0.75rem;
+ padding: 0 0.25rem;
+ border: 1px solid #a0a0a0;
+ border-radius: 0.25rem;
+ width: 100%;
+ font-size: 0.7rem;
+ font-family: inherit;
+ display: block;
+ box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+}
+input.modal-text-input + input.modal-text-input {
+ margin-top: 0.25rem;
+}
+input.modal-text-input.modal-text-input-double {
+ border-radius: 0.25rem 0.25rem 0 0;
+}
+input.modal-text-input.modal-text-input-double + input.modal-text-input {
+ margin-top: 0;
+ border-top: 0;
+ border-radius: 0 0 0.25rem 0.25rem;
+}
+.popup,
+.login-screen {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 10400;
+ background: #fff;
+ box-sizing: border-box;
+ display: none;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+ -webkit-transition-property: -webkit-transform;
+ transition-property: transform;
+ -webkit-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0);
+}
+.popup.modal-in,
+.login-screen.modal-in,
+.popup.modal-out,
+.login-screen.modal-out {
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms;
+}
+.popup.modal-in,
+.login-screen.modal-in {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.popup.modal-out,
+.login-screen.modal-out {
+ -webkit-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0);
+}
+.login-screen.modal-in,
+.login-screen.modal-out {
+ display: block;
+}
+html.with-statusbar-overlay .popup {
+ height: -webkit-calc(100% - 1rem);
+ height: calc(100% - 1rem);
+ top: 1rem;
+}
+html.with-statusbar-overlay .popup-overlay {
+ z-index: 9800;
+}
+@media all and (max-width: 629px), (max-height: 629px) {
+ html.with-statusbar-overlay .popup {
+ height: -webkit-calc(100% - 1rem);
+ height: calc(100% - 1rem);
+ top: 1rem;
+ }
+ html.with-statusbar-overlay .popup-overlay {
+ z-index: 9800;
+ }
+}
+html.with-statusbar-overlay .login-screen,
+html.with-statusbar-overlay .popup.tablet-fullscreen {
+ height: -webkit-calc(100% - 1rem);
+ height: calc(100% - 1rem);
+ top: 1rem;
+}
+.modal .preloader {
+ width: 1.7rem;
+ height: 1.7rem;
+}
+.preloader-indicator-overlay {
+ visibility: visible;
+ opacity: 0;
+ background: none;
+}
+.preloader-indicator-modal {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ padding: 0.4rem;
+ margin-left: -1.25rem;
+ margin-top: -1.25rem;
+ background: rgba(0, 0, 0, 0.8);
+ z-index: 11000;
+ border-radius: 0.25rem;
+}
+.preloader-indicator-modal .preloader {
+ display: block;
+ width: 1.7rem;
+ height: 1.7rem;
+}
+.picker-modal {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ height: 13rem;
+ z-index: 11500;
+ display: none;
+ -webkit-transition-property: -webkit-transform;
+ transition-property: transform;
+ background: #cfd5da;
+ -webkit-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0);
+}
+.picker-modal.modal-in,
+.picker-modal.modal-out {
+ -webkit-transition-duration: 400ms;
+ transition-duration: 400ms;
+}
+.picker-modal.modal-in {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.picker-modal.modal-out {
+ -webkit-transform: translate3d(0, 100%, 0);
+ transform: translate3d(0, 100%, 0);
+}
+.picker-modal .picker-modal-inner {
+ height: 100%;
+ position: relative;
+}
+.picker-modal .toolbar {
+ position: relative;
+ width: 100%;
+}
+.picker-modal .toolbar:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #999999;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .picker-modal .toolbar:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .picker-modal .toolbar:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.picker-modal .toolbar + .picker-modal-inner {
+ height: -webkit-calc(100% - 2.2rem);
+ height: calc(100% - 2.2rem);
+}
+.picker-modal.picker-modal-inline {
+ display: block;
+ position: relative;
+ background: none;
+ z-index: inherit;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+}
+.picker-modal.picker-modal-inline .toolbar:before {
+ display: none;
+}
+.picker-modal.picker-modal-inline .toolbar:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #999999;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .picker-modal.picker-modal-inline .toolbar:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .picker-modal.picker-modal-inline .toolbar:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.toast {
+ background: rgba(0, 0, 0, 0.8);
+ border-radius: 1rem;
+ color: white;
+ padding: 0 .8rem;
+ height: 2rem;
+ line-height: 2rem;
+ font-size: 0.8rem;
+ width: auto;
+}
+/* === Preloader === */
+.preloader {
+ display: inline-block;
+ width: 1rem;
+ height: 1rem;
+ -webkit-transform-origin: 50%;
+ transform-origin: 50%;
+ -webkit-animation: preloader-spin 1s steps(12, end) infinite;
+ animation: preloader-spin 1s steps(12, end) infinite;
+}
+.preloader:after {
+ display: block;
+ content: "";
+ width: 100%;
+ height: 100%;
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
+ background-position: 50%;
+ background-size: 100%;
+ background-repeat: no-repeat;
+}
+.preloader-white:after {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
+}
+@-webkit-keyframes preloader-spin {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ }
+}
+@keyframes preloader-spin {
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+/* === Cards === */
+.cards-list ul,
+.card .list-block ul {
+ background: none;
+}
+.cards-list > ul:before,
+.card .list-block > ul:before {
+ display: none;
+}
+.cards-list > ul:after,
+.card .list-block > ul:after {
+ display: none;
+}
+.card {
+ background: #fff;
+ box-shadow: 0 0.05rem 0.1rem rgba(0, 0, 0, 0.3);
+ margin: 0.5rem;
+ position: relative;
+ border-radius: 0.1rem;
+ font-size: 0.7rem;
+}
+.card .list-block,
+.card .content-block {
+ margin: 0;
+}
+.row:not(.no-gutter) .col > .card {
+ margin-left: 0;
+ margin-right: 0;
+}
+.card-content {
+ position: relative;
+}
+.card-content-inner {
+ padding: 0.75rem;
+ position: relative;
+}
+.card-content-inner > p:first-child {
+ margin-top: 0;
+}
+.card-content-inner > p:last-child {
+ margin-bottom: 0;
+}
+.card-content-inner > .list-block,
+.card-content-inner > .content-block {
+ margin: -0.75rem;
+}
+.card-header,
+.card-footer {
+ min-height: 2.2rem;
+ position: relative;
+ padding: 0.5rem 0.75rem;
+ box-sizing: border-box;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+}
+.card-header[valign="top"],
+.card-footer[valign="top"] {
+ -webkit-box-align: start;
+ -webkit-align-items: flex-start;
+ align-items: flex-start;
+}
+.card-header[valign="bottom"],
+.card-footer[valign="bottom"] {
+ -webkit-box-align: end;
+ -webkit-align-items: flex-end;
+ align-items: flex-end;
+}
+.card-header a.link,
+.card-footer a.link {
+ line-height: 2.2rem;
+ height: 2.2rem;
+ text-decoration: none;
+ position: relative;
+ margin-top: -0.5rem;
+ margin-bottom: -0.5rem;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ justify-content: flex-start;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ -webkit-transition-duration: 300ms;
+ transition-duration: 300ms;
+}
+html:not(.watch-active-state) .card-header a.link:active,
+html:not(.watch-active-state) .card-footer a.link:active,
+.card-header a.link.active-state,
+.card-footer a.link.active-state {
+ opacity: 0.3;
+ -webkit-transition-duration: 0ms;
+ transition-duration: 0ms;
+}
+.card-header a.link i + span,
+.card-footer a.link i + span,
+.card-header a.link i + i,
+.card-footer a.link i + i,
+.card-header a.link span + i,
+.card-footer a.link span + i,
+.card-header a.link span + span,
+.card-footer a.link span + span {
+ margin-left: 0.35rem;
+}
+.card-header a.link i.icon,
+.card-footer a.link i.icon {
+ display: block;
+}
+.card-header a.icon-only,
+.card-footer a.icon-only {
+ min-width: 2.2rem;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ justify-content: center;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ margin: 0;
+}
+.card-header {
+ border-radius: 0.1rem 0.1rem 0 0;
+ font-size: 0.85rem;
+}
+.card-header:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e1e1e1;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .card-header:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .card-header:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.card-header .card-cover {
+ width: 100%;
+ display: block;
+}
+.card-header.no-border:after {
+ display: none;
+}
+.card-header.no-padding {
+ padding: 0;
+}
+.card-footer {
+ border-radius: 0 0 0.1rem 0.1rem;
+ color: #5f646e;
+}
+.card-footer:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #e1e1e1;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .card-footer:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .card-footer:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.card-footer.no-border:before {
+ display: none;
+}
+.facebook-card .card-header {
+ display: block;
+ padding: 0.5rem;
+}
+.facebook-card .facebook-avatar {
+ float: left;
+}
+.facebook-card .facebook-name {
+ margin-left: 2.2rem;
+ font-size: 0.7rem;
+ font-weight: 500;
+}
+.facebook-card .facebook-date {
+ margin-left: 2.2rem;
+ font-size: 0.65rem;
+ color: #5f646e;
+}
+.facebook-card .card-footer {
+ background: #fafafa;
+}
+.facebook-card .card-footer a {
+ color: #5f646e;
+ font-weight: 500;
+}
+.facebook-card .card-content img {
+ display: block;
+}
+.facebook-card .card-content-inner {
+ padding: 0.75rem 0.5rem;
+}
+/* === Panels === */
+.panel-overlay {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0);
+ opacity: 0;
+ z-index: 5999;
+ display: none;
+}
+.panel {
+ z-index: 1000;
+ display: none;
+ background: #111;
+ color: white;
+ box-sizing: border-box;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+ position: absolute;
+ width: 12rem;
+ top: 0;
+ height: 100%;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ -webkit-transition: -webkit-transform 400ms;
+ transition: transform 400ms;
+}
+.panel.panel-left.panel-cover {
+ z-index: 6000;
+ left: -12rem;
+}
+.panel.panel-left.panel-reveal {
+ left: 0;
+}
+.panel.panel-right.panel-cover {
+ z-index: 6000;
+ right: -12rem;
+}
+.panel.panel-right.panel-reveal {
+ right: 0;
+}
+body.with-panel-left-cover .page,
+body.with-panel-right-cover .page {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ -webkit-transition: -webkit-transform 400ms;
+ transition: transform 400ms;
+}
+body.with-panel-left-cover .panel-overlay,
+body.with-panel-right-cover .panel-overlay {
+ display: block;
+}
+body.with-panel-left-reveal .page,
+body.with-panel-right-reveal .page {
+ -webkit-transition: 400ms;
+ transition: 400ms;
+ -webkit-transition-property: -webkit-transform;
+ transition-property: transform;
+}
+body.with-panel-left-reveal .panel-overlay,
+body.with-panel-right-reveal .panel-overlay {
+ display: block;
+}
+body.with-panel-left-reveal .page {
+ -webkit-transform: translate3d(12rem, 0, 0);
+ transform: translate3d(12rem, 0, 0);
+}
+body.with-panel-left-reveal .panel-overlay {
+ margin-left: 12rem;
+}
+body.with-panel-left-cover .panel-left {
+ -webkit-transform: translate3d(12rem, 0, 0);
+ transform: translate3d(12rem, 0, 0);
+}
+body.with-panel-right-reveal .page {
+ -webkit-transform: translate3d(-12rem, 0, 0);
+ transform: translate3d(-12rem, 0, 0);
+}
+body.with-panel-right-reveal .panel-overlay {
+ margin-left: -12rem;
+}
+body.with-panel-right-cover .panel-right {
+ -webkit-transform: translate3d(-12rem, 0, 0);
+ transform: translate3d(-12rem, 0, 0);
+}
+body.panel-closing .page {
+ -webkit-transition: 400ms;
+ transition: 400ms;
+ -webkit-transition-property: -webkit-transform;
+ transition-property: transform;
+}
+/* === Calendar === */
+.picker-calendar {
+ background: #fff;
+ height: 300px;
+ width: 100%;
+ overflow: hidden;
+}
+@media (orientation: landscape) and (max-height: 415px) {
+ .picker-calendar:not(.picker-modal-inline) {
+ height: 220px;
+ }
+}
+.picker-calendar .picker-modal-inner {
+ overflow: hidden;
+}
+.picker-calendar-week-days {
+ height: 18px;
+ background: #f7f7f8;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ font-size: 11px;
+ box-sizing: border-box;
+ position: relative;
+}
+.picker-calendar-week-days:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #c4c4c4;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .picker-calendar-week-days:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .picker-calendar-week-days:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.picker-calendar-week-days .picker-calendar-week-day {
+ -webkit-flex-shrink: 1;
+ -ms-flex: 0 1 auto;
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ width: 14.28571429%;
+ width: -webkit-calc(100% / 7);
+ width: calc(100% / 7);
+ line-height: 17px;
+ text-align: center;
+}
+.picker-calendar-week-days + .picker-calendar-months {
+ height: -webkit-calc(100% - 18px);
+ height: calc(100% - 18px);
+}
+.picker-calendar-months {
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ position: relative;
+}
+.picker-calendar-months-wrapper {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ -webkit-transition: 300ms;
+ transition: 300ms;
+}
+.picker-calendar-month {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-flex-direction: column;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+.picker-calendar-row {
+ height: 16.66666667%;
+ height: -webkit-calc(100% / 6);
+ height: calc(100% / 6);
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-shrink: 1;
+ -ms-flex: 0 1 auto;
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ width: 100%;
+ position: relative;
+}
+.picker-calendar-row:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #cccccc;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .picker-calendar-row:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .picker-calendar-row:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.picker-calendar-row:last-child:after {
+ display: none;
+}
+.picker-calendar-day {
+ -webkit-flex-shrink: 1;
+ -ms-flex: 0 1 auto;
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ justify-content: center;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ box-sizing: border-box;
+ width: 14.28571429%;
+ width: -webkit-calc(100% / 7);
+ width: calc(100% / 7);
+ text-align: center;
+ color: #3d4145;
+ font-size: 15px;
+ cursor: pointer;
+}
+.picker-calendar-day.picker-calendar-day-prev,
+.picker-calendar-day.picker-calendar-day-next {
+ color: #cccccc;
+}
+.picker-calendar-day.picker-calendar-day-disabled {
+ color: #d4d4d4;
+ cursor: auto;
+}
+.picker-calendar-day.picker-calendar-day-today span {
+ background: #e3e3e3;
+}
+.picker-calendar-day.picker-calendar-day-selected span {
+ background: #0894ec;
+ color: #fff;
+}
+.picker-calendar-day span {
+ display: inline-block;
+ border-radius: 100%;
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+}
+.picker-calendar-month-picker,
+.picker-calendar-year-picker {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+ -webkit-box-pack: justify;
+ -webkit-justify-content: space-between;
+ justify-content: space-between;
+ width: 50%;
+ max-width: 200px;
+ -webkit-flex-shrink: 10;
+ -ms-flex: 0 10 auto;
+ -webkit-flex-shrink: 10;
+ flex-shrink: 10;
+}
+.picker-calendar-month-picker a.icon-only,
+.picker-calendar-year-picker a.icon-only {
+ min-width: 36px;
+}
+.picker-calendar-month-picker span,
+.picker-calendar-year-picker span {
+ -webkit-flex-shrink: 1;
+ -ms-flex: 0 1 auto;
+ -webkit-flex-shrink: 1;
+ flex-shrink: 1;
+ position: relative;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.picker-modal .toolbar-inner {
+ height: 2.2rem;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ text-align: center;
+}
+.picker-calendar-month-picker,
+.picker-calendar-year-picker {
+ display: block;
+ line-height: 2.2rem;
+}
+.picker-calendar-month-picker a.icon-only,
+.picker-calendar-year-picker a.icon-only {
+ float: left;
+ width: 25%;
+ height: 2.2rem;
+ line-height: 2rem;
+}
+.picker-calendar-month-picker .current-month-value,
+.picker-calendar-year-picker .current-month-value,
+.picker-calendar-month-picker .current-year-value,
+.picker-calendar-year-picker .current-year-value {
+ float: left;
+ width: 50%;
+ height: 2.2rem;
+}
+/* === Columns Picker === */
+.picker-columns {
+ width: 100%;
+ height: 13rem;
+ z-index: 11500;
+}
+.picker-columns.picker-modal-inline {
+ height: 10rem;
+}
+@media (orientation: landscape) and (max-height: 415px) {
+ .picker-columns:not(.picker-modal-inline) {
+ height: 10rem;
+ }
+}
+.picker-items {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-pack: center;
+ -webkit-justify-content: center;
+ justify-content: center;
+ padding: 0;
+ text-align: right;
+ font-size: 1.2rem;
+ -webkit-mask-box-image: -webkit-linear-gradient(bottom, transparent, transparent 5%, white 20%, white 80%, transparent 95%, transparent);
+ -webkit-mask-box-image: linear-gradient(to top, transparent, transparent 5%, white 20%, white 80%, transparent 95%, transparent);
+}
+.bar + .picker-items {
+ height: 10.8rem;
+}
+.picker-items-col {
+ overflow: hidden;
+ position: relative;
+ max-height: 100%;
+}
+.picker-items-col.picker-items-col-left {
+ text-align: left;
+}
+.picker-items-col.picker-items-col-center {
+ text-align: center;
+}
+.picker-items-col.picker-items-col-right {
+ text-align: right;
+}
+.picker-items-col.picker-items-col-divider {
+ color: #3d4145;
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: flex;
+ -webkit-box-align: center;
+ -webkit-align-items: center;
+ align-items: center;
+}
+.picker-items-col-normal {
+ width: 100%;
+}
+.picker-items-col-wrapper {
+ -webkit-transition: 300ms;
+ transition: 300ms;
+ -webkit-transition-timing-function: ease-out;
+ transition-timing-function: ease-out;
+}
+.picker-item {
+ height: 36px;
+ line-height: 36px;
+ padding: 0 10px;
+ white-space: nowrap;
+ position: relative;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ color: #999999;
+ left: 0;
+ top: 0;
+ width: 100%;
+ box-sizing: border-box;
+ -webkit-transition: 300ms;
+ transition: 300ms;
+}
+.picker-items-col-absolute .picker-item {
+ position: absolute;
+}
+.picker-item.picker-item-far {
+ pointer-events: none;
+}
+.picker-item.picker-selected {
+ color: #3d4145;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ -webkit-transform: rotateX(0deg);
+ transform: rotateX(0deg);
+}
+.picker-center-highlight {
+ height: 36px;
+ box-sizing: border-box;
+ position: absolute;
+ left: 0;
+ width: 100%;
+ top: 50%;
+ margin-top: -18px;
+ pointer-events: none;
+}
+.picker-center-highlight:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #a8abb0;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .picker-center-highlight:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .picker-center-highlight:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.picker-center-highlight:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #a8abb0;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .picker-center-highlight:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .picker-center-highlight:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.picker-3d .picker-items {
+ overflow: hidden;
+ -webkit-perspective: 1200px;
+ perspective: 1200px;
+}
+.picker-3d .picker-items-col,
+.picker-3d .picker-items-col-wrapper,
+.picker-3d .picker-item {
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d;
+}
+.picker-3d .picker-items-col {
+ overflow: visible;
+}
+.picker-3d .picker-item {
+ -webkit-transform-origin: center center -110px;
+ transform-origin: center center -110px;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-transition-timing-function: ease-out;
+ transition-timing-function: ease-out;
+}
+.picker-modal .bar {
+ position: relative;
+ top: 0;
+}
+.picker-modal .bar:before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: auto;
+ right: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #a8abb0;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .picker-modal .bar:before {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .picker-modal .bar:before {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.picker-modal .bar:after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ right: auto;
+ top: auto;
+ height: 1px;
+ width: 100%;
+ background-color: #a8abb0;
+ display: block;
+ z-index: 15;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 2) {
+ .picker-modal .bar:after {
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ }
+}
+@media only screen and (-webkit-min-device-pixel-ratio: 3) {
+ .picker-modal .bar:after {
+ -webkit-transform: scaleY(0.33);
+ transform: scaleY(0.33);
+ }
+}
+.picker-modal .bar .title {
+ color: #5f646e;
+ font-weight: normal;
+}
+.city-picker .col-province {
+ width: 5rem;
+}
+.city-picker .col-city {
+ width: 6rem;
+}
+.city-picker .col-district {
+ width: 5rem;
+}
+@font-face {
+ font-family: "iconfont-sm";
+ src: url('../fonts/iconfont.woff') format('woff'), /* chrome、firefox */
+ url('../fonts/iconfont.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
+ url('../fonts/iconfont.svg#iconfont') format('svg');
+
+ /* iOS 4.1- */
+}
+.icon {
+ font-family: "iconfont-sm" !important;
+ font-style: normal;
+ display: inline-block;
+ vertical-align: middle;
+ background-size: 100% auto;
+ background-position: center;
+ -webkit-font-smoothing: antialiased;
+ -webkit-text-stroke-width: 0.2px;
+ -moz-osx-font-smoothing: grayscale;
+}
+.icon-app:before {
+ content: "\e605";
+}
+.icon-browser:before {
+ content: "\e606";
+}
+.icon-card:before {
+ content: "\e607";
+}
+.icon-cart:before {
+ content: "\e600";
+}
+.icon-code:before {
+ content: "\e609";
+}
+.icon-computer:before {
+ content: "\e616";
+}
+.icon-remove:before {
+ content: "\e60a";
+}
+.icon-download:before {
+ content: "\e60b";
+}
+.icon-edit:before {
+ content: "\e60c";
+}
+.icon-emoji:before {
+ content: "\e615";
+}
+.icon-star:before {
+ content: "\e60e";
+}
+.icon-friends:before {
+ content: "\e601";
+}
+.icon-gift:before {
+ content: "\e618";
+}
+.icon-phone:before {
+ content: "\e60f";
+}
+.icon-clock:before {
+ content: "\e619";
+}
+.icon-home:before {
+ content: "\e602";
+}
+.icon-menu:before {
+ content: "\e60d";
+}
+.icon-message:before {
+ content: "\e617";
+}
+.icon-me:before {
+ content: "\e603";
+}
+.icon-picture:before {
+ content: "\e61a";
+}
+.icon-share:before {
+ content: "\e61b";
+}
+.icon-settings:before {
+ content: "\e604";
+}
+.icon-refresh:before {
+ content: "\e61c";
+}
+.icon-caret:before {
+ content: "\e610";
+}
+.icon-down:before {
+ content: "\e611";
+}
+.icon-up:before {
+ content: "\e612";
+}
+.icon-right:before {
+ content: "\e613";
+}
+.icon-left:before {
+ content: "\e614";
+}
+.icon-check:before {
+ content: "\e608";
+}
+.icon-search:before {
+ content: "\e61d";
+}
+.icon-new:before {
+ content: "\e61e";
+}
+.icon-next,
+.icon-prev {
+ width: 0.75rem;
+ height: 0.75rem;
+}
+.icon-next {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%23007aff'%20d%3D'M1%2C1.6l11.8%2C5.8L1%2C13.4V1.6%20M0%2C0v15l15-7.6L0%2C0L0%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
+}
+.icon-prev {
+ background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2015%2015'%3E%3Cg%3E%3Cpath%20fill%3D'%23007aff'%20d%3D'M14%2C1.6v11.8L2.2%2C7.6L14%2C1.6%20M15%2C0L0%2C7.6L15%2C15V0L15%2C0z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
+}
+/*
+.icon-plus {
+ width: 1.25rem;
+ height: 1.25rem;
+ font-size: 1.55rem;
+ line-height: 1rem;
+ text-align: center;
+ font-weight: 100;
+}
+*/
+/*==========================
+Framework7 Layouts Themes
+==========================*/
+/* === Dark layout === */
+.theme-dark {
+ background-color: #222426;
+}
+.theme-dark .bar,
+.bar.theme-dark {
+ background-color: #131313;
+ color: #ffffff;
+}
+.theme-dark .bar:after,
+.bar.theme-dark:after {
+ background-color: #333333;
+}
+.theme-dark .title {
+ color: #ffffff;
+}
+.theme-dark .bar-nav,
+.theme-dark .bar-tab,
+.bar-nav.theme-dark,
+.bar-tab.theme-dark {
+ background-color: #131313;
+ color: #ffffff;
+}
+.theme-dark .bar-nav:before,
+.theme-dark .bar-tab:before,
+.bar-nav.theme-dark:before,
+.bar-tab.theme-dark:before {
+ background-color: #333333;
+}
+.theme-dark .tab-item {
+ color: #ffffff;
+}
+.theme-dark .tab-item.active {
+ color: #0894ec;
+}
+.theme-dark .picker-calendar-week-days {
+ color: #fff;
+ background-color: #131313;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-center-highlight:before {
+ background-color: #333333;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-center-highlight:after {
+ background-color: #333333;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-item.picker-selected {
+ color: #fff;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-week-days {
+ color: #fff;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-day {
+ color: #fff;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-day.picker-calendar-day-prev,
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-day.picker-calendar-day-next {
+ color: #777;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-day.picker-calendar-day-disabled {
+ color: #555;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-day.picker-calendar-day-today span {
+ background: #444;
+}
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-week-days:after,
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-row:after {
+ background-color: #333333;
+}
+.theme-dark .picker-modal.picker-modal-inline .toolbar ~ .picker-modal-inner .picker-calendar-months:before,
+.theme-dark .picker-modal.picker-modal-inline .picker-calendar-week-days ~ .picker-calendar-months:before {
+ background-color: #333333;
+}
+.theme-dark .photo-browser .navbar,
+.photo-browser.theme-dark .navbar,
+.theme-dark .view[data-page="photo-browser-slides"] .navbar,
+.view[data-page="photo-browser-slides"].theme-dark .navbar,
+.theme-dark .photo-browser .toolbar,
+.photo-browser.theme-dark .toolbar,
+.theme-dark .view[data-page="photo-browser-slides"] .toolbar,
+.view[data-page="photo-browser-slides"].theme-dark .toolbar {
+ background: rgba(19, 19, 19, 0.95);
+}
+.theme-dark .tabbar a:not(.active) {
+ color: #ffffff;
+}
+.theme-dark .page,
+.theme-dark .login-screen-content,
+.page.theme-dark,
+.theme-dark .panel,
+.panel.theme-dark,
+.theme-dark .content {
+ background-color: #222426;
+ color: #dddddd;
+}
+.theme-dark .content-block-title {
+ color: #ffffff;
+}
+.theme-dark .content-block,
+.content-block.theme-dark {
+ color: #bbbbbb;
+}
+.theme-dark .content-block-inner {
+ background: #1c1d1f;
+ color: #dddddd;
+}
+.theme-dark .content-block-inner:before {
+ background-color: #393939;
+}
+.theme-dark .content-block-inner:after {
+ background-color: #393939;
+}
+.theme-dark .list-block ul,
+.list-block.theme-dark ul {
+ background: #1c1d1f;
+}
+.theme-dark .list-block ul:before,
+.list-block.theme-dark ul:before {
+ background-color: #393939;
+}
+.theme-dark .list-block ul:after,
+.list-block.theme-dark ul:after {
+ background-color: #393939;
+}
+.theme-dark .list-block.inset ul,
+.list-block.theme-dark.inset ul {
+ background: #1c1d1f;
+}
+.theme-dark .list-block.notifications > ul,
+.list-block.theme-dark.notifications > ul {
+ background: none;
+}
+.theme-dark .list-block .item-title,
+.list-block.theme-dark .item-title,
+.theme-dark .list-block .item-subtitle,
+.list-block.theme-dark .item-subtitle {
+ color: #bbbbbb;
+}
+.theme-dark .card {
+ background: #1c1d1f;
+}
+.theme-dark .card-header:after {
+ background-color: #393939;
+}
+.theme-dark .card-footer {
+ color: #bbbbbb;
+}
+.theme-dark .card-footer:before {
+ background-color: #393939;
+}
+.theme-dark li.sorting {
+ background-color: #29292f;
+}
+.theme-dark .swipeout-actions-left a,
+.theme-dark .swipeout-actions-right a {
+ background-color: #444444;
+}
+.theme-dark .item-inner:after,
+.theme-dark .list-block ul ul li:last-child .item-inner:after {
+ background-color: #393939;
+}
+.theme-dark .item-after {
+ color: #bbbbbb;
+}
+html:not(.watch-active-state) .theme-dark .item-link:active,
+html:not(.watch-active-state) .theme-dark label.label-checkbox:active,
+html:not(.watch-active-state) .theme-dark label.label-radio:active,
+.theme-dark .item-link.active-state,
+.theme-dark label.label-checkbox.active-state,
+.theme-dark label.label-radio.active-state {
+ background-color: #29292f;
+}
+.theme-dark .item-link.list-button:after {
+ background-color: #393939;
+}
+.theme-dark .list-block-label {
+ color: #bbbbbb;
+}
+.theme-dark .item-divider,
+.theme-dark .list-group-title {
+ background: #1a1a1a;
+ color: #bbbbbb;
+}
+.theme-dark .item-divider:before,
+.theme-dark .list-group-title:before {
+ background-color: #393939;
+}
+.theme-dark .searchbar {
+ background: #333333;
+}
+.theme-dark .searchbar:after {
+ background-color: #333333;
+}
+.theme-dark .list-block input[type="text"],
+.list-block.theme-dark input[type="text"],
+.theme-dark .list-block input[type="password"],
+.list-block.theme-dark input[type="password"],
+.theme-dark .list-block input[type="email"],
+.list-block.theme-dark input[type="email"],
+.theme-dark .list-block input[type="tel"],
+.list-block.theme-dark input[type="tel"],
+.theme-dark .list-block input[type="url"],
+.list-block.theme-dark input[type="url"],
+.theme-dark .list-block input[type="date"],
+.list-block.theme-dark input[type="date"],
+.theme-dark .list-block input[type="datetime-local"],
+.list-block.theme-dark input[type="datetime-local"],
+.theme-dark .list-block input[type="number"],
+.list-block.theme-dark input[type="number"],
+.theme-dark .list-block select,
+.list-block.theme-dark select,
+.theme-dark .list-block textarea,
+.list-block.theme-dark textarea {
+ color: #ffffff;
+}
+.theme-dark .label-switch .checkbox {
+ background-color: #393939;
+}
+.theme-dark .label-switch .checkbox:before {
+ background-color: #1c1d1f;
+}
+.theme-dark .range-slider input[type="range"]:after {
+ background: #1c1d1f;
+}
+.theme-dark .buttons-tab {
+ background: #131313;
+}
+.theme-dark .buttons-tab .tab-link:not(.active) {
+ color: #dddddd;
+}
+/* === White layout === */
+.theme-white .navbar,
+.navbar.theme-white,
+.theme-white .subnavbar,
+.subnavbar.theme-white {
+ background-color: #ffffff;
+ color: #000000;
+}
+.theme-white .navbar:after,
+.navbar.theme-white:after,
+.theme-white .subnavbar:after,
+.subnavbar.theme-white:after {
+ background-color: #dddddd;
+}
+.theme-white .toolbar,
+.toolbar.theme-white {
+ background-color: #ffffff;
+ color: #000000;
+}
+.theme-white .toolbar:before,
+.toolbar.theme-white:before {
+ background-color: #dddddd;
+}
+.theme-white .picker-modal.picker-modal-inline .picker-center-highlight:before {
+ background-color: #dddddd;
+}
+.theme-white .picker-modal.picker-modal-inline .picker-center-highlight:after {
+ background-color: #dddddd;
+}
+.theme-white .picker-modal.picker-modal-inline .picker-calendar-week-days:after,
+.theme-white .picker-modal.picker-modal-inline .picker-calendar-row:after {
+ background-color: #dddddd;
+}
+.theme-white .picker-modal.picker-modal-inline .toolbar ~ .picker-modal-inner .picker-calendar-months:before,
+.theme-white .picker-modal.picker-modal-inline .picker-calendar-week-days ~ .picker-calendar-months:before {
+ background-color: #dddddd;
+}
+.theme-white .photo-browser .navbar,
+.photo-browser.theme-white .navbar,
+.theme-white .view[data-page="photo-browser-slides"] .navbar,
+.view[data-page="photo-browser-slides"].theme-white .navbar,
+.theme-white .photo-browser .toolbar,
+.photo-browser.theme-white .toolbar,
+.theme-white .view[data-page="photo-browser-slides"] .toolbar,
+.view[data-page="photo-browser-slides"].theme-white .toolbar {
+ background: rgba(255, 255, 255, 0.95);
+}
+.theme-white .tabbar a:not(.active) {
+ color: #777777;
+}
+.theme-white .page,
+.theme-white .login-screen-content,
+.page.theme-white,
+.theme-white .panel,
+.panel.theme-white {
+ background-color: #ffffff;
+ color: #000000;
+}
+.theme-white .content-block-title {
+ color: #777777;
+}
+.theme-white .content-block,
+.content-block.theme-white {
+ color: #777777;
+}
+.theme-white .content-block-inner {
+ background: #fafafa;
+ color: #000000;
+}
+.theme-white .content-block-inner:after {
+ background-color: #dddddd;
+}
+.theme-white .content-block-inner:before {
+ background-color: #dddddd;
+}
+.theme-white .list-block ul,
+.list-block.theme-white ul {
+ background: #ffffff;
+}
+.theme-white .list-block ul:after,
+.list-block.theme-white ul:after {
+ background-color: #dddddd;
+}
+.theme-white .list-block ul:before,
+.list-block.theme-white ul:before {
+ background-color: #dddddd;
+}
+.theme-white .list-block.inset ul,
+.list-block.theme-white.inset ul {
+ background: #fafafa;
+}
+.theme-white .list-block.notifications > ul,
+.list-block.theme-white.notifications > ul {
+ background: none;
+}
+.theme-white li.sorting {
+ background-color: #eeeeee;
+}
+.theme-white .swipeout-actions-left a,
+.theme-white .swipeout-actions-right a {
+ background-color: #c7c7cc;
+}
+.theme-white .item-inner,
+.theme-white .list-block ul ul li:last-child .item-inner {
+ border-color: #dddddd;
+}
+.theme-white .item-inner:after,
+.theme-white .list-block ul ul li:last-child .item-inner:after {
+ background-color: #dddddd;
+}
+.theme-white .item-after {
+ color: #8e8e93;
+}
+html:not(.watch-active-state) .theme-white .item-link:active,
+html:not(.watch-active-state) .theme-white label.label-checkbox:active,
+html:not(.watch-active-state) .theme-white label.label-radio:active,
+.theme-white .item-link.active-state,
+.theme-white label.label-checkbox.active-state,
+.theme-white label.label-radio.active-state {
+ background-color: #eeeeee;
+}
+.theme-white .item-link.list-button:after {
+ background-color: #dddddd;
+}
+.theme-white .list-block-label {
+ color: #777777;
+}
+.theme-white .item-divider,
+.theme-white .list-group-title {
+ background: #f7f7f7;
+ color: #777777;
+}
+.theme-white .item-divider:before,
+.theme-white .list-group-title:before {
+ background-color: #dddddd;
+}
+.theme-white .searchbar {
+ background: #c9c9ce;
+}
+.theme-white .searchbar:after {
+ background-color: #b4b4b4;
+}
+.theme-white .list-block input[type="text"],
+.list-block.theme-white input[type="text"],
+.theme-white .list-block input[type="password"],
+.list-block.theme-white input[type="password"],
+.theme-white .list-block input[type="email"],
+.list-block.theme-white input[type="email"],
+.theme-white .list-block input[type="tel"],
+.list-block.theme-white input[type="tel"],
+.theme-white .list-block input[type="url"],
+.list-block.theme-white input[type="url"],
+.theme-white .list-block input[type="date"],
+.list-block.theme-white input[type="date"],
+.theme-white .list-block input[type="datetime-local"],
+.list-block.theme-white input[type="datetime-local"],
+.theme-white .list-block input[type="number"],
+.list-block.theme-white input[type="number"],
+.theme-white .list-block select,
+.list-block.theme-white select,
+.theme-white .list-block textarea,
+.list-block.theme-white textarea {
+ color: #777777;
+}
+.theme-white .label-switch .checkbox {
+ background-color: #e5e5e5;
+}
+.theme-white .label-switch .checkbox:before {
+ background-color: #ffffff;
+}
+.theme-white .range-slider input[type="range"]:after {
+ background: #ffffff;
+}
diff --git a/web/public/assets/fonts/iconfont.svg b/web/public/assets/fonts/iconfont.svg
new file mode 100644
index 0000000..9ce3b7b
--- /dev/null
+++ b/web/public/assets/fonts/iconfont.svg
@@ -0,0 +1,158 @@
+
+
+
+
+Created by FontForge 20120731 at Thu Jun 4 14:56:48 2015
+ By Ads
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/public/assets/fonts/iconfont.ttf b/web/public/assets/fonts/iconfont.ttf
new file mode 100644
index 0000000..b5104af
Binary files /dev/null and b/web/public/assets/fonts/iconfont.ttf differ
diff --git a/web/public/assets/fonts/iconfont.woff b/web/public/assets/fonts/iconfont.woff
new file mode 100644
index 0000000..32aa26e
Binary files /dev/null and b/web/public/assets/fonts/iconfont.woff differ
diff --git a/web/public/assets/images/app-preview/alert.png b/web/public/assets/images/app-preview/alert.png
new file mode 100644
index 0000000..8397bb4
Binary files /dev/null and b/web/public/assets/images/app-preview/alert.png differ
diff --git a/web/public/assets/images/app-preview/contacts.png b/web/public/assets/images/app-preview/contacts.png
new file mode 100644
index 0000000..017cfee
Binary files /dev/null and b/web/public/assets/images/app-preview/contacts.png differ
diff --git a/web/public/assets/images/app-preview/me.png b/web/public/assets/images/app-preview/me.png
new file mode 100644
index 0000000..ffa27b1
Binary files /dev/null and b/web/public/assets/images/app-preview/me.png differ
diff --git a/web/public/assets/images/app-preview/message.png b/web/public/assets/images/app-preview/message.png
new file mode 100644
index 0000000..d4e6945
Binary files /dev/null and b/web/public/assets/images/app-preview/message.png differ
diff --git a/web/public/assets/images/app-preview/workbench.png b/web/public/assets/images/app-preview/workbench.png
new file mode 100644
index 0000000..5094ee6
Binary files /dev/null and b/web/public/assets/images/app-preview/workbench.png differ
diff --git a/web/public/assets/images/desktop.jpg b/web/public/assets/images/desktop.jpg
new file mode 100644
index 0000000..11f661d
Binary files /dev/null and b/web/public/assets/images/desktop.jpg differ
diff --git a/web/public/assets/images/device-sprite-iPhone-5s.png b/web/public/assets/images/device-sprite-iPhone-5s.png
new file mode 100644
index 0000000..27febbc
Binary files /dev/null and b/web/public/assets/images/device-sprite-iPhone-5s.png differ
diff --git a/web/public/assets/images/umsapp-logo-16x16.png b/web/public/assets/images/umsapp-logo-16x16.png
new file mode 100644
index 0000000..b01b42f
Binary files /dev/null and b/web/public/assets/images/umsapp-logo-16x16.png differ
diff --git a/web/public/assets/images/umsapp-logo-24x24.png b/web/public/assets/images/umsapp-logo-24x24.png
new file mode 100644
index 0000000..b8b4da2
Binary files /dev/null and b/web/public/assets/images/umsapp-logo-24x24.png differ
diff --git a/web/public/assets/images/umsapp-logo-36x36.png b/web/public/assets/images/umsapp-logo-36x36.png
new file mode 100644
index 0000000..7f92fa0
Binary files /dev/null and b/web/public/assets/images/umsapp-logo-36x36.png differ
diff --git a/web/public/assets/js/app-preview.js b/web/public/assets/js/app-preview.js
new file mode 100644
index 0000000..90f281d
--- /dev/null
+++ b/web/public/assets/js/app-preview.js
@@ -0,0 +1,121 @@
+function AppViewModel() {
+ var me = this;
+ me._colorToStr = function(c) {
+ return c ? ['rgba(', c.r, ',', c.g, ',', c.b, ',', c.a, ')'].join('') : '';
+ };
+ me._isActiveItem = function(item) {
+ var ai = this.activeItem();
+ return item && ai && item.name === ai.name;
+ };
+ me.data = ko.observable({
+ header: {
+ bgColor: {
+ r: 19,
+ g: 30,
+ b: 41,
+ a: 1
+ },
+ textColor: {
+ r: 230,
+ b: 180,
+ g: 145,
+ a: 1
+ }
+ },
+ footer: {
+ bgColor: {
+ r: 1,
+ g: 2,
+ b: 3,
+ a: 1
+ },
+ items: []
+ }
+ });
+ me.activeItem = ko.observable({});
+ me.setDefaultActiveItem = function() {
+ me.activeItem($.grep(this.data().footer.items,
+ function(e) {
+ return e.active;
+ })[0]);
+ };
+ me.headerTitle = ko.computed(function() {
+ var activeItem = this.activeItem();
+ return activeItem ? activeItem.text : '';
+ }, me);
+ me.headerBgColor = ko.computed(function() {
+ return this._colorToStr(this.data().header.bgColor);
+ }, me);
+ me.headerTextColor = ko.computed(function() {
+ return this._colorToStr(this.data().header.textColor);
+ }, me);
+ me.footerBgColor = ko.computed(function() {
+ return this._colorToStr(this.data().footer.bgColor);
+ }, me);
+ me.footerItems = ko.computed(function() {
+ return this.data().footer.items;
+ }, me);
+ me.footerItemClick = function(item) {
+ me.activeItem(item);
+ // load iframe
+ var mc = $('#app-middle-content').empty();
+ var ai = me.activeItem();
+ var url = ai && ai.onTap.startsWith('ph://webview?url=') &&
+ decodeURIComponent(ai.onTap.replace('ph://webview?url=', ''));
+ if (url) {
+ mc.append(['',
+ '',
+ '
'].join(''));
+ }
+ };
+ me.footerItemBgImage = function(item) {
+ return ['url(',
+ this._isActiveItem(item) ?
+ item.iconActive : item.iconNormal,
+ ')'].join('');
+ };
+ me.footerItemTextColor = function(item) {
+ return this._colorToStr(this._isActiveItem(item) ?
+ item.textActiveColor : item.textNormalColor);
+ };
+ me._middleContentCssMapping = {
+ 'ph://view/workbench': 'middle-content-workbench',
+
+ 'ph://view/contacts': 'middle-content-contacts',
+
+ 'ph://view/alert-list': 'middle-content-alert',
+
+ 'ph://view/me': 'middle-content-me',
+
+ 'ph://view/room-list': 'middle-content-message'
+ };
+ me.middleContentCss = function() {
+ var ai = this.activeItem();
+ return ai && this._middleContentCssMapping[ai.onTap];
+ };
+}
+
+var vm = new AppViewModel();
+
+var firstInit = true;
+addEventHandler(window, 'message', function(e) {
+ vm.data(JSON.parse(e.data));
+ vm.setDefaultActiveItem();
+ if (firstInit) {
+ $.hideIndicator();
+ firstInit = false;
+ ko.applyBindings(vm);
+ }
+})
+$.showIndicator();
+
+function addEventHandler(el, event, handler) {
+ if (el.addEventListener) {
+ el.addEventListener(event, handler, false);
+ }
+ else if (el.attachEvent) {
+ el.attachEvent('on' + event, handler);
+ }
+}
diff --git a/web/public/assets/js/html5shiv.js b/web/public/assets/js/html5shiv.js
new file mode 100644
index 0000000..85e0ec1
--- /dev/null
+++ b/web/public/assets/js/html5shiv.js
@@ -0,0 +1,350 @@
+/**
+* @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
+*/
+;(function(window, document) {
+/*jshint evil:true */
+ /** version */
+ var version = '3.7.2';
+
+ /** Preset options */
+ var options = window.html5 || {};
+
+ /** Used to skip problem elements */
+ var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
+
+ /** Not all elements can be cloned in IE **/
+ var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
+
+ /** Detect whether the browser supports default html5 styles */
+ var supportsHtml5Styles;
+
+ /** Name of the expando, to work with multiple documents or to re-shiv one document */
+ var expando = '_html5shiv';
+
+ /** The id for the the documents expando */
+ var expanID = 0;
+
+ /** Cached data for each document */
+ var expandoData = {};
+
+ /** Detect whether the browser supports unknown elements */
+ var supportsUnknownElements;
+
+ (function() {
+ try {
+ var a = document.createElement('a');
+ a.innerHTML = ' ';
+ //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
+ supportsHtml5Styles = ('hidden' in a);
+
+ supportsUnknownElements = a.childNodes.length == 1 || (function() {
+ // assign a false positive if unable to shiv
+ (document.createElement)('a');
+ var frag = document.createDocumentFragment();
+ return (
+ typeof frag.cloneNode == 'undefined' ||
+ typeof frag.createDocumentFragment == 'undefined' ||
+ typeof frag.createElement == 'undefined'
+ );
+ }());
+ } catch(e) {
+ // assign a false positive if detection fails => unable to shiv
+ supportsHtml5Styles = true;
+ supportsUnknownElements = true;
+ }
+
+ }());
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a style sheet with the given CSS text and adds it to the document.
+ * @private
+ * @param {Document} ownerDocument The document.
+ * @param {String} cssText The CSS text.
+ * @returns {StyleSheet} The style element.
+ */
+ function addStyleSheet(ownerDocument, cssText) {
+ var p = ownerDocument.createElement('p'),
+ parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
+
+ p.innerHTML = 'x';
+ return parent.insertBefore(p.lastChild, parent.firstChild);
+ }
+
+ /**
+ * Returns the value of `html5.elements` as an array.
+ * @private
+ * @returns {Array} An array of shived element node names.
+ */
+ function getElements() {
+ var elements = html5.elements;
+ return typeof elements == 'string' ? elements.split(' ') : elements;
+ }
+
+ /**
+ * Extends the built-in list of html5 elements
+ * @memberOf html5
+ * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
+ * @param {Document} ownerDocument The context document.
+ */
+ function addElements(newElements, ownerDocument) {
+ var elements = html5.elements;
+ if(typeof elements != 'string'){
+ elements = elements.join(' ');
+ }
+ if(typeof newElements != 'string'){
+ newElements = newElements.join(' ');
+ }
+ html5.elements = elements +' '+ newElements;
+ shivDocument(ownerDocument);
+ }
+
+ /**
+ * Returns the data associated to the given document
+ * @private
+ * @param {Document} ownerDocument The document.
+ * @returns {Object} An object of data.
+ */
+ function getExpandoData(ownerDocument) {
+ var data = expandoData[ownerDocument[expando]];
+ if (!data) {
+ data = {};
+ expanID++;
+ ownerDocument[expando] = expanID;
+ expandoData[expanID] = data;
+ }
+ return data;
+ }
+
+ /**
+ * returns a shived element for the given nodeName and document
+ * @memberOf html5
+ * @param {String} nodeName name of the element
+ * @param {Document} ownerDocument The context document.
+ * @returns {Object} The shived element.
+ */
+ function createElement(nodeName, ownerDocument, data){
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ if(supportsUnknownElements){
+ return ownerDocument.createElement(nodeName);
+ }
+ if (!data) {
+ data = getExpandoData(ownerDocument);
+ }
+ var node;
+
+ if (data.cache[nodeName]) {
+ node = data.cache[nodeName].cloneNode();
+ } else if (saveClones.test(nodeName)) {
+ node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
+ } else {
+ node = data.createElem(nodeName);
+ }
+
+ // Avoid adding some elements to fragments in IE < 9 because
+ // * Attributes like `name` or `type` cannot be set/changed once an element
+ // is inserted into a document/fragment
+ // * Link elements with `src` attributes that are inaccessible, as with
+ // a 403 response, will cause the tab/window to crash
+ // * Script elements appended to fragments will execute when their `src`
+ // or `text` property is set
+ return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
+ }
+
+ /**
+ * returns a shived DocumentFragment for the given document
+ * @memberOf html5
+ * @param {Document} ownerDocument The context document.
+ * @returns {Object} The shived DocumentFragment.
+ */
+ function createDocumentFragment(ownerDocument, data){
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ if(supportsUnknownElements){
+ return ownerDocument.createDocumentFragment();
+ }
+ data = data || getExpandoData(ownerDocument);
+ var clone = data.frag.cloneNode(),
+ i = 0,
+ elems = getElements(),
+ l = elems.length;
+ for(;i -1 ) {
+ props = mouseEventProps;
+ }
+
+ // copy original event properties over to the new event
+ // this would happen if we could call $.event.fix instead of $.Event
+ // but we don't have a way to force an event to be fixed multiple times
+ if ( oe ) {
+ for ( i = props.length, prop; i; ) {
+ prop = props[ --i ];
+ event[ prop ] = oe[ prop ];
+ }
+ }
+
+ // make sure that if the mouse and click virtual events are generated
+ // without a .which one is defined
+ if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) {
+ event.which = 1;
+ }
+
+ if ( t.search(/^touch/) !== -1 ) {
+ ne = getNativeEvent( oe );
+ t = ne.touches;
+ ct = ne.changedTouches;
+ touch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined );
+
+ if ( touch ) {
+ for ( j = 0, len = touchEventProps.length; j < len; j++) {
+ prop = touchEventProps[ j ];
+ event[ prop ] = touch[ prop ];
+ }
+ }
+ }
+
+ return event;
+}
+
+function getVirtualBindingFlags( element ) {
+
+ var flags = {},
+ b, k;
+
+ while ( element ) {
+
+ b = $.data( element, dataPropertyName );
+
+ for ( k in b ) {
+ if ( b[ k ] ) {
+ flags[ k ] = flags.hasVirtualBinding = true;
+ }
+ }
+ element = element.parentNode;
+ }
+ return flags;
+}
+
+function getClosestElementWithVirtualBinding( element, eventType ) {
+ var b;
+ while ( element ) {
+
+ b = $.data( element, dataPropertyName );
+
+ if ( b && ( !eventType || b[ eventType ] ) ) {
+ return element;
+ }
+ element = element.parentNode;
+ }
+ return null;
+}
+
+function enableTouchBindings() {
+ blockTouchTriggers = false;
+}
+
+function disableTouchBindings() {
+ blockTouchTriggers = true;
+}
+
+function enableMouseBindings() {
+ lastTouchID = 0;
+ clickBlockList.length = 0;
+ blockMouseTriggers = false;
+
+ // When mouse bindings are enabled, our
+ // touch bindings are disabled.
+ disableTouchBindings();
+}
+
+function disableMouseBindings() {
+ // When mouse bindings are disabled, our
+ // touch bindings are enabled.
+ enableTouchBindings();
+}
+
+function startResetTimer() {
+ clearResetTimer();
+ resetTimerID = setTimeout( function() {
+ resetTimerID = 0;
+ enableMouseBindings();
+ }, $.vmouse.resetTimerDuration );
+}
+
+function clearResetTimer() {
+ if ( resetTimerID ) {
+ clearTimeout( resetTimerID );
+ resetTimerID = 0;
+ }
+}
+
+function triggerVirtualEvent( eventType, event, flags ) {
+ var ve;
+
+ if ( ( flags && flags[ eventType ] ) ||
+ ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
+
+ ve = createVirtualEvent( event, eventType );
+
+ $( event.target).trigger( ve );
+ }
+
+ return ve;
+}
+
+function mouseEventCallback( event ) {
+ var touchID = $.data( event.target, touchTargetPropertyName ),
+ ve;
+
+ if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) {
+ ve = triggerVirtualEvent( "v" + event.type, event );
+ if ( ve ) {
+ if ( ve.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ if ( ve.isPropagationStopped() ) {
+ event.stopPropagation();
+ }
+ if ( ve.isImmediatePropagationStopped() ) {
+ event.stopImmediatePropagation();
+ }
+ }
+ }
+}
+
+function handleTouchStart( event ) {
+
+ var touches = getNativeEvent( event ).touches,
+ target, flags, t;
+
+ if ( touches && touches.length === 1 ) {
+
+ target = event.target;
+ flags = getVirtualBindingFlags( target );
+
+ if ( flags.hasVirtualBinding ) {
+
+ lastTouchID = nextTouchID++;
+ $.data( target, touchTargetPropertyName, lastTouchID );
+
+ clearResetTimer();
+
+ disableMouseBindings();
+ didScroll = false;
+
+ t = getNativeEvent( event ).touches[ 0 ];
+ startX = t.pageX;
+ startY = t.pageY;
+
+ triggerVirtualEvent( "vmouseover", event, flags );
+ triggerVirtualEvent( "vmousedown", event, flags );
+ }
+ }
+}
+
+function handleScroll( event ) {
+ if ( blockTouchTriggers ) {
+ return;
+ }
+
+ if ( !didScroll ) {
+ triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) );
+ }
+
+ didScroll = true;
+ startResetTimer();
+}
+
+function handleTouchMove( event ) {
+ if ( blockTouchTriggers ) {
+ return;
+ }
+
+ var t = getNativeEvent( event ).touches[ 0 ],
+ didCancel = didScroll,
+ moveThreshold = $.vmouse.moveDistanceThreshold,
+ flags = getVirtualBindingFlags( event.target );
+
+ didScroll = didScroll ||
+ ( Math.abs( t.pageX - startX ) > moveThreshold ||
+ Math.abs( t.pageY - startY ) > moveThreshold );
+
+ if ( didScroll && !didCancel ) {
+ triggerVirtualEvent( "vmousecancel", event, flags );
+ }
+
+ triggerVirtualEvent( "vmousemove", event, flags );
+ startResetTimer();
+}
+
+function handleTouchEnd( event ) {
+ if ( blockTouchTriggers ) {
+ return;
+ }
+
+ disableTouchBindings();
+
+ var flags = getVirtualBindingFlags( event.target ),
+ ve, t;
+ triggerVirtualEvent( "vmouseup", event, flags );
+
+ if ( !didScroll ) {
+ ve = triggerVirtualEvent( "vclick", event, flags );
+ if ( ve && ve.isDefaultPrevented() ) {
+ // The target of the mouse events that follow the touchend
+ // event don't necessarily match the target used during the
+ // touch. This means we need to rely on coordinates for blocking
+ // any click that is generated.
+ t = getNativeEvent( event ).changedTouches[ 0 ];
+ clickBlockList.push({
+ touchID: lastTouchID,
+ x: t.clientX,
+ y: t.clientY
+ });
+
+ // Prevent any mouse events that follow from triggering
+ // virtual event notifications.
+ blockMouseTriggers = true;
+ }
+ }
+ triggerVirtualEvent( "vmouseout", event, flags);
+ didScroll = false;
+
+ startResetTimer();
+}
+
+function hasVirtualBindings( ele ) {
+ var bindings = $.data( ele, dataPropertyName ),
+ k;
+
+ if ( bindings ) {
+ for ( k in bindings ) {
+ if ( bindings[ k ] ) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+function dummyMouseHandler() {}
+
+function getSpecialEventObject( eventType ) {
+ var realType = eventType.substr( 1 );
+
+ return {
+ setup: function(/* data, namespace */) {
+ // If this is the first virtual mouse binding for this element,
+ // add a bindings object to its data.
+
+ if ( !hasVirtualBindings( this ) ) {
+ $.data( this, dataPropertyName, {} );
+ }
+
+ // If setup is called, we know it is the first binding for this
+ // eventType, so initialize the count for the eventType to zero.
+ var bindings = $.data( this, dataPropertyName );
+ bindings[ eventType ] = true;
+
+ // If this is the first virtual mouse event for this type,
+ // register a global handler on the document.
+
+ activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;
+
+ if ( activeDocHandlers[ eventType ] === 1 ) {
+ $document.bind( realType, mouseEventCallback );
+ }
+
+ // Some browsers, like Opera Mini, won't dispatch mouse/click events
+ // for elements unless they actually have handlers registered on them.
+ // To get around this, we register dummy handlers on the elements.
+
+ $( this ).bind( realType, dummyMouseHandler );
+
+ // For now, if event capture is not supported, we rely on mouse handlers.
+ if ( eventCaptureSupported ) {
+ // If this is the first virtual mouse binding for the document,
+ // register our touchstart handler on the document.
+
+ activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1;
+
+ if ( activeDocHandlers[ "touchstart" ] === 1 ) {
+ $document.bind( "touchstart", handleTouchStart )
+ .bind( "touchend", handleTouchEnd )
+
+ // On touch platforms, touching the screen and then dragging your finger
+ // causes the window content to scroll after some distance threshold is
+ // exceeded. On these platforms, a scroll prevents a click event from being
+ // dispatched, and on some platforms, even the touchend is suppressed. To
+ // mimic the suppression of the click event, we need to watch for a scroll
+ // event. Unfortunately, some platforms like iOS don't dispatch scroll
+ // events until *AFTER* the user lifts their finger (touchend). This means
+ // we need to watch both scroll and touchmove events to figure out whether
+ // or not a scroll happenens before the touchend event is fired.
+
+ .bind( "touchmove", handleTouchMove )
+ .bind( "scroll", handleScroll );
+ }
+ }
+ },
+
+ teardown: function(/* data, namespace */) {
+ // If this is the last virtual binding for this eventType,
+ // remove its global handler from the document.
+
+ --activeDocHandlers[ eventType ];
+
+ if ( !activeDocHandlers[ eventType ] ) {
+ $document.unbind( realType, mouseEventCallback );
+ }
+
+ if ( eventCaptureSupported ) {
+ // If this is the last virtual mouse binding in existence,
+ // remove our document touchstart listener.
+
+ --activeDocHandlers[ "touchstart" ];
+
+ if ( !activeDocHandlers[ "touchstart" ] ) {
+ $document.unbind( "touchstart", handleTouchStart )
+ .unbind( "touchmove", handleTouchMove )
+ .unbind( "touchend", handleTouchEnd )
+ .unbind( "scroll", handleScroll );
+ }
+ }
+
+ var $this = $( this ),
+ bindings = $.data( this, dataPropertyName );
+
+ // teardown may be called when an element was
+ // removed from the DOM. If this is the case,
+ // jQuery core may have already stripped the element
+ // of any data bindings so we need to check it before
+ // using it.
+ if ( bindings ) {
+ bindings[ eventType ] = false;
+ }
+
+ // Unregister the dummy event handler.
+
+ $this.unbind( realType, dummyMouseHandler );
+
+ // If this is the last virtual mouse binding on the
+ // element, remove the binding data from the element.
+
+ if ( !hasVirtualBindings( this ) ) {
+ $this.removeData( dataPropertyName );
+ }
+ }
+ };
+}
+
+// Expose our custom events to the jQuery bind/unbind mechanism.
+
+for ( i = 0; i < virtualEventNames.length; i++ ) {
+ $.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );
+}
+
+// Add a capture click handler to block clicks.
+// Note that we require event capture support for this so if the device
+// doesn't support it, we punt for now and rely solely on mouse events.
+if ( eventCaptureSupported ) {
+ document.addEventListener( "click", function( e ) {
+ var cnt = clickBlockList.length,
+ target = e.target,
+ x, y, ele, i, o, touchID;
+
+ if ( cnt ) {
+ x = e.clientX;
+ y = e.clientY;
+ threshold = $.vmouse.clickDistanceThreshold;
+
+ // The idea here is to run through the clickBlockList to see if
+ // the current click event is in the proximity of one of our
+ // vclick events that had preventDefault() called on it. If we find
+ // one, then we block the click.
+ //
+ // Why do we have to rely on proximity?
+ //
+ // Because the target of the touch event that triggered the vclick
+ // can be different from the target of the click event synthesized
+ // by the browser. The target of a mouse/click event that is synthesized
+ // from a touch event seems to be implementation specific. For example,
+ // some browsers will fire mouse/click events for a link that is near
+ // a touch event, even though the target of the touchstart/touchend event
+ // says the user touched outside the link. Also, it seems that with most
+ // browsers, the target of the mouse/click event is not calculated until the
+ // time it is dispatched, so if you replace an element that you touched
+ // with another element, the target of the mouse/click will be the new
+ // element underneath that point.
+ //
+ // Aside from proximity, we also check to see if the target and any
+ // of its ancestors were the ones that blocked a click. This is necessary
+ // because of the strange mouse/click target calculation done in the
+ // Android 2.1 browser, where if you click on an element, and there is a
+ // mouse/click handler on one of its ancestors, the target will be the
+ // innermost child of the touched element, even if that child is no where
+ // near the point of touch.
+
+ ele = target;
+
+ while ( ele ) {
+ for ( i = 0; i < cnt; i++ ) {
+ o = clickBlockList[ i ];
+ touchID = 0;
+
+ if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||
+ $.data( ele, touchTargetPropertyName ) === o.touchID ) {
+ // XXX: We may want to consider removing matches from the block list
+ // instead of waiting for the reset timer to fire.
+ e.preventDefault();
+ e.stopPropagation();
+ return;
+ }
+ }
+ ele = ele.parentNode;
+ }
+ }
+ }, true);
+}
+})( jQuery, window, document );
+
+(function( $ ) {
+ $.mobile = {};
+}( jQuery ));
+
+ (function( $, undefined ) {
+ var support = {
+ touch: "ontouchend" in document
+ };
+
+ $.mobile.support = $.mobile.support || {};
+ $.extend( $.support, support );
+ $.extend( $.mobile.support, support );
+ }( jQuery ));
+
+
+(function( $, window, undefined ) {
+ var $document = $( document ),
+ supportTouch = $.mobile.support.touch,
+ scrollEvent = "touchmove scroll",
+ touchStartEvent = supportTouch ? "touchstart" : "mousedown",
+ touchStopEvent = supportTouch ? "touchend" : "mouseup",
+ touchMoveEvent = supportTouch ? "touchmove" : "mousemove";
+
+ // setup new event shortcuts
+ $.each( ( "touchstart touchmove touchend " +
+ "tap taphold " +
+ "swipe swipeleft swiperight " +
+ "scrollstart scrollstop" ).split( " " ), function( i, name ) {
+
+ $.fn[ name ] = function( fn ) {
+ return fn ? this.bind( name, fn ) : this.trigger( name );
+ };
+
+ // jQuery < 1.8
+ if ( $.attrFn ) {
+ $.attrFn[ name ] = true;
+ }
+ });
+
+ function triggerCustomEvent( obj, eventType, event, bubble ) {
+ var originalType = event.type;
+ event.type = eventType;
+ if ( bubble ) {
+ $.event.trigger( event, undefined, obj );
+ } else {
+ $.event.dispatch.call( obj, event );
+ }
+ event.type = originalType;
+ }
+
+ // also handles scrollstop
+ $.event.special.scrollstart = {
+
+ enabled: true,
+ setup: function() {
+
+ var thisObject = this,
+ $this = $( thisObject ),
+ scrolling,
+ timer;
+
+ function trigger( event, state ) {
+ scrolling = state;
+ triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );
+ }
+
+ // iPhone triggers scroll after a small delay; use touchmove instead
+ $this.bind( scrollEvent, function( event ) {
+
+ if ( !$.event.special.scrollstart.enabled ) {
+ return;
+ }
+
+ if ( !scrolling ) {
+ trigger( event, true );
+ }
+
+ clearTimeout( timer );
+ timer = setTimeout( function() {
+ trigger( event, false );
+ }, 50 );
+ });
+ },
+ teardown: function() {
+ $( this ).unbind( scrollEvent );
+ }
+ };
+
+ // also handles taphold
+ $.event.special.tap = {
+ tapholdThreshold: 750,
+ emitTapOnTaphold: true,
+ setup: function() {
+ var thisObject = this,
+ $this = $( thisObject ),
+ isTaphold = false;
+
+ $this.bind( "vmousedown", function( event ) {
+ isTaphold = false;
+ if ( event.which && event.which !== 1 ) {
+ return false;
+ }
+
+ var origTarget = event.target,
+ timer;
+
+ function clearTapTimer() {
+ clearTimeout( timer );
+ }
+
+ function clearTapHandlers() {
+ clearTapTimer();
+
+ $this.unbind( "vclick", clickHandler )
+ .unbind( "vmouseup", clearTapTimer );
+ $document.unbind( "vmousecancel", clearTapHandlers );
+ }
+
+ function clickHandler( event ) {
+ clearTapHandlers();
+
+ // ONLY trigger a 'tap' event if the start target is
+ // the same as the stop target.
+ if ( !isTaphold && origTarget === event.target ) {
+ triggerCustomEvent( thisObject, "tap", event );
+ } else if ( isTaphold ) {
+ event.preventDefault();
+ }
+ }
+
+ $this.bind( "vmouseup", clearTapTimer )
+ .bind( "vclick", clickHandler );
+ $document.bind( "vmousecancel", clearTapHandlers );
+
+ timer = setTimeout( function() {
+ if ( !$.event.special.tap.emitTapOnTaphold ) {
+ isTaphold = true;
+ }
+ triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
+ }, $.event.special.tap.tapholdThreshold );
+ });
+ },
+ teardown: function() {
+ $( this ).unbind( "vmousedown" ).unbind( "vclick" ).unbind( "vmouseup" );
+ $document.unbind( "vmousecancel" );
+ }
+ };
+
+ // Also handles swipeleft, swiperight
+ $.event.special.swipe = {
+
+ // More than this horizontal displacement, and we will suppress scrolling.
+ scrollSupressionThreshold: 30,
+
+ // More time than this, and it isn't a swipe.
+ durationThreshold: 1000,
+
+ // Swipe horizontal displacement must be more than this.
+ horizontalDistanceThreshold: 30,
+
+ // Swipe vertical displacement must be less than this.
+ verticalDistanceThreshold: 30,
+
+ getLocation: function ( event ) {
+ var winPageX = window.pageXOffset,
+ winPageY = window.pageYOffset,
+ x = event.clientX,
+ y = event.clientY;
+
+ if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) ||
+ event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) {
+
+ // iOS4 clientX/clientY have the value that should have been
+ // in pageX/pageY. While pageX/page/ have the value 0
+ x = x - winPageX;
+ y = y - winPageY;
+ } else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) {
+
+ // Some Android browsers have totally bogus values for clientX/Y
+ // when scrolling/zooming a page. Detectable since clientX/clientY
+ // should never be smaller than pageX/pageY minus page scroll
+ x = event.pageX - winPageX;
+ y = event.pageY - winPageY;
+ }
+
+ return {
+ x: x,
+ y: y
+ };
+ },
+
+ start: function( event ) {
+ var data = event.originalEvent.touches ?
+ event.originalEvent.touches[ 0 ] : event,
+ location = $.event.special.swipe.getLocation( data );
+ return {
+ time: ( new Date() ).getTime(),
+ coords: [ location.x, location.y ],
+ origin: $( event.target )
+ };
+ },
+
+ stop: function( event ) {
+ var data = event.originalEvent.touches ?
+ event.originalEvent.touches[ 0 ] : event,
+ location = $.event.special.swipe.getLocation( data );
+ return {
+ time: ( new Date() ).getTime(),
+ coords: [ location.x, location.y ]
+ };
+ },
+
+ handleSwipe: function( start, stop, thisObject, origTarget ) {
+ if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
+ Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&
+ Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {
+ var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight";
+
+ triggerCustomEvent( thisObject, "swipe", $.Event( "swipe", { target: origTarget, swipestart: start, swipestop: stop }), true );
+ triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true );
+ return true;
+ }
+ return false;
+
+ },
+
+ // This serves as a flag to ensure that at most one swipe event event is
+ // in work at any given time
+ eventInProgress: false,
+
+ setup: function() {
+ var events,
+ thisObject = this,
+ $this = $( thisObject ),
+ context = {};
+
+ // Retrieve the events data for this element and add the swipe context
+ events = $.data( this, "mobile-events" );
+ if ( !events ) {
+ events = { length: 0 };
+ $.data( this, "mobile-events", events );
+ }
+ events.length++;
+ events.swipe = context;
+
+ context.start = function( event ) {
+
+ // Bail if we're already working on a swipe event
+ if ( $.event.special.swipe.eventInProgress ) {
+ return;
+ }
+ $.event.special.swipe.eventInProgress = true;
+
+ var stop,
+ start = $.event.special.swipe.start( event ),
+ origTarget = event.target,
+ emitted = false;
+
+ context.move = function( event ) {
+ if ( !start || event.isDefaultPrevented() ) {
+ return;
+ }
+
+ stop = $.event.special.swipe.stop( event );
+ if ( !emitted ) {
+ emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget );
+ if ( emitted ) {
+
+ // Reset the context to make way for the next swipe event
+ $.event.special.swipe.eventInProgress = false;
+ }
+ }
+ // prevent scrolling
+ if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
+ event.preventDefault();
+ }
+ };
+
+ context.stop = function() {
+ emitted = true;
+
+ // Reset the context to make way for the next swipe event
+ $.event.special.swipe.eventInProgress = false;
+ $document.off( touchMoveEvent, context.move );
+ context.move = null;
+ };
+
+ $document.on( touchMoveEvent, context.move )
+ .one( touchStopEvent, context.stop );
+ };
+ $this.on( touchStartEvent, context.start );
+ },
+
+ teardown: function() {
+ var events, context;
+
+ events = $.data( this, "mobile-events" );
+ if ( events ) {
+ context = events.swipe;
+ delete events.swipe;
+ events.length--;
+ if ( events.length === 0 ) {
+ $.removeData( this, "mobile-events" );
+ }
+ }
+
+ if ( context ) {
+ if ( context.start ) {
+ $( this ).off( touchStartEvent, context.start );
+ }
+ if ( context.move ) {
+ $document.off( touchMoveEvent, context.move );
+ }
+ if ( context.stop ) {
+ $document.off( touchStopEvent, context.stop );
+ }
+ }
+ }
+ };
+ $.each({
+ scrollstop: "scrollstart",
+ taphold: "tap",
+ swipeleft: "swipe.left",
+ swiperight: "swipe.right"
+ }, function( event, sourceEvent ) {
+
+ $.event.special[ event ] = {
+ setup: function() {
+ $( this ).bind( sourceEvent, $.noop );
+ },
+ teardown: function() {
+ $( this ).unbind( sourceEvent );
+ }
+ };
+ });
+
+})( jQuery, this );
+
+
+}));
diff --git a/web/public/assets/js/knockout.js b/web/public/assets/js/knockout.js
new file mode 100644
index 0000000..059d58f
--- /dev/null
+++ b/web/public/assets/js/knockout.js
@@ -0,0 +1,123 @@
+/*!
+ * Knockout JavaScript library v3.4.0
+ * (c) Steven Sanderson - http://knockoutjs.com/
+ * License: MIT (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+(function() {(function(n){var x=this||(0,eval)("this"),u=x.document,M=x.navigator,v=x.jQuery,F=x.JSON;(function(n){"function"===typeof define&&define.amd?define(["exports","require"],n):"object"===typeof exports&&"object"===typeof module?n(module.exports||exports):n(x.ko={})})(function(N,O){function J(a,c){return null===a||typeof a in T?a===c:!1}function U(b,c){var d;return function(){d||(d=a.a.setTimeout(function(){d=n;b()},c))}}function V(b,c){var d;return function(){clearTimeout(d);d=a.a.setTimeout(b,c)}}function W(a,
+c){c&&c!==I?"beforeChange"===c?this.Kb(a):this.Ha(a,c):this.Lb(a)}function X(a,c){null!==c&&c.k&&c.k()}function Y(a,c){var d=this.Hc,e=d[s];e.R||(this.lb&&this.Ma[c]?(d.Pb(c,a,this.Ma[c]),this.Ma[c]=null,--this.lb):e.r[c]||d.Pb(c,a,e.s?{ia:a}:d.uc(a)))}function K(b,c,d,e){a.d[b]={init:function(b,g,k,l,m){var h,r;a.m(function(){var q=a.a.c(g()),p=!d!==!q,A=!r;if(A||c||p!==h)A&&a.va.Aa()&&(r=a.a.ua(a.f.childNodes(b),!0)),p?(A||a.f.da(b,a.a.ua(r)),a.eb(e?e(m,q):m,b)):a.f.xa(b),h=p},null,{i:b});return{controlsDescendantBindings:!0}}};
+a.h.ta[b]=!1;a.f.Z[b]=!0}var a="undefined"!==typeof N?N:{};a.b=function(b,c){for(var d=b.split("."),e=a,f=0;f a.a.o(c,b[d])&&c.push(b[d]);return c},fb:function(a,b){a=a||[];for(var c=[],d=0,e=a.length;de?d&&b.push(c):d||b.splice(e,1)},ka:f,extend:c,Xa:d,Ya:f?d:c,D:b,Ca:function(a,b){if(!a)return a;var c={},d;for(d in a)a.hasOwnProperty(d)&&(c[d]=b(a[d],d,a));return c},ob:function(b){for(;b.firstChild;)a.removeNode(b.firstChild)},jc:function(b){b=a.a.V(b);for(var c=(b[0]&&b[0].ownerDocument||u).createElement("div"),d=0,e=b.length;dh?a.setAttribute("selected",b):a.selected=b},$a:function(a){return null===a||a===n?"":a.trim?a.trim():a.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g,"")},nd:function(a,b){a=a||"";return b.length>a.length?!1:a.substring(0,b.length)===b},Mc:function(a,b){if(a===b)return!0;if(11===a.nodeType)return!1;if(b.contains)return b.contains(3===a.nodeType?a.parentNode:a);if(b.compareDocumentPosition)return 16==(b.compareDocumentPosition(a)&16);for(;a&&a!=
+b;)a=a.parentNode;return!!a},nb:function(b){return a.a.Mc(b,b.ownerDocument.documentElement)},Qb:function(b){return!!a.a.Sb(b,a.a.nb)},A:function(a){return a&&a.tagName&&a.tagName.toLowerCase()},Wb:function(b){return a.onError?function(){try{return b.apply(this,arguments)}catch(c){throw a.onError&&a.onError(c),c;}}:b},setTimeout:function(b,c){return setTimeout(a.a.Wb(b),c)},$b:function(b){setTimeout(function(){a.onError&&a.onError(b);throw b;},0)},p:function(b,c,d){var e=a.a.Wb(d);d=h&&m[c];if(a.options.useOnlyNativeEvents||
+d||!v)if(d||"function"!=typeof b.addEventListener)if("undefined"!=typeof b.attachEvent){var l=function(a){e.call(b,a)},f="on"+c;b.attachEvent(f,l);a.a.F.oa(b,function(){b.detachEvent(f,l)})}else throw Error("Browser doesn't support addEventListener or attachEvent");else b.addEventListener(c,e,!1);else v(b).bind(c,e)},Da:function(b,c){if(!b||!b.nodeType)throw Error("element must be a DOM node when calling triggerEvent");var d;"input"===a.a.A(b)&&b.type&&"click"==c.toLowerCase()?(d=b.type,d="checkbox"==
+d||"radio"==d):d=!1;if(a.options.useOnlyNativeEvents||!v||d)if("function"==typeof u.createEvent)if("function"==typeof b.dispatchEvent)d=u.createEvent(l[c]||"HTMLEvents"),d.initEvent(c,!0,!0,x,0,0,0,0,0,!1,!1,!1,!1,0,b),b.dispatchEvent(d);else throw Error("The supplied element doesn't support dispatchEvent");else if(d&&b.click)b.click();else if("undefined"!=typeof b.fireEvent)b.fireEvent("on"+c);else throw Error("Browser doesn't support triggering events");else v(b).trigger(c)},c:function(b){return a.H(b)?
+b():b},zb:function(b){return a.H(b)?b.t():b},bb:function(b,c,d){var h;c&&("object"===typeof b.classList?(h=b.classList[d?"add":"remove"],a.a.q(c.match(r),function(a){h.call(b.classList,a)})):"string"===typeof b.className.baseVal?e(b.className,"baseVal",c,d):e(b,"className",c,d))},Za:function(b,c){var d=a.a.c(c);if(null===d||d===n)d="";var e=a.f.firstChild(b);!e||3!=e.nodeType||a.f.nextSibling(e)?a.f.da(b,[b.ownerDocument.createTextNode(d)]):e.data=d;a.a.Rc(b)},rc:function(a,b){a.name=b;if(7>=h)try{a.mergeAttributes(u.createElement(" "),!1)}catch(c){}},Rc:function(a){9<=h&&(a=1==a.nodeType?a:a.parentNode,a.style&&(a.style.zoom=a.style.zoom))},Nc:function(a){if(h){var b=a.style.width;a.style.width=0;a.style.width=b}},hd:function(b,c){b=a.a.c(b);c=a.a.c(c);for(var d=[],e=b;e<=c;e++)d.push(e);return d},V:function(a){for(var b=[],c=0,d=a.length;c",""],d=[3,""],e=[1,""," "],f={thead:c,tbody:c,tfoot:c,tr:[2,""],td:d,th:d,option:e,optgroup:e},
+g=8>=a.a.C;a.a.ma=function(c,d){var e;if(v)if(v.parseHTML)e=v.parseHTML(c,d)||[];else{if((e=v.clean([c],d))&&e[0]){for(var h=e[0];h.parentNode&&11!==h.parentNode.nodeType;)h=h.parentNode;h.parentNode&&h.parentNode.removeChild(h)}}else{(e=d)||(e=u);var h=e.parentWindow||e.defaultView||x,r=a.a.$a(c).toLowerCase(),q=e.createElement("div"),p;p=(r=r.match(/^<([a-z]+)[ >]/))&&f[r[1]]||b;r=p[0];p="ignored"+p[1]+c+p[2]+"
";"function"==typeof h.innerShiv?q.appendChild(h.innerShiv(p)):(g&&e.appendChild(q),
+q.innerHTML=p,g&&q.parentNode.removeChild(q));for(;r--;)q=q.lastChild;e=a.a.V(q.lastChild.childNodes)}return e};a.a.Cb=function(b,c){a.a.ob(b);c=a.a.c(c);if(null!==c&&c!==n)if("string"!=typeof c&&(c=c.toString()),v)v(b).html(c);else for(var d=a.a.ma(c,b.ownerDocument),e=0;eb){if(5E3<=++c){g=e;a.a.$b(Error("'Too much recursion' after processing "+c+" task groups."));break}b=e}try{m()}catch(h){a.a.$b(h)}}}function c(){b();g=e=d.length=0}var d=[],e=0,f=1,g=0;return{scheduler:x.MutationObserver?function(a){var b=u.createElement("div");(new MutationObserver(a)).observe(b,{attributes:!0});return function(){b.classList.toggle("foo")}}(c):u&&"onreadystatechange"in u.createElement("script")?function(a){var b=u.createElement("script");b.onreadystatechange=
+function(){b.onreadystatechange=null;u.documentElement.removeChild(b);b=null;a()};u.documentElement.appendChild(b)}:function(a){setTimeout(a,0)},Wa:function(b){e||a.Y.scheduler(c);d[e++]=b;return f++},cancel:function(a){a-=f-e;a>=g&&ad[0]?g+d[0]:d[0]),g);for(var g=1===t?g:Math.min(c+(d[1]||0),g),t=c+t-2,G=Math.max(g,t),P=[],n=[],Q=2;cc;c++)b=b();return b})};a.toJSON=function(b,c,d){b=a.wc(b);return a.a.Eb(b,c,d)};d.prototype={save:function(b,c){var d=a.a.o(this.keys,b);0<=d?this.Ib[d]=c:(this.keys.push(b),this.Ib.push(c))},get:function(b){b=a.a.o(this.keys,b);return 0<=b?this.Ib[b]:n}}})();a.b("toJS",a.wc);a.b("toJSON",a.toJSON);(function(){a.j={u:function(b){switch(a.a.A(b)){case "option":return!0===b.__ko__hasDomDataOptionValue__?a.a.e.get(b,a.d.options.xb):7>=a.a.C?b.getAttributeNode("value")&&
+b.getAttributeNode("value").specified?b.value:b.text:b.value;case "select":return 0<=b.selectedIndex?a.j.u(b.options[b.selectedIndex]):n;default:return b.value}},ha:function(b,c,d){switch(a.a.A(b)){case "option":switch(typeof c){case "string":a.a.e.set(b,a.d.options.xb,n);"__ko__hasDomDataOptionValue__"in b&&delete b.__ko__hasDomDataOptionValue__;b.value=c;break;default:a.a.e.set(b,a.d.options.xb,c),b.__ko__hasDomDataOptionValue__=!0,b.value="number"===typeof c?c:""}break;case "select":if(""===c||
+null===c)c=n;for(var e=-1,f=0,g=b.options.length,k;f=p){c.push(r&&k.length?{key:r,value:k.join("")}:{unknown:r||k.join("")});r=p=0;k=[];continue}}else if(58===t){if(!p&&!r&&1===k.length){r=k.pop();continue}}else 47===t&&A&&1=a.a.C&&b.tagName===c))return c};a.g.Ob=function(c,e,f,g){if(1===e.nodeType){var k=a.g.getComponentNameForNode(e);if(k){c=c||{};if(c.component)throw Error('Cannot use the "component" binding on a custom element matching a component');
+var l={name:k,params:b(e,f)};c.component=g?function(){return l}:l}}return c};var c=new a.Q;9>a.a.C&&(a.g.register=function(a){return function(b){u.createElement(b);return a.apply(this,arguments)}}(a.g.register),u.createDocumentFragment=function(b){return function(){var c=b(),f=a.g.Bc,g;for(g in f)f.hasOwnProperty(g)&&c.createElement(g);return c}}(u.createDocumentFragment))})();(function(b){function c(b,c,d){c=c.template;if(!c)throw Error("Component '"+b+"' has no template");b=a.a.ua(c);a.f.da(d,b)}
+function d(a,b,c,d){var e=a.createViewModel;return e?e.call(a,d,{element:b,templateNodes:c}):d}var e=0;a.d.component={init:function(f,g,k,l,m){function h(){var a=r&&r.dispose;"function"===typeof a&&a.call(r);q=r=null}var r,q,p=a.a.V(a.f.childNodes(f));a.a.F.oa(f,h);a.m(function(){var l=a.a.c(g()),k,t;"string"===typeof l?k=l:(k=a.a.c(l.name),t=a.a.c(l.params));if(!k)throw Error("No component name specified");var n=q=++e;a.g.get(k,function(e){if(q===n){h();if(!e)throw Error("Unknown component '"+k+
+"'");c(k,e,f);var g=d(e,f,p,t);e=m.createChildContext(g,b,function(a){a.$component=g;a.$componentTemplateNodes=p});r=g;a.eb(e,f)}})},null,{i:f});return{controlsDescendantBindings:!0}}};a.f.Z.component=!0})();var S={"class":"className","for":"htmlFor"};a.d.attr={update:function(b,c){var d=a.a.c(c())||{};a.a.D(d,function(c,d){d=a.a.c(d);var g=!1===d||null===d||d===n;g&&b.removeAttribute(c);8>=a.a.C&&c in S?(c=S[c],g?b.removeAttribute(c):b[c]=d):g||b.setAttribute(c,d.toString());"name"===c&&a.a.rc(b,
+g?"":d.toString())})}};(function(){a.d.checked={after:["value","attr"],init:function(b,c,d){function e(){var e=b.checked,f=p?g():e;if(!a.va.Sa()&&(!l||e)){var m=a.l.w(c);if(h){var k=r?m.t():m;q!==f?(e&&(a.a.pa(k,f,!0),a.a.pa(k,q,!1)),q=f):a.a.pa(k,f,e);r&&a.Ba(m)&&m(k)}else a.h.Ea(m,d,"checked",f,!0)}}function f(){var d=a.a.c(c());b.checked=h?0<=a.a.o(d,g()):k?d:g()===d}var g=a.nc(function(){return d.has("checkedValue")?a.a.c(d.get("checkedValue")):d.has("value")?a.a.c(d.get("value")):b.value}),k=
+"checkbox"==b.type,l="radio"==b.type;if(k||l){var m=c(),h=k&&a.a.c(m)instanceof Array,r=!(h&&m.push&&m.splice),q=h?g():n,p=l||h;l&&!b.name&&a.d.uniqueName.init(b,function(){return!0});a.m(e,null,{i:b});a.a.p(b,"click",e);a.m(f,null,{i:b});m=n}}};a.h.ea.checked=!0;a.d.checkedValue={update:function(b,c){b.value=a.a.c(c())}}})();a.d.css={update:function(b,c){var d=a.a.c(c());null!==d&&"object"==typeof d?a.a.D(d,function(c,d){d=a.a.c(d);a.a.bb(b,c,d)}):(d=a.a.$a(String(d||"")),a.a.bb(b,b.__ko__cssValue,
+!1),b.__ko__cssValue=d,a.a.bb(b,d,!0))}};a.d.enable={update:function(b,c){var d=a.a.c(c());d&&b.disabled?b.removeAttribute("disabled"):d||b.disabled||(b.disabled=!0)}};a.d.disable={update:function(b,c){a.d.enable.update(b,function(){return!a.a.c(c())})}};a.d.event={init:function(b,c,d,e,f){var g=c()||{};a.a.D(g,function(g){"string"==typeof g&&a.a.p(b,g,function(b){var m,h=c()[g];if(h){try{var r=a.a.V(arguments);e=f.$data;r.unshift(e);m=h.apply(e,r)}finally{!0!==m&&(b.preventDefault?b.preventDefault():
+b.returnValue=!1)}!1===d.get(g+"Bubble")&&(b.cancelBubble=!0,b.stopPropagation&&b.stopPropagation())}})})}};a.d.foreach={ic:function(b){return function(){var c=b(),d=a.a.zb(c);if(!d||"number"==typeof d.length)return{foreach:c,templateEngine:a.W.sb};a.a.c(c);return{foreach:d.data,as:d.as,includeDestroyed:d.includeDestroyed,afterAdd:d.afterAdd,beforeRemove:d.beforeRemove,afterRender:d.afterRender,beforeMove:d.beforeMove,afterMove:d.afterMove,templateEngine:a.W.sb}}},init:function(b,c){return a.d.template.init(b,
+a.d.foreach.ic(c))},update:function(b,c,d,e,f){return a.d.template.update(b,a.d.foreach.ic(c),d,e,f)}};a.h.ta.foreach=!1;a.f.Z.foreach=!0;a.d.hasfocus={init:function(b,c,d){function e(e){b.__ko_hasfocusUpdating=!0;var f=b.ownerDocument;if("activeElement"in f){var g;try{g=f.activeElement}catch(h){g=f.body}e=g===b}f=c();a.h.Ea(f,d,"hasfocus",e,!0);b.__ko_hasfocusLastValue=e;b.__ko_hasfocusUpdating=!1}var f=e.bind(null,!0),g=e.bind(null,!1);a.a.p(b,"focus",f);a.a.p(b,"focusin",f);a.a.p(b,"blur",g);a.a.p(b,
+"focusout",g)},update:function(b,c){var d=!!a.a.c(c());b.__ko_hasfocusUpdating||b.__ko_hasfocusLastValue===d||(d?b.focus():b.blur(),!d&&b.__ko_hasfocusLastValue&&b.ownerDocument.body.focus(),a.l.w(a.a.Da,null,[b,d?"focusin":"focusout"]))}};a.h.ea.hasfocus=!0;a.d.hasFocus=a.d.hasfocus;a.h.ea.hasFocus=!0;a.d.html={init:function(){return{controlsDescendantBindings:!0}},update:function(b,c){a.a.Cb(b,c())}};K("if");K("ifnot",!1,!0);K("with",!0,!1,function(a,c){return a.createChildContext(c)});var L={};
+a.d.options={init:function(b){if("select"!==a.a.A(b))throw Error("options binding applies only to SELECT elements");for(;0a.a.C)var g=a.a.e.I(),k=a.a.e.I(),l=function(b){var c=this.activeElement;(c=c&&a.a.e.get(c,k))&&c(b)},m=function(b,c){var d=b.ownerDocument;a.a.e.get(d,g)||(a.a.e.set(d,g,!0),a.a.p(d,"selectionchange",l));a.a.e.set(b,k,c)};a.d.textInput={init:function(b,d,g){function l(c,d){a.a.p(b,c,d)}function k(){var c=a.a.c(d());if(null===c||c===n)c="";v!==n&&c===v?a.a.setTimeout(k,4):b.value!==c&&(u=c,b.value=c)}function y(){s||(v=b.value,s=a.a.setTimeout(t,4))}function t(){clearTimeout(s);v=s=n;var c=
+b.value;u!==c&&(u=c,a.h.Ea(d(),g,"textInput",c))}var u=b.value,s,v,x=9==a.a.C?y:t;10>a.a.C?(l("propertychange",function(a){"value"===a.propertyName&&x(a)}),8==a.a.C&&(l("keyup",t),l("keydown",t)),8<=a.a.C&&(m(b,x),l("dragend",y))):(l("input",t),5>e&&"textarea"===a.a.A(b)?(l("keydown",y),l("paste",y),l("cut",y)):11>c?l("keydown",y):4>f&&(l("DOMAutoComplete",t),l("dragdrop",t),l("drop",t)));l("change",t);a.m(k,null,{i:b})}};a.h.ea.textInput=!0;a.d.textinput={preprocess:function(a,b,c){c("textInput",
+a)}}})();a.d.uniqueName={init:function(b,c){if(c()){var d="ko_unique_"+ ++a.d.uniqueName.Ic;a.a.rc(b,d)}}};a.d.uniqueName.Ic=0;a.d.value={after:["options","foreach"],init:function(b,c,d){if("input"!=b.tagName.toLowerCase()||"checkbox"!=b.type&&"radio"!=b.type){var e=["change"],f=d.get("valueUpdate"),g=!1,k=null;f&&("string"==typeof f&&(f=[f]),a.a.ra(e,f),e=a.a.Tb(e));var l=function(){k=null;g=!1;var e=c(),f=a.j.u(b);a.h.Ea(e,d,"value",f)};!a.a.C||"input"!=b.tagName.toLowerCase()||"text"!=b.type||
+"off"==b.autocomplete||b.form&&"off"==b.form.autocomplete||-1!=a.a.o(e,"propertychange")||(a.a.p(b,"propertychange",function(){g=!0}),a.a.p(b,"focus",function(){g=!1}),a.a.p(b,"blur",function(){g&&l()}));a.a.q(e,function(c){var d=l;a.a.nd(c,"after")&&(d=function(){k=a.j.u(b);a.a.setTimeout(l,0)},c=c.substring(5));a.a.p(b,c,d)});var m=function(){var e=a.a.c(c()),f=a.j.u(b);if(null!==k&&e===k)a.a.setTimeout(m,0);else if(e!==f)if("select"===a.a.A(b)){var g=d.get("valueAllowUnset"),f=function(){a.j.ha(b,
+e,g)};f();g||e===a.j.u(b)?a.a.setTimeout(f,0):a.l.w(a.a.Da,null,[b,"change"])}else a.j.ha(b,e)};a.m(m,null,{i:b})}else a.Ja(b,{checkedValue:c})},update:function(){}};a.h.ea.value=!0;a.d.visible={update:function(b,c){var d=a.a.c(c()),e="none"!=b.style.display;d&&!e?b.style.display="":!d&&e&&(b.style.display="none")}};(function(b){a.d[b]={init:function(c,d,e,f,g){return a.d.event.init.call(this,c,function(){var a={};a[b]=d();return a},e,f,g)}}})("click");a.O=function(){};a.O.prototype.renderTemplateSource=
+function(){throw Error("Override renderTemplateSource");};a.O.prototype.createJavaScriptEvaluatorBlock=function(){throw Error("Override createJavaScriptEvaluatorBlock");};a.O.prototype.makeTemplateSource=function(b,c){if("string"==typeof b){c=c||u;var d=c.getElementById(b);if(!d)throw Error("Cannot find template with ID "+b);return new a.v.n(d)}if(1==b.nodeType||8==b.nodeType)return new a.v.qa(b);throw Error("Unknown template type: "+b);};a.O.prototype.renderTemplate=function(a,c,d,e){a=this.makeTemplateSource(a,
+e);return this.renderTemplateSource(a,c,d,e)};a.O.prototype.isTemplateRewritten=function(a,c){return!1===this.allowTemplateRewriting?!0:this.makeTemplateSource(a,c).data("isRewritten")};a.O.prototype.rewriteTemplate=function(a,c,d){a=this.makeTemplateSource(a,d);c=c(a.text());a.text(c);a.data("isRewritten",!0)};a.b("templateEngine",a.O);a.Gb=function(){function b(b,c,d,k){b=a.h.yb(b);for(var l=a.h.ta,m=0;m]*))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,d=/\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;return{Oc:function(b,
+c,d){c.isTemplateRewritten(b,d)||c.rewriteTemplate(b,function(b){return a.Gb.dd(b,c)},d)},dd:function(a,f){return a.replace(c,function(a,c,d,e,h){return b(h,c,d,f)}).replace(d,function(a,c){return b(c,"\x3c!-- ko --\x3e","#comment",f)})},Ec:function(b,c){return a.M.wb(function(d,k){var l=d.nextSibling;l&&l.nodeName.toLowerCase()===c&&a.Ja(l,b,k)})}}}();a.b("__tr_ambtns",a.Gb.Ec);(function(){a.v={};a.v.n=function(b){if(this.n=b){var c=a.a.A(b);this.ab="script"===c?1:"textarea"===c?2:"template"==c&&
+b.content&&11===b.content.nodeType?3:4}};a.v.n.prototype.text=function(){var b=1===this.ab?"text":2===this.ab?"value":"innerHTML";if(0==arguments.length)return this.n[b];var c=arguments[0];"innerHTML"===b?a.a.Cb(this.n,c):this.n[b]=c};var b=a.a.e.I()+"_";a.v.n.prototype.data=function(c){if(1===arguments.length)return a.a.e.get(this.n,b+c);a.a.e.set(this.n,b+c,arguments[1])};var c=a.a.e.I();a.v.n.prototype.nodes=function(){var b=this.n;if(0==arguments.length)return(a.a.e.get(b,c)||{}).jb||(3===this.ab?
+b.content:4===this.ab?b:n);a.a.e.set(b,c,{jb:arguments[0]})};a.v.qa=function(a){this.n=a};a.v.qa.prototype=new a.v.n;a.v.qa.prototype.text=function(){if(0==arguments.length){var b=a.a.e.get(this.n,c)||{};b.Hb===n&&b.jb&&(b.Hb=b.jb.innerHTML);return b.Hb}a.a.e.set(this.n,c,{Hb:arguments[0]})};a.b("templateSources",a.v);a.b("templateSources.domElement",a.v.n);a.b("templateSources.anonymousTemplate",a.v.qa)})();(function(){function b(b,c,d){var e;for(c=a.f.nextSibling(c);b&&(e=b)!==c;)b=a.f.nextSibling(e),
+d(e,b)}function c(c,d){if(c.length){var e=c[0],f=c[c.length-1],g=e.parentNode,k=a.Q.instance,n=k.preprocessNode;if(n){b(e,f,function(a,b){var c=a.previousSibling,d=n.call(k,a);d&&(a===e&&(e=d[0]||b),a===f&&(f=d[d.length-1]||c))});c.length=0;if(!e)return;e===f?c.push(e):(c.push(e,f),a.a.za(c,g))}b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.Rb(d,b)});b(e,f,function(b){1!==b.nodeType&&8!==b.nodeType||a.M.yc(b,[d])});a.a.za(c,g)}}function d(a){return a.nodeType?a:0a.a.C?0:b.nodes)?
+b.nodes():null)return a.a.V(c.cloneNode(!0).childNodes);b=b.text();return a.a.ma(b,e)};a.W.sb=new a.W;a.Db(a.W.sb);a.b("nativeTemplateEngine",a.W);(function(){a.vb=function(){var a=this.$c=function(){if(!v||!v.tmpl)return 0;try{if(0<=v.tmpl.tag.tmpl.open.toString().indexOf("__"))return 2}catch(a){}return 1}();this.renderTemplateSource=function(b,e,f,g){g=g||u;f=f||{};if(2>a)throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");var k=b.data("precompiled");
+k||(k=b.text()||"",k=v.template(null,"{{ko_with $item.koBindingContext}}"+k+"{{/ko_with}}"),b.data("precompiled",k));b=[e.$data];e=v.extend({koBindingContext:e},f.templateOptions);e=v.tmpl(k,b,e);e.appendTo(g.createElement("div"));v.fragments={};return e};this.createJavaScriptEvaluatorBlock=function(a){return"{{ko_code ((function() { return "+a+" })()) }}"};this.addTemplate=function(a,b){u.write("
+
+
+
+
+
+
+
+