-
Notifications
You must be signed in to change notification settings - Fork 6.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #122 from GoogleCloudPlatform/angular
Move over appengine-angular-hello-world-python
- Loading branch information
Showing
12 changed files
with
438 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
## App Engine AngularJS "Hello World" Python | ||
|
||
A simple [AngularJS](http://angularjs.org/) CRUD application | ||
for [Google App Engine](https://appengine.google.com/). | ||
|
||
Author: Fred Sauer <[email protected]> | ||
|
||
|
||
## Project setup | ||
|
||
1. Install the [App Engine Python SDK](https://developers.google.com/appengine/downloads) | ||
|
||
|
||
## Testing the app locally | ||
|
||
To run the app locally: | ||
|
||
``` | ||
dev_appserver.py . | ||
``` | ||
|
||
|
||
## Deploying | ||
|
||
To deploy the application: | ||
|
||
1. Use the [Google Cloud Console](https://cloud.google.com/console) to create a project | ||
1. Replace `your-app-id` in `app.yaml` with the project id from the previous step | ||
1. Deploy the application: | ||
|
||
``` | ||
appcfg.py --oauth2 update . | ||
``` | ||
|
||
|
||
## Contributing changes | ||
|
||
See [CONTRIB.md](CONTRIB.md) | ||
|
||
|
||
# Licensing | ||
|
||
See [LICENSE](LICENSE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
application: your-app-id | ||
version: 1 | ||
runtime: python27 | ||
threadsafe: true | ||
api_version: 1 | ||
|
||
handlers: | ||
- url: /favicon\.ico | ||
static_files: favicon.ico | ||
upload: favicon\.ico | ||
|
||
- url: /rest/.* | ||
script: main.APP | ||
|
||
- url: (.*)/ | ||
static_files: app\1/index.html | ||
upload: app | ||
|
||
- url: (.*) | ||
static_files: app\1 | ||
upload: app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
.status { | ||
color: blue; | ||
padding: 1em; | ||
height: 1em; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<!doctype html> | ||
<html ng-app="App"> | ||
<head> | ||
<link rel="stylesheet" href="/css/app.css"> | ||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.3/angular.js"></script> | ||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.3/angular-route.js"></script> | ||
<script src="/js/app.js"></script> | ||
</head> | ||
<body> | ||
<h1>AngularJS Guest List</h1> | ||
<pre class="status" ng-bind="status"></pre> | ||
<div ng-view></div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
'use strict'; | ||
|
||
var App = angular.module('App', ['ngRoute']); | ||
|
||
App.factory('myHttpInterceptor', function($rootScope, $q) { | ||
return { | ||
'requestError': function(config) { | ||
$rootScope.status = 'HTTP REQUEST ERROR ' + config; | ||
return config || $q.when(config); | ||
}, | ||
'responseError': function(rejection) { | ||
$rootScope.status = 'HTTP RESPONSE ERROR ' + rejection.status + '\n' + | ||
rejection.data; | ||
return $q.reject(rejection); | ||
}, | ||
}; | ||
}); | ||
|
||
App.factory('guestService', function($rootScope, $http, $q, $log) { | ||
$rootScope.status = 'Retrieving data...'; | ||
var deferred = $q.defer(); | ||
$http.get('rest/query') | ||
.success(function(data, status, headers, config) { | ||
$rootScope.guests = data; | ||
deferred.resolve(); | ||
$rootScope.status = ''; | ||
}); | ||
return deferred.promise; | ||
}); | ||
|
||
App.config(function($routeProvider) { | ||
$routeProvider.when('/', { | ||
controller : 'MainCtrl', | ||
templateUrl: '/partials/main.html', | ||
resolve : { 'guestService': 'guestService' }, | ||
}); | ||
$routeProvider.when('/invite', { | ||
controller : 'InsertCtrl', | ||
templateUrl: '/partials/insert.html', | ||
}); | ||
$routeProvider.when('/update/:id', { | ||
controller : 'UpdateCtrl', | ||
templateUrl: '/partials/update.html', | ||
resolve : { 'guestService': 'guestService' }, | ||
}); | ||
$routeProvider.otherwise({ | ||
redirectTo : '/' | ||
}); | ||
}); | ||
|
||
App.config(function($httpProvider) { | ||
$httpProvider.interceptors.push('myHttpInterceptor'); | ||
}); | ||
|
||
App.controller('MainCtrl', function($scope, $rootScope, $log, $http, $routeParams, $location, $route) { | ||
|
||
$scope.invite = function() { | ||
$location.path('/invite'); | ||
}; | ||
|
||
$scope.update = function(guest) { | ||
$location.path('/update/' + guest.id); | ||
}; | ||
|
||
$scope.delete = function(guest) { | ||
$rootScope.status = 'Deleting guest ' + guest.id + '...'; | ||
$http.post('/rest/delete', {'id': guest.id}) | ||
.success(function(data, status, headers, config) { | ||
for (var i=0; i<$rootScope.guests.length; i++) { | ||
if ($rootScope.guests[i].id == guest.id) { | ||
$rootScope.guests.splice(i, 1); | ||
break; | ||
} | ||
} | ||
$rootScope.status = ''; | ||
}); | ||
}; | ||
|
||
}); | ||
|
||
App.controller('InsertCtrl', function($scope, $rootScope, $log, $http, $routeParams, $location, $route) { | ||
|
||
$scope.submitInsert = function() { | ||
var guest = { | ||
first : $scope.first, | ||
last : $scope.last, | ||
}; | ||
$rootScope.status = 'Creating...'; | ||
$http.post('/rest/insert', guest) | ||
.success(function(data, status, headers, config) { | ||
$rootScope.guests.push(data); | ||
$rootScope.status = ''; | ||
}); | ||
$location.path('/'); | ||
} | ||
}); | ||
|
||
App.controller('UpdateCtrl', function($routeParams, $rootScope, $scope, $log, $http, $location) { | ||
|
||
for (var i=0; i<$rootScope.guests.length; i++) { | ||
if ($rootScope.guests[i].id == $routeParams.id) { | ||
$scope.guest = angular.copy($rootScope.guests[i]); | ||
} | ||
} | ||
|
||
$scope.submitUpdate = function() { | ||
$rootScope.status = 'Updating...'; | ||
$http.post('/rest/update', $scope.guest) | ||
.success(function(data, status, headers, config) { | ||
for (var i=0; i<$rootScope.guests.length; i++) { | ||
if ($rootScope.guests[i].id == $scope.guest.id) { | ||
$rootScope.guests.splice(i,1); | ||
break; | ||
} | ||
} | ||
$rootScope.guests.push(data); | ||
$rootScope.status = ''; | ||
}); | ||
$location.path('/'); | ||
}; | ||
|
||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<h2>Invite another guest</h2> | ||
<form ng-submit="submitInsert()"> | ||
<p> | ||
<label>First:</label> | ||
<input type="text" ng-model="first" autofocus="true" /> | ||
</p> | ||
<p> | ||
<label>Last:</label> | ||
<input type="text" ng-model="last" /> | ||
</p> | ||
<input type="submit" class="btn" /> | ||
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<h2>Guest list</h2> | ||
<button ng-click="invite()">Invite another guest</button> | ||
<div ng-repeat="guest in guests | orderBy:'last' | orderBy:'first'"> | ||
<button ng-click="delete(guest)">delete</button> | ||
<button ng-click="update(guest)">update</button> | ||
{{ $index + 1 }}. <b>{{ guest.first }} {{ guest.last }}</b> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<h2>Update guest information</h2> | ||
<form ng-submit="submitUpdate()"> | ||
<p> | ||
<label>Id:</label> | ||
<input type="text" ng-model="guest.id" disabled="true" /> | ||
</p> | ||
<p> | ||
<label>First:</label> | ||
<input type="text" ng-model="guest.first" autofocus="true" /> | ||
</p> | ||
<p> | ||
<label>Last:</label> | ||
<input type="text" ng-model="guest.last" /> | ||
</p> | ||
<input type="submit" class="btn" /> | ||
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Copyright 2013 Google, Inc | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import json | ||
|
||
import model | ||
|
||
import webapp2 | ||
|
||
|
||
def AsDict(guest): | ||
return {'id': guest.key.id(), 'first': guest.first, 'last': guest.last} | ||
|
||
|
||
class RestHandler(webapp2.RequestHandler): | ||
|
||
def dispatch(self): | ||
# time.sleep(1) | ||
super(RestHandler, self).dispatch() | ||
|
||
def SendJson(self, r): | ||
self.response.headers['content-type'] = 'text/plain' | ||
self.response.write(json.dumps(r)) | ||
|
||
|
||
class QueryHandler(RestHandler): | ||
|
||
def get(self): | ||
guests = model.AllGuests() | ||
r = [AsDict(guest) for guest in guests] | ||
self.SendJson(r) | ||
|
||
|
||
class UpdateHandler(RestHandler): | ||
|
||
def post(self): | ||
r = json.loads(self.request.body) | ||
guest = model.UpdateGuest(r['id'], r['first'], r['last']) | ||
r = AsDict(guest) | ||
self.SendJson(r) | ||
|
||
|
||
class InsertHandler(RestHandler): | ||
|
||
def post(self): | ||
r = json.loads(self.request.body) | ||
guest = model.InsertGuest(r['first'], r['last']) | ||
r = AsDict(guest) | ||
self.SendJson(r) | ||
|
||
|
||
class DeleteHandler(RestHandler): | ||
|
||
def post(self): | ||
r = json.loads(self.request.body) | ||
model.DeleteGuest(r['id']) | ||
|
||
|
||
APP = webapp2.WSGIApplication([ | ||
('/rest/query', QueryHandler), | ||
('/rest/insert', InsertHandler), | ||
('/rest/delete', DeleteHandler), | ||
('/rest/update', UpdateHandler), | ||
], debug=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Copyright 2013 Google, Inc | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from google.appengine.ext import ndb | ||
|
||
|
||
class Guest(ndb.Model): | ||
first = ndb.StringProperty() | ||
last = ndb.StringProperty() | ||
|
||
|
||
def AllGuests(): | ||
return Guest.query() | ||
|
||
|
||
def UpdateGuest(id, first, last): | ||
guest = Guest(id=id, first=first, last=last) | ||
guest.put() | ||
return guest | ||
|
||
|
||
def InsertGuest(first, last): | ||
guest = Guest(first=first, last=last) | ||
guest.put() | ||
return guest | ||
|
||
|
||
def DeleteGuest(id): | ||
key = ndb.Key(Guest, id) | ||
key.delete() |
Oops, something went wrong.