Skip to content

Commit

Permalink
Merge pull request #36 from developmentseed/enhance/photo-to-osm-element
Browse files Browse the repository at this point in the history
Set one-to-many relation between photos and OSM elements (and other changes)
  • Loading branch information
vgeorge authored Nov 26, 2019
2 parents f9db9e9 + 0a51bbb commit 3fa519b
Show file tree
Hide file tree
Showing 20 changed files with 136 additions and 63 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ Open a new terminal and migrate the database:

npm run migrate-dev-db

Add mock users, traces and photos for testing:

npm run seed-dev

Start development server with changes monitoring:

npm run dev
Expand Down
6 changes: 3 additions & 3 deletions app/models/photos.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function select () {
'bearing',
'createdAt',
'description',
'osmObjects',
'osmElement',
'ownerId',
'uploadedAt',
'users.osmDisplayName as ownerDisplayName'
Expand Down Expand Up @@ -64,7 +64,7 @@ export async function getPhoto (id) {
*/
export async function createPhoto (data) {
const id = generateId();
const { file, ownerId, lon, lat, bearing, createdAt, osmObjects } = data;
const { file, ownerId, lon, lat, bearing, createdAt, osmElement } = data;

// Save media to file store
await persistImageBase64(id, file, {
Expand All @@ -81,7 +81,7 @@ export async function createPhoto (data) {
location: `POINT(${lon} ${lat})`,
bearing,
createdAt,
osmObjects
osmElement
});

// Load inserted photo
Expand Down
6 changes: 3 additions & 3 deletions app/models/utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import nanoid from 'nanoid';
import config from 'config';
import generate from 'nanoid/generate';

const idLength = config.get('idLength');
const { length, alphabet } = config.get('elementIds');

export function generateId () {
return nanoid(idLength);
return generate(alphabet, length);
}
4 changes: 2 additions & 2 deletions app/routes/photos/del.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Joi from '@hapi/joi';
import logger from '../../services/logger';
import { deletePhoto, getPhoto } from '../../models/photos';

const idLength = config.get('idLength');
const elementIds = config.get('elementIds');

/**
* @apiGroup Photos
Expand All @@ -26,7 +26,7 @@ export default [
auth: 'jwt',
validate: {
params: Joi.object({
id: Joi.string().length(idLength)
id: Joi.string().length(elementIds.length)
})
},
handler: async function (request) {
Expand Down
4 changes: 2 additions & 2 deletions app/routes/photos/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Joi from '@hapi/joi';
import { getPhoto } from '../../models/photos';
import logger from '../../services/logger';

const idLength = config.get('idLength');
const elementIds = config.get('elementIds');

/**
* @apiGroup Photos
Expand All @@ -24,7 +24,7 @@ export default [
auth: 'jwt',
validate: {
params: Joi.object({
id: Joi.string().length(idLength)
id: Joi.string().length(elementIds.length)
})
}
},
Expand Down
8 changes: 4 additions & 4 deletions app/routes/photos/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import { getPhoto, updatePhoto } from '../../models/photos';
* @apiParam {string} description Description.
* @apiParam {float} lon Longitude.
* @apiParam {float} lat Latitude.
* @apiParam {object} osmObjects Array of OpenStreetMap ids.
* @apiParam {string} osmElement OpenStreetMap id of photographed element.
* @apiParamExample {json} Example:
* {
* osmObjects: ['way/677949489', 'node/677949489', 'relation/10230293']
* osmElement: 'way/677949489'
* }
*
* @apiUse AuthorizationHeader
Expand All @@ -44,8 +44,8 @@ export default [
lat: Joi.number()
.min(-90)
.max(90),
osmObjects: Joi.array()
.items(Joi.string().pattern(/^(node|way|relation)\/[0-9]+$/))
osmElement: Joi.string()
.pattern(/^(node|way|relation)\/[0-9]+$/)
.optional()
}).required()
},
Expand Down
8 changes: 4 additions & 4 deletions app/routes/photos/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import { createPhoto } from '../../models/photos';
* @apiParam {string} description Description.
* @apiParam {float} lon Longitude.
* @apiParam {float} lat Latitude.
* @apiParam {object} osmObjects Array of OpenStreetMap ids.
* @apiParam {string} osmElement OpenStreetMap id of photographed element..
* @apiParamExample {json} Example:
* {
* osmObjects: ['way/677949489', 'node/677949489', 'relation/10230293']
* osmElement: 'way/677949489'
* }
*
* @apiUse AuthorizationHeader
Expand Down Expand Up @@ -55,8 +55,8 @@ export default [
file: Joi.string()
.base64()
.required(),
osmObjects: Joi.array()
.items(Joi.string().pattern(/^(node|way|relation)\/[0-9]+$/))
osmElement: Joi.string()
.pattern(/^(node|way|relation)\/[0-9]+$/)
.optional()
}).required()
},
Expand Down
4 changes: 2 additions & 2 deletions app/routes/traces/del.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Joi from '@hapi/joi';
import logger from '../../services/logger';
import { getTrace, deleteTrace } from '../../models/traces';

const idLength = config.get('idLength');
const elementIds = config.get('elementIds');

/**
* @apiGroup Traces
Expand All @@ -26,7 +26,7 @@ export default [
auth: 'jwt',
validate: {
params: Joi.object({
id: Joi.string().length(idLength)
id: Joi.string().length(elementIds.length)
})
},
handler: async function (request) {
Expand Down
4 changes: 2 additions & 2 deletions app/routes/traces/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import logger from '../../services/logger';
import config from 'config';
import togpx from 'togpx';

const idLength = config.get('idLength');
const elementIds = config.get('elementIds');

const validate = {
params: Joi.object({
id: Joi.string().length(idLength)
id: Joi.string().length(elementIds.length)
})
};

Expand Down
4 changes: 2 additions & 2 deletions app/routes/traces/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import logger from '../../services/logger';
import { getTrace, updateTrace } from '../../models/traces';
import config from 'config';

const idLength = config.get('idLength');
const elementIds = config.get('elementIds');

/**
* @apiGroup Traces
Expand All @@ -28,7 +28,7 @@ export default [
auth: 'jwt',
validate: {
params: Joi.object({
id: Joi.string().length(idLength)
id: Joi.string().length(elementIds.length)
}),
payload: Joi.object({
description: Joi.string().empty('')
Expand Down
4 changes: 2 additions & 2 deletions app/services/media-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ export async function persistImageBase64 (name, data, meta) {

// Write resized files
for (let i = 0; i < sizes.length; i++) {
const { width, height, id } = sizes[i];
const { id, width, height, fit } = sizes[i];
const resizedFilePath = `${baseFilePath}-${id}.jpg`;
await sharp(originalFilePath)
.withMetadata()
.resize(width, height, { fit: 'inside' })
.resize(width, height, { fit })
.toFile(resizedFilePath);
}
} finally {
Expand Down
14 changes: 12 additions & 2 deletions config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
"pagination": {
"limit": 15
},
"idLength": 10,
"elementIds": {
"length": 15,
"alphabet": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
},
"osmOAuth": {
"requestTokenUrl": "https://master.apis.dev.openstreetmap.org/oauth/request_token",
"accessTokenUrl": "https://master.apis.dev.openstreetmap.org/oauth/access_token",
Expand All @@ -26,7 +29,14 @@
{
"id": "default",
"width": 800,
"height": 600
"height": 600,
"fit": "inside"
},
{
"id": "full",
"width": 1200,
"height": 1200,
"fit": "inside"
}
]
}
Expand Down
13 changes: 13 additions & 0 deletions migrations/20191125144019_change-photo-osm-element.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
exports.up = function (knex) {
return knex.schema.table('photos', function (t) {
t.dropColumn('osmObjects');
t.string('osmElement');
});
};

exports.down = function (knex) {
return knex.schema.table('photos', function (t) {
t.dropColumn('osmElement');
t.specificType('osmObjects', 'text[]');
});
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"lint": "node_modules/.bin/eslint app/ test/ --ext .js",
"test": "NODE_ENV=test mocha -r esm test/test--index.js",
"start-dev-db": "docker-compose -f docker-compose-dev.yml up",
"seed-dev": "NODE_ENV=development node_modules/.bin/knex seed:run",
"start-test-db": "docker-compose -f docker-compose-test.yml up",
"migrate-dev-db": "NODE_ENV=development node_modules/.bin/knex migrate:latest",
"test-lint": "npm run lint && npm run test",
Expand Down
18 changes: 18 additions & 0 deletions seeds/1-users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Enable ECMAScript module loader
require = require("esm")(module); // eslint-disable-line

const { createMockUser } = require('../test/utils/mock-factory');

exports.seed = async function (knex) {
console.log('Seeding users...') // eslint-disable-line

// Create 5 admins
for (let i = 0; i < 5; i++) {
await createMockUser({ isAdmin: true });
}

// Create more 45 users
for (let i = 0; i < 45; i++) {
await createMockUser();
}
};
21 changes: 21 additions & 0 deletions seeds/2-photos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Enable ECMAScript module loader
require = require("esm")(module); // eslint-disable-line

const { createMockPhoto, getRandomInt } = require('../test/utils/mock-factory');

exports.seed = async function (knex) {
console.log('Seeding photos...') // eslint-disable-line

const users = await knex('users').select('osmId');

const totalUsers = users.length;

if (users.length === 0) {
throw Error('No users found. Please login to create a user to associate mock data.');
}

for (let i = 0; i < 50; i++) {
const user = users[getRandomInt(totalUsers)];
await createMockPhoto({ osmId: user.osmId });
}
};
21 changes: 21 additions & 0 deletions seeds/3-traces.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Enable ECMAScript module loader
require = require("esm")(module); // eslint-disable-line

const { createMockTrace, getRandomInt } = require('../test/utils/mock-factory');

exports.seed = async function (knex) {
console.log('Seeding traces...') // eslint-disable-line

const users = await knex('users').select('osmId');

const totalUsers = users.length;

if (users.length === 0) {
throw Error('No users found. Please login to create a user to associate mock data.');
}

for (let i = 0; i < 50; i++) {
const user = users[getRandomInt(totalUsers)];
await createMockTrace({ osmId: user.osmId });
}
};
Loading

0 comments on commit 3fa519b

Please sign in to comment.