mirror of
https://github.com/documize/community.git
synced 2025-07-22 06:39:43 +02:00
PlantUML integration
This commit is contained in:
parent
0f3de51ad5
commit
7d3473365a
18 changed files with 521 additions and 291 deletions
|
@ -1,55 +0,0 @@
|
||||||
// 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 mermaid
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/documize/community/core/env"
|
|
||||||
"github.com/documize/community/domain"
|
|
||||||
"github.com/documize/community/domain/section/provider"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Provider represents Mermaid Diagram
|
|
||||||
type Provider struct {
|
|
||||||
Runtime *env.Runtime
|
|
||||||
Store *domain.Store
|
|
||||||
}
|
|
||||||
|
|
||||||
// Meta describes us
|
|
||||||
func (*Provider) Meta() provider.TypeMeta {
|
|
||||||
section := provider.TypeMeta{}
|
|
||||||
|
|
||||||
section.ID = "f1067a60-45e5-40b5-89f6-aa3b03dd7f35"
|
|
||||||
section.Title = "Mermaid Diagram"
|
|
||||||
section.Description = "Diagrams generated from textual descriptions"
|
|
||||||
section.ContentType = "mermaid"
|
|
||||||
section.PageType = "tab"
|
|
||||||
section.Order = 9990
|
|
||||||
|
|
||||||
return section
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command stub.
|
|
||||||
func (*Provider) Command(ctx *provider.Context, w http.ResponseWriter, r *http.Request) {
|
|
||||||
provider.WriteEmpty(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render returns data as-is (HTML).
|
|
||||||
func (*Provider) Render(ctx *provider.Context, config, data string) string {
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh just sends back data as-is.
|
|
||||||
func (*Provider) Refresh(ctx *provider.Context, config, data string) string {
|
|
||||||
return data
|
|
||||||
}
|
|
116
domain/section/plantuml/plantuml.go
Normal file
116
domain/section/plantuml/plantuml.go
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
// 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 plantuml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/documize/community/core/env"
|
||||||
|
"github.com/documize/community/domain"
|
||||||
|
"github.com/documize/community/domain/section/provider"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider represents Mermaid Diagram
|
||||||
|
type Provider struct {
|
||||||
|
Runtime *env.Runtime
|
||||||
|
Store *domain.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
// Meta describes us
|
||||||
|
func (*Provider) Meta() provider.TypeMeta {
|
||||||
|
section := provider.TypeMeta{}
|
||||||
|
|
||||||
|
section.ID = "f1067a60-45e5-40b5-89f6-aa3b03dd7f35"
|
||||||
|
section.Title = "PlantUML Diagram"
|
||||||
|
section.Description = "Diagrams generated from text"
|
||||||
|
section.ContentType = "plantuml"
|
||||||
|
section.PageType = "tab"
|
||||||
|
section.Order = 9990
|
||||||
|
|
||||||
|
return section
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command stub.
|
||||||
|
func (p *Provider) Command(ctx *provider.Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
query := r.URL.Query()
|
||||||
|
method := query.Get("method")
|
||||||
|
|
||||||
|
if len(method) == 0 {
|
||||||
|
provider.WriteMessage(w, "plantuml", "missing method name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch method {
|
||||||
|
case "preview":
|
||||||
|
var payload struct {
|
||||||
|
Data string `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
defer r.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
provider.WriteMessage(w, "plantuml", "Bad payload")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(body, &payload)
|
||||||
|
if err != nil {
|
||||||
|
provider.WriteMessage(w, "plantuml", "Cannot unmarshal")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
diagram := p.generateDiagram(ctx, payload.Data)
|
||||||
|
payload.Data = diagram
|
||||||
|
provider.WriteJSON(w, payload)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
provider.WriteEmpty(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render returns data as-is (HTML).
|
||||||
|
func (p *Provider) Render(ctx *provider.Context, config, data string) string {
|
||||||
|
return p.generateDiagram(ctx, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh just sends back data as-is.
|
||||||
|
func (*Provider) Refresh(ctx *provider.Context, config, data string) string {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) generateDiagram(ctx *provider.Context, data string) string {
|
||||||
|
org, _ := p.Store.Organization.GetOrganization(ctx.Request, ctx.OrgID)
|
||||||
|
|
||||||
|
var transport = &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true, // TODO should be glick.InsecureSkipVerifyTLS (from -insecure flag) but get error: x509: certificate signed by unknown authority
|
||||||
|
}}
|
||||||
|
client := &http.Client{Transport: transport}
|
||||||
|
|
||||||
|
resp, _ := client.Post(org.ConversionEndpoint+"/api/plantuml", "application/text", bytes.NewReader([]byte(data)))
|
||||||
|
defer func() {
|
||||||
|
if e := resp.Body.Close(); e != nil {
|
||||||
|
fmt.Println("resp.Body.Close error: " + e.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
png, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
pngEncoded := base64.StdEncoding.EncodeToString(png)
|
||||||
|
|
||||||
|
return string(fmt.Sprintf("data:image/png;base64, %s", pngEncoded))
|
||||||
|
}
|
|
@ -21,8 +21,8 @@ import (
|
||||||
"github.com/documize/community/domain/section/gemini"
|
"github.com/documize/community/domain/section/gemini"
|
||||||
"github.com/documize/community/domain/section/github"
|
"github.com/documize/community/domain/section/github"
|
||||||
"github.com/documize/community/domain/section/markdown"
|
"github.com/documize/community/domain/section/markdown"
|
||||||
// "github.com/documize/community/domain/section/mermaid"
|
|
||||||
"github.com/documize/community/domain/section/papertrail"
|
"github.com/documize/community/domain/section/papertrail"
|
||||||
|
"github.com/documize/community/domain/section/plantuml"
|
||||||
"github.com/documize/community/domain/section/provider"
|
"github.com/documize/community/domain/section/provider"
|
||||||
"github.com/documize/community/domain/section/table"
|
"github.com/documize/community/domain/section/table"
|
||||||
"github.com/documize/community/domain/section/trello"
|
"github.com/documize/community/domain/section/trello"
|
||||||
|
@ -41,7 +41,7 @@ func Register(rt *env.Runtime, s *domain.Store) {
|
||||||
provider.Register("trello", &trello.Provider{Runtime: rt, Store: s})
|
provider.Register("trello", &trello.Provider{Runtime: rt, Store: s})
|
||||||
provider.Register("wysiwyg", &wysiwyg.Provider{Runtime: rt, Store: s})
|
provider.Register("wysiwyg", &wysiwyg.Provider{Runtime: rt, Store: s})
|
||||||
provider.Register("airtable", &airtable.Provider{Runtime: rt, Store: s})
|
provider.Register("airtable", &airtable.Provider{Runtime: rt, Store: s})
|
||||||
// provider.Register("mermaid", &mermaid.Provider{Runtime: rt, Store: s})
|
provider.Register("plantuml", &plantuml.Provider{Runtime: rt, Store: s})
|
||||||
|
|
||||||
p := provider.List()
|
p := provider.List()
|
||||||
rt.Log.Info(fmt.Sprintf("Registered %d sections", len(p)))
|
rt.Log.Info(fmt.Sprintf("Registered %d sections", len(p)))
|
||||||
|
|
|
@ -60,6 +60,7 @@ module.exports = {
|
||||||
"userLogin": true,
|
"userLogin": true,
|
||||||
"Keycloak": true,
|
"Keycloak": true,
|
||||||
"slug": true,
|
"slug": true,
|
||||||
"interact": true
|
"interact": true,
|
||||||
|
"velocity": true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,169 +0,0 @@
|
||||||
// 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 { computed, observer } from '@ember/object';
|
|
||||||
import Component from '@ember/component';
|
|
||||||
|
|
||||||
export default Component.extend({
|
|
||||||
isDirty: false,
|
|
||||||
diagramText: '',
|
|
||||||
diagramPreview: null,
|
|
||||||
config: null,
|
|
||||||
|
|
||||||
editorId: computed('page', function () {
|
|
||||||
let page = this.get('page');
|
|
||||||
return `mermaid-editor-${page.id}`;
|
|
||||||
}),
|
|
||||||
previewId: computed('page', function () {
|
|
||||||
let page = this.get('page');
|
|
||||||
return `mermaid-preview-${page.id}`;
|
|
||||||
}),
|
|
||||||
// generateDiagram: observer('diagramText', function() {
|
|
||||||
// let txt = this.get('diagramText');
|
|
||||||
// console.log('calc diaggram');
|
|
||||||
|
|
||||||
// let self = this;
|
|
||||||
// var cb = function(svg) {
|
|
||||||
// return svg;
|
|
||||||
// // self.set('diagramPreview', svg);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// if (is.empty(this.get('diagramText'))) return '';
|
|
||||||
|
|
||||||
// mermaid.render(this.get('previewId'), txt, cb);
|
|
||||||
// }),
|
|
||||||
|
|
||||||
keyUp() {
|
|
||||||
this.generateDiagram();
|
|
||||||
},
|
|
||||||
|
|
||||||
generateDiagram() {
|
|
||||||
console.log('calc diaggram');
|
|
||||||
|
|
||||||
let txt = this.get('diagramText');
|
|
||||||
if (is.empty(this.get('diagramText'))) this.set('diagramPreview', '');
|
|
||||||
|
|
||||||
let self = this;
|
|
||||||
var cb = function(svg) {
|
|
||||||
self.set('diagramPreview', svg);
|
|
||||||
};
|
|
||||||
|
|
||||||
mermaid.render(this.get('previewId'), txt, cb);
|
|
||||||
},
|
|
||||||
|
|
||||||
didReceiveAttrs() {
|
|
||||||
this._super(...arguments);
|
|
||||||
let config = {};
|
|
||||||
mermaid.initialize({});
|
|
||||||
console.log('dra');
|
|
||||||
|
|
||||||
try {
|
|
||||||
config = JSON.parse(this.get('meta.config'));
|
|
||||||
} catch (e) {} // eslint-disable-line no-empty
|
|
||||||
|
|
||||||
if (is.empty(config)) {
|
|
||||||
config = {
|
|
||||||
txt: ""
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set('diagramText', config.txt);
|
|
||||||
this.set('config', config);
|
|
||||||
|
|
||||||
this.generateDiagram();
|
|
||||||
},
|
|
||||||
|
|
||||||
// onType: function() {
|
|
||||||
// debounce(this, this.generateDiagram, 350);
|
|
||||||
// }.observes('diagramText'),
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
isDirty() {
|
|
||||||
return this.get('isDirty') || (this.get('diagramText') !== this.get('config.txt'));
|
|
||||||
},
|
|
||||||
|
|
||||||
onCancel() {
|
|
||||||
let cb = this.get('onCancel');
|
|
||||||
cb();
|
|
||||||
},
|
|
||||||
|
|
||||||
onAction(title) {
|
|
||||||
let page = this.get('page');
|
|
||||||
let meta = this.get('meta');
|
|
||||||
|
|
||||||
meta.set('config', JSON.stringify({ txt: this.get('diagramText') }));
|
|
||||||
meta.set('rawBody', this.get('diagramPreview'));
|
|
||||||
page.set('body', this.get('diagramPreview'));
|
|
||||||
page.set('title', title);
|
|
||||||
|
|
||||||
let cb = this.get('onAction');
|
|
||||||
cb(page, meta);
|
|
||||||
},
|
|
||||||
|
|
||||||
onInsertFlowchart() {
|
|
||||||
let txt = `graph TB
|
|
||||||
c1-->a2
|
|
||||||
subgraph one
|
|
||||||
a1-->a2
|
|
||||||
end
|
|
||||||
subgraph two
|
|
||||||
b1-->b2
|
|
||||||
end
|
|
||||||
subgraph three
|
|
||||||
c1-->c2
|
|
||||||
end`;
|
|
||||||
|
|
||||||
// this.set('diagramPreview', null);
|
|
||||||
this.set('diagramText', txt);
|
|
||||||
this.generateDiagram();
|
|
||||||
},
|
|
||||||
|
|
||||||
onInsertSequence() {
|
|
||||||
let txt = `sequenceDiagram
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
Alice->John: Hello John, how are you?
|
|
||||||
loop Healthcheck
|
|
||||||
John->John: Fight against hypochondria
|
|
||||||
end
|
|
||||||
Note right of John: Rational thoughts <br/>prevail...
|
|
||||||
John-->Alice: Great!
|
|
||||||
John->Bob: How about you?
|
|
||||||
Bob-->John: Jolly good!`;
|
|
||||||
|
|
||||||
// this.set('diagramPreview', null);
|
|
||||||
this.set('diagramText', txt);
|
|
||||||
this.generateDiagram();
|
|
||||||
},
|
|
||||||
|
|
||||||
onInsertGantt() {
|
|
||||||
let txt = `gantt
|
|
||||||
dateFormat YYYY-MM-DD
|
|
||||||
title Adding GANTT diagram functionality to mermaid
|
|
||||||
section A section
|
|
||||||
Completed task :done, des1, 2014-01-06,2014-01-08
|
|
||||||
Active task :active, des2, 2014-01-09, 3d
|
|
||||||
Future task : des3, after des2, 5d
|
|
||||||
Future task2 : des4, after des3, 5d
|
|
||||||
section Critical tasks
|
|
||||||
Completed task in the critical line :crit, done, 2014-01-06,24h
|
|
||||||
Implement parser and jison :crit, done, after des1, 2d
|
|
||||||
Create tests for parser :crit, active, 3d
|
|
||||||
Future task in critical line :crit, 5d
|
|
||||||
Create tests for renderer :2d
|
|
||||||
Add to mermaid :1d`;
|
|
||||||
|
|
||||||
// this.set('diagramPreview', null);
|
|
||||||
this.set('diagramText', txt);
|
|
||||||
this.generateDiagram();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
342
gui/app/components/section/plantuml/type-editor.js
Normal file
342
gui/app/components/section/plantuml/type-editor.js
Normal file
|
@ -0,0 +1,342 @@
|
||||||
|
// 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 { schedule } from '@ember/runloop';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { computed, observer } from '@ember/object';
|
||||||
|
import Component from '@ember/component';
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
appMeta: service(),
|
||||||
|
sectionSvc: service('section'),
|
||||||
|
isDirty: false,
|
||||||
|
waiting: false,
|
||||||
|
diagramText: '',
|
||||||
|
diagramPreview: null,
|
||||||
|
previewButtonCaption: 'Preview',
|
||||||
|
|
||||||
|
editorId: computed('page', function () {
|
||||||
|
let page = this.get('page');
|
||||||
|
return `plantuml-editor-${page.id}`;
|
||||||
|
}),
|
||||||
|
previewId: computed('page', function () {
|
||||||
|
let page = this.get('page');
|
||||||
|
return `plantuml-preview-${page.id}`;
|
||||||
|
}),
|
||||||
|
|
||||||
|
generatePreview() {
|
||||||
|
this.set('waiting', true);
|
||||||
|
this.set('previewButtonCaption', 'Generating preview...');
|
||||||
|
|
||||||
|
let self = this;
|
||||||
|
let data = { data: this.get('diagramText') };
|
||||||
|
|
||||||
|
schedule('afterRender', () => {
|
||||||
|
this.get('sectionSvc').fetch(this.get('page'), 'preview', data).then(function (response) {
|
||||||
|
self.set('diagramPreview', response.data);
|
||||||
|
self.set('waiting', false);
|
||||||
|
self.set('previewButtonCaption', 'Preview');
|
||||||
|
}, function (reason) { // eslint-disable-line no-unused-vars
|
||||||
|
self.set('diagramPreview', null);
|
||||||
|
self.set('waiting', false);
|
||||||
|
self.set('previewButtonCaption', 'Preview');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
didReceiveAttrs() {
|
||||||
|
this._super(...arguments);
|
||||||
|
this.set('waiting', false);
|
||||||
|
this.set('diagramText', this.get('meta.rawBody'));
|
||||||
|
|
||||||
|
this.generatePreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
isDirty() {
|
||||||
|
return this.get('isDirty') || (this.get('diagramText') !== this.get('meta.rawBody'));
|
||||||
|
},
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
let cb = this.get('onCancel');
|
||||||
|
cb();
|
||||||
|
},
|
||||||
|
|
||||||
|
onPreview() {
|
||||||
|
this.generatePreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
onAction(title) {
|
||||||
|
this.set('waiting', true);
|
||||||
|
let page = this.get('page');
|
||||||
|
let meta = this.get('meta');
|
||||||
|
|
||||||
|
meta.set('rawBody', this.get('diagramText'));
|
||||||
|
page.set('title', title);
|
||||||
|
|
||||||
|
let cb = this.get('onAction');
|
||||||
|
cb(page, meta);
|
||||||
|
this.set('waiting', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
onInsertActivity() {
|
||||||
|
let txt = `
|
||||||
|
@startuml
|
||||||
|
title Servlet Container
|
||||||
|
|
||||||
|
(*) --> "ClickServlet.handleRequest()"
|
||||||
|
--> "new Page"
|
||||||
|
|
||||||
|
if "Page.onSecurityCheck" then
|
||||||
|
->[true] "Page.onInit()"
|
||||||
|
|
||||||
|
if "isForward?" then
|
||||||
|
->[no] "Process controls"
|
||||||
|
|
||||||
|
if "continue processing?" then
|
||||||
|
-->[yes] ===RENDERING===
|
||||||
|
else
|
||||||
|
-->[no] ===REDIRECT_CHECK===
|
||||||
|
endif
|
||||||
|
|
||||||
|
else
|
||||||
|
-->[yes] ===RENDERING===
|
||||||
|
endif
|
||||||
|
|
||||||
|
if "is Post?" then
|
||||||
|
-->[yes] "Page.onPost()"
|
||||||
|
--> "Page.onRender()" as render
|
||||||
|
--> ===REDIRECT_CHECK===
|
||||||
|
else
|
||||||
|
-->[no] "Page.onGet()"
|
||||||
|
--> render
|
||||||
|
endif
|
||||||
|
|
||||||
|
else
|
||||||
|
-->[false] ===REDIRECT_CHECK===
|
||||||
|
endif
|
||||||
|
|
||||||
|
if "Do redirect?" then
|
||||||
|
->[yes] "redirect request"
|
||||||
|
--> ==BEFORE_DESTROY===
|
||||||
|
else
|
||||||
|
if "Do Forward?" then
|
||||||
|
-left->[yes] "Forward request"
|
||||||
|
--> ==BEFORE_DESTROY===
|
||||||
|
else
|
||||||
|
-right->[no] "Render page template"
|
||||||
|
--> ==BEFORE_DESTROY===
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
--> "Page.onDestroy()"
|
||||||
|
-->(*)
|
||||||
|
@enduml`;
|
||||||
|
|
||||||
|
this.set('diagramText', txt);
|
||||||
|
this.generatePreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
onInsertSequence() {
|
||||||
|
let txt = `
|
||||||
|
@startuml
|
||||||
|
actor Bob #red
|
||||||
|
' The only difference between actor
|
||||||
|
'and participant is the drawing
|
||||||
|
participant Alice
|
||||||
|
participant "I have a reallylong name" as L #99FF99
|
||||||
|
/' You can also declare:
|
||||||
|
participant L as "I have a really long name" #99FF99
|
||||||
|
'/
|
||||||
|
|
||||||
|
Alice->Bob: Authentication Request
|
||||||
|
Bob->Alice: Authentication Response
|
||||||
|
Bob->L: Log transaction
|
||||||
|
@enduml`;
|
||||||
|
|
||||||
|
this.set('diagramText', txt);
|
||||||
|
this.generatePreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
onInsertUseCase() {
|
||||||
|
let txt = `
|
||||||
|
@startuml
|
||||||
|
:Main Admin: as Admin
|
||||||
|
(Use the application) as (Use)
|
||||||
|
|
||||||
|
User -> (Start)
|
||||||
|
User --> (Use)
|
||||||
|
|
||||||
|
Admin ---> (Use)
|
||||||
|
|
||||||
|
note right of Admin : This is an example.
|
||||||
|
|
||||||
|
note right of (Use)
|
||||||
|
A note can also
|
||||||
|
be on several lines
|
||||||
|
end note
|
||||||
|
|
||||||
|
note "This note is connected to several objects." as N2
|
||||||
|
(Start) .. N2
|
||||||
|
N2 .. (Use)
|
||||||
|
@enduml
|
||||||
|
`;
|
||||||
|
|
||||||
|
this.set('diagramText', txt);
|
||||||
|
this.generatePreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
onInsertClass() {
|
||||||
|
let txt = `
|
||||||
|
@startuml
|
||||||
|
class Foo1 {
|
||||||
|
You can use
|
||||||
|
several lines
|
||||||
|
..
|
||||||
|
as you want
|
||||||
|
and group
|
||||||
|
==
|
||||||
|
things together.
|
||||||
|
__
|
||||||
|
You can have as many groups
|
||||||
|
as you want
|
||||||
|
--
|
||||||
|
End of class
|
||||||
|
}
|
||||||
|
|
||||||
|
class User {
|
||||||
|
.. Simple Getter ..
|
||||||
|
+ getName()
|
||||||
|
+ getAddress()
|
||||||
|
.. Some setter ..
|
||||||
|
+ setName()
|
||||||
|
__ private data __
|
||||||
|
int age
|
||||||
|
-- encrypted --
|
||||||
|
String password
|
||||||
|
}
|
||||||
|
|
||||||
|
@enduml`;
|
||||||
|
|
||||||
|
this.set('diagramText', txt);
|
||||||
|
this.generatePreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
onInsertActivityNew() {
|
||||||
|
let txt = `
|
||||||
|
@startuml
|
||||||
|
|
||||||
|
start
|
||||||
|
:ClickServlet.handleRequest();
|
||||||
|
:new page;
|
||||||
|
if (Page.onSecurityCheck) then (true)
|
||||||
|
:Page.onInit();
|
||||||
|
if (isForward?) then (no)
|
||||||
|
:Process controls;
|
||||||
|
if (continue processing?) then (no)
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (isPost?) then (yes)
|
||||||
|
:Page.onPost();
|
||||||
|
else (no)
|
||||||
|
:Page.onGet();
|
||||||
|
endif
|
||||||
|
:Page.onRender();
|
||||||
|
endif
|
||||||
|
else (false)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (do redirect?) then (yes)
|
||||||
|
:redirect process;
|
||||||
|
else
|
||||||
|
if (do forward?) then (yes)
|
||||||
|
:Forward request;
|
||||||
|
else (no)
|
||||||
|
:Render page template;
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
stop
|
||||||
|
|
||||||
|
@enduml`;
|
||||||
|
|
||||||
|
this.set('diagramText', txt);
|
||||||
|
this.generatePreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
onInsertComponent() {
|
||||||
|
let txt = `
|
||||||
|
@startuml
|
||||||
|
|
||||||
|
package "Some Group" {
|
||||||
|
HTTP - [First Component]
|
||||||
|
[Another Component]
|
||||||
|
}
|
||||||
|
|
||||||
|
node "Other Groups" {
|
||||||
|
FTP - [Second Component]
|
||||||
|
[First Component] --> FTP
|
||||||
|
}
|
||||||
|
|
||||||
|
cloud {
|
||||||
|
[Example 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
database "MySql" {
|
||||||
|
folder "This is my folder" {
|
||||||
|
[Folder 3]
|
||||||
|
}
|
||||||
|
frame "Foo" {
|
||||||
|
[Frame 4]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Another Component] --> [Example 1]
|
||||||
|
[Example 1] --> [Folder 3]
|
||||||
|
[Folder 3] --> [Frame 4]
|
||||||
|
|
||||||
|
@enduml`;
|
||||||
|
|
||||||
|
this.set('diagramText', txt);
|
||||||
|
this.generatePreview();
|
||||||
|
},
|
||||||
|
|
||||||
|
onInsertState() {
|
||||||
|
let txt = `
|
||||||
|
@startuml
|
||||||
|
scale 600 width
|
||||||
|
|
||||||
|
[*] -> State1
|
||||||
|
State1 --> State2 : Succeeded
|
||||||
|
State1 --> [*] : Aborted
|
||||||
|
State2 --> State3 : Succeeded
|
||||||
|
State2 --> [*] : Aborted
|
||||||
|
state State3 {
|
||||||
|
state "Some State Name" as long1
|
||||||
|
long1 : Just a test
|
||||||
|
[*] --> long1
|
||||||
|
long1 --> long1 : New Data
|
||||||
|
long1 --> ProcessData : Enough Data
|
||||||
|
}
|
||||||
|
State3 --> State3 : Failed
|
||||||
|
State3 --> [*] : Succeeded / Save Result
|
||||||
|
State3 --> [*] : Aborted
|
||||||
|
|
||||||
|
@enduml`;
|
||||||
|
|
||||||
|
this.set('diagramText', txt);
|
||||||
|
this.generatePreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -28,7 +28,7 @@
|
||||||
@import "section/markdown.scss";
|
@import "section/markdown.scss";
|
||||||
@import "section/table.scss";
|
@import "section/table.scss";
|
||||||
@import "section/code.scss";
|
@import "section/code.scss";
|
||||||
@import "section/mermaid.scss";
|
@import "section/plantuml.scss";
|
||||||
@import "section/papertrail.scss";
|
@import "section/papertrail.scss";
|
||||||
@import "section/wysiwyg.scss";
|
@import "section/wysiwyg.scss";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
.section-mermaid-diagram {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
4
gui/app/styles/section/plantuml.scss
Normal file
4
gui/app/styles/section/plantuml.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.section-plantuml-diagram {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
<div id="section-editor-{{pageId}}">
|
<div id="section-editor-{{pageId}}">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-8 section-editor">
|
<div class="col-8 section-editor">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -11,7 +10,6 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<div class="float-right">
|
<div class="float-right">
|
||||||
{{#if busy}}
|
{{#if busy}}
|
||||||
|
@ -23,7 +21,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col section-editor">
|
<div class="col section-editor">
|
||||||
<div class="canvas rounded">
|
<div class="canvas rounded">
|
||||||
|
@ -31,7 +28,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id={{concat "discard-modal"}} class="modal" tabindex="-1" role="dialog">
|
<div id={{concat "discard-modal"}} class="modal" tabindex="-1" role="dialog">
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
{{#section/base-editor document=document folder=folder page=page tip="Concise name that describes the diagram" isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
|
||||||
<div class="section-mermaid-diagram">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12 col-sm-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Diagram Text </label> <a href="https://mermaidjs.github.io/" target="_blank">(Mermaid User Guide)</a>
|
|
||||||
<textarea rows=20 id={{editorId}} class="diagram-editor form-control mousetrap">{{diagramText}}</textarea>
|
|
||||||
<div class="mt-3">
|
|
||||||
<p>Insert sample diagrams:</p>
|
|
||||||
<p>
|
|
||||||
<button type="button" class="btn btn-light btn-sm" {{action 'onInsertFlowchart'}}>Flowchart</button>
|
|
||||||
<button type="button" class="btn btn-light btn-sm" {{action 'onInsertSequence'}}>Sequence</button>
|
|
||||||
<button type="button" class="btn btn-light btn-sm" {{action 'onInsertGantt'}}>Gantt</button>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 col-sm-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Diagram Preview</label>
|
|
||||||
<div id={{previewId}}>
|
|
||||||
{{{diagramPreview}}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/section/base-editor}}
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
{{#section/base-editor document=document folder=folder page=page busy=waiting tip="Concise name that describes the diagram" isDirty=(action 'isDirty') onCancel=(action 'onCancel') onAction=(action 'onAction')}}
|
||||||
|
<div class="section-plantuml-diagram">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label><a href="http://plantuml.com/" target="_blank">PlantUML Diagram</a></label>
|
||||||
|
<div class="my-3">
|
||||||
|
<p>Insert sample diagrams:</p>
|
||||||
|
<p>
|
||||||
|
<button type="button" class="btn btn-light" {{action 'onInsertSequence'}}>Sequence</button>
|
||||||
|
<button type="button" class="btn btn-light" {{action 'onInsertUseCase'}}>Use Case</button>
|
||||||
|
<button type="button" class="btn btn-light" {{action 'onInsertClass'}}>Class</button>
|
||||||
|
<button type="button" class="btn btn-light" {{action 'onInsertActivity'}}>Activity</button>
|
||||||
|
<button type="button" class="btn btn-light" {{action 'onInsertActivityNew'}}>Activity (new syntax)</button>
|
||||||
|
<button type="button" class="btn btn-light" {{action 'onInsertComponent'}}>Component</button>
|
||||||
|
<button type="button" class="btn btn-light" {{action 'onInsertState'}}>State</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{focus-textarea value=diagramText rows=30 id=editorId class="diagram-editor form-control mousetrap"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="button" class="btn btn-secondary" {{action 'onPreview'}}>{{previewButtonCaption}}</button>
|
||||||
|
<div id={{previewId}} class="text-center my-5">
|
||||||
|
<img src="{{diagramPreview}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/section/base-editor}}
|
|
@ -1,3 +1,3 @@
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
{{{page.body}}}
|
<img src="{{page.body}}" />
|
||||||
</div>
|
</div>
|
|
@ -50,7 +50,6 @@ module.exports = function (defaults) {
|
||||||
app.import('vendor/keycloak.js');
|
app.import('vendor/keycloak.js');
|
||||||
app.import('vendor/markdown-it.min.js');
|
app.import('vendor/markdown-it.min.js');
|
||||||
app.import('vendor/md5.js');
|
app.import('vendor/md5.js');
|
||||||
app.import('vendor/mermaid.min.js');
|
|
||||||
app.import('vendor/moment.js');
|
app.import('vendor/moment.js');
|
||||||
app.import('vendor/mousetrap.js');
|
app.import('vendor/mousetrap.js');
|
||||||
app.import('vendor/prism.js');
|
app.import('vendor/prism.js');
|
||||||
|
|
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 359 B |
Before Width: | Height: | Size: 630 B After Width: | Height: | Size: 630 B |
6
gui/vendor/mermaid.min.js
vendored
6
gui/vendor/mermaid.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue