2018-02-05 19:05:41 +01:00
|
|
|
class Blogger extends this.OS.GUI.BaseApplication
|
|
|
|
constructor: (args) ->
|
|
|
|
super "Blogger", args
|
|
|
|
|
|
|
|
main: () ->
|
|
|
|
me = @
|
|
|
|
@tabbar = @find "tabbar"
|
|
|
|
@containers = [
|
|
|
|
@find("user-container"),
|
|
|
|
@find("cv-container"),
|
|
|
|
@find("blog-container")
|
|
|
|
]
|
2018-02-11 00:39:08 +01:00
|
|
|
@user = {}
|
2018-02-05 19:05:41 +01:00
|
|
|
@cvlist = @find "cv-list"
|
2018-02-13 04:59:08 +01:00
|
|
|
@cvlist.set "ontreeselect", (d) ->
|
2018-02-16 18:38:14 +01:00
|
|
|
me.CVSectionByCID Number(d.id)
|
2018-02-18 21:11:49 +01:00
|
|
|
@inputtags = @.find "input-tags"
|
2018-02-05 19:05:41 +01:00
|
|
|
@bloglist = @find "blog-list"
|
2018-02-13 04:59:08 +01:00
|
|
|
@userdb = new @_api.DB("user")
|
|
|
|
@cvcatdb = new @_api.DB("cv_cat")
|
2018-02-16 18:38:14 +01:00
|
|
|
@cvsecdb = new @_api.DB("cv_sections")
|
2018-02-18 21:11:49 +01:00
|
|
|
@blogdb = new @_api.DB("blogs")
|
2018-02-05 19:05:41 +01:00
|
|
|
@tabbar.set "onlistselect", (e) ->
|
|
|
|
($ el).hide() for el in me.containers
|
2018-02-11 00:39:08 +01:00
|
|
|
me.fetchData e.idx
|
2018-02-05 19:05:41 +01:00
|
|
|
($ me.containers[e.idx]).show()
|
2018-02-13 04:59:08 +01:00
|
|
|
me.trigger "calibrate"
|
2018-02-05 19:05:41 +01:00
|
|
|
|
|
|
|
@tabbar.set "items", [
|
|
|
|
{ iconclass: "fa fa-user-circle", selected: true },
|
|
|
|
{ iconclass: "fa fa-info-circle" },
|
|
|
|
{ iconclass: "fa fa-book" }
|
|
|
|
]
|
|
|
|
(@find "bt-user-save").set "onbtclick", (e) ->
|
|
|
|
me.saveUser()
|
2018-02-11 00:39:08 +01:00
|
|
|
|
2018-02-13 04:59:08 +01:00
|
|
|
(@find "cv-cat-add").set "onbtclick", (e) ->
|
|
|
|
me.openDialog "BloggerCategoryDialog",
|
|
|
|
(d) ->
|
|
|
|
c =
|
|
|
|
name: d.value,
|
|
|
|
pid: d.p.id,
|
|
|
|
publish: 1
|
|
|
|
me.cvcatdb.save c, (r) ->
|
|
|
|
me.error "Cannot add new category" if r.error
|
|
|
|
me.refreshCVCat()
|
|
|
|
#update the list
|
|
|
|
|
|
|
|
, "Add category", { tree: me.cvlist.get "data" }
|
|
|
|
|
|
|
|
(@find "cv-cat-edit").set "onbtclick", (e) ->
|
|
|
|
cat = me.cvlist.get "selectedItem"
|
|
|
|
return unless cat
|
|
|
|
me.openDialog "BloggerCategoryDialog", (d) ->
|
|
|
|
c =
|
|
|
|
id: cat.id,
|
|
|
|
publish: cat.publish,
|
|
|
|
pid: d.p.id,
|
|
|
|
name: d.value
|
|
|
|
|
|
|
|
me.cvcatdb.save c, (r) ->
|
2018-02-16 18:38:14 +01:00
|
|
|
return me.error "Cannot Edit category" if r.error
|
2018-02-13 04:59:08 +01:00
|
|
|
me.refreshCVCat()
|
|
|
|
, "Edit category", { tree: (me.cvlist.get "data"), cat: cat }
|
|
|
|
|
|
|
|
(@find "cv-cat-del").set "onbtclick", (e) ->
|
|
|
|
cat = me.cvlist.get "selectedItem"
|
|
|
|
return unless cat
|
|
|
|
me.openDialog "YesNoDialog",
|
|
|
|
(d) ->
|
|
|
|
return unless d
|
2018-02-21 11:55:15 +01:00
|
|
|
me.deleteCVCat cat
|
2018-02-13 04:59:08 +01:00
|
|
|
, "Delete cagegory" ,
|
|
|
|
{ iconclass: "fa fa-question-circle", text: "Do you really want to delete: #{cat.name} ?" }
|
2018-02-16 18:38:14 +01:00
|
|
|
|
|
|
|
(@find "cv-sec-add").set "onbtclick", (e) ->
|
|
|
|
cat = me.cvlist.get "selectedItem"
|
|
|
|
return me.notify "Please select a category" unless cat and cat.id isnt 0
|
|
|
|
me.openDialog "BloggerCVSectionDiaglog", (d) ->
|
|
|
|
d.cid = Number cat.id
|
|
|
|
d.start = Number d.start
|
|
|
|
d.end = Number d.end
|
2018-02-18 21:11:49 +01:00
|
|
|
d.publish = 1
|
2018-02-16 18:38:14 +01:00
|
|
|
me.cvsecdb.save d, (r) ->
|
|
|
|
return me.error "Cannot save section: #{r.error}" if r.error
|
|
|
|
me.CVSectionByCID Number(cat.id)
|
|
|
|
|
|
|
|
, "New section entry for #{cat.name}", null
|
|
|
|
|
2018-02-21 19:05:45 +01:00
|
|
|
(@find "cv-sec-move").set "onbtclick", (e) ->
|
|
|
|
sec = (me.find "cv-sec-list").get "selected"
|
|
|
|
return me.notify "Please select a section to move" unless sec
|
|
|
|
|
|
|
|
me.openDialog "BloggerCategoryDialog", (d) ->
|
|
|
|
c =
|
|
|
|
id: sec.id,
|
|
|
|
cid: d.p.id
|
|
|
|
|
|
|
|
me.cvsecdb.save c, (r) ->
|
|
|
|
return me.error "Cannot move section" if r.error
|
|
|
|
me.CVSectionByCID(sec.cid)
|
|
|
|
(me.find "cv-sec-list").set "selected", -1
|
|
|
|
, "Move to", { tree: (me.cvlist.get "data"), selonly: true }
|
|
|
|
|
2018-02-16 18:38:14 +01:00
|
|
|
(@find "cv-sec-edit").set "onbtclick", (e) ->
|
|
|
|
sec = (me.find "cv-sec-list").get "selected"
|
|
|
|
return me.notify "Please select a section to edit" unless sec
|
|
|
|
|
|
|
|
me.openDialog "BloggerCVSectionDiaglog", (d) ->
|
|
|
|
d.cid = Number sec.cid
|
|
|
|
d.start = Number d.start
|
|
|
|
d.end = Number d.end
|
2018-02-18 21:11:49 +01:00
|
|
|
d.publish = Number sec.publish
|
2018-02-16 18:38:14 +01:00
|
|
|
me.cvsecdb.save d, (r) ->
|
|
|
|
return me.error "Cannot save section: #{r.error}" if r.error
|
|
|
|
me.CVSectionByCID Number(sec.cid)
|
|
|
|
|
|
|
|
, "Modify section entry", sec
|
2018-02-18 21:11:49 +01:00
|
|
|
|
|
|
|
@editor = new SimpleMDE
|
|
|
|
element: me.find "markarea"
|
|
|
|
autofocus: true
|
|
|
|
tabSize: 4
|
|
|
|
indentWithTabs: true
|
|
|
|
toolbar: [
|
|
|
|
{
|
|
|
|
name: "new",
|
|
|
|
className: "fa fa-file",
|
|
|
|
action: (e) ->
|
|
|
|
me.bloglist.set "selected", -1
|
2018-02-27 01:17:48 +01:00
|
|
|
me.clearEditor()
|
2018-02-18 21:11:49 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "save",
|
|
|
|
className: "fa fa-save",
|
|
|
|
action: (e) ->
|
|
|
|
me.saveBlog()
|
|
|
|
}
|
|
|
|
, "|", "bold", "italic", "heading", "|", "quote", "code",
|
|
|
|
"unordered-list", "ordered-list", "|", "link",
|
|
|
|
"image", "table", "horizontal-rule",
|
|
|
|
{
|
|
|
|
name: "image",
|
|
|
|
className: "fa fa-file-image-o",
|
|
|
|
action: (e) ->
|
2018-02-19 16:52:05 +01:00
|
|
|
me.openDialog "FileDiaLog", (d, n, p) ->
|
|
|
|
p.asFileHandler().publish (r) ->
|
2018-02-19 16:45:18 +01:00
|
|
|
return me.error "Cannot export file for embeding to text" if r.error
|
|
|
|
doc = me.editor.codemirror.getDoc()
|
|
|
|
doc.replaceSelection "![](#{me._api.handler.shared}/#{r.result})"
|
2018-02-18 21:11:49 +01:00
|
|
|
, "Select image file", { mimes: ["image/.*"] }
|
|
|
|
},
|
2018-03-05 22:57:33 +01:00
|
|
|
{
|
|
|
|
name:"Youtube",
|
|
|
|
className: "fa fa-youtube",
|
|
|
|
action: (e) ->
|
|
|
|
doc = me.editor.codemirror.getDoc()
|
|
|
|
doc.replaceSelection "[[youtube:]]"
|
|
|
|
}
|
2018-02-18 21:11:49 +01:00
|
|
|
"|",
|
|
|
|
{
|
|
|
|
name: "preview",
|
|
|
|
className: "fa fa-eye no-disable",
|
|
|
|
action: (e) ->
|
|
|
|
me.previewOn = !me.previewOn
|
|
|
|
SimpleMDE.togglePreview e
|
|
|
|
}
|
|
|
|
]
|
|
|
|
@bloglist.set "onlistselect", (e) ->
|
|
|
|
sel = me.bloglist.get "selected"
|
|
|
|
return unless sel
|
2018-03-07 10:57:01 +01:00
|
|
|
me.blogdb.get Number(sel.id), (r) ->
|
|
|
|
me.error "Cannot fetch the entry content" if r.error
|
|
|
|
me.editor.value atob(r.result.content)
|
|
|
|
me.inputtags.value = r.result.tags
|
|
|
|
(me.find "blog-publish").set "swon", (if Number(r.result.publish) then true else false)
|
2018-02-27 00:55:02 +01:00
|
|
|
|
|
|
|
@.bloglist.set "onitemclose", (e) ->
|
|
|
|
me.openDialog "YesNoDialog", (b) ->
|
|
|
|
return unless b
|
|
|
|
me.blogdb.delete e.item.item.id, (r) ->
|
|
|
|
return me.error "Cannot delete: #{r.error}" if r.error
|
|
|
|
me.bloglist.remove e.item.item, true
|
|
|
|
me.bloglist.set "selected", -1
|
|
|
|
me.clearEditor()
|
|
|
|
, "Delete a post" ,
|
|
|
|
{ iconclass: "fa fa-question-circle", text: "Do you really want to delete this post ?" }
|
|
|
|
return false
|
2018-03-06 20:51:37 +01:00
|
|
|
@bindKey "CTRL-S", () ->
|
|
|
|
sel = me.tabbar.get "selidx"
|
|
|
|
return unless sel is 2
|
|
|
|
me.saveBlog()
|
2018-02-18 21:11:49 +01:00
|
|
|
@on "vboxchange", () ->
|
|
|
|
me.resizeContent()
|
2018-02-16 18:38:14 +01:00
|
|
|
# USER TAB
|
2018-02-11 00:39:08 +01:00
|
|
|
fetchData: (idx) ->
|
|
|
|
me = @
|
|
|
|
switch idx
|
|
|
|
when 0 #user info
|
2018-02-13 04:59:08 +01:00
|
|
|
|
|
|
|
@userdb.get null, (d) ->
|
2018-02-11 00:39:08 +01:00
|
|
|
return me.error "Cannot fetch user data" if d.error
|
|
|
|
me.user = d.result[0]
|
2018-02-16 18:38:14 +01:00
|
|
|
inputs = me.select "[input-class='user-input']"
|
2018-02-11 00:39:08 +01:00
|
|
|
($ v).val me.user[v.name] for v in inputs
|
2018-02-13 04:59:08 +01:00
|
|
|
when 1 # category
|
|
|
|
@refreshCVCat()
|
2018-02-11 00:39:08 +01:00
|
|
|
else
|
2018-02-18 21:11:49 +01:00
|
|
|
@loadBlogs()
|
2018-02-16 18:38:14 +01:00
|
|
|
|
|
|
|
saveUser:() ->
|
|
|
|
me = @
|
|
|
|
inputs = @select "[input-class='user-input']"
|
|
|
|
@user[v.name] = ($ v).val() for v in inputs
|
|
|
|
return @notify "Full name must be entered" if not @user.fullname or @user.fullname is ""
|
|
|
|
#console.log @user
|
|
|
|
@userdb.save @user, (r) ->
|
|
|
|
return me.error "Cannot save user data" if r.error
|
|
|
|
return me.notify "User data updated"
|
2018-02-11 00:39:08 +01:00
|
|
|
|
2018-02-16 18:38:14 +01:00
|
|
|
|
|
|
|
# PORFOLIO TAB
|
2018-02-13 04:59:08 +01:00
|
|
|
refreshCVCat: () ->
|
|
|
|
me = @
|
|
|
|
data =
|
|
|
|
name: "Porfolio",
|
|
|
|
id:0,
|
|
|
|
nodes: []
|
2018-02-21 19:05:45 +01:00
|
|
|
cnd =
|
|
|
|
order:
|
|
|
|
name: "ASC"
|
|
|
|
@cvcatdb.find cnd, (d) ->
|
2018-02-16 18:38:14 +01:00
|
|
|
if d.error
|
|
|
|
me.cvlist.set "data", data
|
|
|
|
return me.notify "Cannot fetch CV categories"
|
2018-02-13 04:59:08 +01:00
|
|
|
me.fetchCVCat d.result, data, "0"
|
|
|
|
me.cvlist.set "data", data
|
2018-02-16 18:38:14 +01:00
|
|
|
#it = (me.cvlist.find "pid", "2")[0]
|
|
|
|
#me.cvlist.set "selectedItem", it
|
2018-02-13 04:59:08 +01:00
|
|
|
|
|
|
|
fetchCVCat: (table, data, id) ->
|
|
|
|
result = (v for v in table when v.pid is id)
|
|
|
|
return data.nodes = null if result.length is 0
|
|
|
|
for v in result
|
|
|
|
v.nodes = []
|
|
|
|
@fetchCVCat table, v, v.id
|
|
|
|
#v.nodes = null if v.nodes.length is 0
|
|
|
|
data.nodes.push v
|
|
|
|
|
2018-02-21 11:55:15 +01:00
|
|
|
deleteCVCat: (cat) ->
|
|
|
|
me = @
|
|
|
|
ids = []
|
|
|
|
func = (c) ->
|
|
|
|
ids.push c.id
|
|
|
|
func(v) for v in c.nodes if c.nodes
|
|
|
|
func(cat)
|
2018-02-21 19:05:45 +01:00
|
|
|
|
|
|
|
cond = ({ "=": { cid: v } } for v in ids)
|
2018-02-21 11:55:15 +01:00
|
|
|
# delete all content
|
2018-02-21 19:05:45 +01:00
|
|
|
@cvsecdb.delete { "or": cond }, (r) ->
|
2018-02-21 11:55:15 +01:00
|
|
|
return me.error "Cannot delete all content of: #{cat.name} [#{r.error}]" if r.error
|
2018-02-21 19:05:45 +01:00
|
|
|
cond = ({ "=": { id: v } } for v in ids)
|
|
|
|
me.cvcatdb.delete { "or": cond }, (re) ->
|
2018-02-21 11:55:15 +01:00
|
|
|
return me.error "Cannot delete the category: #{cat.name} [#{re.error}]" if re.error
|
2018-02-21 19:05:45 +01:00
|
|
|
me.refreshCVCat()
|
2018-02-21 11:55:15 +01:00
|
|
|
|
2018-02-16 18:38:14 +01:00
|
|
|
CVSectionByCID: (cid) ->
|
2018-02-05 19:05:41 +01:00
|
|
|
me = @
|
2018-02-18 21:11:49 +01:00
|
|
|
cond =
|
|
|
|
exp:
|
|
|
|
"=":
|
|
|
|
cid: cid
|
|
|
|
order:
|
|
|
|
start: "DESC"
|
|
|
|
@cvsecdb.find cond, (d) ->
|
2018-02-16 18:38:14 +01:00
|
|
|
return me.notify "Section list is empty, please add one" if d.error
|
|
|
|
v.text = v.title for v in d.result
|
|
|
|
items = []
|
|
|
|
$(me.find "cv-sec-status").html "Found #{d.result.length} sections"
|
|
|
|
for v in d.result
|
|
|
|
v.text = v.title
|
|
|
|
v.complex = true
|
|
|
|
v.start = Number(v.start)
|
|
|
|
v.end = Number(v.end)
|
|
|
|
v.detail = []
|
|
|
|
v.detail.push { text: v.subtitle, class: "cv-subtitle" } if v.subtitle isnt ""
|
2018-02-21 19:05:45 +01:00
|
|
|
if v.start isnt 0 and v.end isnt 0
|
|
|
|
v.detail.push { text: "#{v.start} - #{v.end}", class: "cv-period" }
|
|
|
|
else
|
|
|
|
v.detail.push { text: "", class: "cv-period" }
|
2018-02-16 18:38:14 +01:00
|
|
|
v.detail.push { text: v.location, class: "cv-loc" } if v.location isnt ""
|
|
|
|
#v.detail.push { text: v.end } if v.end isnt 0
|
|
|
|
v.closable = true
|
|
|
|
v.detail.push { text: v.content, class: "cv-content" }
|
|
|
|
items.push v
|
|
|
|
el = me.find "cv-sec-list"
|
|
|
|
el.set "onitemclose", (e) ->
|
2018-02-18 21:11:49 +01:00
|
|
|
me.openDialog "YesNoDialog", (b) ->
|
2018-02-16 18:38:14 +01:00
|
|
|
return unless b
|
|
|
|
me.cvsecdb.delete e.item.item.id, (r) ->
|
|
|
|
return me.error "Cannot delete the section: #{r.error}" if r.error
|
|
|
|
el.remove e.item.item, true
|
|
|
|
, "Delete section" ,
|
|
|
|
{ iconclass: "fa fa-question-circle", text: "Do you really want to delete: #{e.item.item.text} ?" }
|
|
|
|
return false
|
|
|
|
el.set "items", items
|
2018-02-05 19:05:41 +01:00
|
|
|
|
2018-02-18 21:11:49 +01:00
|
|
|
# blog
|
|
|
|
saveBlog: () ->
|
|
|
|
me = @
|
|
|
|
sel = @bloglist.get "selected"
|
|
|
|
tags = @inputtags.value
|
|
|
|
content = @editor.value()
|
|
|
|
title = (new RegExp "^#+(.*)\n", "g").exec content
|
|
|
|
return @notify "Please insert a title in the text: beginning with heading" unless title and title.length is 2
|
|
|
|
return @notify "Please enter tags" if tags is ""
|
|
|
|
d = new Date()
|
|
|
|
data =
|
2018-02-23 19:52:53 +01:00
|
|
|
content: content.asBase64()
|
2018-02-18 21:11:49 +01:00
|
|
|
title: title[1].trim()
|
|
|
|
tags: tags
|
|
|
|
ctime: if sel then sel.ctime else d.timestamp()
|
|
|
|
ctimestr: if sel then sel.ctimestr else d.toString()
|
|
|
|
utime: d.timestamp()
|
|
|
|
utimestr: d.toString()
|
2018-03-05 14:58:20 +01:00
|
|
|
rendered: me.process(me.editor.options.previewRender(content))
|
2018-02-27 00:55:02 +01:00
|
|
|
publish: if ((@find "blog-publish").get "swon") then 1 else 0
|
2018-02-18 21:11:49 +01:00
|
|
|
data.id = sel.id if sel
|
|
|
|
#save the data
|
|
|
|
@blogdb.save data, (r) ->
|
|
|
|
return me.error "Cannot save blog: #{r.error}" if r.error
|
|
|
|
me.loadBlogs()
|
2018-03-05 14:58:20 +01:00
|
|
|
|
|
|
|
process: (text) ->
|
|
|
|
# find video tag and rendered it
|
|
|
|
embed = (id) ->
|
|
|
|
return """
|
|
|
|
<iframe
|
|
|
|
class = "embeded-video"
|
|
|
|
width="560" height="315"
|
|
|
|
src="https://www.youtube.com/embed/#{id}"
|
|
|
|
frameborder="0" allow="encrypted-media" allowfullscreen
|
|
|
|
></iframe>
|
|
|
|
"""
|
|
|
|
re = /\[\[([^:]*):([^\]]*)\]\]/g
|
|
|
|
replace = []
|
|
|
|
while (found = re.exec text) isnt null
|
|
|
|
replace.push found
|
|
|
|
return text.asBase64() unless replace.length > 0
|
|
|
|
ret = ""
|
|
|
|
begin = 0
|
|
|
|
for it in replace
|
|
|
|
ret += text.substring begin, it.index
|
|
|
|
ret += embed(it[2])
|
|
|
|
begin = it.index + it[0].length
|
|
|
|
ret += text.substring begin, text.length
|
|
|
|
#console.log ret
|
|
|
|
return ret.asBase64()
|
|
|
|
|
2018-02-27 00:55:02 +01:00
|
|
|
clearEditor:() ->
|
|
|
|
@.editor.value ""
|
|
|
|
@.inputtags.value = ""
|
|
|
|
(@.find "blog-publish").set "swon", false
|
2018-02-18 21:11:49 +01:00
|
|
|
# load blog
|
|
|
|
loadBlogs: () ->
|
|
|
|
me = @
|
2018-02-27 00:55:02 +01:00
|
|
|
selidx = @bloglist.get "selidx"
|
2018-02-23 19:52:53 +01:00
|
|
|
cond =
|
|
|
|
order:
|
|
|
|
ctime: "DESC"
|
2018-03-07 10:57:01 +01:00
|
|
|
fields: [
|
|
|
|
"id",
|
|
|
|
"title",
|
|
|
|
"ctimestr",
|
2018-03-07 14:19:23 +01:00
|
|
|
"ctime",
|
|
|
|
"utime",
|
2018-03-07 10:57:01 +01:00
|
|
|
"utimestr"
|
|
|
|
]
|
2018-02-23 19:52:53 +01:00
|
|
|
@blogdb.find cond, (r) ->
|
2018-02-18 21:28:40 +01:00
|
|
|
return me.notify "No post found: #{r.error}" if r.error
|
2018-03-07 10:57:01 +01:00
|
|
|
console.log r.result
|
2018-02-18 21:11:49 +01:00
|
|
|
for v in r.result
|
|
|
|
v.text = v.title
|
|
|
|
v.complex = true
|
|
|
|
v.closable = true
|
|
|
|
v.detail = [
|
|
|
|
{ text: "Created: #{v.ctimestr}", class: "blog-dates" },
|
|
|
|
{ text: "Updated: #{v.utimestr}", class: "blog-dates" }]
|
|
|
|
me.bloglist.set "items", r.result
|
2018-02-27 00:55:02 +01:00
|
|
|
if selidx isnt -1
|
|
|
|
me.bloglist.set "selected", selidx
|
|
|
|
else
|
|
|
|
me.clearEditor()
|
|
|
|
me.bloglist.set "selected", -1
|
2018-02-18 21:11:49 +01:00
|
|
|
resizeContent: () ->
|
|
|
|
container = @find "editor-container"
|
|
|
|
children = ($ container).children()
|
|
|
|
titlebar = (($ @scheme).find ".afx-window-top")[0]
|
|
|
|
toolbar = children[1]
|
|
|
|
statusbar = children[4]
|
|
|
|
cheight = ($ @scheme).height() - ($ titlebar).height() - ($ toolbar).height() - ($ statusbar).height() - 90
|
|
|
|
($ children[2]).css("height", cheight + "px")
|
2018-02-05 19:05:41 +01:00
|
|
|
Blogger.singleton = true
|
2018-02-16 18:38:14 +01:00
|
|
|
Blogger.dependencies = [ "mde/simplemde.min" ]
|
2018-02-05 19:05:41 +01:00
|
|
|
this.OS.register "Blogger", Blogger
|