View | Details | Raw Unified | Return to bug 14974
Collapse All | Expand All

(-)a/Koha/REST/V1/Cities.pm (+98 lines)
Line 0 Link Here
1
package Koha::REST::V1::Cities;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 3 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along
15
# with Koha; if not, write to the Free Software Foundation, Inc.,
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
use Modern::Perl;
19
20
use Mojo::Base 'Mojolicious::Controller';
21
22
use C4::Auth qw( haspermission );
23
use Koha::City;
24
use Koha::Cities;
25
26
sub list_cities {
27
    my ($c, $args, $cb) = @_;
28
29
    my $user = $c->stash('koha.user');
30
    # Check permissions here
31
32
    # Catch possible errors here
33
    my $cities = Koha::Cities->search(
34
         {
35
            map { $args->{$_} ? ( $_ => $args->{$_} ): () } keys %$args
36
         }
37
    );
38
39
    return $c->$cb($cities->unblessed, 200);
40
}
41
42
sub get_city {
43
    my ($c, $args, $cb) = @_;
44
45
    my $user = $c->stash('koha.user');
46
    # Check permissions here
47
48
    # Catch possible errors here
49
    my $city = Koha::Cities->find($args->{cityid});
50
    unless ($city) {
51
        return $c->$cb({error => "City not found"}, 404);
52
    }
53
54
    return $c->$cb($city->unblessed, 200);
55
}
56
57
sub add_city {
58
    my ($c, $args, $cb) = @_;
59
60
    my $user = $c->stash('koha.user');
61
    # Check permissions here
62
63
    # Catch possible errors here
64
    my $city = Koha::City->new($args->{city});
65
    $city->store;
66
67
    return $c->$cb($city->unblessed, 200);
68
}
69
70
sub update_city {
71
    my ($c, $args, $cb) = @_;
72
73
    my $user = $c->stash('koha.user');
74
    # Check permissions here
75
76
    # Catch possible errors here
77
    my $city = Koha::Cities->find($args->{city}{cityid});
78
    while ( my ( $k, $v ) = each %{$args->{city}} ) {
79
        $city->$k($v);
80
    }
81
    $city->store;
82
83
    return $c->$cb($city->unblessed, 200);
84
}
85
86
sub delete_city {
87
    my ($c, $args, $cb) = @_;
88
89
    my $user = $c->stash('koha.user');
90
    # Check permissions here
91
92
    # Catch possible errors here
93
    my $city = Koha::Cities->find($args->{cityid})->delete;
94
95
    return $c->$cb("", 200);
96
}
97
98
1;
(-)a/admin/cities.pl (-51 / +2 lines)
Lines 30-36 my $input = new CGI; Link Here
30
my $searchfield = $input->param('city_name') // q||;
30
my $searchfield = $input->param('city_name') // q||;
31
my $cityid      = $input->param('cityid');
31
my $cityid      = $input->param('cityid');
32
my $op          = $input->param('op') || 'list';
32
my $op          = $input->param('op') || 'list';
33
my @messages;
33
my $message     = $input->param('message');
34
34
35
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
35
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
36
    {   template_name   => "admin/cities.tt",
36
    {   template_name   => "admin/cities.tt",
Lines 50-104 if ( $op eq 'add_form' ) { Link Here
50
    }
50
    }
51
51
52
    $template->param( city => $city, );
52
    $template->param( city => $city, );
53
} elsif ( $op eq 'add_validate' ) {
54
    my $cityid       = $input->param('cityid');
55
    my $city_name    = $input->param('city_name');
56
    my $city_state   = $input->param('city_state');
57
    my $city_zipcode = $input->param('city_zipcode');
58
    my $city_country = $input->param('city_country');
59
60
    if ($cityid) {
61
        my $city = Koha::Cities->find($cityid);
62
        $city->city_name($city_name);
63
        $city->city_state($city_state);
64
        $city->city_zipcode($city_zipcode);
65
        $city->city_country($city_country);
66
        eval { $city->store; };
67
        if ($@) {
68
            push @messages, { type => 'error', code => 'error_on_update' };
69
        } else {
70
            push @messages, { type => 'message', code => 'success_on_update' };
71
        }
72
    } else {
73
        my $city = Koha::City->new(
74
            {   city_name    => $city_name,
75
                city_state   => $city_state,
76
                city_zipcode => $city_zipcode,
77
                city_country => $city_country,
78
            }
79
        );
80
        eval { $city->store; };
81
        if ($@) {
82
            push @messages, { type => 'error', code => 'error_on_insert' };
83
        } else {
84
            push @messages, { type => 'message', code => 'success_on_insert' };
85
        }
86
    }
87
    $searchfield = q||;
88
    $op          = 'list';
89
} elsif ( $op eq 'delete_confirm' ) {
90
    my $city = Koha::Cities->find($cityid);
91
    $template->param( city => $city, );
92
} elsif ( $op eq 'delete_confirmed' ) {
93
    my $city = Koha::Cities->find($cityid);
94
    my $deleted = eval { $city->delete; };
95
96
    if ( $@ or not $deleted ) {
97
        push @messages, { type => 'error', code => 'error_on_delete' };
98
    } else {
99
        push @messages, { type => 'message', code => 'success_on_delete' };
100
    }
101
    $op = 'list';
102
}
53
}
103
54
104
if ( $op eq 'list' ) {
55
if ( $op eq 'list' ) {
Lines 109-115 if ( $op eq 'list' ) { Link Here
109
$template->param(
60
$template->param(
110
    cityid      => $cityid,
61
    cityid      => $cityid,
111
    searchfield => $searchfield,
62
    searchfield => $searchfield,
112
    messages    => \@messages,
63
    message     => $message,
113
    op          => $op,
64
    op          => $op,
114
);
65
);
115
66
(-)a/api/v1/swagger.json (+192 lines)
Lines 75-80 Link Here
75
          }
75
          }
76
        }
76
        }
77
      }
77
      }
78
    },
79
    "/cities": {
80
      "get": {
81
        "x-mojo-controller": "Koha::REST::V1::Cities",
82
        "operationId": "listCities",
83
        "tags": ["cities"],
84
        "produces": [
85
          "application/json"
86
        ],
87
        "responses": {
88
          "200": {
89
            "description": "A list of cities",
90
            "schema": {
91
              "type": "array",
92
              "items": {
93
                "$ref": "#/definitions/city"
94
              }
95
            }
96
          },
97
          "403": {
98
            "description": "Access forbidden",
99
            "schema": {
100
              "$ref": "#/definitions/error"
101
            }
102
          }
103
        }
104
      },
105
      "put": {
106
        "x-mojo-controller": "Koha::REST::V1::Cities",
107
        "operationId": "AddCity",
108
        "tags": ["cities"],
109
        "parameters": [
110
          {
111
            "$ref": "#/parameters/cityBodyParam"
112
          }
113
        ],
114
        "produces": [
115
          "application/json"
116
        ],
117
        "responses": {
118
          "200": {
119
            "description": "City added",
120
            "schema": {
121
              "$ref": "#/definitions/city"
122
            }
123
          },
124
          "403": {
125
            "description": "Access forbidden",
126
            "schema": {
127
              "$ref": "#/definitions/error"
128
            }
129
          }
130
        }
131
      }
132
    },
133
    "/cities/{cityid}": {
134
      "get": {
135
        "x-mojo-controller": "Koha::REST::V1::Cities",
136
        "operationId": "getCity",
137
        "tags": ["cities"],
138
        "parameters": [
139
          {
140
            "$ref": "#/parameters/cityidPathParam"
141
          }
142
        ],
143
        "produces": [
144
          "application/json"
145
        ],
146
        "responses": {
147
          "200": {
148
            "description": "A city",
149
            "schema": {
150
              "$ref": "#/definitions/city"
151
            }
152
          },
153
          "403": {
154
            "description": "Access forbidden",
155
            "schema": {
156
              "$ref": "#/definitions/error"
157
            }
158
          },
159
          "404": {
160
            "description": "City not found",
161
            "schema": {
162
              "$ref": "#/definitions/error"
163
            }
164
          }
165
        }
166
      },
167
      "put": {
168
        "x-mojo-controller": "Koha::REST::V1::Cities",
169
        "operationId": "updateCity",
170
        "tags": ["cities"],
171
        "parameters": [
172
          {
173
            "$ref": "#/parameters/cityBodyParam"
174
          }
175
        ],
176
        "produces": [
177
          "application/json"
178
        ],
179
        "responses": {
180
          "200": {
181
            "description": "A city",
182
            "schema": {
183
              "$ref": "#/definitions/city"
184
            }
185
          },
186
          "403": {
187
            "description": "Access forbidden",
188
            "schema": {
189
              "$ref": "#/definitions/error"
190
            }
191
          },
192
          "404": {
193
            "description": "City not found",
194
            "schema": {
195
              "$ref": "#/definitions/error"
196
            }
197
          }
198
        }
199
      },
200
      "delete": {
201
        "x-mojo-controller": "Koha::REST::V1::Cities",
202
        "operationId": "deleteCity",
203
        "tags": ["cities"],
204
        "parameters": [
205
          {
206
            "$ref": "#/parameters/cityidPathParam"
207
          }
208
        ],
209
        "produces": [
210
          "application/json"
211
        ],
212
        "responses": {
213
          "200": {
214
            "description": "City deleted",
215
            "schema": {
216
              "type": "string"
217
            }
218
          },
219
          "403": {
220
            "description": "Access forbidden",
221
            "schema": {
222
              "$ref": "#/definitions/error"
223
            }
224
          },
225
          "404": {
226
            "description": "City not found",
227
            "schema": {
228
              "$ref": "#/definitions/error"
229
            }
230
          }
231
        }
232
      }
78
    }
233
    }
79
  },
234
  },
80
  "definitions": {
235
  "definitions": {
Lines 106-111 Link Here
106
          "type": "string"
261
          "type": "string"
107
        }
262
        }
108
      }
263
      }
264
    },
265
    "city": {
266
      "type": "object",
267
      "properties": {
268
        "cityid": {
269
          "$ref": "#/definitions/cityid"
270
        },
271
        "city_name": {
272
          "description": "city name"
273
        },
274
        "city_state": {
275
          "description": "city state"
276
        },
277
        "city_zipcode": {
278
          "description": "city zipcode"
279
        },
280
        "city_country": {
281
          "description": "city country"
282
        }
283
      }
284
    },
285
    "cityid": {
286
      "description": "city id"
109
    }
287
    }
110
  },
288
  },
111
  "parameters": {
289
  "parameters": {
Lines 115-120 Link Here
115
      "description": "Internal borrower identifier",
293
      "description": "Internal borrower identifier",
116
      "required": "true",
294
      "required": "true",
117
      "type": "integer"
295
      "type": "integer"
296
    },
297
    "cityidPathParam": {
298
      "name": "cityid",
299
      "in": "path",
300
      "description": "City id",
301
      "required": "true",
302
      "type": "integer"
303
    },
304
    "cityBodyParam": {
305
      "name": "city",
306
      "in": "body",
307
      "description": "A JSON object representing a city",
308
      "required": "true",
309
      "schema": { "$ref": "#/definitions/city" }
118
    }
310
    }
119
  }
311
  }
120
}
312
}
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/cities.tt (-63 / +114 lines)
Lines 5-20 Link Here
5
[% INCLUDE 'datatables.inc' %]
5
[% INCLUDE 'datatables.inc' %]
6
<script type="text/javascript">
6
<script type="text/javascript">
7
//<![CDATA[
7
//<![CDATA[
8
    var aDataSet = [];
8
    $(document).ready(function() {
9
    $(document).ready(function() {
9
        $("#table_cities").dataTable($.extend(true, {}, dataTablesDefaults, {
10
10
            "aoColumnDefs": [
11
        var dtCityResults = $("#table_cities").dataTable($.extend(true, {}, dataTablesDefaults, {
11
                { "aTargets": [ -1, -2 ], "bSortable": false, "bSearchable": false },
12
            'bServerSide': true,
12
            ],
13
            'sAjaxSource': "/api/v1/cities",
13
            "aaSorting": [[ 1, "asc" ]],
14
            'fnServerData': function(sSource, aoData, fnCallback) {
14
            "iDisplayLength": 10,
15
                var echo = aoData[0].value;
15
            "sPaginationType": "full_numbers"
16
                $.ajax({
17
                    dataType: 'json',
18
                    type: 'GET',
19
                    url: sSource,
20
                    //data: aoData,
21
                    success: function(data){
22
                        aDataSet = [];
23
                        var json = {};
24
                        $.each(data, function() {
25
                            aDataSet.push([
26
                                this.cityid,
27
                                this.city_name,
28
                                this.city_state,
29
                                this.city_zipcode,
30
                                this.city_country,
31
                                "<a href='/cgi-bin/koha/admin/cities.pl?op=add_form&amp;cityid=" + this.cityid + "'>" + _("Edit") + "</a>",
32
                                "<a data-cityid='" + this.cityid + "' href='#'>" + _("Delete") + "</a>"
33
                            ]);
34
                        });
35
                        json.iTotalRecords = data.length;
36
                        json.iTotalDisplayRecords = data.length;
37
                        json.sEcho = echo;
38
                        json.aaData = aDataSet;
39
                        fnCallback(json);
40
                    }
41
                });
42
            },
43
            'fnRowCallback': function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
44
                $("td:eq(6)", nRow).find('a').on('click', function() {
45
                    return delete_city($(this).attr('data-cityid'));
46
                });
47
            },
48
            // Should add filter/search/pagination
49
            // Not supported yet
50
            'bAutoWidth': false,
51
            'bPaginate': false,
52
            'bSort': false,
53
            'bFilter': false
16
        }));
54
        }));
55
56
        $("#add_city").on('submit', function(e){
57
            e.preventDefault();
58
            var city = {
59
                cityid: $("#cityid").val(),
60
                city_name: $("#city_name").val(),
61
                city_state: $("#city_state").val(),
62
                city_zipcode: $("#city_zipcode").val(),
63
                city_country: $("#city_country").val()
64
            };
65
            // Double check on required fields should be avoided
66
            if ( !city.city_name || !city.city_zipcode ) return;
67
            cityid ? update_city(city) : add_city(city);
68
        });
17
    });
69
    });
70
71
    // The 3 functions should be extracted somewhere else
72
    function update_city(city) {
73
        $.ajax({
74
            type: 'PUT',
75
            url: '/api/v1/cities/' + city.cityid,
76
            data: JSON.stringify(city),
77
            success: function(data){
78
                // Need a better way to redirect, we would like to inform the user that the action succeeded
79
                window.location.href='/cgi-bin/koha/admin/cities.pl';
80
            },
81
            error: function(data){
82
                // Need a better way to inform the user that the action has failed
83
                alert(data);
84
            }
85
        });
86
    }
87
    function add_city(city) {
88
        $.ajax({
89
            type: 'PUT',
90
            url: '/api/v1/cities',
91
            data: JSON.stringify(city),
92
            success: function(data){
93
                window.location.href='/cgi-bin/koha/admin/cities.pl';
94
            },
95
            error: function(data){
96
                alert(data);
97
            }
98
        });
99
    }
100
    function delete_city(cityid) {
101
        if ( confirm(_("Are you sure you want to delete this city?")) ) {
102
            $.ajax({
103
                type: 'DELETE',
104
                url: '/api/v1/cities/' + cityid,
105
                success: function(data){
106
                    window.location.href='/cgi-bin/koha/admin/cities.pl';
107
                },
108
                error: function(data){
109
                    alert(data);
110
                }
111
            })
112
        }
113
    }
18
//]]>
114
//]]>
19
</script>
115
</script>
20
</head>
116
</head>
Lines 39-59 Link Here
39
    <div id="yui-main">
135
    <div id="yui-main">
40
    <div class="yui-b">
136
    <div class="yui-b">
41
137
42
[% FOR m IN messages %]
138
[% IF message %]
43
    <div class="dialog [% m.type %]">
139
    <div class="dialog message">
44
        [% SWITCH m.code %]
140
    [% SWITCH message %]
45
        [% CASE 'error_on_update' %]
141
        [% CASE 'updated' %]
46
            An error occurred when updating this city. Perhaps it already exists.
142
            City updated successfully.
143
        [% CASE 'added' %]
144
            City added successfully.
145
        [% CASE 'deleted' %]
146
            City deleted successfully.
47
        [% CASE 'error_on_insert' %]
147
        [% CASE 'error_on_insert' %]
48
            An error occurred when adding this city. The city id might already exist.
148
            An error occurred when adding this city. The city id might already exist.
49
        [% CASE 'error_on_delete' %]
149
        [% CASE 'error_on_delete' %]
50
            An error occurred when deleting this city. Check the logs.
150
            An error occurred when deleting this city. Check the logs.
51
        [% CASE 'success_on_update' %]
52
            City updated successfully.
53
        [% CASE 'success_on_insert' %]
54
            City added successfully.
55
        [% CASE 'success_on_delete' %]
56
            City deleted successfully.
57
        [% CASE 'already_exists' %]
151
        [% CASE 'already_exists' %]
58
            This city already exists.
152
            This city already exists.
59
        [% CASE %]
153
        [% CASE %]
Lines 69-77 Link Here
69
        <h1>New city</h1>
163
        <h1>New city</h1>
70
    [% END %]
164
    [% END %]
71
165
72
    <form action="/cgi-bin/koha/admin/cities.pl" name="Aform" method="post" class="validated">
166
    <form id="add_city" action="/cgi-bin/koha/admin/cities.pl" name="Aform" method="post" class="validated">
73
        <input type="hidden" name="op" value="add_validate" />
167
        <input type="hidden" name="op" value="add_validate" />
74
        <input type="hidden" name="cityid" value="[% city.cityid %]" />
168
        <input type="hidden" name="cityid" id="cityid" value="[% city.cityid %]" />
75
169
76
        <fieldset class="rows">
170
        <fieldset class="rows">
77
            <ol>
171
            <ol>
Lines 104-140 Link Here
104
    </form>
198
    </form>
105
[% END %]
199
[% END %]
106
200
107
[% IF op == 'delete_confirm' %]
108
    <div class="dialog alert">
109
        <h3>Delete City "[% city.city_name %]?"</h3>
110
        <table>
111
            <tr><th>City id</th>
112
                <td>[% city.cityid %]</td>
113
            </tr>
114
            <tr><th>City</th>
115
                <td>[% city.city_name %]</td>
116
            </tr>
117
            <tr><th>State</th>
118
                <td>[% city.city_state %]</td>
119
            </tr>
120
            <tr><th>Zip/Postal code</th>
121
                <td>[% city.city_zipcode %]</td>
122
            </tr>
123
            <tr><th>Country</th>
124
                <td>[% city.city_country %]</td>
125
            </tr>
126
        </table>
127
        <form action="/cgi-bin/koha/admin/cities.pl" method="post">
128
            <input type="hidden" name="op" value="delete_confirmed" />
129
            <input type="hidden" name="cityid" value="[% city.cityid %]" />
130
            <input type="submit" class="approve" value="Yes, delete" />
131
        </form>
132
        <form action="/cgi-bin/koha/admin/cities.pl" method="get">
133
            <input type="submit" class="deny" value="No, do not Delete" />
134
        </form>
135
    </div>
136
[% END %]
137
138
[% IF op == 'list' %]
201
[% IF op == 'list' %]
139
202
140
    <div id="toolbar" class="btn-toolbar">
203
    <div id="toolbar" class="btn-toolbar">
Lines 158-174 Link Here
158
                <th>&nbsp;</th>
221
                <th>&nbsp;</th>
159
            </thead>
222
            </thead>
160
            <tbody>
223
            <tbody>
161
                [% FOREACH city IN cities %]
162
                <tr>
163
                    <td>[% city.cityid %]</td>
164
                    <td>[% city.city_name %]</td>
165
                    <td>[% city.city_state %]</td>
166
                    <td>[% city.city_zipcode %]</td>
167
                    <td>[% city.city_country %]</td>
168
                    <td><a href="/cgi-bin/koha/admin/cities.pl?op=add_form&amp;cityid=[% city.cityid %]">Edit</a></td>
169
                    <td><a href="/cgi-bin/koha/admin/cities.pl?op=delete_confirm&amp;cityid=[% city.cityid %]">Delete</a></td>
170
                </tr>
171
                [% END %]
172
            </tbody>
224
            </tbody>
173
        </table>
225
        </table>
174
    [% ELSE %]
226
    [% ELSE %]
175
- 

Return to bug 14974