This commit is contained in:
Liang Ding 2014-09-16 23:58:52 +08:00
parent 1ced1982ce
commit 004c0a67a7
6 changed files with 111 additions and 75 deletions

View File

@ -29,14 +29,15 @@
例如在执行“构建 & 运行”时Wide 会设置命令 go build 执行的环境变量 $GOPATH 为用户的工作空间,这样编译过程就是在该用户的工作空间中进行,保证其隔离性。 例如在执行“构建 & 运行”时Wide 会设置命令 go build 执行的环境变量 $GOPATH 为用户的工作空间,这样编译过程就是在该用户的工作空间中进行,保证其隔离性。
</p> </p>
<h3>Tabs</h3> <h3>Wide 会话</h3>
<p> <p>
用户可以打开多个编辑器 tabs但输出窗口只有一个。同时运行多个程序的场景可以通过打开多个浏览器 tabs 达成。 在 UI 上存在两种 tab浏览器 tab编辑器 tab。
用户可以在一个浏览器 tab 中打开多个编辑器 tabs但输出窗口只有一个。这意味着一个浏览器 tab 只能有一个正在运行的用户代码的程序进程。
需要同时运行多个程序进程的场景可以通过打开多个浏览器 tabs 达成。
</p> </p>
<p> <p>
使用编辑器 tabs (而不使用浏览器 tabs主要是考虑到和文件树的同步显示这是非常实用的功能。 一个浏览器 tab 对应一个 Wide 会话:只要打开/刷新一个 tab就会新建一个 Wide 会话。
在大多数情况下,一个浏览器 tab 使用 Wide 应该就可以完成开发者的大多数需求,这样的用户体验也更接近桌面 IDE。
</p> </p>
<h3>WebSocket</h3> <h3>WebSocket</h3>
@ -49,11 +50,11 @@
<li>Shell 通道</li> <li>Shell 通道</li>
</ul> </ul>
通道和用户会话一对一关联,也就是说如果用户新开浏览器 tab老的 tab 的通道就会失效。目前为了简化才这样实现,后续需要改进为每个浏览器 tab 都开不同的通道 通道和会话一对一关联,也就是说如果用户新开浏览器 tab新建通道何其关联
<h3>事件与通知</h3> <h3>事件与通知</h3>
<p> <p>
每个用户会话都有一个对应的事件队列,当接收到事件时取出该事件并转为通知,再通过通知窗口通道推送给前端。 每个会话都有一个对应的事件队列,当接收到事件时取出该事件并转为通知,再通过通知窗口通道推送给前端。
还存在一个全局事件队列,入队的事件将分发到每个用户的事件队列中,以便进行通知广播。 还存在一个全局事件队列,入队的事件将分发到每个用户的事件队列中,以便进行通知广播。
</p> </p>

20
main.go
View File

@ -39,25 +39,29 @@ func init() {
// Wide 首页. // Wide 首页.
func indexHandler(w http.ResponseWriter, r *http.Request) { func indexHandler(w http.ResponseWriter, r *http.Request) {
// 创建一个 Wide 会话
wideSession := user.NewSession()
i18n.Load() i18n.Load()
model := map[string]interface{}{"Wide": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r)} model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r),
"session": wideSession}
session, _ := user.Session.Get(r, "wide-session") httpSession, _ := user.Session.Get(r, "wide-session")
if session.IsNew { if httpSession.IsNew {
// TODO: 写死以 admin 作为用户登录 // TODO: 写死以 admin 作为用户登录
name := conf.Wide.Users[0].Name name := conf.Wide.Users[0].Name
session.Values["username"] = name httpSession.Values["username"] = name
session.Values["id"] = strconv.Itoa(rand.Int()) httpSession.Values["id"] = strconv.Itoa(rand.Int())
// 一天过期 // 一天过期
session.Options.MaxAge = 60 * 60 * 24 httpSession.Options.MaxAge = 60 * 60 * 24
glog.Infof("Created a session [%s] for user [%s]", session.Values["id"].(string), name) glog.Infof("Created a session [%s] for user [%s]", httpSession.Values["id"].(string), name)
} }
session.Save(r, w) httpSession.Save(r, w)
t, err := template.ParseFiles("view/index.html") t, err := template.ParseFiles("view/index.html")

View File

@ -28,7 +28,7 @@ var shellWS = map[string]*util.WSChannel{}
func IndexHandler(w http.ResponseWriter, r *http.Request) { func IndexHandler(w http.ResponseWriter, r *http.Request) {
i18n.Load() i18n.Load()
model := map[string]interface{}{"Wide": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r)} model := map[string]interface{}{"conf": conf.Wide, "i18n": i18n.GetAll(r), "locale": i18n.GetLocale(r)}
session, _ := user.Session.Get(r, "wide-session") session, _ := user.Session.Get(r, "wide-session")

View File

@ -1,8 +1,39 @@
package user package user
import ( import (
"math/rand"
"strconv"
"time"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
) )
// 用户会话. const (
SessionStateActive = iota // 会话状态:活的
)
// 用户 HTTP 会话,用于验证登录.
var Session = sessions.NewCookieStore([]byte("BEYOND")) var Session = sessions.NewCookieStore([]byte("BEYOND"))
// Wide 会话,对应一个浏览器 tab.
type WideSession struct {
Id string // 唯一标识
State int // 状态
Created time.Time // 创建时间
Updated time.Time // 最近一次使用时间
}
// 创建一个 Wide 会话.
func NewSession() *WideSession {
rand.Seed(time.Now().UnixNano())
id := strconv.Itoa(rand.Int())
now := time.Now()
return &WideSession{
Id: id,
State: SessionStateActive,
Created: now,
Updated: now,
}
}

View File

@ -2,18 +2,18 @@
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{.i18n.wide}}</title> <title>{{.i18n.wide}} - {{.session.Id}}</title>
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/codemirror.css"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/codemirror.css">
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/hint/show-hint.css"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/hint/show-hint.css">
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/lint/lint.css"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/lint/lint.css">
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/display/fullscreen.css"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/display/fullscreen.css">
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/foldgutter.css"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/foldgutter.css">
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/theme/lesser-dark.css"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/theme/lesser-dark.css">
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/js/lib/ztree/zTreeStyle.css"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/ztree/zTreeStyle.css">
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/css/base.css?{{.Wide.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/base.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/css/side.css?{{.Wide.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/side.css?{{.conf.StaticResourceVersion}}">
</head> </head>
<body> <body>
<!-- 主菜单 --> <!-- 主菜单 -->
@ -167,52 +167,52 @@
<script type="text/javascript"> <script type="text/javascript">
var config = { var config = {
channel: { channel: {
editor: '{{.Wide.EditorChannel}}', editor: '{{.conf.EditorChannel}}',
shell: '{{.Wide.ShellChannel}}', shell: '{{.conf.ShellChannel}}',
output: '{{.Wide.OutputChannel}}' output: '{{.conf.OutputChannel}}'
} }
};</script> };</script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/reconnecting-websocket.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/reconnecting-websocket.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/ztree/jquery.ztree.all-3.5.min.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/ztree/jquery.ztree.all-3.5.min.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/underscore.string-2.3.3/underscore.string.min.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/underscore.string-2.3.3/underscore.string.min.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/codemirror.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/codemirror.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/lint/lint.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/lint/lint.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/lint/json-lint.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/lint/json-lint.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/selection/active-line.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/selection/active-line.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/hint/show-hint.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/hint/show-hint.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/hint/anyword-hint.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/hint/anyword-hint.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/display/fullscreen.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/display/fullscreen.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/display/rulers.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/display/rulers.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/edit/closebrackets.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/edit/closebrackets.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/edit/matchbrackets.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/edit/matchbrackets.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/edit/closetag.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/edit/closetag.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/search/searchcursor.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/search/searchcursor.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/search/match-highlighter.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/search/match-highlighter.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/foldcode.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/foldcode.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/foldgutter.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/foldgutter.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/brace-fold.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/brace-fold.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/xml-fold.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/xml-fold.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/markdown-fold.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/markdown-fold.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/comment-fold.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/fold/comment-fold.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/mode/go/go.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/mode/go/go.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/mode/xml/xml.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/mode/xml/xml.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/mode/htmlmixed/htmlmixed.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/mode/htmlmixed/htmlmixed.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/mode/javascript/javascript.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/mode/javascript/javascript.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/mode/markdown/markdown.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/mode/markdown/markdown.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/mode/css/css.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/mode/css/css.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/mode/shell/shell.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/mode/shell/shell.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/codemirror-4.5/mode/sql/sql.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/mode/sql/sql.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lint/json-lint.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lint/json-lint.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lint/go-lint.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lint/go-lint.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/tabs.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/tabs.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/editor.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/editor.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/notification.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/notification.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/tree.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/tree.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/wide.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/wide.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/menu.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/menu.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/hotkeys.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/hotkeys.js?{{.conf.StaticResourceVersion}}"></script>
</body> </body>
</html> </html>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{.i18n.wide}}</title> <title>{{.i18n.wide}}</title>
<link rel="stylesheet" href="{{.Wide.StaticServer}}/static/css/shell.css?{{.Wide.StaticResourceVersion}}"> <link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/shell.css?{{.conf.StaticResourceVersion}}">
</head> </head>
<body> <body>
<input id="shellInput" placeholder="Command..."/> <input id="shellInput" placeholder="Command..."/>
@ -15,14 +15,14 @@
<script type="text/javascript"> <script type="text/javascript">
var config = { var config = {
channel: { channel: {
shell: '{{.Wide.ShellChannel}}' shell: '{{.conf.ShellChannel}}'
} }
}; };
</script> </script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/lib/reconnecting-websocket.js"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/reconnecting-websocket.js"></script>
<script type="text/javascript" src="{{.Wide.StaticServer}}/static/js/shell.js?{{.Wide.StaticResourceVersion}}"></script> <script type="text/javascript" src="{{.conf.StaticServer}}/static/js/shell.js?{{.conf.StaticResourceVersion}}"></script>
</body> </body>
</html> </html>