diff --git a/Blogger/README.md b/Blogger/README.md deleted file mode 100644 index 2c958fe..0000000 --- a/Blogger/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Blogger - -Blackend for my blog at https://blog.iohub.dev - - -## Change logs - -### v0.2.x-a -* Patch 7: Fix sendmail API security bug -* Patch 6: Chage libraries load order -* Patch 5: Add user photo to portfolio -* Patch 4: Add package dependencies -* Patch 3: Correct JSON text decoding -* Patch 2: Bug fix rendering content -* Patch 0-1 Important change: Store raw post content to the database instead of base64 string as before - -### v0.1.x-a -* Patch 3-4: Enhance youtube video embedding feature in markdown -* Patch 2: CV Category now can be created when database is not created yet -* Patch 1: Fix package archive broken -* Patch 0: Change default email of the sender \ No newline at end of file diff --git a/Blogger/api/sendmail.lua b/Blogger/api/sendmail.lua deleted file mode 100644 index 6e8aab4..0000000 --- a/Blogger/api/sendmail.lua +++ /dev/null @@ -1,32 +0,0 @@ - -local data = ... --- print(data.content) -local error_msg = {} -local iserror = false -local tmp_name = "/tmp/"..os.time(os.date("!*t")) -local file = io.open (tmp_name , "w") -if file then - file:write("From: mrsang@lxsang.me\n") - file:write("Subject: " .. data.title .. "\n") - file:write( data.content.."\n") - file:close() - for k,v in pairs(data.to) do - print("sent to:"..v) - local to = v - local cmd = 'cat ' ..tmp_name .. '| sendmail ' .. to - --print(cmd) - local r = os.execute(cmd) - if not r then - iserror = true - table.insert(error_msg, v) - print("Unable to send mail to: "..v) - end - end -else - iserror = true - table.insert(error_msg, "Cannot create mail file") -end -local result = {} -result.error = iserror -result.result = error_msg -return result \ No newline at end of file diff --git a/Blogger/build/release/Blogger.zip b/Blogger/build/release/Blogger.zip deleted file mode 100644 index 5571e96..0000000 Binary files a/Blogger/build/release/Blogger.zip and /dev/null differ diff --git a/Blogger/cvsection.html b/Blogger/cvsection.html deleted file mode 100644 index eb7eeaf..0000000 --- a/Blogger/cvsection.html +++ /dev/null @@ -1,32 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - -
- -
- -
- - -
-
-
\ No newline at end of file diff --git a/Blogger/dialogs.coffee b/Blogger/dialogs.coffee deleted file mode 100644 index efe94b8..0000000 --- a/Blogger/dialogs.coffee +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright 2017-2018 Xuan Sang LE - -# AnTOS Web desktop is is licensed under the GNU General Public -# License v3.0, see the LICENCE file for more information - -# This program is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. - -# You should have received a copy of the GNU General Public License -#along with this program. If not, see https://www.gnu.org/licenses/. -class BloggerCategoryDialog extends this.OS.GUI.BasicDialog - constructor: () -> - super "BloggerCategoryDialog", BloggerCategoryDialog.scheme - - main: () -> - super.main() - @tree = @find "tree" - @txtinput = @find "txtinput" - - (@find "bt-ok").onbtclick = (e) => - sel = @tree.selectedItem - return @notify __("Please select a parent category") unless sel - seldata = sel.data - val = @txtinput.value - return @notify __("Please enter category name") if val is "" and not @data.selonly - return @notify __("Parent can not be the category itself") if @data.cat and @data.cat.id is seldata.id - @handle { p: seldata, value: val } if @handle - @quit() - - (@find "bt-cancel").onbtclick = (e) => - @quit() - if @data and @data.tree - if @data and @data.cat - @txtinput.value = @data.cat.name - if @data.cat.pid is "0" - seldata = @data.tree - else - seldata = @findDataByID @data.cat.pid, @data.tree.nodes - seldata.selected = true if seldata - @tree.data = @data.tree - @tree.expandAll() - # TODO set selected category name - - findDataByID: (id, list) -> - for data in list - return data if data.id is id - if data.nodes - @findDataByID id, data.nodes - return undefined - -BloggerCategoryDialog.scheme = """ - - - - - - - -
- - -
-
-
-
-
-""" - -# This dialog is use for cv section editing - -class BloggerCVSectionDiaglog extends this.OS.GUI.BasicDialog - constructor: (parent) -> - file = "#{parent.meta().path}/cvsection.html".asFileHandle() - super "BloggerCVSectionDiaglog", file - - main: () -> - super.main() - @editor = new SimpleMDE - autoDownloadFontAwesome: false - element: @find "contentarea" - status: false - toolbar: false - ($ (@select '[class = "CodeMirror-scroll"]')[0]).css "min-height", "50px" - ($ (@select '[class="CodeMirror cm-s-paper CodeMirror-wrap"]')[0]).css "min-height", "50px" - inputs = @select "[input-class='user-input']" - (($ v).val @data.section[v.name] for v in inputs ) if @data and @data.section - @editor.value @data.section.content if @data and @data.section - (@find "section-publish").swon = (if @data and @data.section and Number(@data.section.publish) then true else false) - (@find "bt-cv-sec-save").onbtclick = (e) => - data = {} - data[v.name] = ($ v).val() for v in inputs - data.content = @editor.value() - return @notify __("Title or content must not be blank") if data.title is "" and data.content is "" - #return @notify "Content must not be blank" if data.content is "" - data.id = @data.section.id if @data and @data.section - val = (@find "section-publish").swon - if val is true - data.publish = 1 - else - data.publish = 0 - @handle data if @handle - @quit() - - @on "vboxchange", () => @resizeContent() - @resizeContent() - - resizeContent: () -> - container = @find "editor-container" - children = ($ container).children() - cheight = ($ container).height() - 30 - ($ children[1]).css("height", cheight + "px") - - -# this dialog is for send mail -class BloggerSendmailDiaglog extends this.OS.GUI.BasicDialog - constructor: (parent) -> - file = "#{parent.meta().path}/sendmail.html".asFileHandle() - super "BloggerSendmailDiaglog", file - - main: () -> - super.main() - @subdb = new @.parent._api.DB("subscribers") - @maillinglist = @find "email-list" - title = (new RegExp "^#+(.*)\n", "g").exec @data.content - (@find "mail-title").value = title[1] - content = (@data.content.substring 0, 500) + "..." - (@find "contentarea").value = BloggerSendmailDiaglog.template.format @data.id, content - - @subdb.find {} - .then (d) => - for v in d - v.text = v.name - v.switch = true - v.checked = true - @maillinglist. items = d - .catch (e) => - @error __("Cannot fetch subscribers data: {0}", e.toString()), e - - (@find "bt-sendmail").onbtclick = (e) => - items = @maillinglist.items - emails = [] - for v in items - if v.checked is true - console.log v.email - emails.push v.email - - return @notify __("No email selected") if emails.length is 0 - # send the email - data = - path: "#{@parent.path()}/sendmail.lua", - parameters: - to: emails, - title: (@find "mail-title").value, - content: (@find "contentarea").value - @_api.apigateway data, false - .then (d) => - return @notify __("Unable to send mail to: {0}", d.result.join(", ")) if d.error - @quit() - .catch (e) => - console.log e - @error __("Error sending mail: {0}", e.toString()), e - - - -BloggerSendmailDiaglog.template = """ -Hello, - -Xuan Sang LE has just published a new post on his blog: https://blog.lxsang.me/post/id/{0} - -========== -{1} -========== - - -Read the full article via: -https://blog.lxsang.me/post/id/{0} - -You receive this email because you have been subscribed to his blog. - -Have a nice day, - -Sent from Blogger, an AntOS application -""" \ No newline at end of file diff --git a/Blogger/main.coffee b/Blogger/main.coffee deleted file mode 100644 index e601d2b..0000000 --- a/Blogger/main.coffee +++ /dev/null @@ -1,506 +0,0 @@ -# Copyright 2017-2018 Xuan Sang LE - -# AnTOS Web desktop is is licensed under the GNU General Public -# License v3.0, see the LICENCE file for more information - -# This program is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. - -# You should have received a copy of the GNU General Public License -#along with this program. If not, see https://www.gnu.org/licenses/. -class Blogger extends this.OS.application.BaseApplication - constructor: (args) -> - super "Blogger", args - - - main: () -> - @user = {} - @cvlist = @find "cv-list" - @cvlist.ontreeselect = (d) => - return unless d - data = d.data.item.data - @CVSectionByCID Number(data.id) - - @inputtags = @.find "input-tags" - @bloglist = @find "blog-list" - @seclist = @find "cv-sec-list" - - el = @find("photo") - $(el) - .click (e) => - @openDialog("FileDialog", { - title: __("Select image file"), - mimes: ["image/.*"] - }) - .then (d) => - el.value = d.file.path - .catch (e) => @error __("Unable to get file"), e - - @userdb = new @_api.DB("user") - @cvcatdb = new @_api.DB("cv_cat") - @cvsecdb = new @_api.DB("cv_sections") - @blogdb = new @_api.DB("blogs") - - - @tabcontainer = @find "tabcontainer" - @tabcontainer.ontabselect = (e) => - @fetchData e.data.container.aid - - (@find "bt-user-save").onbtclick = (e) => - @saveUser() - - (@find "cv-cat-add").onbtclick = (e) => - fn = (tree) => - @openDialog(new BloggerCategoryDialog(), { - title: __("Add category"), - tree: tree - }).then (d) => - c = - name: d.value, - pid: d.p.id, - publish: 1 - @cvcatdb.save c - .then (r) => - @refreshCVCat() - .catch (e) => @error __("Cannot add new category"), e - .catch (e) => @error e.toString(), e - @fetchCVCat() - .then (tree) => fn(tree) - .catch (e) => - data = - text: "Porfolio", - id:"0", - nodes: [] - fn(data) - @error __("Unable to fetch categories"), e - - (@find "cv-cat-edit").onbtclick = (e) => - sel = @cvlist.selectedItem - return unless sel - cat = sel.data - return unless cat - @fetchCVCat().then (tree) => - @openDialog(new BloggerCategoryDialog(), { - title: __("Edit category"), - tree: tree, cat: cat - }).then (d) => - c = - id: cat.id, - publish: cat.publish, - pid: d.p.id, - name: d.value - - @cvcatdb.save c - .then (r) => - @refreshCVCat() - .catch (e) => - @error __("Cannot Edit category"), e - .catch (e) => @error __("Unable to fetch categories"), e - - (@find "cv-cat-del").onbtclick = (e) => - sel = @cvlist.selectedItem - return unless sel - cat = sel.data - return unless cat - @openDialog("YesNoDialog", { - title: __("Delete category") , - iconclass: "fa fa-question-circle", - text: __("Do you really want to delete: {0}?", cat.name) - }).then (d) => - return unless d - @deleteCVCat cat - .catch (e) => @error e.toString(), e - - (@find "cv-sec-add").onbtclick = (e) => - sel = @cvlist.selectedItem - return unless sel - cat = sel.data - return @notify __("Please select a category") unless cat and cat.id isnt "0" - @openDialog(new BloggerCVSectionDiaglog(@), { - title: __("New section entry for {0}", cat.name) - }).then (d) => - d.cid = Number cat.id - d.start = Number d.start - d.end = Number d.end - # d.publish = 1 - @cvsecdb.save d - .then (r) => - @CVSectionByCID Number(cat.id) - .catch (e) => @error __("Cannot save section: {0}", e.toString()), e - - (@find "cv-sec-move").onbtclick = (e) => - sel = (@find "cv-sec-list").selectedItem - return @notify __("Please select a section to move") unless sel - sec = sel.data - - @fetchCVCat().then (tree) => - @openDialog(new BloggerCategoryDialog(),{ - title: __("Move to"), - tree: tree, - selonly: true - }).then (d) => - c = - id: sec.id, - cid: d.p.id - - @cvsecdb.save c - .then (r) => - @CVSectionByCID(sec.cid) - (@find "cv-sec-list").unselect() - .catch (e) => @error __("Cannot move section"), e - - (@find "cv-sec-edit").onbtclick = (e) => - sel = (@find "cv-sec-list").selectedItem - return @notify __("Please select a section to edit") unless sel - sec = sel.data - @openDialog(new BloggerCVSectionDiaglog(@), { - title: __("Modify section entry"), - section: sec - }).then (d) => - d.cid = Number sec.cid - d.start = Number d.start - d.end = Number d.end - #d.publish = Number sec.publish - @cvsecdb.save d - .then (r) => - @CVSectionByCID Number(sec.cid) - .catch (e) => return @error __("Cannot save section: {0}", e.toString()), e - - @seclist.onitemclose = (e) => - return unless e - data = e.data.item.data - @openDialog("YesNoDialog", { - iconclass: "fa fa-question-circle", - text: __("Do you really want to delete: {0}?", data.title) - }).then (b) => - return unless b - @cvsecdb.delete data.id - .then (r) => - @seclist.delete e.data.item - .catch (e) => @error __("Cannot delete the section: {0}", e.toString()), e - return false - - @editor = new SimpleMDE - element: @find "markarea" - autoDownloadFontAwesome: false - autofocus: true - tabSize: 4 - indentWithTabs: true - toolbar: [ - { - name: __("New"), - className: "fa fa-file", - action: (e) => - @bloglist.unselect() - @clearEditor() - }, - { - name: __("Save"), - className: "fa fa-save", - action: (e) => - @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) => - @openDialog("FileDialog", { - title: __("Select image file"), - mimes: ["image/.*"] - }).then (d) => - d.file.path.asFileHandle().publish() - .then (r) => - doc = @editor.codemirror.getDoc() - doc.replaceSelection "![](#{@_api.handle.shared}/#{r.result})" - .catch (e) => @error __("Cannot export file for embedding to text"), e - }, - { - name:"Youtube", - className: "fa fa-youtube", - action: (e) => - doc = @editor.codemirror.getDoc() - doc.replaceSelection "[[youtube:]]" - } - "|", - { - name: __("Preview"), - className: "fa fa-eye no-disable", - action: (e) => - @previewOn = !@previewOn - SimpleMDE.togglePreview e - #/console.log @select ".editor-preview editor-preview-active" - renderMathInElement @find "editor-container" - }, - "|", - { - name: __("Send mail"), - className: "fa fa-paper-plane", - action: (e) => - sel = @bloglist.selectedItem - return @error __("No post selected") unless sel - data = sel.data - @openDialog(new BloggerSendmailDiaglog(@), { - title: __("Send mail"), - content: @editor.value(), - id: data.id - }) - .then (d) -> - console.log "Email sent" - } - ], - - @bloglist.onlistselect = (e) => - el = @bloglist.selectedItem - return unless el - sel = el.data - return unless sel - @blogdb.get Number(sel.id) - .then (r) => - @editor.value r.content - @inputtags.value = r.tags - (@find "blog-publish").swon = if Number(r.publish) then true else false - .catch (e) => - @error __("Cannot fetch the entry content"), e - - @bloglist.onitemclose = (e) => - return unless e - el = e.data.item - data = el.data - @openDialog("YesNoDialog", { - title: __("Delete a post"), - iconclass: "fa fa-question-circle", - text: __("Do you really want to delete this post ?") - }).then (b) => - return unless b - @blogdb.delete data.id - .then (r) => - @bloglist.delete el - @bloglist.unselect() - @clearEditor() - return false - - - @bindKey "CTRL-S", () => - sel = @tabcontainer.selectedTab - return unless sel and sel.container.aid is "blog-container" - @saveBlog() - @on "vboxchange", () => - @resizeContent() - - @resizeContent() - @loadBlogs() - # @fetchData 0 - # USER TAB - fetchData: (idx) -> - switch idx - when "user-container" #user info - - @userdb.get null - .then (d) => - @user = d[0] - inputs = @select "[input-class='user-input']" - ($ v).val @user[v.name] for v in inputs - .catch (e) => @error __("Cannot fetch user data"), e - when "cv-container" # category - @refreshCVCat() - else - @loadBlogs() - - saveUser:() -> - 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 - .then (r) => - return @notify __("User data updated") - .catch (e) => return @error __("Cannot save user data"), e - - - # PORFOLIO TAB - refreshCVCat: () -> - @fetchCVCat().then (data) => - @cvlist.data = data - @cvlist.expandAll() - .catch (e) => @error __("Unable to load categories"), e - - fetchCVCat: () -> - new Promise (resolve, reject) => - data = - text: "Porfolio", - id:"0", - nodes: [] - cnd = - order: - name: "ASC" - @cvcatdb.find cnd - .then (d) => - @catListToTree d, data, "0" - resolve data - .catch (e) -> reject __e e - #it = (@cvlist.find "pid", "2")[0] - #@cvlist.set "selectedItem", it - - catListToTree: (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 = [] - v.text = v.name - @catListToTree table, v, v.id - #v.nodes = null if v.nodes.length is 0 - data.nodes.push v - - deleteCVCat: (cat) -> - me = @ - ids = [] - func = (c) -> - ids.push c.id - func(v) for v in c.nodes if c.nodes - func(cat) - - cond = ({ "=": { cid: v } } for v in ids) - # delete all content - @cvsecdb.delete({ "or": cond }).then (r) => - cond = ({ "=": { id: v } } for v in ids) - @cvcatdb.delete({ "or": cond }).then (re) => - @refreshCVCat() - @seclist.data=[] - .catch (e) => - @error __("Cannot delete the category: {0} [{1}]", cat.name, e.toString()), e - .catch (e) => - @error __("Cannot delete all content of: {0} [{1}]", cat.name, e.toString()), e - - CVSectionByCID: (cid) -> - cond = - exp: - "=": - cid: cid - order: - start: "DESC" - @cvsecdb.find(cond).then (d) => - items = [] - (@find "cv-sec-status").text = __("Found {0} sections", d.length) - for v in d - v.closable = true - v.tag = "afx-blogger-cvsection-item" - v.start = Number(v.start) - v.end = Number(v.end) - v.start = undefined if v.start < 1000 - v.end = undefined if v.end < 1000 - items.push v - @seclist.data = items - .catch (e) => @error e.toString(), e - - # blog - saveBlog: () -> - sel = undefined - selel = @bloglist.selectedItem - sel = selel.data if selel - 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 = - content: content - 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() - rendered: @process(@editor.options.previewRender(content)) - publish: if (@find "blog-publish").swon then 1 else 0 - data.id = sel.id if sel - #save the data - @blogdb.save data - .then (r) => - @loadBlogs() - .catch (e) => @error __("Cannot save blog: {0}", e.toString()), e - - process: (text) -> - # find video tag and rendered it - embed = (id) -> - return """ - - """ - re = /\[\[youtube:([^\]]*)\]\]/g - replace = [] - while (found = re.exec text) isnt null - replace.push found - return text unless replace.length > 0 - ret = "" - begin = 0 - for it in replace - ret += text.substring begin, it.index - ret += embed(it[1]) - begin = it.index + it[0].length - ret += text.substring begin, text.length - #console.log ret - return ret - - clearEditor:() -> - @.editor.value "" - @.inputtags.value = "" - (@.find "blog-publish").swon = false - # load blog - loadBlogs: () -> - selidx = -1 - el = @bloglist.selectedItem - selidx = $(el).index() - cond = - order: - ctime: "DESC" - fields: [ - "id", - "title", - "ctimestr", - "ctime", - "utime", - "utimestr" - ] - @blogdb.find cond - .then (r) => - v.tag = "afx-blogger-post-item" for v in r - @bloglist.data = r - if selidx isnt -1 - @bloglist.selected = selidx - else - @clearEditor() - @bloglist.selected = -1 - .catch (e) => @error __("No post found: {0}", e.toString()), e - - 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") - -Blogger.singleton = true -Blogger.dependencies = [ - "pkg://SimpleMDE/main.js", - "pkg://SimpleMDE/main.css" - "pkg://Katex/main.js", - "pkg://Katex/main.css", -] -this.OS.register "Blogger", Blogger \ No newline at end of file diff --git a/Blogger/main.css b/Blogger/main.css deleted file mode 100644 index 780d5fc..0000000 --- a/Blogger/main.css +++ /dev/null @@ -1,92 +0,0 @@ -afx-app-window[data-id="blogger-win"] afx-tab-container[data-id="tabcontainer"] afx-tab-bar afx-list-view > div.list-container { - padding: 0; - margin: 0; - border-right: 1px solid #292929; -} - -afx-app-window[data-id="blogger-win"] afx-tab-container[data-id="tabcontainer"] afx-tab-bar afx-list-view > div.list-container > ul li{ - font-size: 15px; - padding:0; - width: 100%; - border-radius: 0; - border:0; - margin: 0; - text-align: center; -} -afx-app-window[data-id="blogger-win"] afx-tab-container[data-id="tabcontainer"] afx-tab-bar afx-list-view > div.list-container > ul li.selected { - background-color: #116cd6; - color:white; -} - -afx-app-window[data-id="blogger-win"] afx-hbox[data-id="user-container"] afx-label i.label-text{ - font-weight: bold; -} - -afx-app-window .lbl-header i.label-text{ - font-weight: bold; -} -afx-app-window[data-id="blogger-win"] afx-hbox[data-id="cv-container"] .cat-header{ - border-bottom: 1px solid #cbcbcb; - text-align: center; -} - - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] > .list-container > ul .afx-cv-sec-title .label-text{ - font-weight: bold; - -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] afx-blogger-cvsection-item afx-label { - display: block; - -} -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] afx-blogger-cvsection-item p { - padding: 0; - margin: 0; -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] afx-blogger-cvsection-item .afx-cv-sec-period, -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] afx-blogger-cvsection-item .afx-cv-sec-loc { - text-align: right; -} -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] afx-blogger-cvsection-item afx-cv-sec-content{ - text-align: justify; - overflow-wrap: break-word; -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] > div.list-container > ul li.selected { - border: 1px solid #116cd6; - background-color: transparent; - border-radius: 5px; -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] .closable::before{ - content: "\f014"; - font-size: 14px; -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "cv-sec-list"] .period-end::before{ - content: "-"; -} - -afx-app-window[data-id ='blogger-win'] .editor-toolbar{ - background-color: white; -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "blog-list"] > div.list-container > ul li afx-label { - display: block; -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "blog-list"] > div.list-container > ul .afx-blogpost-title .label-text{ - font-weight: bold; -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "blog-list"] > div.list-container > ul .blog-dates .label-text{ - font-size: 10px; - font-weight: normal; -} - -afx-app-window[data-id="blogger-win"] afx-list-view[ data-id = "blog-list"] > div.list-container > ul li.selected { - background-color: #116cd6; - color:white; -} diff --git a/Blogger/package.json b/Blogger/package.json deleted file mode 100644 index 0531786..0000000 --- a/Blogger/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "app":"Blogger", - "name":"Blogging application", - "description":"Backend manager for blogging", - "info":{ - "author": "Xuan Sang LE", - "email": "xsang.le@gmail.com" - }, - "version":"0.2.7-a", - "category":"Internet", - "iconclass":"fa fa-book", - "dependencies": ["SimpleMDE@1.11.2-r","Katex@0.11.1-r"], - "mimes":["none"] -} \ No newline at end of file diff --git a/Blogger/project.json b/Blogger/project.json deleted file mode 100644 index e2c2d72..0000000 --- a/Blogger/project.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "Blogger", - "css": ["main.css"], - "javascripts": [], - "coffees": ["main.coffee", "dialogs.coffee", "tags.coffee"], - "copies": [ - "scheme.html", - "cvsection.html", - "api/sendmail.lua", - "sendmail.html", - "package.json", - "README.md" - ] -} \ No newline at end of file diff --git a/Blogger/scheme.html b/Blogger/scheme.html deleted file mode 100644 index 36d7082..0000000 --- a/Blogger/scheme.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
-
- - -
- - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
- -
- - - -
- -
-
- -
-
-
- -
-
-
\ No newline at end of file diff --git a/Blogger/sendmail.html b/Blogger/sendmail.html deleted file mode 100644 index 799709a..0000000 --- a/Blogger/sendmail.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - -
- -
- - - - -
- -
- -
-
-
-
-
\ No newline at end of file diff --git a/Blogger/tags.coffee b/Blogger/tags.coffee deleted file mode 100644 index b751498..0000000 --- a/Blogger/tags.coffee +++ /dev/null @@ -1,63 +0,0 @@ -Ant = this - -class CVSectionListItemTag extends this.OS.GUI.tag.ListViewItemTag - constructor: () -> - super() - - ondatachange: () -> - return unless @data - v = @data - nativel = ["content", "start", "end" ] - @closable = v.closable - for k, el of @refs - if v[k] and v[k] isnt "" - if nativel.includes k - $(el).text v[k] - else - el.text = v[k] - - reload: () -> - - init:() -> - - - itemlayout: () -> - { el: "div", children: [ - { el: "afx-label", ref: "title", class: "afx-cv-sec-title" }, - { el: "afx-label", ref: "subtitle", class: "afx-cv-sec-subtitle" }, - { el: "p", ref: "content", class: "afx-cv-sec-content" }, - { el: "p", class: "afx-cv-sec-period", children: [ - { el: "i", ref: "start" }, - { el: "i", ref: "end", class: "period-end" } - ] }, - { el: "afx-label", ref: "location", class: "afx-cv-sec-loc" } - ] } - -this.OS.GUI.tag.define "afx-blogger-cvsection-item", CVSectionListItemTag - - -class BlogPostListItemTag extends this.OS.GUI.tag.ListViewItemTag - constructor: () -> - super() - - ondatachange: (v) -> - return unless @data - v = @data - v.closable = true - @closable = v.closable - @refs.title.text = v.title - @refs.ctimestr.text = __("Created: {0}", v.ctimestr) - @refs.utimestr.text = __("Updated: {0}", v.utimestr) - - reload: () -> - - init:() -> - - itemlayout: () -> - { el: "div", children: [ - { el: "afx-label", ref: "title", class: "afx-blogpost-title" }, - { el: "afx-label", ref: "ctimestr", class: "blog-dates" }, - { el: "afx-label", ref: "utimestr", class: "blog-dates" }, - ] } - -this.OS.GUI.tag.define "afx-blogger-post-item", BlogPostListItemTag \ No newline at end of file diff --git a/DBDecoder/README.md b/DBDecoder/README.md deleted file mode 100644 index 4b364cd..0000000 --- a/DBDecoder/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# DBDecoder -This is an example project, generated by AntOS Development Kit - -## Howto -Use the CodePad command palette to access to the SDK functionalities: - -1. Create new project -2. Init the project from the current folder located in side bar -3. Build and run the project -4. Release the project in zip package - -## Set up build target - -Open the `project.json` file from the current project tree and add/remove -build target entries. Save the file \ No newline at end of file diff --git a/DBDecoder/assets/scheme.html b/DBDecoder/assets/scheme.html deleted file mode 100644 index cb58be5..0000000 --- a/DBDecoder/assets/scheme.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/DBDecoder/build/debug/README.md b/DBDecoder/build/debug/README.md deleted file mode 100644 index 4b364cd..0000000 --- a/DBDecoder/build/debug/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# DBDecoder -This is an example project, generated by AntOS Development Kit - -## Howto -Use the CodePad command palette to access to the SDK functionalities: - -1. Create new project -2. Init the project from the current folder located in side bar -3. Build and run the project -4. Release the project in zip package - -## Set up build target - -Open the `project.json` file from the current project tree and add/remove -build target entries. Save the file \ No newline at end of file diff --git a/DBDecoder/build/debug/main.js b/DBDecoder/build/debug/main.js deleted file mode 100644 index 08b71ff..0000000 --- a/DBDecoder/build/debug/main.js +++ /dev/null @@ -1,54 +0,0 @@ -(function() { - var DBDecoder; - - DBDecoder = class DBDecoder extends this.OS.application.BaseApplication { - constructor(args) { - super("DBDecoder", args); - } - - main() { - var bt; - bt = this.find("decoder"); - this.db = new this._api.DB("blogs"); - return bt.onbtclick = (e) => { - // decode the database - return this.db.find("1=1").then((data) => { - var i, len, v; - for (i = 0, len = data.length; i < len; i++) { - v = data[i]; - v.content = atob(v.content); - v.rendered = atob(v.rendered); - } - return this.saveDB(data).then(() => { - return this.notify("Data base saved"); - }).catch((e) => { - return this.error(e.toString(), e); - }); - }); - }; - } - - saveDB(list) { - return new Promise((resolve, reject) => { - var record; - if (list.length === 0) { - return resolve(); - } - record = list.shift(); - return this.db.save(record).then(() => { - return this.saveDB(list).then(() => { - return resolve(); - }).catch((e) => { - return reject(__e(e)); - }); - }).catch((e) => { - return reject(__e(e)); - }); - }); - } - - }; - - this.OS.register("DBDecoder", DBDecoder); - -}).call(this); diff --git a/DBDecoder/build/debug/package.json b/DBDecoder/build/debug/package.json deleted file mode 100644 index 3075358..0000000 --- a/DBDecoder/build/debug/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "app":"DBDecoder", - "name":"DBDecoder", - "description":"DBDecoder", - "info":{ - "author": "", - "email": "" - }, - "version":"0.0.2-a", - "category":"Other", - "iconclass":"fa fa-adn", - "mimes":["none"], - "locale": {} -} \ No newline at end of file diff --git a/DBDecoder/build/debug/scheme.html b/DBDecoder/build/debug/scheme.html deleted file mode 100644 index cb58be5..0000000 --- a/DBDecoder/build/debug/scheme.html +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/DBDecoder/build/release/DBDecoder.zip b/DBDecoder/build/release/DBDecoder.zip deleted file mode 100644 index ad0e7f0..0000000 Binary files a/DBDecoder/build/release/DBDecoder.zip and /dev/null differ diff --git a/DBDecoder/coffees/main.coffee b/DBDecoder/coffees/main.coffee deleted file mode 100644 index a1a75e7..0000000 --- a/DBDecoder/coffees/main.coffee +++ /dev/null @@ -1,29 +0,0 @@ -class DBDecoder extends this.OS.application.BaseApplication - constructor: ( args ) -> - super "DBDecoder", args - - main: () -> - bt = @find "decoder" - @db = new @_api.DB("blogs") - bt.onbtclick = (e) => - # decode the database - @db.find("1=1").then (data) => - for v in data - v.content = atob(v.content) - v.rendered = atob(v.rendered) - @saveDB(data).then () => - @notify "Data base saved" - .catch (e) => @error e.toString(), e - - saveDB: (list) -> - new Promise (resolve, reject) => - return resolve() if list.length is 0 - record = list.shift() - @db.save(record).then () => - @saveDB(list) - .then () => resolve() - .catch (e) => reject __e e - .catch (e) => reject __e e - - -this.OS.register "DBDecoder", DBDecoder \ No newline at end of file diff --git a/DBDecoder/package.json b/DBDecoder/package.json deleted file mode 100644 index 3075358..0000000 --- a/DBDecoder/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "app":"DBDecoder", - "name":"DBDecoder", - "description":"DBDecoder", - "info":{ - "author": "", - "email": "" - }, - "version":"0.0.2-a", - "category":"Other", - "iconclass":"fa fa-adn", - "mimes":["none"], - "locale": {} -} \ No newline at end of file diff --git a/DBDecoder/project.json b/DBDecoder/project.json deleted file mode 100644 index a0454bc..0000000 --- a/DBDecoder/project.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "DBDecoder", - "css": [], - "javascripts": [], - "coffees": ["coffees/main.coffee"], - "copies": ["assets/scheme.html", "package.json", "README.md"] -} \ No newline at end of file diff --git a/Docify/README.md b/Docify/README.md deleted file mode 100644 index 662978c..0000000 --- a/Docify/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Docify -Simple PDF document manager - -## Change logs -- v0.0.8-b: Allow upload files directly from the app -- v0.0.7-a: Change category and icon -- v0.0.6-a: Add print dialog (support server side printing) -- v0.0.5-a: Fix delete file bug -- v0.0.4-a: Display file size in entry meta-data -- v0.0.3-a: Fix document moved bug, sort entries by year, month, day \ No newline at end of file diff --git a/Docify/api/api.lua b/Docify/api/api.lua deleted file mode 100644 index 9fb4241..0000000 --- a/Docify/api/api.lua +++ /dev/null @@ -1,435 +0,0 @@ -local arg = ... - -ulib = require("ulib") -sqlite = modules.sqlite() -vfs = require("vfs") - -local handle = {} -local docpath = nil -local dbpath = nil - -local result = function(data) - return { - error = false, - result = data - } -end - -local error = function(data) - return { - error = data, - result = false - } -end - -local mkdirp =function(p) - if not vfs.exists(p) then - if not vfs.mkdir(p) then - return false, error("Unable to create directory: "..p) - end - end - return true, nil -end - -local merge_files = function(data) - local firstfile = data.file[1] - local fpath = docpath.."/"..data.cid - local r, e = mkdirp(fpath) - if not r then return e end - fpath = fpath.."/"..os.date("%d-%m-%Y_%H_%M_%S")..".pdf" - -- concat the files - if #data.file > 1 then - local cmd = "gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="..vfs.ospath(fpath) - for i,v in ipairs(data.file) do - cmd = cmd.." \""..vfs.ospath(v).."\"" - end - os.execute(cmd) - if not vfs.exists(fpath) then - return error("Unable to merge PDF files") - end - cmd = "chmod 777 "..vfs.ospath(fpath) - os.execute(cmd) - else - local cmd = "mv \""..vfs.ospath(firstfile).."\" \""..vfs.ospath(fpath).."\"" - os.execute(cmd) - if not vfs.exists(fpath) then - return error("Unable to move PDF file") - end - end - -- move the thumb file to the cache folder - local thumb = docpath.."/cache/"..std.sha1(firstfile:gsub(docpath, ""))..".png" - local desthumb = docpath.."/cache/"..std.sha1(fpath:gsub(docpath, ""))..".png" - if vfs.exists(thumb) then - vfs.move(thumb, desthumb) - end - -- remove all other thumb files - for i,v in ipairs(data.file) do - thumb = docpath.."/cache/"..std.sha1(v:gsub(docpath, ""))..".png" - if vfs.exists(thumb) then - vfs.delete(thumb) - end - -- delete all files - if vfs.exists(v) then - vfs.delete(v) - end - end - return result(fpath) -end - -handle.init = function(args) - - local r, e = mkdirp(docpath) - if not r then return e end - - r, e = mkdirp(docpath.."/unclassified") - if not r then return e end - - r, e = mkdirp(docpath.."/cache") - if not r then return e end - - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to initialized database "..dbpath) - end - local sql - -- check if table exists - if sqlite.hasTable(db, "categories") == 0 then - -- create the table - sql = [[ - CREATE TABLE "categories" ( - "id" INTEGER, - "name" TEXT NOT NULL, - PRIMARY KEY("id" AUTOINCREMENT) - ); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create table categories") - end - -- insert unknown category - sql = [[ - INSERT INTO categories("id","name") VALUES (0,'Uncategoried'); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create default category") - end - end - - if sqlite.hasTable(db, "owners") == 0 then - -- create the table - sql = [[ - CREATE TABLE "owners" ( - "id" INTEGER, - "name" TEXT NOT NULL, - PRIMARY KEY("id" AUTOINCREMENT) - ); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create table owners") - end - -- insert unknown category - sql = [[ - INSERT INTO owners("id","name") VALUES (0,'None'); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create default None owner") - end - end - - if sqlite.hasTable(db, "docs") == 0 then - -- create the table - sql = [[ - CREATE TABLE "docs" ( - "id" INTEGER, - "name" TEXT NOT NULL, - "ctime" INTEGER, - "day" INTEGER, - "month" INTEGER, - "year" INTEGER, - "cid" INTEGER DEFAULT 0, - "oid" INTEGER DEFAULT 0, - "file" TEXT NOT NULL, - "tags" TEXT, - "note" TEXT, - "mtime" INTEGER, - FOREIGN KEY("oid") REFERENCES "owners"("id") ON DELETE SET DEFAULT ON UPDATE NO ACTION, - FOREIGN KEY("cid") REFERENCES "categories"("id") ON DELETE SET DEFAULT ON UPDATE NO ACTION, - PRIMARY KEY("id" AUTOINCREMENT) - ); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create table docs") - end - end - sqlite.dbclose(db) - return result("Docify initialized") -end - -handle.select = function(param) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local r = sqlite.select(db, param.table, "*", param.cond) - sqlite.dbclose(db) - if r == nil then - return error("Unable to select data from "..param.table) - else - return result(r) - end -end - -handle.fetch = function(table) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local r = sqlite.select(db, table, "*", "1=1") - sqlite.dbclose(db) - if r == nil then - return error("Unable to fetch data from "..table) - else - return result(r) - end -end - -handle.insert = function(param) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local keys = {} - local values = {} - for k,v in pairs(param.data) do - if k ~= "id" then - table.insert(keys,k) - if type(v) == "number" then - table.insert(values, v) - elseif type(v) == "boolean" then - table.insert( values, v and 1 or 0 ) - else - local t = "\""..v:gsub('"', '""').."\"" - table.insert(values,t) - end - end - end - local sql = "INSERT INTO "..param.table.." ("..table.concat(keys,',')..') VALUES (' - sql = sql..table.concat(values,',')..');' - local r = sqlite.query(db, sql) - sqlite.dbclose(db) - if r == nil then - return error("Unable to insert data to "..param.table) - else - return result("Data inserted") - end -end - -handle.preview = function(path) - -- convert -resize 300x500 noel.pdf[0] thumb.png - local name = std.sha1(path:gsub(docpath,""))..".png" - -- try to find the thumb - local tpath = docpath.."/cache/"..name - if not vfs.exists(tpath) then - -- regenerate thumb - local cmd = "convert -resize 250x500 \""..vfs.ospath(path).."\"[0] "..vfs.ospath(tpath) - os.execute(cmd) - end - - if vfs.exists(tpath) then - local cmd = "chmod 777 "..vfs.ospath(tpath) - os.execute(cmd) - return result(tpath) - else - return error("do not exist") - end -end - -handle.get_doc = function(id) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local r = sqlite.select(db, "docs", "*", "id = "..id) - if r == nil or #r == 0 then - sqlite.dbclose(db) - return error("Unable to select data from "..param.table) - else - r = r[1] - local ret, meta = vfs.fileinfo(r.file) - if ret then - r.fileinfo = meta - end - local o = sqlite.select(db, "owners", "*", "id = "..r.oid) - sqlite.dbclose(db) - if o == nil or #o == 0 then - return result(r) - else - o = o[1] - r.owner = o.name - if r.ctime then - r.ctime = os.date("%d/%m/%Y %H:%M:%S", r.ctime) - end - - if r.mtime then - r.mtime = os.date("%d/%m/%Y %H:%M:%S", r.mtime) - end - local edate = "" - return result(r) - end - end -end - -handle.deletedoc = function(param) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local sql = "DELETE FROM docs WHERE id="..param.id..";" - local ret = sqlite.query(db, sql) == 1 - sqlite.dbclose(db) - if not ret then - return error("Unable to delete doc meta-data from database") - end - -- move file to unclassified - local newfile = docpath.."/unclassified/"..std.basename(param.file) - vfs.move(param.file, newfile) - -- delete thumb file - local thumb = docpath.."/cache/"..std.sha1(param.file:gsub(docpath,""))..".png" - if vfs.exists(thumb) then - vfs.delete(thumb) - end - return result("Document entry deleted") -end - -handle.updatedoc = function(param) - local r = merge_files(param.data) - if r.error then return r end - - if param.rm then - -- move ve the old file to unclassified - local newfile = docpath.."/unclassified/"..std.basename(param.rm) - local cmd = "rm -f "..vfs.ospath(param.rm) - os.execute(cmd) - --if vfs.exists(param.rm) then - -- vfs.move(param.rm, newfile) - --end - -- move the thumb file if needed - local thumb = docpath.."/cache/"..std.sha1(param.rm:gsub(docpath,""))..".png" - local newwthumb = docpath.."/cache/"..std.sha1(newfile:gsub(docpath, ""))..".png" - if vfs.exists(thumb) then - vfs.move(thumb, newwthumb) - end - end - param.data.file = r.result - print(r.result) - param.data.mtime = os.time(os.date("!*t")) - return handle.update({ - table = "docs", - data = param.data - }) -end - - -handle.insertdoc = function(data) - local r = merge_files(data) - if r.error then return r end - -- save data - data.file = r.result - data.ctime = os.time(os.date("!*t")) - data.mtime = os.time(os.date("!*t")) - local ret = handle.insert({ - table = "docs", - data = data - }) - return ret -end - -handle.update = function(param) - if not param.data.id or param.data.id == 0 then - return error("Record id is 0 or not found") - end - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local lst = {} - for k,v in pairs(param.data) do - if(type(v)== "number") then - table.insert(lst,k.."="..v) - elseif type(v) == "boolean" then - table.insert( lst, k.."="..(v and 1 or 0) ) - else - table.insert(lst,k.."=\""..v:gsub('"', '""').."\"") - end - end - - local sql = "UPDATE "..param.table.." SET "..table.concat(lst,",").." WHERE id="..param.data.id..";" - local r = sqlite.query(db, sql) - sqlite.dbclose(db) - if r == nil then - return error("Unable to update data to "..param.table) - else - return result("Data Updated") - end -end - -handle.delete = function(param) - if param.id == 0 then - return error("Record with id = 0 cannot be deleted") - end - - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local sql = "DELETE FROM "..param.table.." WHERE id="..param.id..";" - local r = sqlite.query(db, sql) - sqlite.dbclose(db) - if r == nil then - return error("Unable to delete data from "..param.table) - else - return result("Data deleted") - end -end - -handle.printdoc = function(opt) - local cmd = "lp " - if opt.printer and opt.printer ~= "" then - cmd = cmd .. " -d "..opt.printer - end - if opt.side == 0 then - cmd = cmd.. " -o sides=one-sided" - elseif opt.side == 1 then - cmd = cmd.. " -o sides=two-sided-long-edge" - elseif opt.side == 2 then - cmd = cmd .. " -o sides=two-sided-short-edge" - end - -- orientation landscape - if opt.orientation == 1 then - cmd = cmd.." -o orientation-requested=5" - end - - if opt.range == 1 then - cmd = cmd.." -P "..opt.pages - end - - cmd = cmd.. " "..vfs.ospath(opt.file) - print(cmd) - os.execute(cmd) - return result("A print job has been posted on server. Check if it successes") -end - - -if arg.action and handle[arg.action] then - -- check if the database exits - docpath = arg.docpath - dbpath = docpath.."/docify.db" - - return handle[arg.action](arg.args) -else - return error("Invalid action parameter") -end \ No newline at end of file diff --git a/Docify/assets/scheme.html b/Docify/assets/scheme.html deleted file mode 100644 index 1d5c67e..0000000 --- a/Docify/assets/scheme.html +++ /dev/null @@ -1,34 +0,0 @@ - - -
- - - -
-
- - - - - -
- - - - -
-
- - -
- -
- -
- - - -
-
-
-
\ No newline at end of file diff --git a/Docify/build.json b/Docify/build.json deleted file mode 100644 index 27525e2..0000000 --- a/Docify/build.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "Docify", - "targets": { - "init": { - "jobs": [ - { - "name": "vfs-mkdir", - "data": [ - "build", - "build/debug", - "build/release" - ] - } - ] - }, - "coffee": { - "require": [ - "coffee" - ], - "jobs": [ - { - "name": "coffee-compile", - "data": { - "src": [ - "coffees/dialogs.coffee", - "coffees/main.coffee" - ], - "dest": "build/debug/main.js" - } - } - ] - }, - "uglify": { - "require": [ - "terser" - ], - "jobs": [ - { - "name": "terser-uglify", - "data": [ - "build/debug/main.js" - ] - } - ] - }, - "copy": { - "jobs": [ - { - "name": "vfs-cp", - "data": { - "src": [ - "assets/scheme.html", - "api/api.lua", - "package.json", - "README.md" - ], - "dest": "build/debug" - } - } - ] - }, - "release": { - "require": [ - "zip" - ], - "depend": [ - "init", - "coffee", - "uglify", - "copy" - ], - "jobs": [ - { - "name": "zip-mk", - "data": { - "src": "build/debug", - "dest": "build/release/Docify.zip" - } - } - ] - } - } -} \ No newline at end of file diff --git a/Docify/build/debug/README.md b/Docify/build/debug/README.md deleted file mode 100644 index 662978c..0000000 --- a/Docify/build/debug/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Docify -Simple PDF document manager - -## Change logs -- v0.0.8-b: Allow upload files directly from the app -- v0.0.7-a: Change category and icon -- v0.0.6-a: Add print dialog (support server side printing) -- v0.0.5-a: Fix delete file bug -- v0.0.4-a: Display file size in entry meta-data -- v0.0.3-a: Fix document moved bug, sort entries by year, month, day \ No newline at end of file diff --git a/Docify/build/debug/api.lua b/Docify/build/debug/api.lua deleted file mode 100644 index 9fb4241..0000000 --- a/Docify/build/debug/api.lua +++ /dev/null @@ -1,435 +0,0 @@ -local arg = ... - -ulib = require("ulib") -sqlite = modules.sqlite() -vfs = require("vfs") - -local handle = {} -local docpath = nil -local dbpath = nil - -local result = function(data) - return { - error = false, - result = data - } -end - -local error = function(data) - return { - error = data, - result = false - } -end - -local mkdirp =function(p) - if not vfs.exists(p) then - if not vfs.mkdir(p) then - return false, error("Unable to create directory: "..p) - end - end - return true, nil -end - -local merge_files = function(data) - local firstfile = data.file[1] - local fpath = docpath.."/"..data.cid - local r, e = mkdirp(fpath) - if not r then return e end - fpath = fpath.."/"..os.date("%d-%m-%Y_%H_%M_%S")..".pdf" - -- concat the files - if #data.file > 1 then - local cmd = "gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile="..vfs.ospath(fpath) - for i,v in ipairs(data.file) do - cmd = cmd.." \""..vfs.ospath(v).."\"" - end - os.execute(cmd) - if not vfs.exists(fpath) then - return error("Unable to merge PDF files") - end - cmd = "chmod 777 "..vfs.ospath(fpath) - os.execute(cmd) - else - local cmd = "mv \""..vfs.ospath(firstfile).."\" \""..vfs.ospath(fpath).."\"" - os.execute(cmd) - if not vfs.exists(fpath) then - return error("Unable to move PDF file") - end - end - -- move the thumb file to the cache folder - local thumb = docpath.."/cache/"..std.sha1(firstfile:gsub(docpath, ""))..".png" - local desthumb = docpath.."/cache/"..std.sha1(fpath:gsub(docpath, ""))..".png" - if vfs.exists(thumb) then - vfs.move(thumb, desthumb) - end - -- remove all other thumb files - for i,v in ipairs(data.file) do - thumb = docpath.."/cache/"..std.sha1(v:gsub(docpath, ""))..".png" - if vfs.exists(thumb) then - vfs.delete(thumb) - end - -- delete all files - if vfs.exists(v) then - vfs.delete(v) - end - end - return result(fpath) -end - -handle.init = function(args) - - local r, e = mkdirp(docpath) - if not r then return e end - - r, e = mkdirp(docpath.."/unclassified") - if not r then return e end - - r, e = mkdirp(docpath.."/cache") - if not r then return e end - - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to initialized database "..dbpath) - end - local sql - -- check if table exists - if sqlite.hasTable(db, "categories") == 0 then - -- create the table - sql = [[ - CREATE TABLE "categories" ( - "id" INTEGER, - "name" TEXT NOT NULL, - PRIMARY KEY("id" AUTOINCREMENT) - ); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create table categories") - end - -- insert unknown category - sql = [[ - INSERT INTO categories("id","name") VALUES (0,'Uncategoried'); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create default category") - end - end - - if sqlite.hasTable(db, "owners") == 0 then - -- create the table - sql = [[ - CREATE TABLE "owners" ( - "id" INTEGER, - "name" TEXT NOT NULL, - PRIMARY KEY("id" AUTOINCREMENT) - ); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create table owners") - end - -- insert unknown category - sql = [[ - INSERT INTO owners("id","name") VALUES (0,'None'); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create default None owner") - end - end - - if sqlite.hasTable(db, "docs") == 0 then - -- create the table - sql = [[ - CREATE TABLE "docs" ( - "id" INTEGER, - "name" TEXT NOT NULL, - "ctime" INTEGER, - "day" INTEGER, - "month" INTEGER, - "year" INTEGER, - "cid" INTEGER DEFAULT 0, - "oid" INTEGER DEFAULT 0, - "file" TEXT NOT NULL, - "tags" TEXT, - "note" TEXT, - "mtime" INTEGER, - FOREIGN KEY("oid") REFERENCES "owners"("id") ON DELETE SET DEFAULT ON UPDATE NO ACTION, - FOREIGN KEY("cid") REFERENCES "categories"("id") ON DELETE SET DEFAULT ON UPDATE NO ACTION, - PRIMARY KEY("id" AUTOINCREMENT) - ); - ]] - if sqlite.query(db, sql) ~= 1 then - sqlite.dbclose(db) - return error("Unable to create table docs") - end - end - sqlite.dbclose(db) - return result("Docify initialized") -end - -handle.select = function(param) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local r = sqlite.select(db, param.table, "*", param.cond) - sqlite.dbclose(db) - if r == nil then - return error("Unable to select data from "..param.table) - else - return result(r) - end -end - -handle.fetch = function(table) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local r = sqlite.select(db, table, "*", "1=1") - sqlite.dbclose(db) - if r == nil then - return error("Unable to fetch data from "..table) - else - return result(r) - end -end - -handle.insert = function(param) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local keys = {} - local values = {} - for k,v in pairs(param.data) do - if k ~= "id" then - table.insert(keys,k) - if type(v) == "number" then - table.insert(values, v) - elseif type(v) == "boolean" then - table.insert( values, v and 1 or 0 ) - else - local t = "\""..v:gsub('"', '""').."\"" - table.insert(values,t) - end - end - end - local sql = "INSERT INTO "..param.table.." ("..table.concat(keys,',')..') VALUES (' - sql = sql..table.concat(values,',')..');' - local r = sqlite.query(db, sql) - sqlite.dbclose(db) - if r == nil then - return error("Unable to insert data to "..param.table) - else - return result("Data inserted") - end -end - -handle.preview = function(path) - -- convert -resize 300x500 noel.pdf[0] thumb.png - local name = std.sha1(path:gsub(docpath,""))..".png" - -- try to find the thumb - local tpath = docpath.."/cache/"..name - if not vfs.exists(tpath) then - -- regenerate thumb - local cmd = "convert -resize 250x500 \""..vfs.ospath(path).."\"[0] "..vfs.ospath(tpath) - os.execute(cmd) - end - - if vfs.exists(tpath) then - local cmd = "chmod 777 "..vfs.ospath(tpath) - os.execute(cmd) - return result(tpath) - else - return error("do not exist") - end -end - -handle.get_doc = function(id) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local r = sqlite.select(db, "docs", "*", "id = "..id) - if r == nil or #r == 0 then - sqlite.dbclose(db) - return error("Unable to select data from "..param.table) - else - r = r[1] - local ret, meta = vfs.fileinfo(r.file) - if ret then - r.fileinfo = meta - end - local o = sqlite.select(db, "owners", "*", "id = "..r.oid) - sqlite.dbclose(db) - if o == nil or #o == 0 then - return result(r) - else - o = o[1] - r.owner = o.name - if r.ctime then - r.ctime = os.date("%d/%m/%Y %H:%M:%S", r.ctime) - end - - if r.mtime then - r.mtime = os.date("%d/%m/%Y %H:%M:%S", r.mtime) - end - local edate = "" - return result(r) - end - end -end - -handle.deletedoc = function(param) - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local sql = "DELETE FROM docs WHERE id="..param.id..";" - local ret = sqlite.query(db, sql) == 1 - sqlite.dbclose(db) - if not ret then - return error("Unable to delete doc meta-data from database") - end - -- move file to unclassified - local newfile = docpath.."/unclassified/"..std.basename(param.file) - vfs.move(param.file, newfile) - -- delete thumb file - local thumb = docpath.."/cache/"..std.sha1(param.file:gsub(docpath,""))..".png" - if vfs.exists(thumb) then - vfs.delete(thumb) - end - return result("Document entry deleted") -end - -handle.updatedoc = function(param) - local r = merge_files(param.data) - if r.error then return r end - - if param.rm then - -- move ve the old file to unclassified - local newfile = docpath.."/unclassified/"..std.basename(param.rm) - local cmd = "rm -f "..vfs.ospath(param.rm) - os.execute(cmd) - --if vfs.exists(param.rm) then - -- vfs.move(param.rm, newfile) - --end - -- move the thumb file if needed - local thumb = docpath.."/cache/"..std.sha1(param.rm:gsub(docpath,""))..".png" - local newwthumb = docpath.."/cache/"..std.sha1(newfile:gsub(docpath, ""))..".png" - if vfs.exists(thumb) then - vfs.move(thumb, newwthumb) - end - end - param.data.file = r.result - print(r.result) - param.data.mtime = os.time(os.date("!*t")) - return handle.update({ - table = "docs", - data = param.data - }) -end - - -handle.insertdoc = function(data) - local r = merge_files(data) - if r.error then return r end - -- save data - data.file = r.result - data.ctime = os.time(os.date("!*t")) - data.mtime = os.time(os.date("!*t")) - local ret = handle.insert({ - table = "docs", - data = data - }) - return ret -end - -handle.update = function(param) - if not param.data.id or param.data.id == 0 then - return error("Record id is 0 or not found") - end - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local lst = {} - for k,v in pairs(param.data) do - if(type(v)== "number") then - table.insert(lst,k.."="..v) - elseif type(v) == "boolean" then - table.insert( lst, k.."="..(v and 1 or 0) ) - else - table.insert(lst,k.."=\""..v:gsub('"', '""').."\"") - end - end - - local sql = "UPDATE "..param.table.." SET "..table.concat(lst,",").." WHERE id="..param.data.id..";" - local r = sqlite.query(db, sql) - sqlite.dbclose(db) - if r == nil then - return error("Unable to update data to "..param.table) - else - return result("Data Updated") - end -end - -handle.delete = function(param) - if param.id == 0 then - return error("Record with id = 0 cannot be deleted") - end - - local db = sqlite._getdb(vfs.ospath(dbpath)) - if not db then - return error("Unable to get database "..dbpath) - end - local sql = "DELETE FROM "..param.table.." WHERE id="..param.id..";" - local r = sqlite.query(db, sql) - sqlite.dbclose(db) - if r == nil then - return error("Unable to delete data from "..param.table) - else - return result("Data deleted") - end -end - -handle.printdoc = function(opt) - local cmd = "lp " - if opt.printer and opt.printer ~= "" then - cmd = cmd .. " -d "..opt.printer - end - if opt.side == 0 then - cmd = cmd.. " -o sides=one-sided" - elseif opt.side == 1 then - cmd = cmd.. " -o sides=two-sided-long-edge" - elseif opt.side == 2 then - cmd = cmd .. " -o sides=two-sided-short-edge" - end - -- orientation landscape - if opt.orientation == 1 then - cmd = cmd.." -o orientation-requested=5" - end - - if opt.range == 1 then - cmd = cmd.." -P "..opt.pages - end - - cmd = cmd.. " "..vfs.ospath(opt.file) - print(cmd) - os.execute(cmd) - return result("A print job has been posted on server. Check if it successes") -end - - -if arg.action and handle[arg.action] then - -- check if the database exits - docpath = arg.docpath - dbpath = docpath.."/docify.db" - - return handle[arg.action](arg.args) -else - return error("Invalid action parameter") -end \ No newline at end of file diff --git a/Docify/build/debug/main.css b/Docify/build/debug/main.css deleted file mode 100644 index 6b0de1d..0000000 --- a/Docify/build/debug/main.css +++ /dev/null @@ -1,25 +0,0 @@ - -afx-app-window[data-id = "Docify"] .header .label-text -{ - font-weight: bold; -} -div[data-id = "preview-container"] -{ - overflow: auto; - display: block; -} - -canvas[data-id = "preview-canvas"] -{ - display: block; - margin:0 auto; -} -afx-app-window[data-id = "DocifyPrintDialog"] i.label-text { - font-weight: bold; -} - -afx-app-window[data-id = "DocifyPrintDialog"] input[type="radio"] { - margin: 0; - height: 12px; - margin-left: 10px; -} \ No newline at end of file diff --git a/Docify/build/debug/main.js b/Docify/build/debug/main.js deleted file mode 100644 index 25cd55f..0000000 --- a/Docify/build/debug/main.js +++ /dev/null @@ -1 +0,0 @@ -(function(){var t,i,a,r,n;(r=class t extends this.OS.GUI.BasicDialog{constructor(){super("OwnerDialog",t.scheme)}main(){return super.main(),this.oview=this.find("ownview"),this.oview.buttons=[{text:"",iconclass:"fa fa-plus-circle",onbtclick:t=>this.openDialog("PromptDialog",{title:__("Owner"),label:__("Name")}).then(t=>this.parent.exec("insert",{table:"owners",data:{name:t}}).then(t=>t.error?this.error(t.error):this.owner_refresh()).catch(t=>this.error(__("Unable to insert owner: {0}",t.toString()),t))).catch(t=>this.error(t.toString(),t))},{text:"",iconclass:"fa fa-minus-circle",onbtclick:t=>{var e;if(e=this.oview.selectedItem)return this.ask({text:__("Do you realy want to delete: `{0}`",e.data.text)}).then(t=>{if(t)return this.parent.exec("delete",{table:"owners",id:parseInt(e.data.id)}).then(t=>t.error?this.error(t.error):this.owner_refresh()).catch(t=>this.error(__("Unable delete category: {0}",t.toString()),t))})}},{text:"",iconclass:"fa fa-pencil-square-o",onbtclick:t=>{var e;if(e=this.oview.selectedItem)return this.openDialog("PromptDialog",{title:__("Owner"),label:__("Name"),value:e.data.name}).then(t=>this.parent.exec("update",{table:"owners",data:{id:parseInt(e.data.id),name:t}}).then(t=>t.error?this.error(t.error):this.owner_refresh()).catch(t=>this.error(__("Unable to update owner: {0}",t.toString()),t))).catch(t=>this.error(t.toString()))}}],this.owner_refresh()}owner_refresh(){return this.parent.exec("fetch","owners").then(t=>{var e,i,a,r;for(e=0,i=(a=t.result).length;ethis.error(__("Unable to fetch owners: {0}",t.toString()),e))}}).scheme="\n \n \n \n",(t=class t extends this.OS.GUI.BasicDialog{constructor(){super("DocDialog",t.scheme)}main(){var t,e,i,r,n,s,h,l;for(super.main(),this.flist=this.find("file-list"),this.dlist=this.find("dlist"),this.mlist=this.find("mlist"),this.ylist=this.find("ylist"),this.olist=this.find("olist"),this.setting=this.parent.setting,this.exec=this.parent.exec,this.preview=this.parent.preview,this.exec("fetch","owners").then(t=>{var e,i,a,r,n,s,h;if(t.error)return this.error(t.error);for(e=0,a=(n=t.result).length;ethis.error(__("Unable to fetch owner list: {0}",t.toString()),t)),this.dlist.push({text:"None",value:0}),h=0,t=i=1;i<=31;t=++i)this.dlist.push({text:""+t,value:t}),this.data&&parseInt(this.data.day)===t&&(h=t);for(this.dlist.selected=h,this.mlist.push({text:"None",value:0}),h=0,t=r=1;r<=12;t=++r)this.mlist.push({text:""+t,value:t}),this.data&&parseInt(this.data.month)===t&&(h=t);for(this.mlist.selected=h,this.ylist.push({text:"None",value:0}),this.ylist.selected=0,l=n=1960,s=(new Date).getFullYear();1960<=s?n<=s:n>=s;l=1960<=s?++n:--n)this.ylist.push({text:""+l,value:l,selected:this.data&&parseInt(this.data.year)===l});if(this.flist.buttons=[{text:"",iconclass:"fa fa-plus-circle",onbtclick:t=>this.openDialog(new a).then(t=>(t.text=t.filename,this.flist.push(t)))},{text:"",iconclass:"fa fa-minus-circle",onbtclick:t=>{var e;if(e=this.flist.selectedItem)return this.flist.delete(e)}}],this.flist.onlistselect=t=>this.parent.preview(t.data.item.data.path,this.find("preview-canvas")),this.find("btsave").onbtclick=t=>{var e,i;return(e={name:this.find("title").value.trim(),day:this.dlist.selectedItem.data.value,month:this.mlist.selectedItem.data.value,year:this.ylist.selectedItem.data.value,file:function(){var t,e,a,r;for(r=[],t=0,e=(a=this.flist.data).length;t0?(this.handle&&this.handle(e),this.quit()):this.notify(__("Please attach files to the entry")):this.notify(__("Please enter title"))},this.data)return this.find("title").value=this.data.name,this.find("note").value=this.data.note,this.find("tag").value=this.data.tags,(e=this.data.file.asFileHandle()).text=e.filename,this.flist.data=[e]}}).scheme='\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n
\n
\n \n
\n
\n
\n
',(a=class t extends this.OS.GUI.BasicDialog{constructor(){super("FilePreviewDialog",t.scheme)}main(){return super.main(),this.flist=this.find("file-list"),this.flist.buttons=[{text:"",iconclass:"fa fa-refresh",onbtclick:t=>this.refresh()}],this.flist.onlistselect=t=>this.parent.preview(t.data.item.data.path,this.find("preview-canvas")),this.find("btok").onbtclick=t=>{var e;return(e=this.flist.selectedItem)?(this.handle&&this.handle(e.data),this.quit()):this.quit()},this.refresh()}refresh(){return(this.parent.setting.docpath+"/unclassified").asFileHandle().read().then(t=>{var e,i,a,r;if(t.error)return this.error(t.error);for(e=0,i=(a=t.result).length;ethis.error(__("Unable to fetch unclassified file list: {0}",t.toString()),t))}}).scheme='\n \n \n \n \n \n \n
\n \n
\n
\n \n
\n \n
\n
\n
',(n=class t extends this.OS.GUI.BasicDialog{constructor(){super("PrintDialog",t.scheme)}main(){return super.main(),this.find("printerName").value=this.parent.setting.printer,this.find("btnprint").onbtclick=t=>{var e;return(e={}).range=parseInt($("input[name=range]:checked",this.scheme).val()),e.pages=this.find("txtPageRange").value,e.printer=this.find("printerName").value,e.orientation=parseInt($("input[name=orientation]:checked",this.scheme).val()),e.side=parseInt($("input[name=side]:checked",this.scheme).val()),this.handle&&this.handle(e),this.quit()}}}).scheme='\n \n \n \n \n
\n \n
\n \n \n \n
\n \n
\n \n
\n \n \n
\n \n
\n \n
\n \n
\n \n \n
\n
\n \n
\n
\n
',i=class extends this.OS.application.BaseApplication{constructor(t){super("Docify",t)}main(){return this.setting.printer||(this.setting.printer=""),this.catview=this.find("catview"),this.docview=this.find("docview"),this.docpreview=this.find("preview-canvas"),this.docgrid=this.find("docgrid"),this.docgrid.header=[{text:"",width:100},{text:""}],this.find("btdld").onbtclick=t=>{var e;if(e=this.docview.selectedItem)return e.data.file.asFileHandle().download().catch(t=>this.error(__("Unable to download: {}",t.toString()),t))},this.find("btopen").onbtclick=t=>{var e;if(e=this.docview.selectedItem)return e.data.file.asFileHandle().meta().then(t=>t.error?this.error(t.error):this._gui.openWith(t.result)).catch(t=>this.error(t.toString(),t))},this.find("btprint").onbtclick=t=>{var e;if(e=this.docview.selectedItem)return this.openDialog(new n,{}).then(t=>{if(t)return t.file=e.data.file,this.exec("printdoc",t).then(t=>t.error?this.error(t.error):this.notify(t.result)).catch(t=>this.error(__("Unable to insert category: {0}",t.toString()),t))})},this.catview.buttons=[{text:"",iconclass:"fa fa-plus-circle",onbtclick:t=>this.openDialog("PromptDialog",{title:__("Category"),label:__("Name")}).then(t=>this.exec("insert",{table:"categories",data:{name:t}}).then(t=>t.error?this.error(t.error):this.cat_refresh()).catch(t=>this.error(__("Unable to insert category: {0}",t.toString()),t))).catch(t=>this.error(t.toString(),t))},{text:"",iconclass:"fa fa-minus-circle",onbtclick:t=>{var e;if(e=this.catview.selectedItem)return this.ask({text:__("Do you realy want to delete: `{0}`",e.data.text)}).then(t=>{if(t)return this.exec("delete",{table:"categories",id:parseInt(e.data.id)}).then(t=>t.error?this.error(t.error):this.cat_refresh()).catch(t=>this.error(__("Unable delete category: {0}",t.toString()),t))})}},{text:"",iconclass:"fa fa-pencil-square-o",onbtclick:t=>{var e;if(e=this.catview.selectedItem)return this.openDialog("PromptDialog",{title:__("Category"),label:__("Name"),value:e.data.name}).then(t=>this.exec("update",{table:"categories",data:{id:parseInt(e.data.id),name:t}}).then(t=>t.error?this.error(t.error):this.cat_refresh()).catch(t=>this.error(__("Unable to update category: {0}",t.toString()),t))).catch(t=>this.error(t.toString(),t))}}],this.docview.onlistselect=t=>{var e;if(this.clear_preview(),e=t.data.item)return this.exec("get_doc",e.data.id).then(t=>{var e,i,a,r,n,s;if(t.error)return this.error(t.error);for(i in this.preview(t.result.file,this.docpreview),n=[],t.result.fileinfo&&(t.result.size=(t.result.fileinfo.size/1024).toFixed(2)+" Kb"),a={ctime:"Created on",mtime:"Modified on",note:"Note",tags:"Tags",name:"Title",owner:"Owner",edate:"Effective date",file:"File",size:"Size"},t.result.edate=`${t.result.day}/${t.result.month}/${t.result.year}`,r=t.result)s=r[i],(e=a[i])&&n.push([{text:e},{text:s}]);return this.docgrid.rows=n}).catch(t=>this.error(t.toString(),t))},this.catview.onlistselect=t=>{var e;if(this.clear_preview(),e=t.data.item)return this.update_doclist(e.data.id)},this.find("bt-add-doc").onbtclick=e=>{var i;return(i=this.catview.selectedItem)?this.openDialog(new t).then(t=>(t.cid=parseInt(i.data.id),this.exec("insertdoc",t).then(t=>t.error?this.error(t.error):(t.result&&this.notify(t.result),this.update_doclist(i.data.id),this.clear_preview())).catch(t=>this.error(t.toString(),t)))):this.notify(__("Please select a category"))},this.find("bt-del-doc").onbtclick=t=>{var e;if(e=this.docview.selectedItem)return this.ask({text:__("Do you really want to delete: `{0}`",e.data.name)}).then(t=>{if(t)return this.exec("deletedoc",{id:e.data.id,file:e.data.file}).then(t=>t.error?this.error(t.error):(this.notify(t.result),this.update_doclist(e.data.cid),this.clear_preview())).catch(t=>this.error(t.toString(),t))})},this.find("bt-upload-doc").onbtclick=t=>(this.setting.docpath+"/unclassified").asFileHandle().upload().then(t=>this.notify(__("File uploaded"))).catch(t=>this.error(t.toString(),t)),this.find("bt-edit-doc").onbtclick=e=>{var i,a;if(a=this.docview.selectedItem,i=this.catview.selectedItem,a)return this.openDialog(new t,a.data).then(t=>(t.cid=parseInt(i.data.id),t.id=a.data.id,this.exec("updatedoc",{data:t,rm:!t.file.includes(a.data.file)&&a.data.file}).then(t=>t.error?this.error(t.error):(t.result&&this.notify(t.result),this.update_doclist(i.data.id),this.clear_preview())).catch(t=>this.error(t.toString(),t))))},this.initialize()}update_doclist(t){return this.exec("select",{table:"docs",cond:`cid = ${t} ORDER BY year DESC, month DESC, day DESC`}).then(t=>{var e,i,a,r;if(t.error)return this.error(t.error);for(e=0,i=(a=t.result).length;ethis.error(t.toString(),t))}clear_preview(){return this.docpreview.getContext("2d").clearRect(0,0,this.docpreview.width,this.docpreview.height),this.docgrid.rows=[]}preview(t,e){return this.exec("preview",t).then(t=>{var i;return t.error?this.error(t.error):(i=t.result.asFileHandle()).read("binary").then(t=>{var a,r;return(r=new Image).onload=()=>{var t;return t=e.getContext("2d"),e.height=r.height,e.width=r.width,t.drawImage(r,0,0)},a=new Blob([t],{type:i.info.mime}),r.src=URL.createObjectURL(a)}).catch(t=>this.error(t.toString(),t))}).catch(t=>this.error(t.toString(),t))}cat_refresh(){return this.docview.data=[],this.clear_preview(),this.exec("fetch","categories").then(t=>{var e,i,a,r;for(e=0,i=(a=t.result).length;ethis.error(__("Unable to fetch categories: {0}",t.toString()),t))}initialize(){return this.setting.docpath?this.initdb():this.openDialog("FileDialog",{title:__("Please select a doc path"),mimes:["dir"]}).then(t=>(this.setting.docpath=t.file.path,this._api.setting(),this.initdb())).catch(t=>this.error(t.toString(),t))}exec(t,e){var i;return i={path:this.path()+"/api.lua",parameters:{action:t,docpath:this.setting.docpath,args:e}},this.call(i)}initdb(){return this.setting.docpath?this.exec("init").then(t=>t.error?this.error(t.error):(this.notify(t.result),this.cat_refresh())).catch(t=>this.error(__("Unable to init database: {0}",t.toString()),t)):this.error(__("No configured docpath"))}menu(){return[{text:"__(Options)",nodes:[{text:"__(Owners)",id:"owners"},{text:"__(Preview)",id:"preview"},{text:"__(Change doc path)",id:"setdocp"},{text:"__(Set default printer)",id:"setprinter"}],onchildselect:t=>this.fileMenuHandle(t.data.item.data.id)}]}fileMenuHandle(t){switch(t){case"owners":return this.openDialog(new r,{title:__("Owners")});case"preview":return this.openDialog(new a).then(t=>this.notify(t.path));case"setdocp":return this.setting.docpath=void 0,this.initialize();case"setprinter":return this.openDialog("PromptDialog",{title:__("Default Printer"),label:__("Enter printer name")}).then(t=>this.setting.printer=t)}}},this.OS.register("Docify",i)}).call(this); \ No newline at end of file diff --git a/Docify/build/debug/package.json b/Docify/build/debug/package.json deleted file mode 100644 index d03ee9b..0000000 --- a/Docify/build/debug/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "pkgname": "Docify", - "app":"Docify", - "name":"Docify", - "description":"Docify", - "info":{ - "author": "", - "email": "" - }, - "version":"0.0.8-b", - "category":"Office", - "iconclass":"bi bi-collection-fill", - "mimes":["none"], - "locale": {} -} \ No newline at end of file diff --git a/Docify/build/debug/scheme.html b/Docify/build/debug/scheme.html deleted file mode 100644 index 1d5c67e..0000000 --- a/Docify/build/debug/scheme.html +++ /dev/null @@ -1,34 +0,0 @@ - - -
- - - -
-
- - - - - -
- - - - -
-
- - -
- -
- -
- - - -
-
-
-
\ No newline at end of file diff --git a/Docify/build/release/Docify.zip b/Docify/build/release/Docify.zip deleted file mode 100644 index 02c0003..0000000 Binary files a/Docify/build/release/Docify.zip and /dev/null differ diff --git a/Docify/coffees/dialogs.coffee b/Docify/coffees/dialogs.coffee deleted file mode 100644 index 63344b3..0000000 --- a/Docify/coffees/dialogs.coffee +++ /dev/null @@ -1,329 +0,0 @@ -class OwnerDialog extends this.OS.GUI.BasicDialog - constructor: () -> - super "OwnerDialog", OwnerDialog.scheme - - main: () -> - super.main() - @oview = @find("ownview") - @oview.buttons = [ - { - text: "", - iconclass: "fa fa-plus-circle", - onbtclick: (e) => - @openDialog("PromptDialog", { title: __("Owner"), label: __("Name")}) - .then (d) => - @parent.exec("insert", { table: "owners", data: { name: d } }) - .then (r) => - return @error r.error if r.error - @owner_refresh() - .catch (e) => @error __("Unable to insert owner: {0}", e.toString()),e - .catch (e) => @error e.toString(),e - }, - { - text: "", - iconclass: "fa fa-minus-circle", - onbtclick: (e) => - item = @oview.selectedItem - return unless item - @ask({ text:__("Do you realy want to delete: `{0}`", item.data.text)}) - .then (d) => - return unless d - @parent.exec("delete", {table:"owners", id: parseInt(item.data.id)}) - .then (d) => - return @error d.error if d.error - @owner_refresh() - .catch (e) => - @error __("Unable delete category: {0}", e.toString()), e - }, - { - text: "", - iconclass: "fa fa-pencil-square-o", - onbtclick: (e) => - item = @oview.selectedItem - return unless item - @openDialog("PromptDialog", { title: __("Owner"), label: __("Name"), value: item.data.name }) - .then (d) => - @parent.exec("update", { table: "owners", data: { id: parseInt(item.data.id), name: d } }) - .then (r) => - return @error r.error if r.error - @owner_refresh() - .catch (e) => @error __("Unable to update owner: {0}", e.toString()), e - .catch (e) => @error e.toString() - } - ] - @owner_refresh() - - owner_refresh: () -> - @parent.exec("fetch", "owners") - .then (d) => - v.text = v.name for v in d.result - @oview.data = d.result - .catch (err) => @error __("Unable to fetch owners: {0}", err.toString()), e - -OwnerDialog.scheme = """ - - - - - -""" - -class DocDialog extends this.OS.GUI.BasicDialog - constructor: () -> - super "DocDialog", DocDialog.scheme - - main: () -> - super.main() - @flist = @find("file-list") - @dlist = @find("dlist") - @mlist = @find("mlist") - @ylist = @find("ylist") - @olist = @find("olist") - - @setting = @parent.setting - @exec = @parent.exec - @preview = @parent.preview - - @exec("fetch", "owners") - .then (d) => - return @error d.error if d.error - v.text = v.name for v in d.result - v.selected = (@data and @data.oid is v.id) for v in d.result - @olist.data = d.result - @olist.selected = 0 if not @olist.selectedItem - .catch (e) => - @error __("Unable to fetch owner list: {0}", e.toString()), e - - @dlist.push { - text:"None", - value: 0 - } - selected = 0 - for d in [1..31] - @dlist.push { - text:"#{d}", - value: d - } - selected = d if @data and parseInt(@data.day) is d - @dlist.selected = selected - - @mlist.push { - text:"None", - value: 0 - } - selected = 0 - for d in [1..12] - @mlist.push { - text:"#{d}", - value: d - } - selected = d if @data and parseInt(@data.month) is d - @mlist.selected = selected - - @ylist.push { - text:"None", - value: 0 - } - @ylist.selected = 0 - for y in [1960..new Date().getFullYear()] - @ylist.push { - text:"#{y}", - value: y, - selected: @data and parseInt(@data.year) is y - } - - @flist.buttons = [ - { - text: "", - iconclass: "fa fa-plus-circle", - onbtclick: (e) => - @openDialog(new FilePreviewDialog()) - .then (d) => - d.text = d.filename - @flist.push d - }, - { - text: "", - iconclass: "fa fa-minus-circle", - onbtclick: (e) => - item = @flist.selectedItem - return unless item - @flist.delete item - } - ] - @flist.onlistselect = (e) => - @parent.preview(e.data.item.data.path, @find("preview-canvas")) - - @find("btsave").onbtclick = (e) => - data = { - name: @find("title").value.trim(), - day: @dlist.selectedItem.data.value, - month: @mlist.selectedItem.data.value, - year: @ylist.selectedItem.data.value, - file: (v.path for v in @flist.data), - note: @find("note").value.trim(), - tags: @find("tag").value.trim(), - oid: parseInt(@olist.selectedItem.data.id) - } - return @notify __("Please enter title") unless data.name and data.title != "" - return @notify __("Please attach files to the entry") unless data.file.length > 0 - - @handle data if @handle - @quit() - - return unless @data - @find("title").value = @data.name - @find("note").value = @data.note - @find("tag").value = @data.tags - file = @data.file.asFileHandle() - file.text = file.filename - @flist.data = [ file ] - # owner - - -DocDialog.scheme = """ - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- -
-
-
-
-""" - -class FilePreviewDialog extends this.OS.GUI.BasicDialog - constructor: () -> - super "FilePreviewDialog", FilePreviewDialog.scheme - - main: () -> - super.main() - @flist = @find("file-list") - @flist.buttons = [ - { - text: "", - iconclass: "fa fa-refresh", - onbtclick: (e) => @refresh() - } - ] - - @flist.onlistselect = (e) => - # console.log e.data.item.data - @parent.preview(e.data.item.data.path, @find("preview-canvas")) - @find("btok").onbtclick = (e) => - item = @flist.selectedItem - return @quit() unless item - @handle(item.data) if @handle - @quit() - - @refresh() - - refresh: () -> - "#{@parent.setting.docpath}/unclassified".asFileHandle().read() - .then (d) => - return @error d.error if d.error - v.text = v.filename for v in d.result - @flist.data = (v for v in d.result when v.filename[0] isnt '.') - .catch (e) => - @error __("Unable to fetch unclassified file list: {0}", e.toString()), e - -FilePreviewDialog.scheme = """ - - - - - - - -
- -
-
- -
- -
-
-
-""" - -class PrintDialog extends this.OS.GUI.BasicDialog - constructor: () -> - super "PrintDialog", PrintDialog.scheme - - main: () -> - super.main() - @find("printerName").value = @parent.setting.printer - @find("btnprint").onbtclick = (e) => - data = {} - data.range = parseInt($('input[name=range]:checked', @scheme).val()) - data.pages = @find("txtPageRange").value - data.printer = @find("printerName").value - data.orientation = parseInt($('input[name=orientation]:checked', @scheme).val()) - data.side = parseInt($('input[name=side]:checked', @scheme).val()) - @handle data if @handle - @quit() - -PrintDialog.scheme = """ - - - - - -
- -
- - - -
- -
- -
- - -
- -
- -
- -
- - -
-
- -
-
-
-""" \ No newline at end of file diff --git a/Docify/coffees/main.coffee b/Docify/coffees/main.coffee deleted file mode 100644 index f4de028..0000000 --- a/Docify/coffees/main.coffee +++ /dev/null @@ -1,290 +0,0 @@ -class Docify extends this.OS.application.BaseApplication - constructor: ( args ) -> - super "Docify", args - - main: () -> - - @setting.printer = "" unless @setting.printer - - @catview = @find "catview" - @docview = @find "docview" - @docpreview = @find "preview-canvas" - @docgrid = @find "docgrid" - @docgrid.header = [ - { text: "", width: 100 }, - { text: "" }, - ] - @find("btdld").onbtclick = (e) => - item = @docview.selectedItem - return unless item - item.data.file.asFileHandle() - .download() - .catch (e) => @error __("Unable to download: {}", e.toString()), e - @find("btopen").onbtclick = (e) => - item = @docview.selectedItem - return unless item - item.data.file.asFileHandle().meta() - .then (m) => - return @error m.error if m.error - @_gui.openWith m.result - .catch (e) => @error e.toString(), e - @find("btprint").onbtclick = (e) => - item = @docview.selectedItem - return unless item - @openDialog new PrintDialog(), {} - .then (d) => - return unless d - d.file = item.data.file - @exec("printdoc", d) - .then (r) => - return @error r.error if r.error - @notify r.result - .catch (e) => @error __("Unable to insert category: {0}", e.toString()), e - @catview.buttons = [ - { - text: "", - iconclass: "fa fa-plus-circle", - onbtclick: (e) => - @openDialog("PromptDialog", { title: __("Category"), label: __("Name")}) - .then (d) => - @exec("insert", { table: "categories", data: { name: d } }) - .then (r) => - return @error r.error if r.error - @cat_refresh() - .catch (e) => @error __("Unable to insert category: {0}", e.toString()), e - .catch (e) => @error e.toString(), e - }, - { - text: "", - iconclass: "fa fa-minus-circle", - onbtclick: (e) => - item = @catview.selectedItem - return unless item - @ask({ text:__("Do you realy want to delete: `{0}`", item.data.text)}) - .then (d) => - return unless d - @exec("delete", {table:"categories", id: parseInt(item.data.id)}) - .then (d) => - return @error d.error if d.error - @cat_refresh() - .catch (e) => - @error __("Unable delete category: {0}", e.toString()), e - }, - { - text: "", - iconclass: "fa fa-pencil-square-o", - onbtclick: (e) => - item = @catview.selectedItem - return unless item - @openDialog("PromptDialog", { title: __("Category"), label: __("Name"), value: item.data.name }) - .then (d) => - @exec("update", { table: "categories", data: { id: parseInt(item.data.id), name: d } }) - .then (r) => - return @error r.error if r.error - @cat_refresh() - .catch (e) => @error __("Unable to update category: {0}", e.toString()), e - .catch (e) => @error e.toString(), e - } - ] - - @docview.onlistselect = (e) => - @clear_preview() - item = e.data.item - return unless item - @exec("get_doc", item.data.id) - .then (d) => - return @error d.error if d.error - @preview d.result.file, @docpreview - rows = [] - d.result.size = (d.result.fileinfo.size / 1024.0).toFixed(2) + " Kb" if d.result.fileinfo - map = { - ctime: "Created on", - mtime: "Modified on", - note: "Note", - tags: "Tags", - name: "Title", - owner: "Owner", - edate: "Effective date", - file: "File", - size: "Size" - } - d.result.edate = "#{d.result.day}/#{d.result.month}/#{d.result.year}" - for key, value of d.result - field = map[key] - rows.push [{text: field}, {text: value}] if field - @docgrid.rows = rows - .catch (e) => @error e.toString(), e - - @catview.onlistselect = (e) => - @clear_preview() - item = e.data.item - return unless item - @update_doclist(item.data.id) - - @find("bt-add-doc").onbtclick = (e) => - catiem = @catview.selectedItem - return @notify __("Please select a category") unless catiem - - @openDialog(new DocDialog()) - .then (data) => - data.cid = parseInt(catiem.data.id) - @exec("insertdoc", data) - .then (d) => - return @error d.error if d.error - @notify d.result if d.result - @update_doclist(catiem.data.id) - @clear_preview() - .catch (e) => @error e.toString(), e - - @find("bt-del-doc").onbtclick = (e) => - item = @docview.selectedItem - return unless item - @ask({ text: __("Do you really want to delete: `{0}`", item.data.name) }) - .then (d) => - return unless d - @exec("deletedoc", {id: item.data.id, file: item.data.file}) - .then (r) => - return @error r.error if r.error - @notify r.result - @update_doclist(item.data.cid) - @clear_preview() - .catch (e) => - @error e.toString(), e - @find("bt-upload-doc").onbtclick = (e) => - "#{@setting.docpath}/unclassified".asFileHandle().upload() - .then (r) => - @notify __("File uploaded") - .catch (e) => - @error e.toString(), e - @find("bt-edit-doc").onbtclick = (e) => - item = @docview.selectedItem - catiem = @catview.selectedItem - return unless item - @openDialog(new DocDialog(), item.data) - .then (data) => - data.cid = parseInt(catiem.data.id) - data.id = item.data.id - @exec("updatedoc", { - data:data, - rm: if not data.file.includes(item.data.file) then item.data.file else false - }) - .then (d) => - return @error d.error if d.error - @notify d.result if d.result - @update_doclist(catiem.data.id) - @clear_preview() - .catch (e) => @error e.toString(), e - - @initialize() - - update_doclist: (cid) -> - @exec("select",{table: "docs", cond:"cid = #{cid} ORDER BY year DESC, month DESC, day DESC"}) - .then (d) => - return @error d.error if d.error - v.text = v.name for v in d.result - @docview.data = d.result - .catch (e) => - @error e.toString(), e - - clear_preview: () -> - @docpreview.getContext('2d').clearRect(0,0,@docpreview.width,@docpreview.height) - @docgrid.rows = [] - - preview: (path, canvas) -> - @exec("preview", path) - .then (d) => - return @error d.error if d.error - file = d.result.asFileHandle() - file.read("binary") - .then (d) => - img = new Image() - #($ me.view).append img - img.onload = () => - context = canvas.getContext '2d' - canvas.height = img.height - canvas.width = img.width - #console.log canvas.width, canvas.height - context.drawImage img, 0, 0 - - blob = new Blob [d], { type: file.info.mime } - img.src = URL.createObjectURL blob - - .catch (e) => @error e.toString(), e - .catch (e) => - @error e.toString(), e - - cat_refresh: () -> - @docview.data = [] - @clear_preview() - @exec("fetch", "categories") - .then (d) => - v.text = v.name for v in d.result - @catview.data = d.result - .catch (err) => @error __("Unable to fetch categories: {0}", err.toString()), err - - initialize: () -> - # Check if we have configured docpath - if @setting.docpath - # check data base - @initdb() - else - # ask user to choose a docpath - @openDialog "FileDialog", { title:__("Please select a doc path"), mimes: ['dir'] } - .then (d) => - @setting.docpath = d.file.path - @_api.setting() - @initdb() - .catch (msg) => @error msg.toString(), msg - - exec: (action, args) -> - cmd = - path: "#{@path()}/api.lua", - parameters: - action: action, - docpath: @setting.docpath, - args: args - return @call(cmd) - - initdb: () -> - return @error __("No configured docpath") unless @setting.docpath - # fetch the categories from the database - @exec("init") - .then (d) => - return @error d.error if d.error - @notify d.result - # load categories - @cat_refresh() - .catch (e) => - @error __("Unable to init database: {0}", e.toString()), e - - menu: () -> - [ - { - text: "__(Options)", - nodes: [ - { text: "__(Owners)", id:"owners"}, - { text: "__(Preview)", id:"preview"}, - { text: "__(Change doc path)", id:"setdocp"}, - { text: "__(Set default printer)", id:"setprinter"} - ], - onchildselect: (e) => @fileMenuHandle e.data.item.data.id - } - ] - - fileMenuHandle:(id) -> - switch id - when "owners" - @openDialog new OwnerDialog(), { title: __("Owners")} - when "preview" - @openDialog(new FilePreviewDialog()) - .then (d) => - @notify d.path - when "setdocp" - @setting.docpath = undefined - @initialize() - when "setprinter" - @openDialog "PromptDialog", {title: __("Default Printer"), label: __("Enter printer name")} - .then (n) => - @setting.printer = n - -this.OS.register "Docify", Docify \ No newline at end of file diff --git a/Docify/css/main.css b/Docify/css/main.css deleted file mode 100644 index 1c69b86..0000000 --- a/Docify/css/main.css +++ /dev/null @@ -1,24 +0,0 @@ -afx-app-window[data-id = "Docify"] .header .label-text -{ - font-weight: bold; -} -div[data-id = "preview-container"] -{ - overflow: auto; - display: block; -} - -canvas[data-id = "preview-canvas"] -{ - display: block; - margin:0 auto; -} -afx-app-window[data-id = "DocifyPrintDialog"] i.label-text { - font-weight: bold; -} - -afx-app-window[data-id = "DocifyPrintDialog"] input[type="radio"] { - margin: 0; - height: 12px; - margin-left: 10px; -} \ No newline at end of file diff --git a/Docify/package.json b/Docify/package.json deleted file mode 100644 index d03ee9b..0000000 --- a/Docify/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "pkgname": "Docify", - "app":"Docify", - "name":"Docify", - "description":"Docify", - "info":{ - "author": "", - "email": "" - }, - "version":"0.0.8-b", - "category":"Office", - "iconclass":"bi bi-collection-fill", - "mimes":["none"], - "locale": {} -} \ No newline at end of file diff --git a/Docify/project.json b/Docify/project.json deleted file mode 100644 index ec2e84e..0000000 --- a/Docify/project.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "Docify", - "css": ["css/main.css"], - "javascripts": [], - "coffees": ["coffees/dialogs.coffee", "coffees/main.coffee"], - "copies": ["assets/scheme.html", "api/api.lua", "package.json", "README.md"] -} \ No newline at end of file diff --git a/LibreOffice/api/api.lua b/LibreOffice/api/api.lua index 230edb4..ec4ebf8 100644 --- a/LibreOffice/api/api.lua +++ b/LibreOffice/api/api.lua @@ -6,7 +6,6 @@ if not args then args = REQUEST end local vfs = require("vfs") -local DLCMD="wget --no-check-certificate -O" local handle = {} --local logger = Logger:new{ levels = {INFO = true, ERROR = true, DEBUG = false}} local result = function(data) @@ -17,12 +16,22 @@ local error = function(msg) return {error = msg, result = false} end +local fetch = function(url) + local https = require('ssl.https') + local body, code, headers = https.request(url) + if code~=200 then + LOG_ERROR("Error: ".. (code or '') ) + return nil + end + return body +end + handle.token = function(data) local file = vfs.ospath(data.file) local stat = ulib.file_stat(file) local ret = { sid = "access_token="..SESSION.sessionid, - key = std.sha1(file..":"..stat.mtime) + key = enc.sha1(file..":"..stat.mtime) } return result(ret) end @@ -43,14 +52,9 @@ handle.duplicate = function(data) end handle.discover = function(data) - local tmpfile = "/tmp/libreoffice_discover.xml" - local cmd = DLCMD.." "..tmpfile..' '..data.uri - os.execute(cmd) + content = fetch(url) -- move file to correct position - if ulib.exists(tmpfile) then - local f = assert(io.open(tmpfile, "rb")) - local content = f:read("*all") - f:close() + if content then return result(content) else return error("Unable to discover data") @@ -74,7 +78,7 @@ handle.file = function(data) elseif REQUEST.method == "POST" then --local clen = tonumber(HEADER['Content-Length']) local barr = REQUEST["application/octet-stream"] - bytes.write(barr, path) + barr:fileout(path) return result(true) else return error("Unknown request method") diff --git a/OnlyOffice/api/api.lua b/OnlyOffice/api/api.lua index 9cbd282..1ffc573 100644 --- a/OnlyOffice/api/api.lua +++ b/OnlyOffice/api/api.lua @@ -1,7 +1,6 @@ local args=... local vfs = require("vfs") -local DLCMD="wget --no-check-certificate -O" if not args then args = REQUEST end @@ -20,6 +19,25 @@ local error = function(data) } end +local download_file = function(src, dest) + local https = require('ssl.https') + local ltn12 = require("ltn12") + local file = io.open(dest, "w") + if not file then + LOG_ERROR("Unable to open file %s to write", dest) + return false + end + local body, code, headers = https.request{ + url = src, + sink = ltn12.sink.file(file) + } + if code~=200 then + LOG_ERROR("Error: ".. (code or '') ) + return false + end + return true +end + local handle = {} handle.token = function(data) @@ -27,17 +45,17 @@ handle.token = function(data) local stat = ulib.file_stat(file) local ret = { sid = "sessionid="..SESSION.sessionid, - key = std.sha1(file..":"..stat.mtime) + key = enc.sha1(file..":"..stat.mtime) } return result(ret) end handle.history = function(data) local file = vfs.ospath(data.file) - local history_file = vfs.ospath("home://.office/"..std.sha1(file).."/history.json") + local history_file = vfs.ospath("home://.office/"..enc.sha1(file).."/history.json") if(ulib.exists(history_file)) then local obj = JSON.decodeFile(history_file) - obj.hash = std.sha1(file) + obj.hash = enc.sha1(file) return result(obj) else return error("No history found") @@ -64,7 +82,7 @@ end handle.restore = function(data) local version = data.version local file = vfs.ospath(data.file) - local basepath = vfs.ospath("home://.office/"..std.sha1(file)) + local basepath = vfs.ospath("home://.office/"..enc.sha1(file)) if ulib.exists(basepath.."/history.json") then local history = JSON.decodeFile(basepath.."/history.json") local obj = handle.clean_up_version(basepath, history,version) @@ -95,22 +113,14 @@ handle.restore = function(data) end handle.duplicate = function(data) local file = vfs.ospath(data.as) - local tmpfile = "/tmp/"..std.sha1(file) - local cmd = DLCMD.." "..tmpfile..' "'..data.remote..'"' - os.execute(cmd) - -- move file to correct position - if ulib.exists(tmpfile) then - cmd = "mv "..tmpfile.." "..file - os.execute(cmd) - print("File "..file.." is duplicated with remote") - else + download_file(data.remote, file) + if not ulib.exists(file) then return error("Unable to duplicate file") end return result("File duplicated") end handle.save = function() - --print(JSON.encode(REQUEST)) if not REQUEST.json then return error("Invalid request") end @@ -123,31 +133,31 @@ handle.save = function() end local file = vfs.ospath(REQUEST.file) if data.status == 2 then - local tmpfile = "/tmp/"..std.sha1(file) - local cmd = DLCMD.." "..tmpfile..' "'..data.url..'"' - os.execute(cmd) + local tmpfile = "/tmp/"..enc.sha1(file) + download_file(data.url, tmpfile) -- move file to correct position if ulib.exists(tmpfile) then + LOG_INFO("Remote file saved to %s", tmpfile) -- back up the file version local history_dir = "home://.office" vfs.mkdir(history_dir) - history_dir = history_dir.."/"..std.sha1(file) + history_dir = history_dir.."/"..enc.sha1(file) vfs.mkdir(history_dir) history_dir = vfs.ospath(history_dir) -- backup old version - cmd = 'cp "'..file..'" "'..history_dir.."/"..data.key..'"' - os.execute(cmd) + ulib.send_file(file,history_dir.."/"..data.key) + LOG_INFO("Backup file saved to %s", history_dir.."/"..data.key) -- create new version local old_stat = ulib.file_stat(file) - cmd = 'mv "'..tmpfile..'" "'..file..'"' - os.execute(cmd) + if not ulib.move(tmpfile, file) then + ulib.send_file(tmpfile, file) + end -- get the new key local stat = ulib.file_stat(file) - local new_key = std.sha1(file..":"..stat.mtime) + local new_key = enc.sha1(file..":"..stat.mtime) -- save changes if(data.changesurl) then - cmd = DLCMD.." "..history_dir.."/"..new_key..'.zip "'..data.changesurl..'"' - os.execute(cmd) + download_file(data.changesurl, history_dir.."/"..new_key..'.zip') end -- now save version object local history_file = history_dir.."/history.json" @@ -177,7 +187,7 @@ handle.save = function() else return error("Cannot save history") end - print("File "..file.." sync with remote") + LOG_INFO("File "..file.." sync with remote") else return error("Unable to download") end @@ -192,4 +202,4 @@ if args.action and handle[args.action] then return handle[args.action](args.args) else return error("Invalid action parameter") -end +end \ No newline at end of file diff --git a/packages.json b/packages.json index e80ee10..67ee834 100644 --- a/packages.json +++ b/packages.json @@ -89,16 +89,6 @@ "dependencies": [], "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Archive/build/release/Archive.zip" }, - { - "pkgname": "Blogger", - "name": "Blogging application", - "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Blogger/README.md", - "category": "Internet", - "author": "Xuan Sang LE", - "version": "0.2.7-a", - "dependencies": ["SimpleMDE@1.11.2-r","Katex@0.11.1-r"],"mimes":["none"], - "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Blogger/build/release/Blogger.zip" - }, { "pkgname": "Booklet", "name": "Booklet", @@ -129,16 +119,6 @@ "dependencies": ["ACECore@1.4.12-r"],"mimes":["text/.*","[^/]*/json.*","[^/]*/.*ml","[^/]*/javascript","dir"], "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/CodePad/build/release/CodePad.zip" }, - { - "pkgname": "DBDecoder", - "name": "DBDecoder", - "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/DBDecoder/README.md", - "category": "Other", - "author": "", - "version": "0.0.2-a", - "dependencies": [], - "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/DBDecoder/build/release/DBDecoder.zip" - }, { "pkgname": "DiffEditor", "name": "Diff Editor", @@ -149,16 +129,6 @@ "dependencies": ["AceDiff@3.0.3-r"], "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/DiffEditor/build/release/DiffEditor.zip" }, - { - "pkgname": "Docify", - "name": "Docify", - "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Docify/README.md", - "category": "Office", - "author": "", - "version": "0.0.8-b", - "dependencies": [], - "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/Docify/build/release/Docify.zip" - }, { "pkgname": "Dockman", "name": "Remote Docker Manager",