set admin user's workspace using $GOPATH by default

This commit is contained in:
Liang Ding 2014-11-12 14:17:35 +08:00
parent b903f6b907
commit c362c3a4ef
16 changed files with 60 additions and 798 deletions

View File

@ -141,9 +141,7 @@ func FixedTimeSave() {
func (c *conf) GetUserWorkspace(username string) string {
for _, user := range c.Users {
if user.Name == username {
ret := strings.Replace(user.Workspace, "{WD}", c.WD, 1)
return filepath.FromSlash(ret)
return user.GetWorkspace()
}
}
@ -154,9 +152,13 @@ func (c *conf) GetUserWorkspace(username string) string {
//
// Compared to the use of Wide.Workspace, this function will be processed as follows:
// 1. Replace {WD} variable with the actual directory path
// 2. Replace "/" with "\\" (Windows)
// 2. Replace ${GOPATH} with enviorment variable GOPATH
// 3. Replace "/" with "\\" (Windows)
func (c *conf) GetWorkspace() string {
return filepath.FromSlash(strings.Replace(c.Workspace, "{WD}", c.WD, 1))
w := strings.Replace(c.Workspace, "{WD}", c.WD, 1)
w = strings.Replace(w, "${GOPATH}", os.Getenv("GOPATH"), 1)
return filepath.FromSlash(w)
}
// GetGoFmt gets the path of Go format tool, returns "gofmt" if not found.
@ -182,9 +184,13 @@ func (c *conf) GetGoFmt(username string) string {
//
// Compared to the use of Wide.Workspace, this function will be processed as follows:
// 1. Replace {WD} variable with the actual directory path
// 2. Replace "/" with "\\" (Windows)
// 2. Replace ${GOPATH} with enviorment variable GOPATH
// 3. Replace "/" with "\\" (Windows)
func (u *User) GetWorkspace() string {
return filepath.FromSlash(strings.Replace(u.Workspace, "{WD}", Wide.WD, 1))
w := strings.Replace(u.Workspace, "{WD}", Wide.WD, 1)
w = strings.Replace(w, "${GOPATH}", os.Getenv("GOPATH"), 1)
return filepath.FromSlash(w)
}
// GetUser gets configuration of the user specified by the given username, returns nil if not found.

View File

@ -11,13 +11,13 @@
"MaxProcs": 4,
"RuntimeMode": "dev",
"WD": "${pwd}",
"Workspace": "{WD}/data/workspace",
"Workspace": "${GOPATH}",
"Locale": "en_US",
"Users": [
{
"Name": "admin",
"Password": "admin",
"Workspace": "{WD}/data/user_workspaces/admin",
"Workspace": "${GOPATH}",
"Locale": "en_US",
"GoFormat": "gofmt",
"FontFamily": "Helvetica",
@ -31,6 +31,20 @@
"Files": [],
"CurrentFile": ""
}
},
{
"Name": "test1",
"Password": "1",
"Workspace": "D:\\test1",
"Locale": "en_US",
"GoFormat": "gofmt",
"FontFamily": "Helvetica",
"FontSize": "13px",
"Editor": {
"FontFamily": "Consolas, 'Courier New', monospace",
"FontSize": "inherit"
},
"LatestSessionContent": null
}
]
}

View File

@ -1 +0,0 @@
User workspaces.

View File

@ -1,319 +0,0 @@
/* start icon */
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?35cb2z');
src: url('fonts/icomoon.eot?#iefix35cb2z') format('embedded-opentype'), url('fonts/icomoon.woff?35cb2z') format('woff'), url('fonts/icomoon.ttf?35cb2z') format('truetype'), url('fonts/icomoon.svg?35cb2z#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
.font-ico {
font-family: 'icomoon';
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #666;
cursor: pointer;
font-size: 13px;
line-height: 18px;
}
.font-ico:hover {
color: #333;
}
.ico-play:before {
content: "\e605";
}
.ico-save:before {
content: "\f0c7";
}
.ico-max:before {
content: "\f096";
}
.ico-format:before {
content: "\e60b";
}
.ico-buildrun:before {
content: "\e607";
}
.ico-stop:before {
content: "\e608";
}
.ico-restore:before {
content: "\e60c";
}
.ico-min:before {
content: "\e60d";
position: absolute;
right: 5px;
}
.ico-close:before {
content: "\e60a";
}
/* end ico */
/* start frame */
.frame {
position: absolute;
border: 1px solid #5F5F5F;
background-color: #F8F8F8;
width: 320px;
z-index: 21;
display: none;
}
.frame li {
padding: 0 5px;
line-height: 25px;
cursor: pointer;
}
.frame li.disabled {
color: #999;
}
.frame li:hover {
background-color: #3875D7;
color: #FFF;
}
.frame li.disabled:hover {
background-color: #F8F8F8;
color: #999;
}
.frame a {
color: #000;
text-decoration: none;
}
.frame li:hover a,
.frame a:hover {
color: #FFF;
}
.frame .hr {
background-color: #bdbdbd;
height: 1px;
margin: 0 1px;
}
/* end frame */
/* start tabs */
.tabs {
height: 20px;
overflow: hidden;
width: 100%;
background-color: #E6E6E6;
border-top: 1px solid #A4A4A4;
border-bottom: 1px solid #9D9D9D;
}
.tabs > div {
float: left;
line-height: 18px;
height: 18px;
padding: 0 5px;
cursor: pointer;
background-color: #DDD;
color: #8B8B8B;
border-right: 1px solid #ADADAD;
}
.tabs > div.current {
background-color: #9F9F9F;
color: #FFF;
}
/* end tabs */
/* start framework */
.content {
position: relative;
overflow: hidden;
}
/* end framework */
/* start menu */
.menu {
background-color: #F0F0F0;
height: 24px;
}
.menu > ul > li {
float: left;
}
.menu > ul > li > span {
color: #000;
font-size: 12px;
line-height: 24px;
padding: 5px;
text-decoration: none;
cursor: pointer;
}
/* end menu */
/* start editor */
.edit-panel {
width: 80%;
position: absolute;
left: 20%;
width: 80%;
height: 70%;
overflow: hidden;
}
.edit-panel .tabs > div {
background-color: #d1d1d1;
border-right-color: #9b9b9b;
color: #333;
cursor: auto;
}
.edit-panel .tabs > div.current {
background-color: #F7F7F7;
}
.toolbars {
position: absolute;
right: 5px;
top: 1px;
}
.edit-panel .tabs .ico {
background-image: url("../images/ico-file.png");
float: left;
height: 16px;
margin: 2px 0 0 -2px;
width: 16px;
}
/* 统一为 static/js/lib/codemirror-4.5/addon/hint/show-hint.css 中的.CodeMirror-hints */
.edit-exprinfo {
position: absolute;
z-index: 10;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
-moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
border-radius: 3px;
border: 1px solid silver;
background: white;
font-size: 90%;
font-family: Consolas, Courier New, monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror,
.CodeMirror-hints {
font-family: Consolas, Courier New, monospace;
}
.CodeMirror-focused .cm-matchhighlight {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);
background-position: bottom;
background-repeat: repeat-x;
}
.CodeMirror-hint {
padding-right: 18px;
max-width: none;
}
.CodeMirror-hint:hover {
background: #08f;
color: white;
}
/* end editor */
/* start bottom-window-group */
.bottom-window-group {
width: 80%;
position: absolute;
left: 20%;
width: 80%;
height: 30%;
top: 70%;
z-index: 7;
background-color: #fff;
}
.bottom-window-group-max {
height: 100%;
left: 0;
top: 0;
width: 100%;
z-index: 11;
}
.bottom-window-group > div > div {
overflow: auto;
}
.bottom-window-group .output {
font-family: Consolas, Courier New, monospace;
padding: 0 5px;
line-height: 16px;
font-size: 12px;
}
.bottom-window-group .output pre {
margin: 0;
}
.bottom-window-group .output .start-build,
.bottom-window-group .output .start-test,
.bottom-window-group .output .start-install,
.bottom-window-group .output .start-get {
color: #999;
}
.bottom-window-group .output .build-succ,
.bottom-window-group .output .test-succ,
.bottom-window-group .output .install-succ,
.bottom-window-group .output .get-succ {
color: rgb(0, 153, 0);
}
.bottom-window-group .output .build-error,
.bottom-window-group .output .test-error,
.bottom-window-group .output .install-error,
.bottom-window-group .output .get-error {
color: red;
}
.bottom-window-group table {
width: 100%;
}
.bottom-window-group td {
border-bottom: 1px solid #DDD;
line-height: 20px;
}
.bottom-window-group .notification .type,
.bottom-window-group .notification .severity {
width: 50px;
padding: 0 5px;
}
.bottom-window-group .search li {
cursor: pointer;
line-height: 20px;
padding: 0 3px;
word-wrap: normal;
word-break: normal;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.bottom-window-group .search li.selected {
background-color: #3875d7;
color: #FFF;
}
.bottom-window-group .search .path {
color: #999;
font-size: 12px;
}
.bottom-window-group .search li.selected .path {
color: #FFF;
}
/* end bottom-window-group */
/* start footer */
.footer {
border-top: 1px solid #919191;
background-color: #F0F0F0;
padding-left: 5px;
height: 19px;
line-height: 18px;
}
.footer .cursor {
cursor: pointer;
}
.notification-count {
float: right;
display: none;
cursor: pointer;
background-color: red;
color: #FFF;
margin: 1px 5px;
padding: 0 2px;
border-radius: 3px;
line-height: 16px;
}
/* end footer */

View File

@ -1,333 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{.i18n.wide}}</title>
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/show-hint.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/lint.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/overwrite/codemirror/theme/wide.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/ztree/zTreeStyle.css">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/dialog.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/base.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/base-{{.conf.Locale}}.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/wide.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/side.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/start.css?{{.conf.StaticResourceVersion}}">
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/css/about.css?{{.conf.StaticResourceVersion}}">
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
</head>
<body>
<!-- 主菜单 -->
<div class="menu fn-clear">
<ul class="fn-cleaer">
<li>
<span>{{.i18n.file}}</span>
<div class="frame">
<ul>
<li class="save-all disabled" onclick="wide.saveAllFiles()">
<span>{{.i18n.save_all_files}}</span>
</li>
<li class="close-all disabled" onclick="wide.closeAllFiles()">
<span>{{.i18n.close_all_files}}</span>
</li>
<li class="hr"></li>
<li onclick="wide.exit()">
<span>{{.i18n.exit}}</span>
</li>
</ul>
</div>
</li>
<li>
<span>{{.i18n.run}}</span>
<div class="frame">
<ul>
<li class="build disabled" onclick="wide.build()">
<span>{{.i18n.build}}</span>
</li>
<li class="run disabled" onclick="wide.run()">
<span>{{.i18n.build_n_run}}</span>
</li>
<li class="hr"></li>
<li class="go-test disabled" onclick="wide.test()">
<span>{{.i18n.test}}</span>
</li>
<li class="hr"></li>
<li class="go-get disabled" onclick="wide.goget()">
<span>{{.i18n.goget}}</span>
</li>
<li class="go-install disabled" onclick="wide.goinstall()">
<span>{{.i18n.goinstall}}</span>
</li>
</ul>
</div>
</li>
<!--
<li>
<span>{{.i18n.debug}}</span>
<div class="frame">
<ul>
<li>
<span>{{.i18n.debug}}</span>
</li>
</ul>
</div>
</li>
-->
<li>
<span>{{.i18n.team}}</span>
<div class="frame">
<ul>
<li class="signup" onclick="window.open('/signup')">
<span>{{.i18n.sign_up}}</span>
</li>
</ul>
</div>
</li>
<li>
<span>{{.i18n.help}}</span>
<div class="frame">
<ul>
<li onclick="window.open('https://www.gitbook.io/book/88250/wide-user-guide')">
<span>{{.i18n.wide_doc}}</span>
</li>
<li onclick="window.open('https://github.com/b3log/wide/issues/new')">
{{.i18n.report_issues}}
</li>
<li class="hr"></li>
<li onclick="window.open('/keyboard_shortcuts')">
{{.i18n.keyboard_shortcuts}}
</li>
<li class="hr"></li>
<li onclick="editors.openStartPage()">
<span>{{.i18n.start_page}}</span>
</li>
<li onclick="wide.openAbout()">
<span>{{.i18n.about}}</span>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="content">
<div class="side">
<span title="{{.i18n.min}}" class="font-ico ico-min"></span>
<div class="tabs">
<div class="current" data-index="filreTree">
<span title="{{.i18n.file}}">{{.i18n.file}}</span>
</div>
</div>
<div class="tabs-panel">
<div data-index="filreTree">
<ul id="files" tabindex="-1" class="ztree"></ul>
<!-- 目录右键菜单 -->
<div id="dirRMenu" class="frame">
<ul>
<li onclick="tree.newFile();">{{.i18n.create_file}}</li>
<li onclick="tree.newDir();">{{.i18n.create_dir}}</li>
<li onclick="tree.removeIt();">{{.i18n.delete}}</li>
</ul>
</div>
<!-- 文件右键菜单 -->
<div id="fileRMenu" class="frame">
<ul>
<li onclick="tree.removeIt();">{{.i18n.delete}}</li>
</ul>
</div>
</div>
</div>
</div>
<div class="edit-panel">
<div class="toolbars fn-none">
<span onclick="wide.run()" class="font-ico ico-buildrun" title="{{.i18n.build_n_run}}"></span>
<span onclick="wide.saveFile()" title="{{.i18n.save}}" class="font-ico ico-save"></span>
<span onclick="wide.fmt(editors.getCurrentPath(), wide.curEditor)" class="ico-format font-ico" title="{{.i18n.format}}"></span>
<span class="font-ico ico-max" onclick="windows.maxEditor()" title="{{.i18n.max_editor}}"></span>
</div>
<div class="tabs"></div>
<div class="tabs-panel"></div>
</div>
<div class="bottom-window-group">
<span title="{{.i18n.min}}" class="font-ico ico-min"></span>
<div class="tabs">
<div class="current" data-index="output">
<span title="{{.i18n.output}}">{{.i18n.output}}</span>
</div>
<div data-index="search">
<span title="{{.i18n.search}}">{{.i18n.search}}</span>
</div>
<div data-index="notification">
<span title="{{.i18n.notification}}">{{.i18n.notification}}</span>
</div>
</div>
<div class="tabs-panel">
<div data-index="output">
<div class="output" tabindex="-1">
<div></div>
</div>
</div>
<div class="fn-none" data-index="search">
<div tabindex="-1" class="search">
<div class="tabs fn-none">
<div class="current" data-index="first">
<span class="first"></span><span class="ico-close font-ico"></span>
</div>
</div>
<div class="tabs-panel">
<div data-index="first"></div>
</div>
</div>
</div>
<div class="fn-none" data-index="notification">
<div tabindex="-1" class="notification">
<table cellpadding="0" cellspacing="0"></table>
</div>
</div>
</div>
</div>
</div>
<div class="footer fn-clear">
<div class="fn-left">
<span title="{{.i18n.restore_side}}" class="font-ico ico-restore fn-none"></span>
<span title="{{.i18n.restore_bottom}}" class="font-ico ico-restore fn-none"></span>
</div>
<div class="fn-right">
<span class="cursor"></span>
<span class="notification-count" title="{{.i18n.unread_notification}}">{{.i18n.notification}}</span>
</div>
</div>
<div id="dialogRemoveConfirm" class="fn-none">
{{.i18n.isDelete}} <b></b>?
</div>
<div id="dialogAlert" class="fn-none"></div>
<div id="dialogAbout" class="fn-none"></div>
<div id="dialogNewFilePrompt" class="dialog-prompt fn-none">
<input/>
</div>
<div id="dialogNewDirPrompt" class="dialog-prompt fn-none">
<input/>
</div>
<div id="dialogGoLinePrompt" class="dialog-prompt fn-none">
<input/>
</div>
<div id="dialogSearchForm" class="dialog-form fn-none">
<input placeholder="{{.i18n.keyword}}" />
<input placeholder="{{.i18n.file_format}}" />
</div>
<script>
var config = {
"pathSeparator": {
{.pathSeparator
}
},
"latestSessionContent": {
{.latestSessionContent
}
},
"label": {
"restore_editor": "{{.i18n.restore_editor}}",
"max_editor": "{{.i18n.max_editor}}",
"delete": "{{.i18n.delete}}",
"cancel": "{{.i18n.cancel}}",
"goto_line": "{{.i18n.goto_line}}",
"go": "{{.i18n.go}}",
"create": "{{.i18n.create}}",
"create_file": "{{.i18n.create_file}}",
"create_dir": "{{.i18n.create_dir}}",
"tip": "{{.i18n.tip}}",
"confirm": "{{.i18n.confirm}}",
"build_n_run": "{{.i18n.build_n_run}}",
"stop": "{{.i18n.stop}}",
"find_usages": "{{.i18n.find_usages}}",
"search_text": "{{.i18n.search_text}}",
"search": "{{.i18n.search}}",
"start_page": "{{.i18n.start_page}}",
"confirm_save": "{{.i18n.confirm_save}}",
"community": "{{.i18n.community}}",
"about": "{{.i18n.about}}",
"new_version_available": "{{.i18n.new_version_available}}",
"colon": "{{.i18n.colon}}",
"uptodate": "{{.i18n.uptodate}}"
},
"channel": {
"editor": '{{.conf.EditorChannel}}',
"shell": '{{.conf.ShellChannel}}',
"output": '{{.conf.OutputChannel}}',
"session": '{{.conf.SessionChannel}}'
},
"wideSessionId": '{{.session.Id}}'
};
// 发往 Wide 的所有 AJAX 请求需要使用该函数创建请求参数.
function newWideRequest() {
var ret = {
sid: config.wideSessionId
}
return ret;
}
</script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/reconnecting-websocket.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="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/codemirror.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/lint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/lint/json-lint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/selection/active-line.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/overwrite/codemirror/addon/hint/show-hint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/hint/anyword-hint.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/display/rulers.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closebrackets.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/matchbrackets.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/edit/closetag.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/searchcursor.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/search.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/dialog/dialog.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/search/match-highlighter.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldcode.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/foldgutter.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/brace-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/xml-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/markdown-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/addon/fold/comment-fold.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/go/go.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/xml/xml.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/htmlmixed/htmlmixed.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/javascript/javascript.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/markdown/markdown.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/css/css.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/shell/shell.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/codemirror-{{.codeMirrorVer}}/mode/sql/sql.js"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/lint/json-lint.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/lint/go-lint.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/js-beautify-1.5.4/beautify.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/js-beautify-1.5.4/beautify-html.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/js-beautify-1.5.4/beautify-css.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/tabs.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/dialog.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/editors.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/notification.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/tree.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/wide.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/session.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/menu.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/windows.js?{{.conf.StaticResourceVersion}}"></script>
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/hotkeys.js?{{.conf.StaticResourceVersion}}"></script>
</body>
</html>

View File

@ -1,36 +0,0 @@
{
"Server": "{IP}:7070",
"StaticServer": "http://{IP}:7070",
"EditorChannel": "ws://{IP}:7070",
"OutputChannel": "ws://{IP}:7070",
"ShellChannel": "ws://{IP}:7070",
"SessionChannel": "ws://{IP}:7070",
"HTTPSessionMaxAge": 86400,
"StaticResourceVersion": "201410271700",
"MaxProcs": 4,
"RuntimeMode": "dev",
"Pwd": "{pwd}",
"Workspace": "{pwd}/data/workspace",
"Locale": "en_US",
"Users": [{
"Name": "admin",
"Password": "admin",
"Workspace": "{pwd}/data/user_workspaces/admin",
"Locale": "en_US",
"GoFormat": "gofmt",
"LatestSessionContent": {
"FileTree": [
"D:\\GoGoGo\\src\\github.com\\b3log\\wide\\data\\user_workspaces\\admin\\src",
"D:\\GoGoGo\\src\\github.com\\b3log\\wide\\data\\user_workspaces\\admin\\src\\format",
"D:\\GoGoGo\\src\\github.com\\b3log\\wide\\data\\user_workspaces\\admin\\src\\gotest",
"D:\\GoGoGo\\src\\github.com\\b3log\\wide\\data\\user_workspaces\\admin\\src\\hello",
"D:\\GoGoGo\\src\\github.com\\b3log\\wide\\data\\user_workspaces\\admin\\src\\time"
],
"Files": [
"D:\\GoGoGo\\src\\github.com\\b3log\\wide\\data\\user_workspaces\\admin\\src\\time\\main.go",
"D:\\GoGoGo\\src\\github.com\\b3log\\wide\\data\\user_workspaces\\admin\\src\\format\\index.html"
],
"CurrentFile": "D:\\GoGoGo\\src\\github.com\\b3log\\wide\\data\\user_workspaces\\admin\\src\\format\\index.html"
}
}]
}

View File

@ -1,16 +0,0 @@
package test
import (
"testing"
)
func Test_Division_1(t *testing.T) {
if i, e := Division(6, 2); i != 3 || e != nil { //try a unit test on function
t.Error("除法函数测试没通过") // 如果不是如预期的那么就报错
} else {
t.Log("第一个测试通过了") //记录一些你期望记录的信息
}
}
func Test_Division_2(t *testing.T) {
}

View File

@ -1,17 +0,0 @@
package test
import (
"testing"
)
func Test_Division_3(t *testing.T) {
if i, e := Division(6, 2); i != 3 || e != nil { //try a unit test on function
t.Error("除法函数测试没通过") // 如果不是如预期的那么就报错
} else {
t.Log("第一个测试通过了") //记录一些你期望记录的信息
}
}
func Test_Division_4(t *testing.T) {
t.Error("就是不通过")
}

View File

@ -1,13 +0,0 @@
package test
import (
"errors"
)
func Division(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("除数不能为0")
}
return a / b, nil
}

View File

@ -1,9 +0,0 @@
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, 世界")
}

View File

@ -1,17 +0,0 @@
package main
import (
"fmt"
"time"
"time/pkg"
)
func main() {
for i := 0; i < 50; i++ {
fmt.Println("Hello, 世界", pkg.Now())
time.Sleep(time.Second)
}
}

View File

@ -1,17 +0,0 @@
package pkg
import (
"time"
)
func Now() time.Time {
return time.Now()
}
func Now1() time.Time {
return time.Now()
}
func Now2() {
}

View File

@ -1 +0,0 @@
Master workspace.

View File

@ -114,9 +114,15 @@ func GetFile(w http.ResponseWriter, r *http.Request) {
data["mode"] = "img"
path2 := strings.Replace(path, "\\", "/", -1)
idx := strings.Index(path2, "/data/user_workspaces")
data["path"] = path2[idx:]
user := GetUsre(path)
if nil == user {
glog.Warningf("The path [%s] has no owner")
data["path"] = ""
return
}
data["path"] = "/workspace/" + user.Name + "/" + strings.Replace(path, user.GetWorkspace(), "", 1)
return
}
@ -568,3 +574,14 @@ func isImg(extension string) bool {
return false
}
}
// GetUsre gets the user the specified path belongs to. Returns nil if not found.
func GetUsre(path string) *conf.User {
for _, user := range conf.Wide.Users {
if strings.HasPrefix(path, user.GetWorkspace()) {
return user
}
}
return nil
}

View File

@ -217,7 +217,10 @@ func main() {
serveSingle("/favicon.ico", "./static/favicon.ico")
// workspaces
http.Handle("/data/", http.StripPrefix("/data/", http.FileServer(http.Dir("data"))))
for _, user := range conf.Wide.Users {
http.Handle("/workspace/"+user.Name+"/",
http.StripPrefix("/workspace/"+user.Name+"/", http.FileServer(http.Dir(user.GetWorkspace()))))
}
// session
http.HandleFunc("/session/ws", handlerWrapper(session.WSHandler))

View File

@ -143,8 +143,6 @@ func SignUpUser(w http.ResponseWriter, r *http.Request) {
}
func addUser(username, password string) string {
// XXX: validate
for _, user := range conf.Wide.Users {
if user.Name == username {
return UserExists
@ -155,10 +153,10 @@ func addUser(username, password string) string {
dir := filepath.Dir(firstUserWorkspace)
workspace := filepath.Join(dir, username)
conf.Wide.Users = append(conf.Wide.Users,
&conf.User{Name: username, Password: password, Workspace: workspace,
Locale: conf.Wide.Locale, GoFormat: "gofmt", FontFamily: "Helvetica", FontSize: "inherit",
Editor: &conf.Editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit"}})
newUser := &conf.User{Name: username, Password: password, Workspace: workspace,
Locale: conf.Wide.Locale, GoFormat: "gofmt", FontFamily: "Helvetica", FontSize: "13px",
Editor: &conf.Editor{FontFamily: "Consolas, 'Courier New', monospace", FontSize: "inherit"}}
conf.Wide.Users = append(conf.Wide.Users, newUser)
if !conf.Save() {
return UserCreateError
@ -167,6 +165,9 @@ func addUser(username, password string) string {
conf.CreateWorkspaceDir(workspace)
conf.UpdateCustomizedConf(username)
http.Handle("/workspace/"+username+"/",
http.StripPrefix("/workspace/"+username+"/", http.FileServer(http.Dir(newUser.GetWorkspace()))))
glog.Infof("Created a user [%s]", username)
return UserCreated