From d396d33506614f7267f966f9ad8ead34e2996171 Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Fri, 16 Jun 2017 16:56:59 +0200 Subject: [PATCH] Rewrite doc and frontend to match new constraints in config --- doc/0.getting_started.md | 31 ++++++------------- flatisfy/filters/metadata.py | 4 +-- flatisfy/models/flat.py | 3 ++ flatisfy/web/app.py | 3 +- flatisfy/web/js_src/api/index.js | 2 +- flatisfy/web/js_src/store/getters.js | 15 ++++++++- flatisfy/web/js_src/views/details.vue | 6 ++-- flatisfy/web/routes/api.py | 44 ++++++++++++++++++--------- 8 files changed, 63 insertions(+), 45 deletions(-) diff --git a/doc/0.getting_started.md b/doc/0.getting_started.md index f1a459f..84c083f 100644 --- a/doc/0.getting_started.md +++ b/doc/0.getting_started.md @@ -124,31 +124,18 @@ under the `constraints` key. The available constraints are: form. Beware that `time` constraints are in **seconds**. +You can think of constraints as "a set of criterias to filter out flats". You +can specify as many constraints as you want, in the configuration file, +provided that you name each of them uniquely. + +Note that it is mandatory to keep a constraint called `default`, which will be +the default constraint use for refiltering flats already imported with a +constraint that you deleted after the import. + + ## Building the web assets If you want to build the web assets, you can use `npm run build:dev` (respectively `npm run watch:dev` to build continuously and monitor changes in source files). You can use `npm run build:prod` (`npm run watch:prod`) to do the same in production mode (with minification etc). - - -## Tips - -### Running with multiple configs - -Let's say you are looking for a place in different places far apart (e.g. both -a house in the country for the weekends and a place in a city for the week), -you can use multiple configuration file (in this case, two configuration -files) to define everything. - -Indeed, `serve` command for the web app only use a subset of the -configuration, basically only the `data_directory`, `database` URI and so on. -So, you are free to use any config file for `serve` command and still run -`import` commands multiple times with different configuration files, for -different housing queries. - -This is kind of a hack on the current system, but is working! - -*Note*: You can also use this tip if you are living in a city split across -multiple postal codes and want to implement constraints such as "close to -place X if postal code is Y". diff --git a/flatisfy/filters/metadata.py b/flatisfy/filters/metadata.py index 20c22cd..7e793df 100644 --- a/flatisfy/filters/metadata.py +++ b/flatisfy/filters/metadata.py @@ -33,6 +33,8 @@ def init(flats_list, constraint): # Init flatisfy key if "flatisfy" not in flat: flat["flatisfy"] = {} + if "constraint" not in flat["flatisfy"]: + flat["flatisfy"]["constraint"] = constraint # Move url key to urls if "urls" not in flat: if "url" in flat: @@ -42,8 +44,6 @@ def init(flats_list, constraint): # Create merged_ids key if "merged_ids" not in flat: flat["merged_ids"] = [flat["id"]] - if "constraint" not in flat: - flat["constraint"] = constraint return flats_list diff --git a/flatisfy/models/flat.py b/flatisfy/models/flat.py index 71de109..87c0fd7 100644 --- a/flatisfy/models/flat.py +++ b/flatisfy/models/flat.py @@ -109,6 +109,9 @@ class Flat(BASE): flat_dict["flatisfy_time_to"] = ( flat_dict["flatisfy"].get("time_to", {}) ) + flat_dict["flatisfy_constraint"] = ( + flat_dict["flatisfy"].get("constraint", "default") + ) del flat_dict["flatisfy"] # Handle utilities field diff --git a/flatisfy/web/app.py b/flatisfy/web/app.py index 0428d58..8dfea39 100644 --- a/flatisfy/web/app.py +++ b/flatisfy/web/app.py @@ -69,7 +69,8 @@ def get_app(config): # API v1 routes app.route("/api/v1/", "GET", api_routes.index_v1) - app.route("/api/v1/time_to/places", "GET", api_routes.time_to_places_v1) + app.route("/api/v1/time_to_places", "GET", + api_routes.time_to_places_v1) app.route("/api/v1/flats", "GET", api_routes.flats_v1) app.route("/api/v1/flats/status/:status", "GET", diff --git a/flatisfy/web/js_src/api/index.js b/flatisfy/web/js_src/api/index.js index 4dfbba8..a9c6ea5 100644 --- a/flatisfy/web/js_src/api/index.js +++ b/flatisfy/web/js_src/api/index.js @@ -107,7 +107,7 @@ export const updateFlatNotation = function (flatId, newNotation, callback) { } export const getTimeToPlaces = function (callback) { - fetch('/api/v1/time_to/places', { credentials: 'same-origin' }) + fetch('/api/v1/time_to_places', { credentials: 'same-origin' }) .then(function (response) { return response.json() }).then(function (json) { diff --git a/flatisfy/web/js_src/store/getters.js b/flatisfy/web/js_src/store/getters.js index c5b1f1c..3a8691e 100644 --- a/flatisfy/web/js_src/store/getters.js +++ b/flatisfy/web/js_src/store/getters.js @@ -54,5 +54,18 @@ export default { return markers }, - allTimeToPlaces: state => state.timeToPlaces + allTimeToPlaces: state => { + let places = {} + Object.keys(state.timeToPlaces).forEach(constraint => { + let constraintTimeToPlaces = state.timeToPlaces[constraint] + Object.keys(constraintTimeToPlaces).forEach(name => + places[name] = constraintTimeToPlaces[name] + ) + }) + return places + }, + + timeToPlaces: (state, getters) => (constraint_name) => { + return state.timeToPlaces[constraint_name] + }, } diff --git a/flatisfy/web/js_src/views/details.vue b/flatisfy/web/js_src/views/details.vue index 9d42bb6..5f4b094 100644 --- a/flatisfy/web/js_src/views/details.vue +++ b/flatisfy/web/js_src/views/details.vue @@ -222,12 +222,12 @@ export default { flatMarkers () { return this.$store.getters.flatsMarkers(this.$router, flat => flat.id === this.$route.params.id) }, - timeToPlaces () { - return this.$store.getters.allTimeToPlaces - }, flat () { return this.$store.getters.flat(this.$route.params.id) }, + timeToPlaces () { + return this.$store.getters.timeToPlaces(this.flat.flatisfy_constraint) + }, notation () { if (this.overloadNotation) { return this.overloadNotation diff --git a/flatisfy/web/routes/api.py b/flatisfy/web/routes/api.py index e851922..88f40dc 100644 --- a/flatisfy/web/routes/api.py +++ b/flatisfy/web/routes/api.py @@ -39,7 +39,11 @@ def flats_v1(config, db): :return: The available flats objects in a JSON ``data`` dict. """ - postal_codes = flatisfy.data.load_data(PostalCode, config) # TODO + postal_codes = {} + for constraint_name, constraint in config["constraints"].items(): + postal_codes[constraint_name] = flatisfy.data.load_data( + PostalCode, constraint, config + ) flats = [ flat.json_api_repr() @@ -50,13 +54,14 @@ def flats_v1(config, db): if flat["flatisfy_postal_code"]: postal_code_data = next( x - for x in postal_codes + for x in postal_codes.get(flat["flatisfy_constraint"], + postal_codes["default"]) if x.postal_code == flat["flatisfy_postal_code"] ) flat["flatisfy_postal_code"] = { "postal_code": flat["flatisfy_postal_code"], - "name": postal_code_data["name"], - "gps": (postal_code_data["lat"], postal_code_data["lng"]) + "name": postal_code_data.name, + "gps": (postal_code_data.lat, postal_code_data.lng) } else: flat["flatisfy_postal_code"] = {} @@ -99,10 +104,12 @@ def flat_v1(flat_id, config, db): :return: The flat object in a JSON ``data`` dict. """ - postal_codes = flatisfy.data.load_data(PostalCode, config) # TODO - flat = db.query(flat_model.Flat).filter_by(id=flat_id).first() + constraint = config["constraints"].get(flat.flatisfy_constraint, + config["constraints"]["default"]) + postal_codes = flatisfy.data.load_data(PostalCode, constraint, config) + if not flat: return bottle.HTTPError(404, "No flat with id {}.".format(flat_id)) @@ -116,8 +123,8 @@ def flat_v1(flat_id, config, db): ) flat["flatisfy_postal_code"] = { "postal_code": flat["flatisfy_postal_code"], - "name": postal_code_data["name"], - "gps": (postal_code_data["lat"], postal_code_data["lng"]) + "name": postal_code_data.name, + "gps": (postal_code_data.lat, postal_code_data.lng) } else: flat["flatisfy_postal_code"] = {} @@ -215,15 +222,17 @@ def time_to_places_v1(config): """ API v1 route to fetch the details of the places to compute time to. - GET /api/v1/time_to/places + GET /api/v1/time_to_places :return: The JSON dump of the places to compute time to (dict of places names mapped to GPS coordinates). """ - places = { - k: v["gps"] - for k, v in config["constraints"]["time_to"].items() # TODO: Constraints should be named and stored in db along flats - } + places = {} + for constraint_name, constraint in config["constraints"].items(): + places[constraint_name] = { + k: v["gps"] + for k, v in constraint["time_to"].items() + } return { "data": places } @@ -240,7 +249,11 @@ def search_v1(db, config): :return: The matching flat objects in a JSON ``data`` dict. """ - postal_codes = flatisfy.data.load_data(PostalCode, config) # TODO + postal_codes = {} + for constraint_name, constraint in config["constraints"].items(): + postal_codes[constraint_name] = flatisfy.data.load_data( + PostalCode, constraint, config + ) try: query = json.load(bottle.request.body)["query"] @@ -257,7 +270,8 @@ def search_v1(db, config): if flat["flatisfy_postal_code"]: postal_code_data = next( x - for x in postal_codes + for x in postal_codes.get(flat["flatisfy_constraint"], + postal_codes["default"]) if x.postal_code == flat["flatisfy_postal_code"] ) flat["flatisfy_postal_code"] = {