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

[WIP] User can select theme

This commit is contained in:
Harvey Kandola 2018-11-24 18:39:43 +00:00
parent 11e164496b
commit 679049d2b1
11 changed files with 141 additions and 8 deletions

View file

@ -282,13 +282,12 @@ type searchStatus struct {
// Themes returns list of installed UI themes. // Themes returns list of installed UI themes.
func (h *Handler) Themes(w http.ResponseWriter, r *http.Request) { func (h *Handler) Themes(w http.ResponseWriter, r *http.Request) {
type theme struct { type theme struct {
Name string `json:"names"` Name string `json:"name"`
Primary string `json:"primary"` Primary string `json:"primary"`
} }
th := []theme{} th := []theme{}
th = append(th, theme{Name: "", Primary: "#280A42"})
th = append(th, theme{Name: "Default", Primary: "#280A42"})
th = append(th, theme{Name: "Blue", Primary: "#176091"}) th = append(th, theme{Name: "Blue", Primary: "#176091"})
th = append(th, theme{Name: "Deep Orange", Primary: "#BF360C"}) th = append(th, theme{Name: "Deep Orange", Primary: "#BF360C"})
th = append(th, theme{Name: "Teal", Primary: "#00695C"}) th = append(th, theme{Name: "Teal", Primary: "#00695C"})

View file

@ -13,10 +13,12 @@ import $ from 'jquery';
import { empty, and } from '@ember/object/computed'; import { empty, and } from '@ember/object/computed';
import { isEmpty } from '@ember/utils'; import { isEmpty } from '@ember/utils';
import { set } from '@ember/object'; import { set } from '@ember/object';
import { inject as service } from '@ember/service';
import Notifier from '../../mixins/notifier'; import Notifier from '../../mixins/notifier';
import Component from '@ember/component'; import Component from '@ember/component';
export default Component.extend(Notifier, { export default Component.extend(Notifier, {
appMeta: service(),
maxTags: 3, maxTags: 3,
titleEmpty: empty('model.general.title'), titleEmpty: empty('model.general.title'),
messageEmpty: empty('model.general.message'), messageEmpty: empty('model.general.message'),
@ -70,6 +72,11 @@ export default Component.extend(Notifier, {
set(this, 'messageError', false); set(this, 'messageError', false);
set(this, 'conversionEndpointError', false); set(this, 'conversionEndpointError', false);
}); });
},
onThemeChange(theme) {
this.get('appMeta').setTheme(theme);
this.set('model.general.theme', theme);
} }
} }
}); });

View file

@ -0,0 +1,46 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
import { inject as service } from '@ember/service';
import { set } from '@ember/object';
import Component from '@ember/component';
export default Component.extend({
appMeta: service(),
value: '',
onChange: null,
didReceiveAttrs() {
this._super(...arguments);
let defTheme = this.get('appMeta.theme');
this.get('appMeta').getThemes().then((themes) => {
_.each(themes, (theme) => {
theme.selected = theme.name === defTheme ? true: false;
if (theme.name === '') theme.name = 'Default';
});
this.set('themes', themes);
});
},
actions: {
onSelect(selectedTheme) {
let themes = this.get('themes');
if (this.get('onChange') !== null) {
_.each(themes, (theme) => {
set(theme, 'selected', theme.name === selectedTheme ? true: false);
});
this.get('onChange')(selectedTheme);
}
}
}
});

View file

@ -11,12 +11,14 @@
import $ from 'jquery'; import $ from 'jquery';
import { empty } from '@ember/object/computed'; import { empty } from '@ember/object/computed';
import Component from '@ember/component';
import { computed, set } from '@ember/object'; import { computed, set } from '@ember/object';
import { isPresent, isEqual, isEmpty } from '@ember/utils'; import { isPresent, isEqual, isEmpty } from '@ember/utils';
import { inject as service } from '@ember/service';
import AuthProvider from '../mixins/auth'; import AuthProvider from '../mixins/auth';
import Component from '@ember/component';
export default Component.extend(AuthProvider, { export default Component.extend(AuthProvider, {
appMeta: service(),
hasFirstnameError: empty('model.firstname'), hasFirstnameError: empty('model.firstname'),
hasLastnameError: empty('model.lastname'), hasLastnameError: empty('model.lastname'),
hasEmailError: computed('model.email', function() { hasEmailError: computed('model.email', function() {
@ -83,6 +85,11 @@ export default Component.extend(AuthProvider, {
set(this, 'password.password', ''); set(this, 'password.password', '');
set(this, 'password.confirmation', ''); set(this, 'password.confirmation', '');
}); });
},
onThemeChange(theme) {
this.get('appMeta').setTheme(theme);
this.set('model.theme', theme);
} }
} }
}); });

View file

@ -19,6 +19,7 @@ export default Model.extend({
conversionEndpoint: attr('string'), conversionEndpoint: attr('string'),
allowAnonymousAccess: attr('boolean', { defaultValue: false }), allowAnonymousAccess: attr('boolean', { defaultValue: false }),
maxTags: attr('number', {defaultValue: 3}), maxTags: attr('number', {defaultValue: 3}),
theme: attr('string'),
created: attr(), created: attr(),
revised: attr() revised: attr()
}); });

View file

@ -27,6 +27,7 @@ export default Model.extend({
accounts: attr(), accounts: attr(),
groups: attr(), groups: attr(),
lastVersion: attr('string'), lastVersion: attr('string'),
theme: attr('string'),
created: attr(), created: attr(),
revised: attr(), revised: attr(),

View file

@ -120,10 +120,22 @@ export default Service.extend({
}, },
setTheme(theme) { setTheme(theme) {
theme = theme.trim(); $('#theme-link').remove();
if (theme.length === 0) return;
theme = theme.toLowerCase().replace(' ', '-').replace('default', '').trim();
if (theme.length === 0) {
return;
}
let file = this.get('assetMap').resolve(`assets/theme-${theme}.css`); let file = this.get('assetMap').resolve(`assets/theme-${theme}.css`);
$('head').append(`<link rel="stylesheet" href="${file}">`); $('head').append(`<link id="theme-link" rel="stylesheet" href="${file}">`);
},
getThemes() {
return this.get('ajax').request(`public/meta/themes`, {
method: 'GET'
}).then((response) => {
return response;
});
} }
}); });

View file

@ -32,3 +32,37 @@
color: $color-gray; color: $color-gray;
margin: 5rem 0; margin: 5rem 0;
} }
.theme-picker {
display : block;
margin-bottom: 10px;
> .theme {
height: 100px;
width: 250px;
text-align: center;
color: $color-white;
font-weight: 600;
font-size: 1.2rem;
display: inline-block;
position: relative;
margin: 0 20px 20px 0;
padding: 10px 0 0 0;
cursor: default;
border: 7px solid $color-gray-light;
@include border-radius(3px);
@include ease-in();
&:hover {
border: 7px solid $color-gray;
}
.tick {
text-align: center;
color: $color-white;
font-weight: 400;
font-size: 2rem;
}
}
}

View file

@ -61,6 +61,14 @@
<small class="form-text text-muted">How many tags can be assigned to a document (between 3 and 10 tags)</small> <small class="form-text text-muted">How many tags can be assigned to a document (between 3 and 10 tags)</small>
</div> </div>
</div> </div>
<div class="form-group row">
<label class="col-sm-4 col-form-label">Default Site Theme</label>
<div class="col-sm-7">
{{ui/theme-picker onChange=(action 'onThemeChange')}}
<small class="form-text text-muted">Users can set their own theme under Profile</small>
</div>
</div>
<div class="btn btn-success font-weight-bold text-uppercase mt-4" {{action 'save'}}>Save</div> <div class="btn btn-success font-weight-bold text-uppercase mt-4" {{action 'save'}}>Save</div>
</form> </form>
</div> </div>

View file

@ -0,0 +1,14 @@
<div class="theme-picker">
{{#each themes as |theme|}}
<div class="theme" style="{{concat 'background-color: ' theme.primary}}" {{action 'onSelect' theme.name}}>
{{theme.name}}
<div class="tick">
{{#if theme.selected}}
&#10003;
{{else}}
&nbsp;
{{/if}}
</div>
</div>
{{/each}}
</div>

View file

@ -20,6 +20,10 @@
<label for="confirmPassword">Confirm Password</label> <label for="confirmPassword">Confirm Password</label>
{{input id="confirmPassword" type="password" value=password.confirmation class=(if hasConfirmPasswordError 'form-control is-invalid' 'form-control')}} {{input id="confirmPassword" type="password" value=password.confirmation class=(if hasConfirmPasswordError 'form-control is-invalid' 'form-control')}}
</div> </div>
<div class="form-group">
<label>Theme</label>
{{ui/theme-picker onChange=(action 'onThemeChange')}}
</div>
{{/if}} {{/if}}
<div class="btn btn-success" {{action 'save'}}>Save</div> <div class="btn btn-success my-5" {{action 'save'}}>Save</div>
</div> </div>