core services renamed to syslog

This commit is contained in:
Xuan Sang LE 2020-05-20 23:11:58 +02:00
parent 33eab1d30a
commit 9008396ac9
28 changed files with 436 additions and 226 deletions

View File

@ -49,7 +49,7 @@ coffees= src/core/core.coffee \
src/core/tags/SystemPanelTag.coffee \
src/antos.coffee
packages = CoreServices Files Setting CodePad MarketPlace
packages = Syslog Files Setting CodePad MarketPlace
main: initd build_coffees build_themes libs build_packages languages
- cp src/index.html $(BUILDDIR)/

View File

@ -36,7 +36,7 @@ class SubWindow extends this.OS.GUI.BaseModel
show: () ->
@trigger 'focus'
($ @scheme).css "z-index", window._zindex + 2
($ @scheme).css "z-index", Ant.OS.GUI.zindex + 2
hide: () ->
@trigger 'hide'
@ -56,10 +56,14 @@ this.OS.GUI.BaseDialog = BaseDialog
class BasicDialog extends BaseDialog
constructor: ( name, target) ->
super name
if typeof target is "string"
Ant.OS.GUI.htmlToScheme target, @, @host
else # a file handle
@render target.path
if target
if typeof target is "string"
Ant.OS.GUI.htmlToScheme target, @, @host
else # a file handle
@render target.path
else if Ant.OS.GUI.subwindows[name] and Ant.OS.GUI.subwindows[name].scheme
scheme = Ant.OS.GUI.subwindows[name].scheme
Ant.OS.GUI.htmlToScheme scheme, @, @host
init: () ->
@scheme.set "apptitle", @data.title if @data and @data.title
@ -70,20 +74,28 @@ this.OS.GUI.BasicDialog = BasicDialog
class PromptDialog extends BasicDialog
constructor: () ->
super "PromptDialog", PromptDialog.scheme
super "PromptDialog"
init: () ->
super.init()
$input = $(@find "txtInput")
@find("lbl").set "text", @data.label if @data and @data.label
$(@find "txtInput").val @data.value if @data and @data.value
$input.val @data.value if @data and @data.value
(@find "btnOk").set "onbtclick", (e) =>
@handle($(@find "txtInput").val()) if @handle
@handle($input.val()) if @handle
@quit()
(@find "btnCancel").set "onbtclick", (e) =>
@quit()
$input.keyup (e) =>
return unless e.which is 13
@handle($input.val()) if @handle
@quit()
$input.focus()
PromptDialog.scheme = """
<afx-app-window width='200' height='150' apptitle = "Prompt">
@ -110,7 +122,7 @@ this.OS.register "PromptDialog", PromptDialog
class CalendarDialog extends BasicDialog
constructor: () ->
super "CalendarDialog", CalendarDialog.scheme
super "CalendarDialog"
init: () ->
super.init()
@ -149,7 +161,7 @@ this.OS.register "CalendarDialog", CalendarDialog
class ColorPickerDialog extends BasicDialog
constructor: () ->
super "ColorPickerDialog", ColorPickerDialog.scheme
super "ColorPickerDialog"
init: () ->
super.init()
@ -188,7 +200,7 @@ this.OS.register "ColorPickerDialog", ColorPickerDialog
class InfoDialog extends BasicDialog
constructor: () ->
super "InfoDialog", InfoDialog.scheme
super "InfoDialog"
init: () ->
super.init()
@ -226,7 +238,7 @@ this.OS.register "InfoDialog", InfoDialog
class YesNoDialog extends BasicDialog
constructor: () ->
super "YesNoDialog", YesNoDialog.scheme
super "YesNoDialog"
init: () ->
super.init()
@ -262,7 +274,7 @@ this.OS.register "YesNoDialog", YesNoDialog
class SelectionDialog extends BasicDialog
constructor: () ->
super "SelectionDialog", SelectionDialog.scheme
super "SelectionDialog"
init: () ->
super.init()
@ -302,8 +314,7 @@ this.OS.register "SelectionDialog", SelectionDialog
class AboutDialog extends BasicDialog
constructor: () ->
super "AboutDialog", AboutDialog.scheme
super "AboutDialog"
init: () ->
mt = @meta()
@scheme.set "apptitle", __("About: {0}", mt.name)
@ -348,7 +359,7 @@ this.OS.register "AboutDialog", AboutDialog
class FileDialog extends BasicDialog
constructor: () ->
super "FileDialog", FileDialog.scheme
super "FileDialog"
init: () ->
super.init()

View File

@ -113,7 +113,7 @@ class BaseModel
@publish "warning", m
error: (m, e) ->
@publish "error", m, if e then e else (@_api.throwe @name)
@publish "error", m, if e then e else (@_api.throwe m)
fail: (m) ->
@publish "fail", m

View File

@ -391,6 +391,17 @@ Ant.OS.API =
err = e
return "" if not err
return err
setClipboard: (v) ->
$el = $("#clipboard")
$el.val v
$el[0].select()
$el[0].setSelectionRange(0, 99999)
document.execCommand("copy")
getClipboard: () ->
$("#clipboard").val()
# utilities functioncs
switcher: () ->
o = {}

View File

@ -41,32 +41,32 @@ Ant.OS or=
pidalloc: 0
processes: {}
createProcess: (app, cls, args) ->
f = () ->
#if it is single ton
# and a process is existing
# just return it
if cls.singleton and Ant.OS.PM.processes[app] and Ant.OS.PM.processes[app].length == 1
Ant.OS.PM.processes[app][0].show()
new Promise (resolve, reject) ->
f = () ->
#if it is single ton
# and a process is existing
# just return it
if cls.singleton and Ant.OS.PM.processes[app] and Ant.OS.PM.processes[app].length == 1
obj = Ant.OS.PM.processes[app][0]
obj.show()
else
Ant.OS.PM.processes[app] = [] if not Ant.OS.PM.processes[app]
obj = new cls(args)
obj.birth = (new Date).getTime()
Ant.OS.PM.pidalloc++
obj.pid = Ant.OS.PM.pidalloc
Ant.OS.PM.processes[app].push obj
if cls.type is 1 then Ant.OS.GUI.dock obj, cls.meta else Ant.OS.GUI.attachservice obj
obj
if cls.dependencies
libs = (v for v in cls.dependencies)
Ant.OS.API.require libs
.then () ->
resolve f()
.catch (e) ->
reject e
else
Ant.OS.PM.processes[app] = [] if not Ant.OS.PM.processes[app]
obj = new cls(args)
obj.birth = (new Date).getTime()
Ant.OS.PM.pidalloc++
obj.pid = Ant.OS.PM.pidalloc
Ant.OS.PM.processes[app].push obj
if cls.type is 1 then Ant.OS.GUI.dock obj, cls.meta else Ant.OS.GUI.attachservice obj
if cls.type is 2
Ant.OS.announcer.trigger "srvroutineready", app
if cls.dependencies
libs = (v for v in cls.dependencies)
Ant.OS.API.require libs
.then () ->
console.log "launch the app"
f()
.catch (e) ->
Ant.OS.announcer.oserror __("Unable to load libraries"), e
else
f()
resolve f()
appByPid: (pid) ->
app = undefined
find = (l) ->

View File

@ -53,11 +53,19 @@ Ant.OS.GUI =
.attr "href", path
pushServices: (srvs) ->
return unless srvs.length > 0
Ant.OS.announcer.observable.one "srvroutineready", () ->
srvs.splice 0, 1
Ant.OS.GUI.pushServices srvs
Ant.OS.GUI.pushService srvs[0]
new Promise (resolve, reject) ->
return resolve() unless srvs.length > 0
srv = srvs.splice(0, 1)[0]
Ant.OS.GUI.pushService srv
.then (d) ->
Ant.OS.GUI.pushServices srvs
.then () -> resolve()
.catch (e) -> reject e
.catch (e) ->
Ant.OS.announcer.osfail __("Unable to load: {0}", srv), e
Ant.OS.GUI.pushServices srvs
.then () -> resolve()
.catch (e) -> reject e
openDialog: (d, data) ->
new Promise (resolve, reject) ->
@ -76,16 +84,23 @@ Ant.OS.GUI =
Ant.OS.GUI.dialog.init()
pushService: (ph) ->
arr = ph.split "/"
srv = arr[1]
app = arr[0]
return Ant.OS.PM.createProcess srv, Ant.OS.APP[srv] if Ant.OS.APP[srv]
Ant.OS.GUI.loadApp app
.then (a) ->
return Ant.OS.PM.createProcess srv, Ant.OS.APP[srv] if Ant.OS.APP[srv]
.catch (e) ->
Ant.OS.announcer.trigger "srvroutineready", srv
Ant.OS.announcer.osfail __("Cannot read service script: {0}", srv), e
new Promise (resolve, reject) ->
arr = ph.split "/"
srv = arr[1]
app = arr[0]
if Ant.OS.APP[srv]
Ant.OS.PM.createProcess srv, Ant.OS.APP[srv]
.then (d) -> resolve d
.catch (e) -> reject e
else
Ant.OS.GUI.loadApp app
.then (a) ->
if not Ant.OS.APP[srv]
return reject Ant.OS.API.throwe __("Service not found: {0}", ph)
Ant.OS.PM.createProcess srv, Ant.OS.APP[srv]
.then (d) -> resolve d
.catch (e) -> reject e
.catch (e) -> reject e
appsByMime: (mime) ->
metas = ( v for k, v of Ant.OS.setting.system.packages when v and v.app )
@ -165,12 +180,18 @@ Ant.OS.GUI =
if not Ant.OS.APP[app]
# first load it
Ant.OS.GUI.loadApp(app).then (a) ->
console.log "apploaded"
Ant.OS.PM.createProcess a, Ant.OS.APP[a], args
.catch (e) ->
console.log e
Ant.OS.announcer.osfail __("Unable to launch: {0}", app), e
else
# now launch it
if Ant.OS.APP[app]
Ant.OS.PM.createProcess app, Ant.OS.APP[app], args
.catch (e)->
console.log e
Ant.OS.announcer.osfail __("Unable to launch: {0}", app), e
dock: (app, meta) ->
# dock an application to a dock
# create a data object
@ -473,6 +494,7 @@ Ant.OS.GUI.schemes.ws = """
</div>
<afx-menu id="contextmenu" data-id="contextmenu" context="true" style="display:none;"></afx-menu>
<afx-label id="systooltip" data-id="systooltip" style="display:none;position:absolute;"></afx-label>
<textarea id="clipboard"></textarea>
"""
Ant.OS.GUI.schemes.login = """

View File

@ -43,8 +43,8 @@
Ant.OS.setting.system = conf.system if conf.system
Ant.OS.setting.system.startup = {
services: [
"CoreServices/PushNotification",
"CoreServices/Calendar"
"Syslog/PushNotification",
"Syslog/Calendar"
],
apps: []
} if not Ant.OS.setting.system.startup

View File

@ -32,6 +32,7 @@ class SystemPanelTag extends Ant.OS.GUI.BaseTag
@toggle false
# launch the app or open the file
Ant.OS.GUI.openWith data
@refs.applist.unselect()
search: (e) ->
switch e.which

View File

@ -100,7 +100,7 @@ class WindowTag extends Ant.OS.GUI.BaseTag
$(@refs["grip"]).hide()
__apptitle__: (value) ->
$(@refs["dragger"]).text value.__() if value
@refs["txtTitle"].set "text", value if value
enable_dragging: () ->
$(@refs["dragger"])
@ -190,7 +190,9 @@ class WindowTag extends Ant.OS.GUI.BaseTag
{ el: "li", class: "afx-window-close", ref: "closebt" },
{ el: "li", class: "afx-window-minimize", ref: "minbt" },
{ el: "li", class: "afx-window-maximize", ref: "maxbt" },
{ el: "li", class: "afx-window-title", ref: "dragger" }
{ el: "li", class: "afx-window-title", ref: "dragger", children: [{
el: "afx-label", ref: "txtTitle"
}] }
]
},
{ el: "div", class: "afx-clear" },

View File

@ -51,6 +51,10 @@ class BaseFileHandle
@basename = @genealogy[@genealogy.length - 1] unless @isRoot()
@ext = @basename.split( "." ).pop() unless @basename.lastIndexOf(".") is 0 or @basename.indexOf( "." ) is -1
filename: () ->
return "Untitled" unless @basename
@basename
setCache: (v) ->
@cache = v
@

View File

@ -14,8 +14,8 @@ class CodePad.BaseExtension
notify: (m) ->
@app.notify m
error: (m) ->
@app.error m
error: (m, e) ->
@app.error m, e
dependencies: () ->
[]
@ -87,6 +87,7 @@ class CodePad.BaseExtension
path = (list.splice 0, 1)[0].asFileHandle()
path.parent().mk path.basename
.then (d) =>
@app.trigger "filechange", { file: path.parent(), type: "dir" }
@mkdirAll list
.then () -> resolve()
.catch (e) -> reject e
@ -101,9 +102,11 @@ class CodePad.BaseExtension
.read()
.then (data) =>
file = item[1].asFileHandle()
file
.setCache(data.format name, "#{path}/#{name}")
.write "text/plain"
.then () =>
@app.trigger "filechange", { file: file, type: "file" }
@mkfileAll list, path, name
.then () -> resolve()
.catch (e) -> reject e

View File

@ -47,9 +47,6 @@ class App.extensions.AntOSDK extends App.BaseExtension
mktpl: (path, name, flag) ->
rpath = "#{path}/#{name}"
dirs = [
"#{rpath}/build",
"#{rpath}/build/release",
"#{rpath}/build/debug",
"#{rpath}/javascripts",
"#{rpath}/css",
"#{rpath}/coffees",
@ -102,33 +99,40 @@ class App.extensions.AntOSDK extends App.BaseExtension
.catch (e) -> reject e
build: (meta) ->
dirs = [
"#{meta.root}/build",
"#{meta.root}/build/debug",
"#{meta.root}/build/release"
]
new Promise (resolve, reject) =>
@compile(meta).then (src) =>
@cat ("#{meta.root}/#{v}" for v in meta.javascripts), src
.then (jsrc) ->
new Promise (r, e) ->
"#{meta.root}/build/debug/main.js"
.asFileHandle()
.setCache jsrc
.write("text/plain")
.then (d) ->
r()
.catch (ex) -> e ex
.then () =>
new Promise (r, e) =>
@cat ("#{meta.root}/#{v}" for v in meta.css), ""
.then (txt) ->
return r() if txt is ""
"#{meta.root}/build/debug/main.css"
.asFileHandle()
.setCache txt
.write("text/plain")
.then (d) ->
r()
.catch (ex) -> e ex
.then () =>
@copy ("#{meta.root}/#{v}" for v in meta.copies), "#{meta.root}/build/debug"
.then () -> resolve()
@mkdirAll(dirs).then =>
@compile(meta).then (src) =>
@cat ("#{meta.root}/#{v}" for v in meta.javascripts), src
.then (jsrc) ->
new Promise (r, e) ->
"#{meta.root}/build/debug/main.js"
.asFileHandle()
.setCache jsrc
.write("text/plain")
.then (d) ->
r()
.catch (ex) -> e ex
.then () =>
new Promise (r, e) =>
@cat ("#{meta.root}/#{v}" for v in meta.css), ""
.then (txt) ->
return r() if txt is ""
"#{meta.root}/build/debug/main.css"
.asFileHandle()
.setCache txt
.write("text/plain")
.then (d) ->
r()
.catch (ex) -> e ex
.then () =>
@copy ("#{meta.root}/#{v}" for v in meta.copies), "#{meta.root}/build/debug"
.then () -> resolve()
.catch (e) -> reject e
.catch (e) -> reject e
.catch (e) -> reject e

View File

@ -27,6 +27,7 @@ class CodePad extends this.OS.GUI.BaseApplication
dir.read().then (d) ->
return reject d.error if d.error
resolve d.result
.catch (e) -> reject e
@setup()
setup: () ->
@ -38,6 +39,8 @@ class CodePad extends this.OS.GUI.BaseApplication
enableSnippets: true,
enableLiveAutocompletion: true,
highlightActiveLine: true,
highlightSelectedWord: true,
behavioursEnabled: true,
wrap: true,
fontSize: "11pt"
}
@ -72,11 +75,13 @@ class CodePad extends this.OS.GUI.BaseApplication
@editor.focus()
return false
@fileview.set "onfileopen", (e) =>
return unless e.data and e.data.path
return if e.data.type is "dir"
@openFile e.data.path.asFileHandle()
@fileview.set "onfileselect", (e) =>
return unless e.data or e.data.type is "dir"
return unless e.data and e.data.path
return if e.data.type is "dir"
i = @findTabByFile e.data.path.asFileHandle()
return @tabbar.set "selected", i if i isnt -1
@ -118,6 +123,12 @@ class CodePad extends this.OS.GUI.BaseApplication
e.data.from.get("parent").update src.parent().path
.catch (e) => @error __("Unable to move file/folder"), e
@on "filechange", (data) =>
path = data.file.path
path = data.file.parent().path if data.type is "file"
@fileview.update path
@loadExtensionMetaData()
@initCommandPalete()
@initSideBar()
@ -178,16 +189,17 @@ class CodePad extends this.OS.GUI.BaseApplication
m = @modes.getModeForPath(file.path)
file.langmode = { caption: m.caption, mode: m.mode }
else
file.langmode = { caption: "Text", mode: "ace/mode/text" }
file.langmode = { caption: "Text", mode: "ace/mode/text" }
@editormux = true
@editor.getSession().setUndoManager new ace.UndoManager()
@editor.setValue file.cache, -1
@editor.session.setMode file.langmode.mode
@editor.session.setUndoManager file.um
@editor.getSession().setMode file.langmode.mode
if file.cursor
@editor.renderer.scrollCursorIntoView {
row: file.cursor.row, column: file.cursor.column
}, 0.5
@editor.selection.moveTo file.cursor.row, file.cursor.column
@editor.getSession().setUndoManager file.um
@updateStatus()
@editor.focus()
@ -423,7 +435,7 @@ class CodePad extends this.OS.GUI.BaseApplication
evt.preventDefault()
@.openDialog("YesNoDialog", {
title: "__(Quit)",
text: __("Ignore all {0} unsaved files ?", dirties.length)
text: __("Ignore all unsaved files: {0} ?", (v.filename() for v in dirties).join ", " )
}).then (d) =>
if d
v.dirty = false for v in dirties

View File

@ -1,11 +0,0 @@
coffee_files = Calendar.coffee PushNotification.coffee
jsfiles =
cssfiles = main.css
copyfiles = package.json
PKG_NAME=CoreServices
include ../pkg.mk

View File

@ -36,15 +36,22 @@ class Files extends this.OS.GUI.BaseApplication
@view.contextmenuHandle = (e, m) =>
file = @view.get "selectedFile"
return unless file
apps = []
if file and file.mime
file.mime = "dir" if file.type is "dir"
file.mime = "dir" if file.type is "dir"
for v in @_gui.appsByMime file.mime
v.args = [ file ]
apps.push v
for v in @_gui.appsByMime file.mime
v.args = [ file ]
apps.push v
m.set "items", [
{ text: "__(Open with)", dataid: "#{@name}-open", child: apps },
{
text: "__(Open with)",
child: apps,
onchildselect: (e) =>
return unless e
it = e.data.item.get("data")
@_gui.launch it.app, [file]
},
@mnFile(),
@mnEdit()
]
@ -83,33 +90,50 @@ class Files extends this.OS.GUI.BaseApplication
resolve d.result
.catch (e) -> reject e
@vfs_event_flag = true
@view.set "ondragndrop", (e) =>
return unless e
src = e.data.from.get("data")
des = e.data.to.get("data")
return if des.type is "file"
file = src.path.asFileHandle()
# disable the vfs event on
# we update it manually
@vfs_event_flag = false
file.move "#{des.path}/#{file.basename}"
.then () =>
@view.set "path", @view.get("path")
@view.update file.parent().path
@view.update des.path
.catch (e) => @error __("Unable to move: {0} -> {1}", src.path, des.path), e
if @view.get("view") is "icon"
@view.set "path", @view.get("path")
else
@view.update file.parent().path
@view.update des.path
#reenable the vfs event
@vfs_event_flag = true
.catch (e) =>
# reenable the vfs event
@vfs_event_flag = true
@error __("Unable to move: {0} -> {1}", src.path, des.path), e
# application setting
@setting.sidebar = true if @setting.sidebar is undefined
@setting.nav = true if @setting.nav is undefined
@setting.showhidden = false if @setting.showhidden is undefined
@applyAllSetting()
# VFS mount point and event
mntpoints = @systemsetting.VFS.mountpoints
el.selected = false for el, i in mntpoints
@favo.set "data", mntpoints
#@favo.set "selected", -1
@view.set "view", @setting.view if @setting.view
@subscribe "VFS", (d) =>
return unless @vfs_event_flag
return if ["read", "publish", "download"].includes d.data.m
if d.data.file.hash() is @currdir.hash() or d.data.file.parent().hash() is @currdir.hash()
if (d.data.file.hash() is @currdir.hash() or
d.data.file.parent().hash() is @currdir.hash())
@view.set "path", @currdir
# bind keyboard shortcut
@bindKey "CTRL-F", () => @actionFile "#{@name}-mkf"
@bindKey "CTRL-D", () => @actionFile "#{@name}-mkdir"
@bindKey "CTRL-U", () => @actionFile "#{@name}-upload"

View File

@ -50,7 +50,7 @@ class MarketPlace extends this.OS.GUI.BaseApplication
el = @applist.get "selectedItem"
return unless el
app = el.get("data")
@_gui.launch app.className if app.className
@_gui.launch app.pkgname if app.pkgname
@btinstall.set "onbtclick", (e) =>
if @btinstall.get "dirty"
@ -108,7 +108,7 @@ class MarketPlace extends this.OS.GUI.BaseApplication
list = []
for k, v of pkgcache
list.push {
className: if v.app then v.app else v.className,
pkgname: if v.pkgname then v.pkgname else v.app,
name: v.name,
text: v.name,
icon: v.icon,
@ -140,14 +140,16 @@ class MarketPlace extends this.OS.GUI.BaseApplication
d.description.asFileHandle().read().then (text) =>
converter = new showdown.Converter()
($ @appdesc).html(converter.makeHtml text)
.catch (e) => @notify __("Unable to read package description")
.catch (e) =>
@notify __("Unable to read package description")
($ @appdesc).empty()
else
($ @appdesc).empty()
pkgcache = @systemsetting.system.packages
@btinstall.set "text", "__(Install)"
@btinstall.set "dirty", false
if pkgcache[d.className]
vs = pkgcache[d.className].version
if pkgcache[d.pkgname]
vs = pkgcache[d.pkgname].version
ovs = d.version
($ @btinstall).hide()
if vs and ovs
@ -223,7 +225,7 @@ class MarketPlace extends this.OS.GUI.BaseApplication
.then (n) =>
@repo.unselect()
@repo.set "selected", 0
apps = (v.className for v in @applist.get("data"))
apps = (v.pkgname for v in @applist.get("data"))
idx = apps.indexOf n
if idx >= 0
@applist.set "selected", idx
@ -249,7 +251,7 @@ class MarketPlace extends this.OS.GUI.BaseApplication
@mkdirs(dir).then () =>
@installFile(v.app, zip, files).then () =>
app_meta = {
className: v.app,
pkgname: v.app,
name: v.name,
text: v.name,
icon: v.icon,
@ -281,8 +283,8 @@ class MarketPlace extends this.OS.GUI.BaseApplication
return unless el
sel = el.get "data"
return unless sel
name = sel.className
app = @systemsetting.system.packages[sel.className]
name = sel.pkgname
app = @systemsetting.system.packages[sel.pkgname]
return unless app
@openDialog("YesNoDialog", {
title: __("Uninstall") ,

View File

@ -0,0 +1,11 @@
coffee_files = Calendar.coffee PushNotification.coffee Syslog.coffee
jsfiles =
cssfiles = main.css
copyfiles = package.json scheme.html
PKG_NAME=Syslog
include ../pkg.mk

View File

@ -5,7 +5,7 @@
# This program is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of
# published by the Free Software Foundation, either version 3 of
# the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
@ -15,74 +15,6 @@
# You should have received a copy of the GNU General Public License
#along with this program. If not, see https://www.gnu.org/licenses/.
Ant = this
class LogDialog extends this.OS.GUI.BasicDialog
constructor: () ->
super "LogDialog", LogDialog.scheme
init: () ->
@loglist = @find "loglist"
@logdetail = @find "logdetail"
@loglist.set "data", @data.logs if @data and @data.logs
$(@find("txturi")).val Ant.OS.setting.system.error_report
@loglist.set "onlistselect", (e) =>
data = e.data.item.get("data") if e and e.data
return unless data
stacktrace = "None"
stacktrace = data.error.stack if data.error
$(@logdetail).text LogDialog.template.format(
data.text,
data.type,
data.time,
data.name,
data.id,
stacktrace
)
@find("btnreport").set "onbtclick", (e) =>
uri = $(@find("txturi")).val()
return if uri is ""
el = @loglist.get "selectedItem"
return unless el
data = el.get("data")
return unless data
Ant.OS.API.post uri, data
.then (d) =>
@notify __("Error reported")
.catch (e) =>
@notify __("Unable to report error: {0}", e.toString())
LogDialog.template = """
{0}
Log type: {1}
Log time: {2}
Process: {3} ({4})
detail:
{5}
"""
LogDialog.scheme = """
<afx-app-window data-id="LogDialog" width='500' height='350' apptitle = "__(System error log)" >
<afx-hbox>
<afx-list-view data-id = "loglist" data-width="200"> </afx-list-view>
<afx-resizer data-width = "2" />
<afx-vbox>
<div data-height="10" />
<div data-id = "container">
<pre><code data-id="logdetail"></code></pre>
</div>
<div data-height="10" />
<afx-hbox style="text-align:right;" data-height = "27">
<div data-width="5" />
<input type = "text" data-id = "txturi" />
<afx-button data-width ="80" text = "__(Report)"
iconclass = "fa fa-bug" data-id = "btnreport" />
<div data-width="10" />
</afx-hbox>
<div data-height="10" />
</afx-vbox>
</afx-hbox>
</afx-app-window>
"""
class PushNotification extends this.OS.GUI.BaseService
constructor: (args) ->
@ -91,6 +23,7 @@ class PushNotification extends this.OS.GUI.BaseService
@cb = undefined
@pending = []
@logs = []
@logmon = undefined
init: ->
@view = false
@_gui.htmlToScheme PushNotification.scheme, @, @host
@ -139,23 +72,26 @@ class PushNotification extends this.OS.GUI.BaseService
.hide()
showLogReport: () ->
@openDialog(new LogDialog(), {
logs: @logs
})
@_gui.launch "Syslog"
addLog: (s, o) ->
logtime = new Date()
@logs.push {
log = {
type: s,
name: o.name,
text: "#{logtime}: #{o.data.m}",
text: "#{o.data.m}",
id: o.id,
icon: o.data.icon,
iconclass: o.data.iconclass,
error: o.data.e,
time: logtime
time: logtime,
closable: true,
tag: "afx-bug-list-item"
}
@dialog.loglist.set "data", @dialog.data.logs if @dialog
if @logmon
@logmon.addLog log
else
@logs.push log
pushout: (s, o) ->
d = {

View File

@ -0,0 +1,105 @@
Ant = this
class BugListItemTag extends Ant.OS.GUI.tag["afx-list-item-proto"]
constructor: (r, o) ->
super r, o
__data__: (v) ->
return unless v
@refs.error.set "text", v.text
@refs.time.set "text", v.time
@refs.error.set "icon", v.icon if v.icon
if not v.icon
@refs.error.set "iconclass", if v.iconclass then v.iconclass else "fa fa-bug"
@set "closable", v.closable
__selected: (v) ->
@get("data").selected = v
itemlayout: () ->
{ el: "div", children: [
{ el: "afx-label", ref: "error", class: "afx-bug-list-item-error" },
{ el: "afx-label", ref: "time", class: "afx-bug-list-item-time" }
] }
Ant.OS.GUI.define "afx-bug-list-item", BugListItemTag
class Syslog extends this.OS.GUI.BaseApplication
constructor: (args) ->
super "Syslog", args
main: () ->
@loglist = @find "loglist"
@logdetail = @find "logdetail"
@_gui.pushService "Syslog/PushNotification"
.then (srv) =>
@srv = srv
@loglist.set "data", @srv.logs if @srv and @srv.logs
@srv.logmon = @
.catch (e) =>
@error __("Unable to load push notification service"), e
@quit()
$(@find("txturi")).val Ant.OS.setting.system.error_report
@loglist.set "onlistselect", (e) =>
data = e.data.item.get("data") if e and e.data
return unless data
stacktrace = "None"
stacktrace = data.error.stack if data.error
$(@logdetail).text Syslog.template.format(
data.text,
data.type,
data.time,
data.name,
data.id,
stacktrace
)
@loglist.set "onitemclose", (e) =>
el = e.data.item if e and e.data
return true unless el
data = el.get "data"
console.log data
return true unless data.selected
$(@logdetail).text("")
return true
@find("btnreport").set "onbtclick", (e) =>
uri = $(@find("txturi")).val()
return if uri is ""
el = @loglist.get "selectedItem"
return unless el
data = el.get("data")
return unless data
Ant.OS.API.post uri, data
.then (d) =>
@notify __("Error reported")
.catch (e) =>
@notify __("Unable to report error: {0}", e.toString())
@find("btclean").set "onbtclick", (e) =>
return unless @srv
@srv.logs = []
@loglist.set "data", @srv.logs
$(@logdetail).text("")
addLog: (log) ->
@loglist.push log
cleanup: () ->
@srv.logmon = undefined if @srv
Syslog.template = """
{0}
Log type: {1}
Log time: {2}
Process: {3} ({4})
detail:
{5}
"""
Syslog.singleton = true
this.OS.register "Syslog", Syslog

View File

@ -49,13 +49,38 @@ afx-list-view[data-id = "notifeed"] li{
word-break: break-word;
}
afx-app-window[data-id ='LogDialog'] div[data-id ='container']{
afx-app-window[data-id ='Syslog'] div[data-id ='container']{
overflow: auto;
}
afx-app-window[data-id ='LogDialog'] pre {
padding: 10px;
afx-app-window[data-id ='Syslog'] .afx-bug-list-item-error {
display: block;
}
afx-app-window[data-id ='LogDialog'] input{
afx-app-window[data-id ='Syslog'] .afx-bug-list-item-error i::before {
color: chocolate;
}
afx-app-window[data-id ='Syslog'] .afx-bug-list-item-time{
display: block;
padding-left: 10px;
}
afx-app-window[data-id ='Syslog'] .afx-bug-list-item-time i.label-text{
font-size: 10px;
font-style: italic;
}
afx-app-window[data-id ='Syslog'] afx-bug-list-item li.selected {
background-color: #116cd6;
color: white;
}
afx-app-window[data-id ='Syslog'] pre {
padding: 10px;
margin:0;
user-select: text;
cursor: text;
}
afx-app-window[data-id ='Syslog'] input{
height: 100%;
}

View File

@ -1,9 +1,9 @@
{
"app":null,
"className": "CoreServices",
"app":"Syslog",
"pkgname": "Syslog",
"services": [ "Calendar", "PushNotification" ],
"name": "Core services",
"description":"This is the core services",
"name": "System log",
"description":"Core services and system log",
"info":{
"author": "Xuan Sang LE",
"email": "xsang.le@gmail.com",
@ -12,5 +12,6 @@
},
"version":"0.0.1-a",
"category":"System",
"mimes":["*"]
"iconclass": "fa fa-bug",
"mimes":[]
}

View File

@ -0,0 +1,21 @@
<afx-app-window data-id="Syslog" width='500' height='350' apptitle = "__(System error log)" >
<afx-hbox>
<afx-list-view data-id = "loglist" data-width="200"> </afx-list-view>
<afx-resizer data-width = "2" />
<afx-vbox>
<div data-id = "container">
<pre><code data-id="logdetail"></code></pre>
</div>
<div data-height="10" />
<afx-hbox style="text-align:right;" data-height = "27">
<afx-button data-width ="20"
tooltip = "ct:__(Clear all logs)" iconclass = "fa fa-trash-o" data-id = "btclean" />
<input type = "text" data-id = "txturi" />
<afx-button data-width ="80" text = "__(Report)"
iconclass = "fa fa-bug" data-id = "btnreport" />
<div data-width="10" />
</afx-hbox>
<div data-height="10" />
</afx-vbox>
</afx-hbox>
</afx-app-window>

View File

@ -11,7 +11,6 @@ afx-file-view afx-list-view > div.list-container > ul li{
height: 60px;
background-color: transparent;
text-align: center;
padding:3px;
margin-right: 5px;
margin-bottom: 5px;
}
@ -27,9 +26,8 @@ afx-file-view afx-list-view i.dir:before{
font-style: normal;
}
afx-file-view afx-list-view i{
width: 32px;
height: 32px;
margin-left: 19px;
width: 100%;
margin-left: 3px;
}
@ -42,7 +40,11 @@ afx-file-view afx-list-view i.file:before{
font-weight: normal;
}
afx-file-view afx-list-view > div.list-container > ul > afx-list-item > li.selected, afx-file-view afx-list-view div.list-container > ul li.selected i:before {
afx-file-view afx-list-view > div.list-container > ul > afx-list-item > li.selected
{
background-color: transparent;
}
afx-file-view afx-list-view div.list-container > ul li.selected i.label-text {
background-color: #116cd6;
color:white;
border-radius: 6px;

View File

@ -66,4 +66,12 @@ input {
box-sizing: border-box;
font-family: "Ubuntu";
font-size: 13px;
}
textarea {
color: white;
background-color: #464646;
outline: none;
border: 1px solid #262626;
box-sizing: border-box;
}

View File

@ -10,7 +10,6 @@ afx-file-view afx-list-view > div.list-container > ul li{
height: 60px;
background-color: transparent;
text-align: center;
padding:3px;
margin-right: 5px;
margin-bottom: 5px;
}
@ -26,9 +25,8 @@ afx-file-view afx-list-view i.dir:before{
font-style: normal;
}
afx-file-view afx-list-view i{
width: 32px;
height: 32px;
margin-left: 19px;
width: 100%;
margin-left: 3px;
}
@ -40,8 +38,11 @@ afx-file-view afx-list-view i.file:before{
font-style: normal;
font-weight: normal;
}
afx-file-view afx-list-view > div.list-container > ul > afx-list-item > li.selected, afx-file-view afx-list-view div.list-container > ul li.selected i:before {
afx-file-view afx-list-view > div.list-container > ul > afx-list-item > li.selected
{
background-color: transparent;
}
afx-file-view afx-list-view div.list-container > ul li.selected i.label-text {
background-color: #116cd6;
color:white;
border-radius: 6px;

View File

@ -66,4 +66,11 @@ input {
box-sizing: border-box;
font-family: "Ubuntu";
font-size: 13px;
}
textarea {
color: #414339;
background-color: #f6F6F6;
outline: none;
border: 1px solid #a6a6a6;
box-sizing: border-box;
}

View File

@ -121,4 +121,12 @@ body
padding:3px;
color:chocolate;
font-weight: normal;
}
#clipboard {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
box-sizing: border-box;
}