surikat 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.idea/workspace.xml +186 -81
- data/README.md +1 -1
- data/exe/surikat +2 -1
- data/frontend-demo/LICENSE +21 -0
- data/frontend-demo/README.md +89 -0
- data/frontend-demo/aaa.html +153 -0
- data/frontend-demo/aaa.js +115 -0
- data/frontend-demo/authors.js +159 -0
- data/frontend-demo/books.html +138 -0
- data/frontend-demo/books.js +201 -0
- data/frontend-demo/gulpfile.js +42 -0
- data/frontend-demo/index.html +137 -0
- data/frontend-demo/package-lock.json +4757 -0
- data/frontend-demo/package.json +36 -0
- data/frontend-demo/vendor/bootstrap/css/bootstrap.css +8981 -0
- data/frontend-demo/vendor/bootstrap/css/bootstrap.css.map +1 -0
- data/frontend-demo/vendor/bootstrap/css/bootstrap.min.css +7 -0
- data/frontend-demo/vendor/bootstrap/css/bootstrap.min.css.map +1 -0
- data/frontend-demo/vendor/bootstrap/js/bootstrap.bundle.js +6444 -0
- data/frontend-demo/vendor/bootstrap/js/bootstrap.bundle.js.map +1 -0
- data/frontend-demo/vendor/bootstrap/js/bootstrap.bundle.min.js +7 -0
- data/frontend-demo/vendor/bootstrap/js/bootstrap.bundle.min.js.map +1 -0
- data/frontend-demo/vendor/bootstrap/js/bootstrap.js +3927 -0
- data/frontend-demo/vendor/bootstrap/js/bootstrap.js.map +1 -0
- data/frontend-demo/vendor/bootstrap/js/bootstrap.min.js +7 -0
- data/frontend-demo/vendor/bootstrap/js/bootstrap.min.js.map +1 -0
- data/frontend-demo/vendor/graphql.min.js +1 -0
- data/frontend-demo/vendor/jquery/jquery.js +10364 -0
- data/frontend-demo/vendor/jquery/jquery.min.js +2 -0
- data/frontend-demo/vendor/jquery/jquery.min.map +1 -0
- data/frontend-demo/vendor/jquery/jquery.slim.js +8269 -0
- data/frontend-demo/vendor/jquery/jquery.slim.min.js +2 -0
- data/frontend-demo/vendor/jquery/jquery.slim.min.map +1 -0
- data/frontend-demo/vendor/notify.min.js +1 -0
- data/lib/surikat.rb +16 -11
- data/lib/surikat/templates/aaa_queries.rb.tmpl +5 -3
- data/lib/surikat/templates/config.ru.tmpl +5 -0
- data/lib/surikat/version.rb +1 -1
- metadata +33 -2
data/README.md
CHANGED
data/exe/surikat
CHANGED
@@ -143,7 +143,8 @@ def exemplify_mutations(query_name, route)
|
|
143
143
|
r_args.each.each do |var_name, var_type|
|
144
144
|
k_var_name = ActiveSupport::Inflector.singularize(var_name.underscore)
|
145
145
|
variables[k_var_name] = {}
|
146
|
-
all_types[var_type]['arguments']
|
146
|
+
arguments = all_types[var_type] && all_types[var_type]['arguments'] || []
|
147
|
+
arguments.each do |a, t|
|
147
148
|
next if a == 'id' && route['method'] == 'create' # yes, someone may make create queries with other names
|
148
149
|
if Types::BASIC.include?(t)
|
149
150
|
variables[k_var_name][a] = random_values(t)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013-2018 Blackrock Digital LLC
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Surikat Demo
|
2
|
+
|
3
|
+
This is a collection of three HTML pages which test a few basic [Surikat](https://github.com/alxx/surikat) features.
|
4
|
+
The layout is based on [Bare](http://startbootstrap.com/template-overviews/bare/) by [Start Bootstrap](http://startbootstrap.com/)
|
5
|
+
and, in addition to Bootstrap and jQuery, it uses [jquery-graphql](https://www.jquerycards.com/media/tables-graphs/jquery-graphql/).
|
6
|
+
|
7
|
+
## Page 1. Authors
|
8
|
+
|
9
|
+
The purpose of this page is to implement CRUD (create, retrieve, update and delete) operations using GraphQL.
|
10
|
+
These operations can automatically created in a Surikat app by means of a scaffold command:
|
11
|
+
|
12
|
+
```bash
|
13
|
+
$ surikat generate scaffold Author name:string yob:integer
|
14
|
+
$ rake db:migrate
|
15
|
+
```
|
16
|
+
|
17
|
+
## Page 2. Books
|
18
|
+
|
19
|
+
To further comment on Surikat's simplicity, there's a secondary page where an author's list of books
|
20
|
+
can be managed. In order for this to work, first the underlying scaffold must be generated:
|
21
|
+
|
22
|
+
```bash
|
23
|
+
$ surikat generate scaffold Book title:string
|
24
|
+
$ rake db:migrate
|
25
|
+
```
|
26
|
+
|
27
|
+
Then, the `Author` and `Book` models need to be connected
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class Author < Surikat::BaseModel
|
31
|
+
has_many :books, dependent: :destroy
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
class Book < Surikat::BaseModel
|
37
|
+
belongs_to :author
|
38
|
+
end
|
39
|
+
```
|
40
|
+
|
41
|
+
And finally, the `Author` GraphQL type needs to include a field called `books`. So in `config/types.yml` add the last line, `books: "[Book]"`:
|
42
|
+
|
43
|
+
```yaml
|
44
|
+
Author:
|
45
|
+
type: Output
|
46
|
+
fields:
|
47
|
+
name: String
|
48
|
+
yob: Int
|
49
|
+
age: Int
|
50
|
+
created_at: String
|
51
|
+
updated_at: String
|
52
|
+
id: ID
|
53
|
+
books: "[Book]"
|
54
|
+
```
|
55
|
+
|
56
|
+
## Page 3. AAA
|
57
|
+
|
58
|
+
The last page in this demo works with authentication, authorisation and access control (AAA).
|
59
|
+
|
60
|
+
It requires that AAA is added to the Surikat app:
|
61
|
+
|
62
|
+
```bash
|
63
|
+
$ surikat generate aaa
|
64
|
+
$ rake db:migrate
|
65
|
+
```
|
66
|
+
|
67
|
+
and that there's a user to login with:
|
68
|
+
|
69
|
+
```bash
|
70
|
+
$ bin/console
|
71
|
+
> User.create email:'a@b.c', password:'1'
|
72
|
+
```
|
73
|
+
|
74
|
+
### Live Reload
|
75
|
+
|
76
|
+
If you want to edit this demo and would like the benefits of live reloading, you can use `gulp`. First, install the necessary modules:
|
77
|
+
|
78
|
+
```bash
|
79
|
+
$ npm install
|
80
|
+
```
|
81
|
+
|
82
|
+
Then, the `gulp` command line interface:
|
83
|
+
|
84
|
+
```bash
|
85
|
+
$ npm install gulp-cli
|
86
|
+
```
|
87
|
+
|
88
|
+
Now, if you run `gulp dev` the index page will open in a browser, and it will refresh
|
89
|
+
when you make changes in the files.
|
@@ -0,0 +1,153 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
|
6
|
+
<meta charset="utf-8">
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
8
|
+
<meta name="description" content="">
|
9
|
+
<meta name="author" content="">
|
10
|
+
|
11
|
+
<title>Surikat Demo</title>
|
12
|
+
|
13
|
+
<!-- Bootstrap core CSS -->
|
14
|
+
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
15
|
+
|
16
|
+
<!-- Custom styles for this template -->
|
17
|
+
<style>
|
18
|
+
body {
|
19
|
+
padding-top: 54px;
|
20
|
+
}
|
21
|
+
|
22
|
+
@media (min-width: 992px) {
|
23
|
+
body {
|
24
|
+
padding-top: 56px;
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
</style>
|
29
|
+
|
30
|
+
</head>
|
31
|
+
|
32
|
+
<body>
|
33
|
+
|
34
|
+
<!-- Navigation -->
|
35
|
+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
|
36
|
+
<div class="container">
|
37
|
+
<a class="navbar-brand" href="https://github.com/alxx/surikat">
|
38
|
+
<img src="https://camo.githubusercontent.com/b17e471f697a115ac68f565e637602328c402478/68747470733a2f2f692e696d6775722e636f6d2f4f6c43557733382e706e67"
|
39
|
+
width="26" height="40" alt="">
|
40
|
+
Surikat Demo
|
41
|
+
</a>
|
42
|
+
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive"
|
43
|
+
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
44
|
+
<span class="navbar-toggler-icon"></span>
|
45
|
+
</button>
|
46
|
+
<div class="collapse navbar-collapse" id="navbarResponsive">
|
47
|
+
<ul class="navbar-nav ml-auto">
|
48
|
+
<li class="nav-item">
|
49
|
+
<a class="nav-link" href="index.html">Authors</a>
|
50
|
+
</li>
|
51
|
+
<li class="nav-item">
|
52
|
+
<a class="nav-link" href="books.html">Books</a>
|
53
|
+
</li>
|
54
|
+
<li class="nav-item active">
|
55
|
+
<a class="nav-link" href="aaa.html">AAA</a>
|
56
|
+
<span class="sr-only">(current)</span>
|
57
|
+
</li>
|
58
|
+
</ul>
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
</nav>
|
62
|
+
|
63
|
+
<!-- Page Content -->
|
64
|
+
<div class="container">
|
65
|
+
<div class="row">
|
66
|
+
<div class="col-lg-12 text-center">
|
67
|
+
<h1 class="mt-5">Authentication, Authorisation, Access</h1>
|
68
|
+
|
69
|
+
|
70
|
+
<div id="not-logged-in">
|
71
|
+
<form>
|
72
|
+
|
73
|
+
<div class="input-group mb-3">
|
74
|
+
<div class="input-group-prepend">
|
75
|
+
<label class="input-group-text" for="email">Email</label>
|
76
|
+
</div>
|
77
|
+
<input type="text" class="form-control" placeholder="Enter your email address" id="email">
|
78
|
+
</div>
|
79
|
+
|
80
|
+
<div class="input-group mb-3">
|
81
|
+
<div class="input-group-prepend">
|
82
|
+
<label class="input-group-text">Password</label>
|
83
|
+
</div>
|
84
|
+
<input type="password" class="form-control" placeholder="Enter your password" id="password">
|
85
|
+
</div>
|
86
|
+
|
87
|
+
<button type="submit" class="btn btn-primary" id="btnLogin" disabled="disabled">Login</button>
|
88
|
+
</form>
|
89
|
+
</div>
|
90
|
+
|
91
|
+
<div id="logged-in" style="display: none;">
|
92
|
+
<div id="current_user" class="alert alert-primary mb-3">You are logged in.</div>
|
93
|
+
|
94
|
+
<table class="table mb-lg-5">
|
95
|
+
<tr width="100%">
|
96
|
+
<td width="33%">
|
97
|
+
<div class="card mb-lg-5">
|
98
|
+
Click this button to make a call to CurrentUser.<br/>
|
99
|
+
<button class="btn btn-outline-info" id="btnCurUser">Retrieve current user</button>
|
100
|
+
</div>
|
101
|
+
</td>
|
102
|
+
<td width="33%">
|
103
|
+
<div class="card mb-lg-5">
|
104
|
+
Try to call DemoTwo, which only users who have the role 'hotdog' or 'hamburger' may call
|
105
|
+
<button class="btn btn-outline-info" id="btnProtected">Try a role-protected action</button>
|
106
|
+
</div>
|
107
|
+
</td>
|
108
|
+
<td width="33%">
|
109
|
+
<div class="card mb-lg-5">
|
110
|
+
Logout as this user and return to the login form
|
111
|
+
<button class="btn btn-outline-info" id="btnLogout">Logout</button>
|
112
|
+
</div>
|
113
|
+
</td>
|
114
|
+
</tr>
|
115
|
+
</table>
|
116
|
+
|
117
|
+
</div>
|
118
|
+
|
119
|
+
</div>
|
120
|
+
</div>
|
121
|
+
</div>
|
122
|
+
|
123
|
+
<!-- Bootstrap core JavaScript -->
|
124
|
+
<script src="vendor/jquery/jquery.min.js"></script>
|
125
|
+
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
126
|
+
|
127
|
+
<!-- GraphQL Plugin -->
|
128
|
+
<script src="vendor/graphql.min.js"></script>
|
129
|
+
|
130
|
+
<!-- Notifications -->
|
131
|
+
<script src="vendor/notify.min.js"></script>
|
132
|
+
|
133
|
+
<!-- App -->
|
134
|
+
<script src="aaa.js"></script>
|
135
|
+
|
136
|
+
<script language="JavaScript">
|
137
|
+
$(document).ready(function () {
|
138
|
+
|
139
|
+
$('input[type="text"]').keyup(function () {
|
140
|
+
if ($(this).val() != '') {
|
141
|
+
$(':input[type="submit"]').prop('disabled', false);
|
142
|
+
} else {
|
143
|
+
$(':input[type="submit"]').prop('disabled', true);
|
144
|
+
}
|
145
|
+
});
|
146
|
+
|
147
|
+
run();
|
148
|
+
})
|
149
|
+
</script>
|
150
|
+
|
151
|
+
</body>
|
152
|
+
|
153
|
+
</html>
|
@@ -0,0 +1,115 @@
|
|
1
|
+
var graph = graphql("http://localhost:3000/", {
|
2
|
+
headers: {
|
3
|
+
'Surikat': 'abc'//Math.random().toString(36).replace(/[^a-z]+/g, '')
|
4
|
+
}
|
5
|
+
});
|
6
|
+
|
7
|
+
var current_user;
|
8
|
+
|
9
|
+
$("#btnLogin").click(function (el) {
|
10
|
+
el.preventDefault();
|
11
|
+
|
12
|
+
$(this).attr('disabled', true);
|
13
|
+
|
14
|
+
var email = $('#email').val();
|
15
|
+
var password = $('#password').val();
|
16
|
+
|
17
|
+
authenticate(email, password);
|
18
|
+
});
|
19
|
+
|
20
|
+
$('#btnCurUser').click(function (el) {
|
21
|
+
el.preventDefault();
|
22
|
+
|
23
|
+
$(this).attr('disabled', true);
|
24
|
+
getCurrentUser();
|
25
|
+
});
|
26
|
+
|
27
|
+
$('#btnLogout').click(function (e) {
|
28
|
+
e.preventDefault();
|
29
|
+
|
30
|
+
logout();
|
31
|
+
});
|
32
|
+
|
33
|
+
$('#btnProtected').click(function (e) {
|
34
|
+
e.preventDefault();
|
35
|
+
|
36
|
+
demoTwo();
|
37
|
+
});
|
38
|
+
|
39
|
+
function demoTwo() {
|
40
|
+
var q = '{DemoTwo}';
|
41
|
+
console.log('calling a role-protected method...');
|
42
|
+
|
43
|
+
graph.query.run(q).then(function (r) {
|
44
|
+
$.notify(r.DemoTwo, {position: 'top left', autoHideDelay: 3000})
|
45
|
+
}).catch(function(error) {
|
46
|
+
if (error.find(e => e.accessDenied)) {
|
47
|
+
$.notify('Access denied', {position: "top center", autoHideDelay: 3000});
|
48
|
+
} else {
|
49
|
+
alert(JSON.stringify(error))
|
50
|
+
}
|
51
|
+
})
|
52
|
+
}
|
53
|
+
|
54
|
+
function logout() {
|
55
|
+
var q = '{Logout}';
|
56
|
+
console.log('logging out...');
|
57
|
+
|
58
|
+
graph.query.run(q).then(function (r) {
|
59
|
+
$.notify('You have been logged out.', {position: "top center", autoHideDelay: 3000});
|
60
|
+
$('#not-logged-in').show();
|
61
|
+
$('#logged-in').hide();
|
62
|
+
$('#btnLogin').removeAttr('disabled');
|
63
|
+
}).catch(function(error) {
|
64
|
+
alert(JSON.stringify(error))
|
65
|
+
})
|
66
|
+
}
|
67
|
+
|
68
|
+
function getCurrentUser() {
|
69
|
+
var q = '{CurrentUser {id,email,roleids}}';
|
70
|
+
console.log('getting current user...');
|
71
|
+
|
72
|
+
graph.query.run(q).then(function (r) {
|
73
|
+
current_user = r.CurrentUser;
|
74
|
+
console.log('current user: ', current_user);
|
75
|
+
|
76
|
+
$('#not-logged-in').hide();
|
77
|
+
$('#logged-in').show();
|
78
|
+
|
79
|
+
$('#current_user').html(`You are logged in as ${current_user.email}. Your roles are: ${current_user.roleids}`);
|
80
|
+
$.notify(`You are logged in as ${current_user.email}. Your roles are: ${current_user.roleids}`, {position: "top center", autoHideDelay: 3000});
|
81
|
+
$('#btnCurUser').removeAttr('disabled');
|
82
|
+
}).catch(function(error) {
|
83
|
+
if (error.find(e => e.accessDenied)) {
|
84
|
+
$.notify('Bad credentials', {position: "top center", autoHideDelay: 3000});
|
85
|
+
} else {
|
86
|
+
alert(JSON.stringify(error))
|
87
|
+
}
|
88
|
+
alert(JSON.stringify(error))
|
89
|
+
})
|
90
|
+
}
|
91
|
+
|
92
|
+
function authenticate(email, password) {
|
93
|
+
var q = `{Authenticate(email: "${email}", password: "${password}")}`;
|
94
|
+
console.log(`logging in...`);
|
95
|
+
|
96
|
+
graph.query.run(q).then(function (r) {
|
97
|
+
$.notify('Successfully authenticated!', {position: "top center", autoHideDelay: 3000});
|
98
|
+
$('#not-logged-in').hide();
|
99
|
+
$('#logged-in').show();
|
100
|
+
}).catch(function (error) {
|
101
|
+
if (error.find(e => e.noResult)) {
|
102
|
+
$.notify('Bad credentials', {position: "top center", autoHideDelay: 3000});
|
103
|
+
} else {
|
104
|
+
alert(JSON.stringify(error))
|
105
|
+
}
|
106
|
+
$('#btnLogin').removeAttr('disabled');
|
107
|
+
})
|
108
|
+
}
|
109
|
+
|
110
|
+
|
111
|
+
function run() {
|
112
|
+
console.log('starting...');
|
113
|
+
|
114
|
+
getCurrentUser();
|
115
|
+
}
|
@@ -0,0 +1,159 @@
|
|
1
|
+
var graph = graphql("http://localhost:3000/", {});
|
2
|
+
|
3
|
+
$(document).on("click", '#all tbody tr', function (tr) {
|
4
|
+
var id = $(tr.target.parentNode).data('id');
|
5
|
+
|
6
|
+
// simple way to ignore graphql if the click was on a link
|
7
|
+
if (tr.target.outerHTML.indexOf('<a href') == -1) {
|
8
|
+
setAuthor(id);
|
9
|
+
}
|
10
|
+
});
|
11
|
+
|
12
|
+
$("#btnDelete").click(function (el) {
|
13
|
+
el.preventDefault();
|
14
|
+
|
15
|
+
var id = $('#author_id').val();
|
16
|
+
|
17
|
+
$(this).attr('disabled', true);
|
18
|
+
$("#btnSubmit").attr('disabled', true);
|
19
|
+
deleteAuthor(id);
|
20
|
+
});
|
21
|
+
|
22
|
+
$("#btnSubmit").click(function (el) {
|
23
|
+
el.preventDefault();
|
24
|
+
|
25
|
+
$(this).attr('disabled', true);
|
26
|
+
$("#btnDelete").attr('disabled', true);
|
27
|
+
|
28
|
+
var id = $('#author_id').val();
|
29
|
+
var name = $('#name').val();
|
30
|
+
var yob = $('#yob').val();
|
31
|
+
|
32
|
+
if (id == null || id === "") {
|
33
|
+
console.log('save author');
|
34
|
+
saveAuthor(name, yob);
|
35
|
+
} else {
|
36
|
+
console.log('update author');
|
37
|
+
updateAuthor(id, name, yob);
|
38
|
+
}
|
39
|
+
});
|
40
|
+
|
41
|
+
function setAuthor(id) {
|
42
|
+
var q = `{Author(id: ${id}) {name,yob}}`;
|
43
|
+
console.log(`loading author ${id}...`);
|
44
|
+
|
45
|
+
graph.query.run(q).then(function (r) {
|
46
|
+
author = r.Author;
|
47
|
+
console.log(author);
|
48
|
+
$("#author_id").val(id);
|
49
|
+
$("#name").val(author.name);
|
50
|
+
$("#yob").val(author.yob);
|
51
|
+
|
52
|
+
$("#btnSubmit").removeAttr('disabled');
|
53
|
+
$("#btnDelete").removeAttr('disabled');
|
54
|
+
}).catch(function (error) {
|
55
|
+
alert(JSON.stringify(error))
|
56
|
+
})
|
57
|
+
}
|
58
|
+
|
59
|
+
function saveAuthor(name, yob) {
|
60
|
+
var q = `mutation Author($author: AuthorInput) {Author(author: $author) {id}}`;
|
61
|
+
var vars = {author: {name: name, yob: parseInt(yob)}};
|
62
|
+
console.log('creating author...');
|
63
|
+
|
64
|
+
var create = graph(q);
|
65
|
+
|
66
|
+
create(vars).then(function (r) {
|
67
|
+
author = r.Author;
|
68
|
+
$.notify(`Author created with id ${author.id}`, {position: "top center", autoHideDelay: 3000});
|
69
|
+
|
70
|
+
$("#author_id").val(author.id);
|
71
|
+
|
72
|
+
$("#btnSubmit").removeAttr('disabled');
|
73
|
+
$("#btnDelete").removeAttr('disabled');
|
74
|
+
|
75
|
+
authorList();
|
76
|
+
}).catch(function (error) {
|
77
|
+
alert(JSON.stringify(error))
|
78
|
+
})
|
79
|
+
}
|
80
|
+
|
81
|
+
function updateAuthor(id, name, yob) {
|
82
|
+
var q = `mutation UpdateAuthor($author: AuthorInput) {UpdateAuthor(author: $author) {id}}`;
|
83
|
+
var vars = {author: {id: id, name: name, yob: parseInt(yob)}};
|
84
|
+
console.log(`updating author ${id}...`);
|
85
|
+
|
86
|
+
var update = graph(q);
|
87
|
+
|
88
|
+
update(vars).then(function (r) {
|
89
|
+
author = r.UpdateAuthor;
|
90
|
+
$.notify(`Author updated`, {position: "top center", autoHideDelay: 3000});
|
91
|
+
|
92
|
+
$("#btnSubmit").removeAttr('disabled');
|
93
|
+
$("#btnDelete").removeAttr('disabled');
|
94
|
+
|
95
|
+
authorList();
|
96
|
+
}).catch(function (error) {
|
97
|
+
alert(JSON.stringify(error))
|
98
|
+
})
|
99
|
+
}
|
100
|
+
|
101
|
+
function deleteAuthor(id) {
|
102
|
+
var q = `mutation DeleteAuthor($id: ID) {DeleteAuthor(id: $id)}`;
|
103
|
+
var vars = {id: id};
|
104
|
+
console.log(`deleting author ${id}...`);
|
105
|
+
|
106
|
+
var del = graph(q);
|
107
|
+
|
108
|
+
del(vars).then(function (r) {
|
109
|
+
$.notify(`Author ${id} deleted.`, {position: "top center", autoHideDelay: 3000});
|
110
|
+
|
111
|
+
$('#author_id').val(null);
|
112
|
+
$('#name').val(null);
|
113
|
+
$('#yob').val(null);
|
114
|
+
|
115
|
+
authorList();
|
116
|
+
}).catch(function (error) {
|
117
|
+
alert(JSON.stringify(error))
|
118
|
+
})
|
119
|
+
}
|
120
|
+
|
121
|
+
function authorList() {
|
122
|
+
$("#all > tbody").html("");
|
123
|
+
|
124
|
+
var q = `{
|
125
|
+
Authors {
|
126
|
+
id
|
127
|
+
name
|
128
|
+
yob
|
129
|
+
created_at
|
130
|
+
updated_at
|
131
|
+
books {
|
132
|
+
id
|
133
|
+
}
|
134
|
+
}
|
135
|
+
}`;
|
136
|
+
|
137
|
+
console.log('loading authors...');
|
138
|
+
|
139
|
+
graph.query.run(q).then(function (all) {
|
140
|
+
all.Authors.forEach(function (r) {
|
141
|
+
$('#all tbody').append(`<tr data-id="${r.id}"><th scope="row">${r.id}</th>
|
142
|
+
<td>${r.name}</td>
|
143
|
+
<td>${r.yob}</td>
|
144
|
+
<td>${r.created_at}</td>
|
145
|
+
<td>${r.updated_at}</td>
|
146
|
+
<td><a href="books.html?author_id=${r.id}">${r.books.length}</a></td></tr>`);
|
147
|
+
});
|
148
|
+
|
149
|
+
}).catch(function (error) {
|
150
|
+
alert(JSON.stringify(error));
|
151
|
+
})
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
function run() {
|
156
|
+
console.log('starting...');
|
157
|
+
|
158
|
+
authorList();
|
159
|
+
}
|