dialog mechanism

This commit is contained in:
Xuan Sang LE 2017-08-24 01:53:13 +02:00
parent 978dee5f91
commit 8f9dd68213
18 changed files with 381 additions and 146 deletions

View File

@ -12,6 +12,7 @@ coffees= src/core/core.coffee\
src/core/BaseApplication.coffee\
src/core/BaseService.coffee\
src/core/BaseEvent.coffee\
src/core/BaseDialog.coffee\
src/antos.coffee

View File

@ -1,7 +1,4 @@
self = this
_PM = self.OS.PM
_APP = self.OS.APP
_MAIL = self.OS.courrier
class BaseApplication extends this.OS.GUI.BaseModel
constructor: (name) ->
super name
@ -16,9 +13,11 @@ class BaseApplication extends this.OS.GUI.BaseModel
me.appmenu.set "items", (me.baseMenu() || [])
me.appmenu.set "onmenuselect", (d) ->
me.trigger("menuselect", d)
me.dialog.show() if me.dialog
@on "hide", () ->
me.sysdock.set "selectedApp", null
me.appmenu.set "items", []
me.dialog.hide() if me.dialog
@on "menuselect", (d) ->
switch d.e.item.data.dataid
when "#{me.name}-about" then alert "About " + me.pid + me.name

View File

@ -0,0 +1,85 @@
class BaseDialog extends this.OS.GUI.BaseModel
constructor: (name) ->
super name
@parent = undefined
@modal = false
@handler = undefined
quit: () ->
evt = new _GUI.BaseEvent("exit")
@onexit(evt)
if not evt.prevent
delete @.observable
@parent.dialog = undefined if @parent
($ @scheme).remove() if @scheme
@dialog.quit() if @dialog
meta: () ->
@parent.meta()
show: () ->
@trigger 'focus'
($ @scheme).css "z-index", window._zindex+2
hide: () ->
@trigger 'hide'
BaseDialog.type = 3
this.OS.GUI.BaseDialog = BaseDialog
###
this dialog rende a tag as main content
and a list of buttons, the behaviour of
the button is specified by user. The conf
object is in the follow form
{
tag: <tag_name>,
buttons:[
{
label: 'buton label',
onclick: function(d){...}
}, ...
]
}
###
class BasicDialog extends BaseDialog
constructor: ( name, @conf ) ->
super name
html = "<afx-app-window data-id = 'dia-window' apptitle='#{name}' width='#{@conf.width}' height='#{@conf.height}'>
<afx-hbox>"
html += "<#{@conf.tag} data-id = 'content'></#{@conf.tag}>"
html += "<div data-height = '40' style='padding:5px; text-align:right;'>"
html += "<afx-button data-id = 'bt#{k}' text = '#{v.label}' style='margin-left:5px;'></afx-button>" for k,v of @conf.buttons
html += "</div></afx-hbox></afx-app-window>"
#render the html
_GUI.htmlToScheme html, @, @host
main: () ->
@scheme.set "minimizable", false
me = @
f = (_v) -> () -> _v.onclick me
# bind action to button
( (me.find "bt#{k}").set "onbtclick", f(v) ) for k, v of @conf.buttons
this.OS.GUI.BasicDialog = BasicDialog
class CalendarDialog extends BasicDialog
constructor: () ->
super "CalendarDialog", {
tag: 'afx-calendar-view',
width: 300,
height: 220,
buttons: [
{
label: 'Ok',
onclick: (d) ->
date = (d.find "content").get "selectedDate"
if date
d.handler date if d.handler
d.quit()
else
d.notify "Please select a date"
},
{
label: 'Cancel',
onclick: (d) -> d.quit()
}
]
}
this.OS.register "CalendarDialog", CalendarDialog

View File

@ -1,24 +1,21 @@
self = this
_PM = self.OS.PM
_APP = self.OS.APP
_MAIL = self.OS.courrier
_GUI = self.OS.GUI
class BaseModel
constructor: (@name) ->
@observable = riot.observable()
@_api = self.OS.API
me = @
@on "exit", () -> me.quit()
@parent = "#desktop"
@host = "#desktop"
@dialog = undefined
render: (p) ->
_GUI.loadScheme p, @, @parent
_GUI.loadScheme p, @, @host
quit: () ->
evt = new _GUI.BaseEvent("exit")
@onexit(evt)
if not evt.prevent
delete @.observable
@dialog.quit() if @dialog
_PM.kill @
init: ->
@ -29,11 +26,23 @@ class BaseModel
trigger: (e, d) -> @observable.trigger e, d
subscribe: (e, f) -> _MAIL.on e, f, @
subscribe: (e, f) -> _courrier.on e, f, @
openDialog: (d, f) ->
if @dialog
@dialog.show()
return
if not _GUI.dialog[d]
@error "Dialog #{d} not found"
return
@dialog = new _GUI.dialog[d]()
@dialog.parent = @
@dialog.handler = f
@dialog.pid = @pid
publish: (t, m) ->
mt = @meta()
_MAIL.trigger t, { id: @pid, name: @name, data: { m: m, icon: mt.icon, iconclass: mt.iconclass } }
_courrier.trigger t, { id: @pid, name: @name, data: { m: m, icon: mt.icon, iconclass: mt.iconclass } }
notify: (m) ->
@publish "notification", m

View File

@ -1,5 +1,3 @@
MAIL = this.OS.courrier
_API = this.OS.API
class BaseService extends this.OS.GUI.BaseModel
constructor: (name) ->
super name
@ -13,7 +11,8 @@ class BaseService extends this.OS.GUI.BaseModel
#implement by user
# event registe, etc
# scheme loader
meta: () ->
@
attach: (h) ->
@holder = h

View File

@ -19,7 +19,8 @@ self.OS or=
_courrier.observable.off i.e, i.f for i in _courrier.listeners[app.pid]
delete _courrier.listeners[app.pid]
_courrier.listeners[app.pid] = []
register: (name, x) -> _APP[name] = x
register: (name, x) ->
if x.type is 3 then self.OS.GUI.dialog[name] = x else _APP[name] = x
PM:
pidalloc: 0

View File

@ -1,20 +1,22 @@
self.OS.GUI =
dialog: new Object()
init: () ->
query =
path: 'VFS/get'
data: "#{_GUI.tagPath}/tags.json"
self.OS.API.request query, ()->
htmlToScheme: (html, app, parent) ->
scheme = $.parseHTML html
($ parent).append scheme
riot.mount ($ scheme), { observable: app.observable }
app.scheme = scheme[0]
app.main()
app.show()
loadScheme: (path, app, parent) ->
_API.get path,
(x) ->
return null unless x
scheme = $.parseHTML x
($ parent).append scheme
riot.mount ($ scheme), { observable: app.observable }
app.scheme = scheme[0]
app.main()
app.show()
_GUI.htmlToScheme x, app, parent
, (f) ->
_courrier.trigger "fail",
{id: 0, data: {

View File

@ -2,8 +2,8 @@
<div class = "afx-window-wrapper">
<ul class= "afx-window-top" >
<li class = "afx-window-close" onclick = {close}></li>
<li class = "afx-window-minimize" onclick = {minimize}></li>
<li class = "afx-window-maximize" onclick={maximize}></li>
<li if = {minimizable == true} class = "afx-window-minimize" onclick = {minimize}></li>
<li if = {maximizable == true} class = "afx-window-maximize" onclick={maximize}></li>
<li ref = "dragger" class = "afx-window-title">{ apptitle }</li>
</ul>
<div class = "afx-clear"></div>
@ -15,6 +15,8 @@
<script>
this.apptitle = opts.apptitle || ""
this.minimizable = eval(opts.minimizable) || true
this.maximizable = eval(opts.maximizable) || true
var self = this
var offset = {top:0,left:0}
var desktop_pos = $("#desktop").offset()
@ -24,7 +26,7 @@
var width = opts.width || 400
var height = opts.height || 300
this.root.observable = opts.observable || riot.observable()
if(!window._zidex) window._zidex = 10
if(!window._zindex) window._zindex = 10
this.shown = false
self.root.set = function(k,v)
{
@ -49,15 +51,15 @@
}
this.on('mount', function() {
var left,top
left = 20 + Math.floor(Math.random() * width)
top = 20 + Math.floor(Math.random() * height)
left = 20 + Math.floor(Math.random() * ($("#desktop").width() - width))
top = 20 + Math.floor(Math.random() * ($("#desktop").height() - height))
$(self.refs.window)
.css("position",'absolute')
.css("left",left + "px")
.css("top",top + "px")
.css("width",width + "px")
.css("height", height + "px")
.css("z-index",window._zidex++)
.css("z-index",window._zindex++)
$(self.refs.window).on("mousedown", function(e){
if(self.shown == false)
self.root.observable.trigger("focus")
@ -78,10 +80,10 @@
})
self.root.observable.on("focus",function(){
window._zidex++
window._zindex++
$(self.refs.window)
.show()
.css("z-index",window._zidex)
.css("z-index",window._zindex)
.removeClass("unactive")
self.shown = true
@ -179,6 +181,7 @@
var toggle_window = function()
{
if(!self.maximizable) return;
if(isMaxi == false)
{
history = {

View File

@ -1,43 +1,78 @@
<afx-calendar-view>
<div>{text}</div>
<afx-grid-view style = "height:100%;" ref = "grid" header = {header} observable = {root.observable}> </afx-grid-view>
<div><i class ="prevmonth" onclick={prevmonth}></i>{text}<i onclick={nextmonth} class="nextmonth"></i></div>
<afx-grid-view data-id ={"grid_" + rid} style = "height:100%;" ref = "grid" header = {header} observable = {root.observable}> </afx-grid-view>
<script >
this.header = [{value:"S"},{value:"M"},{value:"T"},{value:"W"},{value:"T"},{value:"F"},{value:"S"}]
this.header = [{value:"Sun"},{value:"Mon"},{value:"Tue"},{value:"Wed"},{value:"Thu"},{value:"Fri"},{value:"Sat"}]
this.root.observable = opts.observable
this.on("mount", function (e) {
calendar(null)
self.refs.grid.root.set("rows",self.rows)
})
this.on("updated", function(e){
if (self.refs.grid.root.observable != self.root.observable)
{
console.log("reset observable")
}
})
var self = this
this.day = 0
this.month = 0
this.year = 0
this.ondayselect = opts.ondayselect
this.rid = $(self.root).attr("data-id") || Math.floor(Math.random() * 100000) + 1
this.selectedDate = undefined
self.root.get = function(k)
{
return self[k]
}
this.on("mount", function (e) {
self.refs.grid.root.observable = self.root.observable
calendar(null)
self.root.observable.on("gridcellselect", function(d){
if(d.id != "grid_" + self.rid) return
if(d.data.value == "") return
var data = {id:self.rid, data:new Date(self.year, self.month,d.data.value)};
if(self.ondayselect)
self.ondayselect(data)
self.selectedDate = data.data
self.root.observable.trigger("dayselect",data)
})
})
prevmonth()
{
self.selectedDate = undefined
this.month--
if(this.month < 0)
{
this.month = 11
this.year--
}
calendar(new Date(this.year, this.month,1))
}
nextmonth()
{
self.selectedDate = undefined
this.month++
if(this.month > 11)
{
this.month = 0
this.year++
}
calendar(new Date(this.year, this.month,1))
}
var calendar = function (date) {
if (date === null)
date = new Date()
day = date.getDate()
month = date.getMonth()
year = date.getFullYear()
self.day = date.getDate()
self.month = date.getMonth()
self.year = date.getFullYear()
var now ={ d:(new Date()).getDate(), m:(new Date()).getMonth(), y:(new Date()).getFullYear()}
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
this_month = new Date(year, month, 1)
next_month = new Date(year, month + 1, 1)
this_month = new Date(self.year, self.month, 1)
next_month = new Date(self.year, self.month + 1, 1)
// Find out when this month starts and ends.
first_week_day = this_month.getDay()
days_in_this_month = Math.round((next_month.getTime() - this_month.getTime()) / (1000 * 60 * 60 * 24))
self.text = months[month] + ' ' + year
self.rows = []
self.text = months[self.month] + ' ' + self.year
var rows = []
var row = []
console.log(days_in_this_month)
// Fill the first week of the month with the appropriate number of blanks.
for (week_day = 0; week_day < first_week_day; week_day++)
row.push({value:""})
@ -47,21 +82,23 @@
week_day %= 7
if (week_day == 0)
{
self.rows.push(row)
rows.push(row)
row =[]
}
// Do something different for the current day.
//if (day == day_counter)
// calendar_html += '<td style="text-align: center;"><b>' + day_counter + '</b></td>';
//else
// calendar_html += '<td style="background-color:9999cc; color:000000; text-align: center;"> ' + day_counter + ' </td>';
row.push({value:day_counter})
if (now.d == day_counter && self.month == now.m && self.year == now.y)
row.push({value:day_counter, selected:true})
else
row.push({value:day_counter})
week_day++;
}
for(var i = 0; i <= 7 - row.length;i++)
row.push({value:""})
self.rows.push(row)
rows.push(row)
self.refs.grid.root.set("rows",rows)
}
</script>
</afx-calendar-view>

View File

@ -2,7 +2,7 @@
<afx-grid-row ref="gridhead" rootid = {rid} observable = {root.observable} header="true" class = {grid_row_header:header} if = {header} cols = {header}> </afx-grid-row>
<div ref = "scroller" style="width:100%; overflow:auto;">
<div ref = "container">
<afx-grid-row each={ child, i in rows } class = {selected: child.selected} rootid = {parent.rid} observable = {parent.root.observable} cols = {child} onclick = {parent._select}></afx-grid-row>
<afx-grid-row each={ child, i in rows } class = {selected: child.selected} rootid = {parent.rid} observable = {parent.root.observable} index = {i} cols = {child} onclick = {parent._select} head = {parent.refs.gridhead} ></afx-grid-row>
</div>
</div>
<script>
@ -28,11 +28,12 @@
if(self.header)
{
$(self.refs.scroller).css("height",
$(self.root).height() - $(self.refs.gridhead.root).height()
$(self.root).height() - $(self.refs.gridhead.root).children().first().height()
+ "px")
}
else
$(self.refs.scroller).css("height","100%")
$(self.refs.scroller).css("height",
$(self.root).height() + "px")
}
self.root.get = function(k)
@ -42,24 +43,17 @@
return self[k]
}
if(opts.observable)
this.root.observable = opts.observable
else
{
this.root.observable = riot.observable()
}
this.root.observable = opts.observable || riot.observable()
this.on("mount", function(){
$(self.refs.container)
.css("display","flex")
.css("flex-direction","column")
.css("display","table")
//.css("flex-direction","column")
.css("width","100%")
self.calibrate_size()
this.root.observable.on("resize",function(){
self.calibrate_size()
if(self.refs.gridhead)
self.refs.gridhead.calibrate_size()
})
})
this.on("updated",function(){
@ -68,8 +62,6 @@
if(self.nrow == self.rows.length) return
self.nrow = self.rows.length
self.calibrate_size()
if(self.refs.gridhead)
self.refs.gridhead.calibrate_size()
})
_select(event)
{
@ -84,14 +76,15 @@
self.rows[self.selidx].selected = true
this.root.observable.trigger('gridselect',data)
event.preventUpdate = true
self.update()
event.preventDefault()
self.update()
//event.preventDefault()
}
</script>
</afx-grid-view>
<afx-grid-row>
<div style = "flex-grow:1;" each = { child,i in cols } class = {string:typeof child.value == "string", number: typeof child.value == "number"} >
<div style = {!header? "display: table-cell;" :""} onclick = {parent._cell_select} each = { child,i in cols } class = {string:typeof child.value == "string", number: typeof child.value == "number", cellselected: parent._auto_cell_select(child,i)} >
<i if={child.iconclass} class = {child.iconclass} ></i>
<i if={child.icon} class="icon-style" style = { "background: url("+child.icon+");background-size: 100% 100%;background-repeat: no-repeat;" }></i>
{child.value}
@ -100,58 +93,112 @@
this.cols = opts.cols || []
var self = this
this.rid = opts.rootid
this.observable = opts.observable
this.index = opts.index
this.header = opts.header||false
this.calibrate_size = function()
this.head = opts.head
this.selidx = -1;
self.observable = opts.observable
this.colssize = []
var update_header_size = function()
{
if(!self.cols || self.cols.length == 0 || !self.observable) return
if(!self.cols || self.cols.length == 0) return
var totalw = $(self.root).parent().width()
if(totalw == 0) return
var ocw = 0
var nauto = 0
var dist = []
self.colssize = []
$.each(self.cols, function(i,e){
if(e.width)
{
dist.push(e.width)
self.colssize.push(e.width)
ocw += e.width
}
else
{
dist.push(-1)
self.colssize.push(-1)
nauto++
}
})
if(nauto > 0)
{
var cellw = (totalw - ocw)/ nauto
$.each(dist,function(i,e){
if(e == -1) dist[i] = cellw
})
var cellw = parseInt((totalw - ocw)/ nauto)
$.each(self.colssize,function(i,e){if(e == -1) self.colssize[i] = cellw})
}
self.observable.trigger("cellresize",{id:self.rid,data:dist})
calibrate_size()
}
self.observable.on("cellresize",function(d){
if(d.id && d.id == self.rid)
{
var i = 0
$(self.root)
.children()
.each(function(){
$(this).css("width", d.data[i]+"px")
i++
})
}
})
this.on("mount", function(){
var calibrate_size = function()
{
var i = 0
$(self.root)
.css("display","flex")
.css("flex-direction","row")
.css("width","100%")
.children()
.each(function(){
$(this).css("width", self.colssize[i]+"px")
i++
})
}
this.on("updated", function(){
if(self.header)
self.calibrate_size()
update_header_size()
else if(self.head && self.index == 0)
{
self.colssize = self.head.colssize
calibrate_size()
}
})
this.on("mount", function(){
if (self.header)
{
$(self.root)
.css("display", "flex")
.css("flex-direction", "row")
update_header_size()
}
else
{
$(self.root)
.css("display","table-row")
//.css("flex-direction","row")
.css("width","100%")
if(self.head && self.index == 0)
{
self.colssize = self.head.colssize
calibrate_size()
}
}
self.observable.on("gridcellselect", function(data){
if(data.id != self.rid || self.selidx == -1) return;
if(data.row != self.index)
{
self.cols[self.selidx].selected = false
self.selidx = -1
}
})
})
_cell_select(event)
{
if(self.header) return;
if(self.selidx != -1)
{
self.cols[self.selidx].selected = false
self.selidx = -1
}
self.cols[event.item.i].selected = true
}
_auto_cell_select(child,i)
{
if(!child.selected || self.header) return false;
if(self.selidx == i) return true;
var data = {
id:self.rid,
data:child,
col:i,
row:self.index}
self.selidx = i
self.observable.trigger("gridcellselect",data)
return true;
}
</script>
</afx-grid-row>

View File

@ -1,5 +1,4 @@
<afx-app-window data-id = "am-window" apptitle="" width="400" height="300">
<afx-vbox>
<afx-hbox>
<afx-grid-view data-id = "mygrid"></afx-grid-view>
<afx-button data-height="30" data-id = "btkill" text = "Kill process" iconclass="fa fa-times"></afx-button>

View File

@ -5,8 +5,8 @@ class DummyApp extends this.OS.GUI.BaseApplication
main: () ->
self = @
@on "btclick", (e)->
self.notify "this is a dummy notify"
_GUI.pushService "Budgy"
#_GUI.pushService "Budgy"
self.openDialog "CalendarDialog", (d) -> console.log d
@on "resize", (w,h)->
console.log "#{self.name}: resize"
#@on "listselect", (i)->
@ -15,6 +15,8 @@ class DummyApp extends this.OS.GUI.BaseApplication
console.log self.name,i
@on "focus", ()->
console.log self.name, "is focused"
@on "dayselect", (e) -> console.log "cellselected", e
@on "gridselect", (e) -> console.log "GRID selected", e
tree = @find "mytree"
@scheme.set "apptitle", "Terminal"

View File

@ -1,4 +1,4 @@
<afx-app-window apptitle="Preview" width="600" height="600">
<afx-app-window apptitle="Preview" width="600" height="400">
<afx-vbox>
<afx-tree-view data-id="mytree"> </afx-tree-view>
<afx-hbox>

View File

@ -37,7 +37,6 @@ class NotePad extends this.OS.GUI.BaseApplication
mode: m.theme,
selected: if m.theme is "ace/theme/monokai" then true else false
} for k, m of themes.themesByName
console.log themes.themesByName
themelist.set "items", ldata
themelist.set "onlistselect", (e) ->
me.editor.setTheme e.data.mode
@ -49,7 +48,7 @@ class NotePad extends this.OS.GUI.BaseApplication
l = me.editor.session.getLength()
$(stat).html "Row #{c.row}, col #{c.column}, lines: #{l}"
stup(0)
@.editor.getSession().selection.on "changeCursor", (e)->stup(e)
@.editor.getSession().selection.on "changeCursor", (e) -> stup(e)
@on "resize", () -> me.editor.resize()
@on "focus", () -> me.editor.focus()
@ -64,4 +63,4 @@ class NotePad extends this.OS.GUI.BaseApplication
}]
menu
NotePad.singleton = false
this.OS.register "NotePad",NotePad
this.OS.register "NotePad", NotePad

View File

@ -14,7 +14,7 @@ class Calendar extends this.OS.GUI.BaseService
me.update()
awake: (e) ->
console.log @name,@pid
@.openDialog "CalendarDialog", (d) ->
# do nothing
cleanup: (evt) ->
console.log "cleanup for quit"

View File

@ -12,46 +12,44 @@ class PushNotification extends this.OS.GUI.BaseService
main: ->
me = @
mfeed = @find "notifeed"
@mlist = @find "notifylist"
@mfeed = @find "notifeed"
@nzone = @find "notifyzone"
mlist = @find "notifylist"
(@find "btclear").set "onbtclick", (e) -> mlist.set "items", []
(@find "btclear").set "onbtclick", (e) -> me.mlist.set "items", []
#mlist.set "onlistselect", (e) -> console.log e
@subscribe "notification", (o) ->
d = {
header: "#{o.name} (#{o.id})"
text: "INFO: #{o.name} (#{o.id}): #{o.data.m}",
lite: o.data.m
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
mlist.push d, true
me.notifeed d, mfeed
@subscribe "fail", (o) ->
d = {
header: "#{o.name} (#{o.id})"
text: "FAIL: #{o.name} (#{o.id}): #{o.data.m}",
lite: o.data.m
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
mlist.push d, true
me.notifeed d, mfeed
@subscribe "notification", (o) -> me.pushout 'INFO', o
@subscribe "fail", (o) -> me.pushout 'FAIL', o
@subscribe "error", (o) -> me.pushout 'ERROR', o
($ @nzone).css "right", 0
.css "top", "-3px"
.css "height", ""
.css "bottom", "0"
.hide()
($ mfeed).css "right", "5px"
($ @mfeed).css "right", "5px"
.css "top", "0"
notifeed: (d, mfeed) ->
mfeed.push d, true
($ mfeed).show()
pushout: (s, o, mfeed) ->
d = {
text: "#{o.name} (#{o.id}) - #{s}: #{o.data.m}",
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
d1 = {
header: "#{o.name} (#{o.id})"
text: "#{s}: #{o.data.m}",
icon: o.data.icon,
iconclass: o.data.iconclass,
closable: true }
@mlist.push d, true
@notifeed d1
notifeed: (d) ->
me = @
@mfeed.push d, true
($ @mfeed).show()
timer = setTimeout () ->
mfeed.remove d, true
me.mfeed.remove d, true
clearTimeout timer
, 3000

View File

@ -0,0 +1,53 @@
afx-calendar-view div{
text-align: center;
background-color: white;
}
afx-calendar-view > div {
font-weight: bold;
}
afx-calendar-view i.prevmonth, afx-calendar-view i.nextmonth{
display: inline-block;
width: 16px;
height: 16px;
cursor: pointer;
}
afx-calendar-view i.prevmonth{
margin-right: 20px;
}
afx-calendar-view i.nextmonth{
margin-left: 20px;
}
afx-calendar-view i.prevmonth:before{
content: "\f104";
font-family: "FontAwesome";
font-size: 16px;
font-style: normal;
color: #414339;
/*position:absolute;
top:25%;
right:5px;*/
}
afx-calendar-view i.nextmonth:before{
content: "\f105";
font-family: "FontAwesome";
font-size: 16px;
font-style: normal;
color: #414339;
margin-left: 20px;
/*position:absolute;
top:25%;
right:5px;*/
}
afx-calendar-view afx-grid-view afx-grid-row.selected{
background-color: white;
color:#414339;
}
afx-calendar-view afx-grid-view afx-grid-row .cellselected{
background-color: #116cd6;
color:white;
border-radius: 6px;
}

View File

@ -7,6 +7,7 @@ html,body{
height: 100%;
background-image: url(wallpaper.jpg);
background-size: cover;
overflow: hidden;
}
#wrapper{
margin: 0;