mirror of
https://github.com/documize/community.git
synced 2025-08-07 14:35:28 +02:00
fixes and Trello updates
1. Fixed Firefox input field height. 2. Moved to server side Trello API calls. 3. New mixing for Section types. 4. Cleaned up TOC entry HTML
This commit is contained in:
parent
99dca0e1ad
commit
58a8f9169e
10 changed files with 270 additions and 92 deletions
|
@ -12,8 +12,9 @@
|
|||
import Ember from 'ember';
|
||||
import NotifierMixin from '../../../mixins/notifier';
|
||||
import TooltipMixin from '../../../mixins/tooltip';
|
||||
import SectionMixin from '../../../mixins/section';
|
||||
|
||||
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
||||
export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, {
|
||||
sectionService: Ember.inject.service('section'),
|
||||
isDirty: false,
|
||||
waiting: false,
|
||||
|
@ -22,14 +23,6 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
workspaces: [],
|
||||
config: {},
|
||||
|
||||
fieldEditable: function() {
|
||||
if (this.get('page.userId') !== this.session.user.id) {
|
||||
return "readonly";
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}.property('config'),
|
||||
|
||||
didReceiveAttrs() {
|
||||
let config = {};
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// 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>.
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
|
@ -13,11 +13,12 @@
|
|||
import Ember from 'ember';
|
||||
import NotifierMixin from '../../../mixins/notifier';
|
||||
import TooltipMixin from '../../../mixins/tooltip';
|
||||
import SectionMixin from '../../../mixins/section';
|
||||
|
||||
export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
||||
export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, {
|
||||
sectionService: Ember.inject.service('section'),
|
||||
isDirty: false,
|
||||
waiting: false,
|
||||
busy: false,
|
||||
authenticated: false,
|
||||
config: {},
|
||||
boards: null,
|
||||
|
@ -42,6 +43,8 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
|
||||
if (this.get('config.appKey') !== "" &&
|
||||
this.get('config.token') !== "") {
|
||||
console.log(this.get('isReadonly'));
|
||||
console.log(this.get('isMine'));
|
||||
this.send('auth');
|
||||
}
|
||||
},
|
||||
|
@ -51,12 +54,14 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
},
|
||||
|
||||
getBoardLists() {
|
||||
this.set('busy', true);
|
||||
|
||||
let self = this;
|
||||
let boards = this.get('boards');
|
||||
let board = this.get('config.board');
|
||||
this.set('waiting', true);
|
||||
let page = this.get('page');
|
||||
|
||||
if (is.null(board)) {
|
||||
if (is.null(board) || is.undefined(board)) {
|
||||
if (boards.length) {
|
||||
board = boards[0];
|
||||
this.set('config.board', board);
|
||||
|
@ -65,9 +70,9 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
this.set('config.board', boards.findBy('id', board.id));
|
||||
}
|
||||
|
||||
Trello.get(`boards/${board.id}/lists/open?fields=id,name,url`,
|
||||
function(lists) {
|
||||
let savedLists = self.get('config.lists');
|
||||
this.get('sectionService').fetch(page, "lists", self.get('config'))
|
||||
.then(function(lists) {
|
||||
let savedLists = self.get('config.lists');
|
||||
if (savedLists === null) {
|
||||
savedLists = [];
|
||||
}
|
||||
|
@ -82,14 +87,40 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
});
|
||||
|
||||
self.set('config.lists', lists);
|
||||
self.set('waiting', false);
|
||||
},
|
||||
function(error) {
|
||||
self.set('waiting', false);
|
||||
self.set('busy', false);
|
||||
}, function(error) { //jshint ignore: line
|
||||
self.set('busy', false);
|
||||
self.set('authenticated', false);
|
||||
self.showNotification("Unable to fetch board lists");
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Trello.get(`boards/${board.id}/lists/open?fields=id,name,url`,
|
||||
// function(lists) {
|
||||
// let savedLists = self.get('config.lists');
|
||||
// if (savedLists === null) {
|
||||
// savedLists = [];
|
||||
// }
|
||||
//
|
||||
// lists.forEach(function(list) {
|
||||
// let saved = savedLists.findBy("id", list.id);
|
||||
// let included = true;
|
||||
// if (is.not.undefined(saved)) {
|
||||
// included = saved.included;
|
||||
// }
|
||||
// list.included = included;
|
||||
// });
|
||||
//
|
||||
// self.set('config.lists', lists);
|
||||
// self.set('busy', false);
|
||||
// },
|
||||
// function(error) {
|
||||
// self.set('busy', false);
|
||||
// self.set('authenticated', false);
|
||||
// self.showNotification("Unable to fetch board lists");
|
||||
// console.log(error);
|
||||
// });
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
@ -124,7 +155,9 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
}
|
||||
|
||||
let self = this;
|
||||
self.set('waiting', true);
|
||||
let page = this.get('page');
|
||||
|
||||
self.set('busy', true);
|
||||
|
||||
Ember.$.getScript("https://api.trello.com/1/client.js?key=" + this.get('config.appKey'), function() {
|
||||
Trello.authorize({
|
||||
|
@ -140,24 +173,36 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
success: function() {
|
||||
self.set('authenticated', true);
|
||||
self.set('config.token', Trello.token());
|
||||
self.set('waiting', true);
|
||||
self.set('busy', true);
|
||||
|
||||
Trello.get("members/me/boards?fields=id,name,url,closed,prefs,idOrganization",
|
||||
function(boards) {
|
||||
self.set('waiting', false);
|
||||
self.get('sectionService').fetch(page, "boards", self.get('config'))
|
||||
.then(function(boards) {
|
||||
self.set('busy', false);
|
||||
self.set('boards', boards.filterBy("closed", false));
|
||||
self.getBoardLists();
|
||||
},
|
||||
function(error) {
|
||||
self.set('waiting', false);
|
||||
}, function(error) { //jshint ignore: line
|
||||
self.set('busy', false);
|
||||
self.set('authenticated', false);
|
||||
self.showNotification("Unable to fetch boards");
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Trello.get("members/me/boards?fields=id,name,url,closed,prefs,idOrganization",
|
||||
// function(boards) {
|
||||
// self.set('busy', false);
|
||||
// self.set('boards', boards.filterBy("closed", false));
|
||||
// self.getBoardLists();
|
||||
// },
|
||||
// function(error) {
|
||||
// self.set('busy', false);
|
||||
// self.set('authenticated', false);
|
||||
// self.showNotification("Unable to fetch boards");
|
||||
// console.log(error);
|
||||
// }
|
||||
// );
|
||||
},
|
||||
error: function(error) {
|
||||
self.set('waiting', false);
|
||||
self.set('busy', false);
|
||||
self.set('authenticated', false);
|
||||
self.showNotification("Unable to authenticate");
|
||||
console.log(error);
|
||||
|
@ -178,7 +223,7 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
},
|
||||
|
||||
onAction(title) {
|
||||
this.set('waiting', false);
|
||||
this.set('busy', true);
|
||||
|
||||
let self = this;
|
||||
let page = this.get('page');
|
||||
|
@ -191,12 +236,15 @@ export default Ember.Component.extend(NotifierMixin, TooltipMixin, {
|
|||
this.get('sectionService').fetch(page, "cards", this.get('config'))
|
||||
.then(function(response) {
|
||||
meta.set('rawBody', JSON.stringify(response));
|
||||
self.set('waiting', false);
|
||||
self.set('busy', false);
|
||||
self.attrs.onAction(page, meta);
|
||||
}, function(reason) { //jshint ignore: line
|
||||
self.set('waiting', false);
|
||||
self.set('busy', false);
|
||||
self.attrs.onAction(page, meta);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// show who owner is -- logout
|
||||
// key really required?
|
||||
|
|
|
@ -13,6 +13,7 @@ export function initialize(application) {
|
|||
application.inject('route', 'session', 'service:session');
|
||||
application.inject('controller', 'session', 'service:session');
|
||||
application.inject('component', 'session', 'service:session');
|
||||
application.inject('mixin', 'session', 'service:session');
|
||||
}
|
||||
|
||||
export default {
|
||||
|
|
26
app/app/mixins/section.js
Normal file
26
app/app/mixins/section.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
// 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 Ember from 'ember';
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
isReadonly: function() {
|
||||
if (this.get('page.userId') !== this.session.user.id) {
|
||||
return "readonly";
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}.property('page'),
|
||||
|
||||
isMine: function() {
|
||||
return this.get('page.userId') !== this.session.user.id;
|
||||
}.property('page')
|
||||
});
|
|
@ -53,7 +53,7 @@
|
|||
padding: 5px;
|
||||
border: 1px solid $color-input;
|
||||
border-radius: 2px;
|
||||
height: 2rem;
|
||||
height: 2.3rem;
|
||||
font-size: 1rem;
|
||||
display: inline-block;
|
||||
|
||||
|
|
|
@ -47,17 +47,17 @@
|
|||
<div class="input-control">
|
||||
<label>Gemini URL</label>
|
||||
<div class="tip">e.g. http://helpdesk.countersoft.com</div>
|
||||
{{focus-input id="gemini-url" type="text" value=config.url readonly=fieldEditable}}
|
||||
{{focus-input id="gemini-url" type="text" value=config.url readonly=isReadonly}}
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>Username</label>
|
||||
<div class="tip">Gemini username</div>
|
||||
{{input id="gemini-username" type="text" value=config.username readonly=fieldEditable}}
|
||||
{{input id="gemini-username" type="text" value=config.username readonly=isReadonly}}
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>API Key</label>
|
||||
<div class="tip">Gemini user API key (from user profile)</div>
|
||||
{{input id="gemini-apikey" type="password" value=config.APIKey readonly=fieldEditable}}
|
||||
{{input id="gemini-apikey" type="password" value=config.APIKey readonly=isReadonly}}
|
||||
</div>
|
||||
<div class="regular-button button-blue" {{ action 'auth' }}>Authenticate</div>
|
||||
</form>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
}
|
||||
</style>
|
||||
|
||||
{{#section/base-editor document=document folder=folder page=page busy=waiting tip="Trello is the visual way to manage your projects and organize anything (https://trello.com)" isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
||||
{{#section/base-editor document=document folder=folder page=page busy=busy tip="Trello is the visual way to manage your projects and organize anything (https://trello.com)" isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
||||
|
||||
<div class="pull-left width-45">
|
||||
<div class="input-form">
|
||||
|
@ -72,7 +72,8 @@
|
|||
action=(action 'onBoardChange')
|
||||
optionValuePath="id"
|
||||
optionLabelPath="name"
|
||||
selection=config.board}}
|
||||
selection=config.board
|
||||
readonly=isReadonly}}
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>Lists</label>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<select {{action 'change' on='change'}} class={{csslass}}>
|
||||
<select {{action 'change' on='change'}} class={{csslass}} readonly={{readonly}}>
|
||||
{{#if prompt}}
|
||||
<option disabled selected={{is-not selection}}>
|
||||
{{prompt}}
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
import { documentTocEntry } from '../../../../helpers/document/toc-entry';
|
||||
import { module, test } from 'qunit';
|
||||
import {
|
||||
documentTocEntry
|
||||
} from '../../../../helpers/document/toc-entry';
|
||||
import {
|
||||
module,
|
||||
test
|
||||
} from 'qunit';
|
||||
|
||||
module('Unit | Helper | document/toc entry');
|
||||
|
||||
test('toc entry should be not indented and not selected', function(assert) {
|
||||
let result = documentTocEntry(['node-123', 'node-321', 1]);
|
||||
assert.equal(result.toString(), "<span style='margin-left: 0px;'></span><span class=''><i class='material-icons toc-bullet'>remove</i></span>");
|
||||
assert.equal(result.toString(), "<span style='margin-left: 0px;'></span><span class=''></span>");
|
||||
});
|
||||
|
||||
test('toc entry should be indented and selected', function(assert) {
|
||||
let result = documentTocEntry(['node-123', 'node-123', 2]);
|
||||
assert.equal(result.toString(), "<span style='margin-left: 20px;'></span><span class='selected'><i class='material-icons toc-bullet'>remove</i></span>");
|
||||
});
|
||||
assert.equal(result.toString(), "<span style='margin-left: 20px;'></span><span class='selected'></span>");
|
||||
});
|
|
@ -51,9 +51,67 @@ func (*trello) Command(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
defer r.Body.Close()
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
|
||||
if err != nil {
|
||||
writeMessage(w, "trello", "Bad body")
|
||||
return
|
||||
}
|
||||
|
||||
var config = trelloConfig{}
|
||||
err = json.Unmarshal(body, &config)
|
||||
|
||||
if err != nil {
|
||||
writeError(w, "trello", err)
|
||||
return
|
||||
}
|
||||
|
||||
config.Clean()
|
||||
|
||||
if len(config.AppKey) == 0 {
|
||||
writeMessage(w, "trello", "Missing appKey")
|
||||
return
|
||||
}
|
||||
|
||||
if len(config.Token) == 0 {
|
||||
writeMessage(w, "trello", "Missing token")
|
||||
return
|
||||
}
|
||||
|
||||
switch method {
|
||||
case "cards":
|
||||
cards(w, r)
|
||||
render, err := getCards(config)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
writeError(w, "trello", err)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, render)
|
||||
|
||||
case "boards":
|
||||
render, err := getBoards(config)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
writeError(w, "trello", err)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, render)
|
||||
|
||||
case "lists":
|
||||
render, err := getLists(config)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
writeError(w, "trello", err)
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, render)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,50 +163,102 @@ func (*trello) Refresh(config, data string) string {
|
|||
}
|
||||
|
||||
// Helpers
|
||||
func cards(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
// func cards(w http.ResponseWriter, r *http.Request) {
|
||||
// defer r.Body.Close()
|
||||
// body, err := ioutil.ReadAll(r.Body)
|
||||
//
|
||||
// if err != nil {
|
||||
// writeMessage(w, "trello", "Bad body")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// var config = trelloConfig{}
|
||||
// err = json.Unmarshal(body, &config)
|
||||
//
|
||||
// if err != nil {
|
||||
// writeError(w, "trello", err)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// config.Clean()
|
||||
//
|
||||
// if len(config.AppKey) == 0 {
|
||||
// writeMessage(w, "trello", "Missing appKey")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if len(config.Token) == 0 {
|
||||
// writeMessage(w, "trello", "Missing token")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// render, err := getCards(config)
|
||||
//
|
||||
// if err != nil {
|
||||
// fmt.Println(err)
|
||||
// writeError(w, "trello", err)
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// writeJSON(w, render)
|
||||
// }
|
||||
|
||||
func getBoards(config trelloConfig) (boards []trelloBoard, err error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("https://api.trello.com/1/members/me/boards?fields=id,name,url,closed,prefs,idOrganization&key=%s&token=%s", config.AppKey, config.Token), nil)
|
||||
client := &http.Client{}
|
||||
res, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
writeMessage(w, "trello", "Bad body")
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var config = trelloConfig{}
|
||||
err = json.Unmarshal(body, &config)
|
||||
|
||||
if err != nil {
|
||||
writeError(w, "trello", err)
|
||||
// writeMessage(w, "trello", "Bad payload")
|
||||
return
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("error: HTTP status code %d", res.StatusCode)
|
||||
}
|
||||
|
||||
config.Clean()
|
||||
defer res.Body.Close()
|
||||
|
||||
if len(config.AppKey) == 0 {
|
||||
writeMessage(w, "trello", "Missing appKey")
|
||||
return
|
||||
}
|
||||
|
||||
if len(config.Token) == 0 {
|
||||
writeMessage(w, "trello", "Missing token")
|
||||
return
|
||||
}
|
||||
|
||||
render, err := getCards(config)
|
||||
dec := json.NewDecoder(res.Body)
|
||||
err = dec.Decode(&boards)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
writeError(w, "trello", err)
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
writeJSON(w, render)
|
||||
return boards, nil
|
||||
}
|
||||
|
||||
func getLists(config trelloConfig) (lists []trelloList, err error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("https://api.trello.com/1/boards/%s/lists/open?key=%s&token=%s", config.Board.ID, config.AppKey, config.Token), nil)
|
||||
client := &http.Client{}
|
||||
res, err := client.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("error: HTTP status code %d", res.StatusCode)
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
dec := json.NewDecoder(res.Body)
|
||||
err = dec.Decode(&lists)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return lists, nil
|
||||
}
|
||||
|
||||
func getCards(config trelloConfig) (listCards []trelloListCards, err error) {
|
||||
for _, list := range config.Lists {
|
||||
|
||||
// don't process lists that user excluded from rendering
|
||||
if !list.Included {
|
||||
continue
|
||||
}
|
||||
|
@ -198,18 +308,18 @@ func (c *trelloConfig) Clean() {
|
|||
}
|
||||
|
||||
type trelloBoard struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Desc string `json:"desc"`
|
||||
DescData struct {
|
||||
Emoji struct{} `json:"emoji"`
|
||||
} `json:"descData"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Closed bool `json:"closed"`
|
||||
OrganizationID string `json:"idOrganization"`
|
||||
Pinned bool `json:"pinned"`
|
||||
URL string `json:"url"`
|
||||
ShortURL string `json:"shortUrl"`
|
||||
Prefs struct {
|
||||
Desc string `json:"desc"`
|
||||
DescData struct {
|
||||
Emoji struct{} `json:"emoji"`
|
||||
} `json:"descData"`
|
||||
Prefs struct {
|
||||
PermissionLevel string `json:"permissionLevel"`
|
||||
Voting string `json:"voting"`
|
||||
Comments string `json:"comments"`
|
||||
|
@ -326,7 +436,7 @@ const trelloTemplate = `
|
|||
{{ $card.Name }}
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
@ -334,10 +444,4 @@ const trelloTemplate = `
|
|||
|
||||
/*
|
||||
does server side load up all data? YES!!??
|
||||
owner read-only control?
|
||||
|
||||
is appKey is global?
|
||||
- where stored?
|
||||
- how access?
|
||||
- does section.go ask config to give us saved json
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue