mirror of
http://git.whoc.org.uk/git/password-manager.git
synced 2024-11-13 07:49:01 +01:00
Interim synchronization with internal repository
This is an intermir commit to share what is going on with the development of the new /delta version.
This commit is contained in:
parent
6dd16d9359
commit
f8da092f3d
@ -117,4 +117,4 @@ Once the index.html files have been built (one for each frontend) and a backend
|
||||
This application has not been fully tested, so there may be still problems due to the new build script or to the new repository structure. So, for the moment, **use it at your own risk!**
|
||||
|
||||
|
||||
[pog]: http://www.phpobjectgenerator.com/
|
||||
[pog]: http://www.phpobjectgenerator.com/
|
File diff suppressed because one or more lines are too long
431
frontend/delta/fonts/IcoMoon/Clipperz Icon font.json
Executable file
431
frontend/delta/fonts/IcoMoon/Clipperz Icon font.json
Executable file
@ -0,0 +1,431 @@
|
||||
{
|
||||
"IcoMoonType": "selection",
|
||||
"icons": [
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M2.259 734.824h279.462v286.917h-279.462v-286.917z",
|
||||
"M2.259 2.259h279.462v286.917h-279.462v-286.917z",
|
||||
"M2.259 368.519h279.462v286.917h-279.462v-286.917z"
|
||||
],
|
||||
"width": 284,
|
||||
"grid": 0,
|
||||
"tags": [
|
||||
"commands"
|
||||
]
|
||||
},
|
||||
"properties": {
|
||||
"order": 22,
|
||||
"id": 0,
|
||||
"prevSize": 32,
|
||||
"code": 58894,
|
||||
"name": "commands",
|
||||
"ligatures": "commands"
|
||||
},
|
||||
"setIdx": 0,
|
||||
"iconIdx": 0
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M667.586 345.635v-338.544h-268.055v338.544l-299.967-121.263-90.486 257.986 310.037 104.527-198.134 262.808 224.514 164.237 184.802-279.685 203.382 279.685 221.11-164.237-203.382-262.808 319.397-107.080-90.486-257.986zM1220.574 2319.317z"
|
||||
],
|
||||
"width": 1080,
|
||||
"grid": 0,
|
||||
"tags": [
|
||||
"logo"
|
||||
]
|
||||
},
|
||||
"properties": {
|
||||
"order": 4,
|
||||
"id": 0,
|
||||
"prevSize": 32,
|
||||
"code": 58884,
|
||||
"name": "logo",
|
||||
"ligatures": "clipperz"
|
||||
},
|
||||
"setIdx": 1,
|
||||
"iconIdx": 0
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M96.188 0h288.562c52.906 0 126.796 30.606 164.204 68.014l446.99 446.99c37.408 37.408 37.408 98.624 0 136.032l-344.91 344.906c-37.408 37.41-98.622 37.41-136.030 0l-446.99-446.988c-37.408-37.41-68.014-111.302-68.014-164.204v-288.562c0-52.904 43.286-96.188 96.188-96.188zM224 320c53.020 0 96-42.98 96-96s-42.98-96-96-96-96 42.98-96 96 42.98 96 96 96z"
|
||||
],
|
||||
"tags": [
|
||||
"tag",
|
||||
"price"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 48,
|
||||
"order": 6,
|
||||
"prevSize": 32,
|
||||
"code": 58885,
|
||||
"name": "tag",
|
||||
"ligatures": "tag"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 49
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M96 64h224c52.8 0 126.546 30.546 163.882 67.882l376.236 376.236c37.334 37.334 37.334 98.428 0 135.764l-280.236 280.234c-37.334 37.336-98.428 37.336-135.764 0l-376.234-376.234c-37.338-37.336-67.884-111.082-67.884-163.882v-224c0-52.8 43.2-96 96-96zM224 384c53.020 0 96-42.98 96-96s-42.98-96-96-96-96 42.98-96 96 42.98 96 96 96zM1001.374 598.626l-342.378 342.378c36.264 19.16 82.462 13.538 112.886-16.888l280.236-280.234c37.334-37.336 37.334-98.43 0-135.764l-376.236-376.236c-37.336-37.336-111.082-67.882-163.882-67.882l489.374 489.372c12.444 12.446 12.444 32.808 0 45.254z"
|
||||
],
|
||||
"width": 1088,
|
||||
"tags": [
|
||||
"tags",
|
||||
"prices"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 49,
|
||||
"order": 1,
|
||||
"prevSize": 32,
|
||||
"code": 58880,
|
||||
"name": "tags",
|
||||
"ligatures": "tags"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 50
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M928 128h-832c-52.8 0-96 43.2-96 96v640c0 52.8 43.2 96 96 96h832c52.8 0 96-43.2 96-96v-640c0-52.8-43.2-96-96-96zM398.74 550.372l-270.74 210.892v-501.642l270.74 290.75zM176.38 256h671.24l-335.62 252-335.62-252zM409.288 561.698l102.712 110.302 102.71-110.302 210.554 270.302h-626.528l210.552-270.302zM625.26 550.372l270.74-290.75v501.642l-270.74-210.892z"
|
||||
],
|
||||
"tags": [
|
||||
"envelope",
|
||||
"mail",
|
||||
"email",
|
||||
"contact",
|
||||
"letter"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 64,
|
||||
"order": 8,
|
||||
"prevSize": 32,
|
||||
"code": 58888,
|
||||
"name": "envelope",
|
||||
"ligatures": "email"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 65
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M658.744 749.256l-210.744-210.746v-282.51h128v229.49l173.256 173.254zM512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 896c-212.078 0-384-171.922-384-384s171.922-384 384-384c212.078 0 384 171.922 384 384 0 212.078-171.922 384-384 384z"
|
||||
],
|
||||
"tags": [
|
||||
"clock",
|
||||
"time",
|
||||
"schedule"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 72,
|
||||
"order": 7,
|
||||
"prevSize": 32,
|
||||
"code": 58887,
|
||||
"name": "clock",
|
||||
"ligatures": "recent"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 73
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M384 128c0-70.692 57.308-128 128-128 70.692 0 128 57.308 128 128 0 70.692-57.308 128-128 128-70.692 0-128-57.308-128-128zM655.53 240.47c0-70.692 57.308-128 128-128s128 57.308 128 128c0 70.692-57.308 128-128 128-70.692 0-128-57.308-128-128zM832 512c0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64zM719.53 783.53c0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64zM448.002 896c-0-0-0-0-0-0 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 0 0 0 0 0 0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64zM176.472 783.53c-0-0-0-0-0-0 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 0 0 0 0 0 0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64zM144.472 240.47c-0-0-0-0-0-0 0-53.019 42.981-96 96-96 53.019 0 96 42.981 96 96 0 0 0 0 0 0 0 53.019-42.981 96-96 96-53.019 0-96-42.981-96-96zM56 512c0-39.765 32.235-72 72-72s72 32.235 72 72c0 39.765-32.235 72-72 72-39.765 0-72-32.235-72-72z"
|
||||
],
|
||||
"tags": [
|
||||
"spinner",
|
||||
"loading",
|
||||
"busy",
|
||||
"wait",
|
||||
"wheel"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 120,
|
||||
"order": 11,
|
||||
"prevSize": 32,
|
||||
"code": 58891,
|
||||
"name": "spinner",
|
||||
"ligatures": "loading"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 121
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M992.262 871.396l-242.552-206.294c-25.074-22.566-51.89-32.926-73.552-31.926 57.256-67.068 91.842-154.078 91.842-249.176 0-212.078-171.922-384-384-384-212.076 0-384 171.922-384 384 0 212.078 171.922 384 384 384 95.098 0 182.108-34.586 249.176-91.844-1 21.662 9.36 48.478 31.926 73.552l206.294 242.552c35.322 39.246 93.022 42.554 128.22 7.356s31.892-92.898-7.354-128.22zM384 640c-141.384 0-256-114.616-256-256s114.616-256 256-256 256 114.616 256 256-114.614 256-256 256z"
|
||||
],
|
||||
"tags": [
|
||||
"search",
|
||||
"magnifier",
|
||||
"lookup",
|
||||
"find"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 127,
|
||||
"order": 5,
|
||||
"prevSize": 32,
|
||||
"code": 58886,
|
||||
"name": "search",
|
||||
"ligatures": "search"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 128
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M832 448h-64v-192c0-141.384-114.616-256-256-256s-256 114.616-256 256v192h-64c-35.2 0-64 28.8-64 64v448c0 35.2 28.8 64 64 64h640c35.2 0 64-28.8 64-64v-448c0-35.2-28.8-64-64-64zM512 832c-35.346 0-64-28.654-64-64s28.654-64 64-64 64 28.654 64 64-28.654 64-64 64zM640 448h-256v-192c0-70.58 57.42-128 128-128s128 57.42 128 128v192z"
|
||||
],
|
||||
"tags": [
|
||||
"lock",
|
||||
"secure",
|
||||
"private",
|
||||
"encrypted"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 136,
|
||||
"order": 9,
|
||||
"prevSize": 32,
|
||||
"code": 58889,
|
||||
"name": "lock",
|
||||
"ligatures": "password"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 137
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M64 192h896v192h-896zM64 448h896v192h-896zM64 704h896v192h-896z"
|
||||
],
|
||||
"tags": [
|
||||
"menu",
|
||||
"list",
|
||||
"items",
|
||||
"lines",
|
||||
"options"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 184,
|
||||
"order": 14,
|
||||
"prevSize": 32,
|
||||
"code": 58881,
|
||||
"name": "menu2",
|
||||
"ligatures": "menu"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 185
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M1014.662 822.66c-0.004-0.004-0.008-0.008-0.012-0.010l-310.644-310.65 310.644-310.65c0.004-0.004 0.008-0.006 0.012-0.010 3.344-3.346 5.762-7.254 7.312-11.416 4.246-11.376 1.824-24.682-7.324-33.83l-146.746-146.746c-9.148-9.146-22.45-11.566-33.828-7.32-4.16 1.55-8.070 3.968-11.418 7.31 0 0.004-0.004 0.006-0.008 0.010l-310.648 310.652-310.648-310.65c-0.004-0.004-0.006-0.006-0.010-0.010-3.346-3.342-7.254-5.76-11.414-7.31-11.38-4.248-24.682-1.826-33.83 7.32l-146.748 146.748c-9.148 9.148-11.568 22.452-7.322 33.828 1.552 4.16 3.97 8.072 7.312 11.416 0.004 0.002 0.006 0.006 0.010 0.010l310.65 310.648-310.65 310.652c-0.002 0.004-0.006 0.006-0.008 0.010-3.342 3.346-5.76 7.254-7.314 11.414-4.248 11.376-1.826 24.682 7.322 33.83l146.748 146.746c9.15 9.148 22.452 11.568 33.83 7.322 4.16-1.552 8.070-3.97 11.416-7.312 0.002-0.004 0.006-0.006 0.010-0.010l310.648-310.65 310.648 310.65c0.004 0.002 0.008 0.006 0.012 0.008 3.348 3.344 7.254 5.762 11.414 7.314 11.378 4.246 24.684 1.826 33.828-7.322l146.746-146.748c9.148-9.148 11.57-22.454 7.324-33.83-1.552-4.16-3.97-8.068-7.314-11.414z"
|
||||
],
|
||||
"tags": [
|
||||
"close",
|
||||
"cancel",
|
||||
"quit",
|
||||
"remove",
|
||||
"cross"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 253,
|
||||
"order": 3,
|
||||
"prevSize": 32,
|
||||
"code": 58882,
|
||||
"name": "close",
|
||||
"ligatures": "failure, failed"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 254
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M864 128l-480 480-224-224-160 160 384 384 640-640z"
|
||||
],
|
||||
"tags": [
|
||||
"checkmark",
|
||||
"tick",
|
||||
"correct",
|
||||
"accept",
|
||||
"ok"
|
||||
],
|
||||
"grid": 16
|
||||
},
|
||||
"properties": {
|
||||
"id": 254,
|
||||
"order": 2,
|
||||
"prevSize": 32,
|
||||
"code": 58883,
|
||||
"name": "checkmark",
|
||||
"ligatures": "done, ok"
|
||||
},
|
||||
"setIdx": 2,
|
||||
"iconIdx": 255
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M819.2 102.4h-410.624c-56.32 0-101.376 45.056-101.376 101.376v410.624c0 56.32 46.080 102.4 102.4 102.4h409.6c56.32 0 102.4-46.080 102.4-102.4v-409.6c0-56.32-46.080-102.4-102.4-102.4zM819.2 614.4h-409.6v-409.6h409.6v409.6zM204.8 512h-102.4v307.2c0 56.32 46.080 102.4 102.4 102.4h307.2v-102.4h-307.2v-307.2z"
|
||||
],
|
||||
"tags": [
|
||||
"popup",
|
||||
"popout",
|
||||
"new window"
|
||||
],
|
||||
"grid": 20
|
||||
},
|
||||
"properties": {
|
||||
"id": 35,
|
||||
"order": 10,
|
||||
"prevSize": 32,
|
||||
"code": 58890,
|
||||
"name": "popup",
|
||||
"ligatures": "url"
|
||||
},
|
||||
"setIdx": 5,
|
||||
"iconIdx": 35
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M512 81.92c-237.568 0-430.080 192.614-430.080 430.080 0 237.568 192.563 430.080 430.080 430.080 237.517 0 430.080-192.563 430.080-430.080 0-237.517-192.563-430.080-430.080-430.080zM564.326 564.326v206.182h-104.653v-206.182h-206.234v-104.653h206.182v-206.234h104.704v206.182h206.182v104.704h-206.182z"
|
||||
],
|
||||
"tags": [
|
||||
"plus",
|
||||
"add",
|
||||
"sum"
|
||||
],
|
||||
"grid": 20
|
||||
},
|
||||
"properties": {
|
||||
"id": 125,
|
||||
"order": 16,
|
||||
"prevSize": 32,
|
||||
"code": 58895,
|
||||
"name": "plus",
|
||||
"ligatures": "add card"
|
||||
},
|
||||
"setIdx": 5,
|
||||
"iconIdx": 125
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M585.574 231.219c-21.402 20.89-230.502 240.435-230.502 240.435-11.418 11.162-17.101 25.754-17.101 40.346s5.683 29.184 17.101 40.346c0 0 209.101 219.546 230.502 240.384 21.402 20.89 59.904 22.323 82.739 0 22.784-22.272 24.576-53.35-0.051-80.64l-191.846-200.090 191.846-200.090c24.627-27.341 22.835-58.419 0.051-80.691-22.886-22.272-61.389-20.89-82.739-0z"
|
||||
],
|
||||
"tags": [
|
||||
"arrow-left",
|
||||
"left",
|
||||
"previous"
|
||||
],
|
||||
"grid": 20
|
||||
},
|
||||
"properties": {
|
||||
"id": 205,
|
||||
"order": 12,
|
||||
"prevSize": 32,
|
||||
"code": 58892,
|
||||
"name": "arrow-left",
|
||||
"ligatures": "back"
|
||||
},
|
||||
"setIdx": 5,
|
||||
"iconIdx": 205
|
||||
},
|
||||
{
|
||||
"icon": {
|
||||
"paths": [
|
||||
"M438.426 231.219c21.402 20.89 230.502 240.435 230.502 240.435 11.469 11.162 17.152 25.754 17.152 40.346s-5.683 29.184-17.152 40.346c0 0-209.101 219.546-230.502 240.384-21.402 20.89-59.853 22.323-82.739 0-22.835-22.272-24.627-53.35 0-80.64l191.898-200.090-191.846-200.090c-24.627-27.341-22.835-58.419 0-80.691 22.835-22.272 61.338-20.89 82.688-0z"
|
||||
],
|
||||
"tags": [
|
||||
"arrow-right",
|
||||
"right",
|
||||
"next"
|
||||
],
|
||||
"grid": 20
|
||||
},
|
||||
"properties": {
|
||||
"id": 208,
|
||||
"order": 13,
|
||||
"prevSize": 32,
|
||||
"code": 58893,
|
||||
"name": "arrow-right",
|
||||
"ligatures": "show detail"
|
||||
},
|
||||
"setIdx": 5,
|
||||
"iconIdx": 208
|
||||
}
|
||||
],
|
||||
"height": 1024,
|
||||
"metadata": {
|
||||
"name": "clipperz-icons"
|
||||
},
|
||||
"preferences": {
|
||||
"fontPref": {
|
||||
"prefix": "icon-",
|
||||
"metadata": {
|
||||
"fontFamily": "clipperz-icons",
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 0
|
||||
},
|
||||
"showGlyphs": true,
|
||||
"metrics": {
|
||||
"emSize": 512,
|
||||
"baseline": 6.25,
|
||||
"whitespace": 50
|
||||
},
|
||||
"resetPoint": 58880,
|
||||
"showQuickUse": true,
|
||||
"quickUsageToken": false,
|
||||
"showMetrics": true,
|
||||
"showMetadata": false,
|
||||
"autoHost": false,
|
||||
"embed": true,
|
||||
"showVersion": true
|
||||
},
|
||||
"imagePref": {
|
||||
"color": 0,
|
||||
"height": 32,
|
||||
"columns": 16,
|
||||
"margin": 16,
|
||||
"png": false,
|
||||
"sprites": true
|
||||
},
|
||||
"historySize": 100,
|
||||
"showCodes": false,
|
||||
"gridSize": 16,
|
||||
"showLiga": true,
|
||||
"showGrid": true,
|
||||
"showGlyphs": true,
|
||||
"showQuickUse": true,
|
||||
"search": "",
|
||||
"quickUsageToken": {
|
||||
"UntitledProject1": "YzBlN2I0ZDQ5YTQyY2NjYjgwNGRkYzNhYzU4NDZhMDcjMiMxNDAzMTA2OTk5IyMj"
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -21,11 +21,8 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
//Clipperz.Async = MochiKit.Async;
|
||||
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Async) == 'undefined') { Clipperz.Async = {}; }
|
||||
"use strict";
|
||||
Clipperz.Base.module('Clipperz.Async');
|
||||
|
||||
Clipperz.Async.VERSION = "0.1";
|
||||
Clipperz.Async.NAME = "Clipperz.Async";
|
||||
@ -276,6 +273,12 @@ Clipperz.Base.extend(Clipperz.Async.Deferred, MochiKit.Async.Deferred, {
|
||||
}, this));
|
||||
},
|
||||
|
||||
'values': function () {
|
||||
this.addCallback(MochiKit.Base.bind(function () {
|
||||
return this.vars();
|
||||
}, this));
|
||||
},
|
||||
|
||||
//=============================================================================
|
||||
|
||||
'wait': function (someSeconds) {
|
||||
@ -702,6 +705,6 @@ MochiKit.Base.update(Clipperz.Async, {
|
||||
|
||||
//#############################################################################
|
||||
|
||||
CLIPPERZ_DEFERRED_LOGGING_ENABLED = true;
|
||||
CLIPPERZ_DEFERRED_TRACING_ENABLED = false;
|
||||
CLIPPERZ_DEFERRED_CALL_LOGGING_ENABLED = false;
|
||||
var CLIPPERZ_DEFERRED_LOGGING_ENABLED = true;
|
||||
var CLIPPERZ_DEFERRED_TRACING_ENABLED = false;
|
||||
var CLIPPERZ_DEFERRED_CALL_LOGGING_ENABLED = false;
|
||||
|
@ -21,6 +21,8 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Base) == 'undefined') { Clipperz.Base = {}; }
|
||||
|
||||
@ -189,6 +191,10 @@ MochiKit.Base.update(Clipperz.Base, {
|
||||
return Clipperz.Base.removeObjectFromArray(anObject, anArray);
|
||||
},
|
||||
|
||||
'arrayWithUniqueValues': function (anArray) {
|
||||
return anArray.filter(function (value, index, self) { return self.indexOf(value) === index; });
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'splitStringAtFixedTokenSize': function(aString, aTokenSize) {
|
||||
|
@ -21,6 +21,7 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
|
||||
//=============================================================================
|
||||
|
@ -21,7 +21,8 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
"use strict";
|
||||
Clipperz.Base.module('Clipperz');
|
||||
|
||||
|
||||
Clipperz.CSVProcessor = function(args) {
|
||||
@ -32,9 +33,9 @@ Clipperz.CSVProcessor = function(args) {
|
||||
// this._string = undefined;
|
||||
// this._fields = undefined;
|
||||
|
||||
this._quoteChar = args['quoteChar'] || "\042";
|
||||
this._quoteChar = args['quoteChar'] || "\0x42";
|
||||
this._eol = args['eol'] || "";
|
||||
this._escapeChar = args['escapeChar'] || "\042";
|
||||
this._escapeChar = args['escapeChar'] || "\0x42";
|
||||
this._separatorChar = args['separatorChar'] || ",";
|
||||
this._binary = args['binary'] || false;
|
||||
this._alwaysQuote = args['alwaysQuote'] || false;
|
||||
|
@ -293,7 +293,7 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new
|
||||
Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource = function(args) {
|
||||
args = args || {};
|
||||
|
||||
this._intervalTime = args.intervalTime || 1000;
|
||||
this._intervalTime = args.intervalTime || 500;
|
||||
this._browserCrypto = args.browserCrypto;
|
||||
|
||||
Clipperz.Crypto.PRNG.RandomnessSource.call(this, args);
|
||||
@ -318,7 +318,7 @@ Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.upda
|
||||
var bytesToCollect;
|
||||
|
||||
if (this.boostMode() == true) {
|
||||
bytesToCollect = 64;
|
||||
bytesToCollect = 256;
|
||||
} else {
|
||||
bytesToCollect = 8;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
|
||||
return Clipperz.Crypto.SRP._n;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//.........................................................................
|
||||
|
||||
'g': function() {
|
||||
if (Clipperz.Crypto.SRP._g == null) {
|
||||
@ -66,6 +66,8 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, {
|
||||
return Clipperz.Crypto.SRP._g;
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'k': function() {
|
||||
if (Clipperz.Crypto.SRP._k == null) {
|
||||
// Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt(this.stringHash(this.n().asString() + this.g().asString()), 16);
|
||||
|
@ -21,8 +21,8 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.DOM) == 'undefined') { Clipperz.DOM = {}; }
|
||||
"use strict";
|
||||
Clipperz.Base.module('Clipperz.DOM');
|
||||
|
||||
Clipperz.DOM.VERSION = "0.1";
|
||||
Clipperz.DOM.NAME = "Clipperz.DOM";
|
||||
|
@ -21,8 +21,8 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
|
||||
if (typeof(Clipperz.Date) == 'undefined') { Clipperz.Date = {}; }
|
||||
"use strict";
|
||||
Clipperz.Base.module('Clipperz.Date');
|
||||
|
||||
Clipperz.Date.VERSION = "0.1";
|
||||
Clipperz.Date.NAME = "Clipperz.Date";
|
||||
|
@ -30,6 +30,7 @@ Clipperz.PM.DataModel.Record = function(args) {
|
||||
Clipperz.PM.DataModel.Record.superclass.constructor.apply(this, arguments);
|
||||
|
||||
this._updateDate = (args.updateDate ? Clipperz.PM.Date.parse(args.updateDate) : Clipperz.Base.exception.raise('MandatoryParameter'));
|
||||
this._accessDate = (args.accessDate ? Clipperz.PM.Date.parse(args.accessDate) : Clipperz.Base.exception.raise('MandatoryParameter'));
|
||||
|
||||
this._retrieveIndexDataFunction = args.retrieveIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._updateIndexDataFunction = args.updateIndexDataFunction || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
@ -40,6 +41,8 @@ Clipperz.PM.DataModel.Record = function(args) {
|
||||
|
||||
this._createNewDirectLoginFunction = args.createNewDirectLoginFunction || null;
|
||||
|
||||
this._tags = [];
|
||||
|
||||
this._directLogins = {};
|
||||
|
||||
this._versions = {};
|
||||
@ -128,22 +131,109 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
//============================================================================
|
||||
/*
|
||||
'key': function () {
|
||||
return this.getIndexDataForKey('key');
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
//============================================================================
|
||||
|
||||
'fullLabel': function () {
|
||||
return this.getIndexDataForKey('label');
|
||||
},
|
||||
|
||||
'updateFullLabelWithTags': function (someTags) {
|
||||
return Clipperz.Async.callbacks("Record.updateFullLabelWithTags", [
|
||||
MochiKit.Base.method(this, 'label'),
|
||||
function (aLabel) {
|
||||
return aLabel + ' ' + MochiKit.Base.map(function (aTag) { return Clipperz.PM.DataModel.Record.tagChar + aTag; }, MochiKit.Base.keys(someTags)).join(' ');
|
||||
},
|
||||
MochiKit.Base.method(this, 'setIndexDataForKey', 'label')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
'tagChar': function () {
|
||||
return Clipperz.PM.DataModel.Record.tagChar;
|
||||
},
|
||||
|
||||
'tagRegExp': function () {
|
||||
return new RegExp('\\' + this.tagChar() + '(\\w+)', 'g');
|
||||
},
|
||||
|
||||
'trimSpacesRegExp': function () {
|
||||
return new RegExp('^\\s+|\\s+$', 'g');
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
'filterOutTags': function (aValue) {
|
||||
var value;
|
||||
|
||||
value = aValue;
|
||||
value = value.replace(this.tagRegExp(), '');
|
||||
value = value.replace(this.trimSpacesRegExp(), '');
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
'label': function () {
|
||||
return this.getIndexDataForKey('label');
|
||||
return Clipperz.Async.callbacks("Record.label", [
|
||||
MochiKit.Base.method(this, 'fullLabel'),
|
||||
MochiKit.Base.method(this, 'filterOutTags')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'setLabel': function (aValue) {
|
||||
return this.setIndexDataForKey('label', aValue); // [???]
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
'setLabel': function (aValue) {
|
||||
return this.setIndexDataForKey('label', aValue);
|
||||
'extractTags': function (aLabel) {
|
||||
var tagRegEx;
|
||||
var result;
|
||||
var match;
|
||||
|
||||
result = {};
|
||||
tagRegEx = this.tagRegExp();
|
||||
match = tagRegEx.exec(aLabel);
|
||||
while (match != null) {
|
||||
result[match[1]] = true;
|
||||
match = tagRegEx.exec(aLabel);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
'tags': function () {
|
||||
return Clipperz.Async.callbacks("Record.label", [
|
||||
MochiKit.Base.method(this, 'fullLabel'),
|
||||
MochiKit.Base.method(this, 'extractTags'),
|
||||
MochiKit.Base.keys
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'addTag': function (aNewTag) {
|
||||
//console.log("ADD TAG", aNewTag);
|
||||
return Clipperz.Async.callbacks("Record.addTag", [
|
||||
MochiKit.Base.method(this, 'fullLabel'),
|
||||
MochiKit.Base.method(this, 'extractTags'),
|
||||
function (someTags) { someTags[aNewTag] = true; console.log("UPDATED TAGS", someTags); return someTags; },
|
||||
MochiKit.Base.method(this, 'updateFullLabelWithTags')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'removeTag': function (aTag) {
|
||||
//console.log("ADD TAG", aNewTag);
|
||||
return Clipperz.Async.callbacks("Record.removeTag", [
|
||||
MochiKit.Base.method(this, 'fullLabel'),
|
||||
MochiKit.Base.method(this, 'extractTags'),
|
||||
function (someTags) { delete someTags[aTag]; return someTags; },
|
||||
MochiKit.Base.method(this, 'updateFullLabelWithTags')
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
@ -183,6 +273,10 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
|
||||
return MochiKit.Async.succeed(this._updateDate);
|
||||
},
|
||||
|
||||
'accessDate': function () {
|
||||
return MochiKit.Async.succeed(this._accessDate);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'favicon': function () {
|
||||
@ -208,7 +302,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
|
||||
deferredResult = new Clipperz.Async.Deferred("Record.searchableContent", {trace:false});
|
||||
|
||||
deferredResult.collectResults({
|
||||
'recordLabel': MochiKit.Base.method(this, 'label'),
|
||||
'recordLabel': MochiKit.Base.method(this, 'fullLabel'),
|
||||
'directLoginLabels': [
|
||||
MochiKit.Base.method(this, 'directLoginReferences'),
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.itemgetter('label'))
|
||||
@ -889,3 +983,20 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt
|
||||
});
|
||||
|
||||
|
||||
Clipperz.PM.DataModel.Record.defaultCardInfo = {
|
||||
'_rowObject': MochiKit.Async.succeed,
|
||||
'_reference': MochiKit.Base.methodcaller('reference'),
|
||||
'_searchableContent': MochiKit.Base.methodcaller('searchableContent'),
|
||||
'_accessDate': MochiKit.Base.methodcaller('accessDate'),
|
||||
'label': MochiKit.Base.methodcaller('label'),
|
||||
'favicon': MochiKit.Base.methodcaller('favicon')
|
||||
};
|
||||
Clipperz.PM.DataModel.Record.defaultSearchField = '_searchableContent';
|
||||
|
||||
Clipperz.PM.DataModel.Record.tagChar = '#';
|
||||
Clipperz.PM.DataModel.Record.regExpForTag = function (aTag) {
|
||||
return new RegExp('\\' + Clipperz.PM.DataModel.Record.tagChar + aTag, 'g');
|
||||
};
|
||||
Clipperz.PM.DataModel.Record.regExpForSearch = function (aSearch) {
|
||||
return new RegExp(aSearch.replace(/[^A-Za-z0-9]/g, '\\$&'), 'i');
|
||||
};
|
||||
|
@ -25,26 +25,26 @@ try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catc
|
||||
throw "Clipperz.PM.DataModel.User.Subscription depends on Clipperz.PM.DataModel.User!";
|
||||
}
|
||||
|
||||
Clipperz.PM.DataModel.User.Subscription = function(args) {
|
||||
Clipperz.PM.DataModel.User.AccountInfo = function(args) {
|
||||
this._attributes = args;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.User.Subscription, Object, {
|
||||
Clipperz.Base.extend(Clipperz.PM.DataModel.User.AccountInfo, Object, {
|
||||
|
||||
'features': function () {
|
||||
return this._attributes['features'];
|
||||
},
|
||||
|
||||
'type': function () {
|
||||
return this._attributes['type'];
|
||||
'featureSet': function () {
|
||||
return this._attributes['featureSet'];
|
||||
},
|
||||
|
||||
'validity': function () {
|
||||
return {
|
||||
'from': this._attributes['fromDate'],
|
||||
'to': this._attributes['toDate']
|
||||
// 'from': this._attributes['fromDate'],
|
||||
'to': this._attributes['expirationDate']
|
||||
};
|
||||
},
|
||||
|
@ -133,6 +133,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Legacy, Clipperz.PM.DataM
|
||||
'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'),
|
||||
'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
|
||||
'updateDate': someObjectData['recordsStats'][reference]['updateDate'],
|
||||
'accessDate': someObjectData['recordsStats'][reference]['accessDate'],
|
||||
|
||||
'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'),
|
||||
'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
|
||||
|
@ -29,7 +29,7 @@ if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.Data
|
||||
|
||||
Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) {
|
||||
Clipperz.PM.DataModel.User.Header.RecordIndex.superclass.constructor.apply(this, arguments);
|
||||
|
||||
//console.log("RECORD INDEX ARGS", args);
|
||||
this._recordsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({
|
||||
'name': 'recordsData',
|
||||
'retrieveKeyFunction': args.retrieveKeyFunction,
|
||||
@ -37,9 +37,7 @@ Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) {
|
||||
'data': args.recordsData['data'],
|
||||
'version': args.encryptedDataVersion,
|
||||
'recordsStats': args.recordsStats
|
||||
}//,
|
||||
// 'encryptedDataKeypath': 'data',
|
||||
// 'encryptedVersionKeypath': 'version'
|
||||
}
|
||||
});
|
||||
|
||||
this._directLoginsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({
|
||||
@ -48,11 +46,10 @@ Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) {
|
||||
'remoteData': {
|
||||
'data': args.directLoginsData['data'],
|
||||
'version': args.encryptedDataVersion
|
||||
}//,
|
||||
// 'encryptedDataKeypath': 'data',
|
||||
// 'encryptedVersionKeypath': 'version'
|
||||
}
|
||||
});
|
||||
|
||||
this._tagsData =
|
||||
this._lock = new MochiKit.Async.DeferredLock();
|
||||
this._transientState = null;
|
||||
|
||||
@ -154,9 +151,6 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
|
||||
},
|
||||
|
||||
'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) {
|
||||
//if (MochiKit.Base.isUndefinedOrNull(this.directLoginsIndex()[aDirectLoginReference])) {
|
||||
// throw "PIPPO";
|
||||
//}
|
||||
return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference] + '.' + aKey, aValue);
|
||||
},
|
||||
|
||||
@ -182,8 +176,6 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records <inner deferred>", {trace:false});
|
||||
innerDeferredResult.collectResults({
|
||||
'records': [
|
||||
// MochiKit.Base.method(this.recordsData(), 'getObjectDataStore'),
|
||||
// MochiKit.Base.methodcaller('values')
|
||||
MochiKit.Base.method(this.recordsData(), 'values')
|
||||
],
|
||||
'recordsStats': [
|
||||
@ -191,8 +183,6 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
|
||||
MochiKit.Base.itemgetter('recordsStats')
|
||||
],
|
||||
'directLogins': [
|
||||
// MochiKit.Base.method(this.directLoginsData(), 'getObjectDataStore'),
|
||||
// MochiKit.Base.methodcaller('values')
|
||||
MochiKit.Base.method(this.directLoginsData(), 'values')
|
||||
]
|
||||
})
|
||||
@ -210,11 +200,13 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
|
||||
var record;
|
||||
var reference;
|
||||
var updateDate;
|
||||
var accessDate;
|
||||
|
||||
reference = recordsInvertedIndex[indexReference];
|
||||
|
||||
if (typeof(someData['recordsStats'][reference]) != 'undefined') {
|
||||
updateDate = someData['recordsStats'][reference]['updateDate'];
|
||||
accessDate = someData['recordsStats'][reference]['accessDate'];
|
||||
|
||||
record = new Clipperz.PM.DataModel.Record({
|
||||
'reference': reference,
|
||||
@ -224,6 +216,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
|
||||
'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'),
|
||||
'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
|
||||
'updateDate': updateDate,
|
||||
'accessDate': accessDate,
|
||||
|
||||
'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'),
|
||||
'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
|
||||
@ -235,13 +228,10 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, {
|
||||
this._records[reference] = record;
|
||||
} else {
|
||||
Clipperz.log("SKIPPING record " + reference + " as there are no stas associated - " + Clipperz.Base.serializeJSON(someData['records'][reference]));
|
||||
// # skip the record, as it seems it is not present in the DB
|
||||
// updateDate = Clipperz.PM.Date.formatDateWithUTCFormat(new Date());
|
||||
}
|
||||
}
|
||||
|
||||
for (indexReference in someData['directLogins']) {
|
||||
// var directLogin;
|
||||
var reference;
|
||||
var record;
|
||||
|
||||
@ -249,7 +239,6 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated
|
||||
record = this._records[recordsInvertedIndex[someData['directLogins'][indexReference]['record']]];
|
||||
|
||||
if (record != null) {
|
||||
// directLogin = new Clipperz.PM.DataModel.DirectLogin({
|
||||
new Clipperz.PM.DataModel.DirectLogin({
|
||||
'reference': reference,
|
||||
'record': record
|
||||
@ -301,6 +290,7 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated
|
||||
'retrieveIndexDataFunction': MochiKit.Base.method(this, 'getRecordIndexData'),
|
||||
'updateIndexDataFunction': MochiKit.Base.method(this, 'updateRecordIndexData'),
|
||||
'updateDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
'accessDate': Clipperz.PM.Date.formatDateWithUTCFormat(new Date()),
|
||||
|
||||
'retrieveDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'getDirectLoginIndexData'),
|
||||
'setDirectLoginIndexDataFunction': MochiKit.Base.method(this, 'setDirectLoginIndexData'),
|
||||
@ -384,10 +374,6 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated
|
||||
|
||||
'deleteAllCleanTextData': function () {
|
||||
return Clipperz.Async.callbacks("User.Header.RecordIndex.deleteAllCleanTextData", [
|
||||
// MochiKit.Base.method(this, 'records'),
|
||||
// MochiKit.Base.values,
|
||||
// MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')),
|
||||
|
||||
MochiKit.Base.method(this, 'recordsData'),
|
||||
MochiKit.Base.methodcaller('deleteAllCleanTextData'),
|
||||
MochiKit.Base.method(this, 'directLoginsData'),
|
||||
@ -410,21 +396,9 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated
|
||||
MochiKit.Base.method(this, 'directLoginsData'),
|
||||
MochiKit.Base.methodcaller('hasAnyCleanTextData')
|
||||
],
|
||||
// 'records': [
|
||||
// MochiKit.Base.method(this, 'records'),
|
||||
// MochiKit.Base.values,
|
||||
// MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')),
|
||||
// Clipperz.Async.collectAll
|
||||
// ]
|
||||
});
|
||||
|
||||
// deferredResult.addCallback(MochiKit.Base.values);
|
||||
// deferredResult.addCallback(MochiKit.Base.flattenArguments);
|
||||
// deferredResult.addCallback(function(someValues) {
|
||||
// return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
|
||||
// });
|
||||
deferredResult.addCallback(Clipperz.Async.or);
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
@ -447,11 +421,6 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated
|
||||
]
|
||||
});
|
||||
deferredResult.addCallback(Clipperz.Async.or);
|
||||
// deferredResult.addCallback(MochiKit.Base.values);
|
||||
// deferredResult.addCallback(MochiKit.Base.flattenArguments);
|
||||
// deferredResult.addCallback(function(someValues) {
|
||||
// return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity);
|
||||
// });
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
@ -482,9 +451,6 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated
|
||||
MochiKit.Base.method(this, 'recordsData'),
|
||||
MochiKit.Base.methodcaller('revertChanges'),
|
||||
|
||||
// MochiKit.Base.method(this, 'directLoginsData'),
|
||||
// MochiKit.Base.methodcaller('revertChanges'),
|
||||
|
||||
MochiKit.Base.method(this, 'records'),
|
||||
MochiKit.Base.bind(function (someRecords) {
|
||||
var recordReference;
|
||||
@ -500,22 +466,10 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated
|
||||
}
|
||||
}, this),
|
||||
|
||||
// MochiKit.Base.method(this, 'directLogins'),
|
||||
MochiKit.Base.bind(function () {
|
||||
var directLoginReference;
|
||||
|
||||
// this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin);
|
||||
//
|
||||
// this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue;
|
||||
// this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]});
|
||||
|
||||
|
||||
// for (directLoginReference in this.transientState().getValue('deleteDirectLoginReferences')) {
|
||||
// someDirectLogins[directLoginReference] = this.transientState().getValue('deleteDirectLoginReferences' + '.' + recordReference);
|
||||
// }
|
||||
|
||||
for (directLoginReference in this.transientState().getValue('newDirectLoginReferences')) {
|
||||
// this.directLoginsData().removeValue(this.directLoginsIndex()[directLoginReference]);
|
||||
delete this.directLoginsIndex()[directLoginReference];
|
||||
}
|
||||
}, this),
|
||||
|
@ -41,7 +41,7 @@ Clipperz.PM.DataModel.User = function (args) {
|
||||
this._connection = null;
|
||||
this._connectionVersion = 'current';
|
||||
|
||||
this._subscription = null;
|
||||
this._accountInfo = null;
|
||||
this._serverData = null;
|
||||
// this._serverLockValue = null;
|
||||
this._transientState = null;
|
||||
@ -78,12 +78,12 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(someServerData['subscription']));
|
||||
'subscription': function () {
|
||||
return this._subscription;
|
||||
'accountInfo': function () {
|
||||
return this._accountInfo;
|
||||
},
|
||||
|
||||
'setSubscription': function (aValue) {
|
||||
this._subscription = aValue;
|
||||
'setAccountInfo': function (aValue) {
|
||||
this._accountInfo = aValue;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -247,19 +247,16 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("User.login", {trace:false});
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
|
||||
deferredResult.addMethod(this, 'getPassphrase');
|
||||
deferredResult.addCallback(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue);
|
||||
deferredResult.addCallback(Clipperz.Async.deferredIf("Is the passphrase an OTP", [
|
||||
// MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':1}),
|
||||
MochiKit.Base.method(this, 'getCredentials'),
|
||||
MochiKit.Base.method(this.connection(), 'redeemOneTimePassword'),
|
||||
MochiKit.Base.method(this.data(), 'setValue', 'passphrase')
|
||||
], []));
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'getPassphrase'));
|
||||
deferredResult.addMethod(this.connection(), 'login', false);
|
||||
deferredResult.addMethod(this, 'setupConnectionInfo');
|
||||
// deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'userSuccessfullyLoggedIn');
|
||||
deferredResult.addMethod(this, 'setupAccountInfo');
|
||||
deferredResult.addErrback (MochiKit.Base.method(this, 'handleConnectionFallback'));
|
||||
|
||||
deferredResult.callback();
|
||||
@ -295,9 +292,10 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'setupConnectionInfo': function (aValue) {
|
||||
'setupAccountInfo': function (aValue) {
|
||||
//console.log("User.setupAccountInfo", aValue, aValue['accountInfo']);
|
||||
// this.setLoginInfo(aValue['loginInfo']);
|
||||
this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(aValue['subscription']));
|
||||
this.setAccountInfo(new Clipperz.PM.DataModel.User.AccountInfo(aValue['accountInfo']));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -511,6 +509,19 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getTags': function () {
|
||||
return Clipperz.Async.callbacks("User.getTags", [
|
||||
MochiKit.Base.method(this, 'getRecords'),
|
||||
MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('tags')),
|
||||
Clipperz.Async.collectAll,
|
||||
MochiKit.Base.flattenArray,
|
||||
Clipperz.Base.arrayWithUniqueValues
|
||||
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
'getRecords': function () {
|
||||
return Clipperz.Async.callbacks("User.getRecords", [
|
||||
MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'),
|
||||
@ -519,6 +530,36 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
|
||||
], {trace:false});
|
||||
},
|
||||
|
||||
'getRecordsInfo': function (someInfo, shouldIncludeArchivedCards) {
|
||||
return Clipperz.Async.callbacks("User.getRecordsInfo", [
|
||||
MochiKit.Base.method(this, 'getRecords'),
|
||||
MochiKit.Base.partial(MochiKit.Base.map, Clipperz.Async.collectResults("collectResults", someInfo, {trace:false})),
|
||||
Clipperz.Async.collectAll
|
||||
], {trace:false});
|
||||
},
|
||||
/*
|
||||
'filterRecordsInfo': function (someArgs) {
|
||||
var info = (someArgs.info ? someArgs.info : Clipperz.PM.DataModel.Record.defaultCardInfo);
|
||||
var searchField = (someArgs.searchField ? someArgs.searchField : Clipperz.PM.DataModel.Record.defaultSearchField);
|
||||
var includeArchived = (someArgs.includeArchived ? someArgs.includeArchived : false);
|
||||
var regExp = (someArgs.regExp ? someArgs.regExp : Clipperz.PM.DataModel.Record.regExpForSearch(''));
|
||||
|
||||
if (someArgs.regExp) {
|
||||
regExp = regExp;
|
||||
} else if (someArgs.search) {
|
||||
regExp = Clipperz.PM.DataModel.Record.regExpForSearch(someArgs.search);
|
||||
} else if (someArgs.tag) {
|
||||
regExp = Clipperz.PM.DataModel.Record.regExpForTag(someArgs.tag);
|
||||
} else {
|
||||
regExp = Clipperz.PM.DataModel.Record.regExpForSearch('');
|
||||
};
|
||||
|
||||
return Clipperz.Async.callbacks("User.filterRecordsInfo", [
|
||||
MochiKit.Base.method(this, 'getRecordsInfo', info, includeArchived),
|
||||
MochiKit.Base.partial(MochiKit.Base.filter, function (aCardInfo) { regExp.lastIndex = 0; return regExp.test(aCardInfo[searchField]);})
|
||||
], {trace:false});
|
||||
},
|
||||
*/
|
||||
'recordWithLabel': function (aLabel) {
|
||||
return Clipperz.Async.callbacks("User.recordWithLabel", [
|
||||
MochiKit.Base.method(this, 'getRecords'),
|
||||
|
@ -152,7 +152,7 @@ Clipperz.PM.Proxy.prototype = MochiKit.Base.update(null, {
|
||||
'sendMessage': function (aFunctionName, someParameters) {
|
||||
var deferredResult;
|
||||
|
||||
console.log("PROXY.sendMessage", aFunctionName, someParameters);
|
||||
//console.log("PROXY.sendMessage", aFunctionName, someParameters);
|
||||
// TODO: read actual application version for a property set at build time
|
||||
deferredResult = new Clipperz.Async.Deferred("Proxy.sendMessage", {trace:false});
|
||||
deferredResult.addMethod(this, '_sendMessage', aFunctionName, 'fake-app-version');
|
||||
|
@ -57,7 +57,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.JSON, Clipperz.PM.Proxy, {
|
||||
version: aVersion,
|
||||
parameters: Clipperz.Base.serializeJSON(someParameters)
|
||||
};
|
||||
console.log("PROXY.JSON._sendMessage", parameters);
|
||||
//console.log("PROXY.JSON._sendMessage", parameters);
|
||||
deferredResult = new Clipperz.Async.Deferred("Proxy.JSON._sendMessage", {trace:false});
|
||||
deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'remoteRequestSent');
|
||||
deferredResult.addCallback(MochiKit.Async.doXHR, this.url(), {
|
||||
|
@ -36,7 +36,7 @@ Clipperz.PM.Proxy.Offline.DataStore = function(args) {
|
||||
|
||||
this._tolls = {};
|
||||
this._currentStaticConnection = null;
|
||||
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
|
||||
'isReadOnly': function () {
|
||||
return this._isReadOnly;
|
||||
},
|
||||
|
||||
|
||||
'canRegisterNewUsers': function () {
|
||||
return false;
|
||||
},
|
||||
@ -296,14 +296,14 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
|
||||
throw "user already exists";
|
||||
}
|
||||
} else {
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly;
|
||||
}
|
||||
|
||||
result = {
|
||||
result: {
|
||||
'lock': this.data()['users'][someParameters['credentials']['C']]['lock'],
|
||||
'result': 'done'
|
||||
},
|
||||
},
|
||||
toll: this.getTollForRequestType('CONNECT')
|
||||
}
|
||||
|
||||
@ -334,7 +334,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
|
||||
randomBytes = Clipperz.Crypto.Base.generateRandomSeed();
|
||||
aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16);
|
||||
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
|
||||
aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
|
||||
aConnection['B'] = (Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()));
|
||||
|
||||
aConnection['A'] = someParameters.parameters.A;
|
||||
|
||||
@ -343,21 +343,65 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
|
||||
|
||||
nextTollRequestType = 'CONNECT';
|
||||
} else if (someParameters.message == "credentialCheck") {
|
||||
var v, u, S, A, K, M1;
|
||||
|
||||
var v, u, s, S, A, K, M1;
|
||||
var stringHash = function (aValue) {
|
||||
return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2);
|
||||
};
|
||||
|
||||
v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16);
|
||||
u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16);
|
||||
A = new Clipperz.Crypto.BigInt(aConnection['A'], 16);
|
||||
u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10))).toHexString(), 16);
|
||||
s = new Clipperz.Crypto.BigInt(aConnection['userData']['s'], 16);
|
||||
S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n());
|
||||
|
||||
K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2);
|
||||
K = stringHash(S.asString(10));
|
||||
|
||||
M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2);
|
||||
M1 = stringHash(
|
||||
"597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" +
|
||||
stringHash(aConnection['C']) +
|
||||
s.asString(10) +
|
||||
A.asString(10) +
|
||||
aConnection['B'].asString(10) +
|
||||
K
|
||||
);
|
||||
if (someParameters.parameters.M1 == M1) {
|
||||
var M2;
|
||||
|
||||
M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2);
|
||||
M2 = stringHash(
|
||||
A.asString(10) +
|
||||
someParameters.parameters.M1 +
|
||||
K
|
||||
);
|
||||
result['M2'] = M2;
|
||||
result['accountInfo'] = {
|
||||
'currentSubscriptionType': "FAN",
|
||||
'expirationDate': "Tue, 21 April 2015 11:59:12 UTC",
|
||||
'featureSet': "FULL",
|
||||
'features': [
|
||||
'UPDATE_CREDENTIALS',
|
||||
'EDIT_CARD',
|
||||
'CARD_DETAILS',
|
||||
'ADD_CARD',
|
||||
'DELETE_CARD',
|
||||
'OFFLINE_COPY',
|
||||
'LIST_CARDS'
|
||||
],
|
||||
'isExpired': false,
|
||||
'isExpiring': false,
|
||||
'latestActiveLevel': "PAYING",
|
||||
'latestActiveThreshold': "5.00000000",
|
||||
'paymentVerificationPending': false,
|
||||
'payments': [
|
||||
{
|
||||
'amount': "0.08500000",
|
||||
'currency': "BTC",
|
||||
'date': "Mon, 21 April 2014 12:11:12 UTC",
|
||||
'reference': "cad577106f8747ae1b0fad3f139f4b4644301a0608dd931f758ad18c1766cabe",
|
||||
'value': "5.23730000"
|
||||
}
|
||||
],
|
||||
'referenceDate': "Tue, 22 July 2014 15:47:08 UTC"
|
||||
};
|
||||
} else {
|
||||
throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error");
|
||||
}
|
||||
@ -426,6 +470,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, {
|
||||
recordsStats = {};
|
||||
for (recordReference in aConnection['userData']['records']) {
|
||||
recordsStats[recordReference] = {
|
||||
'accessDate': aConnection['userData']['records'][recordReference]['accessDate'],
|
||||
'updateDate': aConnection['userData']['records'][recordReference]['updateDate']
|
||||
}
|
||||
}
|
||||
|
56
frontend/delta/js/Clipperz/PM/UI/Components/AccountStatus.js
Normal file
56
frontend/delta/js/Clipperz/PM/UI/Components/AccountStatus.js
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.AccountStatus = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
'currentSubscriptionType': React.PropTypes.oneOf(['EARLY_ADOPTER', 'FRIEND', 'FAN', 'DEVOTEE', 'PATRON', 'TRIAL', 'TRIAL_EXPIRED', 'PAYMENT_FAILED_2', 'EXPIRED', 'PAYMENT_FAILED', 'VERIFYING_PAYMENT', 'VERIFYING_PAYMENT_2']).isRequired,
|
||||
'expirationDate': React.PropTypes.string.isRequired,
|
||||
'featureSet': React.PropTypes.oneOf(['TRIAL', 'EXPIRED', 'FULL']).isRequired,
|
||||
'isExpired': React.PropTypes.bool.isRequired,
|
||||
'isExpiring': React.PropTypes.bool.isRequired,
|
||||
'paymentVerificationPending': React.PropTypes.bool.isRequired,
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
//console.log("AccountStatus props", this.props);
|
||||
var classes = {
|
||||
'accountStatus': true,
|
||||
'isExpiring': this.props['isExpiring'],
|
||||
'isExpired': this.props['isExpired'],
|
||||
};
|
||||
|
||||
classes[this.props['featureSet']] = true;
|
||||
|
||||
return React.DOM.div({'className':React.addons.classSet(classes)}, [
|
||||
React.DOM.span({'className': 'level'}, this.props['featureSet']),
|
||||
React.DOM.span({'className': 'expirationDate'}, this.props['expirationDate'])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
53
frontend/delta/js/Clipperz/PM/UI/Components/Button.js
Normal file
53
frontend/delta/js/Clipperz/PM/UI/Components/Button.js
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.Button = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
'eventName': React.PropTypes.string.isRequired,
|
||||
'label': React.PropTypes.string.isRequired,
|
||||
'handler': React.PropTypes.func.isRequired,
|
||||
'className': React.PropTypes.string
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var classes = {
|
||||
'button': true
|
||||
};
|
||||
if (typeof(this.props['className']) != 'undefined') {
|
||||
classes[this.props['className']] = true;
|
||||
};
|
||||
|
||||
return React.DOM.div({className:React.addons.classSet(classes), onClick:this.props['handler']}, [
|
||||
React.DOM.div({className:this.props['eventName']}, [
|
||||
React.DOM.h3({className:'label'}, this.props['label'])
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.CardDetail = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
// searchDelay: 0.3
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
card: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
// showSearch: false,
|
||||
// searchTimer: null,
|
||||
unmaskedFields: new Clipperz.Set(),
|
||||
starred: false
|
||||
};
|
||||
},
|
||||
|
||||
handleDirectLoginClick: function (aDirectLoginReference, anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'runDirectLogin', {record:this.props.card['reference'], directLogin:aDirectLoginReference});
|
||||
},
|
||||
|
||||
toggleFieldVisibility: function (aField, anEvent) {
|
||||
var unmaskedFields;
|
||||
var fieldReference;
|
||||
|
||||
unmaskedFields = this.state['unmaskedFields'];
|
||||
fieldReference = aField['reference']
|
||||
if (unmaskedFields.contains(fieldReference)) {
|
||||
unmaskedFields.remove(fieldReference)
|
||||
} else {
|
||||
unmaskedFields.add(fieldReference)
|
||||
}
|
||||
|
||||
this.setState({'unmaskedFields': unmaskedFields});
|
||||
},
|
||||
|
||||
handleGoAction: function (aField, anEvent) {
|
||||
var newWindow;
|
||||
|
||||
newWindow = MochiKit.DOM.currentWindow().open(aField['value'], '_blank');
|
||||
newWindow.focus();
|
||||
},
|
||||
|
||||
handleEmailAction: function (aField, anEvent) {
|
||||
MochiKit.DOM.currentWindow().location = 'mailto:' + aField['value'];
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
normalizeFieldValue: function (aValue) {
|
||||
var result = [];
|
||||
var rows = aValue.split('\n');
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
if (i > 0) {
|
||||
result.push(React.DOM.br());
|
||||
}
|
||||
result.push(rows[i].replace(/[\s]/g, '\u00A0'));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
renderFieldActionButton: function (aField) {
|
||||
// var actionLabel;
|
||||
var result;
|
||||
|
||||
if (aField['actionType'] == 'URL') {
|
||||
result = React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'handleGoAction', aField)}, [
|
||||
React.DOM.a({className:aField['actionType']}, "go")
|
||||
]);
|
||||
} else if (aField['actionType'] == 'PASSWORD') {
|
||||
var icon;
|
||||
|
||||
if (this.state['unmaskedFields'].contains(aField['reference'])) {
|
||||
icon = "unlocked";
|
||||
} else {
|
||||
icon = "locked";
|
||||
}
|
||||
result = React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'toggleFieldVisibility', aField)}, [
|
||||
React.DOM.a({className:aField['actionType']}, icon)
|
||||
]);
|
||||
} else if (aField['actionType'] == 'EMAIL') {
|
||||
result = React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'handleEmailAction', aField)}, [
|
||||
React.DOM.a({className:aField['actionType']}, "email")
|
||||
]);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
renderField: function (aField) {
|
||||
//console.log("FIELD", aField);
|
||||
var fieldExtraClass;
|
||||
|
||||
fieldExtraClass = aField['actionType'];
|
||||
if (this.state['unmaskedFields'].contains(aField['reference'])) {
|
||||
fieldExtraClass = fieldExtraClass + ' unlocked';
|
||||
}
|
||||
|
||||
return React.DOM.div({className:'listItem ' + fieldExtraClass, key:aField['reference']}, [
|
||||
React.DOM.div({className:'fieldWrapper'}, [
|
||||
React.DOM.div({className:'fieldInnerWrapper'}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aField['label'])),
|
||||
React.DOM.div({className:'valueWrapper'}, React.DOM.span({className:'value ' + fieldExtraClass}, this.normalizeFieldValue(aField['value'])))
|
||||
])
|
||||
]),
|
||||
this.renderFieldActionButton(aField)
|
||||
// React.DOM.div({className:'actionWrapper'}, [
|
||||
// React.DOM.div({className:aField['actionType']}, actionLabel)
|
||||
// ])
|
||||
]);
|
||||
},
|
||||
|
||||
renderDirectLogin: function (aDirectLogin) {
|
||||
//console.log("DIRECT LOGIN", aDirectLogin);
|
||||
return React.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleDirectLoginClick', aDirectLogin['reference'])}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aDirectLogin['label'])),
|
||||
React.DOM.div({className:'faviconWrapper'}, React.DOM.img({className:'favicon', src:aDirectLogin['favicon']})),
|
||||
React.DOM.div({className:'directLoginLinkWrapper'}, React.DOM.span({className:'directLoginLink'}, "go"))
|
||||
]);
|
||||
},
|
||||
|
||||
handleBackClick: function (anEvent) {
|
||||
// window.history.back();
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
|
||||
},
|
||||
|
||||
handleStarClick: function (anEvent) {
|
||||
this.setState({starred: !this.state['starred']});
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var card = this.props.card;
|
||||
// var starredStatus = (this.state['starred'] ? "starred" : "unstarred");
|
||||
|
||||
if ((typeof(card['fields']) != 'undefined') && (card['notes'] != '')) {
|
||||
card['fields'].push({ 'actionType': 'NOTES', 'isHidden': false, 'label': "notes", 'reference': "notes", 'value': card['notes'] })
|
||||
}
|
||||
|
||||
return React.DOM.div({className:'cardDetail'}, [
|
||||
React.DOM.div({className:'header'}, [
|
||||
React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title)),
|
||||
React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")),
|
||||
// React.DOM.div({className:'starWrapper'}, React.DOM.a({className:'star', onClick:this.handleStarClick}, starredStatus))
|
||||
]),
|
||||
React.DOM.div({className:'content'}, [
|
||||
card.fields ? React.DOM.div({className:'fields'}, MochiKit.Base.map(this.renderField, card.fields)) : null,
|
||||
card.directLogins ? React.DOM.div({className:'directLogins'}, MochiKit.Base.map(this.renderDirectLogin, card.directLogins)): null
|
||||
]),
|
||||
React.DOM.div({className:'footer'}, [
|
||||
/*
|
||||
// React.DOM.a({className:'cancel'}, "cancel"),
|
||||
// React.DOM.a({className:'save'}, "save")
|
||||
|
||||
React.DOM.a({className:'cancel button'}, "failed"),
|
||||
React.DOM.a({className:'save button'}, "done")
|
||||
*/
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.CardList = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
selectedCard: null,
|
||||
searchDelay: 0.3
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
searchDelay: React.PropTypes.number
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
showSearch: false,
|
||||
searchTimer: null,
|
||||
searchText: '',
|
||||
// passphrase: '',
|
||||
// pin: ''
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
toggleSearch: function (anEvent) {
|
||||
var showSearchBox;
|
||||
|
||||
showSearchBox = !this.state.showSearch;
|
||||
|
||||
this.setState({showSearch: showSearchBox});
|
||||
|
||||
if (showSearchBox) {
|
||||
MochiKit.Async.callLater(0.1, MochiKit.Base.method(this, 'focusOnSearchField'));
|
||||
}
|
||||
},
|
||||
|
||||
updateSearchText: function (anEvent) {
|
||||
var searchText;
|
||||
|
||||
searchText = anEvent.target.value;
|
||||
//console.log(">>> updateSearchText", searchText);
|
||||
|
||||
if ((this.state['searchTimer'] != null) && (searchText != this.state['searchText'])) {
|
||||
this.state['searchTimer'].cancel();
|
||||
}
|
||||
|
||||
if (searchText != this.state['searchText']) {
|
||||
this.state['searchText'] = searchText;
|
||||
this.state['searchTimer'] = MochiKit.Async.callLater(this.props['searchDelay'], MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'searchCards', searchText);
|
||||
}
|
||||
},
|
||||
|
||||
focusOnSearchField: function () {
|
||||
console.log("focusOnSearchField", this.refs['searchField']);
|
||||
this.refs['searchField'].getDOMNode.focus();
|
||||
},
|
||||
|
||||
searchBox: function () {
|
||||
var result;
|
||||
|
||||
if (this.state.showSearch) {
|
||||
result = React.DOM.div({className:'searchBox'}, [
|
||||
React.DOM.div(null, [
|
||||
React.DOM.input({type:'search', placeholder:"search", ref:'searchField', onChange:this.updateSearchText})
|
||||
])
|
||||
]);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
showPreferences: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showPreferences', anEvent);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
cardItem: function (aRecordReference) {
|
||||
var reference = aRecordReference['_reference'];
|
||||
var selectedCard = (reference == this.props.selectedCard);
|
||||
|
||||
// TODO: verify if it is possible to put the onClick handler on the container 'div', instead of adding it to each 'div' item.
|
||||
return React.DOM.div({className:'listItem', key:reference, onClick:MochiKit.Base.method(this, 'handleClickOnCardDetail', reference)}, [
|
||||
React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label)),
|
||||
// React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label)),
|
||||
React.DOM.div({className:'faviconWrapper'}, aRecordReference.favicon ? React.DOM.img({className:'favicon', src:aRecordReference.favicon}) : React.DOM.div({className:'favicon'}, '\u00A0')),
|
||||
React.DOM.div({className:'detailLinkWrapper'}, React.DOM.span({className:'detailLink ' + (selectedCard ? 'icon-spin' : '')}, (selectedCard ? "loading" : "detail")))
|
||||
]);
|
||||
},
|
||||
|
||||
handleClickOnCardDetail: function (aRecordReference, anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRecord', aRecordReference);
|
||||
},
|
||||
|
||||
cardListItems: function () {
|
||||
var list;
|
||||
var result;
|
||||
|
||||
list = this.props['cardList'];
|
||||
|
||||
if (typeof(list) != 'undefined') {
|
||||
result = MochiKit.Base.map(MochiKit.Base.method(this, 'cardItem'), list);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
handleChange: function (anEvent) {
|
||||
// var refs = this.refs;
|
||||
// var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
|
||||
// var newState = {};
|
||||
//
|
||||
// newState[refName] = event.target.value;
|
||||
// this.setState(newState);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({className:'header'}, [
|
||||
React.DOM.a({className:'account'}, 'clipperz'),
|
||||
React.DOM.div({className:'features'}, [
|
||||
// React.DOM.a({className:'addCard'}, 'add'),
|
||||
React.DOM.a({className:'search ' + (this.state.showSearch ? 'selected' : ''), onClick:this.toggleSearch}, 'search'),
|
||||
React.DOM.a({className:'settings', onClick:this.showPreferences}, 'settings')
|
||||
]),
|
||||
// this.searchBox()
|
||||
]),
|
||||
this.searchBox(),
|
||||
React.DOM.div({className:'content cardList'}, this.cardListItems()),
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
101
frontend/delta/js/Clipperz/PM/UI/Components/CardToolbar.js
Normal file
101
frontend/delta/js/Clipperz/PM/UI/Components/CardToolbar.js
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.CardToolbar = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
// 'style': React.PropTypes.oneOf(['extra-short', 'narrow', 'wide', 'extra-wide']).isRequired,
|
||||
'style': React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired,
|
||||
'enableSidePanels': React.PropTypes.bool.isRequired,
|
||||
'accountStatus': React.PropTypes.object.isRequired,
|
||||
'messageBox': React.PropTypes.object.isRequired,
|
||||
'filter': React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
selectionToggleHandler: function (anEvent) {
|
||||
//console.log("selectionToggleHandler");
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSelectionPanel');
|
||||
|
||||
},
|
||||
|
||||
settingsToggleHandler: function (anEvent) {
|
||||
//console.log("settingsToggleHandler");
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel');
|
||||
},
|
||||
|
||||
//============================================================================
|
||||
|
||||
renderWithSidePanels: function () {
|
||||
return [
|
||||
React.DOM.div({className:'selectionToggle'}, [
|
||||
Clipperz.PM.UI.Components.Button({eventName:'selectionToggleButton', label:"tags", handler:this.selectionToggleHandler})
|
||||
]),
|
||||
this.renderWithoutSidePanels(),
|
||||
React.DOM.div({className:'settingsToggle'}, [
|
||||
Clipperz.PM.UI.Components.Button({eventName:'settingsToggleButton', label:"menu", handler:this.settingsToggleHandler})
|
||||
])
|
||||
];
|
||||
},
|
||||
|
||||
renderWithoutSidePanels: function () {
|
||||
var result;
|
||||
|
||||
if (this.props['filter']) {
|
||||
if (this.props['filter']['type'] == 'RECENT') {
|
||||
result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo recent'}, "recent")])];
|
||||
} else if (this.props['filter']['type'] == 'TAG') {
|
||||
result = [React.DOM.div({className:'clipperz'}, [
|
||||
React.DOM.span({className:'logo tag'}, "tag"),
|
||||
React.DOM.span({className:'value'}, this.props['filter']['value'])
|
||||
])];
|
||||
} else if (this.props['filter']['type'] == 'SEARCH') {
|
||||
result = [React.DOM.div({className:'clipperz'}, [
|
||||
React.DOM.span({className:'logo search'}, "search"),
|
||||
React.DOM.span({className:'value'}, this.props['filter']['value'])
|
||||
])];
|
||||
} else {
|
||||
result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo clipperz'}, "clipperz")])];
|
||||
}
|
||||
} else {
|
||||
result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo clipperz'}, "clipperz")])];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
//console.log("CardToolbar props", this.props);
|
||||
return React.DOM.div({className:'cardToolbar ' + this.props['style']}, [
|
||||
// React.DOM.div({className:'header'}, this.props['enableSidePanels'] ? this.renderWithSidePanels() : this.renderWithoutSidePanels()),
|
||||
React.DOM.header({}, this.props['enableSidePanels'] ? this.renderWithSidePanels() : this.renderWithoutSidePanels()),
|
||||
Clipperz.PM.UI.Components.AccountStatus(this.props['accountStatus']),
|
||||
Clipperz.PM.UI.Components.MessageBox(this.props['messageBox']),
|
||||
]);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
});
|
66
frontend/delta/js/Clipperz/PM/UI/Components/Cards/List.js
Normal file
66
frontend/delta/js/Clipperz/PM/UI/Components/Cards/List.js
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Cards');
|
||||
|
||||
Clipperz.PM.UI.Components.Cards.List = React.createClass({
|
||||
|
||||
//=========================================================================
|
||||
|
||||
propTypes: {
|
||||
'cards': React.PropTypes.array,
|
||||
'selectedCard': React.PropTypes.string
|
||||
},
|
||||
|
||||
handleClick: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'cardSelected', {'reference':anEvent.currentTarget.dataset.reference, 'label':anEvent.currentTarget.dataset.label});
|
||||
},
|
||||
|
||||
renderItem: function (anItem) {
|
||||
var classes = {
|
||||
'selected': this.props['selectedCard'] ? this.props['selectedCard']['_reference'] == anItem['_reference'] : false
|
||||
};
|
||||
|
||||
return React.DOM.li({'className':React.addons.classSet(classes), 'onClick': this.handleClick, 'key':anItem['_reference'], 'data-reference':anItem['_reference'], 'data-label':anItem['label']}, [
|
||||
React.DOM.span({'className':'favicon'}, [ React.DOM.img({src:anItem['favicon']})]),
|
||||
React.DOM.span({'className':'label'}, anItem['label']),
|
||||
// React.DOM.span({'className':'action'}, 'show detail')
|
||||
]);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var cards = this.props['cards'] ? this.props['cards'] : [];
|
||||
var classes = {
|
||||
'cardList': true,
|
||||
'loadingCard': this.props['selectedCard'] && this.props['selectedCard']['_reference'] && this.props['selectedCard']['loading']
|
||||
};
|
||||
classes[this.props['style']] = true;
|
||||
|
||||
return React.DOM.div({'key':'cardList', 'className':React.addons.classSet(classes)}, [
|
||||
React.DOM.ul({}, MochiKit.Base.map(this.renderItem, cards))
|
||||
]);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
133
frontend/delta/js/Clipperz/PM/UI/Components/Cards/Toolbar.js
Normal file
133
frontend/delta/js/Clipperz/PM/UI/Components/Cards/Toolbar.js
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Cards');
|
||||
|
||||
Clipperz.PM.UI.Components.Cards.Toolbar = React.createClass({
|
||||
|
||||
//============================================================================
|
||||
|
||||
propTypes: {
|
||||
// 'label': React.PropTypes.string.isRequired,
|
||||
// 'loading': React.PropTypes.bool,
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
getInitialState: function() {
|
||||
return {'showCommandMenu': false };
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
commands: function () {
|
||||
return {
|
||||
'delete': {
|
||||
'label': "delete",
|
||||
'broadcastEvent': 'deleteCard'
|
||||
},
|
||||
'archive': {
|
||||
'label': "archive",
|
||||
'broadcastEvent': 'archiveCard'
|
||||
},
|
||||
// 'share': {
|
||||
// 'label': "share",
|
||||
// 'broadcastEvent': 'shareCard'
|
||||
// },
|
||||
'edit': {
|
||||
'label': "edit",
|
||||
'broadcastEvent': 'editCard'
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
exit: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBackToMainPage', {'reference':this.props['_reference']});
|
||||
},
|
||||
|
||||
toggleMenu: function (anEvent) {
|
||||
this.setState({'showCommandMenu': !this.state['showCommandMenu'] });
|
||||
},
|
||||
|
||||
selectCommandItem: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, anEvent.target.dataset['broadcastEvent'], {'reference':this.props['_reference']});
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderCommands: function () {
|
||||
var commandHandler = this.selectCommandItem;
|
||||
|
||||
return React.DOM.ul({}, MochiKit.Base.map(function (aCommand) {
|
||||
return React.DOM.li({}, [React.DOM.span({'onClick':commandHandler, 'data-broadcast-event':aCommand['broadcastEvent']}, aCommand['label'])]);
|
||||
}, MochiKit.Base.values(this.commands())));
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderNarrow: function () {
|
||||
return [
|
||||
React.DOM.div({}, [
|
||||
React.DOM.div({'className':'back', 'onClick': this.exit}, 'back'),
|
||||
React.DOM.div({'className':'cardMenuOptions', 'onClick':this.toggleMenu}, 'commands'),
|
||||
React.DOM.div({'className':React.addons.classSet({'commandMenu':true, 'show':this.state['showCommandMenu']})}, [
|
||||
React.DOM.div({'className':'commandMenuMask', 'onClick':this.toggleMenu}),
|
||||
React.DOM.div({'className':'commandMenu'}, this.renderCommands())
|
||||
])
|
||||
])
|
||||
]
|
||||
},
|
||||
|
||||
renderOther: function () {
|
||||
return [this.renderCommands()];
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderLayout: function (aLayout) {
|
||||
var result;
|
||||
|
||||
if (aLayout == 'narrow') {
|
||||
result = this.renderNarrow();
|
||||
} else {
|
||||
result = this.renderOther();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var style = this.props['style'];
|
||||
var classes = {
|
||||
'cardDetailToolbar': true,
|
||||
};
|
||||
classes[style] = true;
|
||||
|
||||
return React.DOM.div({'className':React.addons.classSet(classes)}, this.renderLayout(style));
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
161
frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js
Normal file
161
frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Cards');
|
||||
|
||||
Clipperz.PM.UI.Components.Cards.View = React.createClass({
|
||||
|
||||
//============================================================================
|
||||
|
||||
propTypes: {
|
||||
'label': React.PropTypes.string.isRequired,
|
||||
'loading': React.PropTypes.bool,
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderEmpty: function () {
|
||||
return React.DOM.h4({}, "EMPTY");
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderLoading: function () {
|
||||
return React.DOM.div({className:'loading'},[
|
||||
this.renderLabel(),
|
||||
React.DOM.h5({className:'message'}, "loading")
|
||||
/*
|
||||
React.DOM.div({className:'overlay'}, [
|
||||
React.DOM.div({className:'spinner'}, [
|
||||
React.DOM.div({className:'bar01'}),
|
||||
React.DOM.div({className:'bar02'}),
|
||||
React.DOM.div({className:'bar03'}),
|
||||
React.DOM.div({className:'bar04'}),
|
||||
React.DOM.div({className:'bar05'}),
|
||||
React.DOM.div({className:'bar06'}),
|
||||
React.DOM.div({className:'bar07'}),
|
||||
React.DOM.div({className:'bar08'}),
|
||||
React.DOM.div({className:'bar09'}),
|
||||
React.DOM.div({className:'bar10'}),
|
||||
React.DOM.div({className:'bar11'}),
|
||||
React.DOM.div({className:'bar12'})
|
||||
])
|
||||
])
|
||||
*/
|
||||
]);
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderLabel: function (aLabel) {
|
||||
return React.DOM.h3({'className':'cardLabel'}, aLabel);
|
||||
},
|
||||
|
||||
renderNotes: function (someNotes) {
|
||||
return React.DOM.div({'className':'cardNotes'}, someNotes);
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
renderTag: function (aTag) {
|
||||
return React.DOM.div({'className':'cardTag'}, aTag);
|
||||
},
|
||||
|
||||
renderTags: function (someTags) {
|
||||
return React.DOM.div({'className':'cardTags'}, MochiKit.Base.map(this.renderTag, someTags));
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
renderField: function (aField) {
|
||||
var cardFieldClasses = {};
|
||||
var cardFieldValueClasses = {};
|
||||
|
||||
cardFieldClasses['cardField'] = true;
|
||||
cardFieldClasses[aField['actionType']] = true;
|
||||
cardFieldClasses['hidden'] = aField['isHidden'];
|
||||
|
||||
cardFieldValueClasses['fieldValue'] = true;
|
||||
cardFieldValueClasses[aField['actionType']] = true;
|
||||
cardFieldValueClasses['hidden'] = aField['isHidden'];
|
||||
|
||||
return React.DOM.div({'className':React.addons.classSet(cardFieldClasses)}, [
|
||||
React.DOM.div({'className':'fieldValues'}, [
|
||||
React.DOM.div({'className':'fieldLabel'}, aField['label']),
|
||||
React.DOM.div({'className':React.addons.classSet(cardFieldValueClasses)}, aField['value']),
|
||||
]),
|
||||
React.DOM.div({'className':'fieldAction action'}, aField['actionType'].toLowerCase())
|
||||
]);
|
||||
},
|
||||
|
||||
renderFields: function (someFields) {
|
||||
return React.DOM.div({'className':'cardFields'}, MochiKit.Base.map(this.renderField, someFields));
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
renderDirectLogin: function (aDirectLogin) {
|
||||
return React.DOM.div({'className':'cardDirectLogin'}, [
|
||||
React.DOM.span({'className':'directLoginLabel'}, aDirectLogin['label']),
|
||||
React.DOM.div({'className':'directLoginAction action'}, 'DIRECT LOGIN')
|
||||
]);
|
||||
},
|
||||
|
||||
renderDirectLogins: function (someDirectLogins) {
|
||||
return React.DOM.div({'className':'cardDirectLogins'}, MochiKit.Base.map(this.renderDirectLogin, someDirectLogins));
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
renderCard: function () {
|
||||
return React.DOM.div({'className':'view'},[
|
||||
Clipperz.PM.UI.Components.Cards.Toolbar(this.props),
|
||||
React.DOM.div({'className':'content'}, [
|
||||
this.renderLabel(this.props['label']),
|
||||
this.renderTags(this.props['tags']),
|
||||
this.renderNotes(this.props['notes']),
|
||||
this.renderFields(this.props['fields']),
|
||||
this.renderDirectLogins(this.props['directLogins'])
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
render: function () {
|
||||
var result;
|
||||
|
||||
if (this.props['loading'] == true) {
|
||||
result = this.renderLoading();
|
||||
} else if (this.props['label']) {
|
||||
result = this.renderCard();
|
||||
} else {
|
||||
result = this.renderEmpty();
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
@ -21,6 +21,8 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.Checkbox = React.createClass({
|
||||
// http://development.tobypitman.com/iphoneCheckboxes/iphoneCheckboxes2.html
|
||||
|
||||
|
40
frontend/delta/js/Clipperz/PM/UI/Components/ExpiredPanel.js
Normal file
40
frontend/delta/js/Clipperz/PM/UI/Components/ExpiredPanel.js
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.ExpiredPanel = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
// featureSet: React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']).isRequired,
|
||||
// 'level': React.PropTypes.oneOf(['hide', 'info', 'warning', 'error']).isRequired
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
return React.DOM.div({className:'expiredPanel'}, "EXPIRED PANEL");
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
47
frontend/delta/js/Clipperz/PM/UI/Components/MessageBox.js
Normal file
47
frontend/delta/js/Clipperz/PM/UI/Components/MessageBox.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.MessageBox = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
'level': React.PropTypes.oneOf(['HIDE', 'INFO', 'WARNING', 'ERROR']).isRequired,
|
||||
'message': React.PropTypes.string.isRequired
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
level: 'HIDE',
|
||||
message: ''
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
return React.DOM.div({className:'messageBox ' + this.props['level']}, this.props['message']);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
@ -21,13 +21,13 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.PageTemplate = React.createClass({
|
||||
render: function() {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({'className': 'header'}, [
|
||||
React.DOM.h1(null, "clipperz")
|
||||
]),
|
||||
React.DOM.div({'className': 'content'}, this.props.innerComponent)
|
||||
])
|
||||
}
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.CardDetailPage = React.createClass({
|
||||
|
||||
render: function () {
|
||||
// return React.DOM.header({'className':''})
|
||||
return Clipperz.PM.UI.Components.Cards.View(this.props['selectedCard']);
|
||||
|
||||
},
|
||||
});
|
@ -21,11 +21,13 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.ErrorPage = React.createClass({
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.ErrorPage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
// template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
@ -36,11 +38,11 @@ Clipperz.PM.UI.Components.ErrorPage = React.createClass({
|
||||
},
|
||||
|
||||
|
||||
_render: function () {
|
||||
render: function () {
|
||||
return React.DOM.div({className:'error-message'}, this.props.message);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return new this.props.template({'innerComponent': this._render()});
|
||||
}
|
||||
// render: function () {
|
||||
// return new this.props.template({'innerComponent': this._render()});
|
||||
// }
|
||||
});
|
@ -21,24 +21,26 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
"use strict";
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.LoginPage = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.oneOf(['CREDENTIALS','PIN']).isRequired,
|
||||
isNewUserRegistrationAvailable: React.PropTypes.bool.isRequired,
|
||||
disabled: React.PropTypes.bool.isRequired
|
||||
},
|
||||
/*
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
mode: 'CREDENTIALS',
|
||||
isNewUserRegistrationAvailable: false,
|
||||
disabled: false,
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
// template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
mode: React.PropTypes.oneOf(['CREDENTIALS','PIN']),
|
||||
isNewUserRegistrationAvailable: React.PropTypes.bool,
|
||||
disabled: React.PropTypes.bool,
|
||||
template: React.PropTypes.func
|
||||
},
|
||||
|
||||
*/
|
||||
getInitialState: function () {
|
||||
return {
|
||||
username: '',
|
||||
@ -54,7 +56,7 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0];
|
||||
var newState = {};
|
||||
|
||||
newState[refName] = event.target.value;
|
||||
newState[refName] = anEvent.target.value;
|
||||
this.setState(newState);
|
||||
},
|
||||
|
||||
@ -86,25 +88,21 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
((this.state['username'] != '') && (this.state['passphrase'] != ''))
|
||||
||
|
||||
(this.state['pin'] != '')
|
||||
) && !this.props['disabled'];
|
||||
)
|
||||
&&
|
||||
!this.props['disabled'];
|
||||
},
|
||||
|
||||
|
||||
loginForm: function () {
|
||||
registrationLink = React.DOM.div({'className':'registrationLink'}, [
|
||||
React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Sign up")
|
||||
]);
|
||||
return React.DOM.div({'className':'loginForm credentials'},[
|
||||
React.DOM.form({onChange: this.handleChange, onSubmit:this.handleCredentialSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'for' :'name'}, "username"),
|
||||
React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}),
|
||||
React.DOM.label({'for' :'passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'})
|
||||
]),
|
||||
React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login")
|
||||
return React.DOM.form({'className':'loginForm credentials', 'onChange':this.handleChange, 'onSubmit':this.handleCredentialSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'htmlFor' :'name'}, "username"),
|
||||
React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}),
|
||||
React.DOM.label({'htmlFor' :'passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'})
|
||||
]),
|
||||
this.props.isNewUserRegistrationAvailable ? registrationLink : null
|
||||
React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login")
|
||||
]);
|
||||
},
|
||||
|
||||
@ -121,14 +119,12 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
},
|
||||
|
||||
pinForm: function () {
|
||||
return React.DOM.div({'className':'loginForm pin'},[
|
||||
React.DOM.form({onChange: this.handleChange, onSubmit:this.handlePINSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'for':'pin'}, "pin"),
|
||||
React.DOM.input({'type':'text', 'name':'pin', 'ref':'pin', placeholder:"PIN", 'key':'pin', 'autocapitalize':'none'})
|
||||
]),
|
||||
React.DOM.button({'type':'submit', 'disabled':this.props.disabled, 'className':'button'}, "login")
|
||||
])
|
||||
return React.DOM.form({'className':'loginForm pin', 'onChange':this.handleChange, 'onSubmit':this.handlePINSubmit}, [
|
||||
React.DOM.div(null,[
|
||||
React.DOM.label({'for':'pin'}, "pin"),
|
||||
React.DOM.input({'type':'text', 'name':'pin', 'ref':'pin', placeholder:"PIN", 'key':'pin', 'autocapitalize':'none'})
|
||||
]),
|
||||
React.DOM.button({'type':'submit', 'disabled':this.props.disabled, 'className':'button'}, "login")
|
||||
]);
|
||||
},
|
||||
|
||||
@ -145,6 +141,16 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return new this.props.template({'innerComponent': this.props.mode == 'PIN' ? this.pinForm() : this.loginForm()});
|
||||
var registrationLink = React.DOM.div({'className':'registrationLink'}, [
|
||||
React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Sign up")
|
||||
]);
|
||||
|
||||
return React.DOM.div({'className':'loginForm ' + this.props['style']}, [
|
||||
React.DOM.header({}, 'clipperz'),
|
||||
React.DOM.div({'className':'form'}, [
|
||||
this.props.mode == 'PIN' ? this.pinForm() : this.loginForm(),
|
||||
]),
|
||||
this.props.isNewUserRegistrationAvailable ? registrationLink : null
|
||||
]);
|
||||
}
|
||||
});
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.MainPage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
'messageBox': React.PropTypes.object.isRequired,
|
||||
// 'featureSet': React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']),
|
||||
'accountStatus': React.PropTypes.object.isRequired,
|
||||
// 'mediaQueryStyle': React.PropTypes.oneOf(['extra-short', 'narrow', 'wide', 'extra-wide']).isRequired,
|
||||
'style': React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired,
|
||||
// 'cards': React.PropTypes.deferred.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
return {
|
||||
// shouldStoreDataLocally: false
|
||||
};
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var classes = {
|
||||
'mainPage': true
|
||||
};
|
||||
classes[this.props['style']] = true;
|
||||
//console.log("MainPage.cards", this.props['cards'], this.props['cards'].state());
|
||||
|
||||
return React.DOM.div({className:React.addons.classSet(classes)}, [
|
||||
this.props['style'] != 'extra-wide' ? Clipperz.PM.UI.Components.Panels.SelectionPanel(this.props) : null,
|
||||
Clipperz.PM.UI.Components.Panels.MainPanel(this.props),
|
||||
Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel(this.props)
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
@ -21,7 +21,9 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Pages');
|
||||
|
||||
Clipperz.PM.UI.Components.Pages.RegistrationPage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
@ -31,7 +33,7 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
{name:'TERMS_OF_SERVICE', label:'registration', _label:'terms', description:"Check our terms of service"}
|
||||
],
|
||||
disabled: false,
|
||||
template: Clipperz.PM.UI.Components.PageTemplate
|
||||
// template: Clipperz.PM.UI.Components.PageTemplate
|
||||
}
|
||||
},
|
||||
|
||||
@ -166,16 +168,16 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
|
||||
render_CREDENTIALS: function () {
|
||||
return React.DOM.div(null,[
|
||||
React.DOM.label({'for':'name'}, "username"),
|
||||
React.DOM.label({'htmlFor':'name'}, "username"),
|
||||
React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'/*, value:this.state.username*/}),
|
||||
React.DOM.label({'for':'passphrase'}, "passphrase"),
|
||||
React.DOM.label({'htmlFor':'passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'/*, value:this.state.passphrase*/})
|
||||
]);
|
||||
},
|
||||
|
||||
render_PASSWORD_VERIFICATION: function () {
|
||||
return React.DOM.div(null,[
|
||||
React.DOM.label({'for':'verify_passphrase'}, "passphrase"),
|
||||
React.DOM.label({'htmlFor':'verify_passphrase'}, "passphrase"),
|
||||
React.DOM.input({'type':'password', 'name':'verify_passphrase', 'ref':'verify_passphrase', 'placeholder':"verify passphrase", 'key':'verify_passphrase'})
|
||||
]);
|
||||
},
|
||||
@ -183,12 +185,12 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
render_TERMS_OF_SERVICE: function () {
|
||||
return React.DOM.div(null, [
|
||||
React.DOM.div({className:'checkboxBlock'}, [
|
||||
React.DOM.label({'for':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."),
|
||||
React.DOM.label({'htmlFor':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."),
|
||||
React.DOM.input({'type':'checkbox', 'name':'no_password_recovery', 'ref':'no_password_recovery', 'key':'no_password_recovery'}),
|
||||
React.DOM.p(null, "I understand that Clipperz will not be able to recover a lost passphrase.")
|
||||
]),
|
||||
React.DOM.div({className:'checkboxBlock'}, [
|
||||
React.DOM.label({'for':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."),
|
||||
React.DOM.label({'htmlFor':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."),
|
||||
React.DOM.input({'type':'checkbox', 'name':'agree_terms_of_service', 'ref':'agree_terms_of_service', 'key':'agree_terms_of_service'}),
|
||||
React.DOM.p(null, [
|
||||
"I have read and agreed to the ",
|
||||
@ -208,7 +210,7 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
]);
|
||||
},
|
||||
|
||||
_render: function () {
|
||||
render: function () {
|
||||
return React.DOM.div({'className':'registrationForm'},[
|
||||
React.DOM.form({onChange: this.handleChange}, [
|
||||
React.DOM.div({'className':'steps'}, MochiKit.Base.map(this.renderStep, this.props['steps']))
|
||||
@ -216,9 +218,9 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({
|
||||
]);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return new this.props.template({'innerComponent': this._render()});
|
||||
},
|
||||
// render: function () {
|
||||
// return new this.props.template({'innerComponent': this._render()});
|
||||
// },
|
||||
|
||||
//=========================================================================
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Panels');
|
||||
|
||||
Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel = React.createClass({
|
||||
|
||||
settingsToggleHandler: function (anEvent) {
|
||||
//console.log("settingsToggleHandler");
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel');
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
var classes = {
|
||||
'panel': true,
|
||||
'right': true,
|
||||
'open': this.props['settingsPanelStatus'] == 'OPEN'
|
||||
}
|
||||
|
||||
return React.DOM.div({key:'extraFeaturesPanel', id:'extraFeaturesPanel', className:React.addons.classSet(classes)}, [
|
||||
React.DOM.header({}, [
|
||||
React.DOM.div({className:'settingsToggle'}, [
|
||||
Clipperz.PM.UI.Components.Button({eventName:'settingsToggleButton', label:"menu", handler:this.settingsToggleHandler})
|
||||
])
|
||||
]),
|
||||
React.DOM.h2({}, "Extra features")
|
||||
]);
|
||||
/*
|
||||
<div id="extraFeaturesPanel" class="panel extraFeatures">
|
||||
|
||||
<div class="warnings">
|
||||
<ul>
|
||||
<li>Synchronize local data</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
<li>Account</li>
|
||||
<li>Subscription</li>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li>Local Data</li>
|
||||
<li>OTP</li>
|
||||
</ul>
|
||||
|
||||
<div class="donation">
|
||||
<a>Make a donation</a>
|
||||
</div>
|
||||
</div>
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
193
frontend/delta/js/Clipperz/PM/UI/Components/Panels/MainPanel.js
Normal file
193
frontend/delta/js/Clipperz/PM/UI/Components/Panels/MainPanel.js
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Panels');
|
||||
|
||||
Clipperz.PM.UI.Components.Panels.MainPanel = React.createClass({
|
||||
|
||||
//=========================================================================
|
||||
|
||||
propTypes: {
|
||||
'messageBox': React.PropTypes.object.isRequired,
|
||||
'featureSet': React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']).isRequired,
|
||||
'style': React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired,
|
||||
},
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
featureSet: 'FULL'
|
||||
};
|
||||
},
|
||||
|
||||
style: function () {
|
||||
return this.props['style'];
|
||||
},
|
||||
|
||||
featureSet: function () {
|
||||
return this.props['featureSet'];
|
||||
},
|
||||
|
||||
handleMaskClick: function () {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'maskClick');
|
||||
},
|
||||
|
||||
handleAddCardClick: function () {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'addCardClick');
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderToolbarFrame: function (anInnerComponent) {
|
||||
return React.DOM.div({'className':'cardToolbarFrame'}, [
|
||||
this.renderToolbar(),
|
||||
anInnerComponent
|
||||
]);
|
||||
},
|
||||
|
||||
renderCardFrame: function (firstColumnComponents, secondColumnComponents) {
|
||||
var addCardButton = React.DOM.div({'className': 'addCardButton', 'onClick':this.handleAddCardClick}, 'add card');
|
||||
|
||||
return React.DOM.div({'key':'cardContent', 'className':'cardContent'}, [
|
||||
React.DOM.div({'className':'cardListColumn column'}, [addCardButton, firstColumnComponents]),
|
||||
React.DOM.div({'className':'cardDetail column right'}, secondColumnComponents)
|
||||
])
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderToolbar: function () {
|
||||
var cardToolbarProps;
|
||||
|
||||
cardToolbarProps = MochiKit.Base.merge(this.props, {
|
||||
'key': 'toolbar',
|
||||
'style': this.style(),
|
||||
'enableSidePanels': (this.props['featureSet'] != 'EXPIRED')
|
||||
});
|
||||
|
||||
return Clipperz.PM.UI.Components.CardToolbar(cardToolbarProps);
|
||||
},
|
||||
|
||||
renderExpiredPanel: function () {
|
||||
return this.featureSet() == 'EXPIRED' ? Clipperz.PM.UI.Components.ExpiredPanel(this.props) : null;
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
viewComponentProps: function () {
|
||||
var result;
|
||||
|
||||
result = this.props['selectedCard'];
|
||||
if (result) {
|
||||
result['style'] = this.props['style'];
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
renderExtraWide: function () {
|
||||
return [
|
||||
React.DOM.div({'className':'selection subpanel'}, [Clipperz.PM.UI.Components.Selections(this.props)]),
|
||||
React.DOM.div({'className':'cardContent subpanel'}, [
|
||||
this.renderToolbarFrame(
|
||||
this.renderCardFrame(
|
||||
[Clipperz.PM.UI.Components.Cards.List(this.props)],
|
||||
[
|
||||
this.renderExpiredPanel(),
|
||||
Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps())
|
||||
]
|
||||
)
|
||||
)
|
||||
])
|
||||
]
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderWide: function () {
|
||||
return [
|
||||
this.renderToolbarFrame(
|
||||
this.renderCardFrame(
|
||||
[Clipperz.PM.UI.Components.Cards.List(this.props)],
|
||||
[
|
||||
this.renderExpiredPanel(),
|
||||
Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps())
|
||||
]
|
||||
)
|
||||
)
|
||||
];
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderNarrow: function () {
|
||||
return this.renderCardFrame(
|
||||
this.renderToolbarFrame([
|
||||
this.renderExpiredPanel(),
|
||||
Clipperz.PM.UI.Components.Cards.List(this.props),
|
||||
]),
|
||||
[Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps())]
|
||||
);
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
renderLayout: function (aLayout) {
|
||||
var result;
|
||||
|
||||
if (aLayout == 'extra-wide') {
|
||||
result = this.renderExtraWide();
|
||||
} else if (aLayout == 'wide') {
|
||||
result = this.renderWide();
|
||||
} else if (aLayout == 'narrow') {
|
||||
result = this.renderNarrow();
|
||||
} else if (aLayout == 'extra-short') {
|
||||
result = this.renderNarrow();
|
||||
} else {
|
||||
Clipperz.Base.exception.raise('UnknownType');
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
//console.log("MainPanel.cards", this.props['cards']);
|
||||
var classes = {
|
||||
'panel': true,
|
||||
'left': this.props['selectionPanelStatus'] == 'OPEN',
|
||||
'right': this.props['settingsPanelStatus'] == 'OPEN',
|
||||
'open': this.props['selectionPanelStatus'] == 'OPEN' || this.props['settingsPanelStatus'] == 'OPEN'
|
||||
};
|
||||
classes[this.style()] = true;
|
||||
|
||||
return React.DOM.div({'key':'mainPanel', 'id':'mainPanel', 'className':React.addons.classSet(classes)}, [
|
||||
React.DOM.div({'className':'mask', 'onClick': this.handleMaskClick}),
|
||||
React.DOM.div({'className':'container'},
|
||||
// this.style() == 'extra-wide' ? this.renderExtraWide() : this.renderOther()
|
||||
this.renderLayout(this.style())
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components.Panels');
|
||||
|
||||
Clipperz.PM.UI.Components.Panels.SelectionPanel = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
selectionPanelStatus: React.PropTypes.oneOf(['OPEN', 'CLOSED']).isRequired
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
//console.log("SelectionPanel", this.props);
|
||||
var classes = React.addons.classSet({
|
||||
'panel': true,
|
||||
'left': true,
|
||||
'open': this.props['selectionPanelStatus'] == 'OPEN'
|
||||
});
|
||||
|
||||
return React.DOM.div({'key':'selectionPanel', 'id':'selectionPanel', 'className':classes}, [
|
||||
Clipperz.PM.UI.Components.Selections(this.props),
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.PM.UI.Components.PreferencePage = React.createClass({
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
// card: React.PropTypes.object.isRequired
|
||||
// checked: React.PropTypes.boolean.isRequired
|
||||
},
|
||||
|
||||
getInitialState: function () {
|
||||
// return {
|
||||
// shouldStoreDataLocally: false
|
||||
// };
|
||||
},
|
||||
|
||||
handleBackClick: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack');
|
||||
},
|
||||
|
||||
toggleShouldStoreDataLocally: function (anEvent) {
|
||||
// this.setState({shouldStoreDataLocally: !this.state['shouldStoreDataLocally']});
|
||||
Clipperz.PM.DataModel.devicePreferences.setShouldStoreDataLocally(!Clipperz.PM.DataModel.devicePreferences.shouldStoreDataLocally());
|
||||
this.setState({});
|
||||
},
|
||||
|
||||
shouldStoreDataLocally: function () {
|
||||
return Clipperz.PM.DataModel.devicePreferences.shouldStoreDataLocally();
|
||||
},
|
||||
|
||||
syncNow: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'synchronizeLocalData');
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
render: function () {
|
||||
return React.DOM.div({className:'preferences'}, [
|
||||
React.DOM.div({className:'header'}, [
|
||||
React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, "Preferences")),
|
||||
React.DOM.div({className:'backWrapper'}, React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")),
|
||||
]),
|
||||
React.DOM.div({className:'content'}, [
|
||||
React.DOM.form(null, [
|
||||
React.DOM.div({className:'section'}, [
|
||||
React.DOM.h4(null, "Local storage"),
|
||||
React.DOM.p(null, "Store you account data locally for offline viewing"),
|
||||
new Clipperz.PM.UI.Components.Checkbox({'id':'shouldStoreLocally_checkbox', 'checked':this.shouldStoreDataLocally(), 'eventHandler':this.toggleShouldStoreDataLocally}),
|
||||
this.shouldStoreDataLocally() ? React.DOM.div({className:'syncInfo'}, [
|
||||
// React.DOM.h5(null, "data were never synchronized before"),
|
||||
React.DOM.a({className:'button', onClick:this.syncNow}, "Sync now")
|
||||
]) : null
|
||||
])
|
||||
])
|
||||
]),
|
||||
React.DOM.div({className:'footer'}, [
|
||||
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
57
frontend/delta/js/Clipperz/PM/UI/Components/Selections.js
Normal file
57
frontend/delta/js/Clipperz/PM/UI/Components/Selections.js
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.Selections = React.createClass({
|
||||
|
||||
//=========================================================================
|
||||
|
||||
selectAll: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'selectAllCards');
|
||||
},
|
||||
|
||||
selectRecent: function (anEvent) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'selectRecentCards');
|
||||
},
|
||||
|
||||
render: function () {
|
||||
//console.log("Selections", this.props);
|
||||
return React.DOM.div({'key':'selections', 'id':'selections'}, [
|
||||
React.DOM.ul({'className':'defaultSet'}, [
|
||||
React.DOM.li({'className':'allCards', onClick: this.selectAll}, "All"),
|
||||
React.DOM.li({'className':'recentCards', onClick: this.selectRecent}, "Recent")
|
||||
]),
|
||||
React.DOM.div({'className':'search'}, [
|
||||
React.DOM.form({'className':'searchForm'}, [
|
||||
React.DOM.label({'htmlFor':'searchValue'}, 'search'),
|
||||
React.DOM.input({'type':'text', 'id':'searchValue', 'name':'search'})
|
||||
])
|
||||
]),
|
||||
React.DOM.ul({'className':'tagList'}, MochiKit.Base.map(function (aTag) { return Clipperz.PM.UI.Components.TagIndexItem({'label':aTag}); }, this.props['tags'] ? this.props['tags'] : []))
|
||||
]);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
});
|
45
frontend/delta/js/Clipperz/PM/UI/Components/TagIndexItem.js
Normal file
45
frontend/delta/js/Clipperz/PM/UI/Components/TagIndexItem.js
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
Clipperz.Base.module('Clipperz.PM.UI.Components');
|
||||
|
||||
Clipperz.PM.UI.Components.TagIndexItem = React.createClass({
|
||||
|
||||
//=========================================================================
|
||||
|
||||
propTypes: {
|
||||
'label': React.PropTypes.string.isRequired,
|
||||
},
|
||||
|
||||
handleClick: function (anEvent) {
|
||||
//console.log("TAG INDEX ITEM - handle click TAG", anEvent.target.dataset.tag);
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'tagSelected', anEvent.target.dataset.tag);
|
||||
},
|
||||
|
||||
render: function () {
|
||||
return React.DOM.li({onClick: this.handleClick, 'data-tag':this.props['label']}, this.props['label']);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
});
|
@ -23,17 +23,17 @@ refer to http://www.clipperz.com.
|
||||
|
||||
Clipperz.Base.module('Clipperz.PM.UI');
|
||||
|
||||
Clipperz.PM.UI.DirectLoginRunner = function(args) {
|
||||
Clipperz.PM.UI.DirectLoginController = function(args) {
|
||||
this._directLogin = args['directLogin'] || Clipperz.Base.exception.raise('MandatoryParameter');
|
||||
this._target = Clipperz.PM.Crypto.randomKey();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
MochiKit.Base.update(Clipperz.PM.UI.DirectLoginRunner.prototype, {
|
||||
MochiKit.Base.update(Clipperz.PM.UI.DirectLoginController.prototype, {
|
||||
|
||||
'toString': function() {
|
||||
return "Clipperz.PM.UI.DirectLoginRunner";
|
||||
return "Clipperz.PM.UI.DirectLoginController";
|
||||
},
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -237,19 +237,19 @@ MochiKit.Base.update(Clipperz.PM.UI.DirectLoginRunner.prototype, {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.UI.DirectLoginRunner.openDirectLogin = function (aDirectLogin) {
|
||||
Clipperz.PM.UI.DirectLoginController.openDirectLogin = function (aDirectLogin) {
|
||||
var runner;
|
||||
|
||||
runner = new Clipperz.PM.UI.DirectLoginRunner({directLogin:aDirectLogin});
|
||||
runner = new Clipperz.PM.UI.DirectLoginController({directLogin:aDirectLogin});
|
||||
return runner.run();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Clipperz.PM.UI.DirectLoginRunner.testDirectLogin = function (aDirectLogin) {
|
||||
Clipperz.PM.UI.DirectLoginController.testDirectLogin = function (aDirectLogin) {
|
||||
var runner;
|
||||
|
||||
runner = new Clipperz.PM.UI.DirectLoginRunner({directLogin:aDirectLogin});
|
||||
runner = new Clipperz.PM.UI.DirectLoginController({directLogin:aDirectLogin});
|
||||
return runner.test();
|
||||
};
|
||||
|
||||
|
@ -21,31 +21,65 @@ refer to http://www.clipperz.com.
|
||||
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
Clipperz.Base.module('Clipperz.PM.UI');
|
||||
|
||||
Clipperz.PM.UI.MainController = function() {
|
||||
var pages;
|
||||
var genericPageProperties;
|
||||
|
||||
// this._proxy = null;
|
||||
this._mediaQueryStyle = "narrow";
|
||||
this._user = null;
|
||||
this._filter = '';
|
||||
|
||||
// this._currentPage = 'loadingPage';
|
||||
this._filter = {'type':'ALL'};
|
||||
|
||||
this._isSelectionPanelOpen = false;
|
||||
this._isSettingsPanelOpen = false;
|
||||
|
||||
this._pageStack = ['loadingPage'];
|
||||
this._overlay = new Clipperz.PM.UI.Components.Overlay();
|
||||
pages = {
|
||||
'loginPage': new Clipperz.PM.UI.Components.LoginForm(),
|
||||
'registrationPage': new Clipperz.PM.UI.Components.RegistrationWizard(),
|
||||
'cardListPage': new Clipperz.PM.UI.Components.CardList(),
|
||||
'cardDetailPage': new Clipperz.PM.UI.Components.CardDetail({card: {}}),
|
||||
'preferencePage': new Clipperz.PM.UI.Components.PreferencePage(),
|
||||
'errorPage': new Clipperz.PM.UI.Components.ErrorPage({message:''})
|
||||
};
|
||||
|
||||
MochiKit.Base.map(function (anId) {React.renderComponent(pages[anId], MochiKit.DOM.getElement(anId))}, MochiKit.Base.keys(pages));
|
||||
this._pages = pages;
|
||||
this.registerForNotificationCenterEvents();
|
||||
this._isTouchDevice = ('ontouchstart' in window || 'onmsgesturechange' in window);
|
||||
this._isDesktop = window.screenX != 0 && !this._isTouchDevice;
|
||||
this._hasKeyboard = this._isDesktop;
|
||||
|
||||
this._closeMaskAction = null;
|
||||
|
||||
this._pages = {};
|
||||
this.renderPages([
|
||||
'loginPage',
|
||||
'registrationPage',
|
||||
'mainPage',
|
||||
'cardDetailPage',
|
||||
'errorPage',
|
||||
]);
|
||||
|
||||
this.registerForNotificationCenterEvents([
|
||||
'doLogin',
|
||||
'registerNewUser',
|
||||
'showRegistrationForm',
|
||||
'goBack',
|
||||
|
||||
'toggleSelectionPanel',
|
||||
'toggleSettingsPanel',
|
||||
|
||||
'matchMediaQuery',
|
||||
'unmatchMediaQuery',
|
||||
|
||||
'selectAllCards',
|
||||
'selectRecentCards',
|
||||
'tagSelected',
|
||||
|
||||
'cardSelected',
|
||||
|
||||
'addCardClick',
|
||||
'deleteCard',
|
||||
'archiveCard',
|
||||
'editCard',
|
||||
|
||||
'goBackToMainPage',
|
||||
'maskClick',
|
||||
]);
|
||||
|
||||
MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onselectionchange', this, 'selectionChangeHandler');
|
||||
|
||||
return this;
|
||||
@ -125,26 +159,30 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
//=========================================================================
|
||||
|
||||
registerForNotificationCenterEvents: function () {
|
||||
var events = [
|
||||
'doLogin',
|
||||
'registerNewUser',
|
||||
'showRegistrationForm',
|
||||
'goBack',
|
||||
'showRecord',
|
||||
'searchCards',
|
||||
'showPreferences',
|
||||
'runDirectLogin',
|
||||
'synchronizeLocalData'
|
||||
];
|
||||
var self = this;
|
||||
capitaliseFirstLetter: function (aValue) {
|
||||
return aValue.charAt(0).toUpperCase() + aValue.slice(1);
|
||||
},
|
||||
|
||||
renderPages: function (pages) {
|
||||
var self = this;
|
||||
MochiKit.Iter.forEach(pages, function (aPageName) {
|
||||
//console.log("RENDERING", aPageName);
|
||||
self._pages[aPageName] = React.renderComponent(
|
||||
Clipperz.PM.UI.Components.Pages[self.capitaliseFirstLetter(aPageName)](self.pageProperties(aPageName)),
|
||||
MochiKit.DOM.getElement(aPageName)
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
MochiKit.Base.map(function (anEvent) {
|
||||
MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent));
|
||||
}, events);
|
||||
registerForNotificationCenterEvents: function (events) {
|
||||
var self = this;
|
||||
|
||||
MochiKit.Iter.forEach(events, function (anEvent) {
|
||||
MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent + '_handler'));
|
||||
});
|
||||
|
||||
// MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack'));
|
||||
MochiKit.Signal.connect(window, 'onbeforeunload', MochiKit.Base.method(this, 'shouldExitApp'));
|
||||
// MochiKit.Signal.connect(window, 'onbeforeunload', MochiKit.Base.method(this, 'shouldExitApp'));
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -198,11 +236,13 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable':canRegisterNewUsers});
|
||||
|
||||
if (shouldShowRegistrationForm) {
|
||||
this.showRegistrationForm();
|
||||
this.showRegistrationForm_handler();
|
||||
} else {
|
||||
this.showLoginForm();
|
||||
}
|
||||
this.overlay().done("", 0.5);
|
||||
|
||||
// this.overlay().done("", 0.5);
|
||||
this.overlay().hide();
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -216,7 +256,7 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus'));
|
||||
},
|
||||
|
||||
showRegistrationForm: function () {
|
||||
showRegistrationForm_handler: function () {
|
||||
var currentPage;
|
||||
var registrationPage;
|
||||
|
||||
@ -230,7 +270,12 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
//=========================================================================
|
||||
|
||||
doLogin: function (event) {
|
||||
doLogin_handler: function (event) {
|
||||
return this.doLogin(event);
|
||||
},
|
||||
|
||||
doLogin: function (someCredentials) {
|
||||
var deferredResult;
|
||||
var credentials;
|
||||
var getPassphraseDelegate;
|
||||
var user;
|
||||
@ -240,10 +285,10 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
this.overlay().show("logging in");
|
||||
this.pages()['loginPage'].setProps({disabled:true});
|
||||
|
||||
if ('pin' in event) {
|
||||
credentials = Clipperz.PM.PIN.credentialsWithPIN(event['pin']);
|
||||
if ('pin' in someCredentials) {
|
||||
credentials = Clipperz.PM.PIN.credentialsWithPIN(someCredentials['pin']);
|
||||
} else {
|
||||
credentials = event;
|
||||
credentials = someCredentials;
|
||||
}
|
||||
getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase);
|
||||
user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate});
|
||||
@ -254,18 +299,16 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount');
|
||||
deferredResult.addMethod(this, 'setUser', user);
|
||||
|
||||
// deferredResult.addMethod(this, 'setupApplication');
|
||||
deferredResult.addMethod(this, 'runApplication');
|
||||
deferredResult.addMethod(this.overlay(), 'done', "", 1);
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event));
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', someCredentials));
|
||||
deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) {
|
||||
if (anError['isPermanent'] != true) {
|
||||
this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()});
|
||||
this.pages()['loginPage'].setInitialFocus();
|
||||
}
|
||||
return anError;
|
||||
}, this, event))
|
||||
}, this, someCredentials))
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
@ -273,19 +316,19 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
registerNewUser: function (credentials) {
|
||||
registerNewUser_handler: function (credentials) {
|
||||
var deferredResult;
|
||||
|
||||
this.overlay().show("creating user");
|
||||
|
||||
this.pages()['registrationPage'].setProps({disabled:true});
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:false});
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:true});
|
||||
deferredResult.addCallback(Clipperz.PM.DataModel.User.registerNewAccount,
|
||||
credentials['username'],
|
||||
MochiKit.Base.partial(MochiKit.Async.succeed, credentials['passphrase'])
|
||||
);
|
||||
deferredResult.addMethod(this, 'doLogin', credentials);
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event));
|
||||
deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', credentials));
|
||||
deferredResult.addErrback(MochiKit.Base.bind(function (anError) {
|
||||
if (anError['isPermanent'] != true) {
|
||||
this.pages()['registrationPage'].setProps({disabled:false});
|
||||
@ -307,109 +350,222 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
},
|
||||
|
||||
setUser: function (aUser) {
|
||||
console.log("SET USER", aUser);
|
||||
this._user = aUser;
|
||||
return this._user;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
|
||||
allCardInfo: function () {
|
||||
var deferredResult;
|
||||
var cardInfo;
|
||||
|
||||
cardInfo = {
|
||||
'_rowObject': MochiKit.Async.succeed,
|
||||
'_reference': MochiKit.Base.methodcaller('reference'),
|
||||
'_searchableContent': MochiKit.Base.methodcaller('searchableContent'),
|
||||
'label': MochiKit.Base.methodcaller('label'),
|
||||
'favicon': MochiKit.Base.methodcaller('favicon')
|
||||
};
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.allCardInfo', {trace:false});
|
||||
deferredResult.addMethod(this.user(), 'getRecords');
|
||||
deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false}));
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll);
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
filterCards: function (someCardInfo) {
|
||||
var filter;
|
||||
var filterRegExp;
|
||||
var result;
|
||||
|
||||
filter = this.filter().replace(/[^A-Za-z0-9]/g, "\\$&");
|
||||
filterRegExp = new RegExp(filter, "i");
|
||||
result = MochiKit.Base.filter(function (aCardInfo) { return filterRegExp.test(aCardInfo['_searchableContent'])}, someCardInfo);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
sortCards: function (someCardInfo) {
|
||||
return someCardInfo.sort(Clipperz.Base.caseInsensitiveKeyComparator('label'));
|
||||
},
|
||||
|
||||
showRecordList: function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.showRecordList', {trace:false});
|
||||
deferredResult.addMethod(this, 'allCardInfo');
|
||||
deferredResult.addMethod(this, 'filterCards');
|
||||
deferredResult.addMethod(this, 'sortCards');
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (someRecordInfo) {
|
||||
this.pages()['cardListPage'].setProps({cardList: someRecordInfo});
|
||||
}, this));
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
filter: function () {
|
||||
return this._filter;
|
||||
},
|
||||
|
||||
setFilter: function (aValue) {
|
||||
this._filter = aValue;
|
||||
setFilter: function (aType, aValue) {
|
||||
this._filter = {'type':aType, 'value':aValue};
|
||||
return this._filter;
|
||||
},
|
||||
|
||||
searchCards: function (someParameters) {
|
||||
//console.log("SEARCH CARDS", someParameters);
|
||||
this.setFilter(someParameters);
|
||||
this.showRecordList();
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
collectFieldInfo: function (aField) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.collectFieldInfo', {trace:false});
|
||||
deferredResult.addMethod(aField, 'reference');
|
||||
deferredResult.setValue('_reference');
|
||||
deferredResult.addMethod(aField, 'label');
|
||||
deferredResult.setValue('label');
|
||||
deferredResult.addMethod(aField, 'value');
|
||||
deferredResult.setValue('value');
|
||||
deferredResult.addMethod(aField, 'actionType');
|
||||
deferredResult.setValue('actionType');
|
||||
deferredResult.addMethod(aField, 'isHidden');
|
||||
deferredResult.setValue('isHidden');
|
||||
deferredResult.values();
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
collectDirectLoginInfo: function (aDirectLogin) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.collectDirectLoginInfo', {trace:false});
|
||||
deferredResult.addMethod(aDirectLogin, 'reference');
|
||||
deferredResult.setValue('_reference');
|
||||
deferredResult.addMethod(aDirectLogin, 'label');
|
||||
deferredResult.setValue('label');
|
||||
deferredResult.addMethod(aDirectLogin, 'favicon');
|
||||
deferredResult.setValue('favicon');
|
||||
deferredResult.values();
|
||||
|
||||
runApplication: function () {
|
||||
MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack'));
|
||||
/// TODO: remove this TEST HACK
|
||||
this.moveInPage(this.currentPage(), 'cardListPage');
|
||||
return this.showRecordList();
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
collectRecordInfo: function (aRecord) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.collectRecordInfo', {trace:false});
|
||||
deferredResult.addMethod(aRecord, 'reference');
|
||||
deferredResult.setValue('_reference');
|
||||
deferredResult.addMethod(aRecord, 'label');
|
||||
deferredResult.setValue('label');
|
||||
deferredResult.addMethod(aRecord, 'notes');
|
||||
deferredResult.setValue('notes');
|
||||
deferredResult.addMethod(aRecord, 'tags');
|
||||
deferredResult.setValue('tags');
|
||||
|
||||
// this.moveInPage(this.currentPage(), 'preferencePage');
|
||||
deferredResult.addMethod(aRecord, 'fields');
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'collectFieldInfo'));
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll);
|
||||
deferredResult.setValue('fields');
|
||||
|
||||
deferredResult.addMethod(aRecord, 'directLogins');
|
||||
deferredResult.addCallback(MochiKit.Base.values);
|
||||
deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'collectDirectLoginInfo'));
|
||||
deferredResult.addCallback(Clipperz.Async.collectAll);
|
||||
deferredResult.setValue('directLogins');
|
||||
|
||||
deferredResult.values();
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
showRecord: function (aRecordReference) {
|
||||
//console.log("Show Record", aRecordReference);
|
||||
var deferredResult;
|
||||
updateSelectedCard: function (someInfo) {
|
||||
var deferredResult;
|
||||
|
||||
this.pages()['cardListPage'].setProps({selectedCard:aRecordReference});
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false});
|
||||
deferredResult.addMethod(this.user(), 'getRecord', aRecordReference);
|
||||
deferredResult.addMethodcaller('content');
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (aCard) {
|
||||
//console.log("CARD DETAILS", aCard);
|
||||
this.pages()['cardDetailPage'].setProps({card: aCard});
|
||||
this.pages()['cardListPage'].setProps({selectedCard: null});
|
||||
if (someInfo == null) {
|
||||
this.setPageProperties('mainPage', 'selectedCard', {});
|
||||
deferredResult = MochiKit.Async.succeed();
|
||||
} else {
|
||||
this.setPageProperties('mainPage', 'selectedCard', {'loading':true, 'label':someInfo['label'], '_reference':someInfo['reference']});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.updateSelectedCard', {trace:false});
|
||||
deferredResult.addMethod(this.user(), 'getRecord', someInfo['reference']);
|
||||
deferredResult.addMethod(this, 'collectRecordInfo');
|
||||
|
||||
//console.log("MEDIA QUERY STYLE", this.mediaQueryStyle());
|
||||
deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'selectedCard');
|
||||
if (this.mediaQueryStyle() == 'narrow') {
|
||||
deferredResult.addMethod(this, 'setPageProperties', 'cardDetailPage', 'selectedCard');
|
||||
deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage');
|
||||
// deferredResult.addCallback(function (aValue) { console.log("SHOULD SLIDE IN PAGE DETAIL"); return aValue; });
|
||||
//console.log("SHOULD SLIDE IN PAGE DETAIL");
|
||||
}
|
||||
|
||||
MochiKit.Async.callLater(0.1, MochiKit.Base.method(deferredResult, 'callback'));
|
||||
}
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//............................................................................
|
||||
|
||||
regExpFilterGenerator: function (aRegExp, aSearchField) {
|
||||
var searchField = aSearchField ? aSearchField : Clipperz.PM.DataModel.Record.defaultSearchField;
|
||||
|
||||
return function (aCardInfo) {
|
||||
aRegExp.lastIndex = 0;
|
||||
return aRegExp.test(aCardInfo[searchField]);
|
||||
}
|
||||
},
|
||||
|
||||
selectedCardReference: function () {
|
||||
return this.pages()['mainPage'].props &&
|
||||
this.pages()['mainPage'].props['selectedCard'] &&
|
||||
this.pages()['mainPage'].props['selectedCard'] &&
|
||||
this.pages()['mainPage'].props['selectedCard']['_reference']
|
||||
? this.pages()['mainPage'].props['selectedCard']['_reference']
|
||||
: '';
|
||||
},
|
||||
|
||||
isSelectedCardStillVisible: function (someCards) {
|
||||
var result;
|
||||
var reference;
|
||||
|
||||
reference = this.selectedCardReference();
|
||||
result = MochiKit.Iter.some(someCards, function (aCardInfo) {
|
||||
return aCardInfo['_reference'] == reference;
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
updateSelectedCards: function (shouldIncludeArchivedCards, aFilter) {
|
||||
var deferredResult;
|
||||
var sortCriteria;
|
||||
|
||||
sortCriteria = Clipperz.Base.caseInsensitiveKeyComparator('label');
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.setFilter', {trace:false});
|
||||
deferredResult.addMethod(this.user(), 'getRecordsInfo', Clipperz.PM.DataModel.Record.defaultCardInfo, shouldIncludeArchivedCards);
|
||||
|
||||
if (aFilter['type'] == 'ALL') {
|
||||
deferredResult.addMethodcaller('sort', sortCriteria);
|
||||
} else if (aFilter['type'] == 'RECENT') {
|
||||
deferredResult.addMethodcaller('sort', Clipperz.Base.reverseComparator(MochiKit.Base.keyComparator('accessDate')));
|
||||
deferredResult.addCallback(function (someCards) { return someCards.slice(0, 9)});
|
||||
} else if (aFilter['type'] == 'SEARCH') {
|
||||
deferredResult.addCallback(MochiKit.Base.filter, this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForSearch(aFilter['value'])));
|
||||
deferredResult.addMethodcaller('sort', sortCriteria);
|
||||
} else if (aFilter['type'] == 'TAG') {
|
||||
deferredResult.addCallback(MochiKit.Base.filter, this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForTag(aFilter['value'])));
|
||||
deferredResult.addMethodcaller('sort', sortCriteria);
|
||||
}
|
||||
|
||||
deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'cards');
|
||||
deferredResult.addCallback(MochiKit.Base.bind(function (someCards) {
|
||||
if (!this.isSelectedCardStillVisible(someCards)) {
|
||||
this.updateSelectedCard(null);
|
||||
};
|
||||
}, this));
|
||||
deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage', true);
|
||||
deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'filter', this.filter());
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
setPageProperties: function (aPageName, aKey, aValue) {
|
||||
var props = {};
|
||||
props[aKey] = aValue;
|
||||
this.pages()[aPageName].setProps(props);
|
||||
|
||||
return aValue;
|
||||
},
|
||||
|
||||
renderAccountData: function () {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.renderAccountData', {trace:false});
|
||||
deferredResult.addMethod(this, 'setFilter', 'ALL');
|
||||
deferredResult.addMethod(this, 'updateSelectedCards', false);
|
||||
|
||||
deferredResult.addMethod(this.user(), 'getTags');
|
||||
deferredResult.addMethodcaller('sort', Clipperz.Base.caseInsensitiveCompare);
|
||||
deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'tags');
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
runDirectLogin: function (someParameters) {
|
||||
//=========================================================================
|
||||
|
||||
runApplication: function (anUser) {
|
||||
this.moveInPage(this.currentPage(), 'mainPage');
|
||||
return this.renderAccountData();
|
||||
},
|
||||
/*
|
||||
runDirectLogin_handler: function (someParameters) {
|
||||
//console.log("RUN DIRECT LOGIN", someParameters);
|
||||
var deferredResult;
|
||||
|
||||
@ -427,10 +583,18 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
anEvent.preventDefault();
|
||||
anEvent.stopPropagation();
|
||||
},
|
||||
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
showPreferences: function (anEvent) {
|
||||
/*
|
||||
searchCards_handler: function (someParameters) {
|
||||
//console.log("SEARCH CARDS", someParameters);
|
||||
this.setFilter(someParameters);
|
||||
this.renderAccountData();
|
||||
},
|
||||
*/
|
||||
//=========================================================================
|
||||
/*
|
||||
showPreferences_handler: function (anEvent) {
|
||||
var deferredResult;
|
||||
|
||||
this.pages()['preferencePage'].setProps({});
|
||||
@ -440,7 +604,7 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
*/
|
||||
//=========================================================================
|
||||
|
||||
genericErrorHandler: function (anEvent, anError) {
|
||||
@ -471,39 +635,35 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
slidePage: function (fromPage, toPage, direction) {
|
||||
var fromPosition;
|
||||
var toPosition;
|
||||
var toPosition;
|
||||
var itemToTransition;
|
||||
|
||||
if (direction == "LEFT") {
|
||||
fromPosition = 'right';
|
||||
toPosition = 'left'
|
||||
toPosition = 'left';
|
||||
itemToTransition = toPage;
|
||||
} else {
|
||||
fromPosition = 'left';
|
||||
toPosition = 'right'
|
||||
toPosition = 'right';
|
||||
itemToTransition = fromPage;
|
||||
}
|
||||
|
||||
MochiKit.DOM.addElementClass(fromPage, toPosition + ' transition');
|
||||
MochiKit.DOM.addElementClass(itemToTransition, 'transition');
|
||||
|
||||
MochiKit.DOM.addElementClass(toPage, fromPosition);
|
||||
MochiKit.DOM.removeElementClass(toPage, toPosition);
|
||||
MochiKit.DOM.addElementClass(toPage, 'transition');
|
||||
MochiKit.Async.callLater(0.1, function () {
|
||||
MochiKit.Async.callLater(0, function () {
|
||||
MochiKit.DOM.addElementClass(fromPage, toPosition);
|
||||
MochiKit.DOM.removeElementClass(toPage, fromPosition);
|
||||
})
|
||||
|
||||
MochiKit.Async.callLater(0.5, function () {
|
||||
MochiKit.DOM.removeElementClass(fromPage, 'transition');
|
||||
MochiKit.DOM.removeElementClass(toPage, 'transition');
|
||||
MochiKit.DOM.removeElementClass(itemToTransition, 'transition');
|
||||
})
|
||||
},
|
||||
|
||||
rotateInPage: function (fromPage, toPage) {
|
||||
// Broken! :(
|
||||
MochiKit.DOM.addElementClass(MochiKit.DOM.getElement('mainDiv'), 'show-right');
|
||||
},
|
||||
|
||||
//.........................................................................
|
||||
|
||||
goBack: function () {
|
||||
goBack_handler: function () {
|
||||
var fromPage;
|
||||
var toPage;
|
||||
|
||||
@ -525,6 +685,7 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
setCurrentPage: function (aPage) {
|
||||
this.pageStack().unshift(aPage);
|
||||
this.refreshCurrentPage();
|
||||
},
|
||||
|
||||
moveInPage: function (fromPage, toPage, addToHistory) {
|
||||
@ -552,12 +713,108 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
this.setCurrentPage(toPage);
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
synchronizeLocalData: function (anEvent) {
|
||||
messageBoxContent: function () {
|
||||
var message;
|
||||
var level;
|
||||
|
||||
message = "";
|
||||
level = 'HIDE';
|
||||
|
||||
//console.log("messageBox - this.user()", this.user());
|
||||
if (this.user() != null && this.user().accountInfo() != null && this.user().accountInfo().featureSet() == 'EXPIRED') {
|
||||
message = "Exprired subscription";
|
||||
level = 'ERROR';
|
||||
}
|
||||
|
||||
return {
|
||||
'message': message,
|
||||
'level': level
|
||||
};
|
||||
},
|
||||
|
||||
userAccountInfo: function () {
|
||||
var result;
|
||||
|
||||
result = {};
|
||||
|
||||
if (this.user() != null) {
|
||||
var usefulFields = [
|
||||
'currentSubscriptionType',
|
||||
'expirationDate',
|
||||
'featureSet',
|
||||
'isExpired',
|
||||
'isExpiring',
|
||||
'paymentVerificationPending'
|
||||
];
|
||||
|
||||
var attributes = this.user().accountInfo()._attributes;
|
||||
MochiKit.Iter.forEach(usefulFields, function (aFieldName) {
|
||||
result[aFieldName] = attributes[aFieldName];
|
||||
})
|
||||
};
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
genericPageProperties: function () {
|
||||
return {
|
||||
'style': this.mediaQueryStyle(),
|
||||
'isTouchDevice': this.isTouchDevice(),
|
||||
'isDesktop': this.isDesktop(),
|
||||
'hasKeyboard': this.hasKeyboard()
|
||||
};
|
||||
},
|
||||
|
||||
pageProperties: function (aPageName) {
|
||||
var result;
|
||||
var extraProperties = null;
|
||||
|
||||
result = this.genericPageProperties();
|
||||
|
||||
if (aPageName == 'loginPage') {
|
||||
extraProperties = {
|
||||
'mode': 'CREDENTIALS',
|
||||
'isNewUserRegistrationAvailable': true,
|
||||
'disabled': false,
|
||||
};
|
||||
} else if (aPageName == 'registrationPage') {
|
||||
} else if (aPageName == 'mainPage') {
|
||||
extraProperties = {
|
||||
'messageBox': this.messageBoxContent(),
|
||||
'accountStatus': this.userAccountInfo(),
|
||||
'selectionPanelStatus': this.isSelectionPanelOpen() ? 'OPEN' : 'CLOSED',
|
||||
'settingsPanelStatus': this.isSettingsPanelOpen() ? 'OPEN' : 'CLOSED',
|
||||
// 'cards': …,
|
||||
// 'tags': …,
|
||||
// 'selectedCard': …,
|
||||
};
|
||||
} else if (aPageName == 'errorPage') {
|
||||
extraProperties = {
|
||||
'message': ''
|
||||
};
|
||||
}
|
||||
|
||||
if (extraProperties != null) {
|
||||
result = MochiKit.Base.update(result, extraProperties);
|
||||
}
|
||||
//console.log("MainController.pageProperties", result);
|
||||
return result;
|
||||
},
|
||||
|
||||
refreshCurrentPage: function () {
|
||||
if (this.pages()[this.currentPage()] != null) {
|
||||
this.pages()[this.currentPage()].setProps(this.pageProperties(this.currentPage()));
|
||||
}
|
||||
},
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
synchronizeLocalData_handler: function (anEvent) {
|
||||
var deferredResult;
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.synchronizeLocalData', {trace:true});
|
||||
deferredResult = new Clipperz.Async.Deferred('MainController.synchronizeLocalData', {trace:false});
|
||||
// deferredResult.addMethod(this.proxy(), 'message', 'downloadAccountData', {});
|
||||
deferredResult.addMethod(this.user().connection(), 'message', 'downloadAccountData', {});
|
||||
deferredResult.addCallback(function (aResult) {
|
||||
@ -570,8 +827,126 @@ console.log("THE BROWSER IS OFFLINE");
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
*/
|
||||
|
||||
//=========================================================================
|
||||
|
||||
resetPanels: function () {
|
||||
this._isSelectionPanelOpen = false;
|
||||
this._isSettingsPanelOpen = false;
|
||||
},
|
||||
|
||||
isSelectionPanelOpen: function () {
|
||||
return this._isSelectionPanelOpen;
|
||||
},
|
||||
|
||||
|
||||
toggleSelectionPanel_handler: function (anEvent) {
|
||||
this._isSelectionPanelOpen = !this._isSelectionPanelOpen;
|
||||
this.setCloseMaskAction(MochiKit.Base.method(this, 'toggleSelectionPanel_handler'));
|
||||
this.refreshCurrentPage();
|
||||
},
|
||||
|
||||
|
||||
isSettingsPanelOpen: function () {
|
||||
return this._isSettingsPanelOpen;
|
||||
},
|
||||
|
||||
toggleSettingsPanel_handler: function (anEvent) {
|
||||
this._isSettingsPanelOpen = !this._isSettingsPanelOpen;
|
||||
this.setCloseMaskAction(MochiKit.Base.method(this, 'toggleSettingsPanel_handler'));
|
||||
this.refreshCurrentPage();
|
||||
},
|
||||
|
||||
cardSelected_handler: function (aReference) {
|
||||
this.updateSelectedCard(aReference);
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
addCardClick_handler: function () {
|
||||
console.log("ADD CARD CLICK");
|
||||
},
|
||||
|
||||
deleteCard_handler: function (anEvent) {
|
||||
console.log("DELETE CARD", anEvent['reference']);
|
||||
},
|
||||
|
||||
archiveCard_handler: function (anEvent) {
|
||||
console.log("ARCHIVE CARD", anEvent['reference']);
|
||||
},
|
||||
|
||||
editCard_handler: function (anEvent) {
|
||||
console.log("EDIT CARD", anEvent['reference']);
|
||||
},
|
||||
|
||||
goBackToMainPage_handler: function (anEvent) {
|
||||
this.updateSelectedCard();
|
||||
this.moveOutPage(this.currentPage(), 'mainPage');
|
||||
},
|
||||
|
||||
//============================================================================
|
||||
|
||||
selectAllCards_handler: function () {
|
||||
this.setFilter('ALL');
|
||||
this.updateSelectedCards(false, this.filter());
|
||||
},
|
||||
|
||||
selectRecentCards_handler: function () {
|
||||
this.setFilter('RECENT');
|
||||
this.updateSelectedCards(false, this.filter());
|
||||
},
|
||||
|
||||
tagSelected_handler: function (aTag) {
|
||||
this.setFilter('TAG', aTag);
|
||||
this.updateSelectedCards(false, this.filter());
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
setCloseMaskAction: function (aFunction) {
|
||||
this._closeMaskAction = aFunction;
|
||||
},
|
||||
|
||||
maskClick_handler: function () {
|
||||
this._closeMaskAction.apply(this);
|
||||
this._closeMaskAction = null;
|
||||
},
|
||||
|
||||
//============================================================================
|
||||
|
||||
matchMediaQuery_handler: function (newQueryStyle) {
|
||||
this._mediaQueryStyle = newQueryStyle;
|
||||
|
||||
if (this.currentPage() == 'cardDetailPage') {
|
||||
this.moveOutPage(this.currentPage(), 'mainPage');
|
||||
}
|
||||
this.resetPanels();
|
||||
this.refreshCurrentPage();
|
||||
},
|
||||
|
||||
unmatchMediaQuery_handler: function (queryStyle) {
|
||||
},
|
||||
|
||||
mediaQueryStyle: function () {
|
||||
return this._mediaQueryStyle;
|
||||
},
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
isTouchDevice: function () {
|
||||
return this._isTouchDevice;
|
||||
},
|
||||
|
||||
isDesktop: function () {
|
||||
return this._isDesktop;
|
||||
},
|
||||
|
||||
hasKeyboard: function () {
|
||||
return this._hasKeyboard;
|
||||
},
|
||||
|
||||
//============================================================================
|
||||
/*
|
||||
wrongAppVersion: function (anError) {
|
||||
// this.pages()['errorPage'].setProps({message:anError.message});
|
||||
|
261
frontend/delta/js/OnMediaQuery/onmediaquery-0.2.0.js
Normal file
261
frontend/delta/js/OnMediaQuery/onmediaquery-0.2.0.js
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* onMediaQuery
|
||||
* http://springload.co.nz/love-the-web/
|
||||
*
|
||||
* Copyright 2012, Springload
|
||||
* Released under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Date: Fri 24 October, 2012
|
||||
*/
|
||||
|
||||
;(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(function () {
|
||||
// Also create a global in case some scripts
|
||||
// that are loaded still are looking for
|
||||
// a global even when an AMD loader is in use.
|
||||
return (root.MQ = factory(root, root.MQ || {}));
|
||||
});
|
||||
} else {
|
||||
// Browser globals
|
||||
root.MQ = factory(root, root.MQ || {});
|
||||
}
|
||||
}(this, function(mq) {
|
||||
/**
|
||||
* Initialises the MQ object and sets the initial media query callbacks
|
||||
* @returns Void(0)
|
||||
*/
|
||||
mq.init = function(query_array) {
|
||||
|
||||
// Container for all callbacks registered with the plugin
|
||||
this.callbacks = [];
|
||||
this.context = ''; //current active query
|
||||
this.new_context = ''; //current active query to be read inside callbacks, as this.context won't be set when they're called!
|
||||
|
||||
if (typeof(query_array) !== 'undefined' ) {
|
||||
for (i = 0; i < query_array.length; i++) {
|
||||
var r = this.addQuery(query_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a listener to the window.resize event, pass mq/self as the scope.
|
||||
this.addEvent(window, 'resize', mq.listenForChange, mq);
|
||||
|
||||
// Figure out which query is active on load.
|
||||
this.listenForChange();
|
||||
};
|
||||
|
||||
/**
|
||||
* Binds to the window.onResize and checks for media query changes
|
||||
* @returns Void(0)
|
||||
*/
|
||||
mq.listenForChange = function() {
|
||||
var query_string;
|
||||
|
||||
// Get the value of html { font-family } from the element style.
|
||||
if (document.documentElement.currentStyle) {
|
||||
query_string = document.documentElement.currentStyle["fontFamily"];
|
||||
}
|
||||
|
||||
if (window.getComputedStyle) {
|
||||
query_string = window.getComputedStyle(document.documentElement,null).getPropertyValue('font-family');
|
||||
}
|
||||
|
||||
// No support for CSS enumeration? Return and avoid errors.
|
||||
if (query_string === null) return;
|
||||
|
||||
// Android browsers place a "," after an item in the font family list.
|
||||
// Most browsers either single or double quote the string.
|
||||
query_string = query_string.replace(/['",]/g, '');
|
||||
|
||||
if (query_string !== this.context) {
|
||||
this.new_context = query_string;
|
||||
this.triggerCallbacks(this.context, 'unmatch');
|
||||
this.triggerCallbacks(this.new_context, 'match');
|
||||
}
|
||||
|
||||
this.context = this.new_context;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attach a new query to test.
|
||||
* @param query_object {
|
||||
* context: ['some_media_query','some_other_media_query'],
|
||||
* call_for_each_context: true,
|
||||
* callback: function() {
|
||||
* //something awesome
|
||||
* }
|
||||
* }
|
||||
* @returns A reference to the query_object that was added
|
||||
*/
|
||||
mq.addQuery = function(query_object) {
|
||||
if (query_object === null || query_object === undefined) return;
|
||||
|
||||
this.callbacks.push(query_object);
|
||||
|
||||
// If the context is passed as a string, turn it into an array (for unified approach elsewhere in the code)
|
||||
if (typeof(query_object.context) == "string") {
|
||||
query_object.context = [query_object.context];
|
||||
}
|
||||
|
||||
// See if "call_for_each_context" is set, if not, set a default (for unified approach elsewhere in the code)
|
||||
if (typeof(query_object.call_for_each_context) !== "boolean") {
|
||||
query_object.call_for_each_context = true; // Default
|
||||
}
|
||||
|
||||
// Fire the added callback if it matches the current context
|
||||
if (this.context !== '' && this._inArray(this.context, query_object.context)) {
|
||||
query_object.match();
|
||||
}
|
||||
|
||||
return this.callbacks[ this.callbacks.length - 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a query_object by reference.
|
||||
* @returns Void(0)
|
||||
*/
|
||||
mq.removeQuery = function(query_object) {
|
||||
if (query_object === null || query_object === undefined) return;
|
||||
|
||||
var match = -1;
|
||||
|
||||
while ((match = mq._indexOf(query_object,this.callbacks)) > -1) {
|
||||
this.callbacks.splice(match, 1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Loop through the stored callbacks and execute
|
||||
* the ones that are bound to the current context.
|
||||
* @returns Void(0)
|
||||
*/
|
||||
mq.triggerCallbacks = function(size, key) {
|
||||
var i, callback_function, call_for_each_context;
|
||||
|
||||
for (i = 0; i < this.callbacks.length; i++) {
|
||||
|
||||
// Don't call for each context?
|
||||
if(this.callbacks[i].call_for_each_context === false) {
|
||||
if ((key === 'match' && this._inArray(this.context, this.callbacks[i].context)) ||
|
||||
(key === 'unmatch' && this._inArray(this.new_context, this.callbacks[i].context))) {
|
||||
// Was previously called, and we don't want to call it for each context
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
callback_function = this.callbacks[i][key];
|
||||
if (this._inArray(size, this.callbacks[i].context) && callback_function !== undefined) {
|
||||
callback_function();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Swiss Army Knife event binding, in lieu of jQuery.
|
||||
* @returns Void(0)
|
||||
*/
|
||||
mq.addEvent = function(elem, type, eventHandle, eventContext) {
|
||||
if (elem === null || elem === undefined) return;
|
||||
// If the browser supports event listeners, use them.
|
||||
if (elem.addEventListener) {
|
||||
elem.addEventListener(type, function() { eventHandle.call(eventContext); }, false);
|
||||
} else if (elem.attachEvent ) {
|
||||
elem.attachEvent("on" + type, function() { eventHandle.call(eventContext); });
|
||||
|
||||
// Otherwise, replace the current thing bound to on[whatever]! Consider refactoring.
|
||||
} else {
|
||||
elem["on" + type] = function() { eventHandle.call(eventContext); };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to return the mediaquery's previous context
|
||||
* @returns String returns the current mediaquery's context
|
||||
*/
|
||||
mq.getPreviousContext = function()
|
||||
{
|
||||
return this.context;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to return the mediaquery's current context
|
||||
* @returns String returns the current mediaquery's context
|
||||
*/
|
||||
mq.getContext = function()
|
||||
{
|
||||
return this.new_context;
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal helper function that checks wether "needle" occurs in "haystack"
|
||||
* @param needle Mixed Value to look for in haystack array
|
||||
* @param haystack Array Haystack array to search in
|
||||
* @returns Boolan True if the needle occurs, false otherwise
|
||||
*/
|
||||
mq._inArray = function(needle, haystack)
|
||||
{
|
||||
var length = haystack.length;
|
||||
for(var i = 0; i < length; i++) {
|
||||
if(haystack[i] == needle) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* IE8 do not supports Array.properties.indexOf
|
||||
* copy from jQuery.
|
||||
* in lieu of jQuery.
|
||||
* @returns int
|
||||
*/
|
||||
mq._indexOf = function( elem, arr, i )
|
||||
{
|
||||
var len;
|
||||
if ( arr ) {
|
||||
if ( arr.indexOf ) {
|
||||
return arr.indexOf( elem, i );
|
||||
}
|
||||
|
||||
len = arr.length;
|
||||
i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
|
||||
|
||||
for ( ; i < len; i++ ) {
|
||||
// Skip accessing in sparse arrays
|
||||
if ( i in arr && arr[ i ] === elem ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Expose the functions.
|
||||
return mq;
|
||||
}));
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
20258
frontend/delta/js/React/react-with-addons-0.11.0.js
Executable file
20258
frontend/delta/js/React/react-with-addons-0.11.0.js
Executable file
File diff suppressed because it is too large
Load Diff
948
frontend/delta/js/TestData/User.data.js
Normal file
948
frontend/delta/js/TestData/User.data.js
Normal file
File diff suppressed because one or more lines are too long
@ -44,12 +44,27 @@ MochiKit.Logging.logError("## MainController - GENERIC ERROR" + "\n" + "==>> " +
|
||||
React.initializeTouchEvents(true);
|
||||
|
||||
Clipperz.PM.RunTime = {};
|
||||
function run() {
|
||||
|
||||
function initOnMediaQuery () {
|
||||
MQ.init(MochiKit.Base.map(function (queryStyle) {
|
||||
return {
|
||||
context: queryStyle,
|
||||
match: function () {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'matchMediaQuery', queryStyle);
|
||||
},
|
||||
unmatch: function () {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'unmatchMediaQuery', queryStyle);
|
||||
},
|
||||
}
|
||||
// }, ['extra-short', 'narrow', 'wide', 'extra-wide']));
|
||||
}, Clipperz_PM_UI_availableStyles));
|
||||
}
|
||||
|
||||
function run () {
|
||||
var parameters = {};
|
||||
|
||||
Clipperz.PM.Strings.Languages.initSetup();
|
||||
|
||||
|
||||
if ((window.location.search.indexOf('registration') != -1) || (window.location.hash.indexOf('registration') != -1)) {
|
||||
parameters['shouldShowRegistrationForm'] = true;
|
||||
} else {
|
||||
@ -59,7 +74,29 @@ function run() {
|
||||
Clipperz.PM.DataModel.devicePreferences = new Clipperz.PM.DataModel.DevicePreferences({});
|
||||
|
||||
Clipperz.PM.RunTime.mainController = new Clipperz.PM.UI.MainController();
|
||||
initOnMediaQuery();
|
||||
Clipperz.PM.RunTime.mainController.run(parameters);
|
||||
}
|
||||
|
||||
MochiKit.DOM.addLoadEvent(run);
|
||||
|
||||
/* * /
|
||||
MochiKit.DOM.addLoadEvent(simulateLogin);
|
||||
function simulateLogin () {
|
||||
var getURLParameter = function (name) {
|
||||
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null;
|
||||
}
|
||||
|
||||
Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose();
|
||||
|
||||
// MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:'joe', passphrase:'clipperz'}); // FULL
|
||||
// http://localhost:8888/delta/index.html?username=joe&passphrase=clipperz
|
||||
|
||||
// MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:';', passphrase:';'}); // EXPIRED
|
||||
// http://localhost:8888/delta/index.html?username=%3B&passphrase=%3B
|
||||
|
||||
if ((getURLParameter('u') != null) && (getURLParameter('p'))) {
|
||||
MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:getURLParameter('u'), passphrase:getURLParameter('p')});
|
||||
}
|
||||
}
|
||||
/ * */
|
@ -7,7 +7,7 @@
|
||||
# MochiKit (http://www.mochikit.com)
|
||||
- repository: @mochikit.repository@ (version: @mochikit.version@ - commit: @mochikit.commit@)
|
||||
|
||||
* Software licence: https://github.com/mochi/mochikit/blob/master/LICENSE.txt
|
||||
* Software license: https://github.com/mochi/mochikit/blob/master/LICENSE.txt
|
||||
|
||||
| MochiKit is dual-licensed software. It is available under the terms of the
|
||||
| MIT License, or the Academic Free License version 2.1. The full text of
|
||||
@ -207,7 +207,7 @@
|
||||
# React.js (http://facebook.github.io/react/)
|
||||
- repository: @reactjs.repository@ (version: @reactjs.version@ - commit: @reactjs.commit@)
|
||||
|
||||
* Software licence: https://github.com/facebook/react/blob/master/LICENSE
|
||||
* Software license: https://github.com/facebook/react/blob/master/LICENSE
|
||||
|
||||
| Apache License
|
||||
| Version 2.0, January 2004
|
||||
@ -413,10 +413,61 @@
|
||||
|
||||
|
||||
|
||||
# Modernizr (http://modernizr.com)
|
||||
- repository: @modernizr.repository@ (version: @modernizr.version@ - commit: @modernizr.commit@)
|
||||
|
||||
* Software license: http://modernizr.com/license/
|
||||
|
||||
| Copyright (c) 2009–2013
|
||||
| Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
| of this software and associated documentation files (the "Software"), to deal
|
||||
| in the Software without restriction, including without limitation the rights
|
||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
| copies of the Software, and to permit persons to whom the Software is
|
||||
| furnished to do so, subject to the following conditions:
|
||||
| The above copyright notice and this permission notice shall be included in
|
||||
| all copies or substantial portions of the Software.
|
||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
| THE SOFTWARE.
|
||||
|
||||
|
||||
# OnMediaQuery (https://github.com/JoshBarr/on-media-query)
|
||||
- repository: @onmediaquery.repository@ (version: @onmediaquery.version@ - commit: @onmediaquery.commit@)
|
||||
|
||||
* Software license: http://opensource.org/licenses/mit-license.php
|
||||
|
||||
| The MIT License (MIT)
|
||||
|
|
||||
| Copyright (c) <year> <copyright holders>
|
||||
|
|
||||
| Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
| of this software and associated documentation files (the "Software"), to deal
|
||||
| in the Software without restriction, including without limitation the rights
|
||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
| copies of the Software, and to permit persons to whom the Software is
|
||||
| furnished to do so, subject to the following conditions:
|
||||
|
|
||||
| The above copyright notice and this permission notice shall be included in
|
||||
| all copies or substantial portions of the Software.
|
||||
|
|
||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
| THE SOFTWARE.
|
||||
|
||||
|
||||
# Add to Home Screen (http://cubiq.org/add-to-home-screen)
|
||||
- repository: @addtohomescreen.repository@ (version: @addtohomescreen.version@ - commit: @addtohomescreen.commit@)
|
||||
|
||||
* Software licence: https://github.com/facebook/react/blob/master/LICENSE
|
||||
* Software license: https://github.com/facebook/react/blob/master/LICENSE
|
||||
|
||||
| This software is released under the MIT License.
|
||||
|
|
||||
@ -447,7 +498,7 @@
|
||||
|
||||
Copyright © 2005-2006 Yahoo! Inc. All rights reserved
|
||||
* Copyright notes: http://docs.yahoo.com/info/copyright/copyright.html
|
||||
* Software licence: http://developer.yahoo.com/yui/license.txt
|
||||
* Software license: http://developer.yahoo.com/yui/license.txt
|
||||
|
||||
| Software License Agreement (BSD License)
|
||||
|
|
||||
@ -485,7 +536,7 @@
|
||||
# YUI-ext (http://www.yui-ext.com)
|
||||
- repository: http://yui-ext.googlecode.com/svn/trunk/ (revision: 120)
|
||||
|
||||
* Software licence: http://yui-ext.googlecode.com/svn/trunk/src/licence.txt
|
||||
* Software license: http://yui-ext.googlecode.com/svn/trunk/src/licence.txt
|
||||
|
||||
| yui-ext
|
||||
| Copyright (c) 2006, Jack Slocum
|
||||
|
@ -5,9 +5,17 @@
|
||||
"mochikit.commit": "6f26f745d5d915540aa0fc6c34fda24952891a9d",
|
||||
|
||||
"reactjs.repository": "https://github.com/facebook/react.git",
|
||||
"reactjs.version": "0.4.1",
|
||||
"reactjs.commit": "0cac12d375264a8a232a426d6d6cc8074a94000a",
|
||||
"reactjs.version": "0.11.0",
|
||||
"reactjs.commit": "95d82cacd6e9cc6a2fe6366d79510cc9133886cb",
|
||||
|
||||
"modernizr.repository": "https://github.com/Modernizr/Modernizr",
|
||||
"modernizr.version": "2.8.2",
|
||||
"modernizr.commit": "99c09fa23a83f160a021c98b3644628aaec5e37a",
|
||||
|
||||
"onmediaquery.repository": "https://github.com/JoshBarr/on-media-query",
|
||||
"onmediaquery.version": "0.2.0",
|
||||
"onmediaquery.commit": "5080914636d392781ac858fb8eca9c0d99e5d35c",
|
||||
|
||||
"addtohomescreen.repository": "https://github.com/cubiq/add-to-homescreen.git",
|
||||
"addtohomescreen.version": "2.0.8",
|
||||
"addtohomescreen.commit": "4d375840079bcea994cc5795a568802400c7a793"
|
||||
@ -31,13 +39,14 @@
|
||||
"MochiKit/Selector.js",
|
||||
"-- MochiKit/Visual.js",
|
||||
|
||||
"-- React/react-0.4.1.js",
|
||||
"React/react-0.5.0-alpha.js",
|
||||
"React/react-with-addons-0.11.0.js",
|
||||
|
||||
"-- Hammer/hammer-1.0.5.js",
|
||||
|
||||
"Cubiq/add2home.js",
|
||||
"-- Cubiq/add2home.js",
|
||||
"-- Modernizr/modernizr-2.8.2.js",
|
||||
"OnMediaQuery/onmediaquery-0.2.0.js",
|
||||
|
||||
"-- IT WOULD BE NICE TO BE ABLE TO GET RID OF THESE IMPORTS",
|
||||
"Clipperz/YUI/Utils.js",
|
||||
"Clipperz/YUI/DomHelper.js",
|
||||
|
||||
@ -45,14 +54,14 @@
|
||||
"Clipperz/Base.js",
|
||||
"Clipperz/Async.js",
|
||||
"Clipperz/CSVProcessor.js",
|
||||
"Clipperz/KeePassExportProcessor.js",
|
||||
"-- Clipperz/KeePassExportProcessor.js",
|
||||
"Clipperz/Date.js",
|
||||
"Clipperz/DOM.js",
|
||||
"-- Clipperz/DOM.js",
|
||||
"Clipperz/Logging.js",
|
||||
"Clipperz/Signal.js",
|
||||
"-- Clipperz/Style.js",
|
||||
"-- Clipperz/Visual.js",
|
||||
"Clipperz/Set.js",
|
||||
"-- Clipperz/Set.js",
|
||||
"-- Clipperz/Profile.js",
|
||||
"Clipperz/KeyValueObjectStore.js",
|
||||
|
||||
@ -104,7 +113,7 @@
|
||||
"Clipperz/PM/DataModel/User.Header.RecordIndex.js",
|
||||
"Clipperz/PM/DataModel/User.Header.Preferences.js",
|
||||
"Clipperz/PM/DataModel/User.Header.OneTimePasswords.js",
|
||||
"Clipperz/PM/DataModel/User.Subscription.js",
|
||||
"Clipperz/PM/DataModel/User.AccountInfo.js",
|
||||
"Clipperz/PM/DataModel/Record.js",
|
||||
"Clipperz/PM/DataModel/Record.Version.js",
|
||||
"Clipperz/PM/DataModel/Record.Version.Field.js",
|
||||
@ -124,21 +133,42 @@
|
||||
"-- Clipperz/PM/UI/Web/Controllers/MainController.js",
|
||||
|
||||
"Clipperz/PM/UI/Components/Overlay.js",
|
||||
"Clipperz/PM/UI/Components/Button.js",
|
||||
"Clipperz/PM/UI/Components/Checkbox.js",
|
||||
"Clipperz/PM/UI/Components/PageTemplate.js",
|
||||
"Clipperz/PM/UI/Components/LoginForm.js",
|
||||
"Clipperz/PM/UI/Components/RegistrationWizard.js",
|
||||
"Clipperz/PM/UI/Components/CardList.js",
|
||||
"Clipperz/PM/UI/Components/CardDetail.js",
|
||||
"Clipperz/PM/UI/Components/PreferencePage.js",
|
||||
"Clipperz/PM/UI/Components/ErrorPage.js",
|
||||
"Clipperz/PM/UI/Components/CardToolbar.js",
|
||||
"Clipperz/PM/UI/Components/MessageBox.js",
|
||||
"Clipperz/PM/UI/Components/Selections.js",
|
||||
"Clipperz/PM/UI/Components/TagIndexItem.js",
|
||||
|
||||
"Clipperz/PM/UI/Components/ExpiredPanel.js",
|
||||
|
||||
"Clipperz/PM/UI/Components/Pages/LoginPage.js",
|
||||
"Clipperz/PM/UI/Components/Pages/RegistrationPage.js",
|
||||
"Clipperz/PM/UI/Components/Pages/MainPage.js",
|
||||
"Clipperz/PM/UI/Components/Pages/CardDetailPage.js",
|
||||
"Clipperz/PM/UI/Components/Pages/ErrorPage.js",
|
||||
|
||||
"Clipperz/PM/UI/Components/Panels/SelectionPanel.js",
|
||||
"Clipperz/PM/UI/Components/Panels/MainPanel.js",
|
||||
"Clipperz/PM/UI/Components/Panels/ExtraFeaturesPanel.js",
|
||||
|
||||
"Clipperz/PM/UI/Components/Cards/List.js",
|
||||
"Clipperz/PM/UI/Components/Cards/View.js",
|
||||
"Clipperz/PM/UI/Components/Cards/Toolbar.js",
|
||||
|
||||
"Clipperz/PM/UI/Components/AccountStatus.js",
|
||||
|
||||
"Clipperz/PM/UI/MainController.js",
|
||||
"-- Clipperz/PM/UI/MainDesktopController.js",
|
||||
"Clipperz/PM/UI/DirectLoginController.js",
|
||||
"main.js"
|
||||
],
|
||||
|
||||
"css": [
|
||||
"web.css"
|
||||
"clipperz.css"
|
||||
],
|
||||
|
||||
"scss": [
|
||||
"clipperz.scss"
|
||||
]
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
CACHE MANIFEST
|
||||
# 2013-10-01:v0.0.1
|
||||
# @application.version@
|
||||
|
||||
CACHE:
|
||||
# - Explicitly cached 'master entries'.
|
||||
index.html
|
||||
#index.html
|
||||
|
||||
NETWORK:
|
||||
# - Resources that require the user to be online.
|
||||
|
35
frontend/delta/scss/clipperz.scss
Normal file
35
frontend/delta/scss/clipperz.scss
Normal file
@ -0,0 +1,35 @@
|
||||
@import "core/reset";
|
||||
@import "core/palette";
|
||||
@import "core/parameters";
|
||||
@import "core/fonts";
|
||||
@import "core/flex";
|
||||
@import "core/overlay";
|
||||
@import "core/behavior";
|
||||
@import "core/layout";
|
||||
|
||||
@import "style/loadingPage";
|
||||
@import "style/loginPage";
|
||||
@import "style/registrationPage";
|
||||
@import "style/selectionPanel";
|
||||
@import "style/settingsPanel";
|
||||
@import "style/accountStatus";
|
||||
@import "style/card";
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
body {
|
||||
font-family: "clipperz-font";
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@import "core/sizes";
|
||||
|
||||
//@import "sizes/narrow";
|
||||
//@import "sizes/wide";
|
||||
//@import "sizes/extra-wide";
|
||||
//@import "sizes/extra-short";
|
205
frontend/delta/scss/core/behavior.scss
Normal file
205
frontend/delta/scss/core/behavior.scss
Normal file
@ -0,0 +1,205 @@
|
||||
// https://github.com/h5bp/Effeckt.css
|
||||
// http://coenraets.org/blog/2013/03/hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps/
|
||||
|
||||
$transition-duration: 0.5s;
|
||||
|
||||
@mixin pageElement () {
|
||||
position: absolute;
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
@include transform3d(0, 0, 0);
|
||||
@include transition-duration($transition-duration);
|
||||
|
||||
&.left {
|
||||
@include transform3d(-100%, 0, 0);
|
||||
}
|
||||
|
||||
&.right {
|
||||
@include transform3d(100%, 0, 0);
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
|
||||
&.transition {
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
@mixin sliding-panel-left ($size) {
|
||||
// background-color: yellow;
|
||||
|
||||
width: $size;
|
||||
height: 100%;
|
||||
|
||||
top: 0;
|
||||
left: -$size;
|
||||
}
|
||||
|
||||
@mixin sliding-panel-right ($size) {
|
||||
// background-color: green;
|
||||
|
||||
width: $size;
|
||||
height: 100%;
|
||||
|
||||
top: 0;
|
||||
right: -$size;
|
||||
}
|
||||
|
||||
@mixin sliding-panel ($side, $size) {
|
||||
position: fixed;
|
||||
z-index: 20;
|
||||
overflow: scroll;
|
||||
|
||||
@if $side == left {
|
||||
@include sliding-panel-left($size);
|
||||
}
|
||||
|
||||
@if $side == right {
|
||||
@include sliding-panel-right($size);
|
||||
}
|
||||
}
|
||||
|
||||
//.............................................................................
|
||||
|
||||
@mixin sliding-panel-open ($side, $size) {
|
||||
@if $side == left {
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
@if $side == right {
|
||||
right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
//.............................................................................
|
||||
|
||||
@mixin sliding-panel-wrapper-open-left ($size) {
|
||||
top: 0;
|
||||
left: $size;
|
||||
}
|
||||
|
||||
@mixin sliding-panel-wrapper-open-right ($size) {
|
||||
top: 0;
|
||||
right: $size;
|
||||
}
|
||||
|
||||
@mixin sliding-panel-wrapper-open ($side, $size) {
|
||||
@include sliding-panel-wrapper();
|
||||
|
||||
@if $side == left {
|
||||
@include sliding-panel-wrapper-open-left($size);
|
||||
}
|
||||
|
||||
@if $side == right {
|
||||
@include sliding-panel-wrapper-open-right($size);
|
||||
}
|
||||
}
|
||||
|
||||
//.............................................................................
|
||||
|
||||
@mixin sliding-panel-wrapper () {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// @include transition(all, $transition_time);
|
||||
}
|
||||
|
||||
@mixin sliding-panel-container () {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
.registrationForm {
|
||||
.steps {
|
||||
.step {
|
||||
position: absolute;
|
||||
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
|
||||
.slide();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// tentative 3D transformations
|
||||
/*
|
||||
.page {
|
||||
transform: rotateY( 0deg) translateZ( 100px);
|
||||
|
||||
&.left {
|
||||
transform: rotateY( -90deg) translateZ( 100px);
|
||||
}
|
||||
|
||||
&.center {
|
||||
transform: rotateY( 0deg) translateZ( 100px);
|
||||
}
|
||||
|
||||
&.right {
|
||||
transform: rotateY( 90deg) translateZ( 100px);
|
||||
}
|
||||
}
|
||||
|
||||
#mainDiv {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
transform-style: preserve-3d;
|
||||
|
||||
transition: transform 3s;
|
||||
|
||||
&.show-front { transform: translateZ( -100px ) rotateY( 0deg ); }
|
||||
&.show-back { transform: translateZ( -100px ) rotateX( -180deg ); }
|
||||
&.show-right { transform: translateZ( -100px ) rotateY( -90deg ); }
|
||||
&.show-left { transform: translateZ( -100px ) rotateY( 90deg ); }
|
||||
&.show-top { transform: translateZ( -100px ) rotateX( -90deg ); }
|
||||
&.show-bottom { transform: translateZ( -100px ) rotateX( 90deg ); }
|
||||
}
|
||||
*/
|
||||
//=======================================================================
|
||||
|
||||
|
||||
//=======================================================================
|
||||
|
||||
|
||||
//=======================================================================
|
395
frontend/delta/scss/core/flex.scss
Normal file
395
frontend/delta/scss/core/flex.scss
Normal file
@ -0,0 +1,395 @@
|
||||
// Downloaded on June 8, 2014 from https://raw.githubusercontent.com/mastastealth/sass-flex-mixin/master/flex.scss
|
||||
|
||||
// Flexbox Mixins
|
||||
// http://philipwalton.github.io/solved-by-flexbox/
|
||||
// https://github.com/philipwalton/solved-by-flexbox
|
||||
//
|
||||
// Copyright (c) 2013 Brian Franco
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// This is a set of mixins for those who want to mess around with flexbox
|
||||
// using the native support of current browsers. For full support table
|
||||
// check: http://caniuse.com/flexbox
|
||||
//
|
||||
// Basically this will use:
|
||||
//
|
||||
// * Fallback, old syntax (IE10, Safari, mobile webkit browsers)
|
||||
// * Prefixed standard syntax (Chrome)
|
||||
// * Final standards syntax (FF, IE11, Opera 12.1)
|
||||
//
|
||||
// This was inspired by:
|
||||
//
|
||||
// * http://dev.opera.com/articles/view/advanced-cross-browser-flexbox/
|
||||
//
|
||||
// With help from:
|
||||
//
|
||||
// * http://w3.org/tr/css3-flexbox/
|
||||
// * http://the-echoplex.net/flexyboxes/
|
||||
// * http://msdn.microsoft.com/en-us/library/ie/hh772069(v=vs.85).aspx
|
||||
// * http://css-tricks.com/using-flexbox/
|
||||
// * http://dev.opera.com/articles/view/advanced-cross-browser-flexbox/
|
||||
// * https://developer.mozilla.org/en-us/docs/web/guide/css/flexible_boxes
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Containers
|
||||
//
|
||||
// The 'flex' value causes an element to generate a block-level flex
|
||||
// container box.
|
||||
//
|
||||
// The 'inline-flex' value causes an element to generate a inline-level
|
||||
// flex container box.
|
||||
//
|
||||
// display: flex | inline-flex
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#flex-containers
|
||||
//
|
||||
// (Placeholder selectors for each type, for those who rather @extend)
|
||||
|
||||
@mixin flexbox {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -moz-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
%flexbox { @include flexbox; }
|
||||
|
||||
//----------------------------------
|
||||
|
||||
@mixin inline-flex {
|
||||
display: -webkit-inline-box;
|
||||
display: -webkit-inline-flex;
|
||||
display: -moz-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
%inline-flex { @include inline-flex; }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Direction
|
||||
//
|
||||
// The 'flex-direction' property specifies how flex items are placed in
|
||||
// the flex container, by setting the direction of the flex container's
|
||||
// main axis. This determines the direction that flex items are laid out in.
|
||||
//
|
||||
// Values: row | row-reverse | column | column-reverse
|
||||
// Default: row
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#flex-direction-property
|
||||
|
||||
@mixin flex-direction($value: row) {
|
||||
@if $value == row-reverse {
|
||||
-webkit-box-direction: reverse;
|
||||
-webkit-box-orient: horizontal;
|
||||
} @else if $value == column {
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-box-orient: vertical;
|
||||
} @else if $value == column-reverse {
|
||||
-webkit-box-direction: reverse;
|
||||
-webkit-box-orient: vertical;
|
||||
} @else {
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-box-orient: horizontal;
|
||||
}
|
||||
-webkit-flex-direction: $value;
|
||||
-moz-flex-direction: $value;
|
||||
-ms-flex-direction: $value;
|
||||
flex-direction: $value;
|
||||
}
|
||||
// Shorter version:
|
||||
@mixin flex-dir($value: false) { @include flex-direction($value); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Wrap
|
||||
//
|
||||
// The 'flex-wrap' property controls whether the flex container is single-line
|
||||
// or multi-line, and the direction of the cross-axis, which determines
|
||||
// the direction new lines are stacked in.
|
||||
//
|
||||
// Values: nowrap | wrap | wrap-reverse
|
||||
// Default: nowrap
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#flex-wrap-property
|
||||
|
||||
@mixin flex-wrap($value: nowrap) {
|
||||
// No Webkit Box fallback.
|
||||
-webkit-flex-wrap: $value;
|
||||
-moz-flex-wrap: $value;
|
||||
@if $value == nowrap {
|
||||
-ms-flex-wrap: none;
|
||||
} @else {
|
||||
-ms-flex-wrap: $value;
|
||||
}
|
||||
flex-wrap: $value;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Flow (shorthand)
|
||||
//
|
||||
// The 'flex-flow' property is a shorthand for setting the 'flex-direction'
|
||||
// and 'flex-wrap' properties, which together define the flex container's
|
||||
// main and cross axes.
|
||||
//
|
||||
// Values: <flex-direction> | <flex-wrap>
|
||||
// Default: row nowrap
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#flex-flow-property
|
||||
|
||||
@mixin flex-flow($values: (row nowrap)) {
|
||||
// No Webkit Box fallback.
|
||||
-webkit-flex-flow: $values;
|
||||
-moz-flex-flow: $values;
|
||||
-ms-flex-flow: $values;
|
||||
flex-flow: $values;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Order
|
||||
//
|
||||
// The 'order' property controls the order in which flex items appear within
|
||||
// their flex container, by assigning them to ordinal groups.
|
||||
//
|
||||
// Default: 0
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#order-property
|
||||
|
||||
@mixin order($int: 0) {
|
||||
-webkit-box-ordinal-group: $int + 1;
|
||||
-webkit-order: $int;
|
||||
-moz-order: $int;
|
||||
-ms-flex-order: $int;
|
||||
order: $int;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Grow
|
||||
//
|
||||
// The 'flex-grow' property sets the flex grow factor. Negative numbers
|
||||
// are invalid.
|
||||
//
|
||||
// Default: 0
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#flex-grow-property
|
||||
|
||||
@mixin flex-grow($int: 0) {
|
||||
-webkit-box-flex: $int;
|
||||
-webkit-flex-grow: $int;
|
||||
-moz-flex-grow: $int;
|
||||
-ms-flex-positive: $int;
|
||||
flex-grow: $int;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Shrink
|
||||
//
|
||||
// The 'flex-shrink' property sets the flex shrink factor. Negative numbers
|
||||
// are invalid.
|
||||
//
|
||||
// Default: 1
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#flex-shrink-property
|
||||
|
||||
@mixin flex-shrink($int: 1) {
|
||||
-webkit-flex-shrink: $int;
|
||||
-moz-flex-shrink: $int;
|
||||
-ms-flex-negative: $int;
|
||||
flex-shrink: $int;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Basis
|
||||
//
|
||||
// The 'flex-basis' property sets the flex basis. Negative lengths are invalid.
|
||||
//
|
||||
// Values: Like "width"
|
||||
// Default: auto
|
||||
//
|
||||
// http://www.w3.org/TR/css3-flexbox/#flex-basis-property
|
||||
|
||||
@mixin flex-basis($value: auto) {
|
||||
-webkit-flex-basis: $value;
|
||||
-moz-flex-basis: $value;
|
||||
-ms-flex-preferred-size: $value;
|
||||
flex-basis: $value;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox "Flex" (shorthand)
|
||||
//
|
||||
// The 'flex' property specifies the components of a flexible length: the
|
||||
// flex grow factor and flex shrink factor, and the flex basis. When an
|
||||
// element is a flex item, 'flex' is consulted instead of the main size
|
||||
// property to determine the main size of the element. If an element is
|
||||
// not a flex item, 'flex' has no effect.
|
||||
//
|
||||
// Values: none | <flex-grow> <flex-shrink> || <flex-basis>
|
||||
// Default: See individual properties (1 1 0).
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#flex-property
|
||||
|
||||
@mixin flex($fg: 1, $fs: null, $fb: null) {
|
||||
|
||||
// Set a variable to be used by box-flex properties
|
||||
$fg-boxflex: $fg;
|
||||
|
||||
// Box-Flex only supports a flex-grow value so let's grab the
|
||||
// first item in the list and just return that.
|
||||
@if type-of($fg) == 'list' {
|
||||
$fg-boxflex: nth($fg, 1);
|
||||
}
|
||||
|
||||
-webkit-box-flex: $fg-boxflex;
|
||||
-webkit-flex: $fg $fs $fb;
|
||||
-moz-box-flex: $fg-boxflex;
|
||||
-moz-flex: $fg $fs $fb;
|
||||
-ms-flex: $fg $fs $fb;
|
||||
flex: $fg $fs $fb;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Justify Content
|
||||
//
|
||||
// The 'justify-content' property aligns flex items along the main axis
|
||||
// of the current line of the flex container. This is done after any flexible
|
||||
// lengths and any auto margins have been resolved. Typically it helps distribute
|
||||
// extra free space leftover when either all the flex items on a line are
|
||||
// inflexible, or are flexible but have reached their maximum size. It also
|
||||
// exerts some control over the alignment of items when they overflow the line.
|
||||
//
|
||||
// Note: 'space-*' values not supported in older syntaxes.
|
||||
//
|
||||
// Values: flex-start | flex-end | center | space-between | space-around
|
||||
// Default: flex-start
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#justify-content-property
|
||||
|
||||
@mixin justify-content($value: flex-start) {
|
||||
@if $value == flex-start {
|
||||
-webkit-box-pack: start;
|
||||
-ms-flex-pack: start;
|
||||
} @else if $value == flex-end {
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
} @else if $value == space-between {
|
||||
-webkit-box-pack: justify;
|
||||
-ms-flex-pack: justify;
|
||||
} @else {
|
||||
-webkit-box-pack: $value;
|
||||
-ms-flex-pack: $value;
|
||||
}
|
||||
-webkit-justify-content: $value;
|
||||
-moz-justify-content: $value;
|
||||
justify-content: $value;
|
||||
}
|
||||
// Shorter version:
|
||||
@mixin flex-just($value: flex-start) { @include justify-content($value); }
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Align Items
|
||||
//
|
||||
// Flex items can be aligned in the cross axis of the current line of the
|
||||
// flex container, similar to 'justify-content' but in the perpendicular
|
||||
// direction. 'align-items' sets the default alignment for all of the flex
|
||||
// container's items, including anonymous flex items. 'align-self' allows
|
||||
// this default alignment to be overridden for individual flex items. (For
|
||||
// anonymous flex items, 'align-self' always matches the value of 'align-items'
|
||||
// on their associated flex container.)
|
||||
//
|
||||
// Values: flex-start | flex-end | center | baseline | stretch
|
||||
// Default: stretch
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#align-items-property
|
||||
|
||||
@mixin align-items($value: stretch) {
|
||||
@if $value == flex-start {
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
} @else if $value == flex-end {
|
||||
-webkit-box-align: end;
|
||||
-ms-flex-align: end;
|
||||
} @else {
|
||||
-webkit-box-align: $value;
|
||||
-ms-flex-align: $value;
|
||||
}
|
||||
-webkit-align-items: $value;
|
||||
-moz-align-items: $value;
|
||||
align-items: $value;
|
||||
}
|
||||
|
||||
//----------------------------------
|
||||
|
||||
// Flexbox Align Self
|
||||
//
|
||||
// Values: auto | flex-start | flex-end | center | baseline | stretch
|
||||
// Default: auto
|
||||
|
||||
@mixin align-self($value: auto) {
|
||||
// No Webkit Box Fallback.
|
||||
-webkit-align-self: $value;
|
||||
-moz-align-self: $value;
|
||||
@if $value == flex-start {
|
||||
-ms-flex-item-align: start;
|
||||
} @else if $value == flex-end {
|
||||
-ms-flex-item-align: end;
|
||||
} @else {
|
||||
-ms-flex-item-align: $value;
|
||||
}
|
||||
align-self: $value;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Flexbox Align Content
|
||||
//
|
||||
// The 'align-content' property aligns a flex container's lines within the
|
||||
// flex container when there is extra space in the cross-axis, similar to
|
||||
// how 'justify-content' aligns individual items within the main-axis. Note,
|
||||
// this property has no effect when the flexbox has only a single line.
|
||||
//
|
||||
// Values: flex-start | flex-end | center | space-between | space-around | stretch
|
||||
// Default: stretch
|
||||
//
|
||||
// http://w3.org/tr/css3-flexbox/#align-content-property
|
||||
|
||||
@mixin align-content($value: stretch) {
|
||||
// No Webkit Box Fallback.
|
||||
-webkit-align-content: $value;
|
||||
-moz-align-content: $value;
|
||||
@if $value == flex-start {
|
||||
-ms-flex-line-pack: start;
|
||||
} @else if $value == flex-end {
|
||||
-ms-flex-line-pack: end;
|
||||
} @else {
|
||||
-ms-flex-line-pack: $value;
|
||||
}
|
||||
align-content: $value;
|
||||
}
|
103
frontend/delta/scss/core/fonts.scss
Normal file
103
frontend/delta/scss/core/fonts.scss
Normal file
File diff suppressed because one or more lines are too long
289
frontend/delta/scss/core/layout.scss
Normal file
289
frontend/delta/scss/core/layout.scss
Normal file
@ -0,0 +1,289 @@
|
||||
@import "parameters";
|
||||
|
||||
.page {
|
||||
@include pageElement();
|
||||
}
|
||||
|
||||
.mainPage {
|
||||
// background-color: yellow;
|
||||
}
|
||||
|
||||
.mainPage > #selectionPanel {
|
||||
@include sliding-panel(left, $selectionPanelWidth);
|
||||
|
||||
&.open {
|
||||
@include sliding-panel-open(left, $selectionPanelWidth);
|
||||
}
|
||||
}
|
||||
|
||||
#mainPanel {
|
||||
// background-color: $yellow;
|
||||
|
||||
&.extra-wide {
|
||||
@include sliding-panel-container();
|
||||
|
||||
.container {
|
||||
@include flexbox;
|
||||
}
|
||||
|
||||
.subpanel {
|
||||
|
||||
&.selection {
|
||||
@include flex($selectionPanelWidth, 0);
|
||||
// height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
&.cardContent {
|
||||
@include flex($cardContentPanelWidth);
|
||||
@include flexbox;
|
||||
@include flex-direction(column);
|
||||
}
|
||||
}
|
||||
|
||||
.selectionToggle {
|
||||
.button {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.wide, &.narrow {
|
||||
.container {
|
||||
@include sliding-panel-container();
|
||||
}
|
||||
}
|
||||
|
||||
&.narrow {
|
||||
.column {
|
||||
@include pageElement();
|
||||
}
|
||||
}
|
||||
|
||||
&.open.left {
|
||||
@include sliding-panel-wrapper-open (left, $selectionPanelWidth);
|
||||
@include mask();
|
||||
}
|
||||
|
||||
&.open.right {
|
||||
// @include sliding-panel-wrapper-open (right, $settingsPanelWidth);
|
||||
@include mask();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#extraFeaturesPanel {
|
||||
@include sliding-panel(right, $settingsPanelWidth);
|
||||
|
||||
&.open {
|
||||
@include sliding-panel-open(right, $settingsPanelWidth);
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cardToolbarFrame {
|
||||
height: 100%;
|
||||
|
||||
@include flexbox;
|
||||
@include flex-direction(column);
|
||||
|
||||
.cardToolbar {
|
||||
@include flex(none);
|
||||
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
}
|
||||
}
|
||||
|
||||
div.cardToolbar {
|
||||
// background-color: $orange;
|
||||
|
||||
header {
|
||||
@include flexbox;
|
||||
height: $mainCardToolbarHeight;
|
||||
line-height: $mainCardToolbarHeight;
|
||||
|
||||
background-color: $clipperz-orange;
|
||||
color: white;
|
||||
font-size: 24pt;
|
||||
|
||||
div {
|
||||
|
||||
&.clipperz {
|
||||
|
||||
span.logo {
|
||||
@include icon-font();
|
||||
|
||||
@include align-self(center);
|
||||
@include flex(4);
|
||||
text-align: center;
|
||||
|
||||
&.tag, &.search {
|
||||
font-size: 14pt;
|
||||
}
|
||||
}
|
||||
|
||||
span.value {
|
||||
display: inline-block;
|
||||
padding-left: 5px;
|
||||
font-size: 18pt;
|
||||
}
|
||||
}
|
||||
|
||||
&.selectionToggle {
|
||||
@include flex(1);
|
||||
|
||||
.button {
|
||||
text-align: left;
|
||||
|
||||
.label {
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// &.logo {
|
||||
// @include align-self(center);
|
||||
// @include flex(4);
|
||||
// text-align: center;
|
||||
// }
|
||||
|
||||
&.settingsToggle {
|
||||
@include flex(1);
|
||||
|
||||
.button {
|
||||
text-align: right;
|
||||
|
||||
.label {
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
overflow: hidden;
|
||||
font-size: 24pt;
|
||||
@include icon-font();
|
||||
vertical-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
div.cardContent {
|
||||
// @include flex(flex-grow); // ???
|
||||
|
||||
@include flexbox();
|
||||
@include flex-direction(row);
|
||||
|
||||
div.cardListColumn.column {
|
||||
@include flex($cardListWidth, 0);
|
||||
overflow-y: scroll;
|
||||
|
||||
div.cardToolbar.narrow {
|
||||
}
|
||||
|
||||
div.cardList {
|
||||
overflow-y: scroll;
|
||||
padding-bottom: 120px;
|
||||
|
||||
ul {
|
||||
}
|
||||
}
|
||||
|
||||
div.addCardButton {
|
||||
@include icon-font();
|
||||
@include border-radius(50px);
|
||||
@include radial-gradient (white, rgba(0, 0, 0, 0));
|
||||
|
||||
position: relative;
|
||||
bottom: 0px;
|
||||
font-size: 75pt;
|
||||
color: blue;
|
||||
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
|
||||
float: right;
|
||||
position: absolute;
|
||||
margin-left: 100px;
|
||||
margin-bottom: 10px;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
div.cardDetail.column {
|
||||
@include flex($cardDetailWidth);
|
||||
|
||||
@include flexbox();
|
||||
|
||||
div.view {
|
||||
@include flex(auto);
|
||||
|
||||
@include flexbox;
|
||||
@include flex-direction(column);
|
||||
|
||||
.cardDetailToolbar {
|
||||
@include flex(none);
|
||||
height: $mainCardToolbarHeight;
|
||||
line-height: $mainCardToolbarHeight;
|
||||
}
|
||||
|
||||
.content {
|
||||
@include flex(auto);
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#cardDetailPage {
|
||||
.view {
|
||||
@include flexbox();
|
||||
@include flex-direction(column);
|
||||
height: 100%;
|
||||
|
||||
.cardDetailToolbar {
|
||||
@include flex(none);
|
||||
height: $mainCardToolbarHeight;
|
||||
line-height: $mainCardToolbarHeight;
|
||||
|
||||
& > div {
|
||||
@include flexbox();
|
||||
@include flex-direction(row);
|
||||
font-size: 24pt;
|
||||
|
||||
.back {
|
||||
@include flex(auto);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cardMenuOptions {
|
||||
@include flex(auto);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
@include flex(auto);
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -1,10 +1,19 @@
|
||||
@mixin border-radius ($radius) {
|
||||
border-radius: $radius;
|
||||
-moz-border-radius: $radius;
|
||||
-webkit-border-radius: $radius;
|
||||
-moz-border-radius: $radius;
|
||||
border-radius: $radius;
|
||||
}
|
||||
|
||||
@mixin font-feature-settings($foo, $bar) {
|
||||
@mixin radial-gradient ($inner-color, $outer-color) {
|
||||
background-image: -ms-radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%); /* IE10 */
|
||||
background-image: -moz-radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%); /* Mozilla Firefox */
|
||||
background-image: -o-radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%); /* Opera */
|
||||
background-image: -webkit-radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%); /* Webkit (Chrome 11+) */
|
||||
background-image: radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%); /* Proposed W3C Markup */
|
||||
background-image: -webkit-gradient(radial, center center, 0, center center, 495, color-stop(0, $inner-color), color-stop(1, $outer-color)); /* Webkit (Safari/Chrome 10) */
|
||||
}
|
||||
|
||||
@mixin font-feature-settings ($foo, $bar) {
|
||||
-webkit-font-feature-settings:"$foo","$bar";
|
||||
-moz-font-feature-settings:"$foo=1, $bar=1";
|
||||
-moz-font-feature-settings:"$foo","$bar";
|
||||
@ -13,14 +22,14 @@
|
||||
font-feature-settings:"$foo","$bar";
|
||||
}
|
||||
|
||||
@mixin icon-font() {
|
||||
@mixin icon-font () {
|
||||
font-family: 'clipperz-icons';
|
||||
@include font-feature-settings("liga", "dlig");
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering:optimizeLegibility;
|
||||
}
|
||||
|
||||
@mixin password-font() {
|
||||
@mixin password-font () {
|
||||
font-family: 'clipperz-password';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering:optimizeLegibility;
|
||||
@ -60,10 +69,10 @@
|
||||
|
||||
@mixin transition ($item, $time, $function) {
|
||||
-webkit-transition: $item $time $function;
|
||||
-moz-transition: $item $time $function;
|
||||
-o-transition: $item $time $function;
|
||||
-ms-transition: $item $time $function;
|
||||
transition: $item $time $function;
|
||||
-moz-transition: $item $time $function;
|
||||
-o-transition: $item $time $function;
|
||||
-ms-transition: $item $time $function;
|
||||
transition: $item $time $function;
|
||||
}
|
||||
|
||||
@mixin transform ($rotateAngle, $translateX, $translateY) {
|
||||
@ -74,6 +83,16 @@
|
||||
transform: rotate( $rotateAngle) translate($translateX, $translateY);
|
||||
}
|
||||
|
||||
@mixin transform3d ($tx, $ty, $tz) {
|
||||
-webkit-transform: translate3d($tx, $ty, $tz);
|
||||
transform: translate3d($tx, $ty, $tz);
|
||||
}
|
||||
|
||||
@mixin transition-duration ($duration) {
|
||||
-webkit-transition-duration: $duration;
|
||||
transition-duration: $duration;
|
||||
}
|
||||
|
||||
|
||||
@mixin animation-delay ($delay) {
|
||||
-webkit-animation-delay: $delay;
|
||||
@ -91,7 +110,7 @@
|
||||
box-shadow: $xOffset $yOffset $size $color;
|
||||
}
|
||||
|
||||
@mixin keyframes($name) {
|
||||
@mixin keyframes ($name) {
|
||||
@-webkit-keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
@ -104,4 +123,21 @@
|
||||
@keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin mask () {
|
||||
.mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 10;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@include keyframes(spin) {
|
||||
0% { @include transform(0deg, 0, 0); }
|
||||
100% { @include transform(359deg, 0, 0); }
|
||||
}
|
@ -14,7 +14,7 @@ div.overlay {
|
||||
|
||||
.title {
|
||||
color: #FFF;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
// font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
display: block;
|
44
frontend/delta/scss/core/palette.scss
Normal file
44
frontend/delta/scss/core/palette.scss
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// SOLARIZED palette
|
||||
// http://ethanschoonover.com/solarized
|
||||
//
|
||||
$solarize-Background-15: #002b36;
|
||||
$solarize-Background-20: #073642;
|
||||
|
||||
$solarize-Content-45: #586375;
|
||||
$solarize-Content-50: #657b83;
|
||||
$solarize-Content-60: #839496;
|
||||
$solarize-Content-65: #93a1a1;
|
||||
|
||||
$solarize-Background-92: #eee8d5;
|
||||
$solarize-Background-97: #fdf6e3;
|
||||
|
||||
$solarize-Accent-Yellow: #b58900;
|
||||
$solarize-Accent-Orange: #cb4b16;
|
||||
$solarize-Accent-Red: #dc322f;
|
||||
$solarize-Accent-Magenta: #d33682;
|
||||
$solarize-Accent-Violet: #6c71c4;
|
||||
$solarize-Accent-Blue: #268bd2;
|
||||
$solarize-Accent-Cyan: #2aa198;
|
||||
$solarize-Accent-Green: #859900;
|
||||
|
||||
// $yellow: $solarize-Accent-Yellow;
|
||||
// $orange: $solarize-Accent-Orange;
|
||||
// $red: $solarize-Accent-Red;
|
||||
// $magenta: $solarize-Accent-Magenta;
|
||||
// $violete: $solarize-Accent-Violet;
|
||||
// $blue: $solarize-Accent-Blue;
|
||||
// $cyan: $solarize-Accent-Cyan;
|
||||
// $green: $solarize-Accent-Green;
|
||||
|
||||
$clipperz-orange: #ff9900;
|
||||
$clipperz-blue: #1863a1;
|
||||
$terminal-green: #23ff18;
|
||||
|
||||
|
||||
|
||||
$main-color: $clipperz-orange;
|
||||
$main-text-color: black;
|
||||
|
||||
$main-alternate-color: black;
|
||||
$main-alternate-text-color: white;
|
15
frontend/delta/scss/core/parameters.scss
Normal file
15
frontend/delta/scss/core/parameters.scss
Normal file
@ -0,0 +1,15 @@
|
||||
//$selectionPanelWidth: 200px;
|
||||
//$cardListWidth: 200px;
|
||||
|
||||
$selectionPanelWidth: 1;
|
||||
$cardContentPanelWidth: 4;
|
||||
|
||||
$mainCardToolbarHeight: 48px;
|
||||
|
||||
$cardListWidth: 1;
|
||||
$cardDetailWidth: 2;
|
||||
|
||||
$selectionPanelWidth: 300px;
|
||||
$settingsPanelWidth: 300px;
|
||||
|
||||
|
43
frontend/delta/scss/core/reset.scss
Normal file
43
frontend/delta/scss/core/reset.scss
Normal file
@ -0,0 +1,43 @@
|
||||
// Downloaded on June 11, 2014 from: https://gist.github.com/hcatlin/1027867
|
||||
|
||||
/* http://meyerweb.com/eric/tools/css/reset/
|
||||
v2.0 | 20110126
|
||||
License: none (public domain)
|
||||
*/
|
||||
|
||||
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
|
||||
&:before, &:after, {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
52
frontend/delta/scss/core/sizes.scss
Normal file
52
frontend/delta/scss/core/sizes.scss
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
Bootstrap CSS suggests these size breakpoints:
|
||||
|
||||
- Extra small devices Phones (<768px)
|
||||
- Small devices Tablets (≥768px)
|
||||
- Medium devices Desktops (≥992px)
|
||||
- Large devices Desktops (≥1200px)
|
||||
|
||||
|
||||
# ATTENTION
|
||||
When adding a new 'size', remember to update also MQ.init invocation in main.js.
|
||||
This configuration is now located in the first script included in the index_template.html file.
|
||||
|
||||
*/
|
||||
|
||||
@media only screen and (min-width: 100px) {
|
||||
html {
|
||||
font-family: "narrow";
|
||||
}
|
||||
body:after {
|
||||
content: "narrow";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (min-width: 700px) {
|
||||
html {
|
||||
font-family: "wide";
|
||||
}
|
||||
body:after {
|
||||
content: "wide";
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1100px) {
|
||||
html {
|
||||
font-family: "extra-wide";
|
||||
}
|
||||
body:after {
|
||||
content: "extra-wide";
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 100px) and (max-height: 450px) {
|
||||
html {
|
||||
font-family: "extra-short";
|
||||
}
|
||||
body:after {
|
||||
content: "extra-short";
|
||||
}
|
||||
}
|
27
frontend/delta/scss/style/accountStatus.scss
Normal file
27
frontend/delta/scss/style/accountStatus.scss
Normal file
@ -0,0 +1,27 @@
|
||||
.accountStatus {
|
||||
background-color: green;
|
||||
|
||||
&.FULL {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
|
||||
&.isExpiring {
|
||||
display: block;
|
||||
visibility: visible;
|
||||
|
||||
background-color: yellow;
|
||||
}
|
||||
}
|
||||
|
||||
&.TRIAL {
|
||||
background-color: orange;
|
||||
|
||||
&.isExpiring {
|
||||
background-color: red;
|
||||
}
|
||||
}
|
||||
|
||||
&.EXPIRED {
|
||||
background-color: red;
|
||||
}
|
||||
}
|
270
frontend/delta/scss/style/card.scss
Normal file
270
frontend/delta/scss/style/card.scss
Normal file
@ -0,0 +1,270 @@
|
||||
$cardListHeight: 48px;
|
||||
$faviconSize: 32px;
|
||||
$padding: ($cardListHeight - $faviconSize) / 2;
|
||||
|
||||
$cardToolbarBackgroundColor: brown;
|
||||
|
||||
div.cardList {
|
||||
// background-color: $yellow;
|
||||
|
||||
&.loadingCard {
|
||||
li.selected {
|
||||
background-color: gray;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
li.selected {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
li {
|
||||
cursor: pointer;
|
||||
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
@include flexbox();
|
||||
@include flex-direction(row);
|
||||
|
||||
.favicon {
|
||||
width: $cardListHeight;
|
||||
@include flex(none);
|
||||
|
||||
img {
|
||||
width: $faviconSize;
|
||||
height: $faviconSize;
|
||||
padding: $padding;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
@include flex(auto);
|
||||
|
||||
font-size: 18pt;
|
||||
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
padding-left: $padding;
|
||||
padding-right: $padding;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
div.cardList.narrow {
|
||||
&.loadingCard {
|
||||
li.selected {
|
||||
// background-color: gray;
|
||||
|
||||
&:after {
|
||||
color: white;
|
||||
margin-right: 10px;
|
||||
content: "loading";
|
||||
@include animation(spin, 1s, linear, infinite);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
|
||||
&:after {
|
||||
content: "show detail";
|
||||
@include flex(none);
|
||||
@include icon-font();
|
||||
height: 48px;
|
||||
font-size: 24pt;
|
||||
line-height: 48px;
|
||||
margin-right: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cardViewBasePadding: 10px;
|
||||
|
||||
#cardDetailPage, .cardDetail {
|
||||
.loading {
|
||||
// height: 100%;
|
||||
// width: 100%;
|
||||
// background-color: rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.view {
|
||||
|
||||
.cardDetailToolbar {
|
||||
|
||||
ul {
|
||||
@include flexbox();
|
||||
@include flex-direction(row);
|
||||
|
||||
li {
|
||||
@include flex(auto);
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.narrow {
|
||||
.back {
|
||||
@include icon-font();
|
||||
}
|
||||
|
||||
.cardMenuOptions {
|
||||
@include icon-font();
|
||||
text-align: right;
|
||||
font-size: 18pt;
|
||||
padding-right: 10px;
|
||||
|
||||
}
|
||||
|
||||
.commandMenu {
|
||||
// display: none;
|
||||
.commandMenuMask {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.commandMenu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.show {
|
||||
|
||||
.commandMenuMask {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.commandMenu {
|
||||
display: block;
|
||||
float: right;
|
||||
position: absolute;
|
||||
min-width: 200px;
|
||||
top: 48px;
|
||||
right: 5px;
|
||||
color: black;
|
||||
background-color: white;
|
||||
@include box-shadow(0px, 2px, 5px, rgba(50, 50, 50, 0.75));
|
||||
|
||||
ul {
|
||||
@include flex-direction(column);
|
||||
|
||||
li {
|
||||
text-align: left;
|
||||
font-size: 18pt;
|
||||
padding: 5px 10px;
|
||||
border-bottom: 1px solid black;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.cardDetailToolbar {
|
||||
background-color: $cardToolbarBackgroundColor;
|
||||
color: white;
|
||||
|
||||
&.narrow {
|
||||
|
||||
.cardMenuOptions {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
.cardLabel {
|
||||
font-size: 24pt;
|
||||
padding: $cardViewBasePadding;
|
||||
}
|
||||
|
||||
.cardTags {
|
||||
@include flexbox();
|
||||
@include flex-direction(row);
|
||||
@include align-items(flex-start);
|
||||
|
||||
padding: $cardViewBasePadding;
|
||||
|
||||
.cardTag {
|
||||
@include flex(none);
|
||||
font-size: 14pt;
|
||||
padding-right: 10px;
|
||||
|
||||
&:before {
|
||||
content: 'tag';
|
||||
@include icon-font();
|
||||
font-size: 10pt;
|
||||
padding-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cardNotes {
|
||||
padding: $cardViewBasePadding;
|
||||
}
|
||||
|
||||
.cardField {
|
||||
@include flexbox;
|
||||
@include flex-direction(row);
|
||||
|
||||
.fieldValues {
|
||||
@include flex(1);
|
||||
padding: $cardViewBasePadding;
|
||||
|
||||
.fieldLabel {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.fieldValue {
|
||||
font-size: 18pt;
|
||||
|
||||
&.hidden {
|
||||
font-family: clipperz-password;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.fieldAction {
|
||||
@include flex(none);
|
||||
@include align-self(center);
|
||||
}
|
||||
|
||||
.action {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
@include icon-font();
|
||||
font-size: 20pt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.cardDirectLogin {
|
||||
font-size: 18pt;
|
||||
padding: $cardViewBasePadding;
|
||||
background-color: pink;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
32
frontend/delta/scss/style/loadingPage.scss
Normal file
32
frontend/delta/scss/style/loadingPage.scss
Normal file
@ -0,0 +1,32 @@
|
||||
// $Loading_outer_color: $main-color;
|
||||
// $Loading_inner-color: lighten($Loading_outer-color, 30%);
|
||||
//
|
||||
// $Loading_h1-color: lighten($Loading_inner-color, 70%);
|
||||
// $Loading_h3-color: darken($Loading_outer-color, 20%);
|
||||
|
||||
#loadingPage {
|
||||
// @include radial-gradient($Loading_inner-color, $Loading_outer-color);
|
||||
background-color: $main-color;
|
||||
|
||||
div {
|
||||
vertical-align: middle;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
|
||||
h1 {
|
||||
font-size: 40pt;
|
||||
font-weight: bold;
|
||||
// color: $Loading_h1-color;
|
||||
color: $main-alternate-text-color;
|
||||
margin-top: 10%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 18pt;
|
||||
// color: $Loading_h3-color;
|
||||
color: $main-text-color;
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
}
|
151
frontend/delta/scss/style/loginPage.scss
Normal file
151
frontend/delta/scss/style/loginPage.scss
Normal file
@ -0,0 +1,151 @@
|
||||
#loginPage {
|
||||
overflow: scroll;
|
||||
|
||||
div.loginForm {
|
||||
@include flexbox;
|
||||
@include flex-direction(column);
|
||||
@include align-items(stretch);
|
||||
|
||||
height: 100%;
|
||||
|
||||
text-align: center;
|
||||
background-color: $main-color;
|
||||
|
||||
header {
|
||||
@include flex(1);
|
||||
@include icon-font();
|
||||
|
||||
font-size: 48pt;
|
||||
color: $main-alternate-text-color;
|
||||
}
|
||||
|
||||
div.form {
|
||||
@include flex(4);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
form {
|
||||
position: relative;
|
||||
background: $main-alternate-text-color;
|
||||
|
||||
// @include border-radius(10px);
|
||||
padding: 20px;
|
||||
margin-bottom: 50px;
|
||||
/*
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
margin-left: 50%;
|
||||
left: -15px;
|
||||
border-style: solid;
|
||||
border-width: 0 15px 15px;
|
||||
border-color: $main-alternate-text-color transparent;
|
||||
display: block;
|
||||
width: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
*/
|
||||
label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input {
|
||||
font-family: "clipperz-font";
|
||||
display: block;
|
||||
// @include border-radius(4px);
|
||||
padding: 5px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 100%;
|
||||
// box-shadow:inset 0 0 0;
|
||||
font-size: 24pt;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: "clipperz-font";
|
||||
min-height: 48px;
|
||||
min-width: 48px;
|
||||
|
||||
color: white;
|
||||
font-size: 24pt;
|
||||
font-weight: 500;
|
||||
border: 0px;
|
||||
|
||||
padding: 10px 25px;
|
||||
|
||||
border: 1px solid white;
|
||||
background-color: $main-color;
|
||||
@include transition(background-color font-weight, 0.2s, linear);
|
||||
|
||||
&:hover {
|
||||
};
|
||||
|
||||
&:disabled {
|
||||
font-weight: 100;
|
||||
background-color: #c0c0c0;
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
div.registrationLink {
|
||||
@include flex(1);
|
||||
|
||||
color: $main-alternate-text-color;
|
||||
background-color: $main-alternate-color;
|
||||
cursor: pointer;
|
||||
font-size: 24pt;
|
||||
|
||||
&:before {
|
||||
content: "> ";
|
||||
};
|
||||
|
||||
a {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
div.loginForm.extra-short {
|
||||
header {
|
||||
// @include flex(1);
|
||||
font-size: 18pt;
|
||||
}
|
||||
|
||||
div.form {
|
||||
// @include flex(6);
|
||||
form {
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
input {
|
||||
padding: 3px;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 5px;
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
button {
|
||||
min-height: 20px;
|
||||
|
||||
font-size: 12pt;
|
||||
padding: 3px 10px;
|
||||
border: 1px solid white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.registrationLink {
|
||||
// @include flex(2);
|
||||
font-size: 14pt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
111
frontend/delta/scss/style/registrationPage.scss
Normal file
111
frontend/delta/scss/style/registrationPage.scss
Normal file
@ -0,0 +1,111 @@
|
||||
#registrationPage {
|
||||
background-color: $main-alternate-color;
|
||||
color: $main-alternate-text-color;
|
||||
|
||||
label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input {
|
||||
display: block;
|
||||
border: 1px solid $solarize-Background-92;
|
||||
@include border-radius(6px);
|
||||
padding: 5px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 100%;
|
||||
box-shadow:inset 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
.steps {
|
||||
.step {
|
||||
display: none;
|
||||
|
||||
&.center {
|
||||
display: block;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: $solarize-Accent-Blue;
|
||||
font-size: 24pt;
|
||||
font-weight: 700;
|
||||
margin: 0px;
|
||||
}
|
||||
p {
|
||||
color: $solarize-Content-50;
|
||||
font-size: 14pt;
|
||||
font-weight: 100;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
&.TERMS_OF_SERVICE {
|
||||
.checkboxBlock {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
clear: both;
|
||||
|
||||
input {
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 5px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 12pt;
|
||||
font-weight: 500;
|
||||
display: block;
|
||||
|
||||
a {
|
||||
color: $solarize-Accent-Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.stepIndex {
|
||||
text-align: center;
|
||||
.stepIndexItem {
|
||||
font-weight: 900;
|
||||
font-size: 28pt;
|
||||
display: inline;
|
||||
color: lightgrey;
|
||||
|
||||
&.center {
|
||||
color: gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
.buttons {
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
|
||||
.button {
|
||||
margin: 10px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
|
||||
font-weight: 900;
|
||||
line-height: 45px;
|
||||
font-size: 24px;
|
||||
|
||||
&.back {
|
||||
|
||||
background-color: lightgrey;
|
||||
|
||||
// &.step_-1 {
|
||||
// visibility: hidden;
|
||||
// }
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background-color: #c0c0c0;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
frontend/delta/scss/style/selectionPanel.scss
Normal file
69
frontend/delta/scss/style/selectionPanel.scss
Normal file
@ -0,0 +1,69 @@
|
||||
#selections {
|
||||
background-color: $main-alternate-color;
|
||||
color: $main-alternate-text-color;
|
||||
font-size: 18pt;
|
||||
overflow: scroll;
|
||||
height: 100%;
|
||||
|
||||
$iconColumnWidth: 40px;
|
||||
|
||||
ul.defaultSet {
|
||||
font-weight: bold;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
li {
|
||||
&.allCards:before {
|
||||
content: "clipperz";
|
||||
}
|
||||
|
||||
&.recentCards:before {
|
||||
content: "recent";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
label {
|
||||
@include icon-font();
|
||||
font-size: 18pt;
|
||||
padding-left: 5px;
|
||||
padding-right:5px;
|
||||
}
|
||||
|
||||
input {
|
||||
font-family: "clipperz-font";
|
||||
color: #999;
|
||||
font-size: 18pt;
|
||||
width: $selectionPanelWidth - $iconColumnWidth - 10px;
|
||||
}
|
||||
}
|
||||
|
||||
ul.tagList {
|
||||
padding-top: 10px;
|
||||
|
||||
li {
|
||||
&:before {
|
||||
content: "tag";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
padding-left: 35px;
|
||||
text-indent: -35px;
|
||||
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
&:before {
|
||||
@include icon-font();
|
||||
font-weight: normal;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
font-size: 14pt;
|
||||
}
|
||||
}
|
||||
}
|
19
frontend/delta/scss/style/settingsPanel.scss
Normal file
19
frontend/delta/scss/style/settingsPanel.scss
Normal file
@ -0,0 +1,19 @@
|
||||
#extraFeaturesPanel {
|
||||
background-color: $main-alternate-color;
|
||||
color: $main-alternate-text-color;
|
||||
|
||||
header {
|
||||
text-align: right;
|
||||
height: 48px;
|
||||
font-size: 24pt;
|
||||
|
||||
.button {
|
||||
@include icon-font();
|
||||
|
||||
.label {
|
||||
padding-top: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
@import "web/fonts";
|
||||
@import "web/overlay";
|
||||
@import "web/behavior";
|
||||
@import "web/style";
|
||||
@import "web/checkbox";
|
||||
@import "web/480";
|
||||
@import "web/768";
|
||||
@import "web/992";
|
||||
|
||||
@import "web/add2home";
|
@ -1,11 +0,0 @@
|
||||
@media only screen and (min-width: 480px) {
|
||||
.loginForm {
|
||||
font-size: 1.2em;
|
||||
|
||||
input {
|
||||
}
|
||||
button {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
@media only screen and (min-width: 768px) {
|
||||
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
@media only screen and (min-width: 992px) {
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Main container
|
||||
*
|
||||
*/
|
||||
#addToHomeScreen {
|
||||
z-index:9999;
|
||||
-webkit-user-select:none;
|
||||
user-select:none;
|
||||
-webkit-box-sizing:border-box;
|
||||
box-sizing:border-box;
|
||||
-webkit-touch-callout:none;
|
||||
touch-callout:none;
|
||||
width:240px;
|
||||
font-size:15px;
|
||||
padding:12px 14px;
|
||||
text-align:left;
|
||||
font-family:helvetica;
|
||||
background-image:-webkit-gradient(linear,0 0,0 100%,color-stop(0,#fff),color-stop(0.02,#eee),color-stop(0.98,#ccc),color-stop(1,#a3a3a3));
|
||||
border:1px solid #505050;
|
||||
-webkit-border-radius:8px;
|
||||
-webkit-background-clip:padding-box;
|
||||
color:#333;
|
||||
text-shadow:0 1px 0 rgba(255,255,255,0.75);
|
||||
line-height:130%;
|
||||
-webkit-box-shadow:0 0 4px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
#addToHomeScreen.addToHomeIpad {
|
||||
width:268px;
|
||||
font-size:18px;
|
||||
padding:14px;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The 'wide' class is added when the popup contains the touch icon
|
||||
*
|
||||
*/
|
||||
#addToHomeScreen.addToHomeWide {
|
||||
width:296px;
|
||||
}
|
||||
|
||||
#addToHomeScreen.addToHomeIpad.addToHomeWide {
|
||||
width:320px;
|
||||
font-size:18px;
|
||||
padding:14px;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The balloon arrow
|
||||
*
|
||||
*/
|
||||
#addToHomeScreen .addToHomeArrow {
|
||||
position:absolute;
|
||||
background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(204,204,204,0)),color-stop(0.4,rgba(204,204,204,0)),color-stop(0.4,#ccc));
|
||||
border-width:0 1px 1px 0;
|
||||
border-style:solid;
|
||||
border-color:#505050;
|
||||
width:16px; height:16px;
|
||||
-webkit-transform:rotateZ(45deg);
|
||||
bottom:-9px; left:50%;
|
||||
margin-left:-8px;
|
||||
-webkit-box-shadow:inset -1px -1px 0 #a9a9a9;
|
||||
-webkit-border-bottom-right-radius:2px;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The balloon arrow for iPad
|
||||
*
|
||||
*/
|
||||
#addToHomeScreen.addToHomeIpad .addToHomeArrow {
|
||||
-webkit-transform:rotateZ(-135deg);
|
||||
background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(238,238,238,0)),color-stop(0.4,rgba(238,238,238,0)),color-stop(0.4,#eee));
|
||||
-webkit-box-shadow:inset -1px -1px 0 #fff;
|
||||
top:-9px; bottom:auto; left:50%;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Close button
|
||||
*
|
||||
*/
|
||||
#addToHomeScreen .addToHomeClose {
|
||||
-webkit-box-sizing:border-box;
|
||||
position:absolute;
|
||||
right:4px;
|
||||
top:4px;
|
||||
width:18px;
|
||||
height:18px; line-height:14px;
|
||||
text-align:center;
|
||||
text-indent:1px;
|
||||
-webkit-border-radius:9px;
|
||||
background:rgba(0,0,0,0.12);
|
||||
color:#707070;
|
||||
-webkit-box-shadow:0 1px 0 #fff;
|
||||
font-size:16px;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The '+' icon, displayed only on iOS < 4.2
|
||||
*
|
||||
*/
|
||||
#addToHomeScreen .addToHomePlus {
|
||||
font-weight:bold;
|
||||
font-size:1.3em;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* The 'share' icon, displayed only on iOS >= 4.2
|
||||
*
|
||||
*/
|
||||
#addToHomeScreen .addToHomeShare {
|
||||
display:inline-block;
|
||||
width:18px;
|
||||
height:15px;
|
||||
background-repeat:no-repeat;
|
||||
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAeCAQAAADu6HTYAAADPElEQVR4Xq3TX2gcRRzA8e/M7mVv2+TSNpc/TZtrY6jUGqgaSAmEChKLrYK0YH0RFC2CSCkEfCghiKU04J8qNigq6os+iQV98MHWFwVBrQQRWs21lBw5cw3NNb1/udu72RGG5Y77IzXW77D7sAwf5scyYoL6BGXSDKFZwaGpLvIUaeoCkvX1MmsM0Ny6oRSQYOLuIS+YZOpfQdqslpUxcZrzTVAz4qPwW2O3CeIwC/RSzeY6Ow1QhUrkr+YOWfEKDkEP8Rij7CHKJmrFSDHBdwGEE5wiGChPN+PnT8VdRtEIl1d4gRj/1EVe5ZSBKGh8iqQpo/Fo5+3C/gz0MYg4zgwbqday1/Q4B8BGQ45d/Hi54lakCrU5obOcidJpu1+Lg9whjabyaOYLnrIBFFaRD+xe2ybMDWY66GmP/WA9cGfGp0CWhy0wkMN8inepFiH2rV1j0NQSNQbFLRQnS8/8YSDBBpadfv4CYDub2fmeHDNAsL1MBWUel0iA+Xik6eHcyvD3vAMSU1TGuA/YRS+dD7ovCQN43GKRFCU20Kd3V/avDVVyAZ5niTEuLA5/zBGWg9EEEhfJKN200Tat8CmRAQb9+wv7soPlHt2tQorsz1uPbr0HTY4sJwrH47zJZwABBAKLMBoQXepwgTwdHCo+fXMkQ4lrxEmQ5AaXipPqDY9V2vn09tgvTPI71EEGYxM+/uMJLJ4svpgaWGKOi/xKgmqLSUGSUd5f2vIVJ/CgBaTIUsZ7ZBsn0+NzfMOXLFCXQyTcybN6ep5ZZgUOHn7jpfUpsZshdugPGf+E5zjbyHTSRyQ8xfRPPM/s63RHeuknSoT22mjmmnAOIMkUZ6D1xSfPPAfd1WFKM3sO2CMaHx8M1NjnXKHaAGGkOW0C02WeYHUz4qMtx+w5gUDS8NckYe5lHsMYwCZEPyEEmjLDZFmAS7CDviMdxyTkMNVBKEmYLvbiQQBIBBbCQG04bGQvFWz6CfsCQLWCigILFwcfkGYBiOpbYuOizTAyYyDdCtrGaRG1LCkIgMYEFhI0WqQZoSlbGRyHKe4qOx7iv2bVQW9dp4dlM/x6kmwnWQcd/Q3FCqwTEiT5s+6D5v/pb0SSHyg7uhMWAAAAAElFTkSuQmCC);
|
||||
background-size:18px 15px;
|
||||
text-indent:-9999em;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
#addToHomeScreen .addToHomeShare.addToHomeShareOS7 {
|
||||
width:11px;
|
||||
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAA8CAYAAAAQTCjdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAASCQAAEgkB80sG3AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKjSURBVGiB7dpPiFVVHMDxz7m9NCtMyI2bEJEC25WrEkzHUXCRraIwdNE8ZxfYIlcis1ZEbGEzT1QCF4XgH1CyWhUoJKIWNRGEiCNKmkSiYTzfcfGuOokx77x3ZlS8382959zfn+/invvn3RdijHIRBrwkOINCYXEcdjpb7VyiYdBsLScwt5y6IloYdzqXo36Ro0gY9IKWo+5JwmzBt2HQnBw9ehYNazyn5TBee8Dh+Vq+CWu92GufnkTDR6ab7gDeBNHouMM/l9tXTXM0fGBmL726Fg1Dam74EsvKqR8VNowL2Yzj5f7rnnE4DHq2235diYYhhTGfC94up35T0y+6di/ITU0rKVd+sEi0P7xr2pSJOu8zvF+OzqEv7vDH/WFxt7/cshy/ticsN8sXYUht0kXDOlsF9XJ4UaEvNoz9X3zc5bKaZThbyr5jzJ4wlNY7KTgM+ES0vhz+KeiPw36fKC/ucAF9uFBOrTZm26SJCtaV27+xIo7cXdkTEhvOoh+XyxprU1qnim7CQdGK2HAyKRexYVShT3RItDElN+mkjiP2Ym+S3f01hv2EVal5WW6hU0ElmptaqJuBpXg6MbeFH2LDpU6CQ93zWIKnEvs0cayGU3glMfkOo1jQYewZzOuyz7FC95Jwo5OgUFfgeg993hh/eTqCTxOSm/iuk8DY0Ap1b2GhtHXxsfZN4j/X0fOx4auEIknEhqv4OiUn1L13Z/+xWfWVaG4q0dxUormpRHNTieamEs1NJZqbJ1Q0jHvdiJo5S2cVjSNOCHZhn3/SnuYnIvl3yomIIz7MXZMn9hydRCrR3FSiualEc1OJ5qYSzU0lmptKNDePjWgwcPePT7/g+4cp8wCW4GXaryK3tL+mLdD5x62ppllgu7bso8q/2HIbzGWdNmWnSJwAAAAASUVORK5CYII=);
|
||||
background-size:11px 15px;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The touch icon (if available)
|
||||
*
|
||||
*/
|
||||
#addToHomeScreen .addToHomeTouchIcon {
|
||||
display:block;
|
||||
float:left;
|
||||
-webkit-border-radius:6px;
|
||||
border-radius:6px;
|
||||
-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.5),
|
||||
inset 0 0 2px rgba(255,255,255,0.9);
|
||||
box-shadow:0 1px 3px rgba(0,0,0,0.5),
|
||||
inset 0 0 2px rgba(255,255,255,0.9);
|
||||
background-repeat:no-repeat;
|
||||
width:57px; height:57px;
|
||||
-webkit-background-size:57px 57px;
|
||||
background-size:57px 57px;
|
||||
margin:0 12px 0 0;
|
||||
border:1px solid #333;
|
||||
-webkit-background-clip:padding-box;
|
||||
background-clip:padding-box;
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
// https://github.com/h5bp/Effeckt.css
|
||||
|
||||
|
||||
@mixin slide () {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
|
||||
&.left {
|
||||
-webkit-transform: translate3d(-100%, 0, 0);
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
|
||||
&.center {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
&.right {
|
||||
-webkit-transform: translate3d(100%, 0, 0);
|
||||
transform: translate3d(100%, 0, 0);
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
|
||||
&.transition {
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&.transition {
|
||||
-webkit-transition-duration: .25s;
|
||||
transition-duration: .25s;
|
||||
}
|
||||
}
|
||||
|
||||
// http://coenraets.org/blog/2013/03/hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps/
|
||||
.page {
|
||||
position: absolute;
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@include slide();
|
||||
}
|
||||
|
||||
/*
|
||||
.registrationForm {
|
||||
.steps {
|
||||
.step {
|
||||
position: absolute;
|
||||
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// width: 100%;
|
||||
// height: 100%;
|
||||
|
||||
.slide();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// tentative 3D transformations
|
||||
/*
|
||||
.page {
|
||||
transform: rotateY( 0deg) translateZ( 100px);
|
||||
|
||||
&.left {
|
||||
transform: rotateY( -90deg) translateZ( 100px);
|
||||
}
|
||||
|
||||
&.center {
|
||||
transform: rotateY( 0deg) translateZ( 100px);
|
||||
}
|
||||
|
||||
&.right {
|
||||
transform: rotateY( 90deg) translateZ( 100px);
|
||||
}
|
||||
}
|
||||
|
||||
#mainDiv {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
transform-style: preserve-3d;
|
||||
|
||||
transition: transform 3s;
|
||||
|
||||
&.show-front { transform: translateZ( -100px ) rotateY( 0deg ); }
|
||||
&.show-back { transform: translateZ( -100px ) rotateX( -180deg ); }
|
||||
&.show-right { transform: translateZ( -100px ) rotateY( -90deg ); }
|
||||
&.show-left { transform: translateZ( -100px ) rotateY( 90deg ); }
|
||||
&.show-top { transform: translateZ( -100px ) rotateX( -90deg ); }
|
||||
&.show-bottom { transform: translateZ( -100px ) rotateX( 90deg ); }
|
||||
}
|
||||
*/
|
||||
//=======================================================================
|
||||
|
||||
|
||||
//=======================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================================
|
@ -1,96 +0,0 @@
|
||||
div.checkbox {
|
||||
display: block;
|
||||
margin-bottom: 20px;
|
||||
@include border-radius(4px);
|
||||
border: 2px solid white;
|
||||
background-color: white;
|
||||
width: 80px;
|
||||
position: relative;
|
||||
height: 32px;
|
||||
|
||||
&:before {
|
||||
content: "ON";
|
||||
padding-left: 9px;
|
||||
line-height: 32px;
|
||||
color: $solarize-Accent-Cyan;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "OFF";
|
||||
// padding-left: 12px;
|
||||
padding-left: 25px;
|
||||
line-height: 32px;
|
||||
color: $solarize-Accent-Cyan;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
||||
|
||||
label.check {
|
||||
display: block;
|
||||
width: 40px;
|
||||
height: 30px;
|
||||
@include border-radius(3px);
|
||||
background-color: $solarize-Accent-Magenta;
|
||||
border: 1px solid $solarize-Accent-Magenta;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
input[type=checkbox] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked + label.check {
|
||||
top: 0px;
|
||||
left: 38px;
|
||||
@include animation(labelON, .2s, ease-in, 1);
|
||||
}
|
||||
|
||||
input[type=checkbox] + label.check {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
@include animation(labelOFF, .2s, ease-in, 1);
|
||||
}
|
||||
|
||||
label.info {
|
||||
position: absolute;
|
||||
color: white;
|
||||
top: 0px;
|
||||
left: 100px;
|
||||
line-height: 32px;
|
||||
width: 200px;
|
||||
font-size: 16pt;
|
||||
}
|
||||
}
|
||||
|
||||
@include keyframes(labelON) {
|
||||
0% {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
100% {
|
||||
top: 0px;
|
||||
left: 38px;
|
||||
}
|
||||
}
|
||||
|
||||
@include keyframes(labelOFF) {
|
||||
0% {
|
||||
top: 0px;
|
||||
left: 38px;
|
||||
}
|
||||
|
||||
100% {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
// --------------------------------------------------
|
||||
// Flexbox LESS mixins
|
||||
// The spec: http://www.w3.org/TR/css3-flexbox
|
||||
//
|
||||
// Other info:
|
||||
// - http://philipwalton.github.io/solved-by-flexbox/
|
||||
// --------------------------------------------------
|
||||
|
||||
// Flexbox display
|
||||
// flex or inline-flex
|
||||
.flex-display(@display: flex) {
|
||||
display: ~"-webkit-@{display}";
|
||||
display: ~"-moz-@{display}";
|
||||
display: ~"-ms-@{display}box"; // IE10 uses -ms-flexbox
|
||||
display: ~"-ms-@{display}"; // IE11
|
||||
display: @display;
|
||||
}
|
||||
|
||||
// The 'flex' shorthand
|
||||
// - applies to: flex items
|
||||
// <positive-number>, initial, auto, or none
|
||||
.flex(@columns: initial) {
|
||||
-webkit-flex: @columns;
|
||||
-moz-flex: @columns;
|
||||
-ms-flex: @columns;
|
||||
flex: @columns;
|
||||
}
|
||||
|
||||
// Flex Flow Direction
|
||||
// - applies to: flex containers
|
||||
// row | row-reverse | column | column-reverse
|
||||
.flex-direction(@direction: row) {
|
||||
-webkit-flex-direction: @direction;
|
||||
-moz-flex-direction: @direction;
|
||||
-ms-flex-direction: @direction;
|
||||
flex-direction: @direction;
|
||||
}
|
||||
|
||||
// Flex Line Wrapping
|
||||
// - applies to: flex containers
|
||||
// nowrap | wrap | wrap-reverse
|
||||
.flex-wrap(@wrap: nowrap) {
|
||||
-webkit-flex-wrap: @wrap;
|
||||
-moz-flex-wrap: @wrap;
|
||||
-ms-flex-wrap: @wrap;
|
||||
flex-wrap: @wrap;
|
||||
}
|
||||
|
||||
// Flex Direction and Wrap
|
||||
// - applies to: flex containers
|
||||
// <flex-direction> || <flex-wrap>
|
||||
.flex-flow(@flow) {
|
||||
-webkit-flex-flow: @flow;
|
||||
-moz-flex-flow: @flow;
|
||||
-ms-flex-flow: @flow;
|
||||
flex-flow: @flow;
|
||||
}
|
||||
|
||||
// Display Order
|
||||
// - applies to: flex items
|
||||
// <integer>
|
||||
.flex-order(@order: 0) {
|
||||
-webkit-order: @order;
|
||||
-moz-order: @order;
|
||||
-ms-order: @order;
|
||||
order: @order;
|
||||
}
|
||||
|
||||
// Flex grow factor
|
||||
// - applies to: flex items
|
||||
// <number>
|
||||
.flex-grow(@grow: 0) {
|
||||
-webkit-flex-grow: @grow;
|
||||
-moz-flex-grow: @grow;
|
||||
-ms-flex-grow: @grow;
|
||||
flex-grow: @grow;
|
||||
}
|
||||
|
||||
// Flex shr
|
||||
// - applies to: flex itemsink factor
|
||||
// <number>
|
||||
.flex-shrink(@shrink: 1) {
|
||||
-webkit-flex-shrink: @shrink;
|
||||
-moz-flex-shrink: @shrink;
|
||||
-ms-flex-shrink: @shrink;
|
||||
flex-shrink: @shrink;
|
||||
}
|
||||
|
||||
// Flex basis
|
||||
// - the initial main size of the flex item
|
||||
// - applies to: flex itemsnitial main size of the flex item
|
||||
// <width>
|
||||
.flex-basis(@width: auto) {
|
||||
-webkit-flex-basis: @width;
|
||||
-moz-flex-basis: @width;
|
||||
-ms-flex-basis: @width;
|
||||
flex-basis: @width;
|
||||
}
|
||||
|
||||
// Axis Alignment
|
||||
// - applies to: flex containers
|
||||
// flex-start | flex-end | center | space-between | space-around
|
||||
.justify-content(@justify: flex-start) {
|
||||
-webkit-justify-content: @justify;
|
||||
-moz-justify-content: @justify;
|
||||
-ms-justify-content: @justify;
|
||||
justify-content: @justify;
|
||||
}
|
||||
|
||||
// Packing Flex Lines
|
||||
// - applies to: multi-line flex containers
|
||||
// flex-start | flex-end | center | space-between | space-around | stretch
|
||||
.align-content(@align: stretch) {
|
||||
-webkit-align-content: @align;
|
||||
-moz-align-content: @align;
|
||||
-ms-align-content: @align;
|
||||
align-content: @align;
|
||||
}
|
||||
|
||||
// Cross-axis Alignment
|
||||
// - applies to: flex containers
|
||||
// flex-start | flex-end | center | baseline | stretch
|
||||
.align-items(@align: stretch) {
|
||||
-webkit-align-items: @align;
|
||||
-moz-align-items: @align;
|
||||
-ms-align-items: @align;
|
||||
align-items: @align;
|
||||
}
|
||||
|
||||
// Cross-axis Alignment
|
||||
// - applies to: flex items
|
||||
// auto | flex-start | flex-end | center | baseline | stretch
|
||||
.align-self(@align: auto) {
|
||||
-webkit-align-self: @align;
|
||||
-moz-align-self: @align;
|
||||
-ms-align-self: @align;
|
||||
align-self: @align;
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
164
frontend/delta/tests/SimpleTest/SimpleTest.Async.js
Normal file
164
frontend/delta/tests/SimpleTest/SimpleTest.Async.js
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
MochiKit.Base.update(Clipperz.Async.Deferred.prototype, {
|
||||
/*
|
||||
'_addTest': function(anExpectedValue, aDescription, isDeep, aResult) {
|
||||
if (isDeep) {
|
||||
SimpleTest.isDeeply(aResult, anExpectedValue, aDescription);
|
||||
} else {
|
||||
SimpleTest.is(aResult, anExpectedValue, aDescription);
|
||||
}
|
||||
|
||||
return aResult;
|
||||
},
|
||||
*/
|
||||
'addTest': function (anExpectedValue, aDescription, isDeep) {
|
||||
// this.addMethod(this, '_addTest', anExpectedValue, aDescription, isDeep);
|
||||
// this.addCallback(Clipperz.Async.test, anExpectedValue, aDescription, isDeep);
|
||||
|
||||
if (isDeep) {
|
||||
// SimpleTest.isDeeply(aResult, anExpectedValue, aDescription);
|
||||
this.addCallback(Clipperz.Async.Test.isDeeply(anExpectedValue, aDescription));
|
||||
} else {
|
||||
// SimpleTest.is(aResult, anExpectedValue, aDescription);
|
||||
this.addCallback(Clipperz.Async.Test.is(anExpectedValue, aDescription));
|
||||
}
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'shouldSucceed': function (aDescription) {
|
||||
this.addCallbackPass(SimpleTest.ok, true, aDescription);
|
||||
this.addErrbackPass (SimpleTest.ok, false, aDescription);
|
||||
this.addBoth(MochiKit.Async.succeed, null);
|
||||
},
|
||||
|
||||
'shouldFail': function (aDescription) {
|
||||
this.addCallbackPass(SimpleTest.ok, false, aDescription);
|
||||
this.addErrbackPass (SimpleTest.ok, true, aDescription);
|
||||
this.addBoth(MochiKit.Async.succeed, null);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
});
|
||||
|
||||
|
||||
Clipperz.Async.Test = {};
|
||||
MochiKit.Base.update(Clipperz.Async.Test, {
|
||||
|
||||
'is': function (anExpectedResult, aDescription) {
|
||||
return MochiKit.Base.partial(function (anExpectedResult, aDescription, aResult) {
|
||||
SimpleTest.is(aResult, anExpectedResult, aDescription);
|
||||
|
||||
return aResult;
|
||||
}, anExpectedResult, aDescription);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'ok': function (aDescription) {
|
||||
return MochiKit.Base.partial(function (aDescription, aResult) {
|
||||
SimpleTest.ok(aResult, aDescription);
|
||||
|
||||
return aResult;
|
||||
}, aDescription);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'fail': function(aDescription) {
|
||||
return MochiKit.Base.partial(function (aDescription, aResult) {
|
||||
SimpleTest.ok(!aResult, aDescription);
|
||||
|
||||
return aResult;
|
||||
}, aDescription);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isDeeply': function (anExpectedResult, aDescription) {
|
||||
return MochiKit.Base.partial(function (anExpectedResult, aDescription, aResult) {
|
||||
SimpleTest.isDeeply(aResult, anExpectedResult, aDescription);
|
||||
|
||||
return aResult;
|
||||
}, anExpectedResult, aDescription);
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
__syntaxFix__: "syntax fix"
|
||||
});
|
||||
|
||||
|
||||
SimpleTest.runDeferredTests = function (aName, aTestSet, aTestArguments) {
|
||||
try {
|
||||
var deferredTests;
|
||||
var aTestName;
|
||||
var title;
|
||||
|
||||
deferredTests = new Clipperz.Async.Deferred(aName + " <deferred test set>", aTestArguments);
|
||||
|
||||
title = aName;
|
||||
|
||||
aTestName = window.location.href.match(/#.*/);
|
||||
if (aTestName && (aTestName != '#')) {
|
||||
aTestName = aTestName[0].slice(1);
|
||||
if (aTestName in aTestSet) {
|
||||
//Clipperz.log("single test execution, via fragment identifier", aTestName);
|
||||
title += ' [' + aTestName + ']';
|
||||
deferredTests.addCallback(aTestSet[aTestName], aTestArguments);
|
||||
deferredTests.addErrback(SimpleTest.ok, false, aTestName);
|
||||
} else {
|
||||
title = 'WRONG TEST NAME'
|
||||
deferredTests.addBoth(is, aTestName, null, "Wrong test name selected to run");
|
||||
}
|
||||
} else {
|
||||
for (aTestName in aTestSet) {
|
||||
deferredTests.addCallback(aTestSet[aTestName], aTestArguments);
|
||||
deferredTests.addErrback(SimpleTest.ok, false, aTestName);
|
||||
deferredTests.addBoth(MochiKit.Async.wait, 0.5);
|
||||
}
|
||||
deferredTests.addBoth(is, true, true, "FINISH: completed the full stack of tests");
|
||||
}
|
||||
|
||||
MochiKit.DOM.currentDocument().title = title;
|
||||
|
||||
deferredTests.addBoth(SimpleTest.finish);
|
||||
deferredTests.callback();
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
} catch (err) {
|
||||
var s = "test suite failure!\n";
|
||||
var o = {};
|
||||
var k = null;
|
||||
for (k in err) {
|
||||
// ensure unique keys?!
|
||||
if (!o[k]) {
|
||||
s += k + ": " + err[k] + "\n";
|
||||
o[k] = err[k];
|
||||
}
|
||||
}
|
||||
ok ( false, s );
|
||||
}
|
||||
}
|
447
frontend/delta/tests/SimpleTest/SimpleTest.js
Normal file
447
frontend/delta/tests/SimpleTest/SimpleTest.js
Normal file
@ -0,0 +1,447 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* SimpleTest, a partial Test.Simple/Test.More API compatible test library.
|
||||
*
|
||||
* Why?
|
||||
*
|
||||
* Test.Simple doesn't work on IE < 6.
|
||||
* TODO:
|
||||
* * Support the Test.Simple API used by MochiKit, to be able to test MochiKit
|
||||
* itself against IE 5.5
|
||||
*
|
||||
**/
|
||||
|
||||
if (typeof(SimpleTest) == "undefined") {
|
||||
var SimpleTest = {};
|
||||
}
|
||||
|
||||
// Check to see if the TestRunner is present and has logging
|
||||
if (typeof(parent) != "undefined" && parent.TestRunner) {
|
||||
SimpleTest._logEnabled = parent.TestRunner.logEnabled;
|
||||
}
|
||||
|
||||
SimpleTest._tests = [];
|
||||
SimpleTest._stopOnLoad = true;
|
||||
SimpleTest._scopeCopy = {};
|
||||
|
||||
/**
|
||||
* Saves a copy of the specified scope variables.
|
||||
*/
|
||||
SimpleTest.saveScope = function (scope) {
|
||||
SimpleTest._scopeCopy = {};
|
||||
for (var k in scope) {
|
||||
SimpleTest._scopeCopy[k] = scope[k];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the specified scope against the stored copy and reports
|
||||
* any differences as test failures.
|
||||
*/
|
||||
SimpleTest.verifyScope = function (scope) {
|
||||
var filter = ['test', '_firebug','_FirebugConsole','XMLHttpRequest','Audio',
|
||||
'XSLTProcessor','Option','Image','scrollMaxX','scrollMaxY',
|
||||
'clipboardData'];
|
||||
for (var k in scope) {
|
||||
if (MochiKit.Base.findValue(filter, k) < 0) {
|
||||
var v = scope[k];
|
||||
var old = SimpleTest._scopeCopy[k];
|
||||
if (v !== old && typeof(old) === "undefined") {
|
||||
SimpleTest.ok(false, "scope modified, variable " + k + " was added");
|
||||
} else if (v !== old) {
|
||||
SimpleTest.ok(false, "scope modified, variable " + k + " changed from: " + old + ", to: " + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var k in SimpleTest._scopeCopy) {
|
||||
if (!(k in scope)) {
|
||||
SimpleTest.ok(false, "scope modified, variable " + k + " has been removed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Something like assert.
|
||||
*/
|
||||
SimpleTest.ok = function (condition, name, diag) {
|
||||
var test = {'result': !!condition, 'name': name, 'diag': diag || ""};
|
||||
if (SimpleTest._logEnabled) {
|
||||
var msg = test.result ? "PASS" : "FAIL";
|
||||
msg += " | " + test.name;
|
||||
if (test.result) {
|
||||
parent.TestRunner.logger.log(msg);
|
||||
} else {
|
||||
msg += " | " + test.diag;
|
||||
parent.TestRunner.logger.error(msg);
|
||||
}
|
||||
}
|
||||
SimpleTest._tests.push(test);
|
||||
};
|
||||
|
||||
/**
|
||||
* Roughly equivalent to ok(a==b, name)
|
||||
*/
|
||||
SimpleTest.is = function (a, b, name) {
|
||||
var repr = MochiKit.Base.repr;
|
||||
SimpleTest.ok(a == b, name, "got " + repr(a) + ", expected " + repr(b));
|
||||
};
|
||||
|
||||
/**
|
||||
* Roughly equivalent to ok(compare(a,b)==0, name)
|
||||
*/
|
||||
SimpleTest.eq = function (a, b, name) {
|
||||
var base = MochiKit.Base;
|
||||
var repr = base.repr;
|
||||
try {
|
||||
SimpleTest.ok(base.compare(a, b) == 0, name, "got " + repr(a) + ", expected " + repr(b));
|
||||
} catch (e) {
|
||||
SimpleTest.ok(false, name, "exception in compare: " + repr(e));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Makes a test report, returns it as a DIV element.
|
||||
**/
|
||||
SimpleTest.report = function () {
|
||||
var DIV = MochiKit.DOM.DIV;
|
||||
var passed = 0;
|
||||
var failed = 0;
|
||||
var results = MochiKit.Base.map(
|
||||
function (test) {
|
||||
var cls, msg;
|
||||
if (test.result) {
|
||||
passed++;
|
||||
cls = "test_ok";
|
||||
msg = "ok - " + test.name;
|
||||
} else {
|
||||
failed++;
|
||||
cls = "test_not_ok";
|
||||
msg = "not ok - " + test.name;
|
||||
if (test.diag != null && test.diag != "") {
|
||||
msg += ": " + test.diag;
|
||||
}
|
||||
}
|
||||
return DIV({"class": cls}, msg);
|
||||
},
|
||||
SimpleTest._tests
|
||||
);
|
||||
var summary_class = ((failed == 0) ? 'all_pass' : 'some_fail');
|
||||
return DIV({'class': 'tests_report'},
|
||||
DIV({'class': 'tests_summary ' + summary_class},
|
||||
DIV({'class': 'tests_passed'}, "Passed: " + passed),
|
||||
DIV({'class': 'tests_failed'}, "Failed: " + failed)),
|
||||
results
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle element visibility
|
||||
**/
|
||||
SimpleTest.toggle = function(el) {
|
||||
if (MochiKit.Style.getStyle(el, 'display') == 'block') {
|
||||
el.style.display = 'none';
|
||||
} else {
|
||||
el.style.display = 'block';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle visibility for divs with a specific class.
|
||||
**/
|
||||
SimpleTest.toggleByClass = function (cls) {
|
||||
var elems = MochiKit.DOM.getElementsByTagAndClassName('div', cls);
|
||||
MochiKit.Base.map(SimpleTest.toggle, elems);
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the report in the browser
|
||||
**/
|
||||
|
||||
SimpleTest.showReport = function() {
|
||||
var base = MochiKit.Base;
|
||||
var dom = MochiKit.DOM;
|
||||
var togglePassed = dom.A({'href': '#'}, "Toggle passed tests");
|
||||
var toggleFailed = dom.A({'href': '#'}, "Toggle failed tests");
|
||||
togglePassed.onclick = base.partial(SimpleTest.toggleByClass, 'test_ok');
|
||||
toggleFailed.onclick = base.partial(SimpleTest.toggleByClass, 'test_not_ok');
|
||||
var body = document.getElementsByTagName("body")[0];
|
||||
var firstChild = body.childNodes[0];
|
||||
var addNode;
|
||||
if (firstChild) {
|
||||
addNode = function (el) {
|
||||
body.insertBefore(el, firstChild);
|
||||
};
|
||||
} else {
|
||||
addNode = function (el) {
|
||||
body.appendChild(el)
|
||||
};
|
||||
}
|
||||
addNode(togglePassed);
|
||||
addNode(dom.SPAN(null, " "));
|
||||
addNode(toggleFailed);
|
||||
addNode(SimpleTest.report());
|
||||
};
|
||||
|
||||
/**
|
||||
* Tells SimpleTest to don't finish the test when the document is loaded,
|
||||
* useful for asynchronous tests.
|
||||
*
|
||||
* When SimpleTest.waitForExplicitFinish is called,
|
||||
* explicit SimpleTest.finish() is required.
|
||||
**/
|
||||
SimpleTest.waitForExplicitFinish = function () {
|
||||
SimpleTest._stopOnLoad = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Talks to the TestRunner if being ran on a iframe and the parent has a
|
||||
* TestRunner object.
|
||||
**/
|
||||
SimpleTest.talkToRunner = function () {
|
||||
if (typeof(parent) != "undefined" && parent.TestRunner) {
|
||||
parent.TestRunner.testFinished(document);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Finishes the tests. This is automatically called, except when
|
||||
* SimpleTest.waitForExplicitFinish() has been invoked.
|
||||
**/
|
||||
SimpleTest.finish = function () {
|
||||
SimpleTest.showReport();
|
||||
SimpleTest.talkToRunner();
|
||||
};
|
||||
|
||||
|
||||
MochiKit.DOM.addLoadEvent(function() {
|
||||
if (SimpleTest._stopOnLoad) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
});
|
||||
|
||||
// --------------- Test.Builder/Test.More isDeeply() -----------------
|
||||
|
||||
|
||||
SimpleTest.DNE = {dne: 'Does not exist'};
|
||||
SimpleTest.LF = "\r\n";
|
||||
SimpleTest._isRef = function (object) {
|
||||
var type = typeof(object);
|
||||
return type == 'object' || type == 'function';
|
||||
};
|
||||
|
||||
|
||||
SimpleTest._deepCheck = function (e1, e2, stack, seen) {
|
||||
var ok = false;
|
||||
// Either they're both references or both not.
|
||||
var sameRef = !(!SimpleTest._isRef(e1) ^ !SimpleTest._isRef(e2));
|
||||
if (e1 == null && e2 == null) {
|
||||
ok = true;
|
||||
} else if (e1 != null ^ e2 != null) {
|
||||
ok = false;
|
||||
} else if (e1 == SimpleTest.DNE ^ e2 == SimpleTest.DNE) {
|
||||
ok = false;
|
||||
} else if (sameRef && e1 == e2) {
|
||||
// Handles primitives and any variables that reference the same
|
||||
// object, including functions.
|
||||
ok = true;
|
||||
} else if (SimpleTest.isa(e1, 'Array') && SimpleTest.isa(e2, 'Array')) {
|
||||
ok = SimpleTest._eqArray(e1, e2, stack, seen);
|
||||
} else if (typeof e1 == "object" && typeof e2 == "object") {
|
||||
ok = SimpleTest._eqAssoc(e1, e2, stack, seen);
|
||||
} else {
|
||||
// If we get here, they're not the same (function references must
|
||||
// always simply rererence the same function).
|
||||
stack.push({ vals: [e1, e2] });
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
};
|
||||
|
||||
SimpleTest._eqArray = function (a1, a2, stack, seen) {
|
||||
// Return if they're the same object.
|
||||
if (a1 == a2) return true;
|
||||
|
||||
// JavaScript objects have no unique identifiers, so we have to store
|
||||
// references to them all in an array, and then compare the references
|
||||
// directly. It's slow, but probably won't be much of an issue in
|
||||
// practice. Start by making a local copy of the array to as to avoid
|
||||
// confusing a reference seen more than once (such as [a, a]) for a
|
||||
// circular reference.
|
||||
for (var j = 0; j < seen.length; j++) {
|
||||
if (seen[j][0] == a1) {
|
||||
return seen[j][1] == a2;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, we haven't seen a1 before, so store it with reference
|
||||
// to a2.
|
||||
seen.push([ a1, a2 ]);
|
||||
|
||||
var ok = true;
|
||||
// Only examines enumerable attributes. Only works for numeric arrays!
|
||||
// Associative arrays return 0. So call _eqAssoc() for them, instead.
|
||||
var max = a1.length > a2.length ? a1.length : a2.length;
|
||||
if (max == 0) return SimpleTest._eqAssoc(a1, a2, stack, seen);
|
||||
for (var i = 0; i < max; i++) {
|
||||
var e1 = i > a1.length - 1 ? SimpleTest.DNE : a1[i];
|
||||
var e2 = i > a2.length - 1 ? SimpleTest.DNE : a2[i];
|
||||
stack.push({ type: 'Array', idx: i, vals: [e1, e2] });
|
||||
if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
|
||||
stack.pop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
};
|
||||
|
||||
SimpleTest._eqAssoc = function (o1, o2, stack, seen) {
|
||||
// Return if they're the same object.
|
||||
if (o1 == o2) return true;
|
||||
|
||||
// JavaScript objects have no unique identifiers, so we have to store
|
||||
// references to them all in an array, and then compare the references
|
||||
// directly. It's slow, but probably won't be much of an issue in
|
||||
// practice. Start by making a local copy of the array to as to avoid
|
||||
// confusing a reference seen more than once (such as [a, a]) for a
|
||||
// circular reference.
|
||||
seen = seen.slice(0);
|
||||
for (var j = 0; j < seen.length; j++) {
|
||||
if (seen[j][0] == o1) {
|
||||
return seen[j][1] == o2;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, we haven't seen o1 before, so store it with reference
|
||||
// to o2.
|
||||
seen.push([ o1, o2 ]);
|
||||
|
||||
// They should be of the same class.
|
||||
|
||||
var ok = true;
|
||||
// Only examines enumerable attributes.
|
||||
var o1Size = 0; for (var i in o1) o1Size++;
|
||||
var o2Size = 0; for (var i in o2) o2Size++;
|
||||
var bigger = o1Size > o2Size ? o1 : o2;
|
||||
for (var i in bigger) {
|
||||
var e1 = o1[i] == undefined ? SimpleTest.DNE : o1[i];
|
||||
var e2 = o2[i] == undefined ? SimpleTest.DNE : o2[i];
|
||||
stack.push({ type: 'Object', idx: i, vals: [e1, e2] });
|
||||
if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
|
||||
stack.pop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
};
|
||||
|
||||
SimpleTest._formatStack = function (stack) {
|
||||
var variable = '$Foo';
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
var entry = stack[i];
|
||||
var type = entry['type'];
|
||||
var idx = entry['idx'];
|
||||
if (idx != null) {
|
||||
if (/^\d+$/.test(idx)) {
|
||||
// Numeric array index.
|
||||
variable += '[' + idx + ']';
|
||||
} else {
|
||||
// Associative array index.
|
||||
idx = idx.replace("'", "\\'");
|
||||
variable += "['" + idx + "']";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var vals = stack[stack.length-1]['vals'].slice(0, 2);
|
||||
var vars = [
|
||||
variable.replace('$Foo', 'got'),
|
||||
variable.replace('$Foo', 'expected')
|
||||
];
|
||||
|
||||
var out = "Structures begin differing at:" + SimpleTest.LF;
|
||||
for (var i = 0; i < vals.length; i++) {
|
||||
var val = vals[i];
|
||||
if (val == null) {
|
||||
val = 'undefined';
|
||||
} else {
|
||||
val == SimpleTest.DNE ? "Does not exist" : "'" + val + "'";
|
||||
}
|
||||
}
|
||||
|
||||
out += vars[0] + ' = ' + vals[0] + SimpleTest.LF;
|
||||
out += vars[1] + ' = ' + vals[1] + SimpleTest.LF;
|
||||
|
||||
return ' ' + out;
|
||||
};
|
||||
|
||||
|
||||
SimpleTest.isDeeply = function (it, as, name) {
|
||||
var ok;
|
||||
// ^ is the XOR operator.
|
||||
if (SimpleTest._isRef(it) ^ SimpleTest._isRef(as)) {
|
||||
// One's a reference, one isn't.
|
||||
ok = false;
|
||||
} else if (!SimpleTest._isRef(it) && !SimpleTest._isRef(as)) {
|
||||
// Neither is an object.
|
||||
ok = SimpleTest.is(it, as, name);
|
||||
} else {
|
||||
// We have two objects. Do a deep comparison.
|
||||
var stack = [], seen = [];
|
||||
if ( SimpleTest._deepCheck(it, as, stack, seen)) {
|
||||
ok = SimpleTest.ok(true, name);
|
||||
} else {
|
||||
ok = SimpleTest.ok(false, name, SimpleTest._formatStack(stack));
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
};
|
||||
|
||||
SimpleTest.typeOf = function (object) {
|
||||
var c = Object.prototype.toString.apply(object);
|
||||
var name = c.substring(8, c.length - 1);
|
||||
if (name != 'Object') return name;
|
||||
// It may be a non-core class. Try to extract the class name from
|
||||
// the constructor function. This may not work in all implementations.
|
||||
if (/function ([^(\s]+)/.test(Function.toString.call(object.constructor))) {
|
||||
return RegExp.$1;
|
||||
}
|
||||
// No idea. :-(
|
||||
return name;
|
||||
};
|
||||
|
||||
SimpleTest.isa = function (object, clas) {
|
||||
return SimpleTest.typeOf(object) == clas;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Global symbols:
|
||||
var ok = SimpleTest.ok;
|
||||
var is = SimpleTest.is;
|
||||
var isDeeply = SimpleTest.isDeeply;
|
256
frontend/delta/tests/SimpleTest/TestRunner.js
Normal file
256
frontend/delta/tests/SimpleTest/TestRunner.js
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* TestRunner: A test runner for SimpleTest
|
||||
* TODO:
|
||||
*
|
||||
* * Avoid moving iframes: That causes reloads on mozilla and opera.
|
||||
*
|
||||
*
|
||||
**/
|
||||
var TestRunner = {};
|
||||
TestRunner.logEnabled = false;
|
||||
TestRunner._iframes = {};
|
||||
TestRunner._iframeDocuments = {};
|
||||
TestRunner._iframeRows = {};
|
||||
TestRunner._currentTest = 0;
|
||||
TestRunner._urls = [];
|
||||
TestRunner._testsDiv = DIV();
|
||||
TestRunner._progressDiv = DIV();
|
||||
TestRunner._summaryDiv = DIV(null,
|
||||
H1(null, "Tests Summary"),
|
||||
TABLE(null,
|
||||
THEAD(null,
|
||||
TR(null,
|
||||
TH(null, "Test"),
|
||||
TH(null, "Passed"),
|
||||
TH(null, "Failed")
|
||||
)
|
||||
),
|
||||
TFOOT(/*null, TR(null, TH(null, "-"), TH(null, "--"), TH(null, "---"))*/),
|
||||
TBODY()
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* This function is called after generating the summary.
|
||||
**/
|
||||
TestRunner.onComplete = null;
|
||||
|
||||
/**
|
||||
* If logEnabled is true, this is the logger that will be used.
|
||||
**/
|
||||
TestRunner.logger = MochiKit.Logging.logger;
|
||||
|
||||
/**
|
||||
* Toggle element visibility
|
||||
**/
|
||||
TestRunner._toggle = function(el) {
|
||||
if (el.className == "noshow") {
|
||||
el.className = "";
|
||||
el.style.cssText = "";
|
||||
} else {
|
||||
el.className = "noshow";
|
||||
el.style.cssText = "width:0px; height:0px; border:0px;";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates the iframe that contains a test
|
||||
**/
|
||||
TestRunner._makeIframe = function (url) {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.src = url;
|
||||
iframe.name = url;
|
||||
iframe.width = "500";
|
||||
var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
|
||||
var tr = TR(null, TD({'colspan': '3'}, iframe));
|
||||
iframe._row = tr;
|
||||
tbody.appendChild(tr);
|
||||
return iframe;
|
||||
};
|
||||
|
||||
/**
|
||||
* TestRunner entry point.
|
||||
*
|
||||
* The arguments are the URLs of the test to be ran.
|
||||
*
|
||||
**/
|
||||
TestRunner.runTests = function (/*url...*/) {
|
||||
if (TestRunner.logEnabled)
|
||||
TestRunner.logger.log("SimpleTest START");
|
||||
|
||||
var body = document.getElementsByTagName("body")[0];
|
||||
appendChildNodes(body,
|
||||
TestRunner._testsDiv,
|
||||
TestRunner._progressDiv,
|
||||
TestRunner._summaryDiv
|
||||
);
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
TestRunner._urls.push(arguments[i]);
|
||||
}
|
||||
|
||||
TestRunner.runNextTest();
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the next test. If no test remains, calls makeSummary
|
||||
**/
|
||||
TestRunner.runNextTest = function() {
|
||||
if (TestRunner._currentTest < TestRunner._urls.length) {
|
||||
var url = TestRunner._urls[TestRunner._currentTest];
|
||||
var progress = SPAN(null,
|
||||
"Running ", A({href:url}, url), "..."
|
||||
);
|
||||
|
||||
if (TestRunner.logEnabled)
|
||||
TestRunner.logger.log(scrapeText(progress));
|
||||
|
||||
TestRunner._progressDiv.appendChild(progress);
|
||||
TestRunner._iframes[url] = TestRunner._makeIframe(url);
|
||||
} else {
|
||||
TestRunner.makeSummary();
|
||||
if (TestRunner.onComplete) {
|
||||
TestRunner.onComplete();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This stub is called by SimpleTest when a test is finished.
|
||||
**/
|
||||
TestRunner.testFinished = function (doc) {
|
||||
appendChildNodes(TestRunner._progressDiv, SPAN(null, "Done"), BR());
|
||||
var finishedURL = TestRunner._urls[TestRunner._currentTest];
|
||||
|
||||
if (TestRunner.logEnabled)
|
||||
TestRunner.logger.debug("SimpleTest finished " + finishedURL);
|
||||
|
||||
TestRunner._iframeDocuments[finishedURL] = doc;
|
||||
// TestRunner._iframes[finishedURL].style.display = "none";
|
||||
if (finishedURL != null) {
|
||||
TestRunner._toggle(TestRunner._iframes[finishedURL]);
|
||||
TestRunner._currentTest++;
|
||||
TestRunner.runNextTest();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Display the summary in the browser
|
||||
**/
|
||||
/*
|
||||
TestRunner.makeSummary = function() {
|
||||
if (TestRunner.logEnabled)
|
||||
TestRunner.logger.log("SimpleTest FINISHED");
|
||||
var rows = [];
|
||||
for (var url in TestRunner._iframeDocuments) {
|
||||
var doc = TestRunner._iframeDocuments[url];
|
||||
var nOK = withDocument(doc,
|
||||
partial(getElementsByTagAndClassName, 'div', 'test_ok')
|
||||
).length;
|
||||
var nNotOK = withDocument(doc,
|
||||
partial(getElementsByTagAndClassName, 'div', 'test_not_ok')
|
||||
).length;
|
||||
var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]);
|
||||
var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])";
|
||||
var row = TR(
|
||||
{'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}},
|
||||
TD(null, url),
|
||||
TD(null, nOK),
|
||||
TD(null, nNotOK)
|
||||
);
|
||||
row.onclick = toggle;
|
||||
var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
|
||||
tbody.insertBefore(row, TestRunner._iframes[url]._row)
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
TestRunner.makeSummary = function() {
|
||||
var base = MochiKit.Base;
|
||||
var dom = MochiKit.DOM;
|
||||
var iter = MochiKit.Iter;
|
||||
var total_Ok, total_not_Ok;
|
||||
|
||||
total_Ok = 0;
|
||||
total_not_Ok = 0;
|
||||
|
||||
if (TestRunner.logEnabled)
|
||||
TestRunner.logger.log("SimpleTest FINISHED");
|
||||
var rows = [];
|
||||
for (var url in TestRunner._iframeDocuments) {
|
||||
var doc = TestRunner._iframeDocuments[url];
|
||||
var nOK = withDocument(doc,
|
||||
partial(getElementsByTagAndClassName, 'div', 'test_ok')
|
||||
).length;
|
||||
var nNotOK = withDocument(doc,
|
||||
partial(getElementsByTagAndClassName, 'div', 'test_not_ok')
|
||||
).length;
|
||||
var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]);
|
||||
var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])";
|
||||
var row = TR(
|
||||
{'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}},
|
||||
TD(null, url),
|
||||
TD(null, nOK),
|
||||
TD(null, nNotOK)
|
||||
);
|
||||
row.onclick = toggle;
|
||||
var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
|
||||
tbody.insertBefore(row, TestRunner._iframes[url]._row);
|
||||
|
||||
total_Ok += nOK;
|
||||
total_not_Ok += nNotOK;
|
||||
}
|
||||
|
||||
{
|
||||
var tfoot = TestRunner._summaryDiv.getElementsByTagName("tfoot")[0];
|
||||
tfoot.appendChild(TR(null,
|
||||
TH(null, ""),
|
||||
TH({'style':"color:green;"}, total_Ok),
|
||||
TH({'style':"color:" + ((total_not_Ok == 0) ? 'black' : 'red') + ";"}, total_not_Ok)
|
||||
));
|
||||
}
|
||||
|
||||
var testRunnerResults;
|
||||
var i, c;
|
||||
|
||||
testRunnerResults = dom.DIV({'style': 'display:none; visibility:hidden;'}, null);
|
||||
|
||||
c = total_Ok;
|
||||
for (i=0; i<c; i++) {
|
||||
dom.appendChildNodes(testRunnerResults, dom.DIV({'class': 'test_ok'}, "ok"));
|
||||
}
|
||||
|
||||
c = total_not_Ok;
|
||||
for (i=0; i<c; i++) {
|
||||
dom.appendChildNodes(testRunnerResults, dom.DIV({'class': 'test_not_ok'}, "fail"));
|
||||
}
|
||||
|
||||
document.getElementsByTagName("body")[0].appendChild(testRunnerResults);
|
||||
|
||||
if (typeof(parent) != "undefined" && parent.TestRunner) {
|
||||
parent.TestRunner.testFinished(document);
|
||||
}
|
||||
};
|
51
frontend/delta/tests/SimpleTest/test.css
Normal file
51
frontend/delta/tests/SimpleTest/test.css
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
.test_ok {
|
||||
color: green;
|
||||
display: none;
|
||||
}
|
||||
.test_not_ok {
|
||||
color: red;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.test_ok, .test_not_ok {
|
||||
border-bottom-width: 2px;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: black;
|
||||
}
|
||||
|
||||
.all_pass {
|
||||
background-color: lime;
|
||||
}
|
||||
|
||||
.some_fail {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.tests_report {
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
width: 20em;
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
<!--
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Clipperz.PM.DataModel.DirectLogin - test</title>
|
||||
<script>Clipperz = {}</script>
|
||||
<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../../../../js/React/react-with-addons-0.10.0.js"></script>
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css">
|
||||
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES_2.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Toll.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Test.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.Field.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLogin.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginInput.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginBinding.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Legacy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.RecordIndex.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Preferences.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/OneTimePassword.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.AccountInfo.js'></script>
|
||||
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script>
|
||||
<script>
|
||||
Clipperz_IEisBroken = false;
|
||||
</script>
|
||||
|
||||
<!--[if IE]><script>
|
||||
Clipperz_IEisBroken = true;
|
||||
Clipperz_normalizedNewLine = '\x0d\x0a';
|
||||
</script><![endif]-->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script>
|
||||
Clipperz.PM.Strings.Languages.setSelectedLanguage('en-us');
|
||||
</script>
|
||||
<script type="text/javascript" src="User.data.js"></script>
|
||||
<script type="text/javascript" src="User.data.old.js"></script>
|
||||
<script type="text/javascript" src="DirectLogin.test.js"></script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,190 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose();
|
||||
|
||||
var tests = {
|
||||
|
||||
/*
|
||||
user = new Clipperz.PM.DataModel.User({username:'test', getPassphraseFunction:function () { return 'test';}});
|
||||
...
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['test_test_offline_copy_data']);
|
||||
deferredResult.addMethod(user, 'getRecord', '8280842f41162b673335b63860637e8472e8bbff0efa2bc78b0dbc5e09712e13');
|
||||
|
||||
|
||||
user = new Clipperz.PM.DataModel.User({username:'joe', getPassphraseFunction:function () { return 'clipperz';}});
|
||||
...
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['joe_clipperz_offline_copy_data']);
|
||||
deferredResult.addMethod(user, 'getRecord', '5cdac63b317f3942da38f3a3de3b7f0e5d6678200951c6216230295550f63fb4'); // WEB PASSWORD (0)
|
||||
deferredResult.addMethod(user, 'getRecord', '36ec1a41118813ced3553534fa2607d781cba687768db305beed368a8e06e113'); // DIGG (1)
|
||||
deferredResult.addMethod(user, 'getRecord', 'c0ce9130ca365bb02418d4305ea1d29e49c3f0e96d44b9d3cb6b4b6843d25065'); // SAP (2)
|
||||
deferredResult.addMethod(user, 'getRecord', 'd5f700b9c3367c39551ea49e00a9ab20dae09dd79d46047b983fc7c4bfaa050d'); // YAHOO (4)
|
||||
DirectLogin references
|
||||
- dba0db679802f0e6aa6d0b7a6aaf42350aabc5f057409edd99a268a92ebb6496 // Yahoo! Mail
|
||||
- aa18149164302d5dbe7e2d3724565b9550e00887b49978559783b2e38c625584 // (Yahoo! Groups)
|
||||
- 6f7bbc4e42ea462b5246e6f51c3f86056bec50601ce2de6067c8c1d26f21c07f // (Flickr)
|
||||
- a7b32e72502804bf2946a2a8856139cbbb759c5777e6b3e673db1fdf7e3bd06e // (My Yahoo!)
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'editDirectLoginLabel_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var proxy;
|
||||
var user;
|
||||
|
||||
proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false});
|
||||
user = new Clipperz.PM.DataModel.User({username:'joe', getPassphraseFunction:function () { return 'clipperz';}});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("editDirectLoginLabel_test", someTestArgs);
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['joe_clipperz_offline_copy_data']);
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.addMethod(user, 'getRecord', 'd5f700b9c3367c39551ea49e00a9ab20dae09dd79d46047b983fc7c4bfaa050d'); // YAHOO (4)
|
||||
deferredResult.addMethodcaller('directLogins');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('dba0db679802f0e6aa6d0b7a6aaf42350aabc5f057409edd99a268a92ebb6496'));
|
||||
deferredResult.addCallback(function (aDirectLogin) {
|
||||
var innerDeferredResult;
|
||||
var updatedLabel;
|
||||
|
||||
updatedLabel = "updated Yahoo! Mail label";
|
||||
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("editDirectLoginLabel_test <inner>", someTestArgs);
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'label');
|
||||
innerDeferredResult.addTest("Yahoo! Mail", "The label of the selected direct login is correct.");
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'setLabel', updatedLabel);
|
||||
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'label');
|
||||
innerDeferredResult.addTest(updatedLabel, "The DirectLogin returns the correct label even before committing data.");
|
||||
|
||||
innerDeferredResult.addMethod(user, 'hasPendingChanges');
|
||||
innerDeferredResult.addTest(true, "When changing the label of a DirectLogin, the user should report pending changes.");
|
||||
|
||||
//innerDeferredResult.addCallback(function () { console.log("+_+_+_+_+_+_+_+_+_+_+_+ >>>")});
|
||||
innerDeferredResult.addMethod(user, 'saveChanges');
|
||||
//innerDeferredResult.addCallback(function () { console.log("+_+_+_+_+_+_+_+_+_+_+_+ <<<")});
|
||||
innerDeferredResult.addMethod(user, 'hasPendingChanges');
|
||||
innerDeferredResult.addTest(false, "After saving changes there should be no pending changes left.");
|
||||
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'label');
|
||||
innerDeferredResult.addTest(updatedLabel, "The DirectLogin returns the correct label even after committing data.");
|
||||
|
||||
innerDeferredResult.callback();
|
||||
|
||||
return innerDeferredResult;
|
||||
})
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'editDirectLoginLabel_thanResetItToThePreviousValue_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var proxy;
|
||||
var user;
|
||||
|
||||
proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false});
|
||||
user = new Clipperz.PM.DataModel.User({username:'joe', getPassphraseFunction:function () { return 'clipperz';}});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("editDirectLoginLabel_thanResetItToThePreviousValue_test", someTestArgs);
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['joe_clipperz_offline_copy_data']);
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.addMethod(user, 'getRecord', 'd5f700b9c3367c39551ea49e00a9ab20dae09dd79d46047b983fc7c4bfaa050d'); // YAHOO (4)
|
||||
deferredResult.addMethodcaller('directLogins');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('dba0db679802f0e6aa6d0b7a6aaf42350aabc5f057409edd99a268a92ebb6496'));
|
||||
deferredResult.addCallback(function (aDirectLogin) {
|
||||
var innerDeferredResult;
|
||||
var originalLabel;
|
||||
var updatedLabel;
|
||||
|
||||
originalLabel = "Yahoo! Mail";
|
||||
updatedLabel = "updated Yahoo! Mail label";
|
||||
|
||||
innerDeferredResult = new Clipperz.Async.Deferred("editDirectLoginLabel_thanResetItToThePreviousValue_test <inner>", someTestArgs);
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'label');
|
||||
innerDeferredResult.addTest(originalLabel, "The label of the selected direct login is correct.");
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'setLabel', updatedLabel);
|
||||
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'label');
|
||||
innerDeferredResult.addTest(updatedLabel, "The DirectLogin returns the correct label even before committing data.");
|
||||
|
||||
innerDeferredResult.addMethod(user, 'hasPendingChanges');
|
||||
innerDeferredResult.addTest(true, "When changing the label of a DirectLogin, the user should report pending changes [2].");
|
||||
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'setLabel', originalLabel);
|
||||
|
||||
innerDeferredResult.addMethod(aDirectLogin, 'hasPendingChanges');
|
||||
innerDeferredResult.addTest(false, "Restoring the original label, the directLogin should report no pending changes.");
|
||||
|
||||
innerDeferredResult.addMethod(aDirectLogin.record(), 'hasPendingChanges');
|
||||
innerDeferredResult.addTest(false, "Restoring the original label, the record should report no pending changes.");
|
||||
|
||||
innerDeferredResult.addMethod(user, 'hasPendingChanges');
|
||||
innerDeferredResult.addTest(false, "Restoring the original label, the user should report no pending changes.");
|
||||
|
||||
innerDeferredResult.callback();
|
||||
|
||||
return innerDeferredResult;
|
||||
})
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
'bindingValues_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var proxy;
|
||||
var user;
|
||||
|
||||
proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false});
|
||||
user = new Clipperz.PM.DataModel.User({username:'joe', getPassphraseFunction:function () { return 'clipperz';}});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("DirectLogin.bindingValues_test", someTestArgs);
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['joe_clipperz_offline_copy_data']);
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.addMethod(user, 'getRecord', 'd5f700b9c3367c39551ea49e00a9ab20dae09dd79d46047b983fc7c4bfaa050d'); // YAHOO (4)
|
||||
deferredResult.addMethodcaller('directLogins');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('dba0db679802f0e6aa6d0b7a6aaf42350aabc5f057409edd99a268a92ebb6496'));
|
||||
deferredResult.addMethodcaller('bindingValues');
|
||||
deferredResult.addCallback(function (someBindingValues) {
|
||||
SimpleTest.is(MochiKit.Base.keys(someBindingValues).length, 2, "there should be 2 bindings for this direct login");
|
||||
SimpleTest.is(someBindingValues['login'], 'joe.clipperz', "the login field should be filled with 'joe.clipperz'");
|
||||
SimpleTest.is(someBindingValues['passwd'], 'enfvDG1RxAsl', "the passwd field should be filled with 'enfvDG1RxAsl'");
|
||||
})
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
'syntaxFix': MochiKit.Base.noop
|
||||
};
|
||||
|
||||
//#############################################################################
|
||||
|
||||
SimpleTest.runDeferredTests("Clipperz.PM.DataModel.DirectLogin", tests, {trace:false});
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
directLoginConfigurations = {
|
||||
'Yahoo! Mail': '{\n "page": {\n "title": "Yahoo! Mail"\n },\n "form": {\n "attributes": {\n "action": "https://login.yahoo.com/config/login?",\n "method": "post"\n },\n "inputs": [\n {\n "type": "hidden",\n "name": ".tries",\n "value": "1"\n },\n {\n "type": "hidden",\n "name": ".src",\n "value": "ym"\n },\n {\n "type": "hidden",\n "name": ".md5",\n "value": ""\n },\n {\n "type": "hidden",\n "name": ".hash",\n "value": ""\n },\n {\n "type": "hidden",\n "name": ".js",\n "value": ""\n },\n {\n "type": "hidden",\n "name": ".last",\n "value": ""\n },\n {\n "type": "hidden",\n "name": "promo",\n "value": ""\n },\n {\n "type": "hidden",\n "name": ".intl",\n "value": "us"\n },\n {\n "type": "hidden",\n "name": ".bypass",\n "value": ""\n },\n {\n "type": "hidden",\n "name": ".partner",\n "value": ""\n },\n {\n "type": "hidden",\n "name": ".u",\n "value": "5gp62cl2vg3ov"\n },\n {\n "type": "hidden",\n "name": ".v",\n "value": "0"\n },\n {\n "type": "hidden",\n "name": ".challenge",\n "value": "iBEY0IK6k3t9Uals32mrTos8s48p"\n },\n {\n "type": "hidden",\n "name": ".yplus",\n "value": ""\n },\n {\n "type": "hidden",\n "name": ".emailCode",\n "value": ""\n },\n {\n "type": "hidden",\n "name": "pkg",\n "value": ""\n },\n {\n "type": "hidden",\n "name": "stepid",\n "value": ""\n },\n {\n "type": "hidden",\n "name": ".ev",\n "value": ""\n },\n {\n "type": "hidden",\n "name": "hasMsgr",\n "value": "0"\n },\n {\n "type": "hidden",\n "name": ".chkP",\n "value": "Y"\n },\n {\n "type": "hidden",\n "name": ".done",\n "value": "http://mail.yahoo.com"\n },\n {\n "type": "hidden",\n "name": ".pd",\n "value": "ym_ver%3d0%26c="\n },\n {\n "type": "text",\n "name": "login",\n "value": ""\n },\n {\n "type": "password",\n "name": "passwd",\n "value": ""\n },\n {\n "type": "checkbox",\n "name": ".persistent",\n "value": "y"\n },\n {\n "type": "submit",\n "name": ".save",\n "value": "Sign In"\n }\n ]\n },\n "version": "0.2"\n}',
|
||||
'Parallels': '{"page": {"title": "Parallels Account"},\n"form": {"attributes": {"action": "https://www.parallels.com/account/",\n"method": "post"},\n"inputs": [{"type": "text",\n"name": "Email",\n"value": ""},\n{"type": "password",\n"name": "Password",\n"value": ""}]},\n"version": "0.2.3"}',
|
||||
__syntaxFix__: "syntax fix"
|
||||
};
|
@ -0,0 +1,60 @@
|
||||
<!--
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Clipperz.PM.DataModel.EncryptedRemoteObject - test</title>
|
||||
<script>Clipperz = {}</script>
|
||||
<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css">
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES_2.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script>
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script type="text/javascript" src="EncryptedRemoteObject.test.js"></script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,220 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose();
|
||||
|
||||
var tests = {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'simple_tests': function(someTestArgs) {
|
||||
var deferredResult;
|
||||
var encryptedRemoteObject;
|
||||
|
||||
var key;
|
||||
var version;
|
||||
var rawData;
|
||||
|
||||
key = "just a random key";
|
||||
version = Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
|
||||
rawData = "just a random text to encrypt";
|
||||
|
||||
encryptedRemoteObject = new Clipperz.PM.DataModel.EncryptedRemoteObject({
|
||||
'retrieveKeyFunction': MochiKit.Base.noop,
|
||||
'retrieveRemoteDataFunction': function () { return "--"},
|
||||
'encryptedDataKeypath': '--',
|
||||
'encryptedVersionKeypath': '--'
|
||||
});
|
||||
SimpleTest.ok(encryptedRemoteObject != null, "create an encryptedRemoteObject");
|
||||
|
||||
deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.test - simple_tests", [
|
||||
MochiKit.Base.method(encryptedRemoteObject, 'getRemoteData'),
|
||||
function(aResult) {
|
||||
SimpleTest.is(aResult, "--", "setting and getting serverData works");
|
||||
}
|
||||
], someTestArgs);
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'decrypt_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var encryptedRemoteObject;
|
||||
var key;
|
||||
var version;
|
||||
var rawData;
|
||||
|
||||
key = "just a random key";
|
||||
version = Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
|
||||
rawData = "just a random text to encrypt";
|
||||
|
||||
encryptedRemoteObject = new Clipperz.PM.DataModel.EncryptedRemoteObject({
|
||||
'retrieveKeyFunction': MochiKit.Base.partial(MochiKit.Async.succeed, key),
|
||||
'retrieveRemoteDataFunction': MochiKit.Base.partial(Clipperz.Async.callbacks, "EncryptedRemoteObject.test - decrypt_test <encrypt data>", [
|
||||
MochiKit.Base.partial(Clipperz.PM.Crypto.deferredEncrypt, {key:key, value:rawData, version:version}),
|
||||
function (someEncryptedData) {
|
||||
return {
|
||||
'data': someEncryptedData,
|
||||
'version': version
|
||||
}
|
||||
}
|
||||
], someTestArgs)//,
|
||||
// 'encryptedDataKeypath': 'data',
|
||||
// 'encryptedVersionKeypath': 'version'
|
||||
});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("decrypt_test", someTestArgs);
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'getDecryptedData');
|
||||
deferredResult.addCallback(function (aResult) {
|
||||
SimpleTest.is(aResult, rawData, "encrypt and decrypt works");
|
||||
})
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'getValue_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var encryptedRemoteObject;
|
||||
var key;
|
||||
var version;
|
||||
var rawData;
|
||||
|
||||
key = "just a random key";
|
||||
version = Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
|
||||
rawData = {
|
||||
key1: 'value1',
|
||||
key2: 'value2'
|
||||
};
|
||||
|
||||
encryptedRemoteObject = new Clipperz.PM.DataModel.EncryptedRemoteObject({
|
||||
'reference': "testReference",
|
||||
'retrieveKeyFunction': MochiKit.Base.partial(MochiKit.Async.succeed, key),
|
||||
'retrieveRemoteDataFunction': MochiKit.Base.partial(Clipperz.Async.callbacks, "EncryptedRemoteObject.test - decrypt_test <encrypt data>", [
|
||||
MochiKit.Base.partial(Clipperz.PM.Crypto.deferredEncrypt, {key:key, value:rawData, version:version}),
|
||||
function (someEncryptedData) {
|
||||
return {
|
||||
'data': someEncryptedData,
|
||||
'version': version
|
||||
}
|
||||
}
|
||||
], someTestArgs)//,
|
||||
// 'encryptedDataKeypath': 'data',
|
||||
// 'encryptedVersionKeypath': 'version'
|
||||
});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("decrypt_test", someTestArgs);
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'getValue', 'key1');
|
||||
deferredResult.addTest('value1', "getting 'key1' works");
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'hasAnyCleanTextData');
|
||||
deferredResult.addTest(true, "After accessing a value, hasAnyCleanTextData returns false");
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'hasPendingChanges');
|
||||
deferredResult.addTest(false, "if nothing has changed, the object should return not pending changes");
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'deleteAllCleanTextData');
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'hasAnyCleanTextData');
|
||||
deferredResult.addTest(false, "After deleting all cleanTextData, hasAnyCleanTextData returns false");
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'getValue', 'key1');
|
||||
deferredResult.addTest('value1', "getting 'key1' (also after a lock) works correctly");
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'setValue', 'key1', 'new value1');
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'getValue', 'key1');
|
||||
deferredResult.addTest('new value1', "after setting a new value, it is correctly returned");
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'values');
|
||||
deferredResult.addCallback(function (someValues) {
|
||||
SimpleTest.is(someValues['key1'], 'new value1', "the value got straight from the objectStore is correct");
|
||||
});
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'hasPendingChanges');
|
||||
deferredResult.addTest(true, "once a value has been changed, the object should return that there're some pending changes");
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'revertChanges');
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'hasPendingChanges');
|
||||
deferredResult.addTest(false, "reverting the changes should return the object to its initial state, without any peding changes");
|
||||
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'getValue', 'key1');
|
||||
deferredResult.addTest('value1', "also the value of the changed item has been restored");
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'encrypt_with_new_object_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var encryptedRemoteObject;
|
||||
var key;
|
||||
// var version;
|
||||
// var rawData;
|
||||
|
||||
key = "just a random key";
|
||||
// version = Clipperz.PM.Crypto.encryptingFunctions.currentVersion;
|
||||
// rawData = "just a random text to encrypt";
|
||||
|
||||
encryptedRemoteObject = new Clipperz.PM.DataModel.EncryptedRemoteObject({
|
||||
'retrieveRemoteDataFunction': MochiKit.Base.noop
|
||||
});
|
||||
|
||||
encryptedRemoteObject.setValue('key1', "value1");
|
||||
encryptedRemoteObject.setValue('key2', "value2");
|
||||
encryptedRemoteObject.setValue('key3', "value3");
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("encrypt_with_new_object_test", someTestArgs);
|
||||
deferredResult.addMethod(encryptedRemoteObject, 'prepareRemoteDataWithKey', key);
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('data'));
|
||||
deferredResult.collectResults({
|
||||
'key': MochiKit.Base.partial(MochiKit.Async.succeed, key),
|
||||
'value': MochiKit.Async.succeed,
|
||||
'version': MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Crypto.encryptingFunctions.currentVersion)
|
||||
});
|
||||
deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt);
|
||||
deferredResult.addCallback(function (aResult) {
|
||||
SimpleTest.is(aResult['key1'], "value1", "encrypt and decrypt works for first element");
|
||||
SimpleTest.is(aResult['key2'], "value2", "encrypt and decrypt works for second element");
|
||||
SimpleTest.is(aResult['key3'], "value3", "encrypt and decrypt works for third element");
|
||||
})
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
'syntaxFix': MochiKit.Base.noop
|
||||
};
|
||||
|
||||
//#############################################################################
|
||||
|
||||
SimpleTest.runDeferredTests("Clipperz.PM.DataModel.EncryptedRemoteObject", tests, {trace:false});
|
@ -0,0 +1,99 @@
|
||||
<!--
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Clipperz.PM.DataModel.User - test</title>
|
||||
<script>Clipperz = {}</script>
|
||||
<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css">
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Toll.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Test.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/UI/DirectLoginController.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.Field.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLogin.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginInput.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginBinding.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginFormValue.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Legacy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.RecordIndex.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Preferences.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/OneTimePassword.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.AccountInfo.js'></script>
|
||||
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script>
|
||||
<script>
|
||||
Clipperz_IEisBroken = false;
|
||||
</script>
|
||||
|
||||
<!--[if IE]><script>
|
||||
Clipperz_IEisBroken = true;
|
||||
Clipperz_normalizedNewLine = '\x0d\x0a';
|
||||
</script><![endif]-->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script>
|
||||
Clipperz.PM.Strings.Languages.setSelectedLanguage('en-us');
|
||||
</script>
|
||||
<script type="text/javascript" src="User.data.js"></script>
|
||||
<script type="text/javascript" src="OneTimePassword.test.js"></script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose();
|
||||
|
||||
var tests = {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'isValidOneTimePasswordValue_test': function (someTestArgs) {
|
||||
var otp;
|
||||
var notOTP;
|
||||
|
||||
otp = 'yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg';
|
||||
SimpleTest.is(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue(otp), true, "isValidOneTimePasswordValue [expect true] - test 1");
|
||||
|
||||
notOTP = 'trustno1';
|
||||
SimpleTest.is(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue(notOTP), false, "isValidOneTimePasswordValue [expect false] - test 1");
|
||||
|
||||
return MochiKit.Async.succeed('done');
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'loginUsingOtp_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var proxy;
|
||||
var user, user2;
|
||||
var username;
|
||||
var passphrase;
|
||||
|
||||
username = "test";
|
||||
passphrase = "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg"; // OTP
|
||||
|
||||
proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false});
|
||||
user = new Clipperz.PM.DataModel.User({username:username, getPassphraseFunction:function () { return passphrase;}});
|
||||
user2 = new Clipperz.PM.DataModel.User({username:username, getPassphraseFunction:function () { return passphrase;}});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("loginUsingOtp_test", someTestArgs);
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['test_test_with_otps']);
|
||||
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.addMethod(user, 'getRecords');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('length'));
|
||||
deferredResult.addTest(1, "This account has one single card");
|
||||
|
||||
deferredResult.addMethod(user, 'getOneTimePasswords');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('length'));
|
||||
deferredResult.addTest(1, "This account has one OTP");
|
||||
|
||||
deferredResult.addMethod(user, 'getOneTimePasswords');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter(0));
|
||||
deferredResult.addCallback(MochiKit.Base.methodcaller('status'));
|
||||
deferredResult.addTest('USED', "The available OTP has been unsed to login, and should be marked accordingly");
|
||||
|
||||
deferredResult.addMethod(user2, 'login');
|
||||
deferredResult.shouldFail("trying to login using the same OTP twice");
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'changePassphraseAndLoginUsingOtp_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var proxy;
|
||||
var user;
|
||||
var user2;
|
||||
var user3;
|
||||
var otp;
|
||||
|
||||
otp = "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg"; // OTP
|
||||
|
||||
newPassphrase = 'tset';
|
||||
proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false});
|
||||
user = new Clipperz.PM.DataModel.User({username:'test', getPassphraseFunction:function () { return 'test';}});
|
||||
user2 = new Clipperz.PM.DataModel.User({username:'test', getPassphraseFunction:function () { return otp;}});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("changePassphraseAndLoginUsingOtp_test", someTestArgs);
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['test_test_with_otps']);
|
||||
|
||||
deferredResult.addMethod(user, 'login');
|
||||
|
||||
deferredResult.addMethod(user, 'getRecords');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('length'));
|
||||
deferredResult.addTest(1, "This account has only a single card");
|
||||
|
||||
deferredResult.addMethod(user, 'changePassphrase', newPassphrase);
|
||||
deferredResult.addMethod(user, 'logout');
|
||||
|
||||
deferredResult.addMethod(user2, 'login');
|
||||
deferredResult.addMethod(user2, 'getRecords');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('length'));
|
||||
deferredResult.addTest(1, "This account has oly a single card");
|
||||
deferredResult.addMethod(user2, 'logout');
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'loginUsingOtpAndWrongUsername_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var proxy;
|
||||
var user, user2;
|
||||
var username;
|
||||
var wrongUsername;
|
||||
var passphrase;
|
||||
|
||||
username = "test";
|
||||
wrongUsername = "tset";
|
||||
passphrase = "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg"; // OTP
|
||||
|
||||
proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false});
|
||||
user = new Clipperz.PM.DataModel.User({username:wrongUsername, getPassphraseFunction:function () { return passphrase;}});
|
||||
user2 = new Clipperz.PM.DataModel.User({username:username, getPassphraseFunction:function () { return passphrase;}});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("loginUsingOtpAndWrongUsername_test", someTestArgs);
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['test_test_with_otps']);
|
||||
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.shouldFail("login in using the wrong username with the OTP should fail");
|
||||
|
||||
deferredResult.addMethod(user2, 'login');
|
||||
deferredResult.shouldFail("trying to reuse the same OTP should fail, even if now it is used with the correct username");
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
'loginUserWithAPassphraseLookingExactlyLikeAnOTP_test': function (someTestArgs) {
|
||||
var deferredResult;
|
||||
var proxy;
|
||||
var user;
|
||||
var username;
|
||||
var passphrase;
|
||||
|
||||
username = "otp_user";
|
||||
passphrase = "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg"; // passphrase
|
||||
|
||||
proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false});
|
||||
user = new Clipperz.PM.DataModel.User({username:username, getPassphraseFunction:function () { return passphrase;}});
|
||||
|
||||
deferredResult = new Clipperz.Async.Deferred("loginUserWithAPassphraseLookingExactlyLikeAnOTP_test", someTestArgs);
|
||||
deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['otp_user_test']);
|
||||
|
||||
deferredResult.addMethod(user, 'login');
|
||||
deferredResult.addMethod(user, 'getRecords');
|
||||
deferredResult.addCallback(MochiKit.Base.itemgetter('length'));
|
||||
deferredResult.addTest(1, "This account has one single card");
|
||||
|
||||
deferredResult.callback();
|
||||
|
||||
return deferredResult;
|
||||
},
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------
|
||||
'syntaxFix': MochiKit.Base.noop
|
||||
};
|
||||
|
||||
|
||||
|
||||
//#############################################################################
|
||||
|
||||
SimpleTest.runDeferredTests("Clipperz.PM.DataModel.OneTimePassword", tests, {trace:false});
|
94
frontend/delta/tests/tests/Clipperz/PM/DataModel/Record.html
Normal file
94
frontend/delta/tests/tests/Clipperz/PM/DataModel/Record.html
Normal file
@ -0,0 +1,94 @@
|
||||
<!--
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Clipperz.PM.DataModel.Record - test</title>
|
||||
<script>Clipperz = {}</script>
|
||||
<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css">
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Set.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES_2.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Toll.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Test.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.Field.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLogin.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginInput.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginBinding.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginFormValue.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Legacy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.RecordIndex.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Preferences.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/OneTimePassword.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.AccountInfo.js'></script>
|
||||
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script>
|
||||
Clipperz.PM.Strings.Languages.setSelectedLanguage('en-us');
|
||||
</script>
|
||||
<script type="text/javascript" src="DirectLoginConfigurations.data.js"></script>
|
||||
<script type="text/javascript" src="User.data.js"></script>
|
||||
<script type="text/javascript" src="Record.test.js"></script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
1513
frontend/delta/tests/tests/Clipperz/PM/DataModel/Record.test.js
Normal file
1513
frontend/delta/tests/tests/Clipperz/PM/DataModel/Record.test.js
Normal file
File diff suppressed because it is too large
Load Diff
2068
frontend/delta/tests/tests/Clipperz/PM/DataModel/User.data.js
Normal file
2068
frontend/delta/tests/tests/Clipperz/PM/DataModel/User.data.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
102
frontend/delta/tests/tests/Clipperz/PM/DataModel/User.html
Normal file
102
frontend/delta/tests/tests/Clipperz/PM/DataModel/User.html
Normal file
@ -0,0 +1,102 @@
|
||||
<!--
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Clipperz.PM.DataModel.User - test</title>
|
||||
<script>Clipperz = {}</script>
|
||||
<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css">
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES_2.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Toll.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Test.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script>
|
||||
|
||||
<!-- script type='text/javascript' src='../../../../../js/Clipperz/PM/UI/Common/Controllers/DirectLoginRunner.js'></script -->
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/UI/DirectLoginController.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.Field.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLogin.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginInput.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginBinding.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginFormValue.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Legacy.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.RecordIndex.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Preferences.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/OneTimePassword.js'></script>
|
||||
<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.AccountInfo.js'></script>
|
||||
|
||||
<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script>
|
||||
<script>
|
||||
Clipperz_IEisBroken = false;
|
||||
</script>
|
||||
|
||||
<!--[if IE]><script>
|
||||
Clipperz_IEisBroken = true;
|
||||
Clipperz_normalizedNewLine = '\x0d\x0a';
|
||||
</script><![endif]-->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<pre id="test">
|
||||
<script>
|
||||
Clipperz.PM.Strings.Languages.setSelectedLanguage('en-us');
|
||||
</script>
|
||||
<script type="text/javascript" src="User.data.js"></script>
|
||||
<script type="text/javascript" src="User.data.old.js"></script>
|
||||
<script type="text/javascript" src="User.test.js"></script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
2083
frontend/delta/tests/tests/Clipperz/PM/DataModel/User.test.js
Normal file
2083
frontend/delta/tests/tests/Clipperz/PM/DataModel/User.test.js
Normal file
File diff suppressed because it is too large
Load Diff
42
frontend/delta/tests/tests/Clipperz/PM/DataModel/index.html
Normal file
42
frontend/delta/tests/tests/Clipperz/PM/DataModel/index.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!--
|
||||
|
||||
Copyright 2008-2013 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Clipperz.PM.DataModel.* - tests</title>
|
||||
|
||||
<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="../../../../SimpleTest/TestRunner.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
TestRunner.runTests(
|
||||
'DirectLogin.html',
|
||||
'EncryptedRemoteObject.html',
|
||||
'OneTimePassword.html',
|
||||
'Record.html',
|
||||
'User.html'
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user