Compare commits
58 Commits
1.0-beta.2
...
dev-binnch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb484b2132 | ||
|
|
4d5a3ffd0f | ||
|
|
f78eb4db49 | ||
|
|
8a61b64575 | ||
|
|
419585ff7d | ||
|
|
ffaaa8c11a | ||
|
|
3417e71d04 | ||
|
|
014a141808 | ||
|
|
c35aa1eaa4 | ||
|
|
96b094844e | ||
|
|
9af13bcc32 | ||
|
|
29215a1d64 | ||
|
|
d828a10e7b | ||
|
|
a851aaa399 | ||
|
|
ac99e20aa4 | ||
|
|
d5dabecb81 | ||
|
|
df9bc37e1d | ||
|
|
4277caa571 | ||
|
|
1d18908cd0 | ||
|
|
916ee52cdb | ||
|
|
289e7b16d9 | ||
|
|
016ef5de2d | ||
|
|
52d0a7ed21 | ||
|
|
ddf3236c4f | ||
|
|
9515f1e58f | ||
|
|
c514d0bc1c | ||
|
|
d24531dc78 | ||
|
|
2cfc89ca5f | ||
|
|
a393bb8723 | ||
|
|
599e54de5b | ||
|
|
b0d4005ad6 | ||
|
|
c0cd433c3f | ||
|
|
792c8cfd40 | ||
|
|
4f102ff883 | ||
|
|
40973c4615 | ||
|
|
58bf623d05 | ||
|
|
46e97abe91 | ||
|
|
be01c9c3f7 | ||
|
|
17718732cc | ||
|
|
e2e90f8618 | ||
|
|
25d5df6bfc | ||
|
|
b781f8318c | ||
|
|
0e07cbab8b | ||
|
|
ed75704032 | ||
|
|
c49593171c | ||
|
|
45d72051d0 | ||
|
|
10b387faa6 | ||
|
|
30ebc95abf | ||
|
|
9bc65bc099 | ||
|
|
39809dc4c6 | ||
|
|
8c4a203d96 | ||
|
|
034ad821ca | ||
|
|
c894b7b308 | ||
|
|
c0979be9f3 | ||
|
|
b45e9eacb0 | ||
|
|
16d47418ad | ||
|
|
5d48d1853d | ||
|
|
f503da30b7 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,8 +8,6 @@ bin/release
|
||||
bin/tmp
|
||||
bin/test
|
||||
bin/src
|
||||
conf/app.conf
|
||||
conf/routes
|
||||
public/upload
|
||||
app/routes/routes.go
|
||||
app/tmp/main.go
|
||||
@@ -18,3 +16,4 @@ app/tmp/main.go
|
||||
.project
|
||||
public/config.codekit
|
||||
files
|
||||
conf/app.conf
|
||||
|
||||
17
.project
17
.project
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>leanote-public</name>
|
||||
<comment>leanote, your own cloud note!</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.googlecode.goclipse.goBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>goclipse.goNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
119
README.md
119
README.md
@@ -1,8 +1,10 @@
|
||||
[中文](https://github.com/leanote/leanote#1-介绍)
|
||||
|
||||
# Leanote
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
Leanote, note just a notebook!
|
||||
Leanote, not just a notebook!
|
||||

|
||||
|
||||
**Some Features**
|
||||
|
||||
@@ -20,12 +22,18 @@ To be honest, our inspiration comes from Evernote. We use Evernote to manage our
|
||||
|
||||
## 3. How to install leanote
|
||||
|
||||
More information about how to install leanote please see:
|
||||
* [leanote binary distribution installation tutorial](https://github.com/leanote/leanote/wiki/leanote-binary-distribution-installation-tutorial)
|
||||
* [leanote develop distribution installation tutorial](https://github.com/leanote/leanote/wiki/leanote-develop-distribution-installation-tutorial)
|
||||
|
||||
### 3.1. Download leanote
|
||||
|
||||
Leanote V1.0-beta has been released. Binaries:
|
||||
Leanote V1.0.2-beta has been released. Binaries:
|
||||
|
||||
* Linux: [leanote-linux-x86_64.v1.0-beta.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-linux-x86_64.v1.0-beta.bin.tar.gz)
|
||||
* MacOS X: [leanote-mac-x86_64.v1.0-beta.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-mac-x86_64.v1.0-beta.bin.tar.gz)
|
||||
* Linux: [leanote-linux-x86_64.v1.0-beta.2.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-linux-x86_64.v1.0-beta.2.bin.tar.gz)
|
||||
* MacOS X: [leanote-mac-x86_64.v1.0-beta.2.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-mac-x86_64.v1.0-beta.bin.2.tar.gz)
|
||||
|
||||
Or you can clone [Leanote bin repository](https://github.com/leanote/leanote-bin) (Recommend)
|
||||
|
||||
### 3.2. Install MongoDB
|
||||
|
||||
@@ -89,106 +97,17 @@ this project. Your help is much appreciated.
|
||||
|
||||
Please fork this repository and contribute back using [pull requests](https://github.com/leanote/leanote/pulls).
|
||||
|
||||
## Docs
|
||||
* [leanote binary distribution installation tutorial](https://github.com/leanote/leanote/wiki/leanote-binary-distribution-installation-tutorial)
|
||||
* [leanote develop distribution installation tutorial](https://github.com/leanote/leanote/wiki/leanote-develop-distribution-installation-tutorial)
|
||||
* [leanote blog theme api](https://github.com/leanote/leanote/wiki/leanote-blog-theme-api_en)
|
||||
|
||||
## Discussion
|
||||
* [leanote bbs](http://bbs.leanote.com)
|
||||
* [leanote google group](https://groups.google.com/forum/#!forum/leanote)
|
||||
* QQ Group: 158716820
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
[中文](README_zh.md)
|
||||
|
||||
## 1. 介绍
|
||||
|
||||
Leanote, 不只是笔记!
|
||||
|
||||
**特性**
|
||||
|
||||
* 知识管理: 通过leanote来管理知识, leanote有易操作的界面, 包含两款编辑器tinymce和markdown. 在leanote, 你可以尽情享受写作.
|
||||
* 分享: 你也可以通过分享知识给好友, 让好友拥有你的知识.
|
||||
* 协作: 在分享的同时也可以与好友一起协作知识.
|
||||
* 博客: leanote也可以作为你的博客, 将知识公开成博客, 让leanote把你的知识传播的更远!
|
||||
|
||||
## 2. 为什么我们要创建leanote?
|
||||
说实话, 我们曾是evernote的忠实粉丝, 但是我们也发现evernote的不足:
|
||||
* evernote的编辑器不能满足我们的需求, 不能贴代码(格式会乱掉, 作为程序员, 代码是我们的基本需求啊), 图片不能缩放.
|
||||
* 我们是markdown的爱好者, 可是evernote竟然没有.
|
||||
* 我们也想将知识公开, 所以我们有自己的博客, 如wordpress, 但为什么这两者不能合二为一呢?
|
||||
* 还有...
|
||||
|
||||
## 3.安装leanote
|
||||
leanote是一款私有云笔记, 你可以下载它安装在自己的服务器上, 当然也可以在 http://leanote.com 上注册.
|
||||
|
||||
这里详细整理了leanote二进版和leanote开发版的安装教程, 请移步至:
|
||||
* [leanote二进制详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||
* [leanote开发版详细安装教程](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||
|
||||
### 3.1. 下载leanote
|
||||
|
||||
Leanote V1.0-beta 已发布, 二进制文件(暂时没有windows版的):
|
||||
|
||||
* Linux: [leanote-linux-x86_64.v1.0-beta.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-linux-x86_64.v1.0-beta.bin.tar.gz)
|
||||
* MacOS X: [leanote-mac-x86_64.v1.0-beta.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-mac-x86_64.v1.0-beta.bin.tar.gz)
|
||||
|
||||
### 3.2. 安装 MongodbDB
|
||||
|
||||
Leanote是由golang(使用[revel](https://revel.github.io/)框架 和 [MongoDB](https://www.mongodb.org)数据库), 你需要先安装Mongodb.
|
||||
|
||||
安装MongodbDB, 导入数据更多细节请查看: [wiki](https://github.com/leanote/leanote/wiki/Install-Mongodb)
|
||||
|
||||
### 3.3. 导入初始数据
|
||||
|
||||
MongodbDB初始数据在 `[PATH_TO_LEANOTE]/mongodb_backup/leanote_install_data`
|
||||
|
||||
```
|
||||
$> mongorestore -h localhost -d leanote --directoryperdb PATH_TO_LEANOTE/mongodb_backup/leanote_install_data
|
||||
```
|
||||
|
||||
初始数据包含两个用户:
|
||||
|
||||
```
|
||||
user2 username: admin, password: abc123 (管理员, 重要!)
|
||||
user3 username: demo@leanote.com, password: demo@leanote.com (为体验使用)
|
||||
```
|
||||
|
||||
### 3.4. 配置
|
||||
|
||||
修改 `[PATH_TO_LEANOTE]/conf/app.conf`. 有以下选项:
|
||||
|
||||
``mongodb`` **必须配置!**
|
||||
|
||||
```Shell
|
||||
db.host=localhost
|
||||
db.port=27017
|
||||
db.dbname=leanote
|
||||
db.username=
|
||||
db.password=
|
||||
```
|
||||
|
||||
``app.secret`` **重要**
|
||||
请随意修改一个, app的密钥, 不能使用默认的, 不然会有安全问题
|
||||
|
||||
更多配置请查看 `app/app.conf` 和 [revel 手册](https://revel.github.io/)
|
||||
|
||||
### 3.5. 运行leanote
|
||||
|
||||
```
|
||||
$> cd PATH_TO_LEANOTE/bin
|
||||
$> sudo sh run.sh
|
||||
```
|
||||
|
||||
## 4. 如何对leanote进行二次开发
|
||||
|
||||
请查看 [How-to-develop-leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-%E5%A6%82%E4%BD%95%E5%BC%80%E5%8F%91leanote)
|
||||
|
||||
## 5. 贡献者
|
||||
多谢 [贡献者](https://github.com/leanote/leanote/graphs/contributors) 的贡献, leanote因有你们而更完美!
|
||||
|
||||
## 6. 加入我们
|
||||
|
||||
欢迎提交[pull requests](https://github.com/leanote/leanote/pulls) 到leanote.
|
||||
|
||||
leanote还有很多问题, 如果你喜欢它, 欢迎加入我们一起完善leanote.
|
||||
|
||||
## 讨论
|
||||
* [leanote 社区](http://bbs.leanote.com)
|
||||
* QQ群: 158716820
|
||||
* [leanote google group](https://groups.google.com/forum/#!forum/leanote)
|
||||
|
||||
113
README_zh.md
Normal file
113
README_zh.md
Normal file
@@ -0,0 +1,113 @@
|
||||
|
||||
# Leanote<74><65>Ʒ
|
||||
|
||||
## 1. <20><><EFBFBD><EFBFBD>
|
||||
|
||||
Leanote, <20><>ֻ<EFBFBD>DZʼ<C7B1>!
|
||||

|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>**
|
||||
|
||||
* ֪ʶ<D6AA><CAB6><EFBFBD><EFBFBD>: ͨ<><CDA8>leanote<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ʶ, leanote<74><65><EFBFBD>ײ<EFBFBD><D7B2><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>༭<EFBFBD><E0BCAD>tinymce<63><65>markdown. <20><>leanote, <20><><EFBFBD><EFBFBD><EFBFBD>Ծ<EFBFBD><D4BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4>.
|
||||
* <20><><EFBFBD><EFBFBD>: <20><>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ʶ<D6AA><CAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20>ú<EFBFBD><C3BA><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ʶ.
|
||||
* Э<><D0AD>: <20>ڷ<EFBFBD><DAB7><EFBFBD><EFBFBD><EFBFBD>ͬʱҲ<CAB1><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>Э<EFBFBD><D0AD>֪ʶ.
|
||||
* <20><><EFBFBD><EFBFBD>: leanoteҲ<65><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>, <20><>֪ʶ<D6AA><CAB6><EFBFBD><EFBFBD><EFBFBD>ɲ<EFBFBD><C9B2><EFBFBD>, <20><>leanote<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪ʶ<D6AA><CAB6><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>Զ!
|
||||
|
||||
## 2. Ϊʲô<CAB2><C3B4><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>leanote?
|
||||
˵ʵ<EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>evernote<74><65><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>˿, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD>evernote<74>IJ<EFBFBD><C4B2><EFBFBD>:
|
||||
* evernote<74>ı༭<C4B1><E0BCAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><>ʽ<EFBFBD><CABD><EFBFBD>ҵ<EFBFBD>, <20><>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>Ա, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵĻ<C7B5><C4BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>), ͼƬ<CDBC><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>markdown<77>İ<EFBFBD><C4B0><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD>evernote<74><65>Ȼû<C8BB><C3BB>.
|
||||
* <20><><EFBFBD><EFBFBD>Ҳ<EFBFBD>뽫֪ʶ<D6AA><CAB6><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC>IJ<EFBFBD><C4B2><EFBFBD>, <20><>wordpress, <20><>Ϊʲô<CAB2><C3B4><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><DFB2>ܺ϶<DCBA>Ϊһ<CEAA><D2BB>?
|
||||
* <20><><EFBFBD><EFBFBD>...
|
||||
|
||||
## 3.<2E><>װleanote
|
||||
leanote<EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>˽<EFBFBD><EFBFBD><EFBFBD>Ʊʼ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD>Լ<EFBFBD><D4BC>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><>ȻҲ<C8BB><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> http://leanote.com <20><>ע<EFBFBD><D7A2>.
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>leanote<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>leanote<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>İ<EFBFBD>װ<EFBFBD>̳<EFBFBD>, <20><><EFBFBD>Ʋ<EFBFBD><C6B2><EFBFBD>:
|
||||
* [leanote<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>װ<EFBFBD>̳<EFBFBD>](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||
* [leanote<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>װ<EFBFBD>̳<EFBFBD>](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||
|
||||
### 3.1. <20><><EFBFBD><EFBFBD>leanote
|
||||
|
||||
Leanote V1.0-beta.2 <20>ѷ<EFBFBD><D1B7><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>(<28><>ʱû<CAB1><C3BB>windows<77><73><EFBFBD><EFBFBD>):
|
||||
|
||||
* Linux: [leanote-linux-x86_64.v1.0-beta.2.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-linux-x86_64.v1.0-beta.2.bin.tar.gz)
|
||||
* MacOS X: [leanote-mac-x86_64.v1.0-beta.2.bin.tar.gz](https://github.com/leanote/leanote/releases/download/1.0-beta/leanote-mac-x86_64.v1.0-beta.2.bin.tar.gz)
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӽ<EFBFBD><EFBFBD><EFBFBD>[Leanote bin repository](https://github.com/leanote/leanote-bin) (<28>Ƽ<EFBFBD>, <20><>ΪΪ<CEAA><CEAA><EFBFBD>°汾)
|
||||
|
||||
### 3.2. <20><>װ MongodbDB
|
||||
|
||||
Leanote<EFBFBD><EFBFBD><EFBFBD><EFBFBD>golang(ʹ<><CAB9>[revel](https://revel.github.io/)<29><><EFBFBD><EFBFBD> <20><> [MongoDB](https://www.mongodb.org)<29><><EFBFBD>ݿ<EFBFBD>), <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD>Ȱ<EFBFBD>װMongodb.
|
||||
|
||||
<EFBFBD><EFBFBD>װMongodbDB, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݸ<EFBFBD><DDB8><EFBFBD>ϸ<EFBFBD><CFB8><EFBFBD><EFBFBD><EFBFBD>鿴: [wiki](https://github.com/leanote/leanote/wiki/Install-Mongodb)
|
||||
|
||||
### 3.3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
||||
|
||||
MongodbDB<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> `[PATH_TO_LEANOTE]/mongodb_backup/leanote_install_data`
|
||||
|
||||
```
|
||||
$> mongorestore -h localhost -d leanote --directoryperdb PATH_TO_LEANOTE/mongodb_backup/leanote_install_data
|
||||
```
|
||||
|
||||
<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD>:
|
||||
|
||||
```
|
||||
user2 username: admin, password: abc123 (<28><><EFBFBD><EFBFBD>Ա, <20><>Ҫ!)
|
||||
user3 username: demo@leanote.com, password: demo@leanote.com (Ϊ<><CEAA><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>)
|
||||
```
|
||||
|
||||
### 3.4. <20><><EFBFBD><EFBFBD>
|
||||
|
||||
<EFBFBD><EFBFBD> `[PATH_TO_LEANOTE]/conf/app.conf`. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>:
|
||||
|
||||
``mongodb`` **<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!**
|
||||
|
||||
```Shell
|
||||
db.host=localhost
|
||||
db.port=27017
|
||||
db.dbname=leanote
|
||||
db.username=
|
||||
db.password=
|
||||
```
|
||||
|
||||
``app.secret`` **<2A><>Ҫ**
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD>, app<70><70><EFBFBD><EFBFBD>Կ, <20><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>Ĭ<EFBFBD>ϵ<EFBFBD>, <20><>Ȼ<EFBFBD><C8BB><EFBFBD>а<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>鿴 `app/app.conf` <20><> [revel <20>ֲ<EFBFBD>](https://revel.github.io/)
|
||||
|
||||
### 3.5. <20><><EFBFBD><EFBFBD>leanote
|
||||
|
||||
```
|
||||
$> cd PATH_TO_LEANOTE/bin
|
||||
$> sudo sh run.sh
|
||||
```
|
||||
|
||||
## 4. <20><><EFBFBD>ζ<EFBFBD>leanote<74><65><EFBFBD>ж<EFBFBD><D0B6>ο<EFBFBD><CEBF><EFBFBD>
|
||||
|
||||
<EFBFBD><EFBFBD><EFBFBD>鿴 [How-to-develop-leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-%E5%A6%82%E4%BD%95%E5%BC%80%E5%8F%91leanote)
|
||||
|
||||
## 5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
<EFBFBD><EFBFBD>л [<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>](https://github.com/leanote/leanote/graphs/contributors) <20>Ĺ<EFBFBD><C4B9><EFBFBD>, leanote<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><C7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!
|
||||
|
||||
## 6. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
<EFBFBD><EFBFBD>ӭ<EFBFBD>ύ[pull requests](https://github.com/leanote/leanote/pulls) <20><>leanote.
|
||||
|
||||
leanote<EFBFBD><EFBFBD><EFBFBD>кܶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD>, <20><>ӭ<EFBFBD><D3AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>leanote.
|
||||
|
||||
## <20><><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
|
||||
* [leanote<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ư<EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>װ<EFBFBD>̳<EFBFBD>](https://github.com/leanote/leanote/wiki/leanote%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||
* [leanote<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>װ<EFBFBD>̳<EFBFBD>](https://github.com/leanote/leanote/wiki/leanote%E5%BC%80%E5%8F%91%E7%89%88%E8%AF%A6%E7%BB%86%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B)
|
||||
* [Leanote source leanoteԴ<65>뵼<EFBFBD><EBB5BC>](https://github.com/leanote/leanote/wiki/Leanote-source-leanoteԴ<65>뵼<EFBFBD><EBB5BC>)
|
||||
* [leanote blog theme api(<28><><EFBFBD>İ<EFBFBD>)](https://github.com/leanote/leanote/wiki/leanote-blog-theme-api)
|
||||
* [How to develop leanote <20><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD>leanote](https://github.com/leanote/leanote/wiki/How-to-develop-leanote-<2D><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD>leanote)
|
||||
|
||||
|
||||
## <20><><EFBFBD><EFBFBD>
|
||||
* [leanote <20><><EFBFBD><EFBFBD>](http://bbs.leanote.com)
|
||||
* QQȺ: 158716820
|
||||
* [leanote google group](https://groups.google.com/forum/#!forum/leanote)
|
||||
|
||||
----------------------------------------------------------------
|
||||
[English](README.md)
|
||||
@@ -62,7 +62,7 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
||||
maxFileSize = 1000
|
||||
}
|
||||
if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
|
||||
resultMsg = fmt.Sprintf("附件大于%vM", maxFileSize)
|
||||
resultMsg = fmt.Sprintf("The file's size is bigger than %vM", maxFileSize)
|
||||
return re
|
||||
}
|
||||
|
||||
@@ -100,11 +100,15 @@ func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
||||
id := bson.NewObjectId();
|
||||
fileInfo.AttachId = id
|
||||
fileId = id.Hex()
|
||||
Ok = attachService.AddAttach(fileInfo)
|
||||
Ok, resultMsg = attachService.AddAttach(fileInfo)
|
||||
if resultMsg != "" {
|
||||
resultMsg = c.Message(resultMsg)
|
||||
}
|
||||
|
||||
fileInfo.Path = ""; // 不要返回
|
||||
resultMsg = "success"
|
||||
|
||||
if Ok {
|
||||
resultMsg = "success"
|
||||
}
|
||||
return re
|
||||
}
|
||||
|
||||
@@ -125,9 +129,18 @@ func (c Attach) GetAttachs(noteId string) revel.Result {
|
||||
|
||||
// 下载附件
|
||||
// 权限判断
|
||||
func (c Attach) Download(attachId string) revel.Result {
|
||||
attach := attachService.GetAttach(attachId, c.GetUserId()); // 得到路径
|
||||
func (c Attach) Download(attachId, token string) revel.Result {
|
||||
if c.GetUserId() == "" && token == "" {
|
||||
return c.RenderText("你需要从分享页面下载附件!")
|
||||
}
|
||||
|
||||
sessionId := c.Session.Id()
|
||||
attach := attachService.GetAttach(attachId, c.GetUserId(), token, sessionId); // 得到路径
|
||||
path := attach.Path
|
||||
|
||||
if token != "" && attach.Path == "" {
|
||||
return c.RenderText("该下载链接已经失效,请重新刷新原分享笔记页面下载")
|
||||
}
|
||||
if path == "" {
|
||||
return c.RenderText("")
|
||||
}
|
||||
@@ -212,4 +225,4 @@ func (c Attach) DownloadAll(noteId string) revel.Result {
|
||||
// file, _ := os.Open(dir + "/" + filename)
|
||||
// fw.Seek(0, 0)
|
||||
return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/leanote/leanote/app/info"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
// "strconv"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 用户登录/注销/找回密码
|
||||
@@ -40,7 +41,7 @@ func (c Auth) Login(email, from string) revel.Result {
|
||||
func (c Auth) doLogin(email, pwd string) revel.Result {
|
||||
sessionId := c.Session.Id()
|
||||
var msg = ""
|
||||
|
||||
fmt.Println(sessionId)
|
||||
userInfo := authService.Login(email, pwd)
|
||||
if userInfo.Email != "" {
|
||||
c.SetSession(userInfo)
|
||||
@@ -55,8 +56,8 @@ func (c Auth) doLogin(email, pwd string) revel.Result {
|
||||
}
|
||||
func (c Auth) DoLogin(email, pwd string, captcha string) revel.Result {
|
||||
sessionId := c.Session.Id()
|
||||
var msg = ""
|
||||
|
||||
var msg = ""
|
||||
// > 5次需要验证码, 直到登录成功
|
||||
if sessionService.LoginTimesIsOver(sessionId) && sessionService.GetCaptcha(sessionId) != captcha {
|
||||
msg = "captchaError"
|
||||
@@ -91,18 +92,19 @@ func (c Auth) Demo() revel.Result {
|
||||
|
||||
//--------
|
||||
// 注册
|
||||
func (c Auth) Register(from string) revel.Result {
|
||||
func (c Auth) Register(from, iu string) revel.Result {
|
||||
if !configService.IsOpenRegister() {
|
||||
return c.Redirect("/index")
|
||||
}
|
||||
c.SetLocale()
|
||||
c.RenderArgs["from"] = from
|
||||
c.RenderArgs["iu"] = iu
|
||||
|
||||
c.RenderArgs["title"] = c.Message("register")
|
||||
c.RenderArgs["subTitle"] = c.Message("register")
|
||||
return c.RenderTemplate("home/register.html")
|
||||
}
|
||||
func (c Auth) DoRegister(email, pwd string) revel.Result {
|
||||
func (c Auth) DoRegister(email, pwd, iu string) revel.Result {
|
||||
if !configService.IsOpenRegister() {
|
||||
return c.Redirect("/index")
|
||||
}
|
||||
@@ -117,7 +119,7 @@ func (c Auth) DoRegister(email, pwd string) revel.Result {
|
||||
}
|
||||
|
||||
// 注册
|
||||
re.Ok, re.Msg = authService.Register(email, pwd)
|
||||
re.Ok, re.Msg = authService.Register(email, pwd, iu)
|
||||
|
||||
// 注册成功, 则立即登录之
|
||||
if re.Ok {
|
||||
|
||||
@@ -193,12 +193,13 @@ func (c BaseController) SetLocale() string {
|
||||
}
|
||||
|
||||
// 设置userInfo
|
||||
func (c BaseController) SetUserInfo() {
|
||||
func (c BaseController) SetUserInfo() info.User {
|
||||
userInfo := c.GetUserInfo()
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
if(userInfo.Username == configService.GetAdminUsername()) {
|
||||
c.RenderArgs["isAdmin"] = true
|
||||
}
|
||||
return userInfo
|
||||
}
|
||||
|
||||
// life
|
||||
@@ -224,6 +225,7 @@ func (c BaseController) RenderTemplateStr(templatePath string) string {
|
||||
// 为了msg
|
||||
// msg-v1-v2-v3
|
||||
func (c BaseController) RenderRe(re info.Re) revel.Result {
|
||||
oldMsg := re.Msg
|
||||
if re.Msg != "" {
|
||||
if(strings.Contains(re.Msg, "-")) {
|
||||
msgAndValues := strings.Split(re.Msg, "-")
|
||||
@@ -241,5 +243,8 @@ func (c BaseController) RenderRe(re info.Re) revel.Result {
|
||||
re.Msg = c.Message(re.Msg)
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(re.Msg, "???") {
|
||||
re.Msg = oldMsg
|
||||
}
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ func (c Blog) render(templateName string, themePath string) revel.Result {
|
||||
isPreview = true
|
||||
themePath = themePath2.(string)
|
||||
c.setPreviewUrl()
|
||||
|
||||
// 因为common的themeInfo是从UserBlog.ThemeId来取的, 所以这里要fugai下
|
||||
c.RenderArgs["themeInfo"] = c.RenderArgs["themeInfoPreview"];
|
||||
}
|
||||
return blog.RenderTemplate(templateName, c.RenderArgs, revel.BasePath+"/"+themePath, isPreview)
|
||||
}
|
||||
@@ -102,19 +105,23 @@ func (c Blog) setPreviewUrl() {
|
||||
var indexUrl, postUrl, searchUrl, cateUrl, singleUrl, tagsUrl, archiveUrl string
|
||||
|
||||
userId := c.GetUserId()
|
||||
userIdOrEmail := userId
|
||||
username := c.GetUsername()
|
||||
if username != "" {
|
||||
userIdOrEmail = username
|
||||
}
|
||||
themeId := c.Session["themeId"]
|
||||
theme := themeService.GetTheme(userId, themeId)
|
||||
|
||||
siteUrl := configService.GetSiteUrl()
|
||||
blogUrl := siteUrl + "/preview" // blog.leanote.com
|
||||
userIdOrEmail := userId
|
||||
|
||||
indexUrl = blogUrl + "/" + userIdOrEmail
|
||||
cateUrl = blogUrl + "/cate" // /notebookId
|
||||
cateUrl = blogUrl + "/cate/" + userIdOrEmail // /notebookId
|
||||
|
||||
postUrl = blogUrl + "/post" // /xxxxx
|
||||
postUrl = blogUrl + "/post/" + userIdOrEmail // /xxxxx
|
||||
searchUrl = blogUrl + "/search/" + userIdOrEmail // blog.leanote.com/search/userId
|
||||
singleUrl = blogUrl + "/single" // blog.leanote.com/single/singleId
|
||||
singleUrl = blogUrl + "/single/" + userIdOrEmail // blog.leanote.com/single/singleId
|
||||
archiveUrl = blogUrl + "/archives/" + userIdOrEmail // blog.leanote.com/archive/userId
|
||||
tagsUrl = blogUrl + "/tags/" + userIdOrEmail // blog.leanote.com/archive/userId
|
||||
|
||||
@@ -533,21 +540,27 @@ func (c Blog) Index(userIdOrEmail string) (re revel.Result) {
|
||||
}
|
||||
userId, userInfo := c.userIdOrEmail(hasDomain, userBlog, userIdOrEmail)
|
||||
var ok = false
|
||||
fmt.Println("before test...");
|
||||
if ok, userBlog = c.blogCommon(userId, userBlog, userInfo); !ok {
|
||||
fmt.Println("404 occur");
|
||||
return c.e404(userBlog.ThemePath) // 404 TODO 使用用户的404
|
||||
}
|
||||
|
||||
fmt.Println("after test0...");
|
||||
// 分页的话, 需要分页信息, totalPage, curPage
|
||||
page := c.GetPage()
|
||||
|
||||
pageInfo, blogs := blogService.ListBlogs(userId, "", page, userBlog.PerPageSize, userBlog.SortField, userBlog.IsAsc)
|
||||
|
||||
blogs2 := blogService.FixBlogs(blogs)
|
||||
|
||||
c.RenderArgs["posts"] = blogs2
|
||||
|
||||
c.setPaging(pageInfo)
|
||||
c.RenderArgs["pagingBaseUrl"] = c.RenderArgs["indexUrl"]
|
||||
|
||||
c.RenderArgs["curIsIndex"] = true
|
||||
|
||||
|
||||
|
||||
return c.render("index.html", userBlog.ThemePath)
|
||||
}
|
||||
|
||||
@@ -577,7 +590,8 @@ func (c Blog) Post(userIdOrEmail, noteId string) (re revel.Result) {
|
||||
return c.e404(userBlog.ThemePath) // 404 TODO 使用用户的404
|
||||
}
|
||||
|
||||
c.RenderArgs["post"] = blogService.FixBlog(blogInfo)
|
||||
post := blogService.FixBlog(blogInfo)
|
||||
c.RenderArgs["post"] = post
|
||||
// c.RenderArgs["userInfo"] = userInfo
|
||||
c.RenderArgs["curIsPost"] = true
|
||||
|
||||
@@ -593,7 +607,7 @@ func (c Blog) Post(userIdOrEmail, noteId string) (re revel.Result) {
|
||||
baseTime = blogInfo.Title
|
||||
}
|
||||
|
||||
prePost, nextPost := blogService.PreNextBlog(userId, userBlog.SortField, userBlog.IsAsc, baseTime)
|
||||
prePost, nextPost := blogService.PreNextBlog(userId, userBlog.SortField, userBlog.IsAsc, post.NoteId, baseTime)
|
||||
if prePost.NoteId != "" {
|
||||
c.RenderArgs["prePost"] = prePost
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/leanote/leanote/app/info"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"fmt"
|
||||
"strconv"
|
||||
// "strconv"
|
||||
"strings"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 首页
|
||||
@@ -85,7 +85,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
var fileUrlPath = ""
|
||||
var fileId = ""
|
||||
var resultCode = 0 // 1表示正常
|
||||
var resultMsg = "内部错误" // 错误信息
|
||||
var resultMsg = "error" // 错误信息
|
||||
var Ok = false
|
||||
|
||||
defer func() {
|
||||
@@ -120,7 +120,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
} else {
|
||||
_, ext = SplitFilename(filename)
|
||||
if(ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg") {
|
||||
resultMsg = "不是图片"
|
||||
resultMsg = "Please upload image"
|
||||
return re
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
// > 2M?
|
||||
if(float64(len(data)) > maxFileSize * float64(1024*1024)) {
|
||||
resultCode = 0
|
||||
resultMsg = fmt.Sprintf("图片大于%vM", maxFileSize)
|
||||
resultMsg = fmt.Sprintf("The file Size is bigger than %vM", maxFileSize)
|
||||
return re
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
filesize := GetFilesize(toPathGif)
|
||||
fileUrlPath += "/" + filename
|
||||
resultCode = 1
|
||||
resultMsg = "上传成功!"
|
||||
resultMsg = "Upload Success!"
|
||||
|
||||
// File
|
||||
fileInfo := info.File{Name: filename,
|
||||
@@ -178,7 +178,8 @@ func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||
fileId = "public/upload/" + c.GetUserId() + "/images/logo/" + filename
|
||||
}
|
||||
|
||||
Ok = fileService.AddImage(fileInfo, albumId, c.GetUserId())
|
||||
Ok, resultMsg = fileService.AddImage(fileInfo, albumId, c.GetUserId(), from == "" || from == "pasteImage")
|
||||
resultMsg = c.Message(resultMsg)
|
||||
|
||||
fileInfo.Path = ""; // 不要返回
|
||||
re.Item = fileInfo
|
||||
@@ -203,61 +204,13 @@ func (c File) DeleteImage(fileId string) revel.Result {
|
||||
re.Ok, re.Msg = fileService.DeleteImage(c.GetUserId(), fileId)
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
// update image uploader to leaui image,
|
||||
// scan all user's images and insert into db
|
||||
func (c File) UpgradeLeauiImage() revel.Result {
|
||||
re := info.NewRe()
|
||||
|
||||
if ok, _ := revel.Config.Bool("upgradeLeauiImage"); !ok {
|
||||
re.Msg = "Not allowed"
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
uploadPath := revel.BasePath + "/public/upload";
|
||||
userIds := ListDir(uploadPath)
|
||||
if userIds == nil {
|
||||
re.Msg = "no user"
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
msg := "";
|
||||
|
||||
for _, userId := range userIds {
|
||||
dirPath := uploadPath + "/" + userId + "/images"
|
||||
images := ListDir(dirPath)
|
||||
if images == nil {
|
||||
msg += userId + " no images "
|
||||
continue;
|
||||
}
|
||||
|
||||
hadImages := fileService.GetAllImageNamesMap(userId)
|
||||
|
||||
i := 0
|
||||
for _, filename := range images {
|
||||
if _, ok := hadImages[filename]; !ok {
|
||||
fileUrlPath := "/upload/" + userId + "/images/" + filename
|
||||
fileInfo := info.File{Name: filename,
|
||||
Title: filename,
|
||||
Path: fileUrlPath,
|
||||
Size: GetFilesize(dirPath + "/" + filename)}
|
||||
fileService.AddImage(fileInfo, "", userId)
|
||||
i++
|
||||
}
|
||||
}
|
||||
msg += userId + ": " + strconv.Itoa(len(images)) + " -- " + strconv.Itoa(i) + " images "
|
||||
}
|
||||
|
||||
re.Msg = msg
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
//-----------
|
||||
|
||||
// 输出image
|
||||
// 权限判断
|
||||
func (c File) OutputImage(noteId, fileId string) revel.Result {
|
||||
path := fileService.GetFile(c.GetUserId(), fileId); // 得到路径
|
||||
func (c File) OutputImage(noteId, fileId , token string) revel.Result {
|
||||
sessionId := c.Session.Id()
|
||||
path := fileService.GetFile(c.GetUserId(), fileId, sessionId, token); // 得到路径
|
||||
if path == "" {
|
||||
return c.RenderText("")
|
||||
}
|
||||
@@ -267,15 +220,15 @@ func (c File) OutputImage(noteId, fileId string) revel.Result {
|
||||
}
|
||||
|
||||
// 协作时复制图片到owner
|
||||
// 需要计算对方大小
|
||||
func (c File) CopyImage(userId, fileId, toUserId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
|
||||
re.Ok, re.Id = fileService.CopyImage(userId, fileId, toUserId)
|
||||
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
// 复制外网的图片, 成公共图片 放在/upload下
|
||||
// 都要好好的计算大小
|
||||
func (c File) CopyHttpImage(src string) revel.Result {
|
||||
re := info.NewRe()
|
||||
fileUrlPath := "upload/" + c.GetUserId() + "/images"
|
||||
@@ -302,29 +255,7 @@ func (c File) CopyHttpImage(src string) revel.Result {
|
||||
|
||||
re.Id = id.Hex()
|
||||
re.Item = fileInfo.Path
|
||||
re.Ok = fileService.AddImage(fileInfo, "", c.GetUserId())
|
||||
re.Ok, re.Msg = fileService.AddImage(fileInfo, "", c.GetUserId(), true)
|
||||
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
//------------
|
||||
// 过时 已弃用!
|
||||
func (c File) UploadImage(renderHtml string) revel.Result {
|
||||
if renderHtml == "" {
|
||||
renderHtml = "file/image.html"
|
||||
}
|
||||
|
||||
re := c.uploadImage("", "");
|
||||
|
||||
c.RenderArgs["fileUrlPath"] = configService.GetSiteUrl() + re.Id
|
||||
c.RenderArgs["resultCode"] = re.Code
|
||||
c.RenderArgs["resultMsg"] = re.Msg
|
||||
|
||||
return c.RenderTemplate(renderHtml)
|
||||
}
|
||||
|
||||
// 已弃用
|
||||
func (c File) UploadImageJson(from, noteId string) revel.Result {
|
||||
re := c.uploadImage(from, "");
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
}
|
||||
@@ -22,9 +22,8 @@ type Note struct {
|
||||
// 笔记首页, 判断是否已登录
|
||||
// 已登录, 得到用户基本信息(notebook, shareNotebook), 跳转到index.html中
|
||||
// 否则, 转向登录页面
|
||||
func (c Note) Index() revel.Result {
|
||||
func (c Note) Index(noteId string) revel.Result {
|
||||
c.SetLocale()
|
||||
|
||||
userInfo := c.GetUserInfo()
|
||||
|
||||
userId := userInfo.UserId.Hex()
|
||||
@@ -35,7 +34,7 @@ func (c Note) Index() revel.Result {
|
||||
}
|
||||
|
||||
c.RenderArgs["openRegister"] = configService.IsOpenRegister()
|
||||
|
||||
|
||||
// 已登录了, 那么得到所有信息
|
||||
notebooks := notebookService.GetNotebooks(userId)
|
||||
shareNotebooks, sharedUserInfos := shareService.GetShareNotebooks(userId)
|
||||
@@ -43,22 +42,78 @@ func (c Note) Index() revel.Result {
|
||||
// 还需要按时间排序(DESC)得到notes
|
||||
notes := []info.Note{}
|
||||
noteContent := info.NoteContent{}
|
||||
|
||||
if len(notebooks) > 0 {
|
||||
// _, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), pageSize, defaultSortField, false, false);
|
||||
// 变成最新
|
||||
_, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false);
|
||||
if len(notes) > 0 {
|
||||
noteContent = noteService.GetNoteContent(notes[0].NoteId.Hex(), userId)
|
||||
// noteId是否存在
|
||||
// 是否传入了正确的noteId
|
||||
hasRightNoteId := false
|
||||
if IsObjectId(noteId) {
|
||||
note := noteService.GetNoteById(noteId)
|
||||
var noteOwner = note.UserId.Hex()
|
||||
noteContent = noteService.GetNoteContent(noteId, noteOwner)
|
||||
|
||||
if note.NoteId != "" {
|
||||
hasRightNoteId = true
|
||||
c.RenderArgs["curNoteId"] = noteId
|
||||
c.RenderArgs["curNotebookId"] = note.NotebookId.Hex()
|
||||
|
||||
// 打开的是共享的笔记, 那么判断是否是共享给我的默认笔记
|
||||
if noteOwner != c.GetUserId() {
|
||||
if shareService.HasReadPerm(noteOwner, c.GetUserId(), noteId) {
|
||||
// 不要获取notebook下的笔记
|
||||
// 在前端下发请求
|
||||
c.RenderArgs["curSharedNoteNotebookId"] = note.NotebookId.Hex()
|
||||
c.RenderArgs["curSharedUserId"] = noteOwner;
|
||||
// 没有读写权限
|
||||
} else {
|
||||
hasRightNoteId = false
|
||||
}
|
||||
} else {
|
||||
_, notes = noteService.ListNotes(c.GetUserId(), note.NotebookId.Hex(), false, c.GetPage(), 50, defaultSortField, false, false);
|
||||
|
||||
// 如果指定了某笔记, 则该笔记放在首位
|
||||
lenNotes := len(notes)
|
||||
if lenNotes > 1 {
|
||||
notes2 := make([]info.Note, len(notes))
|
||||
notes2[0] = note
|
||||
i := 1
|
||||
for _, note := range notes {
|
||||
if note.NoteId.Hex() != noteId {
|
||||
if i == lenNotes { // 防止越界
|
||||
break;
|
||||
}
|
||||
notes2[i] = note
|
||||
i++
|
||||
}
|
||||
}
|
||||
notes = notes2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 得到最近的笔记
|
||||
_, latestNotes := noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false);
|
||||
c.RenderArgs["latestNotes"] = latestNotes
|
||||
}
|
||||
|
||||
// 没有传入笔记
|
||||
// 那么得到最新笔记
|
||||
if !hasRightNoteId {
|
||||
_, notes = noteService.ListNotes(c.GetUserId(), "", false, c.GetPage(), 50, defaultSortField, false, false);
|
||||
if len(notes) > 0 {
|
||||
noteContent = noteService.GetNoteContent(notes[0].NoteId.Hex(), userId)
|
||||
c.RenderArgs["curNoteId"] = notes[0].NoteId.Hex()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 当然, 还需要得到第一个notes的content
|
||||
//...
|
||||
Log(configService.GetAdminUsername())
|
||||
c.RenderArgs["isAdmin"] = configService.GetAdminUsername() == userInfo.Username
|
||||
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
c.RenderArgs["notebooks"] = notebooks
|
||||
c.RenderArgs["shareNotebooks"] = shareNotebooks
|
||||
c.RenderArgs["shareNotebooks"] = shareNotebooks // note信息在notes列表中
|
||||
c.RenderArgs["sharedUserInfos"] = sharedUserInfos
|
||||
|
||||
c.RenderArgs["notes"] = notes
|
||||
@@ -69,6 +124,9 @@ func (c Note) Index() revel.Result {
|
||||
|
||||
c.RenderArgs["globalConfigs"] = configService.GetGlobalConfigForUser()
|
||||
|
||||
|
||||
// return c.RenderTemplate("note/note.html")
|
||||
|
||||
if isDev, _ := revel.Config.Bool("mode.dev"); isDev {
|
||||
return c.RenderTemplate("note/note-dev.html")
|
||||
} else {
|
||||
|
||||
@@ -33,6 +33,8 @@ func (c Preview) getPreviewThemeAbsolutePath(themeId string) bool {
|
||||
theme := themeService.GetTheme(c.GetUserId(), themeId)
|
||||
|
||||
c.RenderArgs["isPreview"] = true
|
||||
c.RenderArgs["themeId"] = themeId
|
||||
c.RenderArgs["themeInfoPreview"] = theme.Info
|
||||
c.RenderArgs["themePath"] = theme.Path
|
||||
if theme.Path == "" {
|
||||
return false
|
||||
|
||||
@@ -9,12 +9,15 @@ import (
|
||||
// "github.com/leanote/leanote/app/types"
|
||||
// "io/ioutil"
|
||||
// "fmt"
|
||||
// "time"
|
||||
)
|
||||
|
||||
type Share struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
const AttachToken = 2
|
||||
|
||||
// 添加共享note
|
||||
func (c Share) AddShareNote(noteId string, emails []string, perm int) revel.Result {
|
||||
status := make(map[string]info.Re, len(emails))
|
||||
@@ -36,6 +39,8 @@ func (c Share) AddShareNote(noteId string, emails []string, perm int) revel.Resu
|
||||
return c.RenderJson(status)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 添加共享notebook
|
||||
func (c Share) AddShareNotebook(notebookId string, emails []string, perm int) revel.Result {
|
||||
status := make(map[string]info.Re, len(emails))
|
||||
@@ -185,4 +190,64 @@ func (c Share) DeleteShareNotebookGroup(notebookId, groupId string) revel.Result
|
||||
// 更新, 也是一样, 先删后加
|
||||
func (c Share) UpdateShareNotebookGroupPerm(notebookId, groupId string, perm int) revel.Result {
|
||||
return c.AddShareNotebookGroup(notebookId, groupId, perm)
|
||||
}
|
||||
|
||||
//生成笔记分享密码及更新到db
|
||||
func (c Share) GenShareLinkPass(noteId string) revel.Result {
|
||||
pass, ok := shareService.GenSharePass(noteId)
|
||||
re := info.Re{Ok : true, Item : pass, List: ok}
|
||||
return c.RenderJson(re);
|
||||
}
|
||||
|
||||
func (c Share) QuerySharePass(noteId string) revel.Result {
|
||||
pass := shareService.QuerySharePass(noteId)
|
||||
re := info.Re{Ok : true, Item : pass}
|
||||
return c.RenderJson(re);
|
||||
}
|
||||
|
||||
//展示分享笔记
|
||||
func (c Share) ShowShareNote(noteId string) revel.Result {
|
||||
note := noteService.GetNoteById(noteId)
|
||||
//
|
||||
c.RenderArgs["noteId"] = noteId
|
||||
username := userService.GetUsernameById(note.UserId)
|
||||
|
||||
c.RenderArgs["userName"] = username
|
||||
c.RenderArgs["isMarkDown"] = note.IsMarkdown
|
||||
// c.RenderArgs["timestamp"] = time.Now().Unix()
|
||||
c.SetLocale()
|
||||
return c.RenderTemplate("share/show_share_note.html")
|
||||
}
|
||||
|
||||
//验证分享密码
|
||||
func (c Share) Verify4ShareNote(noteId string, sharePass int) revel.Result {
|
||||
ok, note, noteContent := shareService.Verify4ShareNote(noteId, sharePass)
|
||||
|
||||
attaches := []info.Attach{}
|
||||
if ok && note.AttachNum > 0 {
|
||||
attaches = attachService.ListAttachs(noteId, "")
|
||||
}
|
||||
|
||||
|
||||
token := tokenService.NewToken(noteId, noteId, AttachToken)
|
||||
|
||||
//插入笔记作为链接中的附件
|
||||
noteAttachIds := map[string]bool{}
|
||||
noteContent.Content, noteAttachIds = shareService.AppendToken4URL(token, noteContent.Content)
|
||||
//过滤掉插入笔记的附件
|
||||
filteredAttaches := []info.Attach{}
|
||||
if len(noteAttachIds) > 0 && len(attaches) > 0 {
|
||||
for _, attach := range attaches {
|
||||
if !noteAttachIds[attach.AttachId.Hex()] {
|
||||
filteredAttaches = append(filteredAttaches, attach)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filteredAttaches = attaches
|
||||
}
|
||||
|
||||
sessionId := c.Session.Id()
|
||||
sessionService.SetToken(sessionId, token)
|
||||
re := info.Re{Ok : ok, Item: note, List: filteredAttaches, Id: token, Msg: noteContent.Content}
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func (c AdminUser) Register(email, pwd string) revel.Result {
|
||||
}
|
||||
|
||||
// 注册
|
||||
re.Ok, re.Msg = authService.Register(email, pwd)
|
||||
re.Ok, re.Msg = authService.Register(email, pwd, "")
|
||||
|
||||
return c.RenderRe(re)
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ var commonUrl = map[string]map[string]bool{"Index": map[string]bool{"Index": tru
|
||||
"Suggestion": true,
|
||||
},
|
||||
"Note": map[string]bool{"ToImage": true},
|
||||
"Share": map[string]bool{"ShowShareNote": true, "Verify4ShareNote": true},
|
||||
"Blog": map[string]bool{"Index": true,
|
||||
"View": true,
|
||||
"AboutMe": true,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package member
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
"os"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
"fmt"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
"github.com/revel/revel"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
// "github.com/leanote/leanote/app/lea/blog"
|
||||
"time"
|
||||
// "github.com/leanote/leanote/app/lea/blog"
|
||||
)
|
||||
|
||||
// 博客管理
|
||||
@@ -28,35 +28,34 @@ func (c MemberBlog) common() info.UserBlog {
|
||||
|
||||
userBlog := blogService.GetUserBlog(userId)
|
||||
c.RenderArgs["userBlog"] = userBlog
|
||||
|
||||
|
||||
c.SetUserInfo()
|
||||
c.SetLocale()
|
||||
return userBlog
|
||||
}
|
||||
|
||||
|
||||
// 得到sorterField 和 isAsc
|
||||
// okSorter = ['email', 'username']
|
||||
func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool){
|
||||
func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string) (string, bool) {
|
||||
sorter := ""
|
||||
c.Params.Bind(&sorter, "sorter")
|
||||
if sorter == "" {
|
||||
return sorterField, isAsc;
|
||||
return sorterField, isAsc
|
||||
}
|
||||
|
||||
|
||||
// sorter形式 email-up, email-down
|
||||
s2 := strings.Split(sorter, "-")
|
||||
if len(s2) != 2 {
|
||||
return sorterField, isAsc;
|
||||
return sorterField, isAsc
|
||||
}
|
||||
|
||||
|
||||
// 必须是可用的sorter
|
||||
if okSorter != nil && len(okSorter) > 0 {
|
||||
if !InArray(okSorter, s2[0]) {
|
||||
return sorterField, isAsc;
|
||||
return sorterField, isAsc
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sorterField = strings.Title(s2[0])
|
||||
if s2[1] == "up" {
|
||||
isAsc = true
|
||||
@@ -64,24 +63,29 @@ func (c MemberBlog) getSorter(sorterField string, isAsc bool, okSorter []string)
|
||||
isAsc = false
|
||||
}
|
||||
c.RenderArgs["sorter"] = sorter
|
||||
return sorterField, isAsc;
|
||||
return sorterField, isAsc
|
||||
}
|
||||
|
||||
// 博客列表
|
||||
var userPageSize = 15
|
||||
|
||||
func (c MemberBlog) Index(sorter, keywords string) revel.Result {
|
||||
userId := c.GetUserId()
|
||||
userInfo := userService.GetUserInfo(userId)
|
||||
c.RenderArgs["userInfo"] = userInfo
|
||||
|
||||
c.RenderArgs["title"] = "Posts"
|
||||
pageNumber := c.GetPage()
|
||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"});
|
||||
pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc);
|
||||
sorterField, isAsc := c.getSorter("CreatedTime", false, []string{"title", "urlTitle", "updatedTime", "publicTime", "createdTime"})
|
||||
pageInfo, blogs := blogService.ListAllBlogs(c.GetUserId(), "", keywords, false, pageNumber, userPageSize, sorterField, isAsc)
|
||||
c.RenderArgs["pageInfo"] = pageInfo
|
||||
c.RenderArgs["blogs"] = blogs
|
||||
c.RenderArgs["keywords"] = keywords
|
||||
|
||||
|
||||
userAndBlog := userService.GetUserAndBlog(c.GetUserId())
|
||||
c.RenderArgs["userAndBlog"] = userAndBlog
|
||||
|
||||
return c.RenderTemplate("member/blog/list.html");
|
||||
|
||||
return c.RenderTemplate("member/blog/list.html")
|
||||
}
|
||||
|
||||
// 修改笔记的urlTitle
|
||||
@@ -91,17 +95,16 @@ func (c MemberBlog) UpdateBlogUrlTitle(noteId, urlTitle string) revel.Result {
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
|
||||
// 修改笔记的urlTitle
|
||||
func (c MemberBlog) UpdateBlogAbstract(noteId string) revel.Result {
|
||||
c.RenderArgs["title"] = "Update Post Abstract"
|
||||
note := noteService.GetNoteAndContent(noteId, c.GetUserId());
|
||||
note := noteService.GetNoteAndContent(noteId, c.GetUserId())
|
||||
if !note.Note.IsBlog {
|
||||
return c.E404();
|
||||
return c.E404()
|
||||
}
|
||||
c.RenderArgs["note"] = note
|
||||
c.RenderArgs["noteId"] = noteId
|
||||
return c.RenderTemplate("member/blog/update_abstract.html");
|
||||
return c.RenderTemplate("member/blog/update_abstract.html")
|
||||
}
|
||||
func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string) revel.Result {
|
||||
|
||||
@@ -114,38 +117,33 @@ func (c MemberBlog) DoUpdateBlogAbstract(noteId, imgSrc, desc, abstract string)
|
||||
func (c MemberBlog) Base() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = "Blog Base Info"
|
||||
return c.RenderTemplate("member/blog/base.html");
|
||||
return c.RenderTemplate("member/blog/base.html")
|
||||
}
|
||||
func (c MemberBlog) Comment() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = "Comment"
|
||||
return c.RenderTemplate("member/blog/comment.html");
|
||||
}
|
||||
func (c MemberBlog) Domain() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = "Domain"
|
||||
return c.RenderTemplate("member/blog/domain.html");
|
||||
return c.RenderTemplate("member/blog/comment.html")
|
||||
}
|
||||
|
||||
func (c MemberBlog) Paging() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = "Paging"
|
||||
return c.RenderTemplate("member/blog/paging.html");
|
||||
return c.RenderTemplate("member/blog/paging.html")
|
||||
}
|
||||
|
||||
func (c MemberBlog) Cate() revel.Result {
|
||||
userBlog := c.common()
|
||||
c.RenderArgs["title"] = "Cate"
|
||||
|
||||
|
||||
notebooks := blogService.ListBlogNotebooks(c.GetUserId())
|
||||
notebooksMap := map[string]info.Notebook{}
|
||||
for _, each := range notebooks {
|
||||
notebooksMap[each.NotebookId.Hex()] = each
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
var i = 0
|
||||
notebooks2 := make([]info.Notebook, len(notebooks))
|
||||
|
||||
|
||||
// 先要保证已有的是正确的排序
|
||||
cateIds := userBlog.CateIds
|
||||
has := map[string]bool{} // cateIds中有的
|
||||
@@ -167,8 +165,8 @@ func (c MemberBlog) Cate() revel.Result {
|
||||
}
|
||||
}
|
||||
c.RenderArgs["notebooks"] = notebooks2
|
||||
|
||||
return c.RenderTemplate("member/blog/cate.html");
|
||||
|
||||
return c.RenderTemplate("member/blog/cate.html")
|
||||
}
|
||||
|
||||
// 修改分类排序
|
||||
@@ -195,9 +193,10 @@ func (c MemberBlog) AddOrUpdateSingle(singleId string) revel.Result {
|
||||
c.RenderArgs["title"] = "Add Single"
|
||||
c.RenderArgs["singleId"] = singleId
|
||||
if singleId != "" {
|
||||
c.RenderArgs["title"] = "Update Single"
|
||||
c.RenderArgs["single"] = blogService.GetSingle(singleId)
|
||||
}
|
||||
return c.RenderTemplate("member/blog/add_single.html");
|
||||
return c.RenderTemplate("member/blog/add_single.html")
|
||||
}
|
||||
func (c MemberBlog) SortSingles(singleIds []string) revel.Result {
|
||||
re := info.NewRe()
|
||||
@@ -222,8 +221,8 @@ func (c MemberBlog) Single() revel.Result {
|
||||
c.common()
|
||||
c.RenderArgs["title"] = "Cate"
|
||||
c.RenderArgs["singles"] = blogService.GetSingles(c.GetUserId())
|
||||
|
||||
return c.RenderTemplate("member/blog/single.html");
|
||||
|
||||
return c.RenderTemplate("member/blog/single.html")
|
||||
}
|
||||
|
||||
// 主题
|
||||
@@ -232,15 +231,16 @@ func (c MemberBlog) Theme() revel.Result {
|
||||
activeTheme, otherThemes := themeService.GetUserThemes(c.GetUserId())
|
||||
c.RenderArgs["activeTheme"] = activeTheme
|
||||
c.RenderArgs["otherThemes"] = otherThemes
|
||||
|
||||
|
||||
c.RenderArgs["optionThemes"] = themeService.GetDefaultThemes()
|
||||
|
||||
|
||||
c.RenderArgs["title"] = "Theme"
|
||||
return c.RenderTemplate("member/blog/theme.html");
|
||||
return c.RenderTemplate("member/blog/theme.html")
|
||||
}
|
||||
|
||||
// 编辑主题
|
||||
var baseTpls = []string{"header.html", "footer.html", "index.html", "cate.html", "search.html", "post.html", "single.html", "tags.html", "tag_posts.html", "archive.html", "share_comment.html", "404.html", "theme.json", "style.css", "blog.js"}
|
||||
|
||||
func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
|
||||
// 查看用户是否有该theme, 若没有则复制default之
|
||||
// 得到主题的文件列表
|
||||
@@ -249,22 +249,25 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
|
||||
_, themeId = themeService.NewThemeForFirst(userBlog)
|
||||
return c.Redirect("/member/blog/updateTheme?themeId=" + themeId)
|
||||
}
|
||||
|
||||
|
||||
c.common()
|
||||
c.RenderArgs["title"] = "Upate Theme"
|
||||
c.RenderArgs["isNew"] = isNew
|
||||
|
||||
|
||||
// 先复制之
|
||||
c.RenderArgs["themeId"] = themeId
|
||||
|
||||
|
||||
// 得到脚本目录
|
||||
userId := c.GetUserId()
|
||||
|
||||
theme := themeService.GetTheme(userId, themeId)
|
||||
|
||||
theme := themeService.GetTheme(userId, themeId)
|
||||
if theme.ThemeId == "" {
|
||||
return c.E404()
|
||||
}
|
||||
c.RenderArgs["theme"] = theme
|
||||
|
||||
|
||||
path := revel.BasePath + "/" + theme.Path
|
||||
|
||||
|
||||
tpls := ListDir(path)
|
||||
myTpls := make([]string, len(baseTpls))
|
||||
tplMap := map[string]bool{}
|
||||
@@ -275,16 +278,16 @@ func (c MemberBlog) UpdateTheme(themeId string, isNew int) revel.Result {
|
||||
// 得到没有的tpls
|
||||
for _, t := range tpls {
|
||||
if t == "images" {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
if !tplMap[t] {
|
||||
myTpls = append(myTpls, t)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
c.RenderArgs["myTpls"] = myTpls
|
||||
|
||||
return c.RenderTemplate("member/blog/update_theme.html");
|
||||
|
||||
return c.RenderTemplate("member/blog/update_theme.html")
|
||||
}
|
||||
|
||||
// 得到文件内容
|
||||
@@ -292,13 +295,13 @@ func (c MemberBlog) GetTplContent(themeId string, filename string) revel.Result
|
||||
re := info.NewRe()
|
||||
re.Ok = true
|
||||
re.Item = themeService.GetTplContent(c.GetUserId(), themeId, filename)
|
||||
|
||||
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
func (c MemberBlog) UpdateTplContent(themeId, filename, content string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = themeService.UpdateTplContent(c.GetUserId(), themeId, filename, content)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderRe(re)
|
||||
}
|
||||
|
||||
func (c MemberBlog) DeleteTpl(themeId, filename string) revel.Result {
|
||||
@@ -327,7 +330,7 @@ func (c MemberBlog) DeleteThemeImage(themeId, filename string) revel.Result {
|
||||
|
||||
// 上传主题图片
|
||||
func (c MemberBlog) UploadThemeImage(themeId string) revel.Result {
|
||||
re := c.uploadImage(themeId);
|
||||
re := c.uploadImage(themeId)
|
||||
c.RenderArgs["fileUrlPath"] = re.Id
|
||||
c.RenderArgs["resultCode"] = re.Code
|
||||
c.RenderArgs["resultMsg"] = re.Msg
|
||||
@@ -335,17 +338,17 @@ func (c MemberBlog) UploadThemeImage(themeId string) revel.Result {
|
||||
}
|
||||
func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
||||
var fileId = ""
|
||||
var resultCode = 0 // 1表示正常
|
||||
var resultCode = 0 // 1表示正常
|
||||
var resultMsg = "内部错误" // 错误信息
|
||||
var Ok = false
|
||||
|
||||
|
||||
defer func() {
|
||||
re.Id = fileId // 只是id, 没有其它信息
|
||||
re.Code = resultCode
|
||||
re.Msg = resultMsg
|
||||
re.Ok = Ok
|
||||
}()
|
||||
|
||||
|
||||
file, handel, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
return re
|
||||
@@ -359,11 +362,11 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
||||
}
|
||||
// 生成新的文件名
|
||||
filename := handel.Filename
|
||||
|
||||
var ext string;
|
||||
|
||||
|
||||
var ext string
|
||||
|
||||
_, ext = SplitFilename(filename)
|
||||
if(ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg") {
|
||||
if ext != ".gif" && ext != ".jpg" && ext != ".png" && ext != ".bmp" && ext != ".jpeg" {
|
||||
resultMsg = "不是图片"
|
||||
return re
|
||||
}
|
||||
@@ -374,15 +377,15 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
||||
LogJ(err)
|
||||
return re
|
||||
}
|
||||
|
||||
|
||||
// > 2M?
|
||||
if(len(data) > 5 * 1024 * 1024) {
|
||||
if len(data) > 5*1024*1024 {
|
||||
resultCode = 0
|
||||
resultMsg = "图片大于2M"
|
||||
return re
|
||||
}
|
||||
|
||||
toPath := dir + "/" + filename;
|
||||
|
||||
toPath := dir + "/" + filename
|
||||
err = ioutil.WriteFile(toPath, data, 0777)
|
||||
if err != nil {
|
||||
LogJ(err)
|
||||
@@ -391,7 +394,7 @@ func (c MemberBlog) uploadImage(themeId string) (re info.Re) {
|
||||
TransToGif(toPath, 0, true)
|
||||
resultCode = 1
|
||||
resultMsg = "上传成功!"
|
||||
|
||||
|
||||
return re
|
||||
}
|
||||
|
||||
@@ -402,18 +405,21 @@ func (c MemberBlog) ActiveTheme(themeId string) revel.Result {
|
||||
re.Ok = themeService.ActiveTheme(c.GetUserId(), themeId)
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
// 删除主题
|
||||
func (c MemberBlog) DeleteTheme(themeId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = themeService.DeleteTheme(c.GetUserId(), themeId)
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
// 管理员公开主题
|
||||
func (c MemberBlog) PublicTheme(themeId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = themeService.PublicTheme(c.GetUserId(), themeId)
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
// 导出
|
||||
func (c MemberBlog) ExportTheme(themeId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
@@ -423,21 +429,21 @@ func (c MemberBlog) ExportTheme(themeId string) revel.Result {
|
||||
return c.RenderText("error...")
|
||||
}
|
||||
fw, err := os.Open(path)
|
||||
if err != nil {
|
||||
if err != nil {
|
||||
return c.RenderText("error")
|
||||
}
|
||||
return c.RenderBinary(fw, GetFilename(path), revel.Attachment, time.Now()) // revel.Attachment
|
||||
}
|
||||
return c.RenderBinary(fw, GetFilename(path), revel.Attachment, time.Now()) // revel.Attachment
|
||||
}
|
||||
|
||||
// 导入主题
|
||||
func (c MemberBlog) ImportTheme() revel.Result {
|
||||
re := info.NewRe()
|
||||
|
||||
|
||||
file, handel, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
re.Msg = fmt.Sprintf("%v", err)
|
||||
return c.RenderJson(re)
|
||||
|
||||
|
||||
}
|
||||
defer file.Close()
|
||||
// 生成上传路径
|
||||
@@ -450,10 +456,10 @@ func (c MemberBlog) ImportTheme() revel.Result {
|
||||
}
|
||||
// 生成新的文件名
|
||||
filename := handel.Filename
|
||||
|
||||
var ext string;
|
||||
|
||||
var ext string
|
||||
_, ext = SplitFilename(filename)
|
||||
if(ext != ".zip") {
|
||||
if ext != ".zip" {
|
||||
re.Msg = "请上传zip文件"
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
@@ -463,40 +469,40 @@ func (c MemberBlog) ImportTheme() revel.Result {
|
||||
if err != nil {
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
|
||||
// > 10M?
|
||||
if(len(data) > 10 * 1024 * 1024) {
|
||||
if len(data) > 10*1024*1024 {
|
||||
re.Msg = "文件大于10M"
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
toPath := dir + "/" + filename;
|
||||
|
||||
toPath := dir + "/" + filename
|
||||
err = ioutil.WriteFile(toPath, data, 0777)
|
||||
if err != nil {
|
||||
re.Msg = fmt.Sprintf("%v", err)
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
|
||||
// 上传好后, 增加之
|
||||
themeService.ImportTheme(c.GetUserId(), toPath)
|
||||
|
||||
re.Ok = true
|
||||
return c.RenderJson(re)
|
||||
re.Ok, re.Msg = themeService.ImportTheme(c.GetUserId(), toPath)
|
||||
return c.RenderRe(re)
|
||||
}
|
||||
|
||||
|
||||
// 安装
|
||||
func (c MemberBlog) InstallTheme(themeId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = themeService.InstallTheme(c.GetUserId(), themeId)
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
// 新建主题
|
||||
func (c MemberBlog) NewTheme() revel.Result {
|
||||
_, themeId := themeService.NewTheme(c.GetUserId())
|
||||
return c.Redirect("/member/blog/updateTheme?isNew=1&themeId=" + themeId)
|
||||
}
|
||||
|
||||
//-----------
|
||||
//
|
||||
//
|
||||
func (c MemberBlog) SetUserBlogBase(userBlog info.UserBlogBase) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok = blogService.UpdateUserBlogBase(c.GetUserId(), userBlog)
|
||||
@@ -512,6 +518,7 @@ func (c MemberBlog) SetUserBlogStyle(userBlog info.UserBlogStyle) revel.Result {
|
||||
re.Ok = blogService.UpdateUserBlogStyle(c.GetUserId(), userBlog)
|
||||
return c.RenderJson(re)
|
||||
}
|
||||
|
||||
func (c MemberBlog) SetUserBlogPaging(perPageSize int, sortField string, isAsc bool) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = blogService.UpdateUserBlogPaging(c.GetUserId(), perPageSize, sortField, isAsc)
|
||||
|
||||
@@ -35,7 +35,7 @@ func (c MemberGroup) UpdateGroupTitle(groupId, title string) revel.Result {
|
||||
func (c MemberGroup) DeleteGroup(groupId string) revel.Result {
|
||||
re := info.NewRe()
|
||||
re.Ok, re.Msg = groupService.DeleteGroup(c.GetUserId(), groupId)
|
||||
return c.RenderJson(re)
|
||||
return c.RenderRe(re)
|
||||
}
|
||||
|
||||
// 添加用户
|
||||
|
||||
@@ -128,6 +128,7 @@ func init() {
|
||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberIndex{})
|
||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberUser{})
|
||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberBlog{})
|
||||
revel.InterceptFunc(AuthInterceptor, revel.BEFORE, &MemberGroup{})
|
||||
revel.OnAppStart(func() {
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package db
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/revel"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
"gopkg.in/mgo.v2"
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
)
|
||||
@@ -56,12 +57,15 @@ var Themes *mgo.Collection
|
||||
var Sessions *mgo.Collection
|
||||
|
||||
// 初始化时连接数据库
|
||||
func Init() {
|
||||
var url string
|
||||
var ok bool
|
||||
func Init(url, dbname string) {
|
||||
ok := true
|
||||
config := revel.Config
|
||||
url, ok = config.String("db.url")
|
||||
dbname, _ := config.String("db.dbname")
|
||||
if url == "" {
|
||||
url, ok = config.String("db.url")
|
||||
}
|
||||
if dbname == "" {
|
||||
dbname, _ = config.String("db.dbname")
|
||||
}
|
||||
if !ok {
|
||||
host, _ := revel.Config.String("db.host")
|
||||
port, _ := revel.Config.String("db.port")
|
||||
@@ -73,6 +77,7 @@ func Init() {
|
||||
}
|
||||
url = "mongodb://" + usernameAndPassword + host + ":" + port + "/" + dbname
|
||||
}
|
||||
Log(url)
|
||||
|
||||
// [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]
|
||||
// mongodb://myuser:mypass@localhost:40001,otherhost:40001/mydb
|
||||
|
||||
@@ -40,6 +40,8 @@ type Note struct {
|
||||
RecommendTime time.Time `RecommendTime,omitempty` // 推荐时间
|
||||
PublicTime time.Time `PublicTime,omitempty` // 发表时间, 公开为博客则设置
|
||||
UpdatedUserId bson.ObjectId `bson:"UpdatedUserId"` // 如果共享了, 并可写, 那么可能是其它他修改了
|
||||
|
||||
SharePass int `SharePass` //分享笔记的密码
|
||||
}
|
||||
|
||||
// 内容
|
||||
|
||||
@@ -10,10 +10,11 @@ type Session struct {
|
||||
Id bson.ObjectId `bson:"_id,omitempty"` // 没有意义
|
||||
|
||||
SessionId string `bson:"SessionId"` // SessionId
|
||||
|
||||
|
||||
LoginTimes int `LoginTimes` // 登录错误时间
|
||||
Captcha string `Captcha` // 验证码
|
||||
|
||||
Token string `Token` //attach token
|
||||
TokenTime time.Time `TokenTime` //token生成时间
|
||||
CreatedTime time.Time `CreatedTime`
|
||||
UpdatedTime time.Time `UpdatedTime` // 更新时间, expire这个时间会自动清空
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ type User struct {
|
||||
ImageSize int `bson:"ImageSize" json:"-"` // 图片大小
|
||||
AttachNum int `bson:"AttachNum" json:"-"` // 附件数量
|
||||
AttachSize int `bson:"AttachSize" json:"-"` // 附件大小
|
||||
PerAttachSize int `bson:"PerAttachSize" json:"-"` // 单个附件大小
|
||||
FromUserId bson.ObjectId `FromUserId,omitempty` // 邀请的用户
|
||||
|
||||
AccountType string `bson:"AccountType" json:"-"` // normal(为空), premium
|
||||
AccountStartTime time.Time `bson:"AccountStartTime" json:"-"` // 开始日期
|
||||
|
||||
61
app/init.go
61
app/init.go
@@ -111,6 +111,7 @@ func init() {
|
||||
}
|
||||
|
||||
// tags
|
||||
// 2014/12/30 标签添加链接
|
||||
revel.TemplateFuncs["blogTags"] = func(renderArgs map[string]interface{}, tags []string) template.HTML {
|
||||
if tags == nil || len(tags) == 0 {
|
||||
return ""
|
||||
@@ -118,18 +119,68 @@ func init() {
|
||||
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
||||
tagStr := ""
|
||||
lenTags := len(tags)
|
||||
|
||||
tagPostUrl, _ := renderArgs["tagPostsUrl"].(string)
|
||||
|
||||
for i, tag := range tags {
|
||||
str := revel.Message(locale, tag)
|
||||
var classes = "label"
|
||||
if strings.HasPrefix(str, "???") {
|
||||
str = tag
|
||||
}
|
||||
tagStr += str
|
||||
if InArray([]string{"red", "blue", "yellow", "green"}, tag) {
|
||||
classes += " label-" + tag
|
||||
} else {
|
||||
classes += " label-default"
|
||||
}
|
||||
|
||||
classes += " label-post"
|
||||
var url = tagPostUrl + "/" + url.QueryEscape(tag)
|
||||
tagStr += "<a class=\"" + classes + "\" href=\"" + url + "\">" + str + "</a>";
|
||||
if i != lenTags - 1 {
|
||||
tagStr += ","
|
||||
tagStr += " "
|
||||
}
|
||||
}
|
||||
return template.HTML(tagStr)
|
||||
}
|
||||
|
||||
// lea++
|
||||
revel.TemplateFuncs["blogTagsLea"] = func(renderArgs map[string]interface{}, tags []string, isRecommend bool) template.HTML {
|
||||
if tags == nil || len(tags) == 0 {
|
||||
return ""
|
||||
}
|
||||
locale, _ := renderArgs[revel.CurrentLocaleRenderArg].(string)
|
||||
tagStr := ""
|
||||
lenTags := len(tags)
|
||||
|
||||
tagPostUrl := "http://lea.leanote.com/"
|
||||
if isRecommend {
|
||||
tagPostUrl += "?tag=";
|
||||
} else {
|
||||
tagPostUrl += "latest?tag=";
|
||||
}
|
||||
|
||||
for i, tag := range tags {
|
||||
str := revel.Message(locale, tag)
|
||||
var classes = "label"
|
||||
if strings.HasPrefix(str, "???") {
|
||||
str = tag
|
||||
}
|
||||
if InArray([]string{"red", "blue", "yellow", "green"}, tag) {
|
||||
classes += " label-" + tag
|
||||
} else {
|
||||
classes += " label-default"
|
||||
}
|
||||
classes += " label-post"
|
||||
var url = tagPostUrl + url.QueryEscape(tag)
|
||||
tagStr += "<a class=\"" + classes + "\" href=\"" + url + "\">" + str + "</a>";
|
||||
if i != lenTags - 1 {
|
||||
tagStr += " "
|
||||
}
|
||||
}
|
||||
return template.HTML(tagStr)
|
||||
}
|
||||
|
||||
/*
|
||||
revel.TemplateFuncs["blogTags"] = func(tags []string) template.HTML {
|
||||
if tags == nil || len(tags) == 0 {
|
||||
@@ -311,7 +362,7 @@ func init() {
|
||||
// init Email
|
||||
revel.OnAppStart(func() {
|
||||
// 数据库
|
||||
db.Init()
|
||||
db.Init("", "")
|
||||
// email配置
|
||||
InitEmail()
|
||||
InitVd()
|
||||
@@ -322,5 +373,5 @@ func init() {
|
||||
admin.InitService()
|
||||
member.InitService()
|
||||
service.ConfigS.InitGlobalConfigs()
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package lea
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/revel/revel"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func Log(i interface{}) {
|
||||
@@ -12,4 +13,14 @@ func Log(i interface{}) {
|
||||
func LogJ(i interface{}) {
|
||||
b, _ := json.MarshalIndent(i, "", " ")
|
||||
revel.INFO.Println(string(b))
|
||||
}
|
||||
}
|
||||
|
||||
// 为test用
|
||||
func L(i interface{}) {
|
||||
fmt.Println(i)
|
||||
}
|
||||
|
||||
func LJ(i interface{}) {
|
||||
b, _ := json.MarshalIndent(i, "", " ")
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ func init() {
|
||||
// Id retrieves from the cookie or creates a time-based UUID identifying this
|
||||
// session.
|
||||
func (s Session) Id() string {
|
||||
|
||||
if sessionIdStr, ok := s[SESSION_ID_KEY]; ok {
|
||||
return sessionIdStr
|
||||
}
|
||||
@@ -131,7 +132,7 @@ func getSessionFromCookie(cookie *http.Cookie) Session {
|
||||
return session
|
||||
}
|
||||
sig, data := cookie.Value[:hyphen], cookie.Value[hyphen+1:]
|
||||
|
||||
|
||||
// Verify the signature.
|
||||
if !revel.Verify(data, sig) {
|
||||
revel.INFO.Println("Session cookie signature failed")
|
||||
@@ -145,7 +146,7 @@ func getSessionFromCookie(cookie *http.Cookie) Session {
|
||||
if sessionTimeoutExpiredOrMissing(session) {
|
||||
session = make(Session)
|
||||
}
|
||||
|
||||
|
||||
return session
|
||||
}
|
||||
|
||||
@@ -157,6 +158,7 @@ func SessionFilter(c *revel.Controller, fc []revel.Filter) {
|
||||
// c.Session, 重新生成一个revel.Session给controller!!!
|
||||
// Log("sessoin--------")
|
||||
// LogJ(session)
|
||||
|
||||
revelSession := revel.Session(session) // 强制转换 还是同一个对象, 但有个问题, 这样Session.Id()方法是用revel的了
|
||||
c.Session = revelSession
|
||||
// 生成sessionId
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/*
|
||||
用golang exec 总是说找不到uglifyjs命令, 需要全部路径
|
||||
而且node, npm要在/usr/bin下, 已建ln
|
||||
@@ -31,7 +32,7 @@ import (
|
||||
//var jss = []string{"js/jquery-cookie", "js/bootstrap"}
|
||||
var jss = []string{"js/jquery-cookie", "js/bootstrap",
|
||||
"js/common", "js/app/note", "js/app/tag", "js/app/notebook", "js/app/share",
|
||||
"js/object_id", "js/ZeroClipboard/ZeroClipboard"}
|
||||
"js/object_id"}
|
||||
|
||||
var base1 = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/"
|
||||
var base = "/Users/life/Documents/Go/package2/src/github.com/leanote/leanote/public/"
|
||||
@@ -52,7 +53,7 @@ func compressJs(filename string) {
|
||||
to := base + filename + "-min.js"
|
||||
cmd := exec.Command(cmdPath, source, "-o", to)
|
||||
_, err := cmd.CombinedOutput()
|
||||
|
||||
fmt.Println(source);
|
||||
cmdError(err)
|
||||
}
|
||||
|
||||
@@ -80,7 +81,10 @@ func combineJs() {
|
||||
// 改note-dev->note
|
||||
func dev() {
|
||||
// 即替换note.js->note-min.js
|
||||
m := map[string]string{"note.js": "note-min.js",
|
||||
m := map[string]string{"tinymce.dev.js": "tinymce.min.js",
|
||||
"tinymce.js": "tinymce.min.js",
|
||||
"jquery.ztree.all-3.5.js": "jquery.ztree.all-3.5-min.js",
|
||||
"note.js": "note-min.js",
|
||||
"app.js": "app-min.js",
|
||||
"page.js": "page-min.js",
|
||||
"common.js": "common-min.js",
|
||||
@@ -88,6 +92,7 @@ func dev() {
|
||||
"share.js": "share-min.js",
|
||||
"tag.js": "tag-min.js",
|
||||
"main.js": "main-min.js",
|
||||
"jquery.slimscroll.js": "jquery.slimscroll-min.js",
|
||||
"jquery.contextmenu.js": "jquery.contextmenu-min.js",
|
||||
"editor/editor.js": "editor/editor-min.js",
|
||||
"/public/mdeditor/editor/scrollLink.js": "/public/mdeditor/editor/scrollLink-min.js",
|
||||
@@ -111,12 +116,21 @@ func tinymce() {
|
||||
// cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify", "bundle[themes:modern,plugins:table,paste,advlist,autolink,link,image,lists,charmap,hr,searchreplace,visualblocks,visualchars,code,nav,tabfocus,contextmenu,directionality,codemirror,codesyntax,textcolor,fullpage]")
|
||||
cmd := exec.Command("/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master/node_modules/jake/bin/cli.js", "minify")
|
||||
cmd.Dir = "/Users/life/Documents/eclipse-workspace/go/leanote_release/tinymce-master"
|
||||
c, err := cmd.CombinedOutput()
|
||||
|
||||
// 必须要先删除
|
||||
cmd2 := exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.dev.js")
|
||||
cmd2.CombinedOutput()
|
||||
cmd2 = exec.Command("/bin/sh", "-c", "rm " + cmd.Dir + "/js/tinymce/tinymce.jquery.dev.js")
|
||||
c, _ := cmd2.CombinedOutput()
|
||||
fmt.Println(string(c))
|
||||
c, _ = cmd.CombinedOutput()
|
||||
fmt.Println(string(c))
|
||||
cmdError(err)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 压缩tinymce
|
||||
tinymce()
|
||||
|
||||
dev();
|
||||
|
||||
// 其它零散的需要压缩的js
|
||||
@@ -133,6 +147,10 @@ func main() {
|
||||
"mdeditor/editor/underscore",
|
||||
"mdeditor/editor/mathJax",
|
||||
"js/jQuery-slimScroll-1.3.0/jquery.slimscroll",
|
||||
"js/app/editor_drop_paste",
|
||||
"js/app/attachment_upload",
|
||||
"js/jquery.ztree.all-3.5",
|
||||
"js/jQuery-slimScroll-1.3.0/jquery.slimscroll",
|
||||
}
|
||||
|
||||
for _, js := range otherJss {
|
||||
@@ -141,7 +159,5 @@ func main() {
|
||||
|
||||
// 先压缩后合并
|
||||
combineJs()
|
||||
|
||||
// 压缩tinymce
|
||||
tinymce()
|
||||
|
||||
}
|
||||
|
||||
@@ -15,16 +15,16 @@ type AttachService struct {
|
||||
}
|
||||
|
||||
// add attach
|
||||
func (this *AttachService) AddAttach(attach info.Attach) bool {
|
||||
func (this *AttachService) AddAttach(attach info.Attach) (ok bool, msg string) {
|
||||
attach.CreatedTime = time.Now()
|
||||
ok := db.Insert(db.Attachs, attach)
|
||||
ok = db.Insert(db.Attachs, attach)
|
||||
|
||||
if ok {
|
||||
// 更新笔记的attachs num
|
||||
this.updateNoteAttachNum(attach.NoteId, 1)
|
||||
}
|
||||
|
||||
return ok
|
||||
return
|
||||
}
|
||||
|
||||
// 更新笔记的附件个数
|
||||
@@ -46,8 +46,8 @@ func (this *AttachService) updateNoteAttachNum(noteId bson.ObjectId, addNum int)
|
||||
// list attachs
|
||||
func (this *AttachService) ListAttachs(noteId, userId string) []info.Attach {
|
||||
attachs := []info.Attach{}
|
||||
// 判断是否有权限为笔记添加附件
|
||||
if !shareService.HasUpdateNotePerm(noteId, userId) {
|
||||
// 判断是否有权限为笔记添加附件, userId为空时表示是分享笔记的附件
|
||||
if userId != "" && !shareService.HasUpdateNotePerm(noteId, userId) {
|
||||
return attachs
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ func (this *AttachService) ListAttachs(noteId, userId string) []info.Attach {
|
||||
return attachs
|
||||
}
|
||||
|
||||
|
||||
func (this *AttachService) UpdateImageTitle(userId, fileId, title string) bool {
|
||||
return db.UpdateByIdAndUserIdField(db.Files, fileId, userId, "Title", title)
|
||||
}
|
||||
@@ -105,7 +106,7 @@ func (this *AttachService) DeleteAttach(attachId, userId string) (bool, string)
|
||||
// 获取文件路径
|
||||
// 要判断是否具有权限
|
||||
// userId是否具有attach的访问权限
|
||||
func (this *AttachService) GetAttach(attachId, userId string) (attach info.Attach) {
|
||||
func (this *AttachService) GetAttach(attachId, userId, token, sessionId string) (attach info.Attach) {
|
||||
if attachId == "" {
|
||||
return
|
||||
}
|
||||
@@ -136,6 +137,17 @@ func (this *AttachService) GetAttach(attachId, userId string) (attach info.Attac
|
||||
return
|
||||
}
|
||||
|
||||
//userId为空则是分享笔记的附件
|
||||
if userId == "" && sessionId != "" {
|
||||
if token != "" {
|
||||
realToken := sessionService.GetToken(sessionId)
|
||||
if token == realToken {
|
||||
Log("attach token is equal!")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attach = info.Attach{}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
// "github.com/leanote/leanote/app/db"
|
||||
"github.com/leanote/leanote/app/info"
|
||||
// "github.com/revel/revel"
|
||||
"strings"
|
||||
. "github.com/leanote/leanote/app/lea"
|
||||
"fmt"
|
||||
"strconv"
|
||||
@@ -17,6 +18,8 @@ type AuthService struct {
|
||||
|
||||
// pwd已md5了
|
||||
func (this *AuthService) Login(emailOrUsername, pwd string) info.User {
|
||||
emailOrUsername = strings.Trim(emailOrUsername, " ")
|
||||
// pwd = strings.Trim(pwd, " ")
|
||||
userInfo := userService.LoginGetUserInfo(emailOrUsername, Md5(pwd))
|
||||
return userInfo
|
||||
}
|
||||
@@ -32,12 +35,16 @@ func (this *AuthService) Login(emailOrUsername, pwd string) info.User {
|
||||
// 1. 添加用户
|
||||
// 2. 将leanote共享给我
|
||||
// [ok]
|
||||
func (this *AuthService) Register(email, pwd string) (bool, string) {
|
||||
func (this *AuthService) Register(email, pwd, fromUserId string) (bool, string) {
|
||||
// 用户是否已存在
|
||||
if userService.IsExistsUser(email) {
|
||||
return false, "userHasBeenRegistered-" + email
|
||||
}
|
||||
user := info.User{UserId: bson.NewObjectId(), Email: email, Username: email, Pwd: Md5(pwd)}
|
||||
if fromUserId != "" && IsObjectId(fromUserId) {
|
||||
user.FromUserId = bson.ObjectIdHex(fromUserId)
|
||||
}
|
||||
LogJ(user)
|
||||
return this.register(user)
|
||||
}
|
||||
|
||||
@@ -129,4 +136,4 @@ func (this *AuthService) ThirdRegister(thirdType, thirdUserId, thirdUsername str
|
||||
}
|
||||
_, _ = this.register(userInfo)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ func (this *BlogService) SearchBlog(key, userId string, page, pageSize int, sort
|
||||
// 上一篇文章, 下一篇文章
|
||||
// sorterField, baseTime是基准, sorterField=PublicTime, title
|
||||
// isAsc是用户自定义的排序方式
|
||||
func (this *BlogService) PreNextBlog(userId string, sorterField string, isAsc bool, baseTime interface{}) (info.Post, info.Post) {
|
||||
func (this *BlogService) PreNextBlog(userId string, sorterField string, isAsc bool, noteId string, baseTime interface{}) (info.Post, info.Post) {
|
||||
userIdO := bson.ObjectIdHex(userId)
|
||||
|
||||
var sortFieldT1, sortFieldT2 bson.M
|
||||
@@ -367,10 +367,10 @@ func (this *BlogService) PreNextBlog(userId string, sorterField string, isAsc bo
|
||||
--
|
||||
*/
|
||||
// 上一篇时间要比它大, 找最小的
|
||||
sortFieldT1 = bson.M{"$gt": baseTime}
|
||||
sortFieldT1 = bson.M{"$gte": baseTime} // 为什么要相等, 因为将notebook发布成博客, 会统一修改note的publicTime, 此时所有notes都一样
|
||||
sortFieldR1 = sorterField
|
||||
// 下一篇时间要比它小
|
||||
sortFieldT2 = bson.M{"$lt": baseTime}
|
||||
sortFieldT2 = bson.M{"$lte": baseTime}
|
||||
sortFieldR2 = "-" + sorterField
|
||||
} else {
|
||||
// 升序
|
||||
@@ -381,22 +381,28 @@ func (this *BlogService) PreNextBlog(userId string, sorterField string, isAsc bo
|
||||
---------
|
||||
*/
|
||||
// 上一篇要比它小, 找最大的
|
||||
sortFieldT1 = bson.M{"$lt": baseTime}
|
||||
sortFieldT1 = bson.M{"$lte": baseTime}
|
||||
sortFieldR1 = "-" + sorterField
|
||||
// 下一篇, 找最小的
|
||||
sortFieldT2 = bson.M{"$gt": baseTime}
|
||||
sortFieldT2 = bson.M{"$gte": baseTime}
|
||||
sortFieldR2 = sorterField
|
||||
}
|
||||
|
||||
// 上一篇, 比基时间要小, 但是是最后一篇, 所以是降序
|
||||
note := info.Note{}
|
||||
query := bson.M{"UserId": userIdO, "IsTrash": false, "IsBlog": true,
|
||||
query := bson.M{"UserId": userIdO,
|
||||
"IsTrash": false,
|
||||
"IsBlog": true,
|
||||
"_id": bson.M{"$ne": bson.ObjectIdHex(noteId)},
|
||||
sorterField: sortFieldT1,
|
||||
}
|
||||
q := db.Notes.Find(query)
|
||||
q.Sort(sortFieldR1).Limit(1).One(¬e)
|
||||
|
||||
// 下一篇, 比基时间要大, 但是是第一篇, 所以是升序
|
||||
if note.NoteId != "" {
|
||||
query["_id"] = bson.M{"$nin": []bson.ObjectId{bson.ObjectIdHex(noteId), note.NoteId}}
|
||||
}
|
||||
note2 := info.Note{}
|
||||
query[sorterField] = sortFieldT2
|
||||
// Log(isAsc)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
"os"
|
||||
"strings"
|
||||
// "fmt"
|
||||
)
|
||||
|
||||
const DEFAULT_ALBUM_ID = "52d3e8ac99c37b7f0d000001"
|
||||
@@ -17,7 +18,7 @@ type FileService struct {
|
||||
}
|
||||
|
||||
// add Image
|
||||
func (this *FileService) AddImage(image info.File, albumId, userId string) bool {
|
||||
func (this *FileService) AddImage(image info.File, albumId, userId string, needCheckSize bool) (ok bool, msg string) {
|
||||
image.CreatedTime = time.Now()
|
||||
if albumId != "" {
|
||||
image.AlbumId = bson.ObjectIdHex(albumId)
|
||||
@@ -27,7 +28,8 @@ func (this *FileService) AddImage(image info.File, albumId, userId string) bool
|
||||
}
|
||||
image.UserId = bson.ObjectIdHex(userId)
|
||||
|
||||
return db.Insert(db.Files, image)
|
||||
ok = db.Insert(db.Files, image)
|
||||
return
|
||||
}
|
||||
|
||||
// list images
|
||||
@@ -117,7 +119,8 @@ func (this *FileService) UpdateImage(userId, fileId, title string) bool {
|
||||
// 获取文件路径
|
||||
// 要判断是否具有权限
|
||||
// userId是否具有fileId的访问权限
|
||||
func (this *FileService) GetFile(userId, fileId string) string {
|
||||
|
||||
func (this *FileService) GetFile(userId, fileId , sessionId , token string) string {
|
||||
if fileId == "" {
|
||||
return ""
|
||||
}
|
||||
@@ -130,7 +133,8 @@ func (this *FileService) GetFile(userId, fileId string) string {
|
||||
}
|
||||
|
||||
// 1. 判断权限
|
||||
|
||||
//未登录用户,判断token
|
||||
noteIds := noteImageService.GetNoteIds(fileId)
|
||||
// 是否是我的文件
|
||||
if userId != "" && file.UserId.Hex() == userId {
|
||||
return path
|
||||
@@ -140,14 +144,41 @@ func (this *FileService) GetFile(userId, fileId string) string {
|
||||
// 这些笔记是否有public的, 若有则ok
|
||||
// 这些笔记(笔记本)是否有共享给我的, 若有则ok
|
||||
|
||||
noteIds := noteImageService.GetNoteIds(fileId)
|
||||
|
||||
if noteIds != nil && len(noteIds) > 0 {
|
||||
// 这些笔记是否有public的
|
||||
if db.Has(db.Notes, bson.M{"_id": bson.M{"$in": noteIds}, "IsBlog": true}) {
|
||||
return path
|
||||
}
|
||||
|
||||
//分享给未注册用户
|
||||
if userId == "" && sessionId != "" {
|
||||
if token != "" {
|
||||
realToken := sessionService.GetToken(sessionId)
|
||||
if token == realToken {
|
||||
Log("image token is equal!")
|
||||
return path
|
||||
} else {
|
||||
Log("image token is different!")
|
||||
return ""
|
||||
}
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 2014/12/28 修复, 如果是分享给用户组, 那就不行, 这里可以实现
|
||||
for _, noteId := range noteIds {
|
||||
note := noteService.GetNoteById(noteId.Hex())
|
||||
if shareService.HasReadPerm(note.UserId.Hex(), userId, noteId.Hex()) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// 若有共享给我的笔记?
|
||||
// 对该笔记可读?
|
||||
if db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NoteId": bson.M{"$in": noteIds}}) {
|
||||
return path
|
||||
}
|
||||
@@ -166,6 +197,7 @@ func (this *FileService) GetFile(userId, fileId string) string {
|
||||
return path
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// 可能是刚复制到owner上, 但内容又没有保存, 所以没有note->imageId的映射, 此时看是否有fromFileId
|
||||
@@ -180,6 +212,7 @@ func (this *FileService) GetFile(userId, fileId string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
// 复制图片
|
||||
func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, string) {
|
||||
// 是否已经复制过了
|
||||
@@ -222,7 +255,7 @@ func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, strin
|
||||
id := bson.NewObjectId();
|
||||
fileInfo.FileId = id
|
||||
fileId = id.Hex()
|
||||
Ok := this.AddImage(fileInfo, "", toUserId)
|
||||
Ok, _ := this.AddImage(fileInfo, "", toUserId, false)
|
||||
|
||||
if Ok {
|
||||
return Ok, id.Hex()
|
||||
|
||||
@@ -27,9 +27,12 @@ func (this *GroupService) AddGroup(userId, title string) (bool, info.Group) {
|
||||
// 删除分组
|
||||
// 判断是否有好友
|
||||
func (this *GroupService) DeleteGroup(userId, groupId string) (ok bool, msg string) {
|
||||
/*
|
||||
if db.Has(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)}) {
|
||||
return false, "hasUsers"
|
||||
return false, "groupHasUsers"
|
||||
}
|
||||
*/
|
||||
db.DeleteAll(db.GroupUsers, bson.M{"GroupId": bson.ObjectIdHex(groupId)})
|
||||
return db.DeleteByIdAndUserId(db.Groups, groupId, userId), ""
|
||||
|
||||
// TODO 删除分组后, 在shareNote, shareNotebook中也要删除
|
||||
|
||||
@@ -33,7 +33,8 @@ func (this *NoteContentHistoryService) AddHistory(noteId, userId string, eachHis
|
||||
// TODO
|
||||
l := len(history.Histories)
|
||||
if l >= maxSize {
|
||||
history.Histories = history.Histories[l-maxSize:]
|
||||
// history.Histories = history.Histories[l-maxSize:] // BUG, 致使都是以前的
|
||||
history.Histories = history.Histories[:maxSize]
|
||||
}
|
||||
newHistory := []info.EachHistory{eachHistory}
|
||||
newHistory = append(newHistory, history.Histories...) // 在开头加了, 最近的在最前
|
||||
@@ -61,4 +62,4 @@ func (this *NoteContentHistoryService) ListHistories(noteId, userId string) []in
|
||||
histories := info.NoteContentHistory{}
|
||||
db.GetByIdAndUserId(db.NoteContentHistories, noteId, userId, &histories)
|
||||
return histories.Histories
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,17 @@ func (this *NoteService) GetNote(noteId, userId string) (note info.Note) {
|
||||
db.GetByIdAndUserId(db.Notes, noteId, userId, ¬e)
|
||||
return
|
||||
}
|
||||
|
||||
//通过附件id得到note
|
||||
func (this *NoteService) GetNoteByAttachId(attachId string) (note info.Note) {
|
||||
attach := info.Attach{}
|
||||
db.Get(db.Attachs, attachId, &attach)
|
||||
note = info.Note{}
|
||||
noteId := attach.NoteId
|
||||
db.Get(db.Notes, noteId.Hex(), ¬e)
|
||||
return
|
||||
}
|
||||
|
||||
// fileService调用
|
||||
func (this *NoteService) GetNoteById(noteId string) (note info.Note) {
|
||||
note = info.Note{}
|
||||
|
||||
@@ -17,6 +17,13 @@ func (this *SessionService) Update(sessionId, key string, value interface{}) boo
|
||||
return db.UpdateByQMap(db.Sessions, bson.M{"SessionId": sessionId},
|
||||
bson.M{key: value, "UpdatedTime": time.Now()})
|
||||
}
|
||||
|
||||
func (this *SessionService) UpdateToken(sessionId, key string, value interface{}) bool {
|
||||
return db.UpdateByQMap(db.Sessions, bson.M{"SessionId": sessionId},
|
||||
bson.M{key: value, "UpdatedTime": time.Now(), "TokenTime": time.Now()})
|
||||
}
|
||||
|
||||
|
||||
// 注销时清空session
|
||||
func (this *SessionService) Clear(sessionId string) bool {
|
||||
return db.Delete(db.Sessions, bson.M{"SessionId": sessionId})
|
||||
@@ -69,3 +76,19 @@ func (this *SessionService) SetCaptcha(sessionId, captcha string) bool {
|
||||
Log(ok)
|
||||
return ok
|
||||
}
|
||||
|
||||
|
||||
// 附件token
|
||||
func (this *SessionService) GetToken(sessionId string) string {
|
||||
session := this.Get(sessionId)
|
||||
return session.Token
|
||||
}
|
||||
|
||||
func (this *SessionService) SetToken(sessionId, token string) bool {
|
||||
this.Get(sessionId)
|
||||
Log(sessionId)
|
||||
Log(token)
|
||||
ok := this.UpdateToken(sessionId, "Token", token)
|
||||
Log(ok)
|
||||
return ok
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ import (
|
||||
"gopkg.in/mgo.v2/bson"
|
||||
"time"
|
||||
"sort"
|
||||
"math/rand"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 共享Notebook, Note服务
|
||||
@@ -49,6 +52,7 @@ func (this *ShareService) getOrQ(userId string) bson.M {
|
||||
return q
|
||||
}
|
||||
|
||||
// 得到共享给我的笔记本和用户(谁共享给了我)
|
||||
func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksByUser, []info.User) {
|
||||
// 得到共享给我的用户s信息
|
||||
// 得到我参与的组织
|
||||
@@ -60,7 +64,7 @@ func (this *ShareService) GetShareNotebooks(userId string) (info.ShareNotebooksB
|
||||
db.Distinct(db.ShareNotes, q, "UserId", &userIds1)
|
||||
|
||||
userIds2 := []bson.ObjectId{}
|
||||
db.Distinct(db.ShareNotebooks, q, "UserId", &userIds1)
|
||||
db.Distinct(db.ShareNotebooks, q, "UserId", &userIds2) // BUG之前是userId1, 2014/12/29
|
||||
|
||||
userIds := append(userIds1, userIds2...)
|
||||
userInfos := userService.GetUserInfosOrderBySeq(userIds);
|
||||
@@ -336,12 +340,14 @@ func (this *ShareService) AddShareNote(noteId string, perm int, userId, email st
|
||||
"ToUserId": bson.ObjectIdHex(toUserId),
|
||||
});
|
||||
|
||||
|
||||
shareNote := info.ShareNote{NoteId: bson.ObjectIdHex(noteId),
|
||||
UserId: bson.ObjectIdHex(userId),
|
||||
ToUserId: bson.ObjectIdHex(toUserId),
|
||||
Perm: perm,
|
||||
CreatedTime: time.Now(),
|
||||
}
|
||||
|
||||
return db.Insert(db.ShareNotes, shareNote), "", toUserId
|
||||
}
|
||||
|
||||
@@ -776,3 +782,59 @@ func (this *ShareService) DeleteShareNotebookGroup(userId, notebookId, groupId s
|
||||
"ToGroupId": bson.ObjectIdHex(groupId),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
func (this *ShareService) GenSharePass(noteId string) (int, bool) {
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
pass := 1000 + r.Intn(9000)
|
||||
|
||||
ok := db.Update(db.Notes, bson.M{"_id": bson.ObjectIdHex(noteId)}, bson.M{"$set": bson.M{"SharePass": pass}})
|
||||
return pass, ok
|
||||
}
|
||||
|
||||
func (this *ShareService) QuerySharePass(noteId string) int {
|
||||
note := &info.Note{}
|
||||
db.Get(db.Notes, noteId, note)
|
||||
|
||||
return note.SharePass
|
||||
}
|
||||
|
||||
func (this *ShareService) Verify4ShareNote(noteId string, sharePass int) (flag bool, note info.Note, noteContent info.NoteContent) {
|
||||
note = info.Note{}
|
||||
db.Get(db.Notes, noteId, ¬e)
|
||||
if note.SharePass == sharePass {
|
||||
note = noteService.GetNoteById(noteId)
|
||||
noteContent = noteService.GetNoteContent(noteId, note.UserId.Hex())
|
||||
flag = true
|
||||
} else {
|
||||
note = info.Note{}
|
||||
noteContent = info.NoteContent{}
|
||||
flag = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//把笔记中含有attachID的url后加上token,返回笔记中含有的attachids
|
||||
func (this *ShareService) AppendToken4URL(token, content string) (c string, attachIds map[string]bool) {
|
||||
re := regexp.MustCompile(`href=\"(.*?attachId.*?)\".*?data-mce-href=\"(.*?attachId.*?)\"`)
|
||||
re2 := regexp.MustCompile(`\"(.*?attachId.*?)\"`)
|
||||
|
||||
attachIds = map[string]bool{}
|
||||
s := re.ReplaceAllStringFunc(content, func(m string) string {
|
||||
idx := strings.Index(m, "attachId=") + len("attachId=")
|
||||
var ss []byte = []byte(m)
|
||||
attachId := string(ss[idx: idx + 24])
|
||||
attachIds[attachId] = true
|
||||
return re2.ReplaceAllString(m, `"${1}&token=` + token + `"`)
|
||||
})
|
||||
|
||||
re3 := regexp.MustCompile(`<img\s+src=\"(.*?fileId.*?)\".*?data-mce-src=\"(.*?fileId.*?)\"`)
|
||||
re4 := regexp.MustCompile(`\"(.*?fileId.*?)\"`)
|
||||
|
||||
c = re3.ReplaceAllStringFunc(s, func(m string) string {
|
||||
return re4.ReplaceAllString(m, `"${1}&token=` + token + `"`)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"regexp"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
@@ -127,7 +128,8 @@ func (this *ThemeService) CopyDefaultTheme(userBlog info.UserBlog) (ok bool, the
|
||||
// 设为active true
|
||||
func (this *ThemeService) NewThemeForFirst(userBlog info.UserBlog) (ok bool, themeId string) {
|
||||
ok, themeId = this.CopyDefaultTheme(userBlog)
|
||||
db.UpdateByQField(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, "IsActive", true)
|
||||
this.ActiveTheme(userBlog.UserId.Hex(), themeId)
|
||||
// db.UpdateByQField(db.Themes, bson.M{"_id": bson.ObjectIdHex(themeId)}, "IsActive", true)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -285,11 +287,15 @@ func (this *ThemeService) GetThemePath(userId, themeId string) string {
|
||||
}
|
||||
// 更新模板内容
|
||||
func (this *ThemeService) UpdateTplContent(userId, themeId, filename, content string) (ok bool, msg string) {
|
||||
path := this.GetThemeAbsolutePath(userId, themeId) + "/" + filename
|
||||
basePath := this.GetThemeAbsolutePath(userId, themeId)
|
||||
path := basePath + "/" + filename
|
||||
if strings.Contains(filename, ".html") {
|
||||
// 模板
|
||||
if ok, msg = this.mustTpl(filename, content); ok {
|
||||
ok = PutFileStrContent(path, content)
|
||||
Log(">>")
|
||||
if ok, msg = this.ValidateTheme(basePath, filename, content); ok {
|
||||
// 模板
|
||||
if ok, msg = this.mustTpl(filename, content); ok {
|
||||
ok = PutFileStrContent(path, content)
|
||||
}
|
||||
}
|
||||
return
|
||||
} else if filename == "theme.json" {
|
||||
@@ -410,6 +416,11 @@ func (this *ThemeService) ImportTheme(userId, path string) (ok bool, msg string)
|
||||
DeleteFile(targetPath)
|
||||
return
|
||||
}
|
||||
// 主题验证
|
||||
if ok, msg = this.ValidateTheme(targetPath, "", ""); !ok {
|
||||
DeleteFile(targetPath)
|
||||
return
|
||||
}
|
||||
// 解压成功, 那么新建之
|
||||
// 保存到数据库中
|
||||
theme, _ := this.getThemeConfig(targetPath)
|
||||
@@ -505,5 +516,119 @@ func (this *ThemeService) InstallTheme(userId, themeId string) (ok bool) {
|
||||
|
||||
ok = db.Insert(db.Themes, theme)
|
||||
|
||||
// 激活之
|
||||
this.ActiveTheme(userId, themeId);
|
||||
|
||||
return ok
|
||||
}
|
||||
|
||||
// 验证主题是否全法, 存在循环引用?
|
||||
// filename, newContent 表示在修改模板时要判断模板修改时是否有错误
|
||||
func (this *ThemeService) ValidateTheme(path string, filename, newContent string) (ok bool, msg string) {
|
||||
Log("theme Path")
|
||||
Log(path)
|
||||
// 建立一个有向图
|
||||
// 将该path下的所有文件提出, 得到文件的引用情况
|
||||
files := ListDir(path)
|
||||
LogJ(files);
|
||||
size := len(files)
|
||||
if(size > 100) {
|
||||
ok = false;
|
||||
msg = "tooManyFiles"
|
||||
return
|
||||
}
|
||||
/*
|
||||
111111111
|
||||
111000000
|
||||
*/
|
||||
vector := make([][]int, size)
|
||||
for i := 0; i < size; i++ {
|
||||
vector[i] = make([]int, size)
|
||||
}
|
||||
fileIndexMap := map[string]int{} // fileName => index
|
||||
fileContent := map[string]string{} // fileName => content
|
||||
index := 0
|
||||
// 得到文件内容, 和建立索引, 每个文件都有一个index, 对应数组位置
|
||||
for _, t := range files {
|
||||
if !strings.Contains(t, ".html") {
|
||||
continue;
|
||||
}
|
||||
if t != filename {
|
||||
fileBytes, err := ioutil.ReadFile(path + "/" + t)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
fileIndexMap[t] = index;
|
||||
// html内容
|
||||
fileStr := string(fileBytes)
|
||||
fileContent[t] = fileStr
|
||||
} else {
|
||||
fileIndexMap[t] = index
|
||||
fileContent[t] = newContent
|
||||
}
|
||||
index++
|
||||
}
|
||||
// 分析文件内容, 建立有向图
|
||||
reg, _ := regexp.Compile("{{ *template \"(.+?\\.html)\".*}}")
|
||||
for filename, content := range fileContent {
|
||||
thisIndex := fileIndexMap[filename]
|
||||
finds := reg.FindAllStringSubmatch(content, -1) // 子匹配
|
||||
LogJ(finds)
|
||||
// Log(content)
|
||||
if finds != nil && len(finds) > 0 {
|
||||
for _, includes := range finds {
|
||||
include := includes[1]
|
||||
includeIndex, has := fileIndexMap[include]
|
||||
Log(includeIndex)
|
||||
Log("??")
|
||||
Log(has)
|
||||
if has {
|
||||
vector[thisIndex][includeIndex] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogJ(vector)
|
||||
LogJ(fileIndexMap)
|
||||
// 建立图后, 判断是否有环
|
||||
if this.hasRound(vector, index) {
|
||||
ok = false
|
||||
msg = "themeValidHasRoundInclude"
|
||||
} else {
|
||||
ok = true
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 检测有向图是否有环, DFS
|
||||
func (this *ThemeService) hasRound(vector [][]int, size int) (ok bool) {
|
||||
for i := 0; i < size; i++ {
|
||||
visited := make([]int, size)
|
||||
if this.hasRoundEach(vector, i, size, visited) {
|
||||
Log(">>")
|
||||
Log(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 从每个节点出发, 判断是否有环
|
||||
func (this *ThemeService) hasRoundEach(vector [][]int, index int, size int, visited []int) (ok bool) {
|
||||
if visited[index] > 0 {
|
||||
Log("<")
|
||||
Log(index)
|
||||
return true
|
||||
}
|
||||
visited[index] = 1;
|
||||
// 遍历它的孩子
|
||||
for i := 0; i < size; i++ {
|
||||
if vector[index][i] > 0 {
|
||||
return this.hasRoundEach(vector, i, size, visited);
|
||||
}
|
||||
}
|
||||
visited[index] = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,13 @@ func (this *UserService) GetUsername(userId string) string {
|
||||
return user.Username
|
||||
}
|
||||
|
||||
// 得到用户名
|
||||
func (this *UserService) GetUsernameById(userId bson.ObjectId) string {
|
||||
user := info.User{}
|
||||
db.GetByQWithFields(db.Users, bson.M{"_id": userId}, []string{"Username"}, &user)
|
||||
return user.Username
|
||||
}
|
||||
|
||||
// 是否存在该用户 email
|
||||
func (this *UserService) IsExistsUser(email string) bool {
|
||||
if this.GetUserId(email) == "" {
|
||||
@@ -369,7 +376,7 @@ func (this *UserService) ThirdAddUser(userId, email, pwd string) (ok bool, msg s
|
||||
// 宽度
|
||||
func (this *UserService)UpdateColumnWidth(userId string, notebookWidth, noteListWidth, mdEditorWidth int) bool {
|
||||
return db.UpdateByQMap(db.Users, bson.M{"_id": bson.ObjectIdHex(userId)},
|
||||
bson.M{"NotebookWidth": notebookWidth, "NoteListWidth": noteListWidth, "mdEditorWidth": mdEditorWidth})
|
||||
bson.M{"NotebookWidth": notebookWidth, "NoteListWidth": noteListWidth, "MdEditorWidth": mdEditorWidth})
|
||||
}
|
||||
// 左侧是否隐藏
|
||||
func (this *UserService)UpdateLeftIsMin(userId string, leftIsMin bool) bool {
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
</section>
|
||||
<footer class="footer lt hidden-xs b-t b-light" style="min-height: initial;
|
||||
padding: 10px 15px;text-align:center;">
|
||||
<a href="http://leanote.com" target="_blank">leanote</a> © 2014
|
||||
<a href="http://leanote.com" target="_blank">leanote</a> © 2015
|
||||
<!--
|
||||
<a href="#nav" data-toggle="class:nav-xs" class="pull-right btn btn-sm btn-default btn-icon">
|
||||
<i class="fa fa-angle-left text">
|
||||
|
||||
63
app/views/errors/500-blog.html
Normal file
63
app/views/errors/500-blog.html
Normal file
@@ -0,0 +1,63 @@
|
||||
{{template "home/header_box.html" .}}
|
||||
|
||||
<section id="box">
|
||||
<div>
|
||||
<div>
|
||||
<h1 class="h text-white animated fadeInDownBig">ERROR!</h1>
|
||||
</div>
|
||||
<div id="errorBox">
|
||||
<p class="error-info">
|
||||
Sorry, you(not we) got an error. This error is just showing in blog preview for test.
|
||||
</p>
|
||||
|
||||
<div class="list-group m-b-sm bg-white m-b-lg">
|
||||
|
||||
{{with .Error}}
|
||||
<div id="header" class="block">
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{if .SourceType}}
|
||||
The {{.SourceType}} <strong>{{.Path}}</strong> does not compile: <strong>{{.Description}}</strong>
|
||||
{{else}}
|
||||
{{.Description}}
|
||||
{{end}}
|
||||
</p>
|
||||
</div>
|
||||
{{if .Path}}
|
||||
<div id="source" class="block">
|
||||
<h2>In {{.Path}}
|
||||
{{if .Line}}
|
||||
(around {{if .Line}}line {{.Line}}{{end}}{{if .Column}} column {{.Column}}{{end}})
|
||||
{{end}}
|
||||
</h2>
|
||||
{{range .ContextSource}}
|
||||
<div class="line {{if .IsError}}error{{end}}">
|
||||
<span class="lineNumber">{{.Line}}:</span>
|
||||
<pre>{{.Source}}</pre>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .MetaError}}
|
||||
<div id="source" class="block">
|
||||
<h2>Additionally, an error occurred while handling this error.</h2>
|
||||
<div class="line error">
|
||||
{{.MetaError}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div id="boxFooter">
|
||||
<p>
|
||||
<a href="/index">leanote</a> © 2014
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -44,7 +44,6 @@ function log(o) {
|
||||
-->
|
||||
<li><a href="/index#download" target="#download" class="smooth-scroll">{{msg . "download"}}</a> </li>
|
||||
<li><a href="/index#donate" target="#donate" class="smooth-scroll">{{msg . "donate"}}</a> </li>
|
||||
<li><a id="leanoteBlog" href="{{.leaUrl}}/index" target="_blank" title="lea++, leanote博客平台" class="">lea++</a></li>
|
||||
<li style="position: relative; margin-right: 3px;">
|
||||
<a href="http://bbs.leanote.com" target="_blank" class="">{{msg . "discussion"}}</a>
|
||||
<div class="red-circle" style=""></div>
|
||||
|
||||
@@ -100,7 +100,9 @@ $(function() {
|
||||
$("#registerBtn").html("{{msg . "ing"}}...").addClass("disabled");
|
||||
// hideMsg();
|
||||
|
||||
$.post("/doRegister", {email: email, pwd: pwd}, function(e) {
|
||||
var iu = "{{.iu}}";
|
||||
|
||||
$.post("/doRegister", {email: email, pwd: pwd, iu: iu}, function(e) {
|
||||
$("#registerBtn").html("{{msg . "register"}}").removeClass("disabled");
|
||||
if(e.Ok) {
|
||||
$("#registerBtn").html("{{msg . "registerSuccessAndRdirectToNote"}}");
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">
|
||||
{{if .page}}
|
||||
修改页面
|
||||
{{if .single}}
|
||||
{{msg . "updateSingle"}}
|
||||
{{else}}
|
||||
添加页面
|
||||
{{msg . "addSingle"}}
|
||||
{{end}}
|
||||
</h3></div>
|
||||
|
||||
<link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" type="text/css">
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<form id="formData">
|
||||
@@ -16,18 +16,18 @@
|
||||
<div class="alert alert-danger" id="baseMsg" style="display: none"></div>
|
||||
<input type="hidden" id="singleId" value="{{.single.SingleId.Hex}}" />
|
||||
<div class="form-group">
|
||||
<label>标题</label>
|
||||
<label>{{msg . "title"}}</label>
|
||||
<input type="text" class="form-control" id="title" name="title"
|
||||
value="{{.single.Title}}"
|
||||
data-rules='[
|
||||
{rule: "required", msg: "请输入页面标题"},
|
||||
{rule: "required", msg: "{{msg . "inputSingleTitle"}}"},
|
||||
]'
|
||||
data-msg_target="#baseMsg"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="content1">内容</label>
|
||||
<label for="content1">{{msg . "content"}}</label>
|
||||
<div id="popularToolbar"></div>
|
||||
<textarea id="content1" name="content">{{.single.Content}}</textarea>
|
||||
</div>
|
||||
@@ -41,9 +41,9 @@
|
||||
|
||||
</div>
|
||||
{{template "member/footer.html" .}}
|
||||
<script type="text/javascript" src="/tinymce/tinymce.min.js"></script>
|
||||
<script type="text/javascript" src="/tinymce/tinymce.js"></script>
|
||||
<script>
|
||||
var urlPrefix = "{{.siteUrl}}";
|
||||
var urlPrefix = "{{.siteUrl}}";
|
||||
$(function() {
|
||||
tinymce.init({
|
||||
selector : "#content1",
|
||||
@@ -55,7 +55,7 @@ $(function() {
|
||||
skin : "custom",
|
||||
plugins : [
|
||||
"advlist autolink link leanote_image lists charmap hr ",
|
||||
"searchreplace visualblocks visualchars leanote_code tabfocus",
|
||||
"searchreplace visualblocks visualchars tabfocus",
|
||||
"table contextmenu directionality textcolor paste fullpage textcolor"],
|
||||
toolbar1 : "formatselect |fontselect fontsizeselect| forecolor backcolor | bold italic underline strikethrough | bullist numlist |",
|
||||
menubar : false,
|
||||
|
||||
@@ -1,29 +1,26 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "baseInfoSet"}}</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg $ "basicInfoSet"}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<div class="col-sm-8">
|
||||
<div id="formData">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="alert alert-danger" id="baseMsg" style="display: none"></div>
|
||||
<div class="form-horizontal" role="form" id="userBlogForm">
|
||||
<div role="form" id="userBlogForm">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-sm-2 control-label">{{msg . "blogName"}}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="Title" name="Title"
|
||||
<label for="title" >{{msg . "blogName"}}</label>
|
||||
<input type="text" class="form-control" id="Title" name="Title"
|
||||
placeholder="eg: leanote's blog"
|
||||
value="{{if .userBlog.Title}}{{.userBlog.Title}}{{else}}{{.userInfo.Email}} 's blog{{end}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="logo" class="col-sm-2 control-label">{{msg . "blogLogo"}}</label>
|
||||
<div class="col-sm-10">
|
||||
<label for="logo">{{msg . "blogLogo"}}</label>
|
||||
<input type="hidden" name="Logo" id="Logo"
|
||||
value="{{.userBlog.Logo}}" />
|
||||
<form id="formLogo" action="{{$.siteUrl}}/file/uploadBlogLogo" method="post"
|
||||
<form id="formLogo" action="/file/uploadBlogLogo" method="post"
|
||||
enctype="multipart/form-data" target="logoTarget">
|
||||
<input type="file" class="form-control" id="logo2" name="file"
|
||||
onChange='$("#formLogo").submit();' />
|
||||
@@ -37,16 +34,13 @@
|
||||
</div>
|
||||
</form>
|
||||
<iframe id="logoTarget" name="logoTarget" src="#" style="display: none"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="subTitle" class="col-sm-2 control-label">{{msg . "blogDesc"}}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="SubTitle"
|
||||
<label for="subTitle">{{msg . "blogDesc"}}</label>
|
||||
<input type="text" class="form-control" id="SubTitle"
|
||||
name="SubTitle" value="{{.userBlog.SubTitle}}"
|
||||
placeholder="eg: leanote, Not Just A Notebook">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
@@ -1,29 +1,37 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">(笔记本)分类</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "cate"}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
分类是公开为博客的笔记本
|
||||
{{msg . "cateIsPublicNotebook"}}
|
||||
<br />
|
||||
拖动可排序
|
||||
{{if .notebooks}}
|
||||
{{msg . "dragAndSort"}}
|
||||
<ul class="list-group gutter list-group-lg list-group-sp sortable">
|
||||
{{range .notebooks}}
|
||||
<li class="list-group-item" draggable="true" data-id="{{.NotebookId.Hex}}">
|
||||
<span class="pull-left media-xs"><i class="fa fa-sort text-muted fa m-r-sm"></i></span>
|
||||
<div class="pull-right" style="margin-right: 10px">
|
||||
固定链接: /cate/<input data-id="{{.NotebookId.Hex}}" class="url-title" type="text" value="{{if .UrlTitle}}{{.UrlTitle|decodeUrlValue}}{{else}}{{.NotebookId.Hex}}{{end}}"/>
|
||||
{{msg $ "permanentLink"}}: /cate/<input data-id="{{.NotebookId.Hex}}" class="url-title" type="text" value="{{if .UrlTitle}}{{.UrlTitle|decodeUrlValue}}{{else}}{{.NotebookId.Hex}}{{end}}"/>
|
||||
</div>
|
||||
{{.Title}}
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
{{msg . "noCates"}}
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{if .notebooks}}
|
||||
<footer class="panel-footer text-right bg-light lter">
|
||||
<button type="submit" id="baseBtn" class="btn btn-success">{{msg . "submit"}}</button>
|
||||
<button type="submit" id="baseBtn" class="btn btn-success">{{msg . "saveSort"}}</button>
|
||||
</footer>
|
||||
{{end}}
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -36,7 +44,7 @@ $(function() {
|
||||
$(".list-group-item").each(function() {
|
||||
ids.push($(this).data("id"));
|
||||
});
|
||||
ajaxPost("/member/blog/", {cateIds: ids}, function(re){
|
||||
ajaxPost("/member/blog/upateCateIds", {cateIds: ids}, function(re){
|
||||
if(reIsOk(re)) {
|
||||
art.tips("Success");
|
||||
} else {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<input type="radio"
|
||||
name="commentType"
|
||||
value="default"
|
||||
{{if or (not .userBlog.CommentType) (eq .userBlog.CommentType "default")}}checked="checked"{{end}} > Default
|
||||
{{if or (not .userBlog.CommentType) (eq .userBlog.CommentType "default")}}checked="checked"{{end}} > {{msg $ "defaultComment"}}
|
||||
</label>
|
||||
|
||||
<label>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"><h3 class="m-b-none">文章列表</h3></div>
|
||||
<div class="m-b-md"><h3 class="m-b-none">{{msg . "postList"}}</h3></div>
|
||||
<style>
|
||||
.url-title {
|
||||
width: 260px;
|
||||
@@ -13,7 +13,7 @@
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="input-group search-group">
|
||||
<input type="text" class="input-sm form-control" placeholder="Title" id="keywords" value="{{.keywords}}" />
|
||||
<input type="text" class="input-sm form-control" placeholder="{{msg . "title"}}" id="keywords" value="{{.keywords}}" />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-sm btn-default" type="button" data-url="/member/blog/index">Search</button>
|
||||
</span>
|
||||
@@ -40,7 +40,7 @@
|
||||
style="width: 300px"
|
||||
{{sorterTh $url "urlTitle" .sorter}}
|
||||
>
|
||||
固定链接
|
||||
{{msg $ "permanentLink"}}
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
@@ -50,7 +50,7 @@
|
||||
<th
|
||||
{{sorterTh $url "publicTime" .sorter}}
|
||||
>
|
||||
发布日期
|
||||
{{msg . "publicTime"}}
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
@@ -61,7 +61,7 @@
|
||||
<th
|
||||
{{sorterTh $url "updatedTime" .sorter}}
|
||||
>
|
||||
更新日期
|
||||
{{msg . "updatedTime"}}
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
@@ -71,7 +71,7 @@
|
||||
<th
|
||||
{{sorterTh $url "createdTime" .sorter}}
|
||||
>
|
||||
创建日期
|
||||
{{msg . "createdTime"}}
|
||||
<span class="th-sort">
|
||||
<i class="fa fa-sort-down"></i>
|
||||
<i class="fa fa-sort-up"></i>
|
||||
@@ -114,13 +114,13 @@
|
||||
|
||||
<a
|
||||
{{if .HasSelfDefined}}
|
||||
title="已设置"
|
||||
title="{{msg $ "hasSelfDefined"}}"
|
||||
class="btn btn-sm btn-success"
|
||||
{{else}}
|
||||
title="未设置"
|
||||
title="{{msg $ "noSelfDefined"}}"
|
||||
class="btn btn-sm btn-default"
|
||||
{{end}}
|
||||
href="/member/blog/updateBlogAbstract?noteId={{.NoteId.Hex}}">摘要设置</a>
|
||||
href="/member/blog/updateBlogAbstract?noteId={{.NoteId.Hex}}">{{msg $ "setAbstract"}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">分页与排序设置</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg $ "pagingAndSort"}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
@@ -8,43 +8,35 @@
|
||||
<div class="panel-body">
|
||||
<div class="alert alert-danger" id="domainMsg" style="display: none"></div>
|
||||
|
||||
<form class="form-horizontal" role="form" id="dataFrom">
|
||||
|
||||
<form role="form" id="dataFrom">
|
||||
<div class="form-group">
|
||||
<label for="perPageSize" class="col-sm-2 control-label">每页记录数</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control"
|
||||
<label for="perPageSize">{{msg . "perPageSize"}}</label>
|
||||
<input type="text" class="form-control"
|
||||
placeholder="10"
|
||||
id="perPageSize"
|
||||
name="perPageSize"
|
||||
value="{{.userBlog.PerPageSize}}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="perPageSize" class="col-sm-2 control-label">排序字段</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control"
|
||||
id="sortField"
|
||||
name="sortField"
|
||||
value="">
|
||||
<option value="PublicTime" {{if eq $.userBlog.SortField "PublicTime"}}selected{{end}}>公开为博客时间</option>
|
||||
<option value="CreatedTime" {{if eq $.userBlog.SortField "CreatedTimeTime"}}selected{{end}}>创建时间</option>
|
||||
<option value="UpdatedTime" {{if eq $.userBlog.SortField "UpdatedTime"}}selected{{end}}>更新时间</option>
|
||||
<option value="Title" {{if eq $.userBlog.SortField "Title"}}selected{{end}}>标题</option>
|
||||
</select>
|
||||
</div>
|
||||
<label for="perPageSize" >{{msg . "sortField"}}</label>
|
||||
<select class="form-control"
|
||||
id="sortField"
|
||||
name="sortField"
|
||||
value="">
|
||||
<option value="PublicTime" {{if eq $.userBlog.SortField "PublicTime"}}selected{{end}}>{{msg $ "publicTime"}}</option>
|
||||
<option value="CreatedTime" {{if eq $.userBlog.SortField "CreatedTimeTime"}}selected{{end}}>{{msg $ "createdTime"}}</option>
|
||||
<option value="UpdatedTime" {{if eq $.userBlog.SortField "UpdatedTime"}}selected{{end}}>{{msg $ "updatedTime"}}</option>
|
||||
<option value="Title" {{if eq $.userBlog.SortField "Title"}}selected{{end}}>{{msg . "title"}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">排序类型</label>
|
||||
<div class="col-sm-10" style="margin-top: 5px;">
|
||||
<label><input type="radio" name="isAsc" value="0" {{if not .userBlog.IsAsc}}checked{{end}}> 降序</label>
|
||||
<label><input type="radio" name="isAsc" value="1" {{if .userBlog.IsAsc}}checked{{end}}> 升序</label>
|
||||
<label>{{msg $ "sortType"}}</label>
|
||||
<div>
|
||||
<label><input type="radio" name="isAsc" value="0" {{if not .userBlog.IsAsc}}checked{{end}}> {{msg . "desc"}}</label>
|
||||
<label><input type="radio" name="isAsc" value="1" {{if .userBlog.IsAsc}}checked{{end}}> {{msg . "asc"}}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<footer class="panel-footer text-right bg-light lter">
|
||||
<button type="submit" id="baseBtn" class="btn btn-success">{{msg . "submit"}}</button>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">单页面</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "single"}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
您可以添加多个单页面
|
||||
<a href="/member/blog/addOrUpdateSingle" id="addBtn" class="btn btn-success">添加页面</a>
|
||||
{{msg $ "singleTips"}}
|
||||
<a href="/member/blog/addOrUpdateSingle" id="addBtn" class="btn btn-success">{{msg $ "addSingle"}}</a>
|
||||
</p>
|
||||
<ul class="list-group gutter list-group-lg list-group-sp sortable">
|
||||
{{range .singles}}
|
||||
@@ -18,7 +18,7 @@
|
||||
<a href="#"><i class="fa fa-times icon-muted fa-fw page-delete" data-id="{{.SingleId}}"></i></a>
|
||||
</span>
|
||||
<div class="pull-right" style="margin-right: 10px">
|
||||
固定链接: /single/<input data-id="{{.SingleId}}" class="url-title" type="text" value="{{if .UrlTitle}}{{.UrlTitle|decodeUrlValue}}{{else}}{{.SingleId}}{{end}}"/>
|
||||
{{msg $ "permanentLink"}}: /single/<input data-id="{{.SingleId}}" class="url-title" type="text" value="{{if .UrlTitle}}{{.UrlTitle|decodeUrlValue}}{{else}}{{.SingleId}}{{end}}"/>
|
||||
</div>
|
||||
<div class="clear">
|
||||
{{.Title}}
|
||||
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
{{if .singles}}
|
||||
<footer class="panel-footer text-right bg-light lter">
|
||||
<button type="submit" id="baseBtn" class="btn btn-success">保存排序</button>
|
||||
<button type="submit" id="baseBtn" class="btn btn-success">{{msg . "saveSort"}}</button>
|
||||
</footer>
|
||||
{{end}}
|
||||
</section>
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
</div>
|
||||
{{template "member/footer.html" .}}
|
||||
<script type="text/javascript" src="{{.siteUrl}}/public/member/js/jquery.sortable.js"></script>
|
||||
<script type="text/javascript" src="/public/member/js/jquery.sortable.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
$("#baseBtn").click(function(){
|
||||
@@ -79,7 +79,7 @@ $(function() {
|
||||
art.alert(re.Msg || "error");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
<div class="m-b-md clearfix">
|
||||
<h3 class="m-b-none">
|
||||
{{msg . "themeSet"}}
|
||||
<small>(<a href="http://blog.leanote.com/post/545f1a5c380782565e000000" target="_blank">{{msg . "needHelp"}}</a>)</small>
|
||||
<small>
|
||||
(<a href="http://blog.leanote.com/post/545f1a5c380782565e000000" target="_blank">{{msg . "needHelp"}}</a>
|
||||
<a target="_blank" href="https://github.com/leanote/leanote/wiki/leanote-blog-theme-api">Leanote Blog Theme Api</a>)
|
||||
</small>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 theme-container">
|
||||
<section class="panel panel-default">
|
||||
@@ -12,9 +16,9 @@
|
||||
<div>
|
||||
<form id="uploadAvatar" method="post" action="/member/blog/importTheme" enctype="multipart/form-data">
|
||||
<div id="dropAvatar" class="dropzone">
|
||||
<a class="btn btn-default btn-new" href="/member/blog/newTheme"><span class="fa fa-plus"></span> 新建主题</a>
|
||||
<a class="btn btn-default btn-new" href="/member/blog/newTheme"><span class="fa fa-plus"></span> {{msg . "addTheme"}}</a>
|
||||
<a class="btn btn-success btn-choose-file">
|
||||
<span class="fa fa-upload"></span> 导入主题(.zip)
|
||||
<span class="fa fa-upload"></span> {{msg . "importTheme"}}(.zip)
|
||||
</a>
|
||||
<input type="file" name="file" multiple/>
|
||||
<div id="avatarUploadMsg"></div>
|
||||
@@ -22,10 +26,10 @@
|
||||
</form>
|
||||
</div>
|
||||
<p>
|
||||
当前主题:
|
||||
{{msg . "currentTheme"}}:
|
||||
</p>
|
||||
<ul class="themes">
|
||||
<li class="theme">
|
||||
<div class="themes clearfix">
|
||||
<div class="theme pull-left">
|
||||
<a class="choose-theme" data-method="put" href="#" rel="nofollow">
|
||||
<div class="theme-thumb thumb active-theme">
|
||||
<img src="/{{.activeTheme.Path}}/images/screenshot.png" alt="preview">
|
||||
@@ -37,17 +41,26 @@
|
||||
</span>
|
||||
<div class="theme-btns">
|
||||
<div class="btn-group" data-id="{{.activeTheme.ThemeId.Hex}}">
|
||||
<a class="btn btn-default btn-sm btn-export"><span class="fa fa-download"></span> 导出</a>
|
||||
<a class="btn btn-default btn-sm" href="{{$.siteUrl}}/preview?themeId={{.activeTheme.ThemeId.Hex}}" target="_blank"><span class="fa fa-eye"></span> 预览</a>
|
||||
<a class="btn btn-primary btn-sm" target="_blank" href="/member/blog/updateTheme?themeId={{if .activeTheme.ThemeId}}{{.activeTheme.ThemeId.Hex}}{{end}}"><span class="fa fa-pencil"></span> 编辑</a>
|
||||
<a class="btn btn-default btn-sm btn-export"><span class="fa fa-download"></span> {{msg $ "export"}}</a>
|
||||
<!-- 必须是自己的主题 -->
|
||||
{{if .activeTheme.ThemeId}}
|
||||
<a class="btn btn-default btn-sm" href="{{$.siteUrl}}/preview?themeId={{.activeTheme.ThemeId.Hex}}" target="_blank"><span class="fa fa-eye"></span> {{msg $ "preview"}}</a>
|
||||
{{end}}
|
||||
<a class="btn btn-primary btn-sm" target="_blank" href="/member/blog/updateTheme?themeId={{if .activeTheme.ThemeId}}{{.activeTheme.ThemeId.Hex}}{{end}}"><span class="fa fa-pencil"></span> {{msg $ "edit"}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{if .activeTheme.Info.Desc}}
|
||||
<!-- 描述 -->
|
||||
<div class="pull-left theme-desc">
|
||||
{{.activeTheme.Info.Desc|raw}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<p>
|
||||
我的其它主题:
|
||||
{{msg . "myOtherThemes"}}:
|
||||
</p>
|
||||
<ul class="themes">
|
||||
{{range $.otherThemes}}
|
||||
@@ -56,6 +69,11 @@
|
||||
<a class="choose-theme" data-method="put" href="#" rel="nofollow">
|
||||
<div class="theme-thumb thumb">
|
||||
<img src="/{{.Path}}/images/screenshot.png" alt="preview">
|
||||
{{if .Info.Desc}}
|
||||
<div class="theme-desc-mask">
|
||||
{{.Info.Desc|raw}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<span class="theme-title">{{.Name}}</span>
|
||||
</a>
|
||||
@@ -64,11 +82,11 @@
|
||||
</span>
|
||||
<div class="theme-btns">
|
||||
<div class="btn-group" data-id="{{.ThemeId.Hex}}">
|
||||
<a class="btn btn-default btn-sm btn-delete" data-loading-text="..."><span class="fa fa-remove"></span> 删除</a>
|
||||
<a class="btn btn-default btn-sm btn-export"><span class="fa fa-download"></span> 导出</a>
|
||||
<a class="btn btn-default btn-sm" href="{{$.siteUrl}}/preview?themeId={{.ThemeId.Hex}}" target="_blank"><span class="fa fa-eye"></span> 预览</a>
|
||||
<a class="btn btn-default btn-sm" target="_blank" href="/member/blog/updateTheme?themeId={{.ThemeId.Hex}}"><span class="fa fa-pencil"></span> 编辑</a>
|
||||
<a class="btn btn-primary btn-sm btn-active" data-loading-text="..."><span class="fa fa-check"></span> 使用</a>
|
||||
<a class="btn btn-default btn-sm btn-delete" data-loading-text="..."><span class="fa fa-remove"></span> {{msg $ "delete"}}</a>
|
||||
<a class="btn btn-default btn-sm btn-export"><span class="fa fa-download"></span> {{msg $ "export"}}</a>
|
||||
<a class="btn btn-default btn-sm" href="{{$.siteUrl}}/preview?themeId={{.ThemeId.Hex}}" target="_blank"><span class="fa fa-eye"></span> {{msg $ "preview"}}</a>
|
||||
<a class="btn btn-default btn-sm" target="_blank" href="/member/blog/updateTheme?themeId={{.ThemeId.Hex}}"><span class="fa fa-pencil"></span> {{msg $ "edit"}}</a>
|
||||
<a class="btn btn-primary btn-sm btn-active" data-loading-text="..."><span class="fa fa-check"></span> {{msg $ "use"}}</a>
|
||||
{{if $.isAdmin}}
|
||||
<a class="btn btn-default btn-sm btn-public" data-loading-text="...">
|
||||
{{if .IsDefault}}
|
||||
@@ -83,13 +101,13 @@
|
||||
</li>
|
||||
{{end}}
|
||||
{{else}}
|
||||
无
|
||||
{{msg $ "none"}}
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
<hr />
|
||||
<p>
|
||||
leanote主题市场:
|
||||
{{msg . "leanoteThemeMarket"}}:
|
||||
</p>
|
||||
<ul class="themes">
|
||||
{{range $.optionThemes}}
|
||||
@@ -97,6 +115,11 @@
|
||||
<a class="choose-theme" data-method="put" href="#" rel="nofollow">
|
||||
<div class="theme-thumb thumb">
|
||||
<img src="/{{.Path}}/images/screenshot.png" alt="preview">
|
||||
{{if .Info.Desc}}
|
||||
<div class="theme-desc-mask">
|
||||
{{.Info.Desc|raw}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<span class="theme-title">{{.Name}}</span>
|
||||
</a>
|
||||
@@ -104,7 +127,7 @@
|
||||
By: <a href="{{.AuthorUrl}}" target="_blank">{{.Author}}</a>
|
||||
</span>
|
||||
<p class="theme-btns" data-id="{{.ThemeId.Hex}}">
|
||||
<a class="btn btn-primary btn-sm btn-install"><span class="fa fa-gear"></span> 安装</a>
|
||||
<a class="btn btn-primary btn-sm btn-install"><span class="fa fa-gear"></span> {{msg $ "install"}}</a>
|
||||
</p>
|
||||
</li>
|
||||
{{end}}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" type="text/css">
|
||||
<link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" type="text/css">
|
||||
<div class="row">
|
||||
<div class="col-sm-10">
|
||||
<form id="formData">
|
||||
@@ -61,7 +61,7 @@
|
||||
{{template "member/footer.html" .}}
|
||||
<script type="text/javascript" src="/tinymce/tinymce.js"></script>
|
||||
<script>
|
||||
var UrlPrefix = "{{.siteUrl}}";
|
||||
var UrlPrefix = "{{.siteUrl}}";
|
||||
$(function() {
|
||||
tinymce.init({
|
||||
selector : "#content1",
|
||||
@@ -73,9 +73,9 @@ $(function() {
|
||||
skin : "custom",
|
||||
plugins : [
|
||||
"advlist autolink link leanote_image lists charmap hr ",
|
||||
"searchreplace visualblocks visualchars leanote_code tabfocus",
|
||||
"searchreplace visualblocks visualchars tabfocus",
|
||||
"table contextmenu directionality textcolor paste fullpage textcolor"],
|
||||
toolbar1 : "formatselect |fontselect fontsizeselect| forecolor backcolor | bold italic underline strikethrough | bullist numlist | leanote_code",
|
||||
toolbar1 : "formatselect |fontselect fontsizeselect| forecolor backcolor | bold italic underline strikethrough | bullist numlist",
|
||||
menubar : false,
|
||||
statusbar : false,
|
||||
font_formats : "Arial=arial,helvetica,sans-serif;"
|
||||
|
||||
@@ -2,13 +2,18 @@
|
||||
<div class="m-b-md">
|
||||
<h3 class="m-b-none">
|
||||
{{if .isNew}}
|
||||
新建主题
|
||||
{{msg $ "addTheme"}}
|
||||
{{else}}
|
||||
编辑主题
|
||||
{{msg $ "updateTheme"}}
|
||||
-
|
||||
{{.theme.Name}}
|
||||
{{end}}
|
||||
<a class="btn btn-default" href="{{$.siteUrl}}/preview?themeId={{.themeId}}" target="_blank"><span class="fa fa-eye"></span> 预览</a>
|
||||
<a class="btn btn-default" href="{{$.siteUrl}}/preview?themeId={{.themeId}}" target="_blank"><span class="fa fa-eye"></span> {{msg . "preview"}}</a>
|
||||
|
||||
<small>
|
||||
(<a href="http://blog.leanote.com/post/545f1a5c380782565e000000" target="_blank">{{msg . "needHelp"}}</a>
|
||||
<a target="_blank" href="https://github.com/leanote/leanote/wiki/leanote-blog-theme-api">Leanote Blog Theme Api</a>)
|
||||
</small>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
@@ -42,7 +47,7 @@
|
||||
<div class="col-sm-4">
|
||||
<section class="panel panel-default">
|
||||
<header class="panel-heading">
|
||||
模板, 样式, 脚本:
|
||||
{{msg . "tplStyleScript"}}:
|
||||
</header>
|
||||
<div class="panel-body" style="height:430px;overflow: auto;">
|
||||
|
||||
@@ -58,14 +63,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<footer class="panel-footer text-right bg-light lter">
|
||||
<a class="btn btn-default" id="newFile">新建文件</a>
|
||||
<a class="btn btn-default" id="newFile">{{msg . "newFile"}}</a>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<section class="panel panel-default">
|
||||
<header class="panel-heading">
|
||||
当前文件: <span id="curTpl">header.html</span>
|
||||
{{msg . "currentFile"}}: <span id="curTpl">header.html</span>
|
||||
<span id="msg"></span>
|
||||
</header>
|
||||
<div class="panel-body">
|
||||
@@ -82,7 +87,7 @@
|
||||
<div class="col-sm-12">
|
||||
<section class="panel panel-default">
|
||||
<header class="panel-heading">
|
||||
图片: images/
|
||||
{{msg . "image"}}: images/
|
||||
</header>
|
||||
<div class="panel-body">
|
||||
<ul class="image-list" id="imageList">
|
||||
@@ -102,7 +107,7 @@
|
||||
</div>
|
||||
|
||||
{{template "member/footer.html" .}}
|
||||
<script src="/public/member/js/ace/ace.js" type="text/javascript"></script>
|
||||
<script src="/public/libs/ace/ace.js" type="text/javascript"></script>
|
||||
<script>
|
||||
var editor = ace.edit("tplContent");
|
||||
editor.setTheme("ace/theme/tomorrow");
|
||||
@@ -118,7 +123,7 @@ var theme = {
|
||||
saveBtnO: $("#saveBtn"),
|
||||
newFileO: $("#newFile"),
|
||||
curTpl: "",
|
||||
tplInfos: {"header.html": "头部", "footer.html": "底部", "index.html": "首页", "cate.html": "分类页", "search.html": "搜索页", "single.html": "单页", "archive.html": "归档页", "post.html": "文章页", "tags.html": "标签页", "tag_posts.html": "标签文章页", "share_comment.html": "分享评论", "404.html":"404", "theme.json": "主题配置", "paging.html": "分页", "highlight.html": "高亮"},
|
||||
tplInfos: {"header.html": "{{msg . "header"}}", "footer.html": "{{msg . "footer"}}", "index.html": "{{msg . "header"}}", "cate.html": "{{msg . "cate"}}", "search.html": "{{msg . "search"}}", "single.html": "{{msg . "single"}}", "archive.html": "{{msg . "archive"}}", "post.html": "{{msg . "post"}}", "tags.html": "{{msg . "tags"}}", "tag_posts.html": "{{msg . "tag_posts"}}", "share_comment.html": "{{msg . "share_comment"}}", "404.html":"404", "theme.json": "{{msg . "themeJson"}}", "paging.html": "{{msg . "paging"}}", "highlight.html": "{{msg . "highlight"}}"},
|
||||
init: function() {
|
||||
var self = this;
|
||||
self.showTplInfo();
|
||||
@@ -183,11 +188,11 @@ var theme = {
|
||||
info = self.tplInfos[file];
|
||||
if(!info) {
|
||||
if(file.indexOf(".css") > 0) {
|
||||
info = "样式";
|
||||
info = "{{msg . "style"}}";
|
||||
} else if(file.indexOf(".js") > 0) {
|
||||
info = "脚本";
|
||||
info = "{{msg . "script"}}";
|
||||
} else if(file.indexOf(".html") > 0) {
|
||||
info = "模板";
|
||||
info = "{{msg . "tpl"}}";
|
||||
}
|
||||
} else {
|
||||
$(this).find(".remove-file").remove();
|
||||
@@ -209,7 +214,7 @@ var theme = {
|
||||
if(t) {
|
||||
t.button("loading");
|
||||
}
|
||||
self.msgO.html("正在保存...");
|
||||
self.msgO.html("...");
|
||||
ajaxPost("/member/blog/updateTplContent", {themeId: themeId, filename: self.curTpl, content: content}, function(re) {
|
||||
if(t) {
|
||||
t.button("reset");
|
||||
@@ -217,7 +222,7 @@ var theme = {
|
||||
if(reIsOk(re)) {
|
||||
self.cache[filename] = content;
|
||||
// art.tips("Success");
|
||||
self.msgO.html("保存成功")
|
||||
self.msgO.html("{{msg . "saveSuccess"}}")
|
||||
setTimeout(function() {
|
||||
self.msgO.html("");
|
||||
}, 3000);
|
||||
|
||||
@@ -8,17 +8,19 @@
|
||||
width: 200px;
|
||||
}
|
||||
</style>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">项目组/成员</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "group"}}</h3></div>
|
||||
|
||||
<p>
|
||||
<a class="btn btn-default btn-add-group"><span class="fa fa-plus"></span> 新建分组</a>
|
||||
<a class="btn btn-default btn-add-group"><span class="fa fa-plus"></span> {{msg . "newGroup"}}</a>
|
||||
</p>
|
||||
|
||||
|
||||
<script type="text/x-jsrender" id="tUser">
|
||||
<li class="list-group-item" data-id="[[:UserId]]">
|
||||
[[:Username]] [[if Email != Username]]([[:Email]])[[/if]]
|
||||
<span class="fa fa-remove pull-right text-xs m-t-sm"></span>
|
||||
<a title="{{msg . "deleteMember"}}" class="delete-user">
|
||||
<span class="fa fa-remove pull-right text-xs m-t-sm"></span>
|
||||
</a>
|
||||
</li>
|
||||
</script>
|
||||
|
||||
@@ -30,7 +32,7 @@
|
||||
<div class="clear">
|
||||
<div class="h3 m-t-xs m-b-xs text-white">
|
||||
<input type="text" data-ever="[[:Title]]" value="[[:Title]]" class="group-title" />
|
||||
<a title="删除分组" class="delete-group">
|
||||
<a title="{{msg . "deleteGroup"}}" class="delete-group">
|
||||
<i class="fa fa-remove text-white pull-right text-xs m-t-sm"></i>
|
||||
</a>
|
||||
</div>
|
||||
@@ -39,7 +41,7 @@
|
||||
</header>
|
||||
<ul class="list-group no-radius">
|
||||
<li class="list-group-item">
|
||||
<input type="text" class="add-user-input form-control" placeholder="输入用户名或邮箱添加成员" />
|
||||
<input type="text" class="add-user-input form-control" placeholder="{{msg . "addMemberTips"}}" />
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -57,7 +59,7 @@
|
||||
<div class="clear">
|
||||
<div class="h3 m-t-xs m-b-xs text-white">
|
||||
<input type="text" data-ever="{{.Title}}" value="{{.Title}}" class="group-title" />
|
||||
<a title="删除分组" class="delete-group">
|
||||
<a title="{{msg $ "deleteGroup"}}" class="delete-group">
|
||||
<i class="fa fa-remove text-white pull-right text-xs m-t-sm"></i>
|
||||
</a>
|
||||
</div>
|
||||
@@ -69,13 +71,13 @@
|
||||
{{range .Users}}
|
||||
<li class="list-group-item" data-id="{{.UserId.Hex}}">
|
||||
{{.Username}} {{if not (eq .Email .Username)}}({{.Email}}){{end}}
|
||||
<a title="删除成员" class="delete-user">
|
||||
<a title="{{msg $ "deleteMember"}}" class="delete-user">
|
||||
<span class="fa fa-remove pull-right text-xs m-t-sm"></span>
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
||||
<li class="list-group-item">
|
||||
<input type="text" class="add-user-input form-control" placeholder="输入用户名或邮箱添加成员" />
|
||||
<input type="text" class="add-user-input form-control" placeholder="{{msg $ "addMemberTips"}}" />
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -85,7 +87,7 @@
|
||||
</div>
|
||||
|
||||
{{template "member/footer.html" .}}
|
||||
<script src="http://leanote.com/public/blog/js/jsrender.js"></script>
|
||||
<script src="/public/blog/js/jsrender.js"></script>
|
||||
<script>
|
||||
var group = {
|
||||
tGroupO: $("#tGroup"),
|
||||
@@ -111,7 +113,7 @@ var group = {
|
||||
addGroupEvent: function() {
|
||||
var self = this;
|
||||
$('.btn-add-group').click(function() {
|
||||
ajaxPost("/member/group/addGroup", {title: "分组名"}, function(re) {
|
||||
ajaxPost("/member/group/addGroup", {title: "Group Title"}, function(re) {
|
||||
if(reIsOk(re)) {
|
||||
var group = re.Item;
|
||||
self.groupsO.prepend(self.tGroupO.render(group))
|
||||
@@ -217,4 +219,4 @@ $(function() {
|
||||
});
|
||||
|
||||
</script>
|
||||
{{template "member/end.html" .}}
|
||||
{{template "member/end.html" .}}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{.userInfo.Username}}, 欢迎来到leanote</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{.userInfo.Username}}, {{msg . "welcomeToLeanote"}}.</h3></div>
|
||||
|
||||
<section class="panel panel-default">
|
||||
<div class="row m-l-none m-r-none bg-light lter">
|
||||
@@ -26,11 +26,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 最新动态 -->
|
||||
<section class="panel panel-default">
|
||||
<h4 class="font-thin padder">
|
||||
Leanote 动态
|
||||
{{msg . "leanoteEvents"}}
|
||||
</h4>
|
||||
<ul class="list-group" id="eventsList"></ul>
|
||||
</section>
|
||||
|
||||
@@ -26,45 +26,47 @@
|
||||
</i>
|
||||
</span>
|
||||
<span>
|
||||
帐户信息
|
||||
{{msg . "accountInfo"}}
|
||||
</span>
|
||||
</a>
|
||||
<!-- 导航列表 -->
|
||||
<ul class="nav lt">
|
||||
{{if $.userInfo.Email}}
|
||||
<li>
|
||||
<a href="/member/user/username">
|
||||
<span>
|
||||
用户名
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/member/user/avatar">
|
||||
<span>
|
||||
头像
|
||||
{{msg . "avatar"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{{if $.userInfo.Email}}
|
||||
<li>
|
||||
<a href="/member/user/username">
|
||||
<span>
|
||||
{{msg . "username"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/member/user/email">
|
||||
<span>
|
||||
邮箱
|
||||
{{msg . "email"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/member/user/password">
|
||||
<span>
|
||||
密码
|
||||
{{msg . "password"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{{else}}
|
||||
<li>
|
||||
<a href="/member/user/add_account">
|
||||
<a href="/member/user/addAccount">
|
||||
<span>
|
||||
添加leanote帐户
|
||||
{{msg . "addLeanoteAccount"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -85,14 +87,14 @@
|
||||
</i>
|
||||
</span>
|
||||
<span>
|
||||
博客
|
||||
{{msg . "blog"}}
|
||||
</span>
|
||||
</a>
|
||||
<ul class="nav lt">
|
||||
<li>
|
||||
<a href="/member/blog/index">
|
||||
<span>
|
||||
文章列表
|
||||
{{msg . "postList"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -100,42 +102,43 @@
|
||||
<li>
|
||||
<a href="/member/blog/base">
|
||||
<span>
|
||||
基本信息
|
||||
{{msg . "basicInfoSet"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/member/blog/comment">
|
||||
<span>
|
||||
评论
|
||||
{{msg . "comment"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/member/blog/cate">
|
||||
<span>
|
||||
分类
|
||||
{{msg . "cate"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/member/blog/single">
|
||||
<span>
|
||||
单页面
|
||||
{{msg . "single"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/member/blog/paging">
|
||||
<span>
|
||||
分页与排序设置
|
||||
{{msg . "pagingAndSort"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/member/blog/theme">
|
||||
<span>
|
||||
主题
|
||||
{{msg . "theme"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -149,9 +152,9 @@
|
||||
</b>
|
||||
</i>
|
||||
<span>
|
||||
项目组/成员
|
||||
{{msg . "group"}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</nav>
|
||||
@@ -27,11 +27,6 @@
|
||||
</div>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right m-n hidden-xs nav-user">
|
||||
<li class="hidden-xs">
|
||||
<a href="http://lea.leanote.com" class="dk" target="_blank">
|
||||
lea++
|
||||
</a>
|
||||
</li>
|
||||
<li class="hidden-xs">
|
||||
<a href="/note" class="dk" target="_blank">
|
||||
{{msg . "myNote"}}
|
||||
@@ -79,7 +74,7 @@
|
||||
</section>
|
||||
<footer class="footer lt hidden-xs b-t b-light" style="min-height: initial;
|
||||
padding: 10px 15px;text-align:center;">
|
||||
<a href="http://leanote.com" target="_blank">leanote</a> © 2014
|
||||
<a href="http://leanote.com" target="_blank">leanote</a> © 2015
|
||||
<!--
|
||||
<a href="#nav" data-toggle="class:nav-xs" class="pull-right btn btn-sm btn-default btn-icon">
|
||||
<i class="fa fa-angle-left text">
|
||||
@@ -115,4 +110,4 @@ padding: 10px 15px;text-align:center;">
|
||||
</ul>
|
||||
-->
|
||||
<!-- 主要内容区 -->
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">用户名设置</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "addLeanoteAccount"}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="col-sm-8">
|
||||
<form id="formData">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{{template "member/top.html" .}}
|
||||
|
||||
<div class="m-b-md"> <h3 class="m-b-none">头像设置</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "avatar"}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="col-sm-8">
|
||||
<form id="uploadAvatar" method="post" action="/file/uploadAvatar" enctype="multipart/form-data">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
@@ -14,7 +14,7 @@
|
||||
<img src="{{if .userInfo.Logo}}{{.userInfo.Logo}}{{else}}/images/blog/default_avatar.png{{end}}" id="avatar"/>
|
||||
</div>
|
||||
<a class="btn btn-success btn-choose-file">
|
||||
<span class="fa fa-upload"></span> Choose Image
|
||||
<span class="fa fa-upload"></span> {{msg . "chooseImage"}}
|
||||
</a>
|
||||
<input type="file" name="file" multiple/>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">邮箱设置</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "email"}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="col-sm-8">
|
||||
<form id="formData">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">用户名设置</h3></div>
|
||||
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "password"}}</h3></div>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="col-sm-8">
|
||||
<form id="formData">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{{template "member/top.html" .}}
|
||||
<div class="m-b-md"> <h3 class="m-b-none">用户名设置</h3></div>
|
||||
<div class="m-b-md"> <h3 class="m-b-none">{{msg . "username"}}</h3></div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<div class="col-sm-8">
|
||||
<form id="formData">
|
||||
<section class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
|
||||
@@ -12,17 +12,19 @@
|
||||
|
||||
<link href="/css/bootstrap.css" rel="stylesheet" />
|
||||
<!-- 先加载, 没有样式, 宽度不定 -->
|
||||
<link rel="stylesheet" href="tinymce/skins/custom/skin.min.css" rel="stylesheet"/>
|
||||
|
||||
<link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" rel="stylesheet"/>
|
||||
<!-- leanote css -->
|
||||
<link href="css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" />
|
||||
<link href="css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
|
||||
<link href="/css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" />
|
||||
<link href="/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
|
||||
<!-- mdeditor -->
|
||||
<link href="/public/dist/themes/default.css" rel="stylesheet" />
|
||||
|
||||
<script>
|
||||
var hash = location.hash;
|
||||
if(hash == "#writing") {
|
||||
var files = '<link rel="stylesheet" href="css/theme/writting-overwrite.css" type="text/css" id="themeLink" />';
|
||||
if(hash.indexOf("writing") >= 0) {
|
||||
var files = '<link rel="stylesheet" href="/css/theme/writting-overwrite.css" type="text/css" id="themeLink" />';
|
||||
} else {
|
||||
var files ='<link rel="stylesheet" href="css/theme/{{if .userInfo.Theme}}{{.userInfo.Theme}}{{else}}default{{end}}.css" type="text/css" id="themeLink" />';
|
||||
var files ='<link rel="stylesheet" href="/css/theme/{{if .userInfo.Theme}}{{.userInfo.Theme}}{{else}}default{{end}}.css" type="text/css" id="themeLink" />';
|
||||
}
|
||||
document.write(files);
|
||||
</script>
|
||||
@@ -160,12 +162,18 @@ function log(o) {
|
||||
{{msg . "myBlog"}}</a>
|
||||
</li>
|
||||
|
||||
<li role="presentation" class="divider my-link writing-mobile-hide"></li>
|
||||
<li role="presentation" class="my-link toggle-editor-mode writing-mobile-hide" >
|
||||
<a href="#writing"><i class="fa fa-rocket"></i>
|
||||
{{msg . "writingMode"}}</a>
|
||||
</li>
|
||||
|
||||
{{if .isAdmin}}
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li role="presentation">
|
||||
<a target="_blank" title="{{msg . "amdin"}}" href="/admin/index">
|
||||
<a target="_blank" title="{{msg . "admin"}}" href="/admin/index">
|
||||
<i class="fa fa-dashboard"></i>
|
||||
{{msg . "admin"}}
|
||||
<span>{{msg . "admin"}}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
||||
@@ -178,14 +186,22 @@ function log(o) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pull-right top-nav" id="myBlog">
|
||||
<!--
|
||||
<div class="pull-right top-nav writting-hide lea-blog">
|
||||
<a target="_blank" href="http://lea.leanote.com">
|
||||
lea++
|
||||
</a>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div class="pull-right top-nav writting-hide" id="myBlog">
|
||||
<a target="_blank" href="{{$.blogUrl}}/{{.userInfo.Username}}">
|
||||
{{msg . "myBlog"}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="pull-right" style="line-height: 60px; margin-right:10px" id="toggleEditorMode">
|
||||
<a href="#writing">{{msg . "writingMode"}}</a>
|
||||
<div class="pull-right toggle-editor-mode" style="line-height: 60px; margin-right:10px" id="toggleEditorMode">
|
||||
<a href="#writing"><span>{{msg . "writingMode"}}</span></a>
|
||||
</div>
|
||||
|
||||
{{if eq .userInfo.Email "demo@leanote.com"}}
|
||||
@@ -321,6 +337,11 @@ function log(o) {
|
||||
<div class="noteSplit" id="notebookSplitter"></div>
|
||||
|
||||
<div id="noteAndEditor">
|
||||
<div id="noteAndEditorMask">
|
||||
<img src="/images/loading-24.gif"/>
|
||||
<br />
|
||||
loading...
|
||||
</div>
|
||||
<div id="noteList">
|
||||
<div class="clearfix" id="notesAndSort" style="position: relative">
|
||||
<div class="pull-left">
|
||||
@@ -405,11 +426,11 @@ function log(o) {
|
||||
<span id="noteReadTags"></span>
|
||||
|
||||
<!-- 修改时间 -->
|
||||
<i class="fa fa-calendar"></i>{{msg . "update"}}
|
||||
<i class="fa fa-clock-o"></i>{{msg . "update"}}
|
||||
<span id="noteReadUpdatedTime"></span>
|
||||
|
||||
<!-- 修改时间 -->
|
||||
<i class="fa fa-calendar"></i>{{msg . "create"}}
|
||||
<i class="fa fa-clock-o"></i>{{msg . "create"}}
|
||||
<span id="noteReadCreatedTime"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -538,12 +559,12 @@ function log(o) {
|
||||
</a>
|
||||
</div>
|
||||
<div class="editorBg"></div>
|
||||
<div id="leanoteNav">
|
||||
<div id="leanoteNav" class="leanoteNav">
|
||||
<h1>
|
||||
<i class="fa fa-align-justify" title="文档导航"></i>
|
||||
<i class="fa fa-align-justify" title="{{msg . "nav"}}"></i>
|
||||
<span>{{msg . "nav"}}</span>
|
||||
</h1>
|
||||
<div id="leanoteNavContent">
|
||||
<div id="leanoteNavContent" class="leanoteNavContent">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -564,9 +585,85 @@ function log(o) {
|
||||
</div>
|
||||
|
||||
<div id="mdEditor">
|
||||
|
||||
|
||||
<div class="layout-wrapper-l1">
|
||||
<div class="layout-wrapper-l2">
|
||||
<div class="navbar navbar-default">
|
||||
<div class="navbar-inner" id="wmd-button-bar">
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group1 btn-group"></li>
|
||||
</ul>
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group2 btn-group"></li>
|
||||
</ul>
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group3 btn-group"></li>
|
||||
</ul>
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group5 btn-group"></li>
|
||||
</ul>
|
||||
<!-- 帮助 -->
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group6 btn-group">
|
||||
<li class="wmd-button btn btn-success" id="wmd-help-button" title="Markdown syntax" style="left: 0px; display: none;"><span style="display: none; background-position: 0px 0px;"></span><i class="fa fa-question-circle"></i></li>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--
|
||||
<ul class="nav pull-right right-buttons">
|
||||
<li class="offline-status hide">
|
||||
<div class="text-danger">
|
||||
<i class="icon-attention-circled"></i>offline
|
||||
</div>
|
||||
</li>
|
||||
<li class="extension-buttons"></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right title-container">
|
||||
<li><div class="working-indicator"></div></li>
|
||||
<li><a class="btn btn-success file-title-navbar" href="#"
|
||||
title="Rename document"> </a></li>
|
||||
<li><div class="input-file-title-container"><input type="text"
|
||||
class="col-sm-4 form-control hide input-file-title"
|
||||
placeholder="Document title" /></div></li>
|
||||
</ul>
|
||||
-->
|
||||
</div>
|
||||
<div class="editorBg"></div>
|
||||
</div>
|
||||
<div class="layout-wrapper-l3">
|
||||
<div id="left-column">
|
||||
<pre id="wmd-input" class="form-control"><div class="editor-content mousetrap" contenteditable=true></div><div class="editor-margin"></div></pre>
|
||||
</div>
|
||||
<div id="right-column">
|
||||
<div class="preview-panel panel-open" id="preview-panel">
|
||||
<div id="mdSplitter2" class="layout-resizer layout-resizer-preview open" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); touch-action: none;"></div>
|
||||
<div class="layout-toggler layout-toggler-preview btn btn-info open" title="Toggle preview" data-open="1"><i class="fa fa-angle-right"></i></div>
|
||||
<div class="preview-container">
|
||||
<div id="preview-contents">
|
||||
<div id="wmd-preview" class="preview-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="extension-preview-buttons">
|
||||
<div id="leanoteNavMd" class="leanoteNav">
|
||||
<h1>
|
||||
<i class="fa fa-align-justify" title="{{msg . "nav"}}"></i>
|
||||
<span>{{msg . "nav"}}</span>
|
||||
</h1>
|
||||
<div id="leanoteNavContentMd" class="leanoteNavContent table-of-contents">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wmd-button-bar" class="hide"></div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div id="wmd-button-bar" id="mdBar"></div>
|
||||
<div class="editorBg"></div>
|
||||
<!-- 为了scroll -->
|
||||
|
||||
<div class="clearfix" id="mdEditorPreview">
|
||||
<div id="left-column">
|
||||
@@ -582,11 +679,59 @@ function log(o) {
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="md-section-helper"></textarea>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- mdEditor -->
|
||||
<!-- v2 -->
|
||||
<div class="modal fade modal-insert-link">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Hyperlink</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Please provide the link URL and an optional title:</p>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="icon-globe"></i></span><input
|
||||
id="input-insert-link" type="text" class="col-sm-5 form-control"
|
||||
placeholder='http://example.com/ "optional title"' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn btn-default" data-dismiss="modal">Cancel</a>
|
||||
<a href="#" class="btn btn-primary action-insert-link"
|
||||
data-dismiss="modal">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 插入图片 -->
|
||||
<div class="modal fade modal-insert-image">
|
||||
<div class="modal-dialog" style="width: 840px">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Image</h4>
|
||||
</div>
|
||||
<div class="modal-body" style="padding-top: 0; padding-bottom: 0">
|
||||
<iframe name="mdImageManager" style="width: 100%; height: 350px" scrolling="no" id="leauiIfrForMD" src="" frameborder="0"></iframe>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn btn-default"
|
||||
data-dismiss="modal">Cancel</a> <a href="#"
|
||||
class="btn btn-primary action-insert-image" data-dismiss="modal">Insert Image</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- v1 -->
|
||||
<!-- Hidden Popup Modal -->
|
||||
<div class="modal fade bs-modal-sm" id="editorDialog" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
@@ -731,17 +876,22 @@ function log(o) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="js/jquery-1.9.0.min.js"></script>
|
||||
<script src="js/jquery.ztree.all-3.5.js"></script>
|
||||
<script src="js/i18n/msg.{{.locale}}.js"></script>
|
||||
<script src="js/common.js"></script>
|
||||
<script src="/js/jquery-1.9.0.min.js"></script>
|
||||
<script src="/js/jquery.ztree.all-3.5.js"></script>
|
||||
<script src="/js/i18n/msg.{{.locale}}.js"></script>
|
||||
<script src="/js/common.js"></script>
|
||||
<script>
|
||||
var UrlPrefix = "{{.siteUrl}}"; // 为了发weibo
|
||||
var UrlPrefix = '{{.siteUrl}}'; // 为了发weibo
|
||||
var UserInfo = {{.userInfo|jsonJs}};
|
||||
var notebooks = {{.notebooks|jsonJs}};
|
||||
var shareNotebooks = {{.shareNotebooks|jsonJs}};
|
||||
var sharedUserInfos = {{.sharedUserInfos|jsonJs}};
|
||||
var notes = {{.notes|jsonJs}}
|
||||
var curNoteId = '{{.curNoteId}}';
|
||||
var curNotebookId = '{{.curNotebookId}}';
|
||||
var curSharedNoteNotebookId = '{{.curSharedNoteNotebookId}}';
|
||||
var curSharedUserId = '{{.curSharedUserId}}';
|
||||
var notes = {{.notes|jsonJs}};
|
||||
var latestNotes = {{if .latestNotes}}{{.latestNotes|jsonJs}}{{else}}[]{{end}};
|
||||
var noteContentJson = {{.noteContentJson|jsonJs}};
|
||||
var tagsJson = {{.tags|jsonJs}};
|
||||
LEA.locale = "{{.locale}}";
|
||||
@@ -749,44 +899,33 @@ var GlobalConfigs = {{.globalConfigs|jsonJs}}; // 2014/11/9 beta2
|
||||
</script>
|
||||
|
||||
<!-- 渲染view -->
|
||||
<script src="tinymce/tinymce.js"></script>
|
||||
<script src="js/app/page.js"></script>
|
||||
<script src="/tinymce/tinymce.js"></script>
|
||||
<script src="/public/libs/ace/ace.js"></script>
|
||||
<script src="/js/app/page.js"></script>
|
||||
<script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll.js"></script>
|
||||
<script src="/js/contextmenu/jquery.contextmenu.js"></script>
|
||||
<script src="js/jquery-cookie.js"></script>
|
||||
<script src="js/bootstrap-min.js"></script>
|
||||
<script src="js/app/note.js"></script>
|
||||
<script src="js/app/tag.js"></script>
|
||||
<script src="js/app/notebook.js"></script>
|
||||
<script src="js/app/share.js"></script>
|
||||
<script src="js/object_id-min.js"></script>
|
||||
<script src="js/ZeroClipboard/ZeroClipboard-min.js"></script>
|
||||
<script src="/js/bootstrap-min.js"></script>
|
||||
<script src="/js/app/note.js"></script>
|
||||
<script src="/js/app/tag.js"></script>
|
||||
<script src="/js/app/notebook.js"></script>
|
||||
<script src="/js/app/share.js"></script>
|
||||
<script src="/js/object_id-min.js"></script>
|
||||
<script>
|
||||
Notebook.renderNotebooks(notebooks);
|
||||
Share.renderShareNotebooks(sharedUserInfos, shareNotebooks);
|
||||
|
||||
Note.setNoteCache(noteContentJson);
|
||||
Note.renderNotes(notes);
|
||||
if(!isEmpty(notes)) {
|
||||
Note.changeNote(notes[0].NoteId);
|
||||
}
|
||||
|
||||
// Note.chanteNote设置content
|
||||
// Note.renderNoteContent(noteContentJson)
|
||||
|
||||
Tag.renderTagNav(tagsJson);
|
||||
|
||||
// init notebook后才调用
|
||||
initSlimScroll();
|
||||
initPage();
|
||||
</script>
|
||||
|
||||
|
||||
<!-- context-menu -->
|
||||
<link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" />
|
||||
<!-- code -->
|
||||
<link href="/public/mdeditor/editor/google-code-prettify/prettify.css" rel="stylesheet" />
|
||||
<!-- js version 2.0 use require.js -->
|
||||
|
||||
<!-- v2 use require.js, mdeditor -->
|
||||
<script>
|
||||
window.baseDir = '/public/dist';
|
||||
window.require = {
|
||||
baseUrl: window.baseDir,
|
||||
deps: ['main']
|
||||
};
|
||||
</script>
|
||||
<script src="/js/require.js"></script>
|
||||
<script src="/js/main.js"></script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -12,17 +12,19 @@
|
||||
|
||||
<link href="/css/bootstrap.css" rel="stylesheet" />
|
||||
<!-- 先加载, 没有样式, 宽度不定 -->
|
||||
<link rel="stylesheet" href="tinymce/skins/custom/skin.min.css" rel="stylesheet"/>
|
||||
|
||||
<link rel="stylesheet" href="/tinymce/skins/custom/skin.min.css" rel="stylesheet"/>
|
||||
<!-- leanote css -->
|
||||
<link href="css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" />
|
||||
<link href="css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
|
||||
<link href="/css/font-awesome-4.2.0/css/font-awesome.css" rel="stylesheet" />
|
||||
<link href="/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" />
|
||||
<!-- mdeditor -->
|
||||
<link href="/public/dist/themes/default.css" rel="stylesheet" />
|
||||
|
||||
<script>
|
||||
var hash = location.hash;
|
||||
if(hash == "#writing") {
|
||||
var files = '<link rel="stylesheet" href="css/theme/writting-overwrite.css" type="text/css" id="themeLink" />';
|
||||
if(hash.indexOf("writing") >= 0) {
|
||||
var files = '<link rel="stylesheet" href="/css/theme/writting-overwrite.css" type="text/css" id="themeLink" />';
|
||||
} else {
|
||||
var files ='<link rel="stylesheet" href="css/theme/{{if .userInfo.Theme}}{{.userInfo.Theme}}{{else}}default{{end}}.css" type="text/css" id="themeLink" />';
|
||||
var files ='<link rel="stylesheet" href="/css/theme/{{if .userInfo.Theme}}{{.userInfo.Theme}}{{else}}default{{end}}.css" type="text/css" id="themeLink" />';
|
||||
}
|
||||
document.write(files);
|
||||
</script>
|
||||
@@ -160,12 +162,18 @@ function log(o) {
|
||||
{{msg . "myBlog"}}</a>
|
||||
</li>
|
||||
|
||||
<li role="presentation" class="divider my-link writing-mobile-hide"></li>
|
||||
<li role="presentation" class="my-link toggle-editor-mode writing-mobile-hide" >
|
||||
<a href="#writing"><i class="fa fa-rocket"></i>
|
||||
{{msg . "writingMode"}}</a>
|
||||
</li>
|
||||
|
||||
{{if .isAdmin}}
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li role="presentation">
|
||||
<a target="_blank" title="{{msg . "amdin"}}" href="/admin/index">
|
||||
<a target="_blank" title="{{msg . "admin"}}" href="/admin/index">
|
||||
<i class="fa fa-dashboard"></i>
|
||||
{{msg . "admin"}}
|
||||
<span>{{msg . "admin"}}</span>
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
||||
@@ -178,14 +186,22 @@ function log(o) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pull-right top-nav" id="myBlog">
|
||||
<!--
|
||||
<div class="pull-right top-nav writting-hide lea-blog">
|
||||
<a target="_blank" href="http://lea.leanote.com">
|
||||
lea++
|
||||
</a>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div class="pull-right top-nav writting-hide" id="myBlog">
|
||||
<a target="_blank" href="{{$.blogUrl}}/{{.userInfo.Username}}">
|
||||
{{msg . "myBlog"}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="pull-right" style="line-height: 60px; margin-right:10px" id="toggleEditorMode">
|
||||
<a href="#writing">{{msg . "writingMode"}}</a>
|
||||
<div class="pull-right toggle-editor-mode" style="line-height: 60px; margin-right:10px" id="toggleEditorMode">
|
||||
<a href="#writing"><span>{{msg . "writingMode"}}</span></a>
|
||||
</div>
|
||||
|
||||
{{if eq .userInfo.Email "demo@leanote.com"}}
|
||||
@@ -321,6 +337,11 @@ function log(o) {
|
||||
<div class="noteSplit" id="notebookSplitter"></div>
|
||||
|
||||
<div id="noteAndEditor">
|
||||
<div id="noteAndEditorMask">
|
||||
<img src="/images/loading-24.gif"/>
|
||||
<br />
|
||||
loading...
|
||||
</div>
|
||||
<div id="noteList">
|
||||
<div class="clearfix" id="notesAndSort" style="position: relative">
|
||||
<div class="pull-left">
|
||||
@@ -405,11 +426,11 @@ function log(o) {
|
||||
<span id="noteReadTags"></span>
|
||||
|
||||
<!-- 修改时间 -->
|
||||
<i class="fa fa-calendar"></i>{{msg . "update"}}
|
||||
<i class="fa fa-clock-o"></i>{{msg . "update"}}
|
||||
<span id="noteReadUpdatedTime"></span>
|
||||
|
||||
<!-- 修改时间 -->
|
||||
<i class="fa fa-calendar"></i>{{msg . "create"}}
|
||||
<i class="fa fa-clock-o"></i>{{msg . "create"}}
|
||||
<span id="noteReadCreatedTime"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -538,12 +559,12 @@ function log(o) {
|
||||
</a>
|
||||
</div>
|
||||
<div class="editorBg"></div>
|
||||
<div id="leanoteNav">
|
||||
<div id="leanoteNav" class="leanoteNav">
|
||||
<h1>
|
||||
<i class="fa fa-align-justify" title="文档导航"></i>
|
||||
<i class="fa fa-align-justify" title="{{msg . "nav"}}"></i>
|
||||
<span>{{msg . "nav"}}</span>
|
||||
</h1>
|
||||
<div id="leanoteNavContent">
|
||||
<div id="leanoteNavContent" class="leanoteNavContent">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -564,9 +585,85 @@ function log(o) {
|
||||
</div>
|
||||
|
||||
<div id="mdEditor">
|
||||
|
||||
|
||||
<div class="layout-wrapper-l1">
|
||||
<div class="layout-wrapper-l2">
|
||||
<div class="navbar navbar-default">
|
||||
<div class="navbar-inner" id="wmd-button-bar">
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group1 btn-group"></li>
|
||||
</ul>
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group2 btn-group"></li>
|
||||
</ul>
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group3 btn-group"></li>
|
||||
</ul>
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group5 btn-group"></li>
|
||||
</ul>
|
||||
<!-- 帮助 -->
|
||||
<ul class="nav left-buttons">
|
||||
<li class="wmd-button-group6 btn-group">
|
||||
<li class="wmd-button btn btn-success" id="wmd-help-button" title="Markdown syntax" style="left: 0px; display: none;"><span style="display: none; background-position: 0px 0px;"></span><i class="fa fa-question-circle"></i></li>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!--
|
||||
<ul class="nav pull-right right-buttons">
|
||||
<li class="offline-status hide">
|
||||
<div class="text-danger">
|
||||
<i class="icon-attention-circled"></i>offline
|
||||
</div>
|
||||
</li>
|
||||
<li class="extension-buttons"></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right title-container">
|
||||
<li><div class="working-indicator"></div></li>
|
||||
<li><a class="btn btn-success file-title-navbar" href="#"
|
||||
title="Rename document"> </a></li>
|
||||
<li><div class="input-file-title-container"><input type="text"
|
||||
class="col-sm-4 form-control hide input-file-title"
|
||||
placeholder="Document title" /></div></li>
|
||||
</ul>
|
||||
-->
|
||||
</div>
|
||||
<div class="editorBg"></div>
|
||||
</div>
|
||||
<div class="layout-wrapper-l3">
|
||||
<div id="left-column">
|
||||
<pre id="wmd-input" class="form-control"><div class="editor-content mousetrap" contenteditable=true></div><div class="editor-margin"></div></pre>
|
||||
</div>
|
||||
<div id="right-column">
|
||||
<div class="preview-panel panel-open" id="preview-panel">
|
||||
<div id="mdSplitter2" class="layout-resizer layout-resizer-preview open" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); touch-action: none;"></div>
|
||||
<div class="layout-toggler layout-toggler-preview btn btn-info open" title="Toggle preview" data-open="1"><i class="fa fa-angle-right"></i></div>
|
||||
<div class="preview-container">
|
||||
<div id="preview-contents">
|
||||
<div id="wmd-preview" class="preview-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="extension-preview-buttons">
|
||||
<div id="leanoteNavMd" class="leanoteNav">
|
||||
<h1>
|
||||
<i class="fa fa-align-justify" title="{{msg . "nav"}}"></i>
|
||||
<span>{{msg . "nav"}}</span>
|
||||
</h1>
|
||||
<div id="leanoteNavContentMd" class="leanoteNavContent table-of-contents">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wmd-button-bar" class="hide"></div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div id="wmd-button-bar" id="mdBar"></div>
|
||||
<div class="editorBg"></div>
|
||||
<!-- 为了scroll -->
|
||||
|
||||
<div class="clearfix" id="mdEditorPreview">
|
||||
<div id="left-column">
|
||||
@@ -582,11 +679,59 @@ function log(o) {
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="md-section-helper"></textarea>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- mdEditor -->
|
||||
<!-- v2 -->
|
||||
<div class="modal fade modal-insert-link">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Hyperlink</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Please provide the link URL and an optional title:</p>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="icon-globe"></i></span><input
|
||||
id="input-insert-link" type="text" class="col-sm-5 form-control"
|
||||
placeholder='http://example.com/ "optional title"' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn btn-default" data-dismiss="modal">Cancel</a>
|
||||
<a href="#" class="btn btn-primary action-insert-link"
|
||||
data-dismiss="modal">OK</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 插入图片 -->
|
||||
<div class="modal fade modal-insert-image">
|
||||
<div class="modal-dialog" style="width: 840px">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"
|
||||
aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">Image</h4>
|
||||
</div>
|
||||
<div class="modal-body" style="padding-top: 0; padding-bottom: 0">
|
||||
<iframe name="mdImageManager" style="width: 100%; height: 350px" scrolling="no" id="leauiIfrForMD" src="" frameborder="0"></iframe>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" class="btn btn-default"
|
||||
data-dismiss="modal">Cancel</a> <a href="#"
|
||||
class="btn btn-primary action-insert-image" data-dismiss="modal">Insert Image</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- v1 -->
|
||||
<!-- Hidden Popup Modal -->
|
||||
<div class="modal fade bs-modal-sm" id="editorDialog" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
@@ -731,17 +876,22 @@ function log(o) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="js/jquery-1.9.0.min.js"></script>
|
||||
<script src="js/jquery.ztree.all-3.5.js"></script>
|
||||
<script src="js/i18n/msg.{{.locale}}.js"></script>
|
||||
<script src="js/common-min.js"></script>
|
||||
<script src="/js/jquery-1.9.0.min.js"></script>
|
||||
<script src="/js/jquery.ztree.all-3.5-min.js"></script>
|
||||
<script src="/js/i18n/msg.{{.locale}}.js"></script>
|
||||
<script src="/js/common-min.js"></script>
|
||||
<script>
|
||||
var UrlPrefix = "{{.siteUrl}}"; // 为了发weibo
|
||||
var UrlPrefix = '{{.siteUrl}}'; // 为了发weibo
|
||||
var UserInfo = {{.userInfo|jsonJs}};
|
||||
var notebooks = {{.notebooks|jsonJs}};
|
||||
var shareNotebooks = {{.shareNotebooks|jsonJs}};
|
||||
var sharedUserInfos = {{.sharedUserInfos|jsonJs}};
|
||||
var notes = {{.notes|jsonJs}}
|
||||
var curNoteId = '{{.curNoteId}}';
|
||||
var curNotebookId = '{{.curNotebookId}}';
|
||||
var curSharedNoteNotebookId = '{{.curSharedNoteNotebookId}}';
|
||||
var curSharedUserId = '{{.curSharedUserId}}';
|
||||
var notes = {{.notes|jsonJs}};
|
||||
var latestNotes = {{if .latestNotes}}{{.latestNotes|jsonJs}}{{else}}[]{{end}};
|
||||
var noteContentJson = {{.noteContentJson|jsonJs}};
|
||||
var tagsJson = {{.tags|jsonJs}};
|
||||
LEA.locale = "{{.locale}}";
|
||||
@@ -749,44 +899,33 @@ var GlobalConfigs = {{.globalConfigs|jsonJs}}; // 2014/11/9 beta2
|
||||
</script>
|
||||
|
||||
<!-- 渲染view -->
|
||||
<script src="tinymce/tinymce.js"></script>
|
||||
<script src="js/app/page-min.js"></script>
|
||||
<script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll.js"></script>
|
||||
<script src="/tinymce/tinymce.min.js"></script>
|
||||
<script src="/public/libs/ace/ace.js"></script>
|
||||
<script src="/js/app/page-min.js"></script>
|
||||
<script src="/js/jQuery-slimScroll-1.3.0/jquery.slimscroll-min.js"></script>
|
||||
<script src="/js/contextmenu/jquery.contextmenu-min.js"></script>
|
||||
<script src="js/jquery-cookie.js"></script>
|
||||
<script src="js/bootstrap-min.js"></script>
|
||||
<script src="js/app/note-min.js"></script>
|
||||
<script src="js/app/tag-min.js"></script>
|
||||
<script src="js/app/notebook-min.js"></script>
|
||||
<script src="js/app/share-min.js"></script>
|
||||
<script src="js/object_id-min.js"></script>
|
||||
<script src="js/ZeroClipboard/ZeroClipboard-min.js"></script>
|
||||
<script src="/js/bootstrap-min.js"></script>
|
||||
<script src="/js/app/note-min.js"></script>
|
||||
<script src="/js/app/tag-min.js"></script>
|
||||
<script src="/js/app/notebook-min.js"></script>
|
||||
<script src="/js/app/share-min.js"></script>
|
||||
<script src="/js/object_id-min.js"></script>
|
||||
<script>
|
||||
Notebook.renderNotebooks(notebooks);
|
||||
Share.renderShareNotebooks(sharedUserInfos, shareNotebooks);
|
||||
|
||||
Note.setNoteCache(noteContentJson);
|
||||
Note.renderNotes(notes);
|
||||
if(!isEmpty(notes)) {
|
||||
Note.changeNote(notes[0].NoteId);
|
||||
}
|
||||
|
||||
// Note.chanteNote设置content
|
||||
// Note.renderNoteContent(noteContentJson)
|
||||
|
||||
Tag.renderTagNav(tagsJson);
|
||||
|
||||
// init notebook后才调用
|
||||
initSlimScroll();
|
||||
initPage();
|
||||
</script>
|
||||
|
||||
|
||||
<!-- context-menu -->
|
||||
<link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" />
|
||||
<!-- code -->
|
||||
<link href="/public/mdeditor/editor/google-code-prettify/prettify.css" rel="stylesheet" />
|
||||
<!-- js version 2.0 use require.js -->
|
||||
|
||||
<!-- v2 use require.js, mdeditor -->
|
||||
<script>
|
||||
window.baseDir = '/public/dist';
|
||||
window.require = {
|
||||
baseUrl: window.baseDir,
|
||||
deps: ['main']
|
||||
};
|
||||
</script>
|
||||
<script src="/js/require.js"></script>
|
||||
<script src="/js/main-min.js"></script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -5,11 +5,14 @@
|
||||
<h4 class="modal-title" id="modalTitle">{{msg . "share"}} <b>{{.title}}</b></h4>
|
||||
</div>
|
||||
{{$noteOrNotebookId := .noteOrNotebookId}}
|
||||
|
||||
{{$isNote := .isNote}}
|
||||
<div class="modal-body">
|
||||
<ul id="myTab" class="nav nav-tabs">
|
||||
<li class="active"><a href="#baseInfo" data-toggle="tab">分享给好友</a></li>
|
||||
<li class=""><a href="#groupInfo" data-toggle="tab">分享给项目组</a></li>
|
||||
{{if $isNote}}
|
||||
<li class=""><a href="#shareInfo" data-toggle="tab">分享给未注册好友</a></li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
@@ -95,6 +98,19 @@
|
||||
{{end}}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane" id="shareInfo">
|
||||
<p>
|
||||
<button class="btn btn-default" id="genShareLink">生成该笔记的分享链接和密码</button>
|
||||
<span id="showMsg"></span>
|
||||
</p>
|
||||
|
||||
<br>
|
||||
|
||||
分享链接:<input type="text" id="shareLink" value="" size=50> <br/><br/>
|
||||
查看密码:<input type="text" id="sharePass" value="" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -108,11 +124,55 @@
|
||||
<script>
|
||||
Share.dialogIsNote = {{.isNote}};
|
||||
Share.dialogNoteOrNotebookId = '{{.noteOrNotebookId}}';
|
||||
|
||||
var getHost = function(url) {
|
||||
var host = "null";
|
||||
if(typeof url == "undefined"
|
||||
|| null == url)
|
||||
url = window.location.href;
|
||||
var regex = /.*\:\/\/([^\/]*).*/;
|
||||
var match = url.match(regex);
|
||||
if(typeof match != "undefined"
|
||||
&& null != match)
|
||||
host = match[1];
|
||||
return host;
|
||||
}
|
||||
|
||||
|
||||
$(function() {
|
||||
setTimeout(function() {
|
||||
$("#tr1 #friendsEmail").focus();
|
||||
}, 500);
|
||||
|
||||
var host = getHost();
|
||||
if (Share.dialogIsNote) {
|
||||
var url = "/share/querySharePass";
|
||||
var data = {noteId: Share.dialogNoteOrNotebookId};
|
||||
ajaxPost(url, data, function(re) {
|
||||
if(reIsOk(re)) {
|
||||
if (re.Item >= 1000 && re.Item < 10000) {
|
||||
var shareLink = host + '/share/note/{{.noteOrNotebookId}}';
|
||||
$("#shareLink").val(shareLink);
|
||||
$("#sharePass").val(re.Item);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#shareLink").hover(function() {
|
||||
$("#shareLink").focus(function(){
|
||||
$(this).css({'background-color' : '#f5f5dc'});
|
||||
}).select();
|
||||
|
||||
})
|
||||
|
||||
$("#sharePass").hover(function() {
|
||||
$("#sharePass").focus(function(){
|
||||
$(this).css({'background-color' : '#f5f5dc'});
|
||||
}).select();
|
||||
|
||||
})
|
||||
|
||||
// 分享/删除给分组
|
||||
$("#groupInfo").on("click", ".btn-share-or-not", function() {
|
||||
var $t = $(this);
|
||||
@@ -155,6 +215,28 @@ $("#groupInfo").on("click", ".btn-share-or-not", function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//生成分享链接和密码
|
||||
$("#genShareLink").on("click", function() {
|
||||
var sharePass = $("#sharePass").val();
|
||||
if (sharePass != '' && sharePass > 1000 && sharePass < 10000) {
|
||||
$("#showMsg").html("<font color='red'>不能重复生成分享链接和密码</font>");
|
||||
return;
|
||||
}
|
||||
|
||||
var url = "/share/genShareLinkPass";
|
||||
var shareLink = host + '/share/note/{{.noteOrNotebookId}}';
|
||||
var data = {noteId: Share.dialogNoteOrNotebookId};
|
||||
ajaxPost(url, data, function(re) {
|
||||
if(reIsOk(re)) {
|
||||
$("#shareLink").val(shareLink);
|
||||
$("#sharePass").val(re.Item);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
$(".group-perm").click(function() {
|
||||
var $t = $(this);
|
||||
var $ptr = $t.closest("tr");
|
||||
@@ -179,5 +261,6 @@ $(".group-perm").click(function() {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
134
app/views/share/show_share_note.html
Normal file
134
app/views/share/show_share_note.html
Normal file
@@ -0,0 +1,134 @@
|
||||
{{template "home/header.html" .}}
|
||||
|
||||
<section>
|
||||
</section>
|
||||
{{$isMarkDown := .isMarkDown}}
|
||||
|
||||
<div id="queryNote" style="height:300px;padding-top:80px" align="center">
|
||||
{{ .userName }}分享了笔记<br/><br>
|
||||
|
||||
您需要输入分享密码才能查看:<br><br>
|
||||
<input type="password" id="sharePass" />
|
||||
<button id="showShareNote">点击查看</button><br/><br/>
|
||||
<span id="showMsg"></span>
|
||||
</div>
|
||||
|
||||
<div id="noteContainer" style="display:none">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
{{template "home/footer.html"}}
|
||||
|
||||
<script src="/js/jquery-1.9.0.min.js"></script>
|
||||
<script src="/js/bootstrap.js"></script>
|
||||
<script src="/js/common-min.js"></script>
|
||||
<script>
|
||||
|
||||
var noteId = {{ .noteId }};
|
||||
var isMarkDown = {{ .isMarkDown}}
|
||||
|
||||
String.prototype.format = function() {
|
||||
var s = this,
|
||||
i = arguments.length;
|
||||
|
||||
while (i--) {
|
||||
s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
|
||||
var getHost = function(url) {
|
||||
var host = "null";
|
||||
if(typeof url == "undefined"
|
||||
|| null == url)
|
||||
url = window.location.href;
|
||||
var regex = /.*\:\/\/([^\/]*).*/;
|
||||
var match = url.match(regex);
|
||||
if(typeof match != "undefined"
|
||||
&& null != match)
|
||||
host = match[1];
|
||||
return "http://" + host;
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
||||
$("#showShareNote").on("click", function() {
|
||||
$("#showMsg").html("");
|
||||
var url = "/share/verify4ShareNote";
|
||||
|
||||
var sharePass = $("#sharePass").val();
|
||||
var data = {noteId: noteId, sharePass: sharePass};
|
||||
ajaxPost(url, data, function(re) {
|
||||
if(reIsOk(re)) {
|
||||
$("#queryNote").css("display", "none");
|
||||
var title = re.Item.Title;
|
||||
var content = re.Msg;
|
||||
var imgSrc = re.Item.ImgSrc;
|
||||
var htmlContent = "<div><h1 height='50px'>{0}</h1></div><hr/><div style='vertical-align:center'><p height='auto'>{1}<br>{2}</p>";
|
||||
|
||||
var attaches = re.List;
|
||||
var attachesHtml = "";
|
||||
if (attaches.length > 0) {
|
||||
var token = re.Id;
|
||||
for (var i=0; i<attaches.length; i++) {
|
||||
var linkUrl = "{0}/attach/download?attachId={1}&token={2}".format(getHost(), attaches[i].AttachId, token);
|
||||
attachesHtml += "<p><a href='{0}' target='_blank' data-mce-href='{1}' >附件{2}</a></p><br/>".format(linkUrl, linkUrl, i+1);
|
||||
}
|
||||
}
|
||||
|
||||
htmlContent = htmlContent.format(title, content, attachesHtml) + "</div>";
|
||||
|
||||
|
||||
/* if (isMarkDown) {
|
||||
var converter = Markdown.getSanitizingConverter();
|
||||
Markdown.Extra.init(converter, {extensions: ["tables", "fenced_code_gfm", "def_list"]});
|
||||
var mdDesc = converter.makeHtml(desc);
|
||||
$("pre").addClass("prettyprint linenums");
|
||||
prettyPrint();
|
||||
MathJax.Hub.Queue(["Typeset",MathJax.Hub,"wmd-preview"]);
|
||||
htmlContent = "<div><h1 height='50px'>"+title+"</h1></div><hr/><div style='vertical-align:center'><p height='auto'>"
|
||||
+mdDesc+"</p></div>";
|
||||
} else {
|
||||
htmlContent = "<div><h1 height='50px'>"+title+"</h1></div><hr/><div style='vertical-align:center'><p height='auto'>"
|
||||
+desc+"</p></div>";
|
||||
} */
|
||||
|
||||
|
||||
$("#noteContainer").css("display", "block").css("height", "auto")
|
||||
.css("padding-top", "20px").css("text-align", "center")
|
||||
.css("margin-left", "auto").css("margin-right", "auto");
|
||||
|
||||
$("#noteContainer").html(htmlContent);
|
||||
} else {
|
||||
$("#showMsg").html("<font color='red'>密码错误</font>");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 平滑滚动
|
||||
$(".smooth-scroll").click(function(e) {
|
||||
e.preventDefault();
|
||||
var t = $(this).attr("target");
|
||||
var targetOffset = $(t).offset().top - 80;
|
||||
$('html,body').animate({scrollTop: targetOffset}, 300);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{{if $isMarkDown}}
|
||||
<script src="/public/mdeditor/editor/pagedown/Markdown.Converter.js"></script>
|
||||
<script src="/public/mdeditor/editor/pagedown/Markdown.Sanitizer.js"></script>
|
||||
<script src="/public/mdeditor/editor/pagedown/Markdown.Editor.js"></script>
|
||||
<script src="/public/mdeditor/editor/pagedown/local/Markdown.local.zh.js"></script>
|
||||
<script src="/public/mdeditor/editor/Markdown.Extra.js"></script>
|
||||
<script src="/public/mdeditor/editor/editor.js"></script>
|
||||
<script src="/public/js/google-code-prettify/prettify.js"></script>
|
||||
<!--mathjax-->
|
||||
<script type="text/x-mathjax-config">
|
||||
MathJax.Hub.Config({ tex2jax: { inlineMath: [['$','$'], ["\\(","\\)"]], processEscapes: true }, messageStyle: "none"});
|
||||
</script>
|
||||
<script src="/public/mdeditor/editor/mathJax.js"></script>
|
||||
<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
{{end}}
|
||||
@@ -10,7 +10,7 @@ cd ../
|
||||
# tmp path to store leanote release files
|
||||
tmp="/Users/life/Desktop/leanote_release"
|
||||
|
||||
version=x86_64.v1.0-beta2
|
||||
version=x86_64.v1.0-beta.2
|
||||
|
||||
rm -rf $tmp/leanote
|
||||
mkdir -p $tmp/leanote/app
|
||||
@@ -52,7 +52,7 @@ rm $tmp/leanote/public/config.codekit
|
||||
# make link
|
||||
cd $tmp/leanote/bin
|
||||
mkdir ./src/github.com/leanote
|
||||
ln -s ../../../../ ./src/github.com/leanote/leanote
|
||||
# ln -s ../../../../ ./src/github.com/leanote/leanote
|
||||
|
||||
# archieve
|
||||
# << 'BLOCK
|
||||
@@ -73,4 +73,11 @@ cd $tmp
|
||||
tar -cvf $tmp/leanote-mac-$version.bin.tar leanote
|
||||
gzip $tmp/leanote-mac-$version.bin.tar
|
||||
|
||||
cd $SP
|
||||
cd ../
|
||||
cp ./bin/leanote-linux $tmp/leanote/bin/
|
||||
|
||||
rm $tmp/bin/src/github.com/leanote/leanote
|
||||
cp -r $tmp/leanote/* $tmp/leanote_release_github
|
||||
|
||||
# BLOCK'
|
||||
12
bin/run.sh
12
bin/run.sh
@@ -2,12 +2,12 @@
|
||||
SCRIPTPATH=$(cd "$(dirname "$0")"; pwd)
|
||||
|
||||
# set link
|
||||
#
|
||||
#path="$SCRIPTPATH/src/github.com/leanote"
|
||||
#if [ ! -d "$path" ]; then
|
||||
# mkdir -p "$path"
|
||||
#fi
|
||||
# ln -s ../../../../ $SCRIPTPATH/src/github.com/leanote/leanote
|
||||
|
||||
path="$SCRIPTPATH/src/github.com/leanote"
|
||||
if [ ! -d "$path" ]; then
|
||||
mkdir -p "$path"
|
||||
fi
|
||||
ln -s ../../../../ $SCRIPTPATH/src/github.com/leanote/leanote
|
||||
|
||||
# set GOPATH
|
||||
export GOPATH=$GOPATH:$SCRIPTPATH
|
||||
|
||||
@@ -1,545 +0,0 @@
|
||||
3dm=x-world/x-3dmf
|
||||
3dmf=x-world/x-3dmf
|
||||
7z=application/x-7z-compressed
|
||||
a=application/octet-stream
|
||||
aab=application/x-authorware-bin
|
||||
aam=application/x-authorware-map
|
||||
aas=application/x-authorware-seg
|
||||
abc=text/vndabc
|
||||
ace=application/x-ace-compressed
|
||||
acgi=text/html
|
||||
afl=video/animaflex
|
||||
ai=application/postscript
|
||||
aif=audio/aiff
|
||||
aifc=audio/aiff
|
||||
aiff=audio/aiff
|
||||
aim=application/x-aim
|
||||
aip=text/x-audiosoft-intra
|
||||
alz=application/x-alz-compressed
|
||||
ani=application/x-navi-animation
|
||||
aos=application/x-nokia-9000-communicator-add-on-software
|
||||
aps=application/mime
|
||||
arc=application/x-arc-compressed
|
||||
arj=application/arj
|
||||
art=image/x-jg
|
||||
asf=video/x-ms-asf
|
||||
asm=text/x-asm
|
||||
asp=text/asp
|
||||
asx=application/x-mplayer2
|
||||
au=audio/basic
|
||||
avi=video/x-msvideo
|
||||
avs=video/avs-video
|
||||
bcpio=application/x-bcpio
|
||||
bin=application/mac-binary
|
||||
bmp=image/bmp
|
||||
boo=application/book
|
||||
book=application/book
|
||||
boz=application/x-bzip2
|
||||
bsh=application/x-bsh
|
||||
bz2=application/x-bzip2
|
||||
bz=application/x-bzip
|
||||
c++=text/plain
|
||||
c=text/x-c
|
||||
cab=application/vnd.ms-cab-compressed
|
||||
cat=application/vndms-pkiseccat
|
||||
cc=text/x-c
|
||||
ccad=application/clariscad
|
||||
cco=application/x-cocoa
|
||||
cdf=application/cdf
|
||||
cer=application/pkix-cert
|
||||
cha=application/x-chat
|
||||
chat=application/x-chat
|
||||
chrt=application/vnd.kde.kchart
|
||||
class=application/java
|
||||
# ? class=application/java-vm
|
||||
com=text/plain
|
||||
conf=text/plain
|
||||
cpio=application/x-cpio
|
||||
cpp=text/x-c
|
||||
cpt=application/mac-compactpro
|
||||
crl=application/pkcs-crl
|
||||
crt=application/pkix-cert
|
||||
crx=application/x-chrome-extension
|
||||
csh=text/x-scriptcsh
|
||||
css=text/css
|
||||
csv=text/csv
|
||||
cxx=text/plain
|
||||
dar=application/x-dar
|
||||
dcr=application/x-director
|
||||
deb=application/x-debian-package
|
||||
deepv=application/x-deepv
|
||||
def=text/plain
|
||||
der=application/x-x509-ca-cert
|
||||
dif=video/x-dv
|
||||
dir=application/x-director
|
||||
divx=video/divx
|
||||
dl=video/dl
|
||||
dmg=application/x-apple-diskimage
|
||||
doc=application/msword
|
||||
dot=application/msword
|
||||
dp=application/commonground
|
||||
drw=application/drafting
|
||||
dump=application/octet-stream
|
||||
dv=video/x-dv
|
||||
dvi=application/x-dvi
|
||||
dwf=drawing/x-dwf=(old)
|
||||
dwg=application/acad
|
||||
dxf=application/dxf
|
||||
dxr=application/x-director
|
||||
el=text/x-scriptelisp
|
||||
elc=application/x-bytecodeelisp=(compiled=elisp)
|
||||
eml=message/rfc822
|
||||
env=application/x-envoy
|
||||
eps=application/postscript
|
||||
es=application/x-esrehber
|
||||
etx=text/x-setext
|
||||
evy=application/envoy
|
||||
exe=application/octet-stream
|
||||
f77=text/x-fortran
|
||||
f90=text/x-fortran
|
||||
f=text/x-fortran
|
||||
fdf=application/vndfdf
|
||||
fif=application/fractals
|
||||
fli=video/fli
|
||||
flo=image/florian
|
||||
flv=video/x-flv
|
||||
flx=text/vndfmiflexstor
|
||||
fmf=video/x-atomic3d-feature
|
||||
for=text/x-fortran
|
||||
fpx=image/vndfpx
|
||||
frl=application/freeloader
|
||||
funk=audio/make
|
||||
g3=image/g3fax
|
||||
g=text/plain
|
||||
gif=image/gif
|
||||
gl=video/gl
|
||||
gsd=audio/x-gsm
|
||||
gsm=audio/x-gsm
|
||||
gsp=application/x-gsp
|
||||
gss=application/x-gss
|
||||
gtar=application/x-gtar
|
||||
gz=application/x-compressed
|
||||
gzip=application/x-gzip
|
||||
h=text/x-h
|
||||
hdf=application/x-hdf
|
||||
help=application/x-helpfile
|
||||
hgl=application/vndhp-hpgl
|
||||
hh=text/x-h
|
||||
hlb=text/x-script
|
||||
hlp=application/hlp
|
||||
hpg=application/vndhp-hpgl
|
||||
hpgl=application/vndhp-hpgl
|
||||
hqx=application/binhex
|
||||
hta=application/hta
|
||||
htc=text/x-component
|
||||
htm=text/html
|
||||
html=text/html
|
||||
htmls=text/html
|
||||
htt=text/webviewhtml
|
||||
htx=text/html
|
||||
ice=x-conference/x-cooltalk
|
||||
ico=image/x-icon
|
||||
ics=text/calendar
|
||||
icz=text/calendar
|
||||
idc=text/plain
|
||||
ief=image/ief
|
||||
iefs=image/ief
|
||||
iges=application/iges
|
||||
igs=application/iges
|
||||
ima=application/x-ima
|
||||
imap=application/x-httpd-imap
|
||||
inf=application/inf
|
||||
ins=application/x-internett-signup
|
||||
ip=application/x-ip2
|
||||
isu=video/x-isvideo
|
||||
it=audio/it
|
||||
iv=application/x-inventor
|
||||
ivr=i-world/i-vrml
|
||||
ivy=application/x-livescreen
|
||||
jam=audio/x-jam
|
||||
jav=text/x-java-source
|
||||
java=text/x-java-source
|
||||
jcm=application/x-java-commerce
|
||||
jfif-tbnl=image/jpeg
|
||||
jfif=image/jpeg
|
||||
jnlp=application/x-java-jnlp-file
|
||||
jpe=image/jpeg
|
||||
jpeg=image/jpeg
|
||||
jpg=image/jpeg
|
||||
jps=image/x-jps
|
||||
js=application/javascript
|
||||
json=application/json
|
||||
jut=image/jutvision
|
||||
kar=audio/midi
|
||||
karbon=application/vnd.kde.karbon
|
||||
kfo=application/vnd.kde.kformula
|
||||
flw=application/vnd.kde.kivio
|
||||
kml=application/vnd.google-earth.kml+xml
|
||||
kmz=application/vnd.google-earth.kmz
|
||||
kon=application/vnd.kde.kontour
|
||||
kpr=application/vnd.kde.kpresenter
|
||||
kpt=application/vnd.kde.kpresenter
|
||||
ksp=application/vnd.kde.kspread
|
||||
kwd=application/vnd.kde.kword
|
||||
kwt=application/vnd.kde.kword
|
||||
ksh=text/x-scriptksh
|
||||
la=audio/nspaudio
|
||||
lam=audio/x-liveaudio
|
||||
latex=application/x-latex
|
||||
lha=application/lha
|
||||
lhx=application/octet-stream
|
||||
list=text/plain
|
||||
lma=audio/nspaudio
|
||||
log=text/plain
|
||||
lsp=text/x-scriptlisp
|
||||
lst=text/plain
|
||||
lsx=text/x-la-asf
|
||||
ltx=application/x-latex
|
||||
lzh=application/octet-stream
|
||||
lzx=application/lzx
|
||||
m1v=video/mpeg
|
||||
m2a=audio/mpeg
|
||||
m2v=video/mpeg
|
||||
m3u=audio/x-mpegurl
|
||||
m=text/x-m
|
||||
man=application/x-troff-man
|
||||
manifest=text/cache-manifest
|
||||
map=application/x-navimap
|
||||
mar=text/plain
|
||||
mbd=application/mbedlet
|
||||
mc$=application/x-magic-cap-package-10
|
||||
mcd=application/mcad
|
||||
mcf=text/mcf
|
||||
mcp=application/netmc
|
||||
me=application/x-troff-me
|
||||
mht=message/rfc822
|
||||
mhtml=message/rfc822
|
||||
mid=application/x-midi
|
||||
midi=application/x-midi
|
||||
mif=application/x-frame
|
||||
mime=message/rfc822
|
||||
mjf=audio/x-vndaudioexplosionmjuicemediafile
|
||||
mjpg=video/x-motion-jpeg
|
||||
mm=application/base64
|
||||
mme=application/base64
|
||||
mod=audio/mod
|
||||
moov=video/quicktime
|
||||
mov=video/quicktime
|
||||
movie=video/x-sgi-movie
|
||||
mp2=audio/mpeg
|
||||
mp3=audio/mpeg3
|
||||
mp4=video/mp4
|
||||
mpa=audio/mpeg
|
||||
mpc=application/x-project
|
||||
mpe=video/mpeg
|
||||
mpeg=video/mpeg
|
||||
mpg=video/mpeg
|
||||
mpga=audio/mpeg
|
||||
mpp=application/vndms-project
|
||||
mpt=application/x-project
|
||||
mpv=application/x-project
|
||||
mpx=application/x-project
|
||||
mrc=application/marc
|
||||
ms=application/x-troff-ms
|
||||
mv=video/x-sgi-movie
|
||||
my=audio/make
|
||||
mzz=application/x-vndaudioexplosionmzz
|
||||
nap=image/naplps
|
||||
naplps=image/naplps
|
||||
nc=application/x-netcdf
|
||||
ncm=application/vndnokiaconfiguration-message
|
||||
nif=image/x-niff
|
||||
niff=image/x-niff
|
||||
nix=application/x-mix-transfer
|
||||
nsc=application/x-conference
|
||||
nvd=application/x-navidoc
|
||||
o=application/octet-stream
|
||||
oda=application/oda
|
||||
odb=application/vnd.oasis.opendocument.database
|
||||
odc=application/vnd.oasis.opendocument.chart
|
||||
odf=application/vnd.oasis.opendocument.formula
|
||||
odg=application/vnd.oasis.opendocument.graphics
|
||||
odi=application/vnd.oasis.opendocument.image
|
||||
odm=application/vnd.oasis.opendocument.text-master
|
||||
odp=application/vnd.oasis.opendocument.presentation
|
||||
ods=application/vnd.oasis.opendocument.spreadsheet
|
||||
odt=application/vnd.oasis.opendocument.text
|
||||
oga=audio/ogg
|
||||
ogg=audio/ogg
|
||||
ogv=video/ogg
|
||||
omc=application/x-omc
|
||||
omcd=application/x-omcdatamaker
|
||||
omcr=application/x-omcregerator
|
||||
otc=application/vnd.oasis.opendocument.chart-template
|
||||
otf=application/vnd.oasis.opendocument.formula-template
|
||||
otg=application/vnd.oasis.opendocument.graphics-template
|
||||
oth=application/vnd.oasis.opendocument.text-web
|
||||
oti=application/vnd.oasis.opendocument.image-template
|
||||
otm=application/vnd.oasis.opendocument.text-master
|
||||
otp=application/vnd.oasis.opendocument.presentation-template
|
||||
ots=application/vnd.oasis.opendocument.spreadsheet-template
|
||||
ott=application/vnd.oasis.opendocument.text-template
|
||||
p10=application/pkcs10
|
||||
p12=application/pkcs-12
|
||||
p7a=application/x-pkcs7-signature
|
||||
p7c=application/pkcs7-mime
|
||||
p7m=application/pkcs7-mime
|
||||
p7r=application/x-pkcs7-certreqresp
|
||||
p7s=application/pkcs7-signature
|
||||
p=text/x-pascal
|
||||
part=application/pro_eng
|
||||
pas=text/pascal
|
||||
pbm=image/x-portable-bitmap
|
||||
pcl=application/vndhp-pcl
|
||||
pct=image/x-pict
|
||||
pcx=image/x-pcx
|
||||
pdb=chemical/x-pdb
|
||||
pdf=application/pdf
|
||||
pfunk=audio/make
|
||||
pgm=image/x-portable-graymap
|
||||
pic=image/pict
|
||||
pict=image/pict
|
||||
pkg=application/x-newton-compatible-pkg
|
||||
pko=application/vndms-pkipko
|
||||
pl=text/x-scriptperl
|
||||
plx=application/x-pixclscript
|
||||
pm4=application/x-pagemaker
|
||||
pm5=application/x-pagemaker
|
||||
pm=text/x-scriptperl-module
|
||||
png=image/png
|
||||
pnm=application/x-portable-anymap
|
||||
pot=application/mspowerpoint
|
||||
pov=model/x-pov
|
||||
ppa=application/vndms-powerpoint
|
||||
ppm=image/x-portable-pixmap
|
||||
pps=application/mspowerpoint
|
||||
ppt=application/mspowerpoint
|
||||
ppz=application/mspowerpoint
|
||||
pre=application/x-freelance
|
||||
prt=application/pro_eng
|
||||
ps=application/postscript
|
||||
psd=application/octet-stream
|
||||
pvu=paleovu/x-pv
|
||||
pwz=application/vndms-powerpoint
|
||||
py=text/x-scriptphyton
|
||||
pyc=applicaiton/x-bytecodepython
|
||||
qcp=audio/vndqcelp
|
||||
qd3=x-world/x-3dmf
|
||||
qd3d=x-world/x-3dmf
|
||||
qif=image/x-quicktime
|
||||
qt=video/quicktime
|
||||
qtc=video/x-qtc
|
||||
qti=image/x-quicktime
|
||||
qtif=image/x-quicktime
|
||||
ra=audio/x-pn-realaudio
|
||||
ram=audio/x-pn-realaudio
|
||||
rar=application/x-rar-compressed
|
||||
ras=application/x-cmu-raster
|
||||
rast=image/cmu-raster
|
||||
rexx=text/x-scriptrexx
|
||||
rf=image/vndrn-realflash
|
||||
rgb=image/x-rgb
|
||||
rm=application/vndrn-realmedia
|
||||
rmi=audio/mid
|
||||
rmm=audio/x-pn-realaudio
|
||||
rmp=audio/x-pn-realaudio
|
||||
rng=application/ringing-tones
|
||||
rnx=application/vndrn-realplayer
|
||||
roff=application/x-troff
|
||||
rp=image/vndrn-realpix
|
||||
rpm=audio/x-pn-realaudio-plugin
|
||||
rt=text/vndrn-realtext
|
||||
rtf=text/richtext
|
||||
rtx=text/richtext
|
||||
rv=video/vndrn-realvideo
|
||||
s=text/x-asm
|
||||
s3m=audio/s3m
|
||||
s7z=application/x-7z-compressed
|
||||
saveme=application/octet-stream
|
||||
sbk=application/x-tbook
|
||||
scm=text/x-scriptscheme
|
||||
sdml=text/plain
|
||||
sdp=application/sdp
|
||||
sdr=application/sounder
|
||||
sea=application/sea
|
||||
set=application/set
|
||||
sgm=text/x-sgml
|
||||
sgml=text/x-sgml
|
||||
sh=text/x-scriptsh
|
||||
shar=application/x-bsh
|
||||
shtml=text/x-server-parsed-html
|
||||
sid=audio/x-psid
|
||||
skd=application/x-koan
|
||||
skm=application/x-koan
|
||||
skp=application/x-koan
|
||||
skt=application/x-koan
|
||||
sit=application/x-stuffit
|
||||
sitx=application/x-stuffitx
|
||||
sl=application/x-seelogo
|
||||
smi=application/smil
|
||||
smil=application/smil
|
||||
snd=audio/basic
|
||||
sol=application/solids
|
||||
spc=text/x-speech
|
||||
spl=application/futuresplash
|
||||
spr=application/x-sprite
|
||||
sprite=application/x-sprite
|
||||
spx=audio/ogg
|
||||
src=application/x-wais-source
|
||||
ssi=text/x-server-parsed-html
|
||||
ssm=application/streamingmedia
|
||||
sst=application/vndms-pkicertstore
|
||||
step=application/step
|
||||
stl=application/sla
|
||||
stp=application/step
|
||||
sv4cpio=application/x-sv4cpio
|
||||
sv4crc=application/x-sv4crc
|
||||
svf=image/vnddwg
|
||||
svg=image/svg+xml
|
||||
svr=application/x-world
|
||||
swf=application/x-shockwave-flash
|
||||
t=application/x-troff
|
||||
talk=text/x-speech
|
||||
tar=application/x-tar
|
||||
tbk=application/toolbook
|
||||
tcl=text/x-scripttcl
|
||||
tcsh=text/x-scripttcsh
|
||||
tex=application/x-tex
|
||||
texi=application/x-texinfo
|
||||
texinfo=application/x-texinfo
|
||||
text=text/plain
|
||||
tgz=application/gnutar
|
||||
tif=image/tiff
|
||||
tiff=image/tiff
|
||||
tr=application/x-troff
|
||||
tsi=audio/tsp-audio
|
||||
tsp=application/dsptype
|
||||
tsv=text/tab-separated-values
|
||||
turbot=image/florian
|
||||
txt=text/plain
|
||||
uil=text/x-uil
|
||||
uni=text/uri-list
|
||||
unis=text/uri-list
|
||||
unv=application/i-deas
|
||||
uri=text/uri-list
|
||||
uris=text/uri-list
|
||||
ustar=application/x-ustar
|
||||
uu=text/x-uuencode
|
||||
uue=text/x-uuencode
|
||||
vcd=application/x-cdlink
|
||||
vcf=text/x-vcard
|
||||
vcard=text/x-vcard
|
||||
vcs=text/x-vcalendar
|
||||
vda=application/vda
|
||||
vdo=video/vdo
|
||||
vew=application/groupwise
|
||||
viv=video/vivo
|
||||
vivo=video/vivo
|
||||
vmd=application/vocaltec-media-desc
|
||||
vmf=application/vocaltec-media-file
|
||||
voc=audio/voc
|
||||
vos=video/vosaic
|
||||
vox=audio/voxware
|
||||
vqe=audio/x-twinvq-plugin
|
||||
vqf=audio/x-twinvq
|
||||
vql=audio/x-twinvq-plugin
|
||||
vrml=application/x-vrml
|
||||
vrt=x-world/x-vrt
|
||||
vsd=application/x-visio
|
||||
vst=application/x-visio
|
||||
vsw=application/x-visio
|
||||
w60=application/wordperfect60
|
||||
w61=application/wordperfect61
|
||||
w6w=application/msword
|
||||
wav=audio/wav
|
||||
wb1=application/x-qpro
|
||||
wbmp=image/vnd.wap.wbmp
|
||||
web=application/vndxara
|
||||
wiz=application/msword
|
||||
wk1=application/x-123
|
||||
wmf=windows/metafile
|
||||
wml=text/vnd.wap.wml
|
||||
wmlc=application/vnd.wap.wmlc
|
||||
wmls=text/vnd.wap.wmlscript
|
||||
wmlsc=application/vnd.wap.wmlscriptc
|
||||
word=application/msword
|
||||
wp5=application/wordperfect
|
||||
wp6=application/wordperfect
|
||||
wp=application/wordperfect
|
||||
wpd=application/wordperfect
|
||||
wq1=application/x-lotus
|
||||
wri=application/mswrite
|
||||
wrl=application/x-world
|
||||
wrz=model/vrml
|
||||
wsc=text/scriplet
|
||||
wsrc=application/x-wais-source
|
||||
wtk=application/x-wintalk
|
||||
x-png=image/png
|
||||
xbm=image/x-xbitmap
|
||||
xdr=video/x-amt-demorun
|
||||
xgz=xgl/drawing
|
||||
xif=image/vndxiff
|
||||
xl=application/excel
|
||||
xla=application/excel
|
||||
xlb=application/excel
|
||||
xlc=application/excel
|
||||
xld=application/excel
|
||||
xlk=application/excel
|
||||
xll=application/excel
|
||||
xlm=application/excel
|
||||
xls=application/excel
|
||||
xlt=application/excel
|
||||
xlv=application/excel
|
||||
xlw=application/excel
|
||||
xm=audio/xm
|
||||
xml=text/xml
|
||||
xmz=xgl/movie
|
||||
xpix=application/x-vndls-xpix
|
||||
xpm=image/x-xpixmap
|
||||
xsr=video/x-amt-showrun
|
||||
xwd=image/x-xwd
|
||||
xyz=chemical/x-pdb
|
||||
z=application/x-compress
|
||||
zip=application/zip
|
||||
zoo=application/octet-stream
|
||||
zsh=text/x-scriptzsh
|
||||
# Office 2007 mess - http://wdg.uncc.edu/Microsoft_Office_2007_MIME_Types_for_Apache_and_IIS
|
||||
docx=application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
||||
docm=application/vnd.ms-word.document.macroEnabled.12
|
||||
dotx=application/vnd.openxmlformats-officedocument.wordprocessingml.template
|
||||
dotm=application/vnd.ms-word.template.macroEnabled.12
|
||||
xlsx=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||
xlsm=application/vnd.ms-excel.sheet.macroEnabled.12
|
||||
xltx=application/vnd.openxmlformats-officedocument.spreadsheetml.template
|
||||
xltm=application/vnd.ms-excel.template.macroEnabled.12
|
||||
xlsb=application/vnd.ms-excel.sheet.binary.macroEnabled.12
|
||||
xlam=application/vnd.ms-excel.addin.macroEnabled.12
|
||||
pptx=application/vnd.openxmlformats-officedocument.presentationml.presentation
|
||||
pptm=application/vnd.ms-powerpoint.presentation.macroEnabled.12
|
||||
ppsx=application/vnd.openxmlformats-officedocument.presentationml.slideshow
|
||||
ppsm=application/vnd.ms-powerpoint.slideshow.macroEnabled.12
|
||||
potx=application/vnd.openxmlformats-officedocument.presentationml.template
|
||||
potm=application/vnd.ms-powerpoint.template.macroEnabled.12
|
||||
ppam=application/vnd.ms-powerpoint.addin.macroEnabled.12
|
||||
sldx=application/vnd.openxmlformats-officedocument.presentationml.slide
|
||||
sldm=application/vnd.ms-powerpoint.slide.macroEnabled.12
|
||||
thmx=application/vnd.ms-officetheme
|
||||
onetoc=application/onenote
|
||||
onetoc2=application/onenote
|
||||
onetmp=application/onenote
|
||||
onepkg=application/onenote
|
||||
# koffice
|
||||
|
||||
# iWork
|
||||
key=application/x-iwork-keynote-sffkey
|
||||
kth=application/x-iwork-keynote-sffkth
|
||||
nmbtemplate=application/x-iwork-numbers-sfftemplate
|
||||
numbers=application/x-iwork-numbers-sffnumbers
|
||||
pages=application/x-iwork-pages-sffpages
|
||||
template=application/x-iwork-pages-sfftemplate
|
||||
|
||||
# Extensions for Mozilla apps (Firefox and friends)
|
||||
xpi=application/x-xpinstall
|
||||
|
||||
# Opera extensions
|
||||
oex=application/x-opera-extension
|
||||
@@ -1,100 +0,0 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/revel/revel"
|
||||
"os"
|
||||
fpath "path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type Static struct {
|
||||
*revel.Controller
|
||||
}
|
||||
|
||||
// This method handles requests for files. The supplied prefix may be absolute
|
||||
// or relative. If the prefix is relative it is assumed to be relative to the
|
||||
// application directory. The filepath may either be just a file or an
|
||||
// additional filepath to search for the given file. This response may return
|
||||
// the following responses in the event of an error or invalid request;
|
||||
// 403(Forbidden): If the prefix filepath combination results in a directory.
|
||||
// 404(Not found): If the prefix and filepath combination results in a non-existent file.
|
||||
// 500(Internal Server Error): There are a few edge cases that would likely indicate some configuration error outside of revel.
|
||||
//
|
||||
// Note that when defining routes in routes/conf the parameters must not have
|
||||
// spaces around the comma.
|
||||
// Bad: Static.Serve("public/img", "favicon.png")
|
||||
// Good: Static.Serve("public/img","favicon.png")
|
||||
//
|
||||
// Examples:
|
||||
// Serving a directory
|
||||
// Route (conf/routes):
|
||||
// GET /public/{<.*>filepath} Static.Serve("public")
|
||||
// Request:
|
||||
// public/js/sessvars.js
|
||||
// Calls
|
||||
// Static.Serve("public","js/sessvars.js")
|
||||
//
|
||||
// Serving a file
|
||||
// Route (conf/routes):
|
||||
// GET /favicon.ico Static.Serve("public/img","favicon.png")
|
||||
// Request:
|
||||
// favicon.ico
|
||||
// Calls:
|
||||
// Static.Serve("public/img", "favicon.png")
|
||||
func (c Static) Serve(prefix, filepath string) revel.Result {
|
||||
var basePath string
|
||||
|
||||
if !fpath.IsAbs(prefix) {
|
||||
basePath = revel.BasePath
|
||||
}
|
||||
|
||||
basePathPrefix := fpath.Join(basePath, fpath.FromSlash(prefix))
|
||||
fname := fpath.Join(basePathPrefix, fpath.FromSlash(filepath))
|
||||
if !strings.HasPrefix(fname, basePathPrefix) {
|
||||
revel.WARN.Printf("Attempted to read file outside of base path: %s", fname)
|
||||
return c.NotFound("")
|
||||
}
|
||||
|
||||
finfo, err := os.Stat(fname)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) || err.(*os.PathError).Err == syscall.ENOTDIR {
|
||||
revel.WARN.Printf("File not found (%s): %s ", fname, err)
|
||||
return c.NotFound("File not found")
|
||||
}
|
||||
revel.ERROR.Printf("Error trying to get fileinfo for '%s': %s", fname, err)
|
||||
return c.RenderError(err)
|
||||
}
|
||||
|
||||
if finfo.Mode().IsDir() {
|
||||
revel.WARN.Printf("Attempted directory listing of %s", fname)
|
||||
return c.Forbidden("Directory listing not allowed")
|
||||
}
|
||||
|
||||
file, err := os.Open(fname)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
revel.WARN.Printf("File not found (%s): %s ", fname, err)
|
||||
return c.NotFound("File not found")
|
||||
}
|
||||
revel.ERROR.Printf("Error opening '%s': %s", fname, err)
|
||||
return c.RenderError(err)
|
||||
}
|
||||
return c.RenderFile(file, revel.Inline)
|
||||
}
|
||||
|
||||
// This method allows modules to serve binary files. The parameters are the same
|
||||
// as Static.Serve with the additional module name pre-pended to the list of
|
||||
// arguments.
|
||||
func (c Static) ServeModule(moduleName, prefix, filepath string) revel.Result {
|
||||
var basePath string
|
||||
for _, module := range revel.Modules {
|
||||
if module.Name == moduleName {
|
||||
basePath = module.Path
|
||||
}
|
||||
}
|
||||
|
||||
absPath := fpath.Join(basePath, fpath.FromSlash(prefix))
|
||||
|
||||
return c.Serve(absPath, filepath)
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/revel/revel"
|
||||
"html"
|
||||
"html/template"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type TestRunner struct {
|
||||
*revel.Controller
|
||||
}
|
||||
|
||||
type TestSuiteDesc struct {
|
||||
Name string
|
||||
Tests []TestDesc
|
||||
}
|
||||
|
||||
type TestDesc struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
type TestSuiteResult struct {
|
||||
Name string
|
||||
Passed bool
|
||||
Results []TestResult
|
||||
}
|
||||
|
||||
type TestResult struct {
|
||||
Name string
|
||||
Passed bool
|
||||
ErrorHtml template.HTML
|
||||
ErrorSummary string
|
||||
}
|
||||
|
||||
var NONE = []reflect.Value{}
|
||||
|
||||
func (c TestRunner) Index() revel.Result {
|
||||
var testSuites []TestSuiteDesc
|
||||
for _, testSuite := range revel.TestSuites {
|
||||
testSuites = append(testSuites, DescribeSuite(testSuite))
|
||||
}
|
||||
return c.Render(testSuites)
|
||||
}
|
||||
|
||||
// Run runs a single test, given by the argument.
|
||||
func (c TestRunner) Run(suite, test string) revel.Result {
|
||||
result := TestResult{Name: test}
|
||||
for _, testSuite := range revel.TestSuites {
|
||||
t := reflect.TypeOf(testSuite).Elem()
|
||||
if t.Name() != suite {
|
||||
continue
|
||||
}
|
||||
|
||||
// Found the suite, create a new instance and run the named method.
|
||||
v := reflect.New(t)
|
||||
func() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
error := revel.NewErrorFromPanic(err)
|
||||
if error == nil {
|
||||
result.ErrorHtml = template.HTML(html.EscapeString(fmt.Sprint(err)))
|
||||
} else {
|
||||
var buffer bytes.Buffer
|
||||
tmpl, _ := revel.MainTemplateLoader.Template("TestRunner/FailureDetail.html")
|
||||
tmpl.Render(&buffer, error)
|
||||
result.ErrorSummary = errorSummary(error)
|
||||
result.ErrorHtml = template.HTML(buffer.String())
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Initialize the test suite with a NewTestSuite()
|
||||
testSuiteInstance := v.Elem().FieldByName("TestSuite")
|
||||
testSuiteInstance.Set(reflect.ValueOf(revel.NewTestSuite()))
|
||||
|
||||
// Call Before(), call the test, and call After().
|
||||
if m := v.MethodByName("Before"); m.IsValid() {
|
||||
m.Call(NONE)
|
||||
}
|
||||
|
||||
if m := v.MethodByName("After"); m.IsValid() {
|
||||
defer m.Call(NONE)
|
||||
}
|
||||
|
||||
v.MethodByName(test).Call(NONE)
|
||||
|
||||
// No panic means success.
|
||||
result.Passed = true
|
||||
}()
|
||||
break
|
||||
}
|
||||
return c.RenderJson(result)
|
||||
}
|
||||
|
||||
// List returns a JSON list of test suites and tests.
|
||||
// Used by the "test" command line tool.
|
||||
func (c TestRunner) List() revel.Result {
|
||||
var testSuites []TestSuiteDesc
|
||||
for _, testSuite := range revel.TestSuites {
|
||||
testSuites = append(testSuites, DescribeSuite(testSuite))
|
||||
}
|
||||
return c.RenderJson(testSuites)
|
||||
}
|
||||
|
||||
func DescribeSuite(testSuite interface{}) TestSuiteDesc {
|
||||
t := reflect.TypeOf(testSuite)
|
||||
|
||||
// Get a list of methods of the embedded test type.
|
||||
super := t.Elem().Field(0).Type
|
||||
superMethodNameSet := map[string]struct{}{}
|
||||
for i := 0; i < super.NumMethod(); i++ {
|
||||
superMethodNameSet[super.Method(i).Name] = struct{}{}
|
||||
}
|
||||
|
||||
// Get a list of methods on the test suite that take no parameters, return
|
||||
// no results, and were not part of the embedded type's method set.
|
||||
var tests []TestDesc
|
||||
for i := 0; i < t.NumMethod(); i++ {
|
||||
m := t.Method(i)
|
||||
mt := m.Type
|
||||
_, isSuperMethod := superMethodNameSet[m.Name]
|
||||
if mt.NumIn() == 1 &&
|
||||
mt.NumOut() == 0 &&
|
||||
mt.In(0) == t &&
|
||||
!isSuperMethod &&
|
||||
strings.HasPrefix(m.Name, "Test") {
|
||||
tests = append(tests, TestDesc{m.Name})
|
||||
}
|
||||
}
|
||||
|
||||
return TestSuiteDesc{
|
||||
Name: t.Elem().Name(),
|
||||
Tests: tests,
|
||||
}
|
||||
}
|
||||
|
||||
func errorSummary(error *revel.Error) string {
|
||||
var message = fmt.Sprintf("%4sStatus: %s\n%4sIn %s", "", error.Description, "", error.Path)
|
||||
if error.Line != 0 {
|
||||
message += fmt.Sprintf(" (around line %d): ", error.Line)
|
||||
for _, line := range error.ContextSource() {
|
||||
if line.IsError {
|
||||
message += line.Source
|
||||
}
|
||||
}
|
||||
}
|
||||
return message
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/revel/revel"
|
||||
)
|
||||
|
||||
func init() {
|
||||
revel.OnAppStart(func() {
|
||||
fmt.Println("Go to /@tests to run the tests.")
|
||||
})
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
<b>{{.Description}}</b><br>
|
||||
In {{.Path}}
|
||||
{{if .Line}}
|
||||
(around {{if .Line}}line {{.Line}}{{end}}{{if .Column}} column {{.Column}}{{end}})
|
||||
{{end}}:
|
||||
{{range .ContextSource}}{{if .IsError}}<code>{{.Source}}</code>{{end}}{{end}}<br>
|
||||
<a style="cursor:pointer;"
|
||||
onclick="x=this.nextSibling.style;if(!x.display)x.display='none';else x.display=''">
|
||||
Show Stack</a><pre style="display:none;">{{.Stack}}</pre>
|
||||
@@ -1,84 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Revel Test Runner</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<link href="/@tests/public/css/bootstrap.css" type="text/css" rel="stylesheet"></link>
|
||||
<script src="/@tests/public/js/jquery-1.9.1.min.js" type="text/javascript"></script>
|
||||
<style>
|
||||
header { padding:20px 0; background-color:#ADD8E6 }
|
||||
.passed td { background-color: #90EE90 !important; }
|
||||
.failed td { background-color: #FFB6C1 !important; }
|
||||
.tests td.name, .tests td.result { padding-top: 13px; }
|
||||
pre { font-size:10px; white-space: pre; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="container">
|
||||
<table><tr><td>
|
||||
<h1>Test Runner</h1>
|
||||
<p class="lead">Run all of your application's tests from here.</p>
|
||||
</td><td style="padding-left:150px;">
|
||||
<button class="btn btn-large" all-tests="">Run All Tests</button>
|
||||
</td></tr></table>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
{{range .testSuites}}
|
||||
<p class="lead" style="margin-top:20px;">{{.Name}}</p>
|
||||
<table class="table table-striped tests" suite="{{.Name}}">
|
||||
{{range .Tests}}
|
||||
<tr>
|
||||
<td class="name">{{.Name}}</td>
|
||||
<td class="result">
|
||||
</td>
|
||||
<td><button test="{{.Name}}" class="btn">Run</button></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var running = 0;
|
||||
|
||||
$("button[test]").click(function() {
|
||||
var button = $(this).addClass("disabled").text("Running");
|
||||
running += 1;
|
||||
runTest(button);
|
||||
});
|
||||
|
||||
$("button[all-tests]").click(function() {
|
||||
var button = $(this).addClass("disabled").text("Running");
|
||||
$("button[test]").click();
|
||||
});
|
||||
|
||||
function runTest(button) {
|
||||
var suite = button.parents("table").attr("suite");
|
||||
var test = button.attr("test");
|
||||
var row = button.parents("tr");
|
||||
var resultCell = row.children(".result");
|
||||
$.ajax({
|
||||
dataType: "json",
|
||||
url: "/@tests/"+suite+"/"+test,
|
||||
async: false,
|
||||
success: function(result) {
|
||||
row.attr("class", result.Passed ? "passed" : "failed");
|
||||
if (result.Passed) {
|
||||
resultCell.html("");
|
||||
} else {
|
||||
resultCell.html(result.ErrorHtml);
|
||||
}
|
||||
button.removeClass("disabled").text("Run");
|
||||
running -= 1;
|
||||
if (running == 0) {
|
||||
$("button[all-tests]").removeClass("disabled").text("Run All Tests");
|
||||
}
|
||||
}});
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,47 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Revel Test Runner</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #333333;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
header { padding:20px 0; }
|
||||
header.passed { background-color: #90EE90 !important; }
|
||||
header.failed { background-color: #FFB6C1 !important; }
|
||||
table { margin-top: 20px; padding: 8px; line-height: 20px; }
|
||||
td { vertical-align: top; padding-right:20px; }
|
||||
a { color: #0088cc; }
|
||||
.container { margin-left: auto; margin-right: auto; width: 940px; }
|
||||
.result.failed b { font-weight:bold; color: #C00; font-size: 14px; }
|
||||
.result.failed span { color: #C00; font-size: 14px; }
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<header class="{{if .Passed}}passed{{else}}failed{{end}}">
|
||||
<div class="container">
|
||||
<h1>{{.Name}}</h1>
|
||||
<p>{{if .Passed}}PASSED{{else}}FAILED{{end}}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<table>
|
||||
{{range .Results}}
|
||||
<tr class="result {{if .Passed}}passed{{else}}failed{{end}}">
|
||||
<td><span>{{.Name}}</span></td>
|
||||
<td>{{if .ErrorHtml}}{{.ErrorHtml}}{{else}}PASSED{{end}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
GET /@tests TestRunner.Index
|
||||
GET /@tests.list TestRunner.List
|
||||
GET /@tests/public/*filepath Static.ServeModule(testrunner,public)
|
||||
GET /@tests/:suite/:test TestRunner.Run
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 5.5 KiB |
File diff suppressed because one or more lines are too long
@@ -1,16 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Forbidden</title>
|
||||
</head>
|
||||
<body>
|
||||
{{with .Error}}
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{.Description}}
|
||||
</p>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"title": "{{js .Error.Title}}",
|
||||
"description": "{{js .Error.Description}}"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{{.Error.Title}}
|
||||
|
||||
{{.Error.Description}}
|
||||
@@ -1 +0,0 @@
|
||||
<forbidden>{{.Error.Description}}</forbidden>
|
||||
@@ -1,63 +0,0 @@
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Helvetica, Arial, Sans;
|
||||
background: #EEEEEE;
|
||||
}
|
||||
.block {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
#header h1 {
|
||||
font-weight: normal;
|
||||
font-size: 28px;
|
||||
margin: 0;
|
||||
}
|
||||
#more {
|
||||
color: #666;
|
||||
font-size: 80%;
|
||||
border: none;
|
||||
}
|
||||
#header {
|
||||
background: #FFFFCC;
|
||||
}
|
||||
#header p {
|
||||
color: #333;
|
||||
}
|
||||
#routes {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
#routes h2 {
|
||||
font-weight: normal;
|
||||
font-size: 18px;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
#routes ol {
|
||||
|
||||
}
|
||||
#routes li {
|
||||
font-size: 14px;
|
||||
font-family: monospace;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="header" class="block">
|
||||
{{with .Error}}
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{.Description}}
|
||||
</p>
|
||||
{{end}}
|
||||
</div>
|
||||
<div id="routes" class="block">
|
||||
<h2>These routes have been tried, in this order :</h2>
|
||||
<ol>
|
||||
{{range .Router.Routes}}
|
||||
<li>{{pad .Method 10}}{{pad .Path 50}}{{.Action}}</li>
|
||||
{{end}}
|
||||
</ol>
|
||||
</div>
|
||||
@@ -1,26 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Not found</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{{if .DevMode}}
|
||||
|
||||
{{template "errors/404-dev.html" .}}
|
||||
|
||||
{{else}}
|
||||
|
||||
{{with .Error}}
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{.Description}}
|
||||
</p>
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"title": "{{js .Error.Title}}",
|
||||
"description": "{{js .Error.Description}}"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{{.Error.Title}}
|
||||
|
||||
{{.Error.Description}}
|
||||
@@ -1 +0,0 @@
|
||||
<notfound>{{.Error.Description}}</notfound>
|
||||
@@ -1,118 +0,0 @@
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Helvetica, Arial, Sans;
|
||||
background: #EEEEEE;
|
||||
}
|
||||
.block {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
#header h1 {
|
||||
font-weight: normal;
|
||||
font-size: 28px;
|
||||
margin: 0;
|
||||
}
|
||||
#more {
|
||||
color: #666;
|
||||
font-size: 80%;
|
||||
border: none;
|
||||
}
|
||||
#header {
|
||||
background: #fcd2da;
|
||||
}
|
||||
#header p {
|
||||
color: #333;
|
||||
}
|
||||
#source {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
#source h2 {
|
||||
font-weight: normal;
|
||||
font-size: 18px;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
#source .lineNumber {
|
||||
float: left;
|
||||
display: block;
|
||||
width: 40px;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
font-size: 14px;
|
||||
font-family: monospace;
|
||||
background: #333;
|
||||
color: #fff;
|
||||
}
|
||||
#source .line {
|
||||
clear: both;
|
||||
color: #333;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
#source pre {
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
#source .error {
|
||||
color: #c00 !important;
|
||||
}
|
||||
#source .error .lineNumber {
|
||||
background: #c00;
|
||||
}
|
||||
#source a {
|
||||
text-decoration: none;
|
||||
}
|
||||
#source a:hover * {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
#source a:hover pre {
|
||||
background: #FAFFCF !important;
|
||||
}
|
||||
#source em {
|
||||
font-style: normal;
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
}
|
||||
#source strong {
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
{{with .Error}}
|
||||
<div id="header" class="block">
|
||||
<h1>
|
||||
{{.Title}}
|
||||
</h1>
|
||||
<p>
|
||||
{{if .SourceType}}
|
||||
The {{.SourceType}} <strong>{{.Path}}</strong> does not compile: <strong>{{.Description}}</strong>
|
||||
{{else}}
|
||||
{{.Description}}
|
||||
{{end}}
|
||||
</p>
|
||||
</div>
|
||||
{{if .Path}}
|
||||
<div id="source" class="block">
|
||||
<h2>In {{.Path}}
|
||||
{{if .Line}}
|
||||
(around {{if .Line}}line {{.Line}}{{end}}{{if .Column}} column {{.Column}}{{end}})
|
||||
{{end}}
|
||||
</h2>
|
||||
{{range .ContextSource}}
|
||||
<div class="line {{if .IsError}}error{{end}}">
|
||||
<span class="lineNumber">{{.Line}}:</span>
|
||||
<pre>{{.Source}}</pre>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .MetaError}}
|
||||
<div id="source" class="block">
|
||||
<h2>Additionally, an error occurred while handling this error.</h2>
|
||||
<div class="line error">
|
||||
{{.MetaError}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,16 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Application error</title>
|
||||
</head>
|
||||
<body>
|
||||
{{if .DevMode}}
|
||||
{{template "errors/500-dev.html" .}}
|
||||
{{else}}
|
||||
<h1>Oops, an error occured</h1>
|
||||
<p>
|
||||
This exception has been logged.
|
||||
</p>
|
||||
{{end}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"title": "{{js .Error.Title}}",
|
||||
"description": "{{js .Error.Description}}"
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{{.Error.Title}}
|
||||
{{.Error.Description}}
|
||||
|
||||
{{if eq .RunMode "dev"}}
|
||||
{{with .Error}}
|
||||
{{if .Path}}
|
||||
----------
|
||||
In {{.Path}} {{if .Line}}(around line {{.Line}}){{end}}
|
||||
|
||||
{{range .ContextSource}}
|
||||
{{if .IsError}}>{{else}} {{end}} {{.Line}}: {{.Source}}{{end}}
|
||||
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,4 +0,0 @@
|
||||
<error>
|
||||
<title>{{.Error.Title}}</title>
|
||||
<description>{{.Error.Description}}</description>
|
||||
</error>
|
||||
@@ -1,70 +0,0 @@
|
||||
#------------------------
|
||||
# leanote config
|
||||
#------------------------
|
||||
|
||||
http.port=80
|
||||
|
||||
site.url=http://localhost # or http://x.com:8080, http://www.xx.com:9000
|
||||
|
||||
# mongdb
|
||||
db.host=localhost
|
||||
db.port=27017
|
||||
db.dbname=leanote # required
|
||||
db.username=root # if not exists, please leave it blank
|
||||
db.password=root123 # if not exists, please leave it blank
|
||||
# or you can set the mongdb url for more complex needs the format is:
|
||||
# mongodb://myuser:mypass@localhost:40001,otherhost:40001/mydb
|
||||
# db.url=mongodb://root:root123@localhost:27017/leanote
|
||||
|
||||
# You Must Change It !! About Security!!
|
||||
app.secret=V85ZzBeTnzpsHyjQX4zukbQ8qqtju9y2aDM55VWxAH9Qop19poekx3xkcDVvrD0y
|
||||
|
||||
app.name=leanote
|
||||
http.addr=
|
||||
http.ssl=false
|
||||
cookie.domain=
|
||||
cookie.httponly=false
|
||||
cookie.prefix=LEANOTE
|
||||
cookie.secure=false
|
||||
format.date=01/02/2006
|
||||
format.datetime=01/02/2006 15:04
|
||||
results.chunked=false
|
||||
|
||||
#--------------------------------
|
||||
# revel config
|
||||
# for dev
|
||||
#--------------------------------
|
||||
|
||||
log.trace.prefix = "TRACE "
|
||||
log.info.prefix = "INFO "
|
||||
log.warn.prefix = "WARN "
|
||||
log.error.prefix = "ERROR "
|
||||
|
||||
# The default language of this application.
|
||||
i18n.default_language=en
|
||||
|
||||
module.static=github.com/revel/revel/modules/static
|
||||
|
||||
[dev]
|
||||
mode.dev=true
|
||||
results.pretty=true
|
||||
watch=true
|
||||
|
||||
module.testrunner = github.com/revel/revel/modules/testrunner
|
||||
|
||||
log.trace.output = stderr
|
||||
log.info.output = stderr
|
||||
log.warn.output = stderr
|
||||
log.error.output = stderr
|
||||
|
||||
[prod]
|
||||
mode.dev=false
|
||||
results.pretty=false
|
||||
watch=false
|
||||
|
||||
module.testrunner =
|
||||
|
||||
log.trace.output = off
|
||||
log.info.output = off
|
||||
log.warn.output = %(app.name)s.log
|
||||
log.error.output = %(app.name)s.log
|
||||
@@ -5,7 +5,7 @@
|
||||
module:testrunner
|
||||
|
||||
# Home is My Blog
|
||||
Get / Index.Default
|
||||
Get / Index.Index
|
||||
GET /note Note.Index
|
||||
# leanote home
|
||||
GET /index Index.Index
|
||||
@@ -23,6 +23,25 @@ GET /findPassword Auth.FindPassword
|
||||
POST /doFindPassword Auth.DoFindPassword
|
||||
POST /findPasswordUpdate Auth.FindPasswordUpdate
|
||||
|
||||
#####
|
||||
# 这么多列表, 只是为了最后一句pjax
|
||||
# note
|
||||
* /note/listNotes Note.ListNotes
|
||||
* /note/listTrashNotes Note.ListTrashNotes
|
||||
* /note/getNoteAndContent Note.GetNoteAndContent
|
||||
* /note/getNoteContent Note.GetNoteContent
|
||||
* /note/updateNoteOrContent Note.UpdateNoteOrContent
|
||||
* /note/deleteNote Note.DeleteNote
|
||||
* /note/deleteTrash Note.DeleteTrash
|
||||
* /note/moveNote Note.MoveNote
|
||||
* /note/copyNote Note.CopyNote
|
||||
* /note/copySharedNote Note.CopySharedNote
|
||||
* /note/searchNoteByTags Note.SearchNoteByTags
|
||||
* /note/toImage Note.ToImage
|
||||
* /note/html2Image Note.Html2Image
|
||||
* /note/setNote2Blog Note.SetNote2Blog
|
||||
# pjax
|
||||
GET /note/:noteId Note.Index
|
||||
|
||||
# blog
|
||||
|
||||
@@ -64,7 +83,6 @@ GET /blog/:userIdOrEmail Blog.Index
|
||||
GET /blog Blog.Index
|
||||
GET /blog/* Blog.E()
|
||||
|
||||
|
||||
#---------------
|
||||
# preview
|
||||
GET /preview/tags/:userIdOrEmail Preview.Tags
|
||||
@@ -82,13 +100,13 @@ GET /preview/archives Preview.Archives
|
||||
GET /preview/view/:noteId Preview.Post
|
||||
|
||||
GET /preview/post/:noteId Preview.Post
|
||||
GET /preview/post/userIdOrEmail/:noteId Preview.Post
|
||||
GET /preview/post/:userIdOrEmail/:noteId Preview.Post
|
||||
|
||||
GET /preview/single/userIdOrEmail/:singleId Preview.Single
|
||||
GET /preview/single/:userIdOrEmail/:singleId Preview.Single
|
||||
GET /preview/single/:singleId Preview.Single
|
||||
|
||||
GET /preview/cate/:notebookId Preview.Cate
|
||||
GET /preview/cate/userIdOrEmail/:notebookId Preview.Cate
|
||||
GET /preview/cate/:userIdOrEmail/:notebookId Preview.Cate
|
||||
|
||||
GET /preview/:userIdOrEmail Preview.Index
|
||||
GET /preview Preview.Index
|
||||
@@ -110,7 +128,8 @@ GET /upload/*filepath Static.Serve("public/upload")
|
||||
* /member MemberIndex.Index
|
||||
* /member/index MemberIndex.Index
|
||||
|
||||
GET /share/note/:noteId Share.ShowShareNote
|
||||
# common
|
||||
* /:controller/:action :controller.:action
|
||||
* /api/:controller/:action :controller.:action
|
||||
* /member/:controller/:action :controller.:action
|
||||
* /member/:controller/:action :controller.:action
|
||||
BIN
leanote.png
Normal file
BIN
leanote.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 305 KiB |
@@ -79,7 +79,7 @@ myBlog=Blog
|
||||
history=Histories
|
||||
save=Save
|
||||
editorTips=Tips
|
||||
editorTipsInfo=<h4>1. Short cuts</h4>ctrl+shift+c Toggle code <br /> ctrl+shift+i Insert/edit image <h4>2. shift+enter Get out of current block</h4> eg. <img src="/images/outofcode.png" style="width: 90px"/> in this situation you can use shift+enter to get out of current code block.
|
||||
editorTipsInfo=<h4>1. Short cuts</h4>ctrl+shift+c Toggle code<h4>2. shift+enter Get out of current block</h4> eg. <img src="/images/outofcode.png" style="width: 90px"/> in this situation you can use shift+enter to get out of current code block.
|
||||
newNote=New note
|
||||
newMarkdownNote=New Markdown Note
|
||||
noNoteNewNoteTips=The notebook is empty, why not...
|
||||
@@ -129,9 +129,12 @@ themeSetting=Theme
|
||||
setAvatar=Avatar
|
||||
logout=Logout
|
||||
basicInfo=Basic
|
||||
basicInfoSet=Blog Basic Setting
|
||||
updateEmail=Update email
|
||||
usernameSetting=Update username
|
||||
username=Username
|
||||
avatar=Avatar
|
||||
chooseImage=Choose Image
|
||||
oldPassword=Old password
|
||||
newPassword=New password
|
||||
admin=Admin
|
||||
@@ -144,7 +147,7 @@ uploadImage=Upload image
|
||||
|
||||
# blog
|
||||
aboutMe=About me
|
||||
blogSet=Set blog
|
||||
blogSet=Blog Settings
|
||||
|
||||
# index
|
||||
discussion=Discussion
|
||||
@@ -235,6 +238,7 @@ subDomainExisted=Sub domain is already existed
|
||||
domainNotPointToLeanote=The custom domin hasn't pointed to d.leanote.com
|
||||
errorPerPageSize=Page size is error
|
||||
errorSortField=Sort Field is error
|
||||
themeValidHasRoundInclude=WARNING: Templates have circular references!
|
||||
|
||||
# lea++
|
||||
leaDesc=leanote blog platform
|
||||
@@ -243,8 +247,94 @@ latest=Latest
|
||||
|
||||
# 用户中心
|
||||
memberCenter=Member Center
|
||||
userNotExists=该成员沿未注册
|
||||
hasUsers=已存在该成员
|
||||
userNotExists=The user is not exists
|
||||
hasUsers=The user already exists
|
||||
|
||||
# yu
|
||||
service=Service
|
||||
imageSizeOver=Sorry, you have no image opacity, please <a href="/service">upgrade your account</a>.
|
||||
attachSizeOver=Sorry, you have no attachment opacity, please <a href="/service">upgrade your account</a>.
|
||||
|
||||
|
||||
#memeber
|
||||
welcomeToLeanote=Welcome
|
||||
accountInfo=Account Info
|
||||
accountType=Account Type
|
||||
premiumAccountType=Premium
|
||||
normalAccountType=Normal
|
||||
imageSize=Image Opacity
|
||||
attachSize=Attachment Opacity
|
||||
upgrade=Upgrade My Account
|
||||
leanoteEvents=Leanote News
|
||||
addLeanoteAccount=New Leanote Account
|
||||
defaultComment=Default leanote comment system
|
||||
upgradeAccountTips=I want to using a custom domain for my blog, <a class="btn btn-default" href="/service">Upgrade My Account</a>
|
||||
cateIsPublicNotebook=Category is the published notebooks
|
||||
dragAndSort=Drag it to sort
|
||||
permanentLink=Permanent Link
|
||||
cate=Category
|
||||
noCates=No Category
|
||||
single=Single Page
|
||||
singleTips=You can add many single pages
|
||||
addSingle=New single page
|
||||
updateSingle=Update single page
|
||||
inputSingleTitle=Single page title is required
|
||||
saveSort=Save sequencing
|
||||
pagingAndSort=Paging And Sort Settings
|
||||
perPageSize=Per page size
|
||||
sortField=Sorter field
|
||||
sortType=Sorter type
|
||||
publicTime=Published time
|
||||
createdTime=Created time
|
||||
updatedTime=Updated time
|
||||
desc=Desc
|
||||
asc=Asc
|
||||
postList=Post List
|
||||
hasSelfDefined=Has defined
|
||||
noSelfDefined=Not defined
|
||||
setAbstract=Abstract settings
|
||||
title=Title
|
||||
content=Content
|
||||
|
||||
addTheme=New theme
|
||||
importTheme=Import theme
|
||||
exportTheme=Export theme
|
||||
export=Export
|
||||
preview=Preview
|
||||
edit=Edit
|
||||
use=Use
|
||||
install=Install
|
||||
currentTheme=Current theme
|
||||
myOtherThemes=My other themes
|
||||
leanoteThemeMarket=Leanote theme market
|
||||
updateTheme=Update Theme
|
||||
tplStyleScript=template, style, script
|
||||
newFile=New file
|
||||
image=Image
|
||||
currentFile=Current file
|
||||
tpl=Template
|
||||
style=Style
|
||||
script=Script
|
||||
header=Header
|
||||
footer=Footer
|
||||
index=Home
|
||||
cate=Category
|
||||
search=Search
|
||||
single=Single Page
|
||||
archive=Archive
|
||||
post=Post
|
||||
tags=Tags
|
||||
tag_posts=Tag's posts
|
||||
share_comment=Comments
|
||||
themeJson=Theme settings
|
||||
paging=Paging
|
||||
highlight=Code highlight
|
||||
|
||||
group=Group
|
||||
newGroup=New group
|
||||
deleteGroup=Delete group
|
||||
addMemberTips=Input username or email to add member
|
||||
deleteMember=Delete member
|
||||
|
||||
# error
|
||||
notFound=This page cann't found.
|
||||
|
||||
@@ -100,7 +100,7 @@ myBlog=我的博客
|
||||
history=历史记录
|
||||
save=保存
|
||||
editorTips=帮助
|
||||
editorTipsInfo=<h4>1. 快捷键</h4>ctrl+shift+c 代码块切换 <br /> ctrl+shift+i 插入/修改图片<h4>2. shift+enter 跳出当前区域</h4>比如在代码块中<img src="/images/outofcode.png" style="width: 90px"/>按shift+enter可跳出当前代码块.
|
||||
editorTipsInfo=<h4>1. 快捷键</h4>ctrl+shift+c 代码块切换 <h4>2. shift+enter 跳出当前区域</h4>比如在代码块中<img src="/images/outofcode.png" style="width: 90px"/>按shift+enter可跳出当前代码块.
|
||||
newNote=新建笔记
|
||||
newMarkdownNote=新建Markdown笔记
|
||||
noNoteNewNoteTips=该笔记本下空空如也...何不
|
||||
@@ -150,9 +150,12 @@ themeSetting=主题设置
|
||||
setAvatar=头像设置
|
||||
logout=退出
|
||||
basicInfo=基本信息
|
||||
basicInfoSet=博客基本设置
|
||||
updateEmail=修改Email
|
||||
usernameSetting=用户名设置
|
||||
username=用户名
|
||||
avatar=头像
|
||||
chooseImage=选择图片
|
||||
oldPassword=旧密码
|
||||
newPassword=新密码
|
||||
admin=后台管理
|
||||
@@ -261,6 +264,7 @@ subDomainExisted=博客子域名已存在
|
||||
domainNotPointToLeanote=该域名还未指向 d.leanote.com, 请稍后再试
|
||||
errorPerPageSize=每页记录数至少为1
|
||||
errorSortField=排序类型错误
|
||||
themeValidHasRoundInclude=警告: 模板存在循环引用问题!
|
||||
|
||||
# lea++
|
||||
leaDesc=leanote博客平台
|
||||
@@ -272,5 +276,91 @@ memberCenter=用户中心
|
||||
userNotExists=该成员沿未注册
|
||||
hasUsers=已存在该成员
|
||||
|
||||
# yu
|
||||
service=服务
|
||||
imageSizeOver=对不起, 您的图片容量不足, 请<a href="/service">升级您的帐户</a>
|
||||
attachSizeOver=对不起, 您的附件容量不足, 请<a href="/service">升级您的帐户</a>
|
||||
|
||||
#memeber
|
||||
welcomeToLeanote=欢迎来到leanote
|
||||
accountInfo=帐户信息
|
||||
accountType=帐户类型
|
||||
premiumAccountType=彩色套餐
|
||||
normalAccountType=共享套餐
|
||||
imageSize=图片空间
|
||||
attachSize=附件空间
|
||||
upgrade=升级套餐
|
||||
leanoteEvents=Leanote动态
|
||||
addLeanoteAccount=新建Leanote帐户
|
||||
defaultComment=默认leanote评论系统
|
||||
upgradeAccountTips=Leanote支持绑定自己的域名到博客上, 请 <a class="btn btn-default" href="/service">升级您的帐户</a>
|
||||
cateIsPublicNotebook=分类是公开为博客的笔记本
|
||||
dragAndSort=拖动可排序
|
||||
permanentLink=固定链接
|
||||
cate=分类
|
||||
noCates=无分类
|
||||
single=单页面
|
||||
singleTips=您可以添加多个单页面
|
||||
addSingle=添加单页面
|
||||
updateSingle=修改单页面
|
||||
inputSingleTitle=请输入单页面标题
|
||||
saveSort=保存排序
|
||||
pagingAndSort=分页与排序设置
|
||||
perPageSize=每页记录数
|
||||
sortField=排序字段
|
||||
sortType=排序类型
|
||||
publicTime=发表时间
|
||||
createdTime=创建时间
|
||||
updatedTime=更新时间
|
||||
desc=降序
|
||||
asc=升序
|
||||
postList=文章列表
|
||||
hasSelfDefined=已设置
|
||||
noSelfDefined=未设置
|
||||
setAbstract=摘要设置
|
||||
title=标题
|
||||
content=内容
|
||||
|
||||
addTheme=添加主题
|
||||
importTheme=导入主题
|
||||
exportTheme=导出主题
|
||||
export=导出
|
||||
preview=预览
|
||||
edit=编辑
|
||||
use=使用
|
||||
install=安装
|
||||
currentTheme=当前主题
|
||||
myOtherThemes=我的其它主题
|
||||
leanoteThemeMarket=Leanote主题市场
|
||||
updateTheme=编辑主题
|
||||
tplStyleScript=模板, 样式, 脚本
|
||||
newFile=新建文件
|
||||
image=图片
|
||||
currentFile=当前文件
|
||||
tpl=模板
|
||||
style=样式
|
||||
script=脚本
|
||||
header=头部
|
||||
footer=底部
|
||||
index=首页
|
||||
cate=分类页
|
||||
search=搜索页
|
||||
single=单页
|
||||
archive=归档页
|
||||
post=文章页
|
||||
tags=标签页
|
||||
tag_posts=标签文章页
|
||||
share_comment=分享评论
|
||||
themeJson=主题配置
|
||||
paging=分页
|
||||
highlight=高亮
|
||||
|
||||
group=用户组
|
||||
newGroup=新建组
|
||||
deleteGroup=删除组
|
||||
addMemberTips=输入用户名或邮箱添加成员
|
||||
deleteMember=删除成员
|
||||
|
||||
|
||||
# 必须要加这个, 奇怪
|
||||
[CN]
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user