attachment feature #10
This commit is contained in:
212
app/controllers/AttachController.go
Normal file
212
app/controllers/AttachController.go
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/revel/revel"
|
||||||
|
// "encoding/json"
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
. "github.com/leanote/leanote/app/lea"
|
||||||
|
"github.com/leanote/leanote/app/info"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
"io"
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 附件
|
||||||
|
type Attach struct {
|
||||||
|
BaseController
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传附件
|
||||||
|
func (c Attach) UploadAttach(noteId string) revel.Result {
|
||||||
|
re := c.uploadAttach(noteId)
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
func (c Attach) uploadAttach(noteId string) (re info.Re) {
|
||||||
|
var fileId = ""
|
||||||
|
var resultMsg = "error" // 错误信息
|
||||||
|
var Ok = false
|
||||||
|
var fileInfo info.Attach
|
||||||
|
|
||||||
|
re = info.NewRe()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
re.Id = fileId // 只是id, 没有其它信息
|
||||||
|
re.Msg = resultMsg
|
||||||
|
re.Ok = Ok
|
||||||
|
re.Item = fileInfo
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 判断是否有权限为笔记添加附件
|
||||||
|
if !shareService.HasUpdateNotePerm(noteId, c.GetUserId()) {
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
|
file, handel, err := c.Request.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
// > 5M?
|
||||||
|
if(len(data) > 5 * 1024 * 1024) {
|
||||||
|
resultMsg = "File is bigger than 5M"
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成上传路径
|
||||||
|
filePath := "files/" + c.GetUserId() + "/attachs"
|
||||||
|
dir := revel.BasePath + "/" + filePath
|
||||||
|
err = os.MkdirAll(dir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
// 生成新的文件名
|
||||||
|
filename := handel.Filename
|
||||||
|
_, ext := SplitFilename(filename) // .doc
|
||||||
|
filename = NewGuid() + ext
|
||||||
|
toPath := dir + "/" + filename;
|
||||||
|
err = ioutil.WriteFile(toPath, data, 0777)
|
||||||
|
if err != nil {
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
|
// add File to db
|
||||||
|
fileType := ""
|
||||||
|
if ext != "" {
|
||||||
|
fileType = strings.ToLower(ext[1:])
|
||||||
|
}
|
||||||
|
filesize := GetFilesize(toPath)
|
||||||
|
fileInfo = info.Attach{Name: filename,
|
||||||
|
Title: handel.Filename,
|
||||||
|
NoteId: bson.ObjectIdHex(noteId),
|
||||||
|
UploadUserId: c.GetObjectUserId(),
|
||||||
|
Path: filePath + "/" + filename,
|
||||||
|
Type: fileType,
|
||||||
|
Size: filesize}
|
||||||
|
|
||||||
|
id := bson.NewObjectId();
|
||||||
|
fileInfo.AttachId = id
|
||||||
|
fileId = id.Hex()
|
||||||
|
Ok = attachService.AddAttach(fileInfo)
|
||||||
|
|
||||||
|
fileInfo.Path = ""; // 不要返回
|
||||||
|
resultMsg = "success"
|
||||||
|
|
||||||
|
return re
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除附件
|
||||||
|
func (c Attach) DeleteAttach(attachId string) revel.Result {
|
||||||
|
re := info.NewRe()
|
||||||
|
re.Ok, re.Msg = attachService.DeleteAttach(attachId, c.GetUserId())
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get all attachs by noteId
|
||||||
|
func (c Attach) GetAttachs(noteId string) revel.Result {
|
||||||
|
re := info.NewRe()
|
||||||
|
re.Ok = true
|
||||||
|
re.List = attachService.ListAttachs(noteId, c.GetUserId())
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载附件
|
||||||
|
// 权限判断
|
||||||
|
func (c Attach) Download(attachId string) revel.Result {
|
||||||
|
attach := attachService.GetAttach(attachId, c.GetUserId()); // 得到路径
|
||||||
|
path := attach.Path
|
||||||
|
if path == "" {
|
||||||
|
return c.RenderText("")
|
||||||
|
}
|
||||||
|
fn := revel.BasePath + "/" + strings.TrimLeft(path, "/")
|
||||||
|
file, _ := os.Open(fn)
|
||||||
|
return c.RenderBinary(file, attach.Title, revel.Attachment, time.Now()) // revel.Attachment
|
||||||
|
// return c.RenderFile(file, revel.Attachment) // revel.Attachment
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Attach) DownloadAll(noteId string) revel.Result {
|
||||||
|
note := noteService.GetNoteById(noteId)
|
||||||
|
if note.NoteId == "" {
|
||||||
|
return c.RenderText("")
|
||||||
|
}
|
||||||
|
// 得到文件列表
|
||||||
|
attachs := attachService.ListAttachs(noteId, c.GetUserId())
|
||||||
|
if attachs == nil || len(attachs) == 0 {
|
||||||
|
return c.RenderText("")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
dir := revel.BasePath + "/files/tmp"
|
||||||
|
err := os.MkdirAll(dir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return c.RenderText("")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
filename := note.Title + ".tar.gz"
|
||||||
|
if note.Title == "" {
|
||||||
|
filename = "all.tar.gz"
|
||||||
|
}
|
||||||
|
|
||||||
|
// file write
|
||||||
|
fw, err := os.Create(revel.BasePath + "/files/" + filename)
|
||||||
|
if err != nil {
|
||||||
|
return c.RenderText("")
|
||||||
|
}
|
||||||
|
// defer fw.Close() // 不需要关闭, 还要读取给用户下载
|
||||||
|
|
||||||
|
// gzip write
|
||||||
|
gw := gzip.NewWriter(fw)
|
||||||
|
defer gw.Close()
|
||||||
|
|
||||||
|
// tar write
|
||||||
|
tw := tar.NewWriter(gw)
|
||||||
|
defer tw.Close()
|
||||||
|
|
||||||
|
// 遍历文件列表
|
||||||
|
for _, attach := range attachs {
|
||||||
|
fn := revel.BasePath + "/" + strings.TrimLeft(attach.Path, "/")
|
||||||
|
fr, err := os.Open(fn)
|
||||||
|
fileInfo, _ := fr.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return c.RenderText("")
|
||||||
|
}
|
||||||
|
defer fr.Close()
|
||||||
|
|
||||||
|
// 信息头
|
||||||
|
h := new(tar.Header)
|
||||||
|
h.Name = attach.Title
|
||||||
|
h.Size = fileInfo.Size()
|
||||||
|
h.Mode = int64(fileInfo.Mode())
|
||||||
|
h.ModTime = fileInfo.ModTime()
|
||||||
|
|
||||||
|
// 写信息头
|
||||||
|
err = tw.WriteHeader(h)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写文件
|
||||||
|
_, err = io.Copy(tw, fr)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} // for
|
||||||
|
|
||||||
|
// tw.Close()
|
||||||
|
// gw.Close()
|
||||||
|
// fw.Close()
|
||||||
|
// file, _ := os.Open(dir + "/" + filename)
|
||||||
|
// fw.Seek(0, 0)
|
||||||
|
return c.RenderBinary(fw, filename, revel.Attachment, time.Now()) // revel.Attachment
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -17,7 +17,6 @@ type File struct {
|
|||||||
BaseController
|
BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传图片 editor
|
|
||||||
// 过时 已弃用!
|
// 过时 已弃用!
|
||||||
func (c File) UploadImage(renderHtml string) revel.Result {
|
func (c File) UploadImage(renderHtml string) revel.Result {
|
||||||
if renderHtml == "" {
|
if renderHtml == "" {
|
||||||
@ -33,18 +32,19 @@ func (c File) UploadImage(renderHtml string) revel.Result {
|
|||||||
return c.RenderTemplate(renderHtml)
|
return c.RenderTemplate(renderHtml)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 已弃用
|
||||||
|
func (c File) UploadImageJson(from, noteId string) revel.Result {
|
||||||
|
re := c.uploadImage(from, "");
|
||||||
|
return c.RenderJson(re)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 上传的是博客logo
|
// 上传的是博客logo
|
||||||
// TODO logo不要设置权限, 另外的目录
|
// TODO logo不要设置权限, 另外的目录
|
||||||
func (c File) UploadBlogLogo() revel.Result {
|
func (c File) UploadBlogLogo() revel.Result {
|
||||||
return c.UploadImage("file/blog_logo.html");
|
return c.UploadImage("file/blog_logo.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 弃用
|
|
||||||
func (c File) UploadImageJson(from, noteId string) revel.Result {
|
|
||||||
re := c.uploadImage(from, "");
|
|
||||||
return c.RenderJson(re)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 拖拉上传, pasteImage
|
// 拖拉上传, pasteImage
|
||||||
// noteId 是为了判断是否是协作的note, 如果是则需要复制一份到note owner中
|
// noteId 是为了判断是否是协作的note, 如果是则需要复制一份到note owner中
|
||||||
func (c File) PasteImage(noteId string) revel.Result {
|
func (c File) PasteImage(noteId string) revel.Result {
|
||||||
@ -69,13 +69,14 @@ func (c File) PasteImage(noteId string) revel.Result {
|
|||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
|
|
||||||
// leaui image plugin
|
// leaui image plugin upload image
|
||||||
func (c File) UploadImageLeaui(albumId string) revel.Result {
|
func (c File) UploadImageLeaui(albumId string) revel.Result {
|
||||||
re := c.uploadImage("", albumId);
|
re := c.uploadImage("", albumId);
|
||||||
return c.RenderJson(re)
|
return c.RenderJson(re)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传图片, 公用方法
|
// 上传图片, 公用方法
|
||||||
|
// upload image common func
|
||||||
func (c File) uploadImage(from, albumId string) (re info.Re) {
|
func (c File) uploadImage(from, albumId string) (re info.Re) {
|
||||||
var fileUrlPath = ""
|
var fileUrlPath = ""
|
||||||
var fileId = ""
|
var fileId = ""
|
||||||
|
@ -25,6 +25,7 @@ var suggestionService *service.SuggestionService
|
|||||||
|
|
||||||
var albumService *service.AlbumService
|
var albumService *service.AlbumService
|
||||||
var fileService *service.FileService
|
var fileService *service.FileService
|
||||||
|
var attachService *service.AttachService
|
||||||
|
|
||||||
var pageSize = 1000
|
var pageSize = 1000
|
||||||
var defaultSortField = "UpdatedTime"
|
var defaultSortField = "UpdatedTime"
|
||||||
|
@ -36,6 +36,7 @@ var Suggestions *mgo.Collection
|
|||||||
// Album & file(image)
|
// Album & file(image)
|
||||||
var Albums *mgo.Collection
|
var Albums *mgo.Collection
|
||||||
var Files *mgo.Collection
|
var Files *mgo.Collection
|
||||||
|
var Attachs *mgo.Collection
|
||||||
|
|
||||||
var NoteImages *mgo.Collection
|
var NoteImages *mgo.Collection
|
||||||
|
|
||||||
@ -106,6 +107,7 @@ func Init() {
|
|||||||
// Album & file
|
// Album & file
|
||||||
Albums = Session.DB(dbname).C("albums")
|
Albums = Session.DB(dbname).C("albums")
|
||||||
Files = Session.DB(dbname).C("files")
|
Files = Session.DB(dbname).C("files")
|
||||||
|
Attachs = Session.DB(dbname).C("attachs")
|
||||||
|
|
||||||
NoteImages = Session.DB(dbname).C("note_images")
|
NoteImages = Session.DB(dbname).C("note_images")
|
||||||
}
|
}
|
||||||
|
21
app/info/AttachInfo.go
Normal file
21
app/info/AttachInfo.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package info
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Attach belongs to note
|
||||||
|
type Attach struct {
|
||||||
|
AttachId bson.ObjectId `bson:"_id,omitempty"` //
|
||||||
|
NoteId bson.ObjectId `bson:"NoteId"` //
|
||||||
|
UploadUserId bson.ObjectId `bson:"UploadUserId"` // 可以不是note owner, 协作者userId
|
||||||
|
Name string `Name` // file name, md5, such as 13232312.doc
|
||||||
|
Title string `Title` // raw file name
|
||||||
|
Size int64 `Size` // file size (byte)
|
||||||
|
Type string `Type` // file type, "doc" = word
|
||||||
|
Path string `Path` // the file path such as: files/userId/attachs/adfadf.doc
|
||||||
|
CreatedTime time.Time `CreatedTime`
|
||||||
|
|
||||||
|
// FromFileId bson.ObjectId `bson:"FromFileId,omitempty"` // copy from fileId, for collaboration
|
||||||
|
}
|
@ -24,7 +24,7 @@ type Note struct {
|
|||||||
|
|
||||||
IsMarkdown bool `IsMarkdown` // 是否是markdown笔记, 默认是false
|
IsMarkdown bool `IsMarkdown` // 是否是markdown笔记, 默认是false
|
||||||
|
|
||||||
AttachIds []string `FileIds,omitempty` // 2014/9/18, attachments
|
AttachNum int `AttachNum` // 2014/9/21, attachments num
|
||||||
|
|
||||||
CreatedTime time.Time `CreatedTime`
|
CreatedTime time.Time `CreatedTime`
|
||||||
UpdatedTime time.Time `UpdatedTime`
|
UpdatedTime time.Time `UpdatedTime`
|
||||||
|
175
app/service/AttachService.go
Normal file
175
app/service/AttachService.go
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/leanote/leanote/app/lea"
|
||||||
|
"github.com/revel/revel"
|
||||||
|
"github.com/leanote/leanote/app/info"
|
||||||
|
"github.com/leanote/leanote/app/db"
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
"time"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AttachService struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// add attach
|
||||||
|
func (this *AttachService) AddAttach(attach info.Attach) bool {
|
||||||
|
attach.CreatedTime = time.Now()
|
||||||
|
ok := db.Insert(db.Attachs, attach)
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
// 更新笔记的attachs num
|
||||||
|
this.updateNoteAttachNum(attach.NoteId, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新笔记的附件个数
|
||||||
|
// addNum 1或-1
|
||||||
|
func (this *AttachService) updateNoteAttachNum(noteId bson.ObjectId, addNum int) bool {
|
||||||
|
num := db.Count(db.Attachs, bson.M{"NoteId": noteId})
|
||||||
|
/*
|
||||||
|
note := info.Note{}
|
||||||
|
note = noteService.GetNoteById(noteId.Hex())
|
||||||
|
note.AttachNum += addNum
|
||||||
|
if note.AttachNum < 0 {
|
||||||
|
note.AttachNum = 0
|
||||||
|
}
|
||||||
|
Log(note.AttachNum)
|
||||||
|
*/
|
||||||
|
return db.UpdateByQField(db.Notes, bson.M{"_id": noteId}, "AttachNum", num)
|
||||||
|
}
|
||||||
|
|
||||||
|
// list attachs
|
||||||
|
func (this *AttachService) ListAttachs(noteId, userId string) []info.Attach {
|
||||||
|
attachs := []info.Attach{}
|
||||||
|
// 判断是否有权限为笔记添加附件
|
||||||
|
if !shareService.HasUpdateNotePerm(noteId, userId) {
|
||||||
|
return attachs
|
||||||
|
}
|
||||||
|
|
||||||
|
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)
|
||||||
|
|
||||||
|
return attachs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *AttachService) UpdateImageTitle(userId, fileId, title string) bool {
|
||||||
|
return db.UpdateByIdAndUserIdField(db.Files, fileId, userId, "Title", title)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Delete note to delete attas firstly
|
||||||
|
func (this *AttachService) DeleteAllAttachs(noteId, userId string) bool {
|
||||||
|
note := noteService.GetNoteById(noteId)
|
||||||
|
if note.UserId.Hex() == userId {
|
||||||
|
attachs := []info.Attach{}
|
||||||
|
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)
|
||||||
|
for _, attach := range attachs {
|
||||||
|
attach.Path = strings.TrimLeft(attach.Path, "/")
|
||||||
|
os.Remove(revel.BasePath + "/" + attach.Path)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete attach
|
||||||
|
func (this *AttachService) DeleteAttach(attachId, userId string) (bool, string) {
|
||||||
|
attach := info.Attach{}
|
||||||
|
db.Get(db.Attachs, attachId, &attach)
|
||||||
|
|
||||||
|
if(attach.AttachId != "") {
|
||||||
|
// 判断是否有权限为笔记添加附件
|
||||||
|
if !shareService.HasUpdateNotePerm(attach.NoteId.Hex(), userId) {
|
||||||
|
return false, "No Perm"
|
||||||
|
}
|
||||||
|
|
||||||
|
if db.Delete(db.Attachs, bson.M{"_id": bson.ObjectIdHex(attachId)}) {
|
||||||
|
this.updateNoteAttachNum(attach.NoteId, -1)
|
||||||
|
attach.Path = strings.TrimLeft(attach.Path, "/")
|
||||||
|
err := os.Remove(revel.BasePath + "/" + attach.Path)
|
||||||
|
if err == nil {
|
||||||
|
return true, "delete file error"
|
||||||
|
}
|
||||||
|
return false, "delete file error"
|
||||||
|
}
|
||||||
|
return false, "db error"
|
||||||
|
}
|
||||||
|
return false, "no such item"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件路径
|
||||||
|
// 要判断是否具有权限
|
||||||
|
// userId是否具有attach的访问权限
|
||||||
|
func (this *AttachService) GetAttach(attachId, userId string) (attach info.Attach) {
|
||||||
|
if attachId == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
attach = info.Attach{}
|
||||||
|
db.Get(db.Attachs, attachId, &attach)
|
||||||
|
path := attach.Path
|
||||||
|
if path == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
note := noteService.GetNoteById(attach.NoteId.Hex())
|
||||||
|
|
||||||
|
// 判断权限
|
||||||
|
|
||||||
|
// 笔记是否是公开的
|
||||||
|
if note.IsBlog {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 笔记是否是我的
|
||||||
|
if note.UserId.Hex() == userId {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 我是否有权限查看或协作
|
||||||
|
if shareService.HasReadNotePerm(attach.NoteId.Hex(), userId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
attach = info.Attach{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制笔记时需要复制附件
|
||||||
|
// noteService调用, 权限已判断
|
||||||
|
func (this *AttachService) CopyAttachs(noteId, toNoteId, toUserId string) bool {
|
||||||
|
attachs := []info.Attach{}
|
||||||
|
db.ListByQ(db.Attachs, bson.M{"NoteId": bson.ObjectIdHex(noteId)}, &attachs)
|
||||||
|
|
||||||
|
// 复制之
|
||||||
|
toNoteIdO := bson.ObjectIdHex(toNoteId)
|
||||||
|
for _, attach := range attachs {
|
||||||
|
attach.AttachId = ""
|
||||||
|
attach.NoteId = toNoteIdO
|
||||||
|
|
||||||
|
// 文件复制一份
|
||||||
|
_, ext := SplitFilename(attach.Name)
|
||||||
|
newFilename := NewGuid() + ext
|
||||||
|
dir := "files/" + toUserId + "/attachs"
|
||||||
|
filePath := dir + "/" + newFilename
|
||||||
|
err := os.MkdirAll(revel.BasePath + "/" + dir, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, err = CopyFile(revel.BasePath + "/" + attach.Path, revel.BasePath + "/" + filePath)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
attach.Name = newFilename
|
||||||
|
attach.Path = filePath
|
||||||
|
|
||||||
|
this.AddAttach(attach)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
@ -189,7 +189,6 @@ func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, strin
|
|||||||
if file.FileId == "" || file.UserId.Hex() != userId {
|
if file.FileId == "" || file.UserId.Hex() != userId {
|
||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
Log(file)
|
|
||||||
|
|
||||||
_, ext := SplitFilename(file.Name)
|
_, ext := SplitFilename(file.Name)
|
||||||
newFilename := NewGuid() + ext
|
newFilename := NewGuid() + ext
|
||||||
|
@ -366,6 +366,9 @@ func (this *NoteService) CopySharedNote(noteId, notebookId, fromUserId, myUserId
|
|||||||
// 复制图片, 把note的图片都copy给我, 且修改noteContent图片路径
|
// 复制图片, 把note的图片都copy给我, 且修改noteContent图片路径
|
||||||
noteContent.Content = noteImageService.CopyNoteImages(noteId, fromUserId, note.NoteId.Hex(), noteContent.Content, myUserId)
|
noteContent.Content = noteImageService.CopyNoteImages(noteId, fromUserId, note.NoteId.Hex(), noteContent.Content, myUserId)
|
||||||
|
|
||||||
|
// 复制附件
|
||||||
|
attachService.CopyAttachs(noteId, note.NoteId.Hex(), myUserId)
|
||||||
|
|
||||||
// 添加之
|
// 添加之
|
||||||
note = this.AddNoteAndContent(note, noteContent, note.UserId);
|
note = this.AddNoteAndContent(note, noteContent, note.UserId);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package service
|
|||||||
import (
|
import (
|
||||||
"github.com/leanote/leanote/app/info"
|
"github.com/leanote/leanote/app/info"
|
||||||
"github.com/leanote/leanote/app/db"
|
"github.com/leanote/leanote/app/db"
|
||||||
. "github.com/leanote/leanote/app/lea"
|
. "github.com/leanote/leanote/app/lea"
|
||||||
"gopkg.in/mgo.v2/bson"
|
"gopkg.in/mgo.v2/bson"
|
||||||
"time"
|
"time"
|
||||||
"sort"
|
"sort"
|
||||||
@ -286,6 +286,28 @@ func (this *ShareService) AddShareNote(noteId string, perm int, userId, email st
|
|||||||
return db.Insert(db.ShareNotes, shareNote), "", toUserId
|
return db.Insert(db.ShareNotes, shareNote), "", toUserId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updatedUserId是否有查看userId noteId的权限?
|
||||||
|
func (this *ShareService) HasReadPerm(userId, updatedUserId, noteId string) bool {
|
||||||
|
if !db.Has(db.ShareNotes,
|
||||||
|
bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(updatedUserId), "NoteId": bson.ObjectIdHex(noteId)}) {
|
||||||
|
// noteId的notebookId是否被共享了?
|
||||||
|
notebookId := noteService.GetNotebookId(noteId)
|
||||||
|
if notebookId.Hex() == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断notebook是否被共享
|
||||||
|
if !db.Has(db.ShareNotebooks,
|
||||||
|
bson.M{"UserId": bson.ObjectIdHex(userId), "ToUserId": bson.ObjectIdHex(updatedUserId), "NotebookId": notebookId}) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// updatedUserId是否有修改userId noteId的权限?
|
// updatedUserId是否有修改userId noteId的权限?
|
||||||
func (this *ShareService) HasUpdatePerm(userId, updatedUserId, noteId string) bool {
|
func (this *ShareService) HasUpdatePerm(userId, updatedUserId, noteId string) bool {
|
||||||
// 1. noteId是否被共享了?
|
// 1. noteId是否被共享了?
|
||||||
@ -340,8 +362,6 @@ func (this *ShareService) HasSharedNote(noteId, myUserId string) bool {
|
|||||||
// noteId的notebook是否共享了给我
|
// noteId的notebook是否共享了给我
|
||||||
func (this *ShareService) HasSharedNotebook(noteId, myUserId, sharedUserId string) bool {
|
func (this *ShareService) HasSharedNotebook(noteId, myUserId, sharedUserId string) bool {
|
||||||
notebookId := noteService.GetNotebookId(noteId)
|
notebookId := noteService.GetNotebookId(noteId)
|
||||||
Log(noteId)
|
|
||||||
Log(notebookId)
|
|
||||||
if notebookId != "" {
|
if notebookId != "" {
|
||||||
return db.Has(db.ShareNotebooks, bson.M{"NotebookId": notebookId,
|
return db.Has(db.ShareNotebooks, bson.M{"NotebookId": notebookId,
|
||||||
"UserId": bson.ObjectIdHex(sharedUserId),
|
"UserId": bson.ObjectIdHex(sharedUserId),
|
||||||
@ -509,4 +529,51 @@ func (this *ShareService) DeleteUserShareNoteAndNotebook(userId, toUserId string
|
|||||||
db.DeleteAll(db.HasShareNotes, query);
|
db.DeleteAll(db.HasShareNotes, query);
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户userId是否有修改noteId的权限
|
||||||
|
func (this *ShareService) HasUpdateNotePerm(noteId, userId string) bool {
|
||||||
|
if noteId == "" || userId == "" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
note := noteService.GetNoteById(noteId)
|
||||||
|
LogJ(note);
|
||||||
|
if note.UserId != "" {
|
||||||
|
noteUserId := note.UserId.Hex()
|
||||||
|
if noteUserId != userId {
|
||||||
|
// 是否是有权限协作的
|
||||||
|
if this.HasUpdatePerm(noteUserId, userId, noteId) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用户userId是否有修改noteId的权限
|
||||||
|
func (this *ShareService) HasReadNotePerm(noteId, userId string) bool {
|
||||||
|
if noteId == "" || userId == "" {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
note := noteService.GetNoteById(noteId)
|
||||||
|
if note.UserId != "" {
|
||||||
|
noteUserId := note.UserId.Hex()
|
||||||
|
if noteUserId != userId {
|
||||||
|
// 是否是有权限协作的
|
||||||
|
if this.HasReadPerm(noteUserId, userId, noteId) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
@ -53,7 +53,15 @@ func (this *TrashService) recoverNote(noteId, notebookId, userId string) bool {
|
|||||||
|
|
||||||
// 删除trash
|
// 删除trash
|
||||||
func (this *TrashService) DeleteTrash(noteId, userId string) bool {
|
func (this *TrashService) DeleteTrash(noteId, userId string) bool {
|
||||||
return db.DeleteByIdAndUserId(db.Notes, noteId, userId)
|
// delete note's attachs
|
||||||
|
ok := attachService.DeleteAllAttachs(noteId, userId)
|
||||||
|
|
||||||
|
// delete note
|
||||||
|
ok = db.DeleteByIdAndUserId(db.Notes, noteId, userId)
|
||||||
|
// delete content
|
||||||
|
ok = db.DeleteByIdAndUserId(db.NoteContents, noteId, userId)
|
||||||
|
|
||||||
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
// 列出note, 排序规则, 还有分页
|
// 列出note, 排序规则, 还有分页
|
||||||
|
@ -19,6 +19,7 @@ var blogService *BlogService
|
|||||||
var tokenService *TokenService
|
var tokenService *TokenService
|
||||||
var noteImageService *NoteImageService
|
var noteImageService *NoteImageService
|
||||||
var fileService *FileService
|
var fileService *FileService
|
||||||
|
var attachService *AttachService
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
notebookService = &NotebookService{}
|
notebookService = &NotebookService{}
|
||||||
@ -31,5 +32,6 @@ func init() {
|
|||||||
blogService = &BlogService{}
|
blogService = &BlogService{}
|
||||||
tokenService = &TokenService{}
|
tokenService = &TokenService{}
|
||||||
fileService = &FileService{}
|
fileService = &FileService{}
|
||||||
|
attachService = &AttachService{}
|
||||||
noteImageService = &NoteImageService{}
|
noteImageService = &NoteImageService{}
|
||||||
}
|
}
|
@ -353,6 +353,7 @@ function log(o) {
|
|||||||
</i>Sort <i class="fa fa-angle-down"></i>
|
</i>Sort <i class="fa fa-angle-down"></i>
|
||||||
-->
|
-->
|
||||||
</a>
|
</a>
|
||||||
|
<!--
|
||||||
<ul class="dropdown-menu" role="menu"
|
<ul class="dropdown-menu" role="menu"
|
||||||
aria-labelledby="dropdownMenu1"
|
aria-labelledby="dropdownMenu1"
|
||||||
style="right: 3px; ! important; left: -100px; min-width: 100px;">
|
style="right: 3px; ! important; left: -100px; min-width: 100px;">
|
||||||
@ -366,6 +367,7 @@ function log(o) {
|
|||||||
<li role="presentation"><a role="menuitem" tabindex="-1"
|
<li role="presentation"><a role="menuitem" tabindex="-1"
|
||||||
href="#">Separated </a></li>
|
href="#">Separated </a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -466,6 +468,38 @@ function log(o) {
|
|||||||
<ul class="pull-right" id="editorTool">
|
<ul class="pull-right" id="editorTool">
|
||||||
<li><a class="ios7-a " id="saveBtn" title="ctrl+s"
|
<li><a class="ios7-a " id="saveBtn" title="ctrl+s"
|
||||||
data-toggle="dropdown">{{msg . "save"}}</a></li>
|
data-toggle="dropdown">{{msg . "save"}}</a></li>
|
||||||
|
|
||||||
|
<li class="dropdown" id="attachDropdown">
|
||||||
|
<a class="ios7-a dropdown-toggle" data-toggle="dropdown" id="showAttach">
|
||||||
|
<!--
|
||||||
|
<span class="fa fa-upload"></span>
|
||||||
|
-->
|
||||||
|
{{msg . "attachments"}}<span id="attachNum"></span>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu" id="attachMenu">
|
||||||
|
<ul id="attachList">
|
||||||
|
</ul>
|
||||||
|
<form id="uploadAttach" method="post" action="/attach/UploadAttach" enctype="multipart/form-data">
|
||||||
|
<div id="dropAttach">
|
||||||
|
<a class="btn btn-success btn-choose-file">
|
||||||
|
Choose File to Upload
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-default" id="downloadAllBtn">
|
||||||
|
<i class="fa fa-download"></i>
|
||||||
|
Download All
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-default" id="linkAllBtn">
|
||||||
|
<i class="fa fa-link"></i>
|
||||||
|
Link All
|
||||||
|
</a>
|
||||||
|
<input type="file" name="file" multiple/>
|
||||||
|
</div>
|
||||||
|
<div id="attachUploadMsg">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li><a class="ios7-a " id="tipsBtn"
|
<li><a class="ios7-a " id="tipsBtn"
|
||||||
data-toggle="dropdown">{{msg . "editorTips"}}</a></li>
|
data-toggle="dropdown">{{msg . "editorTips"}}</a></li>
|
||||||
<li><a class="ios7-a " id="contentHistory"
|
<li><a class="ios7-a " id="contentHistory"
|
||||||
@ -498,7 +532,7 @@ function log(o) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- leaui image -->
|
<!-- leaui image drop image to editor-->
|
||||||
<form id="upload" method="post" action="/file/uploadImageLeaui" enctype="multipart/form-data" style="margin-top: 5px;">
|
<form id="upload" method="post" action="/file/uploadImageLeaui" enctype="multipart/form-data" style="margin-top: 5px;">
|
||||||
<div id="drop">
|
<div id="drop">
|
||||||
Drop images to here
|
Drop images to here
|
||||||
@ -982,19 +1016,17 @@ initSlimScroll();
|
|||||||
<link href="/public/mdeditor/editor/editor.css" rel="stylesheet">
|
<link href="/public/mdeditor/editor/editor.css" rel="stylesheet">
|
||||||
<script src="/public/mdeditor/editor/pagedown/Markdown.Converter-min.js"></script>
|
<script src="/public/mdeditor/editor/pagedown/Markdown.Converter-min.js"></script>
|
||||||
<script src="/public/mdeditor/editor/pagedown/Markdown.Sanitizer-min.js"></script>
|
<script src="/public/mdeditor/editor/pagedown/Markdown.Sanitizer-min.js"></script>
|
||||||
<script src="/public/mdeditor/editor/pagedown/Markdown.Editor-min.js"></script>
|
<script src="/public/mdeditor/editor/pagedown/Markdown.Editor.js"></script>
|
||||||
<script src="/public/mdeditor/editor/pagedown/local/Markdown.local.zh-min.js"></script>
|
<script src="/public/mdeditor/editor/pagedown/local/Markdown.local.zh-min.js"></script>
|
||||||
<script src="/public/mdeditor/editor/Markdown.Extra-min.js"></script>
|
<script src="/public/mdeditor/editor/Markdown.Extra-min.js"></script>
|
||||||
<script src="/public/mdeditor/editor/underscore-min.js"></script>
|
<script src="/public/mdeditor/editor/underscore-min.js"></script>
|
||||||
<script src="/public/mdeditor/editor/scrollLink.js"></script>
|
<script src="/public/mdeditor/editor/scrollLink.js"></script>
|
||||||
<!--mathjax-->
|
<!--mathjax-->
|
||||||
<!--
|
|
||||||
<script type="text/x-mathjax-config">
|
<script type="text/x-mathjax-config">
|
||||||
MathJax.Hub.Config({ tex2jax: { inlineMath: [['$','$'], ["\\(","\\)"]], processEscapes: true }, messageStyle: "none"});
|
MathJax.Hub.Config({ tex2jax: { inlineMath: [['$','$'], ["\\(","\\)"]], processEscapes: true }, messageStyle: "none"});
|
||||||
</script>
|
</script>
|
||||||
<script src="/public/mdeditor/editor/mathJax-min.js"></script>
|
<script src="/public/mdeditor/editor/mathJax-min.js"></script>
|
||||||
<script src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
<script src="//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||||
-->
|
|
||||||
<script src="/public/mdeditor/editor/jquery.waitforimages-min.js"></script>
|
<script src="/public/mdeditor/editor/jquery.waitforimages-min.js"></script>
|
||||||
<script src="/public/mdeditor/editor/google-code-prettify/prettify.js"></script>
|
<script src="/public/mdeditor/editor/google-code-prettify/prettify.js"></script>
|
||||||
<script src="/public/mdeditor/editor/editor.js"></script>
|
<script src="/public/mdeditor/editor/editor.js"></script>
|
||||||
@ -1003,7 +1035,7 @@ initSlimScroll();
|
|||||||
<!-- context-menu -->
|
<!-- context-menu -->
|
||||||
<link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" />
|
<link rel="stylesheet" href="/js/contextmenu/css/contextmenu.css" type="text/css" />
|
||||||
|
|
||||||
<!-- version 2.0 -->
|
<!-- js version 2.0 use require.js -->
|
||||||
<script src="/js/require.js"></script>
|
<script src="/js/require.js"></script>
|
||||||
<script>
|
<script>
|
||||||
require.config({
|
require.config({
|
||||||
@ -1011,14 +1043,18 @@ require.config({
|
|||||||
paths: {
|
paths: {
|
||||||
// 'jquery': 'js/jquery-1.9.0.min',
|
// 'jquery': 'js/jquery-1.9.0.min',
|
||||||
'leaui_image': 'tinymce/plugins/leaui_image/public/js/for_editor',
|
'leaui_image': 'tinymce/plugins/leaui_image/public/js/for_editor',
|
||||||
|
'attachment_upload': 'js/app/attachment_upload',
|
||||||
'jquery.ui.widget': 'tinymce/plugins/leaui_image/public/js/jquery.ui.widget',
|
'jquery.ui.widget': 'tinymce/plugins/leaui_image/public/js/jquery.ui.widget',
|
||||||
'fileupload': '/tinymce/plugins/leaui_image/public/js/jquery.fileupload'
|
'fileupload': '/tinymce/plugins/leaui_image/public/js/jquery.fileupload'
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
|
'fileupload': {deps: ['jquery.ui.widget']}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
require(['leaui_image'], function(leaui_image) {
|
require(['leaui_image'], function(leaui_image) {
|
||||||
});
|
});
|
||||||
|
require(['attachment_upload'], function(attachment_upload) {
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -132,5 +132,8 @@ discussion=Discussion
|
|||||||
download=Download
|
download=Download
|
||||||
howToInstallLeanote=How to install leanote
|
howToInstallLeanote=How to install leanote
|
||||||
|
|
||||||
|
#
|
||||||
|
attachments = Attachments
|
||||||
|
|
||||||
# error
|
# error
|
||||||
notFound=This page cann't found.
|
notFound=This page cann't found.
|
||||||
|
@ -136,6 +136,9 @@ discussion=社区讨论
|
|||||||
download=下载
|
download=下载
|
||||||
howToInstallLeanote=leanote安装步骤
|
howToInstallLeanote=leanote安装步骤
|
||||||
|
|
||||||
|
#
|
||||||
|
attachments = 附件
|
||||||
|
|
||||||
|
|
||||||
# 必须要加这个, 奇怪
|
# 必须要加这个, 奇怪
|
||||||
[CN]
|
[CN]
|
@ -38,6 +38,13 @@
|
|||||||
|
|
||||||
/*"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue", Helvetica, "Microsoft Yahei", Verdana, Simsun, "Segoe UI", "Segoe UI Web Regular", "Segoe UI Symbol", "BBAlpha Sans", "S60 Sans", Arial, sans-serif;*/
|
/*"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue", Helvetica, "Microsoft Yahei", Verdana, Simsun, "Segoe UI", "Segoe UI Web Regular", "Segoe UI Symbol", "BBAlpha Sans", "S60 Sans", Arial, sans-serif;*/
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.alert {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
#logo {
|
#logo {
|
||||||
font-family: "leanoteregular";
|
font-family: "leanoteregular";
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
@ -319,4 +326,99 @@
|
|||||||
}
|
}
|
||||||
.ztree {
|
.ztree {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// leaui image drop drag
|
||||||
|
#upload {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0px;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#upload #drop {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding-top: 100px;
|
||||||
|
}
|
||||||
|
#drop.in {
|
||||||
|
border: 1px solid #000000;
|
||||||
|
}
|
||||||
|
#drop.hover {
|
||||||
|
border: 2px solid #000000;
|
||||||
|
}
|
||||||
|
#uploadMsg {
|
||||||
|
position: absolute;
|
||||||
|
top: 3px;
|
||||||
|
right: 3px;
|
||||||
|
bottom: 10px;
|
||||||
|
overflow: scroll;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// upload attach
|
||||||
|
#uploadAttach {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
#dropAttach {
|
||||||
|
text-align: center;
|
||||||
|
input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#dropAttach.in {
|
||||||
|
border: 1px solid #000000;
|
||||||
|
}
|
||||||
|
#dropAttach.hover {
|
||||||
|
border: 2px solid #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#attachUploadMsg{
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
max-height: 240px;
|
||||||
|
overflow: scroll;
|
||||||
|
z-index: 3;
|
||||||
|
.alert {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 3px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#attachMenu {
|
||||||
|
width: 400px;
|
||||||
|
padding: 10px 5px;
|
||||||
|
|
||||||
|
}
|
||||||
|
#attachList {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
max-height: 450px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
li {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border-bottom: 1px dashed #eee;
|
||||||
|
height: 45px;
|
||||||
|
line-height: 45px;
|
||||||
|
div {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.attach-title {
|
||||||
|
width: 200px;
|
||||||
|
white-space: nowrap;text-overflow:ellipsis; overflow:hidden;
|
||||||
|
}
|
||||||
|
.attach-process {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,12 @@
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
/*"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue", Helvetica, "Microsoft Yahei", Verdana, Simsun, "Segoe UI", "Segoe UI Web Regular", "Segoe UI Symbol", "BBAlpha Sans", "S60 Sans", Arial, sans-serif;*/
|
/*"HelveticaNeue-Light","Helvetica Neue Light","Helvetica Neue", Helvetica, "Microsoft Yahei", Verdana, Simsun, "Segoe UI", "Segoe UI Web Regular", "Segoe UI Symbol", "BBAlpha Sans", "S60 Sans", Arial, sans-serif;*/
|
||||||
|
.btn {
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.alert {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
#logo {
|
#logo {
|
||||||
font-family: "leanoteregular";
|
font-family: "leanoteregular";
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
@ -285,6 +291,96 @@
|
|||||||
.ztree {
|
.ztree {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
#upload {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 0px;
|
||||||
|
padding: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#upload #drop {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding-top: 100px;
|
||||||
|
}
|
||||||
|
#drop.in {
|
||||||
|
border: 1px solid #000000;
|
||||||
|
}
|
||||||
|
#drop.hover {
|
||||||
|
border: 2px solid #000000;
|
||||||
|
}
|
||||||
|
#uploadMsg {
|
||||||
|
position: absolute;
|
||||||
|
top: 3px;
|
||||||
|
right: 3px;
|
||||||
|
bottom: 10px;
|
||||||
|
overflow: scroll;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
#uploadAttach {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
#dropAttach {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#dropAttach input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#dropAttach.in {
|
||||||
|
border: 1px solid #000000;
|
||||||
|
}
|
||||||
|
#dropAttach.hover {
|
||||||
|
border: 2px solid #000000;
|
||||||
|
}
|
||||||
|
#attachUploadMsg {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
max-height: 240px;
|
||||||
|
overflow: scroll;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
#attachUploadMsg .alert {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 3px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
#attachMenu {
|
||||||
|
width: 400px;
|
||||||
|
padding: 10px 5px;
|
||||||
|
}
|
||||||
|
#attachList {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
max-height: 450px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
#attachList li {
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border-bottom: 1px dashed #eee;
|
||||||
|
height: 45px;
|
||||||
|
line-height: 45px;
|
||||||
|
}
|
||||||
|
#attachList li div {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
#attachList li .attach-title {
|
||||||
|
width: 200px;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#attachList li .attach-process {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
::selection {
|
::selection {
|
||||||
background: #000000;
|
background: #000000;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
@ -1265,12 +1361,6 @@ background-position:-1px -670px
|
|||||||
.tab-pane {
|
.tab-pane {
|
||||||
padding: 5px 0 0 0;
|
padding: 5px 0 0 0;
|
||||||
}
|
}
|
||||||
.alert {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.btn {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
}
|
|
||||||
#notebookNavForNewNote li,
|
#notebookNavForNewNote li,
|
||||||
#notebookNavForNewSharedNote > li {
|
#notebookNavForNewSharedNote > li {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
@ -1313,36 +1403,6 @@ background-position:-1px -670px
|
|||||||
#toggleEditorMode {
|
#toggleEditorMode {
|
||||||
margin: 0 10px !important;
|
margin: 0 10px !important;
|
||||||
}
|
}
|
||||||
#upload {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0px;
|
|
||||||
padding: 0;
|
|
||||||
background-color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#upload #drop {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding-top: 100px;
|
|
||||||
}
|
|
||||||
#drop.in {
|
|
||||||
border: 1px solid #000000;
|
|
||||||
}
|
|
||||||
#drop.hover {
|
|
||||||
border: 2px solid #000000;
|
|
||||||
}
|
|
||||||
#uploadMsg {
|
|
||||||
position: absolute;
|
|
||||||
top: 3px;
|
|
||||||
right: 3px;
|
|
||||||
bottom: 10px;
|
|
||||||
overflow: scroll;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
#searchNotebookForList {
|
#searchNotebookForList {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
@ -1075,13 +1075,6 @@ background-position:-1px -670px
|
|||||||
.tab-pane {
|
.tab-pane {
|
||||||
padding: 5px 0 0 0;
|
padding: 5px 0 0 0;
|
||||||
}
|
}
|
||||||
.alert {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mce-container-body iframe {
|
.mce-container-body iframe {
|
||||||
//overflow-x: hidden; // firefox 不能要
|
//overflow-x: hidden; // firefox 不能要
|
||||||
@ -1137,38 +1130,6 @@ background-position:-1px -670px
|
|||||||
margin: 0 10px !important;
|
margin: 0 10px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// leaui image drop drag
|
|
||||||
#upload {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0px;
|
|
||||||
padding: 0;
|
|
||||||
background-color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#upload #drop {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding-top: 100px;
|
|
||||||
}
|
|
||||||
#drop.in {
|
|
||||||
border: 1px solid #000000;
|
|
||||||
}
|
|
||||||
#drop.hover {
|
|
||||||
border: 2px solid #000000;
|
|
||||||
}
|
|
||||||
#uploadMsg {
|
|
||||||
position: absolute;
|
|
||||||
top: 3px;
|
|
||||||
right: 3px;
|
|
||||||
bottom: 10px;
|
|
||||||
overflow: scroll;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------
|
//----------------------
|
||||||
#searchNotebookForList {
|
#searchNotebookForList {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1024,13 +1024,7 @@ background-position:-1px -670px
|
|||||||
.tab-pane {
|
.tab-pane {
|
||||||
padding: 5px 0 0 0;
|
padding: 5px 0 0 0;
|
||||||
}
|
}
|
||||||
.alert {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mce-container-body iframe {
|
.mce-container-body iframe {
|
||||||
//overflow-x: hidden;
|
//overflow-x: hidden;
|
||||||
@ -1087,37 +1081,6 @@ background-position:-1px -670px
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// leaui image drop drag
|
|
||||||
#upload {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0px;
|
|
||||||
padding: 0;
|
|
||||||
background-color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
#upload #drop {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding-top: 100px;
|
|
||||||
}
|
|
||||||
#drop.in {
|
|
||||||
border: 1px solid #000000;
|
|
||||||
}
|
|
||||||
#drop.hover {
|
|
||||||
border: 2px solid #000000;
|
|
||||||
}
|
|
||||||
#uploadMsg {
|
|
||||||
position: absolute;
|
|
||||||
top: 3px;
|
|
||||||
right: 3px;
|
|
||||||
bottom: 10px;
|
|
||||||
overflow: scroll;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
#notebookList {
|
#notebookList {
|
||||||
border-top: 1px dashed #eee;
|
border-top: 1px dashed #eee;
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
134
public/js/app/attachment_upload.js
Normal file
134
public/js/app/attachment_upload.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
// upload attachment
|
||||||
|
// 依赖note
|
||||||
|
var urlPrefix = window.location.protocol + "//" + window.location.host;
|
||||||
|
define('attachment_upload', ['jquery.ui.widget', 'fileupload'], function(){
|
||||||
|
// var editor = tinymce.activeEditor;
|
||||||
|
// var dom = editor.dom;
|
||||||
|
|
||||||
|
var initUploader = function() {
|
||||||
|
var $msg = $('#attachUploadMsg');
|
||||||
|
|
||||||
|
$('#dropAttach .btn-choose-file').click(function() {
|
||||||
|
// trigger to show file select
|
||||||
|
$(this).parent().find('input').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize the jQuery File Upload plugin
|
||||||
|
$('#uploadAttach').fileupload({
|
||||||
|
dataType: 'json',
|
||||||
|
maxFileSize: 210000,
|
||||||
|
// This element will accept file drag/drop uploading
|
||||||
|
dropZone: $('#dropAttach'),
|
||||||
|
formData: function(form) {
|
||||||
|
return [{name: 'noteId', value: Note.curNoteId}] // 传递笔记本过去
|
||||||
|
},
|
||||||
|
// This function is called when a file is added to the queue;
|
||||||
|
// either via the browse button, or via drag/drop:
|
||||||
|
add: function(e, data) {
|
||||||
|
var note = Note.getCurNote();
|
||||||
|
if(!note || note.IsNew) {
|
||||||
|
alert("This note hasn't saved, please save it firstly!")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var tpl = $('<div class="alert alert-info"><img class="loader" src="/tinymce/plugins/leaui_image/public/images/ajax-loader.gif"> <a class="close" data-dismiss="alert">×</a></div>');
|
||||||
|
|
||||||
|
// Append the file name and file size
|
||||||
|
tpl.append(data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small>');
|
||||||
|
|
||||||
|
// Add the HTML to the UL element
|
||||||
|
tpl.appendTo($msg);
|
||||||
|
data.context = $msg;
|
||||||
|
|
||||||
|
// Automatically upload the file once it is added to the queue
|
||||||
|
var jqXHR;
|
||||||
|
setTimeout(function() {
|
||||||
|
jqXHR = data.submit();
|
||||||
|
}, 0);
|
||||||
|
},
|
||||||
|
|
||||||
|
done: function(e, data) {
|
||||||
|
if (data.result.Ok == true) {
|
||||||
|
data.context.remove();
|
||||||
|
Attach.addAttach(data.result.Item);
|
||||||
|
} else {
|
||||||
|
var re = data.result;
|
||||||
|
data.context.empty();
|
||||||
|
var tpl = $('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');
|
||||||
|
tpl.append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.result.Msg);
|
||||||
|
data.context.html(tpl);
|
||||||
|
setTimeout((function(tpl) {
|
||||||
|
return function() {
|
||||||
|
tpl.remove();
|
||||||
|
}
|
||||||
|
})(tpl), 3000);
|
||||||
|
}
|
||||||
|
$("#uploadAttachMsg").scrollTop(1000);
|
||||||
|
},
|
||||||
|
fail: function(e, data) {
|
||||||
|
data.context.empty();
|
||||||
|
var tpl = $('<div class="alert alert-danger"><a class="close" data-dismiss="alert">×</a></div>');
|
||||||
|
tpl.append('<b>Error:</b> ' + data.files[0].name + ' <small>[<i>' + formatFileSize(data.files[0].size) + '</i>]</small> ' + data.errorThrown);
|
||||||
|
data.context.html(tpl);
|
||||||
|
setTimeout((function(tpl) {
|
||||||
|
return function() {
|
||||||
|
tpl.remove();
|
||||||
|
}
|
||||||
|
})(tpl), 3000);
|
||||||
|
|
||||||
|
$("#uploadAttachMsg").scrollTop(1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent the default action when a file is dropped on the window
|
||||||
|
$(document).on('drop dragover', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Helper function that formats the file sizes
|
||||||
|
function formatFileSize(bytes) {
|
||||||
|
if (typeof bytes !== 'number') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (bytes >= 1000000000) {
|
||||||
|
return (bytes / 1000000000).toFixed(2) + ' GB';
|
||||||
|
}
|
||||||
|
if (bytes >= 1000000) {
|
||||||
|
return (bytes / 1000000).toFixed(2) + ' MB';
|
||||||
|
}
|
||||||
|
return (bytes / 1000).toFixed(2) + ' KB';
|
||||||
|
}
|
||||||
|
|
||||||
|
// drag css
|
||||||
|
$(document).bind('dragover', function (e) {
|
||||||
|
var dropZone = $('#dropAttach'),
|
||||||
|
timeout = window.dropZoneTimeout;
|
||||||
|
if (!timeout) {
|
||||||
|
dropZone.addClass('in');
|
||||||
|
showUpload();
|
||||||
|
} else {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}
|
||||||
|
var found = false,
|
||||||
|
node = e.target;
|
||||||
|
do {
|
||||||
|
if (node === dropZone[0]) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = node.parentNode;
|
||||||
|
} while (node != null);
|
||||||
|
if (found) {
|
||||||
|
dropZone.addClass('hover');
|
||||||
|
} else {
|
||||||
|
dropZone.removeClass('hover');
|
||||||
|
}
|
||||||
|
window.dropZoneTimeout = setTimeout(function () {
|
||||||
|
window.dropZoneTimeout = null;
|
||||||
|
dropZone.removeClass('in hover');
|
||||||
|
hideUpload();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initUploader();
|
||||||
|
});
|
@ -79,6 +79,10 @@ Note.getCurNote = function() {
|
|||||||
}
|
}
|
||||||
return self.cache[self.curNoteId];
|
return self.cache[self.curNoteId];
|
||||||
}
|
}
|
||||||
|
Note.getNote = function(noteId) {
|
||||||
|
var self = this;
|
||||||
|
return self.cache[noteId];
|
||||||
|
}
|
||||||
|
|
||||||
// 每当有notebookId相应的note改变时都要重新清空之
|
// 每当有notebookId相应的note改变时都要重新清空之
|
||||||
// 并设置该notebookId有值
|
// 并设置该notebookId有值
|
||||||
@ -441,6 +445,8 @@ Note.changeNote = function(selectNoteId, isShare, needSaveChanged) {
|
|||||||
Note.renderNoteReadOnly(cacheNote);
|
Note.renderNoteReadOnly(cacheNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Attach.renderNoteAttachNum(selectNoteId, true);
|
||||||
|
|
||||||
function setContent(ret) {
|
function setContent(ret) {
|
||||||
Note.setNoteCache(ret, false);
|
Note.setNoteCache(ret, false);
|
||||||
// 把其它信息也带上
|
// 把其它信息也带上
|
||||||
@ -704,6 +710,9 @@ Note.newNote = function(notebookId, isShare, fromUserId, isMarkdown) {
|
|||||||
// 添加到缓存中
|
// 添加到缓存中
|
||||||
Note.addNoteCache(note);
|
Note.addNoteCache(note);
|
||||||
|
|
||||||
|
// 清空附件数
|
||||||
|
Attach.clearNoteAttachNum();
|
||||||
|
|
||||||
// 是否是为共享的notebook添加笔记, 如果是, 则还要记录fromUserId
|
// 是否是为共享的notebook添加笔记, 如果是, 则还要记录fromUserId
|
||||||
var newItem = "";
|
var newItem = "";
|
||||||
|
|
||||||
@ -1287,8 +1296,209 @@ Note.initContextmenu = function() {
|
|||||||
Note.contextmenu = $("#noteItemList .item-my").contextmenu(noteListMenu);
|
Note.contextmenu = $("#noteItemList .item-my").contextmenu(noteListMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 附件
|
||||||
|
// 笔记的附件需要ajax获取
|
||||||
|
// 建一张附件表? attachId, noteId, 其它信息
|
||||||
|
// note里有attach_nums字段记录个数
|
||||||
|
// [ok]
|
||||||
|
var Attach = {
|
||||||
|
loadedNoteAttachs: {}, // noteId => [attch1Info, attach2Info...] // 按笔记
|
||||||
|
attachsMap: {}, // attachId => attachInfo
|
||||||
|
init: function() {
|
||||||
|
var self = this;
|
||||||
|
// 显示attachs
|
||||||
|
$("#showAttach").click(function(){
|
||||||
|
self.renderAttachs(Note.curNoteId);
|
||||||
|
});
|
||||||
|
// 防止点击隐藏
|
||||||
|
self.attachListO.click(function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
// 删除
|
||||||
|
self.attachListO.on("click", ".delete-attach", function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
var attachId = $(this).closest('li').data("id");
|
||||||
|
var t = this;
|
||||||
|
if(confirm("Are you sure to delete it ?")) {
|
||||||
|
$(t).button("loading");
|
||||||
|
ajaxPost("/attach/deleteAttach", {attachId: attachId}, function(re) {
|
||||||
|
$(t).button("reset");
|
||||||
|
if(reIsOk(re)) {
|
||||||
|
self.deleteAttach(attachId);
|
||||||
|
} else {
|
||||||
|
alert(re.Msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 下载
|
||||||
|
self.attachListO.on("click", ".download-attach", function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
var attachId = $(this).closest('li').data("id");
|
||||||
|
window.open("/attach/download?attachId=" + attachId);
|
||||||
|
// location.href = "/attach/download?attachId=" + attachId;
|
||||||
|
});
|
||||||
|
// 下载全部
|
||||||
|
self.downloadAllBtnO.click(function() {
|
||||||
|
window.open("/attach/downloadAll?noteId=" + Note.curNoteId);
|
||||||
|
// location.href = "/attach/downloadAll?noteId=" + Note.curNoteId;
|
||||||
|
});
|
||||||
|
|
||||||
|
// make link
|
||||||
|
self.attachListO.on("click", ".link-attach", function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
var attachId = $(this).closest('li').data("id");
|
||||||
|
var attach = self.attachsMap[attachId];
|
||||||
|
var src = "/attach/download?attachId=" + attachId;
|
||||||
|
|
||||||
|
if(LEA.isMarkdownEditor() && MarkdownEditor) {
|
||||||
|
MarkdownEditor.insertLink(src, attach.Title);
|
||||||
|
} else {
|
||||||
|
tinymce.activeEditor.insertContent('<a target="_blank" href="' + src + '">' + attach.Title + '</a>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// make all link
|
||||||
|
self.linkAllBtnO.on("click",function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
var note = Note.getCurNote();
|
||||||
|
if(!note) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var src = "/attach/downloadAll?noteId=" + Note.curNoteId
|
||||||
|
var title = note.Title ? note.Title + ".tar.gz" : "all.tar.gz";
|
||||||
|
|
||||||
|
if(LEA.isMarkdownEditor() && MarkdownEditor) {
|
||||||
|
MarkdownEditor.insertLink(src, title);
|
||||||
|
} else {
|
||||||
|
tinymce.activeEditor.insertContent('<a target="_blank" href="' + src + '">' + title + '</a>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
attachListO: $("#attachList"),
|
||||||
|
attachNumO: $("#attachNum"),
|
||||||
|
attachDropdownO: $("#attachDropdown"),
|
||||||
|
downloadAllBtnO: $("#downloadAllBtn"),
|
||||||
|
linkAllBtnO: $("#linkAllBtn"),
|
||||||
|
// 添加笔记时
|
||||||
|
clearNoteAttachNum: function() {
|
||||||
|
var self = this;
|
||||||
|
self.attachNumO.html("").hide();
|
||||||
|
},
|
||||||
|
renderNoteAttachNum: function(noteId, needHide) {
|
||||||
|
var self = this;
|
||||||
|
var note = Note.getNote(noteId);
|
||||||
|
if(note.AttachNum) {
|
||||||
|
self.attachNumO.html("(" + note.AttachNum + ")").show();
|
||||||
|
self.downloadAllBtnO.show();
|
||||||
|
self.linkAllBtnO.show();
|
||||||
|
} else {
|
||||||
|
self.attachNumO.hide();
|
||||||
|
self.downloadAllBtnO.hide();
|
||||||
|
self.linkAllBtnO.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏掉
|
||||||
|
if(needHide) {
|
||||||
|
self.attachDropdownO.removeClass("open");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_renderAttachs: function(attachs) {
|
||||||
|
var self = this;
|
||||||
|
// foreach 循环之
|
||||||
|
/*
|
||||||
|
<li class="clearfix">
|
||||||
|
<div class="attach-title">leanote官abcefedafadfadfadfadfad方文档.doc</div>
|
||||||
|
<div class="attach-process">
|
||||||
|
<button class="btn btn-sm btn-warning">Delete</button>
|
||||||
|
<button class="btn btn-sm btn-deafult">Download</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
*/
|
||||||
|
var html = "";
|
||||||
|
var attachNum = attachs.length;
|
||||||
|
for(var i = 0; i < attachNum; ++i) {
|
||||||
|
var each = attachs[i];
|
||||||
|
html += '<li class="clearfix" data-id="' + each.AttachId + '">' +
|
||||||
|
'<div class="attach-title">' + each.Title + '</div>' +
|
||||||
|
'<div class="attach-process"> ' +
|
||||||
|
' <button class="btn btn-sm btn-warning delete-attach"><i class="fa fa-trash-o"></i></button> ' +
|
||||||
|
' <button type="button" class="btn btn-sm btn-primary download-attach"><i class="fa fa-download"></i></button> ' +
|
||||||
|
' <button type="button" class="btn btn-sm btn-deafult link-attach" title="Insert link into content"><i class="fa fa-link"></i></button> ' +
|
||||||
|
'</div>' +
|
||||||
|
'</li>';
|
||||||
|
self.attachsMap[each.AttachId] = each;
|
||||||
|
}
|
||||||
|
self.attachListO.html(html);
|
||||||
|
|
||||||
|
// 设置数量
|
||||||
|
var note = Note.getCurNote();
|
||||||
|
if(note) {
|
||||||
|
note.AttachNum = attachNum;
|
||||||
|
self.renderNoteAttachNum(note.NoteId, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 渲染noteId的附件
|
||||||
|
// 当点击"附件"时加载,
|
||||||
|
// TODO 判断是否已loaded
|
||||||
|
renderAttachs: function(noteId) {
|
||||||
|
var self = this;
|
||||||
|
if(self.loadedNoteAttachs[noteId]) {
|
||||||
|
self._renderAttachs(self.loadedNoteAttachs[noteId]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// ajax获取noteAttachs
|
||||||
|
ajaxGet("/attach/getAttachs", {noteId: noteId}, function(ret) {
|
||||||
|
var list = [];
|
||||||
|
if(ret.Ok) {
|
||||||
|
list = ret.List;
|
||||||
|
if(!list) {
|
||||||
|
list = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 添加到缓存中
|
||||||
|
self.loadedNoteAttachs[noteId] = list;
|
||||||
|
self._renderAttachs(list);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 添加附件, attachment_upload上传调用
|
||||||
|
addAttach: function(attachInfo) {
|
||||||
|
var self = this;
|
||||||
|
if(!self.loadedNoteAttachs[attachInfo.NoteId]) {
|
||||||
|
self.loadedNoteAttachs[attachInfo.NoteId] = [];
|
||||||
|
}
|
||||||
|
self.loadedNoteAttachs[attachInfo.NoteId].push(attachInfo);
|
||||||
|
self.renderAttachs(attachInfo.NoteId);
|
||||||
|
},
|
||||||
|
// 删除
|
||||||
|
deleteAttach: function(attachId) {
|
||||||
|
var self = this;
|
||||||
|
var noteId = Note.curNoteId;
|
||||||
|
var attachs = self.loadedNoteAttachs[noteId];
|
||||||
|
for(var i = 0; i < attachs.length; ++i) {
|
||||||
|
if(attachs[i].AttachId == attachId) {
|
||||||
|
// 删除之, 并render之
|
||||||
|
attachs.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// self.loadedNoteAttachs[noteId] = attachs;
|
||||||
|
self.renderAttachs(noteId);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 下载
|
||||||
|
downloadAttach: function(fileId) {
|
||||||
|
var self = this;
|
||||||
|
},
|
||||||
|
downloadAll: function() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------- 事件
|
//------------------- 事件
|
||||||
$(function() {
|
$(function() {
|
||||||
|
// 附件初始化
|
||||||
|
Attach.init();
|
||||||
|
|
||||||
//-----------------
|
//-----------------
|
||||||
// for list nav
|
// for list nav
|
||||||
$("#noteItemList").on("click", ".item", function(event) {
|
$("#noteItemList").on("click", ".item", function(event) {
|
||||||
|
@ -288,7 +288,12 @@ function editorIframeTabindex(index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//切换编辑器
|
//切换编辑器
|
||||||
|
LEA.isM = false;
|
||||||
|
LEA.isMarkdownEditor = function() {
|
||||||
|
return LEA.isM;
|
||||||
|
}
|
||||||
function switchEditor(isMarkdown) {
|
function switchEditor(isMarkdown) {
|
||||||
|
LEA.isM = isMarkdown;
|
||||||
// 富文本永远是2
|
// 富文本永远是2
|
||||||
if(!isMarkdown) {
|
if(!isMarkdown) {
|
||||||
$("#editor").show();
|
$("#editor").show();
|
||||||
|
@ -1317,7 +1317,37 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// life 新添加函数
|
||||||
|
// life
|
||||||
|
function insertLinkLife(link, text) {
|
||||||
|
inputBox.focus();
|
||||||
|
if (undoManager) {
|
||||||
|
undoManager.setCommandMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = new TextareaState(panels);
|
||||||
|
|
||||||
|
if (!state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var chunks = state.getChunks(); // 得到chunk
|
||||||
|
var fixupInputArea = function () {
|
||||||
|
inputBox.focus();
|
||||||
|
|
||||||
|
if (chunks) {
|
||||||
|
state.setChunks(chunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.restore();
|
||||||
|
previewManager.refresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
var a = commandProto.insertLink(chunks, fixupInputArea, link, text);
|
||||||
|
if(!a) fixupInputArea();
|
||||||
|
}
|
||||||
|
MarkdownEditor.insertLink = insertLinkLife;
|
||||||
|
|
||||||
// Perform the button's action.
|
// Perform the button's action.
|
||||||
function doClick(button) {
|
function doClick(button) {
|
||||||
@ -1369,6 +1399,7 @@
|
|||||||
|
|
||||||
var noCleanup = button.textOp(chunks, fixupInputArea);
|
var noCleanup = button.textOp(chunks, fixupInputArea);
|
||||||
|
|
||||||
|
// 这里生成
|
||||||
if (!noCleanup) {
|
if (!noCleanup) {
|
||||||
fixupInputArea();
|
fixupInputArea();
|
||||||
}
|
}
|
||||||
@ -1378,6 +1409,7 @@
|
|||||||
if (button.execute) {
|
if (button.execute) {
|
||||||
button.execute(undoManager);
|
button.execute(undoManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function setupButton(button, isEnabled) {
|
function setupButton(button, isEnabled) {
|
||||||
@ -1707,6 +1739,68 @@
|
|||||||
return title ? link + ' "' + title + '"' : link;
|
return title ? link + ' "' + title + '"' : link;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// life 添加
|
||||||
|
commandProto.insertLink = function (chunk, postProcessing, link, text) {
|
||||||
|
isImage = false;
|
||||||
|
chunk.trimWhitespace();
|
||||||
|
chunk.findTags(/\s*!?\[/, /\][ ]?(?:\n[ ]*)?(\[.*?\])?/);
|
||||||
|
var background;
|
||||||
|
|
||||||
|
if (chunk.endTag.length > 1 && chunk.startTag.length > 0) {
|
||||||
|
|
||||||
|
chunk.startTag = chunk.startTag.replace(/!?\[/, "");
|
||||||
|
chunk.endTag = "";
|
||||||
|
this.addLinkDef(chunk, null);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
// We're moving start and end tag back into the selection, since (as we're in the else block) we're not
|
||||||
|
// *removing* a link, but *adding* one, so whatever findTags() found is now back to being part of the
|
||||||
|
// link text. linkEnteredCallback takes care of escaping any brackets.
|
||||||
|
chunk.selection = chunk.startTag + chunk.selection + chunk.endTag;
|
||||||
|
chunk.startTag = chunk.endTag = "";
|
||||||
|
|
||||||
|
if (/\n\n/.test(chunk.selection)) {
|
||||||
|
this.addLinkDef(chunk, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var that = this;
|
||||||
|
// The function to be executed when you enter a link and press OK or Cancel.
|
||||||
|
// Marks up the link and adds the ref.
|
||||||
|
var linkEnteredCallback = function (link) {
|
||||||
|
|
||||||
|
background.parentNode.removeChild(background);
|
||||||
|
|
||||||
|
if (link !== null) {
|
||||||
|
chunk.selection = (" " + chunk.selection).replace(/([^\\](?:\\\\)*)(?=[[\]])/g, "$1\\").substr(1);
|
||||||
|
|
||||||
|
var linkDef = " [999]: " + properlyEncoded(link);
|
||||||
|
|
||||||
|
var num = that.addLinkDef(chunk, linkDef);
|
||||||
|
chunk.startTag = isImage ? "![" : "[";
|
||||||
|
chunk.endTag = "][" + num + "]";
|
||||||
|
chunk.selection = text;
|
||||||
|
}
|
||||||
|
postProcessing();
|
||||||
|
};
|
||||||
|
|
||||||
|
background = ui.createBackground();
|
||||||
|
linkEnteredCallback(link);
|
||||||
|
/*
|
||||||
|
if (isImage) {
|
||||||
|
if (!this.hooks.insertImageDialog(linkEnteredCallback))
|
||||||
|
ui.prompt(this.getString("imagedialog"), imageDefaultText, linkEnteredCallback);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!this.hooks.insertLinkDialog(linkEnteredCallback)) // jiawzhang
|
||||||
|
ui.prompt(this.getString("linkdialog"), linkDefaultText, linkEnteredCallback);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
commandProto.doLinkOrImage = function (chunk, postProcessing, isImage) {
|
commandProto.doLinkOrImage = function (chunk, postProcessing, isImage) {
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user