1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-08-09 07:25:23 +02:00

Merge branch 'master' into github-extension

This commit is contained in:
Elliott Stoneham 2016-06-29 15:47:13 +01:00
commit 1e78245c0b
13 changed files with 662 additions and 4 deletions

View file

@ -0,0 +1,134 @@
// 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';
import NotifierMixin from '../../../mixins/notifier';
import TooltipMixin from '../../../mixins/tooltip';
import SectionMixin from '../../../mixins/section';
export default Ember.Component.extend(SectionMixin, NotifierMixin, TooltipMixin, {
sectionService: Ember.inject.service('section'),
isDirty: false,
waiting: false,
authenticated: false,
config: {},
items: {},
didReceiveAttrs() {
let config = {};
try {
config = JSON.parse(this.get('meta.config'));
} catch (e) {}
if (is.empty(config)) {
config = {
APIToken: "",
query: "",
max: 10,
};
}
this.set('config', config);
if (this.get('config.APIToken').length > 0) {
this.send('auth');
}
},
willDestroyElement() {
this.destroyTooltips();
},
actions: {
isDirty() {
return this.get('isDirty');
},
auth() {
// missing data?
this.set('config.APIToken', this.get('config.APIToken').trim());
if (is.empty(this.get('config.APIToken'))) {
$("#papertrail-apitoken").addClass("error").focus();
return;
}
let page = this.get('page');
let self = this;
this.set('waiting', true);
this.get('sectionService').fetch(page, "auth", this.get('config'))
.then(function(response) {
self.set('authenticated', true);
self.set('items', response);
self.set('waiting', false);
}, function(reason) { //jshint ignore: line
self.set('authenticated', false);
self.set('waiting', false);
switch (reason.status) {
case 400:
self.showNotification(`Unable to connect to Papertrail`);
break;
case 403:
self.showNotification(`Unable to authenticate`);
break;
default:
self.showNotification(`Something went wrong, try again!`);
}
});
},
onCancel() {
this.attrs.onCancel();
},
onAction(title) {
let self = this;
let page = this.get('page');
let meta = this.get('meta');
page.set('title', title);
meta.set('externalSource', true);
let config = this.get('config');
let max = 10;
if (is.number(parseInt(config.max))) {
max = parseInt(config.max);
}
Ember.set(config, 'max', max);
this.set('waiting', true);
this.get('sectionService').fetch(page, "auth", this.get('config'))
.then(function(response) {
self.set('items', response);
let items = self.get('items');
if (items.events.length > max) {
items.events = items.events.slice(0, max);
}
meta.set('config', JSON.stringify(config));
meta.set('rawBody', JSON.stringify(items));
self.set('waiting', false);
self.attrs.onAction(page, meta);
}, function(reason) { //jshint ignore: line
self.set('authenticated', false);
self.set('waiting', false);
console.log(reason);
self.showNotification(`Something went wrong, try again!`);
});
}
}
});

View file

@ -0,0 +1,14 @@
// 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.Component.extend({});

View file

@ -37,3 +37,4 @@
@import "section/markdown.scss";
@import "section/table.scss";
@import "section/code.scss";
@import "section/papertrail.scss";

View file

@ -0,0 +1,16 @@
.section-papertrail-table {
font-size: 12px;
width: 90% important;
th {
font-size: 1rem;
}
td:nth-child(2) {
font-variant: small-caps;
}
a:hover {
text-decoration: underline;
}
}

View file

@ -0,0 +1,46 @@
{{#section/base-editor document=document folder=folder page=page busy=waiting tip="Papertrail cloud logging service (https://papertrailapp.com)" isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
<div class="pull-left width-45">
<div class="input-form">
<form {{action 'auth' on="submit"}}>
<div class="heading">
<div class="title">Papertrail Authentication</div>
<div class="tip">Provide your Papertrail API token</div>
</div>
<div class="input-control">
<label>API Key</label>
<div class="tip">API Token (from your profile)</div>
{{focus-input id="papertrail-apitoken" type="password" value=config.APIToken readonly=isReadonly}}
</div>
<div class="regular-button button-blue" {{ action 'auth' }}>Authenticate</div>
</form>
</div>
</div>
{{#if authenticated}}
<div class="pull-left width-10">&nbsp;</div>
<div class="pull-left width-45">
<div class="input-form">
<form {{action 'onAction' on="submit"}}>
<div class="heading">
<div class="title">Log Filter</div>
<div class="tip">Determine which log entries you want to display</div>
</div>
<div class="input-control">
<label>Search Query</label>
<div class="tip">e.g. bob OR ("some phrase" AND sally)</div>
{{input id="papertrail-query" type="text" class="mousetrap" value=config.query}}
</div>
<div class="input-control">
<label>Maximum Results</label>
<div class="tip">How many log entries do you want?</div>
{{input id="papertrail-max" type="number" class="mousetrap" value=config.max}}
</div>
</form>
</div>
</div>
{{/if}}
<div class="clearfix" />
{{/section/base-editor}}

View file

@ -0,0 +1 @@
{{{page.body}}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -30,7 +30,7 @@ const (
// AppVersion does what it says
// Versioning scheme major.minor where "minor" is optional
// e.g. 1, 2, 3, 4.1, 4.2, 5, 6, 7, 7.1, 8, 9, 10, ..... 127, 127.1, 128
AppVersion = "12.8"
AppVersion = "12.9"
)
var port, certFile, keyFile, forcePort2SSL string

View file

@ -0,0 +1,72 @@
// 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
package papertrail
import "strings"
// the HTML that is rendered by this section.
const renderTemplate = `
{{if .HasData}}
<p class="margin-left-20">The <a href="https://papertrailapp.com">Papertrail log</a> for query <em>{{.Config.Query}}</em> contains {{.Count}} entries.</p>
<table class="basic-table section-papertrail-table">
<thead>
<tr>
<th class="bordered no-width">Date</th>
<th class="bordered no-width">Severity</th>
<th class="bordered">Message</th>
</tr>
</thead>
<tbody>
{{range $item := .Events}}
<tr>
<td class="bordered no-width color-gray">{{ $item.Dated }}</td>
<td class="bordered no-width">{{ $item.Severity }}</td>
<td class="bordered width-90">{{ $item.Message }}</td>
</tr>
{{end}}
</tbody>
</table>
{{else}}
<p>There are no Papertrail log entries to see.</p>
{{end}}
`
// Papertrail helpers
type papertrailRender struct {
Config papertrailConfig
Events []papertrailEvent
Count int
Authenticated bool
HasData bool
}
type papertrailSearch struct {
Events []papertrailEvent `json:"events"`
}
type papertrailEvent struct {
ID string `json:"id"`
Dated string `json:"display_received_at"`
Message string `json:"message"`
Severity string `json:"severity"`
}
type papertrailConfig struct {
APIToken string `json:"APIToken"`
Query string `json:"query"`
Max int `json:"max"`
}
func (c *papertrailConfig) Clean() {
c.APIToken = strings.TrimSpace(c.APIToken)
c.Query = strings.TrimSpace(c.Query)
}

View file

@ -0,0 +1,372 @@
// 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
package papertrail
import (
"bytes"
"encoding/json"
"fmt"
"html/template"
"io/ioutil"
"net/http"
"net/url"
"github.com/documize/community/documize/section/provider"
)
const me = "papertrail"
// Provider represents Gemini
type Provider struct {
}
// Meta describes us.
func (*Provider) Meta() provider.TypeMeta {
section := provider.TypeMeta{}
section.ID = "db0a3a0a-b5d4-4d00-bfac-ee28abba451d"
section.Title = "Papertrail"
section.Description = "Display log entries"
section.ContentType = "papertrail"
return section
}
// Render converts Papertrail data into HTML suitable for browser rendering.
func (*Provider) Render(config, data string) string {
var search papertrailSearch
var events []papertrailEvent
var payload = papertrailRender{}
var c = papertrailConfig{}
json.Unmarshal([]byte(data), &search)
json.Unmarshal([]byte(config), &c)
max := len(search.Events)
if c.Max < max {
max = c.Max
}
events = search.Events[:max]
payload.Count = len(events)
payload.HasData = payload.Count > 0
payload.Events = events
payload.Config = c
payload.Authenticated = c.APIToken != ""
t := template.New("items")
t, _ = t.Parse(renderTemplate)
buffer := new(bytes.Buffer)
t.Execute(buffer, payload)
return buffer.String()
}
// Command handles authentication, workspace listing and items retrieval.
func (p *Provider) Command(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query()
method := query.Get("method")
if len(method) == 0 {
provider.WriteMessage(w, me, "missing method name")
return
}
switch method {
case "auth":
auth(w, r)
// case "items":
// items(w, r)
}
}
// Refresh just sends back data as-is.
func (*Provider) Refresh(config, data string) (newData string) {
return data
// var c = geminiConfig{}
// err := json.Unmarshal([]byte(config), &c)
//
// if err != nil {
// log.Error("Unable to read Gemini config", err)
// return
// }
//
// c.Clean()
//
// if len(c.URL) == 0 {
// log.Info("Gemini.Refresh received empty URL")
// return
// }
//
// if len(c.Username) == 0 {
// log.Info("Gemini.Refresh received empty username")
// return
// }
//
// if len(c.APIKey) == 0 {
// log.Info("Gemini.Refresh received empty API key")
// return
// }
//
// req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/items/card/%d", c.URL, c.WorkspaceID), nil)
// // req.Header.Set("Content-Type", "application/json")
//
// creds := []byte(fmt.Sprintf("%s:%s", c.Username, c.APIKey))
// req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString(creds))
//
// client := &http.Client{}
// res, err := client.Do(req)
//
// if err != nil {
// fmt.Println(err)
// return
// }
//
// if res.StatusCode != http.StatusOK {
// return
// }
//
// defer res.Body.Close()
// var items []geminiItem
//
// dec := json.NewDecoder(res.Body)
// err = dec.Decode(&items)
//
// if err != nil {
// fmt.Println(err)
// return
// }
//
// j, err := json.Marshal(items)
//
// if err != nil {
// log.Error("unable to marshall gemini items", err)
// return
// }
//
// newData = string(j)
// return
}
func auth(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
provider.WriteMessage(w, me, "Bad payload")
return
}
var config = papertrailConfig{}
err = json.Unmarshal(body, &config)
if err != nil {
provider.WriteMessage(w, me, "Bad config")
return
}
config.Clean()
if len(config.APIToken) == 0 {
provider.WriteMessage(w, me, "Missing API token")
return
}
var search string
if len(config.Query) > 0 {
search = "q=" + url.QueryEscape(config.Query)
}
req, err := http.NewRequest("GET", "https://papertrailapp.com/api/v1/events/search.json?"+search, nil)
req.Header.Set("X-Papertrail-Token", config.APIToken)
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
provider.WriteError(w, me, err)
return
}
if res.StatusCode != http.StatusOK {
provider.WriteForbidden(w)
return
}
defer res.Body.Close()
var result interface{}
dec := json.NewDecoder(res.Body)
err = dec.Decode(&result)
if err != nil {
fmt.Println(err)
provider.WriteError(w, me, err)
return
}
provider.WriteJSON(w, result)
}
//
// func workspace(w http.ResponseWriter, r *http.Request) {
// defer r.Body.Close()
// body, err := ioutil.ReadAll(r.Body)
//
// if err != nil {
// provider.WriteMessage(w, "gemini", "Bad payload")
// return
// }
//
// var config = geminiConfig{}
// err = json.Unmarshal(body, &config)
//
// if err != nil {
// provider.WriteMessage(w, "gemini", "Bad payload")
// return
// }
//
// config.Clean()
//
// if len(config.URL) == 0 {
// provider.WriteMessage(w, "gemini", "Missing URL value")
// return
// }
//
// if len(config.Username) == 0 {
// provider.WriteMessage(w, "gemini", "Missing Username value")
// return
// }
//
// if len(config.APIKey) == 0 {
// provider.WriteMessage(w, "gemini", "Missing APIKey value")
// return
// }
//
// if config.UserID == 0 {
// provider.WriteMessage(w, "gemini", "Missing UserId value")
// return
// }
//
// req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/navigationcards/users/%d", config.URL, config.UserID), nil)
//
// creds := []byte(fmt.Sprintf("%s:%s", config.Username, config.APIKey))
// req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString(creds))
//
// client := &http.Client{}
// res, err := client.Do(req)
//
// if err != nil {
// fmt.Println(err)
// provider.WriteError(w, "gemini", err)
// return
// }
//
// if res.StatusCode != http.StatusOK {
// provider.WriteForbidden(w)
// return
// }
//
// defer res.Body.Close()
// var workspace interface{}
//
// dec := json.NewDecoder(res.Body)
// err = dec.Decode(&workspace)
//
// if err != nil {
// fmt.Println(err)
// provider.WriteError(w, "gemini", err)
// return
// }
//
// provider.WriteJSON(w, workspace)
// }
//
// func items(w http.ResponseWriter, r *http.Request) {
// defer r.Body.Close()
// body, err := ioutil.ReadAll(r.Body)
//
// if err != nil {
// provider.WriteMessage(w, "gemini", "Bad payload")
// return
// }
//
// var config = geminiConfig{}
// err = json.Unmarshal(body, &config)
//
// if err != nil {
// provider.WriteMessage(w, "gemini", "Bad payload")
// return
// }
//
// config.Clean()
//
// if len(config.URL) == 0 {
// provider.WriteMessage(w, "gemini", "Missing URL value")
// return
// }
//
// if len(config.Username) == 0 {
// provider.WriteMessage(w, "gemini", "Missing Username value")
// return
// }
//
// if len(config.APIKey) == 0 {
// provider.WriteMessage(w, "gemini", "Missing APIKey value")
// return
// }
//
// creds := []byte(fmt.Sprintf("%s:%s", config.Username, config.APIKey))
//
// filter, err := json.Marshal(config.Filter)
// if err != nil {
// fmt.Println(err)
// provider.WriteError(w, "gemini", err)
// return
// }
//
// var jsonFilter = []byte(string(filter))
// req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/items/filtered", config.URL), bytes.NewBuffer(jsonFilter))
// req.Header.Set("Content-Type", "application/json")
// req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString(creds))
//
// client := &http.Client{}
// res, err := client.Do(req)
//
// if err != nil {
// fmt.Println(err)
// provider.WriteError(w, "gemini", err)
// return
// }
//
// if res.StatusCode != http.StatusOK {
// provider.WriteForbidden(w)
// return
// }
//
// defer res.Body.Close()
// var items interface{}
//
// dec := json.NewDecoder(res.Body)
// err = dec.Decode(&items)
//
// if err != nil {
// fmt.Println(err)
// provider.WriteError(w, "gemini", err)
// return
// }
//
// provider.WriteJSON(w, items)
// }

View file

@ -22,6 +22,7 @@ import (
"github.com/documize/community/documize/section/intercom"
"github.com/documize/community/documize/section/mailchimp"
"github.com/documize/community/documize/section/markdown"
"github.com/documize/community/documize/section/papertrail"
"github.com/documize/community/documize/section/provider"
"github.com/documize/community/documize/section/salesforce"
"github.com/documize/community/documize/section/stripe"
@ -43,6 +44,7 @@ func Register() {
provider.Register("mailchimp", &mailchimp.Provider{})
provider.Register("markdown", &markdown.Provider{})
provider.Register("salesforce", &salesforce.Provider{})
provider.Register("papertrail", &papertrail.Provider{})
provider.Register("stripe", &stripe.Provider{})
provider.Register("table", &table.Provider{})
provider.Register("trello", &trello.Provider{})