ki 0.4.10 → 0.4.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +16 -8
- data/MIDDLEWARE.md +27 -7
- data/README.md +45 -2
- data/REALTIME.md +48 -0
- data/TODO.md +19 -0
- data/ki.gemspec +1 -0
- data/lib/ki.rb +5 -0
- data/lib/ki/base_request.rb +7 -0
- data/lib/ki/channel_manager.rb +58 -0
- data/lib/ki/ki.rb +1 -0
- data/lib/ki/ki_cli.rb +1 -1
- data/lib/ki/ki_config.rb +18 -2
- data/lib/ki/middleware/api_handler.rb +11 -16
- data/lib/ki/middleware/helpers/redirect_to_helper.rb +13 -0
- data/lib/ki/middleware/realtime.rb +81 -0
- data/lib/ki/model.rb +6 -4
- data/lib/ki/modules/restrictions.rb +4 -7
- data/lib/ki/orm.rb +38 -2
- data/lib/ki/utils/redirect_to_helper.rb +0 -0
- data/lib/ki/version.rb +1 -1
- data/spec/examples/json.northpole.ro/.bowerrc +3 -0
- data/spec/examples/json.northpole.ro/Gemfile +1 -0
- data/spec/examples/json.northpole.ro/bower.json +17 -0
- data/spec/examples/json.northpole.ro/config.ru +3 -0
- data/spec/examples/json.northpole.ro/config.yml +4 -0
- data/spec/examples/json.northpole.ro/config.yml.backup +18 -0
- data/spec/examples/json.northpole.ro/config/deploy.rb +2 -1
- data/spec/examples/json.northpole.ro/config/deploy/production.rb +4 -38
- data/spec/examples/json.northpole.ro/public/app/.bowerrc +3 -0
- data/spec/examples/json.northpole.ro/public/app/.gitignore +9 -0
- data/spec/examples/json.northpole.ro/public/app/.jshintrc +13 -0
- data/spec/examples/json.northpole.ro/public/app/.travis.yml +14 -0
- data/spec/examples/json.northpole.ro/public/app/LICENSE +22 -0
- data/spec/examples/json.northpole.ro/public/app/README.md +82 -0
- data/spec/examples/json.northpole.ro/public/app/bower.json +20 -0
- data/spec/examples/json.northpole.ro/public/app/e2e/pages/ContactUser.js +22 -0
- data/spec/examples/json.northpole.ro/public/app/e2e/pages/UserDetails.js +11 -0
- data/spec/examples/json.northpole.ro/public/app/e2e/pages/UserList.js +12 -0
- data/spec/examples/json.northpole.ro/public/app/e2e/protractor.conf.js +26 -0
- data/spec/examples/json.northpole.ro/public/app/e2e/scenarios/users.js +34 -0
- data/spec/examples/json.northpole.ro/public/app/gulpfile.js +104 -0
- data/spec/examples/json.northpole.ro/public/app/karma.conf.js +35 -0
- data/spec/examples/json.northpole.ro/public/app/package.json +30 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/avatar-1.svg +11 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/avatar-4.svg +16 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/avatars.svg +244 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/google_plus.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/hangouts.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_fullscreen_48px.svg +4 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_fullscreen_exit_48px.svg +4 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_music_note_48px.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_note_add_48px.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/ic_view_list_48px.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/icon.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/mail.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/manggo.svg +1095 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/menu.svg +4 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/phone.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/share.svg +3 -0
- data/spec/examples/json.northpole.ro/public/app/src/assets/svg/twitter.svg +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/css/app.css +138 -0
- data/spec/examples/json.northpole.ro/public/app/src/css/app.css.map +7 -0
- data/spec/examples/json.northpole.ro/public/app/src/css/app.sass +145 -0
- data/spec/examples/json.northpole.ro/public/app/src/index.html +157 -0
- data/spec/examples/json.northpole.ro/public/app/src/js/MainController.coffee +167 -0
- data/spec/examples/json.northpole.ro/public/app/src/js/app.coffee +58 -0
- data/spec/examples/json.northpole.ro/public/app/src/js/blobs/BlobsController.coffee +115 -0
- data/spec/examples/json.northpole.ro/public/app/src/js/blobs/blobs.html +48 -0
- data/spec/examples/json.northpole.ro/public/app/src/js/tutorial/tutorial.html +15 -0
- data/spec/examples/json.northpole.ro/public/app/src/js/users/UserService.coffee +12 -0
- data/spec/examples/json.northpole.ro/public/app/src/js/users/Users.coffee +1 -0
- data/spec/examples/json.northpole.ro/public/app/src/js/users/users.html +8 -0
- data/spec/examples/json.northpole.ro/public/javascripts/jnorthpole.coffee +40 -7
- data/spec/examples/json.northpole.ro/public/javascripts/realtime.coffee +28 -0
- data/spec/examples/json.northpole.ro/public/{javascripts/music → music}/angular-youtube-embed.js +0 -0
- data/spec/examples/json.northpole.ro/public/music/index.html +126 -0
- data/spec/examples/json.northpole.ro/public/music/music.coffee +99 -0
- data/spec/examples/json.northpole.ro/public/music/music.sass +63 -0
- data/spec/examples/json.northpole.ro/public/stylesheets/app.sass +3 -0
- data/spec/examples/json.northpole.ro/views/faq.haml +7 -0
- data/spec/examples/json.northpole.ro/views/layout.haml +1 -0
- data/spec/examples/json.northpole.ro/views/music.haml +2 -0
- data/spec/examples/json.northpole.ro/views/websocket.haml +7 -0
- data/spec/lib/ki/channel_manager_spec.rb +82 -0
- data/spec/lib/ki/helpers_spec.rb +11 -0
- data/spec/lib/ki/ki_config_spec.rb +28 -0
- data/spec/lib/ki/middleware/admin_generator_spec.rb +8 -0
- data/spec/lib/ki/middleware/init_middleware_spec.rb +21 -0
- data/spec/lib/ki/middleware/realtime_spec.rb +96 -0
- data/spec/lib/ki/model_spec.rb +28 -7
- data/spec/lib/ki/modules/model_helper_spec.rb +31 -0
- data/spec/lib/ki/orm_spec.rb +26 -0
- metadata +211 -9
- data/spec/examples/json.northpole.ro/public/javascripts/docs.min.js +0 -16
- data/spec/examples/json.northpole.ro/views/awsum.haml +0 -108
@@ -0,0 +1,167 @@
|
|
1
|
+
DialogController = ($scope, $mdDialog, $localStorage, $mdToast) ->
|
2
|
+
# $scope.user =
|
3
|
+
# api_key: 'guest'
|
4
|
+
# secret: 'guest'
|
5
|
+
|
6
|
+
$scope.hide = ->
|
7
|
+
$mdDialog.hide()
|
8
|
+
return
|
9
|
+
|
10
|
+
$scope.cancel = ->
|
11
|
+
$mdDialog.cancel()
|
12
|
+
return
|
13
|
+
|
14
|
+
$scope.showToast = (s) ->
|
15
|
+
toast = $mdToast.simple().content(s).position('bottom right').hideDelay(3000)
|
16
|
+
$mdToast.show toast
|
17
|
+
|
18
|
+
apiError = (error) ->
|
19
|
+
console.log error
|
20
|
+
$scope.showToast error.error
|
21
|
+
|
22
|
+
userFound = (json) ->
|
23
|
+
$localStorage.accounts.push
|
24
|
+
api_key: json.api_key
|
25
|
+
secret: json.secret
|
26
|
+
$mdDialog.hide 'refresh'
|
27
|
+
|
28
|
+
$scope.register = () ->
|
29
|
+
jNorthPole.createUser($scope.user.api_key, $scope.user.secret, userFound, apiError)
|
30
|
+
return
|
31
|
+
|
32
|
+
$scope.connect = () ->
|
33
|
+
jNorthPole.getUser($scope.user, (data) ->
|
34
|
+
json = data[0]
|
35
|
+
exists = (item for item in $localStorage.accounts when item.api_key == json.api_key)
|
36
|
+
if exists.length == 0
|
37
|
+
userFound(json)
|
38
|
+
else
|
39
|
+
$scope.showToast "account already connected"
|
40
|
+
console.log "account already connected"
|
41
|
+
, apiError)
|
42
|
+
return
|
43
|
+
|
44
|
+
return
|
45
|
+
|
46
|
+
MainController = ($scope, userService, $mdSidenav, $mdBottomSheet, $log, $q, $mdDialog, $localStorage, $location, $mdToast) ->
|
47
|
+
self = this
|
48
|
+
|
49
|
+
toggleList = ->
|
50
|
+
pending = $mdBottomSheet.hide() or $q.when(true)
|
51
|
+
pending.then ->
|
52
|
+
$mdSidenav('left').toggle()
|
53
|
+
return
|
54
|
+
return
|
55
|
+
|
56
|
+
selectUser = (user) ->
|
57
|
+
$localStorage.selected = angular.copy(user)
|
58
|
+
$location.path "/blobs/#{user.api_key}"
|
59
|
+
self.toggleList()
|
60
|
+
refresh()
|
61
|
+
return
|
62
|
+
|
63
|
+
$scope.showToast = (s) ->
|
64
|
+
toast = $mdToast.simple().content(s).position('bottom right').hideDelay(3000)
|
65
|
+
$mdToast.show toast
|
66
|
+
|
67
|
+
$scope.fortune = ->
|
68
|
+
# http://www.chinese-fortune-cookie.com/fortune-cookie-quotes.html
|
69
|
+
fortunes = [
|
70
|
+
'There is a true and sincere friendship between you and your friends.'
|
71
|
+
'You find beauty in ordinary things, do not lose this ability.'
|
72
|
+
'Ideas are like children; there are none so wonderful as your own.'
|
73
|
+
'It takes more than good memory to have good memories.'
|
74
|
+
'A thrilling time is in your immediate future.'
|
75
|
+
'Your blessing is no more than being safe and sound for the whole lifetime.'
|
76
|
+
'Plan for many pleasures ahead.'
|
77
|
+
'The joyfulness of a man prolongeth his days.'
|
78
|
+
'Your everlasting patience will be rewarded sooner or later.'
|
79
|
+
'Make two grins grow where there was only a grouch before.'
|
80
|
+
'Something you lost will soon turn up.'
|
81
|
+
'Your heart is pure, and your mind clear, and your soul devout.'
|
82
|
+
'Excitement and intrigue follow you closely wherever you go!'
|
83
|
+
'A pleasant surprise is in store for you.'
|
84
|
+
'May life throw you a pleasant curve.'
|
85
|
+
'As the purse is emptied the heart is filled.'
|
86
|
+
'Be mischievous and you will not be lonesome.'
|
87
|
+
'You have a deep appreciation of the arts and music.'
|
88
|
+
'Your flair for the creative takes an important place in your life.'
|
89
|
+
'Your artistic talents win the approval and applause of others.'
|
90
|
+
'Pray for what you want, but work for the things you need.'
|
91
|
+
'Your many hidden talents will become obvious to those around you.'
|
92
|
+
'Don\'t forget, you are always on our minds.'
|
93
|
+
'Your greatest fortune is the large number of friends you have.'
|
94
|
+
'A firm friendship will prove the foundation on your success in life.'
|
95
|
+
'Don\'t ask, don\'t say. Everything lies in silence.'
|
96
|
+
'Look for new outlets for your own creative abilities.'
|
97
|
+
'Be prepared to accept a wondrous opportunity in the days ahead!'
|
98
|
+
'Fame, riches and romance are yours for the asking.'
|
99
|
+
'Good luck is the result of good planning.'
|
100
|
+
'Good things are being said about you.'
|
101
|
+
'Smiling often can make you look and feel younger.'
|
102
|
+
'Someone is speaking well of you.'
|
103
|
+
'The time is right to make new friends.'
|
104
|
+
'You will inherit some money or a small piece of land.'
|
105
|
+
'Your life will be happy and peaceful.'
|
106
|
+
'A friend is a present you give yourself.'
|
107
|
+
'A member of your family will soon do something that will make you proud.'
|
108
|
+
'A quiet evening with friends is the best tonic for a long day.'
|
109
|
+
'A single kind word will keep one warm for years.'
|
110
|
+
'Anger begins with folly, and ends with regret.'
|
111
|
+
'Generosity and perfection are your everlasting goals.'
|
112
|
+
'Happy news is on its way to you.'
|
113
|
+
'He who laughs at himself never runs out of things to laugh at.'
|
114
|
+
'If your desires are not extravagant they will be granted.'
|
115
|
+
'Let there be magic in your smile and firmness in your handshake.'
|
116
|
+
'If you want the rainbow, you must to put up with the rain. D. Parton'
|
117
|
+
'Nature, time and patience are the three best physicians.'
|
118
|
+
'Strong and bitter words indicate a weak cause.'
|
119
|
+
'The beginning of wisdom is to desire it.'
|
120
|
+
'You will have a very pleasant experience.'
|
121
|
+
'You will inherit some money or a small piece of land.'
|
122
|
+
'You will live a long, happy life.'
|
123
|
+
'You will spend old age in comfort and material wealth.'
|
124
|
+
'You will step on the soil of many countries.'
|
125
|
+
'You will take a chance in something in the near future.'
|
126
|
+
'You will witness a special ceremony.'
|
127
|
+
'Your everlasting patience will be rewarded sooner or later.'
|
128
|
+
'Your great attention to detail is both a blessing and a curse.'
|
129
|
+
'Your heart is a place to draw true happiness.'
|
130
|
+
'Your ability to juggle many tasks will take you far.'
|
131
|
+
'A friend asks only for your time, not your money.'
|
132
|
+
'You will be invited to an exciting event.'
|
133
|
+
]
|
134
|
+
$scope.showToast(fortunes[Math.floor(Math.random()*fortunes.length)])
|
135
|
+
|
136
|
+
showAdvanced = (ev) ->
|
137
|
+
$mdDialog.show(
|
138
|
+
controller: DialogController
|
139
|
+
templateUrl: 'js/templates/dialog1.tmpl.html'
|
140
|
+
parent: angular.element(document.body)
|
141
|
+
targetEvent: ev
|
142
|
+
clickOutsideToClose: true)
|
143
|
+
.then ((answer) ->
|
144
|
+
refresh() if answer == 'refresh'
|
145
|
+
return
|
146
|
+
), ->
|
147
|
+
# $scope.status = 'You cancelled the dialog.'
|
148
|
+
return
|
149
|
+
return
|
150
|
+
|
151
|
+
|
152
|
+
self.selected = null
|
153
|
+
self.users = []
|
154
|
+
self.selectUser = selectUser
|
155
|
+
self.toggleList = toggleList
|
156
|
+
self.showAdvanced = showAdvanced
|
157
|
+
|
158
|
+
refresh = ->
|
159
|
+
userService.loadAllUsers().then (users) ->
|
160
|
+
self.users = [].concat(users)
|
161
|
+
$scope.user = $localStorage.selected if $localStorage.selected?
|
162
|
+
return
|
163
|
+
|
164
|
+
refresh()
|
165
|
+
return
|
166
|
+
|
167
|
+
angular.module('app').controller 'MainController', ['$scope', 'userService', '$mdSidenav', '$mdBottomSheet', '$log', '$q', '$mdDialog', '$localStorage', '$location', '$mdToast', MainController]
|
@@ -0,0 +1,58 @@
|
|
1
|
+
app = angular.module('app', ['ngRoute', 'ngStorage', 'ngMaterial', 'users'])
|
2
|
+
|
3
|
+
app.constant("myConfig",
|
4
|
+
title: 'mango {fruit}'
|
5
|
+
)
|
6
|
+
|
7
|
+
app.config ['$mdThemingProvider', '$mdIconProvider', ($mdThemingProvider, $mdIconProvider) ->
|
8
|
+
$mdIconProvider
|
9
|
+
.defaultIconSet('./assets/svg/avatars.svg', 128)
|
10
|
+
.icon('menu', './assets/svg/menu.svg', 24)
|
11
|
+
.icon('share', './assets/svg/share.svg', 24)
|
12
|
+
.icon('google_plus', './assets/svg/google_plus.svg', 512)
|
13
|
+
.icon('hangouts', './assets/svg/hangouts.svg', 512)
|
14
|
+
.icon('twitter', './assets/svg/twitter.svg', 512)
|
15
|
+
.icon('phone', './assets/svg/phone.svg', 512)
|
16
|
+
.icon('person_add', './assets/svg/ic_person_add_48px.svg', 48)
|
17
|
+
.icon('clear', './assets/svg/ic_clear_48px.svg', 48)
|
18
|
+
.icon('plus', './assets/svg/ic_add_48px.svg', 48)
|
19
|
+
.icon('cog', './assets/svg/ic_settings_48px.svg', 48)
|
20
|
+
.icon('delete', './assets/svg/ic_delete_48px.svg', 48)
|
21
|
+
.icon('lock', './assets/svg/ic_lock_48px.svg', 48)
|
22
|
+
.icon('share', './assets/svg/ic_share_48px.svg', 48)
|
23
|
+
.icon('music', './assets/svg/ic_music_note_48px.svg', 48)
|
24
|
+
.icon('note_add', './assets/svg/ic_note_add_48px.svg', 48)
|
25
|
+
.icon('fullscreen', './assets/svg/ic_fullscreen_48px.svg', 48)
|
26
|
+
.icon('fullscreen_exit', './assets/svg/ic_fullscreen_exit_48px.svg', 48)
|
27
|
+
|
28
|
+
$mdThemingProvider
|
29
|
+
.theme('default')
|
30
|
+
.primaryPalette('deep-orange')
|
31
|
+
.accentPalette('blue')
|
32
|
+
.warnPalette('red')
|
33
|
+
.backgroundPalette('grey')
|
34
|
+
# .dark()
|
35
|
+
|
36
|
+
return
|
37
|
+
]
|
38
|
+
|
39
|
+
app.config ['$routeProvider', ($routeProvider) ->
|
40
|
+
$routeProvider
|
41
|
+
.when('/tutorial', templateUrl: 'js/tutorial/tutorial.html')
|
42
|
+
.when('/blobs', templateUrl: 'js/blobs/blobs.html', controller: 'BlobsController')
|
43
|
+
.when('/blobs/:id', templateUrl: 'js/blobs/blobs.html', controller: 'BlobsController')
|
44
|
+
.otherwise(redirectTo: '/blobs')
|
45
|
+
return
|
46
|
+
]
|
47
|
+
|
48
|
+
app.config(['$localStorageProvider', ($localStorageProvider) ->
|
49
|
+
# $localStorageProvider.get('MyKey');
|
50
|
+
# $localStorageProvider.set('MyKey', { k: 'value' });
|
51
|
+
|
52
|
+
$localStorageProvider.setKeyPrefix 'app'
|
53
|
+
return
|
54
|
+
])
|
55
|
+
|
56
|
+
app.run ($rootScope, myConfig) ->
|
57
|
+
$rootScope.myConfig = myConfig
|
58
|
+
return
|
@@ -0,0 +1,115 @@
|
|
1
|
+
BlobsController = ($scope, $routeParams, $location, $localStorage, $mdBottomSheet) ->
|
2
|
+
if !$routeParams.id? and $localStorage.selected?
|
3
|
+
$location.path "/blobs/#{$localStorage.selected.api_key}"
|
4
|
+
return
|
5
|
+
|
6
|
+
$scope.fullItem = null
|
7
|
+
|
8
|
+
if $routeParams.id?
|
9
|
+
unless $localStorage.selected?
|
10
|
+
$location.path '/blobs'
|
11
|
+
return
|
12
|
+
|
13
|
+
$scope.user = $localStorage.selected
|
14
|
+
jNorthPole.getStorage($scope.user, (data) ->
|
15
|
+
$scope.items = data.reverse()
|
16
|
+
$scope.$apply()
|
17
|
+
, (error) ->
|
18
|
+
console.log error
|
19
|
+
)
|
20
|
+
else
|
21
|
+
$location.path '/tutorial'
|
22
|
+
return
|
23
|
+
|
24
|
+
$scope.delete = (item) ->
|
25
|
+
item = angular.copy(item)
|
26
|
+
item.secret = $scope.user.secret
|
27
|
+
|
28
|
+
jNorthPole.deleteStorage(item, (data) ->
|
29
|
+
for r in $scope.items
|
30
|
+
if r.id == item.id
|
31
|
+
$scope.items.splice $scope.items.indexOf(r), 1
|
32
|
+
break
|
33
|
+
$scope.$apply()
|
34
|
+
, (error) ->
|
35
|
+
console.log error
|
36
|
+
)
|
37
|
+
return
|
38
|
+
|
39
|
+
$scope.addItemToList = (item, s) ->
|
40
|
+
return if s == ''
|
41
|
+
item.list = [] unless item.list?
|
42
|
+
item.list.push { checked: false, text: s }
|
43
|
+
$scope.save(item)
|
44
|
+
|
45
|
+
$scope.removeItemFromList = (item, listItem) ->
|
46
|
+
index = item.list.indexOf(listItem)
|
47
|
+
item.list.splice(index, 1)
|
48
|
+
$scope.save(item)
|
49
|
+
|
50
|
+
$scope.fullscreen = (item) ->
|
51
|
+
if $scope.fullItem?
|
52
|
+
$scope.fullItem = null
|
53
|
+
else
|
54
|
+
$scope.fullItem = item
|
55
|
+
|
56
|
+
$scope.toggleType = (item) ->
|
57
|
+
if item.type == 'list'
|
58
|
+
item.type = 'text'
|
59
|
+
else
|
60
|
+
item.type = 'list'
|
61
|
+
$scope.save(item)
|
62
|
+
|
63
|
+
$scope.save = (item) ->
|
64
|
+
item = angular.copy(item)
|
65
|
+
item.api_key = $scope.user.api_key
|
66
|
+
item.secret = $scope.user.secret
|
67
|
+
|
68
|
+
callback = (data) ->
|
69
|
+
console.log data
|
70
|
+
|
71
|
+
if item.id?
|
72
|
+
jNorthPole.putStorage(item, callback)
|
73
|
+
else
|
74
|
+
jNorthPole.createStorage(item, (data) ->
|
75
|
+
$scope.items.unshift data
|
76
|
+
$scope.$apply()
|
77
|
+
, callback)
|
78
|
+
|
79
|
+
$scope.newPanel = ->
|
80
|
+
$scope.save(text: '')
|
81
|
+
|
82
|
+
$scope.showContactOptions = ($event, json) ->
|
83
|
+
json = angular.copy(json)
|
84
|
+
|
85
|
+
ContactPanelController = ($mdBottomSheet, $scope) ->
|
86
|
+
@json = json
|
87
|
+
@actions = [
|
88
|
+
{
|
89
|
+
name: 'Yes, delete already'
|
90
|
+
icon: 'delete'
|
91
|
+
}
|
92
|
+
]
|
93
|
+
|
94
|
+
@submitContact = (action) ->
|
95
|
+
$mdBottomSheet.hide action
|
96
|
+
return
|
97
|
+
|
98
|
+
return
|
99
|
+
|
100
|
+
$mdBottomSheet
|
101
|
+
.show(
|
102
|
+
parent: angular.element(document.body)
|
103
|
+
templateUrl: './js/templates/contactSheet.html'
|
104
|
+
controller: ['$mdBottomSheet', '$scope', ContactPanelController]
|
105
|
+
controllerAs: 'cp'
|
106
|
+
bindToController: true
|
107
|
+
targetEvent: $event)
|
108
|
+
.then (clickedItem) ->
|
109
|
+
if clickedItem.icon == 'delete'
|
110
|
+
$scope.delete(json)
|
111
|
+
return
|
112
|
+
|
113
|
+
return
|
114
|
+
|
115
|
+
angular.module('users').controller 'BlobsController', ['$scope', '$routeParams', '$location', '$localStorage', '$mdBottomSheet', BlobsController]
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<md-content flex layout="row" layout-align="center">
|
2
|
+
<md-content flex style="padding-bottom: 100px">
|
3
|
+
<md-card ng-repeat="item in items" class="repeat-item" ng-show="!fullItem || (fullItem && fullItem.id == item.id)">
|
4
|
+
<md-card-content>
|
5
|
+
<div layout="row" layout-wrap>
|
6
|
+
<md-input-container flex ng-show="item.type == 'list'">
|
7
|
+
<label class="add-new">{{item.text}}</label>
|
8
|
+
<input ng-model="newListItemText" ng-change="addItemToList(item, newListItemText); newListItemText = ''" ng-model-options="{ debounce: 1000 }">
|
9
|
+
</md-input-container>
|
10
|
+
<md-input-container flex ng-show="item.type != 'list'">
|
11
|
+
<!-- used for space -->
|
12
|
+
</md-input-container>
|
13
|
+
<div ng-include="'./js/templates/dropdown.tmpl.html'"></div>
|
14
|
+
</div>
|
15
|
+
<div layout="row" layout-wrap>
|
16
|
+
<md-input-container flex ng-show="item.type != 'list'">
|
17
|
+
<label>Text</label>
|
18
|
+
<textarea ng-model="item.text" columns="1" md-maxlength="1024" ng-change="save(item)" ng-model-options="{ debounce: 1000 }"></textarea>
|
19
|
+
</md-input-container>
|
20
|
+
|
21
|
+
<md-container flex ng-show="item.type == 'list'">
|
22
|
+
<md-container flex ng-repeat="listItem in item.list" class="repeat-item" layout="row">
|
23
|
+
<md-checkbox aria-label="Checkbox" ng-model="listItem.checked" ng-change="save(item)" class="md-primary">
|
24
|
+
</md-checkbox>
|
25
|
+
<md-input-container flex class="small-bot">
|
26
|
+
<input aria-label="checkbox text" ng-model="listItem.text" ng-change="save(item)" ng-model-options="{ debounce: 1000 }" ng-class="{ done: listItem.checked }" ng-disabled="listItem.checked">
|
27
|
+
</md-input-container>
|
28
|
+
<md-button aria-label="delete checkbox item" class="md-icon-button" ng-click="removeItemFromList(item, listItem)">
|
29
|
+
<md-icon md-menu-origin md-svg-icon="delete"></md-icon>
|
30
|
+
</md-button>
|
31
|
+
</md-container>
|
32
|
+
</md-container>
|
33
|
+
</div>
|
34
|
+
</md-card-content>
|
35
|
+
</md-card>
|
36
|
+
<md-card ng-show="items.length == 0">
|
37
|
+
<md-card-content>
|
38
|
+
<div layout="column" layout-align="center center" layout-wrap md-swipe-left="fortune()">
|
39
|
+
<p><< Swipe left for fortune</p>
|
40
|
+
</div>
|
41
|
+
</md-card-content>
|
42
|
+
</md-card>
|
43
|
+
</md-content>
|
44
|
+
</md-content>
|
45
|
+
|
46
|
+
<md-button ng-show="user.api_key" class="md-fab md-primary md-fab-bottom-right" aria-label="Use Android" ng-click="newPanel()">
|
47
|
+
<md-icon md-svg-icon="plus"></md-icon>
|
48
|
+
</md-button>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<md-card>
|
2
|
+
<md-card-content>
|
3
|
+
<h2 class="md-title">
|
4
|
+
Mango The Polar Bear helps you get your &!@^% together.
|
5
|
+
</h2>
|
6
|
+
<p>With client side encryption</p>
|
7
|
+
<p>Of impossible decryption,</p>
|
8
|
+
<p>Your ideas and your notes</p>
|
9
|
+
<p>Will floats your boats.</p>
|
10
|
+
<br />
|
11
|
+
<p>
|
12
|
+
Data is stored at the <a href="https://json.northpole.ro/">North Pole</a>.
|
13
|
+
</p>
|
14
|
+
</md-card-content>
|
15
|
+
</md-card>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
UserService = ($q, $localStorage) ->
|
2
|
+
unless $localStorage.accounts?
|
3
|
+
$localStorage.accounts = []
|
4
|
+
|
5
|
+
users = $localStorage.accounts
|
6
|
+
|
7
|
+
{
|
8
|
+
loadAllUsers: ->
|
9
|
+
$q.when users
|
10
|
+
}
|
11
|
+
|
12
|
+
angular.module('users').service 'userService', ['$q', '$localStorage', UserService]
|
@@ -0,0 +1 @@
|
|
1
|
+
angular.module 'users', [ 'ngMaterial' ]
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<md-icon md-svg-icon="{{ul.selected.avatar}}" class="avatar"></md-icon>
|
2
|
+
<h2>{{ul.selected.name}}</h2>
|
3
|
+
<p>{{ul.selected.content}}</p>
|
4
|
+
|
5
|
+
<md-button class="contact" md-no-ink ng-click="ul.showContactOptions($event)" aria-label="Contact User">
|
6
|
+
<md-tooltip>Contact {{ ul.selected.name }}</md-tooltip>
|
7
|
+
<md-icon md-svg-icon="share"></md-icon>
|
8
|
+
</md-button>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
window.jNorthPole =
|
2
2
|
|
3
|
-
BASE_URL: '/'
|
3
|
+
BASE_URL: 'https://json.northpole.ro/'
|
4
4
|
|
5
5
|
help: """
|
6
6
|
NorthPole JS wrapper example usage:
|
@@ -9,8 +9,11 @@ window.jNorthPole =
|
|
9
9
|
console.log(data);
|
10
10
|
};
|
11
11
|
|
12
|
-
jNorthPole.BASE_URL = '/';
|
13
12
|
jNorthPole.getStorage(json, responseHandler);
|
13
|
+
|
14
|
+
socket = jNorthPole.getNewRealtimeSocket(responseHandler)
|
15
|
+
jNorthPole.subscribe(socket, 'foo')
|
16
|
+
jNorthPole.publish(socket, 'foo', { message: 'hello' })
|
14
17
|
"""
|
15
18
|
|
16
19
|
genericRequest: (jsonObj, method, endPoint, responseHandler, errorHandler=responseHandler) ->
|
@@ -21,7 +24,7 @@ window.jNorthPole =
|
|
21
24
|
|
22
25
|
r.onreadystatechange = ->
|
23
26
|
return if r.readyState != 4
|
24
|
-
if status == 200
|
27
|
+
if r.status == 200
|
25
28
|
responseHandler(JSON.parse(r.responseText), r.status)
|
26
29
|
else
|
27
30
|
errorHandler(JSON.parse(r.responseText), r.status)
|
@@ -34,18 +37,48 @@ window.jNorthPole =
|
|
34
37
|
@genericRequest(jsonObj, 'POST', 'user', success, failure)
|
35
38
|
return
|
36
39
|
|
37
|
-
|
38
|
-
@genericRequest(jsonObj, '
|
40
|
+
getUser: (jsonObj, responseHandler, errorHandler) ->
|
41
|
+
@genericRequest(jsonObj, 'SEARCH', 'user', responseHandler, errorHandler)
|
39
42
|
return
|
40
43
|
|
41
|
-
|
42
|
-
@genericRequest(jsonObj, '
|
44
|
+
createStorage: (jsonObj, responseHandler, errorHandler) ->
|
45
|
+
@genericRequest(jsonObj, 'POST', 'storage', responseHandler, errorHandler)
|
43
46
|
return
|
44
47
|
|
45
48
|
getStorage: (jsonObj, responseHandler, errorHandler) ->
|
46
49
|
@genericRequest(jsonObj, 'SEARCH', 'storage', responseHandler, errorHandler)
|
47
50
|
return
|
48
51
|
|
52
|
+
putStorage: (jsonObj, responseHandler, errorHandler) ->
|
53
|
+
@genericRequest(jsonObj, 'PUT', 'storage', responseHandler, errorHandler)
|
54
|
+
return
|
55
|
+
|
49
56
|
deleteStorage: (jsonObj, responseHandler, errorHandler) ->
|
50
57
|
@genericRequest(jsonObj, 'DELETE', 'storage', responseHandler, errorHandler)
|
51
58
|
return
|
59
|
+
|
60
|
+
getNewRealtimeSocket: (responseHandler, errorHandler=responseHandler) ->
|
61
|
+
socketUrl = @BASE_URL.replace('http', 'ws')
|
62
|
+
socket = new WebSocket("#{socketUrl}realtime")
|
63
|
+
socket.onmessage = responseHandler
|
64
|
+
socket.onclose = errorHandler
|
65
|
+
socket
|
66
|
+
|
67
|
+
subscribe: (socket, channel_name) ->
|
68
|
+
socket.send(JSON.stringify(
|
69
|
+
type: 'subscribe'
|
70
|
+
channel_name: channel_name
|
71
|
+
))
|
72
|
+
|
73
|
+
unsubscribe: (socket, channel_name) ->
|
74
|
+
socket.send(JSON.stringify(
|
75
|
+
type: 'unsubscribe'
|
76
|
+
channel_name: channel_name
|
77
|
+
))
|
78
|
+
|
79
|
+
publish: (socket, channel_name, json) ->
|
80
|
+
socket.send(JSON.stringify(
|
81
|
+
type: 'publish'
|
82
|
+
channel_name: channel_name
|
83
|
+
content: json
|
84
|
+
))
|