mirror of
https://github.com/bellingcat/datasheet-server.git
synced 2026-06-11 12:58:32 +03:00
Compare commits
9 Commits
v0.5.0
...
feature/ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5d922ef16 | ||
|
|
1971128b18 | ||
|
|
fba74d8e9c | ||
|
|
f3115007e2 | ||
|
|
70149b905f | ||
|
|
afa52bffb6 | ||
|
|
533ab6e6f9 | ||
|
|
d06f4a5b68 | ||
|
|
95cb7a6f80 |
@@ -53,7 +53,7 @@ Each Google Sheet being used as a as source requires a corresponding object in `
|
|||||||
See src/config.js for an example configuration sheet.
|
See src/config.js for an example configuration sheet.
|
||||||
|
|
||||||
|
|
||||||
## [Quickstart](#quickstart)
|
## [Quickstart](#quickstart)
|
||||||
Clone the repository to your local:
|
Clone the repository to your local:
|
||||||
```
|
```
|
||||||
git clone https://www.github.com/forensic-architecture/datasheet-server
|
git clone https://www.github.com/forensic-architecture/datasheet-server
|
||||||
|
|||||||
Binary file not shown.
6
package-lock.json
generated
6
package-lock.json
generated
@@ -4600,9 +4600,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.15",
|
"version": "4.17.19",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash.clone": {
|
"lodash.clone": {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"express-handlebars": "^4.0.4",
|
"express-handlebars": "^4.0.4",
|
||||||
"googleapis": "^32.0.0",
|
"googleapis": "^32.0.0",
|
||||||
"graphql": "^0.13.2",
|
"graphql": "^0.13.2",
|
||||||
|
"moment": "^2.27.0",
|
||||||
"morgan": "^1.8.0",
|
"morgan": "^1.8.0",
|
||||||
"mz": "^2.7.0",
|
"mz": "^2.7.0",
|
||||||
"node-fetch": "^2.3.0",
|
"node-fetch": "^2.3.0",
|
||||||
|
|||||||
@@ -58,6 +58,17 @@ export default ({ config, controller }) => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// api.get('/:sheet/:tab/:resource/validate', (req, res) => {
|
||||||
|
// const { sheet, tab, resource } = req.params
|
||||||
|
// controller
|
||||||
|
// .retrieve(sheet, tab, resource)
|
||||||
|
// .then(data => res.json(data))
|
||||||
|
// .catch(err =>
|
||||||
|
// res.status(err.status || 404)
|
||||||
|
// .send({ error: err.message })
|
||||||
|
// )
|
||||||
|
// })
|
||||||
|
|
||||||
// ERROR routes. Note that it is important that these come AFTER routes
|
// ERROR routes. Note that it is important that these come AFTER routes
|
||||||
// like /update, so that the regex does not greedily match these routes.
|
// like /update, so that the regex does not greedily match these routes.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { fmtObj } from '../lib/util'
|
import { fmtObj } from '../lib/util'
|
||||||
|
import { getColumnValidation } from '../lib/validation'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each resource item is an object with values labelled according
|
* Each resource item is an object with values labelled according
|
||||||
@@ -35,7 +36,6 @@ export default (data) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// generate the value for deep labels using the structure created
|
// generate the value for deep labels using the structure created
|
||||||
data.forEach((row, idx) => {
|
data.forEach((row, idx) => {
|
||||||
if (idx === 0) return
|
if (idx === 0) return
|
||||||
@@ -61,9 +61,11 @@ export default (data) => {
|
|||||||
|
|
||||||
// move values for flat labels over from base
|
// move values for flat labels over from base
|
||||||
structure.__flat.forEach(label => {
|
structure.__flat.forEach(label => {
|
||||||
|
const validatedLabel = getColumnValidation(label, baseRow[label])
|
||||||
|
console.log(validatedLabel)
|
||||||
deepRow[label] = baseRow[label]
|
deepRow[label] = baseRow[label]
|
||||||
})
|
})
|
||||||
if (deepRow['id'] && deepRow['id'] !== '') {
|
if (!Object.keys(deepRow).every(k => deepRow[k] === '')) {
|
||||||
output.push(deepRow)
|
output.push(deepRow)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import { timemap } from './lib'
|
import { timemap } from './lib'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
gsheets: [],
|
gsheets: [
|
||||||
|
{
|
||||||
|
name: 'us2020',
|
||||||
|
id: '1I_pgyTQJlIorTIEHBxw1mM1STn-SrIi66FKYxut61iM',
|
||||||
|
tabs: timemap.default
|
||||||
|
}
|
||||||
|
],
|
||||||
xlsx: [
|
xlsx: [
|
||||||
{
|
{
|
||||||
name: 'timemap_data',
|
name: 'timemap_data',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import R from 'ramda'
|
import R from 'ramda';
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
String.prototype.replaceAll = function (search, replacement) {
|
String.prototype.replaceAll = function (search, replacement) {
|
||||||
|
|||||||
20
src/lib/validation.js
Normal file
20
src/lib/validation.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
const DATE_FORMAT = "MM/DD/YYYY";
|
||||||
|
const TIME_REGEX = new RegExp("^([01]\d|2[0-3]):?([0-5]\d)$")
|
||||||
|
|
||||||
|
|
||||||
|
export const getColumnValidation = (colName, value) => {
|
||||||
|
switch(colName) {
|
||||||
|
case 'longitude':
|
||||||
|
return isFinite(value) && Math.abs(value) <= 180;
|
||||||
|
case 'latitude':
|
||||||
|
return isFinite(value) && Math.abs(value) <= 90;
|
||||||
|
case 'date':
|
||||||
|
return moment(value, DATE_FORMAT, true).isValid();
|
||||||
|
case 'time':
|
||||||
|
return TIME_REGEX.test(value);
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{#each urls}}
|
{{#each urls}}
|
||||||
<div><a target="_blank" href="http://localhost:4040{{ this }}">{{ this }}</a></div>
|
<div><a target="_blank" href="http://localhost:4040{{ this }}">{{ this }}</a></div>
|
||||||
|
<div class="bp-validate-button" target="_blank" href="http://localhost:4040{{ this }}">Validate</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
:root {
|
:root {
|
||||||
--grey: #8a8a8a;
|
--grey: #8a8a8a;
|
||||||
--btn-width: 200px;
|
--btn-width: 200px;
|
||||||
|
--validate-btn-width: 150px;
|
||||||
}
|
}
|
||||||
.main-container {
|
.main-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -79,6 +81,21 @@
|
|||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bp-validate-button {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
width: var(--validate-btn-width);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border: 3px solid red;
|
||||||
|
padding: .5em;
|
||||||
|
text-decoration: none;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
.bp-update-container:hover {
|
.bp-update-container:hover {
|
||||||
background-color: black;
|
background-color: black;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
|||||||
Reference in New Issue
Block a user