Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
itminedu
agkyra
Commits
84db18c6
Commit
84db18c6
authored
Mar 30, 2015
by
Stavros Sachtouris
Committed by
Giorgos Korfiatis
Oct 19, 2015
Browse files
Implement settings GUI window and functionalities
parent
d5f7bfe8
Changes
8
Hide whitespace changes
Inline
Side-by-side
agkyra/exclude.cnf
0 → 100644
View file @
84db18c6
.*
lalaumpa
agkyra/gui/about.html
View file @
84db18c6
...
...
@@ -8,7 +8,7 @@
<style>
.box
{
margin
:
0
auto
;
width
:
9
5
%
;
width
:
9
0
%
;
height
:
256px
;
overflow
:
auto
;
background
:
#e0e0e0
;
...
...
@@ -22,9 +22,9 @@
<h3>
Agkyra... it syncs
</h3>
<p><b>
Agkyra
</b>
is a minimal syncing client for Pithos+.
<br/>
It syncs a Pithos+ container with a local folder.
</p>
<p
class=
"disclaimer"
>
Developed and supported by the Okeanos/Synnefo development team of GRNET
<br/><b>
okeanos-dev@grnet.gr
</b></p>
<p
class=
"disclaimer"
>
Developed and supported by the Okeanos/Synnefo development team of GRNET
<br/><b>
contact:
okeanos-dev@grnet.gr
</b></p>
<h3
class=
"disclaimer"
>
Copyright
2015: Greek Research and Technology Network
<br/>
Licensed under:
</h3>
<h3
class=
"disclaimer"
>
(C)
2015: Greek Research and Technology Network
<br/>
Licensed under:
</h3>
<embed
class=
"box"
src=
"COPYRIGHT"
/>
</div>
<footer
class=
"footer js-footer"
>
...
...
agkyra/gui/menu.html
0 → 100644
View file @
84db18c6
<!DOCTYPE html>
<html>
<head><title>
GUI for Agkyra Pithos+ Syncing Client
</title></head>
<body>
<script
src=
"protocol.js"
></script>
<script
src=
"settings.js"
></script>
<script
type=
"text/javascript"
>
// Setup GUI
var
windows
=
{
"
settings
"
:
null
,
"
about
"
:
null
,
"
index
"
:
gui
.
Window
.
get
()
}
function
closeWindows
()
{
for
(
win
in
windows
)
if
(
windows
[
win
])
windows
[
win
].
close
();
}
// GUI components
var
tray
=
new
gui
.
Tray
({
// tooltip: 'Paused (0% synced)',
title
:
'
Agkyra syncs with Pithos+
'
,
icon
:
'
images/tray.png
'
});
var
menu
=
new
gui
.
Menu
();
// Progress and Pause
var
start_syncing
=
'
Start Syncing
'
;
var
start_icon
=
'
images/play.png
'
;
var
pause_syncing
=
'
Pause Syncing
'
;
var
paused
=
true
;
progress_item
=
new
gui
.
MenuItem
({
// progress menu item
label
:
'
Initializing
'
,
type
:
'
normal
'
,
enabled
:
false
});
menu
.
append
(
progress_item
);
menu
.
append
(
new
gui
.
MenuItem
({
type
:
'
separator
'
}));
pause_item
=
new
gui
.
MenuItem
({
// pause menu item
icon
:
'
images/play_pause.png
'
,
label
:
''
,
type
:
'
normal
'
,
click
:
function
()
{
if
(
paused
)
{
post_start
(
socket
);}
else
{
post_pause
(
socket
);}
}
});
pause_item
.
enabled
=
false
;
menu
.
append
(
pause_item
);
// Update progress
window
.
setInterval
(
function
()
{
var
status
=
globals
[
'
status
'
];
var
new_progress
=
progress_item
.
label
;
var
new_pause
=
pause_item
.
label
;
var
menu_modified
=
false
;
if
(
status
[
'
paused
'
]
!==
null
)
{
switch
(
pause_item
.
label
)
{
case
pause_syncing
:
if
(
status
[
'
paused
'
])
{
// Update to "Paused - start syncing"
paused
=
true
;
new_pause
=
start_syncing
;
menu_modified
=
true
;
}
// else continue syncing
new_progress
=
status
[
'
progress
'
]
+
'
%
'
+
'
synced
'
;
break
;
case
start_syncing
:
if
(
status
[
'
paused
'
])
return
;
// else update to "Syncing - pause syncing"
paused
=
false
;
new_pause
=
pause_syncing
;
new_progress
=
status
[
'
progress
'
]
+
'
%
'
+
'
synced
'
;
menu_modified
=
true
;
break
;
default
:
if
(
status
[
'
paused
'
])
{
new_pause
=
start_syncing
;
paused
=
true
;}
else
{
new_pause
=
pause_syncing
;
paused
=
false
;}
new_progress
=
status
[
'
progress
'
]
+
'
%
'
+
'
synced
'
;
pause_item
.
enabled
=
true
;
menu_modified
=
true
;
}
}
if
(
new_pause
!=
pause_item
.
label
)
{
pause_item
.
label
=
new_pause
;
menu_modified
=
true
;
}
if
(
new_progress
!=
progress_item
.
label
)
{
progress_item
.
label
=
new_progress
;
menu_modified
=
true
;
}
if
(
menu_modified
)
{
if
(
paused
)
progress_item
.
label
+=
'
- paused
'
;
tray
.
menu
=
menu
;
}
get_status
(
socket
);
},
1500
);
// Menu actions contents
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
Open local folder
'
,
icon
:
'
images/folder.png
'
,
click
:
function
()
{
var
dir
=
globals
[
'
settings
'
][
'
directory
'
];
console
.
log
(
'
Open
'
+
dir
);
gui
.
Shell
.
showItemInFolder
(
dir
);
}
}));
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
Launch Pithos+ page
'
,
icon
:
'
images/pithos.png
'
,
click
:
function
()
{
var
pithos_url
=
globals
[
'
settings
'
][
'
pithos_url
'
];
console
.
log
(
'
Visit
'
+
pithos_url
);
gui
.
Shell
.
openExternal
(
pithos_url
);
}
}));
// Settings and About
menu
.
append
(
new
gui
.
MenuItem
({
type
:
'
separator
'
}));
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
Settings
'
,
icon
:
'
images/settings.png
'
,
click
:
function
()
{
export_settings
(
globals
.
settings
);
if
(
windows
[
'
settings
'
])
windows
[
'
settings
'
].
close
();
windows
[
'
settings
'
]
=
gui
.
Window
.
open
(
"
settings.html
"
,
{
toolbar
:
false
,
focus
:
true
,
width
:
841
,
height
:
520
,
});
windows
[
'
settings
'
].
on
(
'
closed
'
,
function
()
{
new_settings
=
import_settings
();
console
.
log
(
'
Settings windows is closed, PUT
'
);
put_settings
(
socket
,
new_settings
);
get_settings
(
socket
);
});
},
}));
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
About
'
,
icon
:
'
images/about.png
'
,
click
:
function
()
{
if
(
windows
[
'
about
'
])
windows
[
'
about
'
].
close
();
windows
[
'
about
'
]
=
gui
.
Window
.
open
(
"
about.html
"
,
{
toolbar
:
false
,
resizable
:
false
,
focus
:
true
,
width
:
679
,
height
:
420
});
}
}));
// Quit
menu
.
append
(
new
gui
.
MenuItem
({
type
:
'
separator
'
}));
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
Quit Agkyra
'
,
icon
:
'
images/exit.png
'
,
click
:
function
()
{
post_shutdown
(
socket
);}
}));
tray
.
menu
=
menu
;
</script>
</body>
</html>
\ No newline at end of file
agkyra/gui/package.json
View file @
84db18c6
{
"name"
:
"Agkyra"
,
"main"
:
"
index
.html"
,
"main"
:
"
menu
.html"
,
"description"
:
"A Pithos+ Syncing Client for Desktop"
,
"version"
:
0.0
,
"window"
:
{
...
...
agkyra/gui/protocol.js
View file @
84db18c6
...
...
@@ -10,7 +10,6 @@ function send_json(socket, msg) {
socket
.
send
(
JSON
.
stringify
(
msg
))
}
var
requests
=
[]
var
globals
=
{
'
settings
'
:
{
'
token
'
:
null
,
...
...
@@ -25,7 +24,6 @@ var globals = {
// Protocol: requests ::: responses
function
post_gui_id
(
socket
)
{
requests
.
push
(
'
post gui_id
'
);
send_json
(
socket
,
{
"
method
"
:
"
post
"
,
"
gui_id
"
:
cnf
[
'
gui_id
'
]})
}
// expected response: {"ACCEPTED": 202}
...
...
@@ -36,30 +34,25 @@ function post_shutdown(socket) {
function
post_pause
(
socket
)
{
console
.
log
(
'
SEND post pause
'
);
requests
.
push
(
'
post pause
'
);
send_json
(
socket
,
{
'
method
'
:
'
post
'
,
'
path
'
:
'
pause
'
});
}
// expected response: {"OK": 200}
function
post_start
(
socket
)
{
console
.
log
(
'
SEND post start
'
);
requests
.
push
(
'
post start
'
);
send_json
(
socket
,
{
'
method
'
:
'
post
'
,
'
path
'
:
'
start
'
});
}
// expected response: {"OK": 200}
function
get_settings
(
socket
)
{
requests
.
push
(
'
get settings
'
);
send_json
(
socket
,
{
'
method
'
:
'
get
'
,
'
path
'
:
'
settings
'
});
}
// expected response: {settings JSON}
function
put_settings
(
socket
,
new_settings
)
{
requests
.
push
(
'
put settings
'
);
new_settings
[
'
method
'
]
=
'
put
'
;
new_settings
[
'
path
'
]
=
'
settings
'
;
send_json
(
socket
,
new_settings
);
}
// expected response: {"CREATED": 201}
function
get_status
(
socket
)
{
requests
.
push
(
'
get status
'
);
send_json
(
socket
,
{
'
method
'
:
'
get
'
,
'
path
'
:
'
status
'
});
}
// expected response {"progress": ..., "paused": ...}
...
...
@@ -72,7 +65,8 @@ socket.onopen = function() {
}
socket
.
onmessage
=
function
(
e
)
{
var
r
=
JSON
.
parse
(
e
.
data
)
switch
(
requests
.
shift
())
{
//console.log('RECV: ' + r['action'])
switch
(
r
[
'
action
'
])
{
case
'
post gui_id
'
:
if
(
r
[
'
ACCEPTED
'
]
===
202
)
{
get_settings
(
this
);
...
...
@@ -101,7 +95,8 @@ socket.onmessage = function(e) {
console
.
log
(
'
Helper:
'
+
JSON
.
stringify
(
r
));
}
break
;
case
'
get status
'
:
globals
[
'
status
'
]
=
r
;
case
'
get status
'
:
globals
[
'
status
'
]
=
r
;
break
;
default
:
console
.
log
(
'
Incomprehensible response
'
+
r
);
...
...
@@ -110,153 +105,9 @@ socket.onmessage = function(e) {
};
socket
.
onerror
=
function
(
e
)
{
console
.
log
(
'
GUI - helper error
'
+
e
.
data
);
gui
.
Window
.
get
().
close
();
close
Window
s
();
}
socket
.
onclose
=
function
()
{
console
.
log
(
'
Connection to helper closed
'
);
closeWindows
();
}
// Setup GUI
var
windows
=
{
"
settings
"
:
null
,
"
about
"
:
null
,
"
index
"
:
gui
.
Window
.
get
()
}
function
closeWindows
()
{
for
(
win
in
windows
)
if
(
windows
[
win
])
windows
[
win
].
close
();
}
// GUI components
var
tray
=
new
gui
.
Tray
({
// tooltip: 'Paused (0% synced)',
title
:
'
Agkyra syncs with Pithos+
'
,
icon
:
'
images/tray.png
'
});
var
menu
=
new
gui
.
Menu
();
// Progress and Pause
var
start_syncing
=
'
Start Syncing
'
;
var
start_icon
=
'
images/play.png
'
;
var
pause_syncing
=
'
Pause Syncing
'
;
var
paused
=
true
;
progress_item
=
new
gui
.
MenuItem
({
// progress menu item
label
:
'
Initializing
'
,
type
:
'
normal
'
,
enabled
:
false
});
menu
.
append
(
progress_item
);
menu
.
append
(
new
gui
.
MenuItem
({
type
:
'
separator
'
}));
pause_item
=
new
gui
.
MenuItem
({
// pause menu item
icon
:
'
images/play_pause.png
'
,
label
:
''
,
type
:
'
normal
'
,
click
:
function
()
{
if
(
paused
)
{
post_start
(
socket
);}
else
{
post_pause
(
socket
);}
}
});
pause_item
.
enabled
=
false
;
menu
.
append
(
pause_item
);
// Update progress
window
.
setInterval
(
function
()
{
var
status
=
globals
[
'
status
'
];
var
new_progress
=
progress_item
.
label
;
var
new_pause
=
pause_item
.
label
;
var
menu_modified
=
false
;
if
(
status
[
'
paused
'
]
!==
null
)
{
switch
(
pause_item
.
label
)
{
case
pause_syncing
:
if
(
status
[
'
paused
'
])
{
// Update to "Paused - start syncing"
paused
=
true
;
new_pause
=
start_syncing
;
menu_modified
=
true
;
}
// else continue syncing
new_progress
=
status
[
'
progress
'
]
+
'
%
'
+
'
synced
'
;
break
;
case
start_syncing
:
if
(
status
[
'
paused
'
])
return
;
// else update to "Syncing - pause syncing"
paused
=
false
;
new_pause
=
pause_syncing
;
new_progress
=
status
[
'
progress
'
]
+
'
%
'
+
'
synced
'
;
menu_modified
=
true
;
break
;
default
:
if
(
status
[
'
paused
'
])
{
new_pause
=
start_syncing
;
paused
=
true
;}
else
{
new_pause
=
pause_syncing
;
paused
=
false
;}
new_progress
=
status
[
'
progress
'
]
+
'
%
'
+
'
synced
'
;
pause_item
.
enabled
=
true
;
menu_modified
=
true
;
}
}
if
(
new_pause
!=
pause_item
.
label
)
{
pause_item
.
label
=
new_pause
;
menu_modified
=
true
;
}
if
(
new_progress
!=
progress_item
.
label
)
{
progress_item
.
label
=
new_progress
;
menu_modified
=
true
;
}
if
(
menu_modified
)
{
if
(
paused
)
progress_item
.
label
+=
'
- paused
'
;
tray
.
menu
=
menu
;
}
get_status
(
socket
);
},
1500
);
// Menu actions contents
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
Open local folder
'
,
icon
:
'
images/folder.png
'
,
click
:
function
()
{
var
dir
=
globals
[
'
settings
'
][
'
directory
'
];
console
.
log
(
'
Open
'
+
dir
);
gui
.
Shell
.
showItemInFolder
(
dir
);
}
}));
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
Launch Pithos+ page
'
,
icon
:
'
images/pithos.png
'
,
click
:
function
()
{
var
pithos_url
=
globals
[
'
settings
'
][
'
pithos_url
'
];
console
.
log
(
'
Visit
'
+
pithos_url
);
gui
.
Shell
.
openExternal
(
pithos_url
);
}
}));
// Settings and About
menu
.
append
(
new
gui
.
MenuItem
({
type
:
'
separator
'
}));
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
Settings
'
,
icon
:
'
images/settings.png
'
,
click
:
function
()
{
if
(
windows
[
'
settings
'
])
windows
[
'
settings
'
].
close
();
windows
[
'
settings
'
]
=
gui
.
Window
.
open
(
"
settings.html
"
,
{
"
toolbar
"
:
false
,
"
focus
"
:
true
});
}
}));
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
About
'
,
icon
:
'
images/about.png
'
,
click
:
function
()
{
if
(
windows
[
'
about
'
])
windows
[
'
about
'
].
close
();
windows
[
'
about
'
]
=
gui
.
Window
.
open
(
"
about.html
"
,
{
"
toolbar
"
:
false
,
"
resizable
"
:
false
,
"
focus
"
:
true
});
}
}));
// Quit
menu
.
append
(
new
gui
.
MenuItem
({
type
:
'
separator
'
}));
menu
.
append
(
new
gui
.
MenuItem
({
label
:
'
Quit Agkyra
'
,
icon
:
'
images/exit.png
'
,
click
:
function
()
{
post_shutdown
(
socket
);}
}));
tray
.
menu
=
menu
;
agkyra/gui/settings.html
View file @
84db18c6
<!DOCTYPE html>
<html>
<head>
<title>
User Settings
</title>
<link
rel=
"stylesheet"
href=
"static/stylesheets/normalize.css"
/>
<link
rel=
"stylesheet"
href=
"static/stylesheets/main.css"
/>
<script
src=
"static/js/jquery.js"
></script>
<script
src=
"static/js/common.js"
></script>
</head>
<script
src=
"settings.js"
></script>
<script
type=
"text/javascript"
>
var
fs
=
require
(
'
fs
'
);
var
exclude
=
null
;
$
(
document
).
ready
(
function
()
{
var
url
=
get_setting
(
'
url
'
);
if
(
url
)
$
(
'
#cloud-url
'
).
val
(
url
);
var
token
=
get_setting
(
'
token
'
);
if
(
token
)
$
(
'
#token
'
).
val
(
token
);
var
container
=
get_setting
(
'
container
'
);
if
(
container
)
$
(
'
#container
'
).
val
(
container
);
var
directory
=
get_setting
(
'
directory
'
);
if
(
directory
)
$
(
'
#directory
'
).
html
(
directory
);
exclude
=
get_setting
(
'
exclude
'
);
if
(
exclude
)
$
(
'
#exclude
'
).
val
(
fs
.
readFileSync
(
exclude
,
encoding
=
'
utf-8
'
));
});
function
update_exclude
(
new_content
)
{
if
(
exclude
)
fs
.
writeFile
(
exclude
,
new_content
);
}
</script>
</head>
<body>
<div
class=
"row js-main"
>
<header>
...
...
@@ -23,18 +44,20 @@
</div>
<div
class=
"small-9 columns"
>
<input
type=
"text"
id=
"cloud-url"
placeholder=
"Authentication URL"
>
<small
class=
"error"
>
Invalid entry
</small>
<input
type=
"text"
id=
"cloud-url"
placeholder=
"Authentication URL"
onchange=
"set_setting('url', $(this).val())"
>
<small
class=
"error"
style=
"visibility: hidden"
>
Invalid entry
</small>
</div>
</div>
<div
class=
"row error"
>
<div
class=
"small-3 columns"
>
<label
for=
"token"
class=
"right inline"
>
T
oken
</label>
<label
for=
"token"
class=
"right inline"
>
User t
oken
</label>
</div>
<div
class=
"small-9 columns"
>
<input
type=
"text"
id=
"token"
placeholder=
"User token"
>
<small
class=
"error"
>
Invalid entry
</small>
<input
type=
"text"
id=
"token"
placeholder=
"User token"
onchange=
"set_setting('token', $(this).val())"
>
<small
class=
"error"
style=
"visibility: hidden"
>
Invalid entry
</small>
</div>
</div>
</fieldset>
...
...
@@ -45,31 +68,43 @@
<label
for=
"container"
class=
"right inline"
>
Remote container
</label>
</div>
<div
class=
"small-9 columns"
>
<input
type=
"text"
id=
"container"
value=
"pithos"
>
<input
type=
"text"
id=
"container"
placeholder=
"Pithos+ container"
onchange=
"set_setting('container', $(this).val())"
>
</div>
</div>
<div
class=
"row"
>
<div
class=
"small-3 columns"
>
<label
for=
""
class=
"right inline"
>
Local directory
</label>
<label
for=
"
directory
"
class=
"right inline"
>
Local directory
</label>
</div>
<div
class=
"small-9 columns"
id=
"directory"
>
No dir chosen
</div>
</div>
<div
class=
"row"
>
<div
class=
"small-3 columns"
>
Change it:
</div>
<div
class=
"small-9 columns"
>
<input
type=
"file"
nwdirectory
/>
<!-- TODO: change the label of this field -->
<input
type=
"file"
nwdirectory
onchange=
"
$('#directory').html($(this).val());
set_setting('directory', $(this).val());
"
/>
</div>
<script>
var
gui
=
require
(
'
nw.gui
'
);
</script>
</div>
<div
class=
"row"
>
<div
class=
"small-3 columns"
>
<label
for=
""
class=
"right inline"
>
Exclude these items from syncing
</label>
</div>
<div
class=
"small-9 columns"
>
<textarea>
tmp/
skata*
</textarea>
<textarea
id=
"exclude"
onchange=
"update_exclude($(this).val())"
>
</textarea>
</div>
</div>
</fieldset>
<div
class=
"clearfix"
>
<a
class=
"button right"
>
Sync
</a>
</div>
<!--<div class="clearfix">
<a id="sync_button" class="button right"
onclick="window.close();">OK</a>
</div> -->
</div>
<div
class=
"small-4 columns"
>
...
...
agkyra/gui/settings.js
0 → 100644
View file @
84db18c6
/**
* Methods for accessing settings between documents
*/
function
export_settings
(
settings
)
{
global
.
settings
=
settings
;
}
function
import_settings
()
{
return
global
.
settings
;
}
function
get_setting
(
key
)
{
return
global
.
settings
[
key
];
}
function
set_setting
(
key
,
val
)
{
global
.
settings
[
key
]
=
val
;
}
agkyra/protocol.py
View file @
84db18c6
from
ws4py.websocket
import
WebSocket
import
json
import
logging
from
os.path
import
abspath
LOG
=
logging
.
getLogger
(
__name__
)
...
...
@@ -11,23 +12,25 @@ class WebSocketProtocol(WebSocket):
-- INTERRNAL HANDSAKE --
GUI: {"method": "post", "gui_id": <GUI ID>}
HELPER: {"ACCEPTED": 202}" or "{"REJECTED": 401}
HELPER: {"ACCEPTED": 202, "method": "post"}" or
"{"REJECTED": 401, "action": "post gui_id"}
-- SHUT DOWN --
GUI: {"method": "post", "path": "shutdown"}
-- PAUSE --
GUI: {"method": "post", "path": "pause"}
HELPER: {"OK": 200} or error
HELPER: {"OK": 200
, "action": "post pause"
} or error
-- start --
GUI: {"method": "post", "path": "start"}
HELPER: {"OK": 200} or error
HELPER: {"OK": 200
, "action": "post start"
} or error
-- GET SETTINGS --
GUI: {"method": "get", "path": "settings"}
HELPER:
{
"action": "get settings",
"token": <user token>,
"url": <auth url>,
"container": <container>,
...
...
@@ -45,11 +48,13 @@ class WebSocketProtocol(WebSocket):
"pithos_url": <pithos URL>,
"exclude": <file path>
}
HELPER: {"CREATED": 201} or {<ERROR>: <ERROR CODE>}
HELPER: {"CREATED": 201, "action": "put settings",} or
{<ERROR>: <ERROR CODE>, "action": "get settings",}
-- GET STATUS --
GUI: {"method": "get", "path": "status"}
HELPER: ""progress": <int>, "paused": <boolean>} or {<ERROR>: <ERROR CODE>}
HELPER: {"progress": <int>, "paused": <boolean>, "action": "get status"} or
{<ERROR>: <ERROR CODE>, "action": "get status"}
"""
gui_id
=
None
...
...
@@ -59,7 +64,7 @@ class WebSocketProtocol(WebSocket):
url
=
' https://accounts.okeanos.grnet.gr/identity/v2.0'
,
container
=
'pithos'
,
directory
=
'/tmp/.'
,
exclude
=
'agkyra.log'
,
exclude
=
abspath
(
'exclude.cnf'
)
,
pithos_url
=
'https://pithos.okeanos.grnet.gr/ui/'
)
status
=
dict
(
progress
=
0
,
paused
=
False
)
...
...
@@ -73,6 +78,9 @@ class WebSocketProtocol(WebSocket):
def
get_settings
(
self
):