mirror of
https://github.com/antos-rde/antosdk-apps.git
synced 2024-12-26 04:08:21 +01:00
Docify: Use libsqlite to handle database in Docify
This commit is contained in:
parent
6354c48680
commit
7292d2ef21
@ -87,7 +87,7 @@ namespace OS {
|
|||||||
</div>
|
</div>
|
||||||
</afx-hbox>
|
</afx-hbox>
|
||||||
</afx-vbox>
|
</afx-vbox>
|
||||||
</afx-app-window>\s
|
</afx-app-window>\
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// This dialog is use for cv section editing
|
// This dialog is use for cv section editing
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
Simple PDF document manager
|
Simple PDF document manager
|
||||||
|
|
||||||
## Change logs
|
## Change logs
|
||||||
|
- v0.1.0-b: use libsqlite for database handling
|
||||||
- v0.0.9-b: Adapt to support AntOS 2.0.x
|
- v0.0.9-b: Adapt to support AntOS 2.0.x
|
||||||
- v0.0.8-b: Allow upload files directly from the app
|
- v0.0.8-b: Allow upload files directly from the app
|
||||||
- v0.0.7-a: Change category and icon
|
- v0.0.7-a: Change category and icon
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
local arg = ...
|
local arg = ...
|
||||||
|
|
||||||
ulib = require("ulib")
|
ulib = require("ulib")
|
||||||
sqlite = modules.sqlite()
|
|
||||||
vfs = require("vfs")
|
vfs = require("vfs")
|
||||||
|
|
||||||
local handle = {}
|
local handle = {}
|
||||||
local docpath = nil
|
local docpath = nil
|
||||||
local dbpath = nil
|
|
||||||
|
|
||||||
local result = function(data)
|
local result = function(data)
|
||||||
return {
|
return {
|
||||||
@ -31,7 +29,7 @@ local mkdirp =function(p)
|
|||||||
return true, nil
|
return true, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local merge_files = function(data)
|
handle.merge_files = function(data)
|
||||||
local firstfile = data.file[1]
|
local firstfile = data.file[1]
|
||||||
local fpath = docpath.."/"..data.cid
|
local fpath = docpath.."/"..data.cid
|
||||||
local r, e = mkdirp(fpath)
|
local r, e = mkdirp(fpath)
|
||||||
@ -57,14 +55,14 @@ local merge_files = function(data)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- move the thumb file to the cache folder
|
-- move the thumb file to the cache folder
|
||||||
local thumb = docpath.."/cache/"..std.sha1(firstfile:gsub(docpath, ""))..".png"
|
local thumb = docpath.."/cache/"..enc.sha1(firstfile:gsub(docpath, ""))..".png"
|
||||||
local desthumb = docpath.."/cache/"..std.sha1(fpath:gsub(docpath, ""))..".png"
|
local desthumb = docpath.."/cache/"..enc.sha1(fpath:gsub(docpath, ""))..".png"
|
||||||
if vfs.exists(thumb) then
|
if vfs.exists(thumb) then
|
||||||
vfs.move(thumb, desthumb)
|
vfs.move(thumb, desthumb)
|
||||||
end
|
end
|
||||||
-- remove all other thumb files
|
-- remove all other thumb files
|
||||||
for i,v in ipairs(data.file) do
|
for i,v in ipairs(data.file) do
|
||||||
thumb = docpath.."/cache/"..std.sha1(v:gsub(docpath, ""))..".png"
|
thumb = docpath.."/cache/"..enc.sha1(v:gsub(docpath, ""))..".png"
|
||||||
if vfs.exists(thumb) then
|
if vfs.exists(thumb) then
|
||||||
vfs.delete(thumb)
|
vfs.delete(thumb)
|
||||||
end
|
end
|
||||||
@ -76,166 +74,15 @@ local merge_files = function(data)
|
|||||||
return result(fpath)
|
return result(fpath)
|
||||||
end
|
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)
|
handle.preview = function(path)
|
||||||
-- convert -resize 300x500 noel.pdf[0] thumb.png
|
-- convert -resize 300x500 noel.pdf[0] thumb.png
|
||||||
local name = std.sha1(path:gsub(docpath,""))..".png"
|
local name = enc.sha1(path:gsub(docpath,""))..".png"
|
||||||
-- try to find the thumb
|
-- try to find the thumb
|
||||||
local tpath = docpath.."/cache/"..name
|
local tpath = docpath.."/cache/"..name
|
||||||
if not vfs.exists(tpath) then
|
if not vfs.exists(tpath) then
|
||||||
-- regenerate thumb
|
-- regenerate thumb
|
||||||
local cmd = "convert -resize 250x500 \""..vfs.ospath(path).."\"[0] "..vfs.ospath(tpath)
|
local cmd = "convert -resize 250x500 \""..vfs.ospath(path).."\"[0] "..vfs.ospath(tpath)
|
||||||
|
LOG_ERROR(cmd)
|
||||||
os.execute(cmd)
|
os.execute(cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -248,57 +95,12 @@ handle.preview = function(path)
|
|||||||
end
|
end
|
||||||
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)
|
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
|
-- move file to unclassified
|
||||||
local newfile = docpath.."/unclassified/"..std.basename(param.file)
|
local newfile = docpath.."/unclassified/"..utils.basename(param.file)
|
||||||
vfs.move(param.file, newfile)
|
vfs.move(param.file, newfile)
|
||||||
-- delete thumb file
|
-- delete thumb file
|
||||||
local thumb = docpath.."/cache/"..std.sha1(param.file:gsub(docpath,""))..".png"
|
local thumb = docpath.."/cache/"..enc.sha1(param.file:gsub(docpath,""))..".png"
|
||||||
if vfs.exists(thumb) then
|
if vfs.exists(thumb) then
|
||||||
vfs.delete(thumb)
|
vfs.delete(thumb)
|
||||||
end
|
end
|
||||||
@ -306,20 +108,20 @@ handle.deletedoc = function(param)
|
|||||||
end
|
end
|
||||||
|
|
||||||
handle.updatedoc = function(param)
|
handle.updatedoc = function(param)
|
||||||
local r = merge_files(param.data)
|
local r = handle.merge_files(param.data)
|
||||||
if r.error then return r end
|
if r.error then return r end
|
||||||
|
|
||||||
if param.rm then
|
if param.rm then
|
||||||
-- move ve the old file to unclassified
|
-- move ve the old file to unclassified
|
||||||
local newfile = docpath.."/unclassified/"..std.basename(param.rm)
|
local newfile = docpath.."/unclassified/"..utils.basename(param.rm)
|
||||||
local cmd = "rm -f "..vfs.ospath(param.rm)
|
local cmd = "rm -f "..vfs.ospath(param.rm)
|
||||||
os.execute(cmd)
|
os.execute(cmd)
|
||||||
--if vfs.exists(param.rm) then
|
--if vfs.exists(param.rm) then
|
||||||
-- vfs.move(param.rm, newfile)
|
-- vfs.move(param.rm, newfile)
|
||||||
--end
|
--end
|
||||||
-- move the thumb file if needed
|
-- move the thumb file if needed
|
||||||
local thumb = docpath.."/cache/"..std.sha1(param.rm:gsub(docpath,""))..".png"
|
local thumb = docpath.."/cache/"..enc.sha1(param.rm:gsub(docpath,""))..".png"
|
||||||
local newwthumb = docpath.."/cache/"..std.sha1(newfile:gsub(docpath, ""))..".png"
|
local newwthumb = docpath.."/cache/"..enc.sha1(newfile:gsub(docpath, ""))..".png"
|
||||||
if vfs.exists(thumb) then
|
if vfs.exists(thumb) then
|
||||||
vfs.move(thumb, newwthumb)
|
vfs.move(thumb, newwthumb)
|
||||||
end
|
end
|
||||||
@ -327,107 +129,16 @@ handle.updatedoc = function(param)
|
|||||||
param.data.file = r.result
|
param.data.file = r.result
|
||||||
print(r.result)
|
print(r.result)
|
||||||
param.data.mtime = os.time(os.date("!*t"))
|
param.data.mtime = os.time(os.date("!*t"))
|
||||||
return handle.update({
|
return result(param.data)
|
||||||
table = "docs",
|
--return handle.update({
|
||||||
data = param.data
|
-- table = "docs",
|
||||||
})
|
-- data = param.data
|
||||||
|
--})
|
||||||
end
|
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
|
if arg.action and handle[arg.action] then
|
||||||
-- check if the database exits
|
-- check if the database exits
|
||||||
docpath = arg.docpath
|
docpath = arg.docpath
|
||||||
dbpath = docpath.."/docify.db"
|
|
||||||
|
|
||||||
return handle[arg.action](arg.args)
|
return handle[arg.action](arg.args)
|
||||||
else
|
else
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
<div style="text-align: right;" data-height="35" >
|
<div style="text-align: right;" data-height="35" >
|
||||||
<afx-button text="" iconclass="bi bi-arrow-up-right-square" data-id="btopen" ></afx-button>
|
<afx-button text="" iconclass="bi bi-arrow-up-right-square" data-id="btopen" ></afx-button>
|
||||||
<afx-button text="" iconclass="bi bi-cloud-arrow-down" data-id="btdld" ></afx-button>
|
<afx-button text="" iconclass="bi bi-cloud-arrow-down" data-id="btdld" ></afx-button>
|
||||||
<afx-button text="" iconclass = "bi bi-printer" data-id="btprint" ></afx-button>
|
|
||||||
</div>
|
</div>
|
||||||
</afx-vbox>
|
</afx-vbox>
|
||||||
</afx-hbox>
|
</afx-hbox>
|
||||||
|
@ -13,17 +13,35 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"coffee": {
|
"locale": {
|
||||||
|
"require": ["locale"],
|
||||||
|
"jobs": [
|
||||||
|
{
|
||||||
|
"name":"locale-gen",
|
||||||
|
"data": {
|
||||||
|
"src": "",
|
||||||
|
"exclude": ["build/", "api/", "css/", "coffees/"],
|
||||||
|
"locale": "en_GB",
|
||||||
|
"dest": "package.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ts": {
|
||||||
"require": [
|
"require": [
|
||||||
"coffee"
|
"ts"
|
||||||
],
|
],
|
||||||
"jobs": [
|
"jobs": [
|
||||||
{
|
{
|
||||||
"name": "coffee-compile",
|
"name": "ts-import",
|
||||||
|
"data": ["sdk://core/ts/core.d.ts", "sdk://core/ts/jquery.d.ts","sdk://core/ts/antos.d.ts"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ts-compile",
|
||||||
"data": {
|
"data": {
|
||||||
"src": [
|
"src": [
|
||||||
"coffees/dialogs.coffee",
|
"ts/dialogs.ts",
|
||||||
"coffees/main.coffee"
|
"ts/main.ts"
|
||||||
],
|
],
|
||||||
"dest": "build/debug/main.js"
|
"dest": "build/debug/main.js"
|
||||||
}
|
}
|
||||||
@ -65,7 +83,7 @@
|
|||||||
],
|
],
|
||||||
"depend": [
|
"depend": [
|
||||||
"init",
|
"init",
|
||||||
"coffee",
|
"ts",
|
||||||
"uglify",
|
"uglify",
|
||||||
"copy"
|
"copy"
|
||||||
],
|
],
|
||||||
@ -78,6 +96,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"debug": {
|
||||||
|
"depend": [
|
||||||
|
"init",
|
||||||
|
"ts",
|
||||||
|
"copy"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@
|
|||||||
Simple PDF document manager
|
Simple PDF document manager
|
||||||
|
|
||||||
## Change logs
|
## Change logs
|
||||||
|
- v0.1.0-b: use libsqlite for database handling
|
||||||
- v0.0.9-b: Adapt to support AntOS 2.0.x
|
- v0.0.9-b: Adapt to support AntOS 2.0.x
|
||||||
- v0.0.8-b: Allow upload files directly from the app
|
- v0.0.8-b: Allow upload files directly from the app
|
||||||
- v0.0.7-a: Change category and icon
|
- v0.0.7-a: Change category and icon
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
local arg = ...
|
local arg = ...
|
||||||
|
|
||||||
ulib = require("ulib")
|
ulib = require("ulib")
|
||||||
sqlite = modules.sqlite()
|
|
||||||
vfs = require("vfs")
|
vfs = require("vfs")
|
||||||
|
|
||||||
local handle = {}
|
local handle = {}
|
||||||
local docpath = nil
|
local docpath = nil
|
||||||
local dbpath = nil
|
|
||||||
|
|
||||||
local result = function(data)
|
local result = function(data)
|
||||||
return {
|
return {
|
||||||
@ -31,7 +29,7 @@ local mkdirp =function(p)
|
|||||||
return true, nil
|
return true, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local merge_files = function(data)
|
handle.merge_files = function(data)
|
||||||
local firstfile = data.file[1]
|
local firstfile = data.file[1]
|
||||||
local fpath = docpath.."/"..data.cid
|
local fpath = docpath.."/"..data.cid
|
||||||
local r, e = mkdirp(fpath)
|
local r, e = mkdirp(fpath)
|
||||||
@ -57,14 +55,14 @@ local merge_files = function(data)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- move the thumb file to the cache folder
|
-- move the thumb file to the cache folder
|
||||||
local thumb = docpath.."/cache/"..std.sha1(firstfile:gsub(docpath, ""))..".png"
|
local thumb = docpath.."/cache/"..enc.sha1(firstfile:gsub(docpath, ""))..".png"
|
||||||
local desthumb = docpath.."/cache/"..std.sha1(fpath:gsub(docpath, ""))..".png"
|
local desthumb = docpath.."/cache/"..enc.sha1(fpath:gsub(docpath, ""))..".png"
|
||||||
if vfs.exists(thumb) then
|
if vfs.exists(thumb) then
|
||||||
vfs.move(thumb, desthumb)
|
vfs.move(thumb, desthumb)
|
||||||
end
|
end
|
||||||
-- remove all other thumb files
|
-- remove all other thumb files
|
||||||
for i,v in ipairs(data.file) do
|
for i,v in ipairs(data.file) do
|
||||||
thumb = docpath.."/cache/"..std.sha1(v:gsub(docpath, ""))..".png"
|
thumb = docpath.."/cache/"..enc.sha1(v:gsub(docpath, ""))..".png"
|
||||||
if vfs.exists(thumb) then
|
if vfs.exists(thumb) then
|
||||||
vfs.delete(thumb)
|
vfs.delete(thumb)
|
||||||
end
|
end
|
||||||
@ -76,166 +74,15 @@ local merge_files = function(data)
|
|||||||
return result(fpath)
|
return result(fpath)
|
||||||
end
|
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)
|
handle.preview = function(path)
|
||||||
-- convert -resize 300x500 noel.pdf[0] thumb.png
|
-- convert -resize 300x500 noel.pdf[0] thumb.png
|
||||||
local name = std.sha1(path:gsub(docpath,""))..".png"
|
local name = enc.sha1(path:gsub(docpath,""))..".png"
|
||||||
-- try to find the thumb
|
-- try to find the thumb
|
||||||
local tpath = docpath.."/cache/"..name
|
local tpath = docpath.."/cache/"..name
|
||||||
if not vfs.exists(tpath) then
|
if not vfs.exists(tpath) then
|
||||||
-- regenerate thumb
|
-- regenerate thumb
|
||||||
local cmd = "convert -resize 250x500 \""..vfs.ospath(path).."\"[0] "..vfs.ospath(tpath)
|
local cmd = "convert -resize 250x500 \""..vfs.ospath(path).."\"[0] "..vfs.ospath(tpath)
|
||||||
|
LOG_ERROR(cmd)
|
||||||
os.execute(cmd)
|
os.execute(cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -248,57 +95,12 @@ handle.preview = function(path)
|
|||||||
end
|
end
|
||||||
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)
|
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
|
-- move file to unclassified
|
||||||
local newfile = docpath.."/unclassified/"..std.basename(param.file)
|
local newfile = docpath.."/unclassified/"..utils.basename(param.file)
|
||||||
vfs.move(param.file, newfile)
|
vfs.move(param.file, newfile)
|
||||||
-- delete thumb file
|
-- delete thumb file
|
||||||
local thumb = docpath.."/cache/"..std.sha1(param.file:gsub(docpath,""))..".png"
|
local thumb = docpath.."/cache/"..enc.sha1(param.file:gsub(docpath,""))..".png"
|
||||||
if vfs.exists(thumb) then
|
if vfs.exists(thumb) then
|
||||||
vfs.delete(thumb)
|
vfs.delete(thumb)
|
||||||
end
|
end
|
||||||
@ -306,20 +108,20 @@ handle.deletedoc = function(param)
|
|||||||
end
|
end
|
||||||
|
|
||||||
handle.updatedoc = function(param)
|
handle.updatedoc = function(param)
|
||||||
local r = merge_files(param.data)
|
local r = handle.merge_files(param.data)
|
||||||
if r.error then return r end
|
if r.error then return r end
|
||||||
|
|
||||||
if param.rm then
|
if param.rm then
|
||||||
-- move ve the old file to unclassified
|
-- move ve the old file to unclassified
|
||||||
local newfile = docpath.."/unclassified/"..std.basename(param.rm)
|
local newfile = docpath.."/unclassified/"..utils.basename(param.rm)
|
||||||
local cmd = "rm -f "..vfs.ospath(param.rm)
|
local cmd = "rm -f "..vfs.ospath(param.rm)
|
||||||
os.execute(cmd)
|
os.execute(cmd)
|
||||||
--if vfs.exists(param.rm) then
|
--if vfs.exists(param.rm) then
|
||||||
-- vfs.move(param.rm, newfile)
|
-- vfs.move(param.rm, newfile)
|
||||||
--end
|
--end
|
||||||
-- move the thumb file if needed
|
-- move the thumb file if needed
|
||||||
local thumb = docpath.."/cache/"..std.sha1(param.rm:gsub(docpath,""))..".png"
|
local thumb = docpath.."/cache/"..enc.sha1(param.rm:gsub(docpath,""))..".png"
|
||||||
local newwthumb = docpath.."/cache/"..std.sha1(newfile:gsub(docpath, ""))..".png"
|
local newwthumb = docpath.."/cache/"..enc.sha1(newfile:gsub(docpath, ""))..".png"
|
||||||
if vfs.exists(thumb) then
|
if vfs.exists(thumb) then
|
||||||
vfs.move(thumb, newwthumb)
|
vfs.move(thumb, newwthumb)
|
||||||
end
|
end
|
||||||
@ -327,107 +129,16 @@ handle.updatedoc = function(param)
|
|||||||
param.data.file = r.result
|
param.data.file = r.result
|
||||||
print(r.result)
|
print(r.result)
|
||||||
param.data.mtime = os.time(os.date("!*t"))
|
param.data.mtime = os.time(os.date("!*t"))
|
||||||
return handle.update({
|
return result(param.data)
|
||||||
table = "docs",
|
--return handle.update({
|
||||||
data = param.data
|
-- table = "docs",
|
||||||
})
|
-- data = param.data
|
||||||
|
--})
|
||||||
end
|
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
|
if arg.action and handle[arg.action] then
|
||||||
-- check if the database exits
|
-- check if the database exits
|
||||||
docpath = arg.docpath
|
docpath = arg.docpath
|
||||||
dbpath = docpath.."/docify.db"
|
|
||||||
|
|
||||||
return handle[arg.action](arg.args)
|
return handle[arg.action](arg.args)
|
||||||
else
|
else
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,15 +1,68 @@
|
|||||||
{
|
{
|
||||||
"pkgname": "Docify",
|
"pkgname": "Docify",
|
||||||
"app":"Docify",
|
"app": "Docify",
|
||||||
"name":"Docify",
|
"name": "Docify",
|
||||||
"description":"Docify",
|
"description": "Simple document manager",
|
||||||
"info":{
|
"info": {
|
||||||
"author": "",
|
"author": "Dany LE",
|
||||||
"email": ""
|
"email": "mrsang@iohub.dev"
|
||||||
},
|
},
|
||||||
"version":"0.0.9-b",
|
"version": "0.1.0-b",
|
||||||
"category":"Office",
|
"category": "Office",
|
||||||
"iconclass":"bi bi-collection-fill",
|
"iconclass": "bi bi-collection-fill",
|
||||||
"mimes":["none"],
|
"mimes": [
|
||||||
"locale": {}
|
"none"
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
"SQLiteDB@0.1.0-a"
|
||||||
|
],
|
||||||
|
"locale": {},
|
||||||
|
"locales": {
|
||||||
|
"en_GB": {
|
||||||
|
"title": "title",
|
||||||
|
"Day": "Day",
|
||||||
|
"Month": "Month",
|
||||||
|
"Year": "Year",
|
||||||
|
"Files": "Files",
|
||||||
|
"Note": "Note",
|
||||||
|
"Owner": "Owner",
|
||||||
|
"Tags": "Tags",
|
||||||
|
"Save": "Save",
|
||||||
|
"Document preview": "Document preview",
|
||||||
|
"Ok": "Ok",
|
||||||
|
"Unable to get owner data handle": "Unable to get owner data handle",
|
||||||
|
"Name": "Name",
|
||||||
|
"Do you realy want to delete: `{0}`": "Do you realy want to delete: `{0}`",
|
||||||
|
"Unable to fetch owner list: {0}": "Unable to fetch owner list: {0}",
|
||||||
|
"Please enter title": "Please enter title",
|
||||||
|
"Please attach files to the entry": "Please attach files to the entry",
|
||||||
|
"Unable to fetch unclassified file list: {0}": "Unable to fetch unclassified file list: {0}",
|
||||||
|
"Options": "Options",
|
||||||
|
"Owners": "Owners",
|
||||||
|
"Preview": "Preview",
|
||||||
|
"Change doc path": "Change doc path",
|
||||||
|
"No configured docpath": "No configured docpath",
|
||||||
|
"Unable to init database file: {0}": "Unable to init database file: {0}",
|
||||||
|
"Unable to download: {0}": "Unable to download: {0}",
|
||||||
|
"Unable to open file: {0}": "Unable to open file: {0}",
|
||||||
|
"Category": "Category",
|
||||||
|
"Unable to insert category: {0}": "Unable to insert category: {0}",
|
||||||
|
"Unable delete category: {0}": "Unable delete category: {0}",
|
||||||
|
"Unable to update category: {0}": "Unable to update category: {0}",
|
||||||
|
"Unable to fetch document detail: {0}": "Unable to fetch document detail: {0}",
|
||||||
|
"Please select a category": "Please select a category",
|
||||||
|
"Unable to add document: {0}": "Unable to add document: {0}",
|
||||||
|
"Do you really want to delete: `{0}`": "Do you really want to delete: `{0}`",
|
||||||
|
"Unable to delete document: {0}": "Unable to delete document: {0}",
|
||||||
|
"File uploaded": "File uploaded",
|
||||||
|
"Unable to upload document: {0}": "Unable to upload document: {0}",
|
||||||
|
"Unable to edit document metadata: {0}": "Unable to edit document metadata: {0}",
|
||||||
|
"Unable to update document list: {0}": "Unable to update document list: {0}",
|
||||||
|
"Unable to generate document thumbnail: {0}": "Unable to generate document thumbnail: {0}",
|
||||||
|
"Please select a doc path": "Please select a doc path",
|
||||||
|
"Error initialize database: {0}": "Error initialize database: {0}",
|
||||||
|
"Categories": "Categories",
|
||||||
|
"Documents": "Documents"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -25,7 +25,6 @@
|
|||||||
<div style="text-align: right;" data-height="35" >
|
<div style="text-align: right;" data-height="35" >
|
||||||
<afx-button text="" iconclass="bi bi-arrow-up-right-square" data-id="btopen" ></afx-button>
|
<afx-button text="" iconclass="bi bi-arrow-up-right-square" data-id="btopen" ></afx-button>
|
||||||
<afx-button text="" iconclass="bi bi-cloud-arrow-down" data-id="btdld" ></afx-button>
|
<afx-button text="" iconclass="bi bi-cloud-arrow-down" data-id="btdld" ></afx-button>
|
||||||
<afx-button text="" iconclass = "bi bi-printer" data-id="btprint" ></afx-button>
|
|
||||||
</div>
|
</div>
|
||||||
</afx-vbox>
|
</afx-vbox>
|
||||||
</afx-hbox>
|
</afx-hbox>
|
||||||
|
Binary file not shown.
@ -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 = """
|
|
||||||
<afx-app-window width='200' height='300'>
|
|
||||||
<afx-vbox>
|
|
||||||
<afx-list-view data-id="ownview"></afx-list-view>
|
|
||||||
</afx-vbox>
|
|
||||||
</afx-app-window>
|
|
||||||
"""
|
|
||||||
|
|
||||||
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 = """
|
|
||||||
<afx-app-window width='600' height='400'>
|
|
||||||
<afx-hbox>
|
|
||||||
<afx-vbox data-width="350">
|
|
||||||
<afx-hbox data-height="30">
|
|
||||||
<afx-label text = "__(title)" data-width="50"></afx-label>
|
|
||||||
<input type="text" data-id="title"></input>
|
|
||||||
</afx-hbox>
|
|
||||||
<afx-hbox data-height="30">
|
|
||||||
<afx-label text = "__(Day)" data-width="50"></afx-label>
|
|
||||||
<afx-list-view dropdown="true" data-id="dlist"></afx-list-view>
|
|
||||||
<afx-label text = "__(Month)"data-width="50" ></afx-label>
|
|
||||||
<afx-list-view dropdown="true" data-id="mlist"></afx-list-view>
|
|
||||||
<afx-label text = "__(Year)"data-width="50" ></afx-label>
|
|
||||||
<afx-list-view dropdown="true" data-id="ylist"></afx-list-view>
|
|
||||||
</afx-hbox>
|
|
||||||
<afx-label text = "__(Files)" data-height="22"></afx-label>
|
|
||||||
<afx-list-view data-id="file-list"></afx-list-view>
|
|
||||||
<afx-label text = "__(Note)" data-height="22"></afx-label>
|
|
||||||
<textarea data-id="note"></textarea>
|
|
||||||
<afx-hbox data-height = "30">
|
|
||||||
<afx-label text = "__(Owner)" data-width="50"></afx-label>
|
|
||||||
<afx-list-view dropdown="true" data-id="olist"></afx-list-view>
|
|
||||||
<afx-label text = "__(Tags)" data-width="50"></afx-label>
|
|
||||||
<input type="text" data-id="tag"></input>
|
|
||||||
</afx-hbox>
|
|
||||||
</afx-vbox>
|
|
||||||
<afx-vbox>
|
|
||||||
<div data-id = "preview-container">
|
|
||||||
<canvas data-id="preview-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
<div style="text-align: right;" data-height="35" >
|
|
||||||
<afx-button text="__(Save)" data-id="btsave" ></afx-button>
|
|
||||||
</div>
|
|
||||||
</afx-vbox>
|
|
||||||
</afx-hbox>
|
|
||||||
</afx-app-window>
|
|
||||||
"""
|
|
||||||
|
|
||||||
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 = """
|
|
||||||
<afx-app-window width='400' height='400' apptitle = "__(Document preview)">
|
|
||||||
<afx-hbox>
|
|
||||||
<afx-vbox data-width="150">
|
|
||||||
<afx-label text = "__(Files)" data-height="25"></afx-label>
|
|
||||||
<afx-list-view data-id="file-list"></afx-list-view>
|
|
||||||
</afx-vbox>
|
|
||||||
<afx-vbox>
|
|
||||||
<div data-id = "preview-container">
|
|
||||||
<canvas data-id="preview-canvas"></canvas>
|
|
||||||
</div>
|
|
||||||
<div style="text-align: right;" data-height="35" >
|
|
||||||
<afx-button text="__(Ok)" data-id="btok" ></afx-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</afx-vbox>
|
|
||||||
</afx-hbox>
|
|
||||||
</afx-app-window>
|
|
||||||
"""
|
|
||||||
|
|
||||||
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 = """
|
|
||||||
<afx-app-window width='300' height='300' data-id="DocifyPrintDialog" apptitle = "__(Print)">
|
|
||||||
<afx-vbox>
|
|
||||||
<afx-label text = "__(Printer name)" data-height="25"></afx-label>
|
|
||||||
<input type="text" data-id="printerName" data-height="25"></input>
|
|
||||||
<afx-label text = "__(Range)" data-height="22"></afx-label>
|
|
||||||
<div>
|
|
||||||
<input type="radio" name="range" value="0" checked ></input>
|
|
||||||
<label for="0">All</label><br>
|
|
||||||
<input type="radio" name="range" value="1" ></input>
|
|
||||||
<label for="1">Pages: </label>
|
|
||||||
<input type="text" data-id="txtPageRange" ></input>
|
|
||||||
</div>
|
|
||||||
<afx-label text = "__(Orientation)" data-height="25"></afx-label>
|
|
||||||
<div>
|
|
||||||
<input type="radio" name="orientation" value="0" checked ></input>
|
|
||||||
<label for="0">Portrait</label><br>
|
|
||||||
<input type="radio" name="orientation" value="1" ></input>
|
|
||||||
<label for="1">Landscape</label>
|
|
||||||
</div>
|
|
||||||
<afx-label text = "__(Side)" data-height="22"></afx-label>
|
|
||||||
<div>
|
|
||||||
<input type="radio" name="side" value="0" ></input>
|
|
||||||
<label for="0">One side</label><br>
|
|
||||||
<input type="radio" name="side" value="1" checked ></input>
|
|
||||||
<label for="1">Double side long edge</label><br>
|
|
||||||
<input type="radio" name="side" value="2" ></input>
|
|
||||||
<label for="2">Double side short edge</label>
|
|
||||||
</div>
|
|
||||||
<div data-height="35" style="text-align:right;">
|
|
||||||
<afx-button text="__(Print)" style="margin-right:5px;" data-id="btnprint"></afx-button>
|
|
||||||
</div>
|
|
||||||
</afx-vbox>
|
|
||||||
</afx-app-window>
|
|
||||||
"""
|
|
@ -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
|
|
@ -1,15 +1,68 @@
|
|||||||
{
|
{
|
||||||
"pkgname": "Docify",
|
"pkgname": "Docify",
|
||||||
"app":"Docify",
|
"app": "Docify",
|
||||||
"name":"Docify",
|
"name": "Docify",
|
||||||
"description":"Docify",
|
"description": "Simple document manager",
|
||||||
"info":{
|
"info": {
|
||||||
"author": "",
|
"author": "Dany LE",
|
||||||
"email": ""
|
"email": "mrsang@iohub.dev"
|
||||||
},
|
},
|
||||||
"version":"0.0.9-b",
|
"version": "0.1.0-b",
|
||||||
"category":"Office",
|
"category": "Office",
|
||||||
"iconclass":"bi bi-collection-fill",
|
"iconclass": "bi bi-collection-fill",
|
||||||
"mimes":["none"],
|
"mimes": [
|
||||||
"locale": {}
|
"none"
|
||||||
|
],
|
||||||
|
"dependencies": [
|
||||||
|
"SQLiteDB@0.1.0-a"
|
||||||
|
],
|
||||||
|
"locale": {},
|
||||||
|
"locales": {
|
||||||
|
"en_GB": {
|
||||||
|
"title": "title",
|
||||||
|
"Day": "Day",
|
||||||
|
"Month": "Month",
|
||||||
|
"Year": "Year",
|
||||||
|
"Files": "Files",
|
||||||
|
"Note": "Note",
|
||||||
|
"Owner": "Owner",
|
||||||
|
"Tags": "Tags",
|
||||||
|
"Save": "Save",
|
||||||
|
"Document preview": "Document preview",
|
||||||
|
"Ok": "Ok",
|
||||||
|
"Unable to get owner data handle": "Unable to get owner data handle",
|
||||||
|
"Name": "Name",
|
||||||
|
"Do you realy want to delete: `{0}`": "Do you realy want to delete: `{0}`",
|
||||||
|
"Unable to fetch owner list: {0}": "Unable to fetch owner list: {0}",
|
||||||
|
"Please enter title": "Please enter title",
|
||||||
|
"Please attach files to the entry": "Please attach files to the entry",
|
||||||
|
"Unable to fetch unclassified file list: {0}": "Unable to fetch unclassified file list: {0}",
|
||||||
|
"Options": "Options",
|
||||||
|
"Owners": "Owners",
|
||||||
|
"Preview": "Preview",
|
||||||
|
"Change doc path": "Change doc path",
|
||||||
|
"No configured docpath": "No configured docpath",
|
||||||
|
"Unable to init database file: {0}": "Unable to init database file: {0}",
|
||||||
|
"Unable to download: {0}": "Unable to download: {0}",
|
||||||
|
"Unable to open file: {0}": "Unable to open file: {0}",
|
||||||
|
"Category": "Category",
|
||||||
|
"Unable to insert category: {0}": "Unable to insert category: {0}",
|
||||||
|
"Unable delete category: {0}": "Unable delete category: {0}",
|
||||||
|
"Unable to update category: {0}": "Unable to update category: {0}",
|
||||||
|
"Unable to fetch document detail: {0}": "Unable to fetch document detail: {0}",
|
||||||
|
"Please select a category": "Please select a category",
|
||||||
|
"Unable to add document: {0}": "Unable to add document: {0}",
|
||||||
|
"Do you really want to delete: `{0}`": "Do you really want to delete: `{0}`",
|
||||||
|
"Unable to delete document: {0}": "Unable to delete document: {0}",
|
||||||
|
"File uploaded": "File uploaded",
|
||||||
|
"Unable to upload document: {0}": "Unable to upload document: {0}",
|
||||||
|
"Unable to edit document metadata: {0}": "Unable to edit document metadata: {0}",
|
||||||
|
"Unable to update document list: {0}": "Unable to update document list: {0}",
|
||||||
|
"Unable to generate document thumbnail: {0}": "Unable to generate document thumbnail: {0}",
|
||||||
|
"Please select a doc path": "Please select a doc path",
|
||||||
|
"Error initialize database: {0}": "Error initialize database: {0}",
|
||||||
|
"Categories": "Categories",
|
||||||
|
"Documents": "Documents"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -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"]
|
|
||||||
}
|
|
354
Docify/ts/dialogs.ts
Normal file
354
Docify/ts/dialogs.ts
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
namespace OS {
|
||||||
|
export namespace application {
|
||||||
|
export namespace docify {
|
||||||
|
export class OwnerDialog extends OS.GUI.BasicDialog {
|
||||||
|
private oview: GUI.tag.ListViewTag;
|
||||||
|
constructor() {
|
||||||
|
super("OwnerDialog", OwnerDialog.scheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
super.main();
|
||||||
|
this.oview = this.find("ownview") as GUI.tag.ListViewTag;
|
||||||
|
if(!this.data.dbhandle)
|
||||||
|
{
|
||||||
|
throw new Error(__("Unable to get owner data handle").__());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oview.buttons = [
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-plus-circle",
|
||||||
|
onbtclick: async (e: any) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const d = await this.openDialog("PromptDialog", {
|
||||||
|
title: __("Owner"),
|
||||||
|
label: __("Name")
|
||||||
|
});
|
||||||
|
this.data.dbhandle.cache = { name: d };
|
||||||
|
const r = await this.data.dbhandle.write(undefined);
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error);
|
||||||
|
}
|
||||||
|
await this.owner_refresh();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-minus-circle",
|
||||||
|
onbtclick: async (e: any) => {
|
||||||
|
try{
|
||||||
|
const item = this.oview.selectedItem;
|
||||||
|
if (!item) { return; }
|
||||||
|
let d = await this.ask({ text:__("Do you realy want to delete: `{0}`", item.data.text)});
|
||||||
|
if (!d) { return; }
|
||||||
|
const handle = item.data.$vfs as API.VFS.BaseFileHandle;
|
||||||
|
let r = await handle.remove();
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error.toString());
|
||||||
|
}
|
||||||
|
await this.owner_refresh();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-pencil-square-o",
|
||||||
|
onbtclick: async (e: any) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const item = this.oview.selectedItem;
|
||||||
|
if (!item) { return; }
|
||||||
|
const d = await this.openDialog("PromptDialog", {
|
||||||
|
title: __("Owner"),
|
||||||
|
label: __("Name"),
|
||||||
|
value: item.data.name
|
||||||
|
});
|
||||||
|
const handle = item.data.$vfs as API.VFS.BaseFileHandle;
|
||||||
|
handle.cache = { name: d };
|
||||||
|
const r = await handle.write(undefined);
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error.toString());
|
||||||
|
}
|
||||||
|
await this.owner_refresh();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return this.owner_refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async owner_refresh() {
|
||||||
|
|
||||||
|
const d = await this.data.dbhandle.read();
|
||||||
|
for (let v of d) { v.text = v.name; }
|
||||||
|
this.oview.data = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OwnerDialog.scheme = `\
|
||||||
|
<afx-app-window width='200' height='300'>
|
||||||
|
<afx-vbox>
|
||||||
|
<afx-list-view data-id="ownview"></afx-list-view>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-app-window>\
|
||||||
|
`;
|
||||||
|
|
||||||
|
export class DocDialog extends OS.GUI.BasicDialog {
|
||||||
|
private flist: GUI.tag.ListViewTag;
|
||||||
|
private dlist: GUI.tag.ListViewTag;
|
||||||
|
private mlist: GUI.tag.ListViewTag;
|
||||||
|
private ylist: GUI.tag.ListViewTag;
|
||||||
|
private olist: GUI.tag.ListViewTag;
|
||||||
|
constructor() {
|
||||||
|
super("DocDialog", DocDialog.scheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
let d: number;
|
||||||
|
super.main();
|
||||||
|
this.flist = this.find("file-list") as GUI.tag.ListViewTag;
|
||||||
|
this.dlist = this.find("dlist") as GUI.tag.ListViewTag;
|
||||||
|
this.mlist = this.find("mlist") as GUI.tag.ListViewTag;
|
||||||
|
this.ylist = this.find("ylist") as GUI.tag.ListViewTag;
|
||||||
|
this.olist = this.find("olist") as GUI.tag.ListViewTag;
|
||||||
|
const app = this.parent as Docify;
|
||||||
|
const target=app.setting.docpath.asFileHandle();
|
||||||
|
const dbhandle=`sqlite://${target.genealogy.join("/")}/docify.db@owners`.asFileHandle();
|
||||||
|
dbhandle.read()
|
||||||
|
.then((d) => {
|
||||||
|
if (d.error) { return this.error(d.error); }
|
||||||
|
for (let v of d) {
|
||||||
|
v.text = v.name;
|
||||||
|
v.selected = this.data && (this.data.oid === v.id);
|
||||||
|
}
|
||||||
|
this.olist.data = d;
|
||||||
|
if (!this.olist.selectedItem) { return this.olist.selected = 0; }
|
||||||
|
}).catch((e) => {
|
||||||
|
return this.error(__("Unable to fetch owner list: {0}", e.toString()), e);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dlist.push({
|
||||||
|
text:"None",
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
let selected = 0;
|
||||||
|
for (d = 1; d <= 31; d++) {
|
||||||
|
this.dlist.push({
|
||||||
|
text:`${d}`,
|
||||||
|
value: d
|
||||||
|
});
|
||||||
|
if (this.data && (parseInt(this.data.day) === d)) { selected = d; }
|
||||||
|
}
|
||||||
|
this.dlist.selected = selected;
|
||||||
|
|
||||||
|
this.mlist.push({
|
||||||
|
text:"None",
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
selected = 0;
|
||||||
|
for (d = 1; d <= 12; d++) {
|
||||||
|
this.mlist.push({
|
||||||
|
text:`${d}`,
|
||||||
|
value: d
|
||||||
|
});
|
||||||
|
if (this.data && (parseInt(this.data.month) === d)) { selected = d; }
|
||||||
|
}
|
||||||
|
this.mlist.selected = selected;
|
||||||
|
|
||||||
|
this.ylist.push({
|
||||||
|
text:"None",
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
this.ylist.selected = 0;
|
||||||
|
for (let y = 1960, end = new Date().getFullYear(), asc = 1960 <= end; asc ? y <= end : y >= end; asc ? y++ : y--) {
|
||||||
|
this.ylist.push({
|
||||||
|
text:`${y}`,
|
||||||
|
value: y,
|
||||||
|
selected: this.data && (parseInt(this.data.year) === y)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.flist.buttons = [
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-plus-circle",
|
||||||
|
onbtclick: (e: any) => {
|
||||||
|
return this.openDialog(new FilePreviewDialog(), {
|
||||||
|
app: app
|
||||||
|
})
|
||||||
|
.then((d: { text: any; filename: any; }) => {
|
||||||
|
d.text = d.filename;
|
||||||
|
return this.flist.push(d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-minus-circle",
|
||||||
|
onbtclick: (e: any) => {
|
||||||
|
const item = this.flist.selectedItem;
|
||||||
|
if (!item) { return; }
|
||||||
|
return this.flist.delete(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
this.flist.onlistselect = async (e) => {
|
||||||
|
return await app.preview(e.data.item.data.path, this.find("preview-canvas") as HTMLCanvasElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
(this.find("btsave") as GUI.tag.ButtonTag).onbtclick = (e: any) => {
|
||||||
|
const data: GenericObject<any> = {
|
||||||
|
name: (this.find("title") as HTMLInputElement).value.trim(),
|
||||||
|
day: this.dlist.selectedItem.data.value,
|
||||||
|
month: this.mlist.selectedItem.data.value,
|
||||||
|
year: this.ylist.selectedItem.data.value,
|
||||||
|
file: (Array.from(this.flist.data).map((v: { path: any; }) => v.path)),
|
||||||
|
note: (this.find("note") as HTMLTextAreaElement).value.trim(),
|
||||||
|
tags: (this.find("tag") as HTMLInputElement).value.trim(),
|
||||||
|
oid: parseInt(this.olist.selectedItem.data.id)
|
||||||
|
};
|
||||||
|
if (!data.name || (data.title === "")) { return this.notify(__("Please enter title")); }
|
||||||
|
if (!(data.file.length > 0)) { return this.notify(__("Please attach files to the entry")); }
|
||||||
|
|
||||||
|
if (this.handle) { this.handle(data); }
|
||||||
|
return this.quit();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!this.data) { return; }
|
||||||
|
(this.find("title") as HTMLInputElement).value = this.data.name;
|
||||||
|
(this.find("note") as HTMLTextAreaElement).value = this.data.note;
|
||||||
|
(this.find("tag") as HTMLInputElement).value = this.data.tags;
|
||||||
|
const file = this.data.file.asFileHandle();
|
||||||
|
file.text = file.filename;
|
||||||
|
return this.flist.data = [ file ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DocDialog.scheme = `\
|
||||||
|
<afx-app-window width='600' height='400'>
|
||||||
|
<afx-hbox>
|
||||||
|
<afx-vbox data-width="350">
|
||||||
|
<afx-hbox data-height="30">
|
||||||
|
<afx-label text = "__(title)" data-width="50"></afx-label>
|
||||||
|
<input type="text" data-id="title"></input>
|
||||||
|
</afx-hbox>
|
||||||
|
<afx-hbox data-height="30">
|
||||||
|
<afx-label text = "__(Day)" data-width="50"></afx-label>
|
||||||
|
<afx-list-view dropdown="true" data-id="dlist"></afx-list-view>
|
||||||
|
<afx-label text = "__(Month)"data-width="50" ></afx-label>
|
||||||
|
<afx-list-view dropdown="true" data-id="mlist"></afx-list-view>
|
||||||
|
<afx-label text = "__(Year)"data-width="50" ></afx-label>
|
||||||
|
<afx-list-view dropdown="true" data-id="ylist"></afx-list-view>
|
||||||
|
</afx-hbox>
|
||||||
|
<afx-label text = "__(Files)" data-height="22"></afx-label>
|
||||||
|
<afx-list-view data-id="file-list"></afx-list-view>
|
||||||
|
<afx-label text = "__(Note)" data-height="22"></afx-label>
|
||||||
|
<textarea data-id="note"></textarea>
|
||||||
|
<afx-hbox data-height = "30">
|
||||||
|
<afx-label text = "__(Owner)" data-width="50"></afx-label>
|
||||||
|
<afx-list-view dropdown="true" data-id="olist"></afx-list-view>
|
||||||
|
<afx-label text = "__(Tags)" data-width="50"></afx-label>
|
||||||
|
<input type="text" data-id="tag"></input>
|
||||||
|
</afx-hbox>
|
||||||
|
</afx-vbox>
|
||||||
|
<afx-vbox>
|
||||||
|
<div data-id = "preview-container">
|
||||||
|
<canvas data-id="preview-canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right;" data-height="35" >
|
||||||
|
<afx-button text="__(Save)" data-id="btsave" ></afx-button>
|
||||||
|
</div>
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-hbox>
|
||||||
|
</afx-app-window>\
|
||||||
|
`;
|
||||||
|
|
||||||
|
export class FilePreviewDialog extends OS.GUI.BasicDialog {
|
||||||
|
private flist: GUI.tag.ListViewTag;
|
||||||
|
constructor() {
|
||||||
|
super("FilePreviewDialog", FilePreviewDialog.scheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
super.main();
|
||||||
|
this.flist = this.find("file-list") as GUI.tag.ListViewTag;
|
||||||
|
this.flist.buttons = [
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-refresh",
|
||||||
|
onbtclick: (e: any) => this.refresh()
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const app = this.data.app as Docify;
|
||||||
|
|
||||||
|
this.flist.onlistselect = async (e) => {
|
||||||
|
// console.log e.data.item.data
|
||||||
|
return await app.preview(e.data.item.data.path, this.find("preview-canvas") as HTMLCanvasElement);
|
||||||
|
};
|
||||||
|
(this.find("btok") as GUI.tag.ButtonTag).onbtclick = (e: any) => {
|
||||||
|
const item = this.flist.selectedItem;
|
||||||
|
if (!item) { return this.quit(); }
|
||||||
|
if (this.handle) { this.handle(item.data); }
|
||||||
|
return this.quit();
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
async refresh() {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const app = this.data.app as Docify;
|
||||||
|
const d = await `${app.setting.docpath}/unclassified`.asFileHandle().read();
|
||||||
|
if (d.error) { return this.error(d.error); }
|
||||||
|
for (let v of d.result) { v.text = v.filename; }
|
||||||
|
return this.flist.data = d.result.filter((e) => e.filename[0] !== '.');
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
return this.error(__("Unable to fetch unclassified file list: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePreviewDialog.scheme = `\
|
||||||
|
<afx-app-window width='400' height='400' apptitle = "__(Document preview)">
|
||||||
|
<afx-hbox>
|
||||||
|
<afx-vbox data-width="150">
|
||||||
|
<afx-label text = "__(Files)" data-height="25"></afx-label>
|
||||||
|
<afx-list-view data-id="file-list"></afx-list-view>
|
||||||
|
</afx-vbox>
|
||||||
|
<afx-vbox>
|
||||||
|
<div data-id = "preview-container">
|
||||||
|
<canvas data-id="preview-canvas"></canvas>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right;" data-height="35" >
|
||||||
|
<afx-button text="__(Ok)" data-id="btok" ></afx-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</afx-vbox>
|
||||||
|
</afx-hbox>
|
||||||
|
</afx-app-window>\
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
543
Docify/ts/main.ts
Normal file
543
Docify/ts/main.ts
Normal file
@ -0,0 +1,543 @@
|
|||||||
|
namespace OS {
|
||||||
|
export namespace application {
|
||||||
|
|
||||||
|
export class Docify extends BaseApplication {
|
||||||
|
private catview: GUI.tag.ListViewTag;
|
||||||
|
private docview: GUI.tag.ListViewTag;
|
||||||
|
private docpreview: HTMLCanvasElement;
|
||||||
|
private docgrid: GUI.tag.GridViewTag;
|
||||||
|
|
||||||
|
private dbhandle: API.VFS.BaseFileHandle;
|
||||||
|
private catdb: API.VFS.BaseFileHandle;
|
||||||
|
private ownerdb: API.VFS.BaseFileHandle;
|
||||||
|
private docdb: API.VFS.BaseFileHandle;
|
||||||
|
|
||||||
|
constructor( args: any ) {
|
||||||
|
super("Docify", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async init_db() {
|
||||||
|
try {
|
||||||
|
if (!this.setting.docpath) { return this.error(__("No configured docpath")); }
|
||||||
|
|
||||||
|
const target=this.setting.docpath.asFileHandle();
|
||||||
|
this.dbhandle=`sqlite://${target.genealogy.join("/")}/docify.db`.asFileHandle();
|
||||||
|
const tables = await this.dbhandle.read();
|
||||||
|
/**
|
||||||
|
* Init following tables if not exist:
|
||||||
|
* - categories
|
||||||
|
* - owners
|
||||||
|
* - docs
|
||||||
|
*/
|
||||||
|
await `${this.setting.docpath}`.asFileHandle().mk("unclassified");
|
||||||
|
await `${this.setting.docpath}`.asFileHandle().mk("cache");
|
||||||
|
let r = undefined;
|
||||||
|
this.catdb = `${this.dbhandle.path}@categories`.asFileHandle();
|
||||||
|
if(!tables.categories)
|
||||||
|
{
|
||||||
|
this.dbhandle.cache = {
|
||||||
|
name: "TEXT"
|
||||||
|
}
|
||||||
|
r = await this.dbhandle.write("categories");
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error as string);
|
||||||
|
}
|
||||||
|
this.catdb.cache = {
|
||||||
|
name: "Uncategoried"
|
||||||
|
};
|
||||||
|
r = await this.catdb.write(undefined);
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.ownerdb = `${this.dbhandle.path}@owners`.asFileHandle();
|
||||||
|
if(!tables.owners)
|
||||||
|
{
|
||||||
|
this.dbhandle.cache = {
|
||||||
|
name: "TEXT",
|
||||||
|
}
|
||||||
|
r = await this.dbhandle.write("owners");
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error as string);
|
||||||
|
}
|
||||||
|
this.ownerdb.cache = {
|
||||||
|
name: "None"
|
||||||
|
};
|
||||||
|
r = await this.ownerdb.write(undefined);
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.docdb = `${this.dbhandle.path}@docs`.asFileHandle();
|
||||||
|
if(!tables.docs)
|
||||||
|
{
|
||||||
|
this.dbhandle.cache = {
|
||||||
|
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',
|
||||||
|
}
|
||||||
|
r = await this.dbhandle.write("docs");
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return await this.cat_refresh();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
this.error(__("Unable to init database file: {0}",e.toString()),e);
|
||||||
|
this.dbhandle = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
|
||||||
|
if (!this.setting.printer) { this.setting.printer = ""; }
|
||||||
|
|
||||||
|
this.catview = this.find("catview") as GUI.tag.ListViewTag;
|
||||||
|
this.docview = this.find("docview") as GUI.tag.ListViewTag;
|
||||||
|
this.docpreview = this.find("preview-canvas") as HTMLCanvasElement;
|
||||||
|
this.docgrid = this.find("docgrid") as GUI.tag.GridViewTag;
|
||||||
|
this.docgrid.header = [
|
||||||
|
{ text: "", width: 100 },
|
||||||
|
{ text: "" },
|
||||||
|
];
|
||||||
|
(this.find("btdld") as GUI.tag.ButtonTag).onbtclick = async (e) => {
|
||||||
|
try {
|
||||||
|
const item = this.docview.selectedItem;
|
||||||
|
if (!item) { return; }
|
||||||
|
await item.data.file.asFileHandle().download();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to download: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(this.find("btopen") as GUI.tag.ButtonTag).onbtclick = async (e) => {
|
||||||
|
try {
|
||||||
|
const item = this.docview.selectedItem;
|
||||||
|
if (!item) { return; }
|
||||||
|
const m = await item.data.file.asFileHandle().meta();
|
||||||
|
if (m.error)
|
||||||
|
{
|
||||||
|
throw new Error(m.error);
|
||||||
|
}
|
||||||
|
return this._gui.openWith(m.result);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to open file: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.catview.buttons = [
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-plus-circle",
|
||||||
|
onbtclick:async (e) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const d = await this.openDialog("PromptDialog", {
|
||||||
|
title: __("Category"),
|
||||||
|
label: __("Name")
|
||||||
|
});
|
||||||
|
this.catdb.cache = { name: d };
|
||||||
|
const r = await this.catdb.write(undefined);
|
||||||
|
if (r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error.toString());
|
||||||
|
}
|
||||||
|
return await this.cat_refresh();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to insert category: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-minus-circle",
|
||||||
|
onbtclick: async (e) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const item = this.catview.selectedItem;
|
||||||
|
if (!item) { return; }
|
||||||
|
const d = await this.ask({ text:__("Do you realy want to delete: `{0}`", item.data.text)});
|
||||||
|
if (!d) { return; }
|
||||||
|
|
||||||
|
const r = await this.catdb.remove({
|
||||||
|
where: {
|
||||||
|
id: item.data.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error.toString());
|
||||||
|
}
|
||||||
|
await this.cat_refresh();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable delete category: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "",
|
||||||
|
iconclass: "fa fa-pencil-square-o",
|
||||||
|
onbtclick: async (_) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const item = this.catview.selectedItem;
|
||||||
|
if (!item) { return; };
|
||||||
|
const cat = item.data;
|
||||||
|
if (!cat) { return; }
|
||||||
|
const d = await this.openDialog("PromptDialog", {
|
||||||
|
title: __("Category"),
|
||||||
|
label: __("Name"),
|
||||||
|
value: item.data.name
|
||||||
|
});
|
||||||
|
const handle: API.VFS.BaseFileHandle = cat.$vfs;
|
||||||
|
handle.cache = { id: parseInt(item.data.id), name: d };
|
||||||
|
const r = await handle.write(undefined);
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error.toString());
|
||||||
|
}
|
||||||
|
await this.cat_refresh();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to update category: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
this.docview.onlistselect = async (evt) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.clear_preview();
|
||||||
|
const item = evt.data.item;
|
||||||
|
if(!item) return;
|
||||||
|
const handle = item.data.$vfs as API.VFS.BaseFileHandle;
|
||||||
|
// TODO join owner here
|
||||||
|
const d = await handle.read();
|
||||||
|
await this.preview(d.file, this.docpreview);
|
||||||
|
const rows = [];
|
||||||
|
// TODO: if (d.result.fileinfo) { d.result.size = (d.result.fileinfo.size / 1024.0).toFixed(2) + " Kb"; }
|
||||||
|
const map = {
|
||||||
|
ctime: "Created on",
|
||||||
|
mtime: "Modified on",
|
||||||
|
note: "Note",
|
||||||
|
tags: "Tags",
|
||||||
|
name: "Title",
|
||||||
|
owner: "Owner",
|
||||||
|
edate: "Effective date",
|
||||||
|
file: "File",
|
||||||
|
size: "Size"
|
||||||
|
};
|
||||||
|
d.edate = `${d.day}/${d.month}/${d.year}`;
|
||||||
|
for (let key in d) {
|
||||||
|
let value = d[key];
|
||||||
|
const field = map[key];
|
||||||
|
if(key === "ctime" || key == "mtime")
|
||||||
|
{
|
||||||
|
value = (new Date(value*1000)).toDateString();
|
||||||
|
}
|
||||||
|
if (field) { rows.push([{text: field}, {text: value}]); }
|
||||||
|
}
|
||||||
|
return this.docgrid.rows = rows;
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to fetch document detail: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.catview.onlistselect = (e) => {
|
||||||
|
this.clear_preview();
|
||||||
|
const item = e.data.item;
|
||||||
|
if (!item) { return; }
|
||||||
|
return this.update_doclist(item.data.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
(this.find("bt-add-doc") as GUI.tag.ButtonTag).onbtclick = async (evt) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const catiem = this.catview.selectedItem;
|
||||||
|
if (!catiem) { return this.notify(__("Please select a category")); }
|
||||||
|
const data = await this.openDialog(new docify.DocDialog());
|
||||||
|
data.cid = parseInt(catiem.data.id);
|
||||||
|
const timestamp = Math.floor(Date.now() / 1000);
|
||||||
|
data.ctime = timestamp;
|
||||||
|
data.mtime = timestamp;
|
||||||
|
const r = await this.exec("merge_files", data);
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error.toString());
|
||||||
|
}
|
||||||
|
data.file = r.result;
|
||||||
|
this.docdb.cache = data;
|
||||||
|
const d = await this.docdb.write(undefined);
|
||||||
|
if(d.error)
|
||||||
|
{
|
||||||
|
throw new Error(d.error.toString());
|
||||||
|
}
|
||||||
|
if (d.result) { this.toast(d.result); }
|
||||||
|
this.update_doclist(catiem.data.id);
|
||||||
|
this.clear_preview();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to add document: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
(this.find("bt-del-doc") as GUI.tag.ButtonTag).onbtclick = async (evt) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const item = this.docview.selectedItem;
|
||||||
|
if (!item) { return; }
|
||||||
|
const d = await this.ask({ text: __("Do you really want to delete: `{0}`", item.data.name) });
|
||||||
|
if (!d) { return; }
|
||||||
|
let r = await this.docdb.remove({
|
||||||
|
where: {
|
||||||
|
id: item.data.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error.toString());
|
||||||
|
}
|
||||||
|
r = await this.exec("deletedoc", {file: item.data.file});
|
||||||
|
if(r.error)
|
||||||
|
{
|
||||||
|
throw new Error(r.error.toString());
|
||||||
|
}
|
||||||
|
this.notify(r.result.toString());
|
||||||
|
this.update_doclist(item.data.cid);
|
||||||
|
return this.clear_preview();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to delete document: {0}", e.tostring()), e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(this.find("bt-upload-doc") as GUI.tag.ButtonTag).onbtclick = async (evt) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await `${this.setting.docpath}/unclassified`.asFileHandle().upload();
|
||||||
|
this.toast(__("File uploaded"));
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to upload document: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(this.find("bt-edit-doc") as GUI.tag.ButtonTag).onbtclick = async (evt) => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const item = this.docview.selectedItem;
|
||||||
|
const catiem = this.catview.selectedItem;
|
||||||
|
if (!item) { return; }
|
||||||
|
const data = await this.openDialog(new docify.DocDialog(), item.data);
|
||||||
|
data.cid = parseInt(catiem.data.id);
|
||||||
|
data.id = item.data.id;
|
||||||
|
const timestamp = Math.floor(Date.now() / 1000);
|
||||||
|
data.mtime = timestamp;
|
||||||
|
let d = await this.exec("updatedoc", {
|
||||||
|
data,
|
||||||
|
rm: !data.file.includes(item.data.file) ? item.data.file : false
|
||||||
|
});
|
||||||
|
if(d.error)
|
||||||
|
{
|
||||||
|
throw new Error(d.error);
|
||||||
|
}
|
||||||
|
const handle = item.data.$vfs;
|
||||||
|
handle.cache = d.result;
|
||||||
|
d = await handle.write(undefined);
|
||||||
|
if(d.error)
|
||||||
|
{
|
||||||
|
throw new Error(d.error);
|
||||||
|
}
|
||||||
|
if (d.result) { this.toast(d.result); }
|
||||||
|
this.update_doclist(catiem.data.id);
|
||||||
|
return this.clear_preview();
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to edit document metadata: {0}", e.toString()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return this.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async update_doclist(cid: any) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const d = await this.docdb.read({
|
||||||
|
where: {
|
||||||
|
cid: cid
|
||||||
|
},
|
||||||
|
order: ["year$desc", "month$desc", "day$desc"]
|
||||||
|
});
|
||||||
|
|
||||||
|
// this.exec("select",{table: "docs", cond:`cid = ${cid} ORDER BY year DESC, month DESC, day DESC`});
|
||||||
|
if(d.error)
|
||||||
|
{
|
||||||
|
throw new Error(d.error);
|
||||||
|
}
|
||||||
|
for (let v of d)
|
||||||
|
{
|
||||||
|
v.text = v.name;
|
||||||
|
}
|
||||||
|
return this.docview.data = d;
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to update document list: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private clear_preview() {
|
||||||
|
this.docpreview.getContext('2d').clearRect(0,0,this.docpreview.width,this.docpreview.height);
|
||||||
|
return this.docgrid.rows = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
async preview(path: any, canvas: HTMLCanvasElement) {
|
||||||
|
try {
|
||||||
|
const d = await this.exec("preview", path);
|
||||||
|
if (d.error) {
|
||||||
|
throw new Error(d.error);
|
||||||
|
}
|
||||||
|
const file = d.result.asFileHandle();
|
||||||
|
const data = await file.read("binary");
|
||||||
|
const img = new Image();
|
||||||
|
//($ me.view).append img
|
||||||
|
img.onload = () => {
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
canvas.height = img.height;
|
||||||
|
canvas.width = img.width;
|
||||||
|
//console.log canvas.width, canvas.height
|
||||||
|
return context.drawImage(img, 0, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const blob = new Blob([data], { type: file.info.mime });
|
||||||
|
return img.src = URL.createObjectURL(blob);
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Unable to generate document thumbnail: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private cat_refresh(): Promise<any> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
this.docview.data = [];
|
||||||
|
this.clear_preview();
|
||||||
|
const d = await this.catdb.read();
|
||||||
|
for (let v of d) {
|
||||||
|
v.text = v.name;
|
||||||
|
}
|
||||||
|
return this.catview.data = d;
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
reject(__e(e));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async initialize() {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check if we have configured docpath
|
||||||
|
if (this.setting.docpath) {
|
||||||
|
// check data base
|
||||||
|
return await this.init_db();
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// ask user to choose a docpath
|
||||||
|
const d = await this.openDialog("FileDialog", {
|
||||||
|
title:__("Please select a doc path"),
|
||||||
|
type: 'dir'
|
||||||
|
});
|
||||||
|
this.setting.docpath = d.file.path;
|
||||||
|
// save the doc path to local setting
|
||||||
|
//await this._api.setting();
|
||||||
|
return await this.init_db();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(e)
|
||||||
|
{
|
||||||
|
this.error(__("Error initialize database: {0}", e.toString()), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exec(action: string, args?: GenericObject<any>) {
|
||||||
|
const cmd = {
|
||||||
|
path: `${this.path()}/api.lua`,
|
||||||
|
parameters: {
|
||||||
|
action,
|
||||||
|
docpath: this.setting.docpath,
|
||||||
|
args
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return this.call(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
text: "__(Options)",
|
||||||
|
nodes: [
|
||||||
|
{ text: "__(Owners)", id:"owners"},
|
||||||
|
{ text: "__(Preview)", id:"preview"},
|
||||||
|
{ text: "__(Change doc path)", id:"setdocp"}
|
||||||
|
],
|
||||||
|
onchildselect: (e) => this.fileMenuHandle(e.data.item.data.id)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private fileMenuHandle(id: any) {
|
||||||
|
switch (id) {
|
||||||
|
case "owners":
|
||||||
|
return this.openDialog(new docify.OwnerDialog(), {
|
||||||
|
title: __("Owners"),
|
||||||
|
dbhandle: this.ownerdb
|
||||||
|
});
|
||||||
|
case "preview":
|
||||||
|
return this.openDialog(new docify.FilePreviewDialog(), {
|
||||||
|
app: this
|
||||||
|
})
|
||||||
|
.then((d: { path: any; }) => {
|
||||||
|
return this.notify(d.path);
|
||||||
|
});
|
||||||
|
case "setdocp":
|
||||||
|
this.setting.docpath = undefined;
|
||||||
|
return this.initialize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Docify.dependencies = ["pkg://SQLiteDB/libsqlite.js"];
|
||||||
|
}
|
||||||
|
}
|
@ -154,9 +154,9 @@
|
|||||||
"name": "Docify",
|
"name": "Docify",
|
||||||
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/2.0.x/Docify/README.md",
|
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/2.0.x/Docify/README.md",
|
||||||
"category": "Office",
|
"category": "Office",
|
||||||
"author": "",
|
"author": "Dany LE",
|
||||||
"version": "0.0.9-b",
|
"version": "0.1.0-b",
|
||||||
"dependencies": [],
|
"dependencies": ["SQLiteDB@0.1.0-a"],
|
||||||
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/2.0.x/Docify/build/release/Docify.zip"
|
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/2.0.x/Docify/build/release/Docify.zip"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user