...
 
Commits (2)
felyx_django is provided with static assets, but you can generate your own using
the following method:
1. Install nodejs, npm
1. Install nodejs, npm and bower
2. Retrieve dependencies using npm and bower
2. Retrieve jquery, bootstrap and less using bower
cd developers
npm install
node_modules/.bin/bower install
bower install
3. Regenerate static files using lessc and uglifyjs2
uglifyjs2 -c -o ../js/thirdparty/jquery.pjax.min.js bower_components/jquery-pjax/jquery.pjax.js
......
{
"name": "felyx_django",
"dependencies": {
"humane-js": "~3.2.0",
"humane-js": "~3.1.0",
"d3": "~3.5.3",
"jsSHA": "~2.1.0",
"rome": "~2.1.0",
"picoModal": "~3.0.0",
"jsSHA": "~1.5.0",
"rome": "~1.2.0",
"picoModal": "~2.0.1",
"byda": "~2.1.1",
"reqwest": "~2.0.0",
"reqwest": "~1.1.5",
"cesiumjs": "~1.13.0",
"kube-framework": "~3.0.2",
"fontawesome": "~4.6.0",
"fontawesome": "~4.3.0",
"datatables": "~1.10.5",
"jslider": "060a8c40ef",
"pako": "~1.0.1"
"pako": "~0.2.7"
}
}
{
"devDependencies": {
"bower": "^1.7.9",
"less": "^2.7.1",
"less-plugin-autoprefix": "^1.5.1",
"less-plugin-clean-css": "^1.5.1",
"uglify-js": "^2.6.2"
},
"dependencies": {
"cesium": "1.24.0",
"clusterize.js": "0.16.1"
}
}
#!/bin/sh
original_dir="$(pwd)"
script_dir=`dirname "$0"`
script_dir=`readlink -m "${script_dir}"`
script_dir=`readlink -f "${script_dir}"`
app_dir=`dirname ${script_dir}`
BOWER="${script_dir}/node_modules/bower/bin/bower"
if [ ! -f "${BOWER}" ];
then
cd "${script_dir}"
npm i bower --save-dev
npm install bower
"${BOWER}" install
cd -
fi
......@@ -17,7 +16,5 @@ fi
js="${script_dir}/regenerate_js"
css="${script_dir}/regenerate_css"
cd "${original_dir}"
. ${js} $*
cd "${original_dir}"
. ${css} $*
......@@ -2,7 +2,7 @@
cwd=`pwd`
script_dir=`dirname ${0}`
script_dir=`readlink -m "${script_dir}"`
script_dir=`readlink -f "${script_dir}"`
app_dir=`dirname ${script_dir}`
bower_dir="${script_dir}/bower_components"
vendor_dir="${script_dir}/vendor"
......@@ -13,7 +13,7 @@ LESSC="${script_dir}/node_modules/less/bin/lessc"
if [ ! -f "${LESSC}" ];
then
cd "${script_dir}"
npm i less less-plugin-clean-css less-plugin-autoprefix --save-dev
npm install less less-plugin-clean-css less-plugin-autoprefix
fi
# Generate and concatenate CSS
......
......@@ -8,20 +8,12 @@ bower_dir="${script_dir}/bower_components"
vendor_dir="${script_dir}/vendor"
static_dir="${app_dir}/felyx_django/static"
js_dir="${static_dir}/dev/js"
node_modules_dir="${script_dir}/node_modules"
BOWER="${node_modules_dir}/.bin/bower"
UGLIFYJS="${node_modules_dir}/.bin/uglifyjs"
UGLIFYJS="${script_dir}/node_modules/uglify-js/bin/uglifyjs"
if [ ! -f "${node_modules_dir}" ];
if [ ! -f "${UGLIFYJS}" ];
then
cd "${script_dir}"
npm install
fi
if [ ! -f "${bower_dir}" ];
then
cd "${script_dir}"
${BOWER} install
npm install uglify-js
fi
......@@ -56,9 +48,6 @@ then
wget "${url}" -O "${vendor_dir}/jquery-migrate-1.2.1.min.js"
fi
wrapped_jsSHA="$(mktemp -t tmp.XXXXXXXXXX.js)"
(echo "(function(){"; cat "${bower_dir}/jsSHA/src/sha.js"; echo "}.call(this))") > "${wrapped_jsSHA}"
_files_list="${vendor_dir}/gator.min.js \
${vendor_dir}/sorttable.js \
${vendor_dir}/MiniEvent.min.js \
......@@ -68,10 +57,8 @@ _files_list="${vendor_dir}/gator.min.js \
${bower_dir}/rome/dist/rome.min.js \
${bower_dir}/humane-js/humane.min.js \
${bower_dir}/d3/d3.min.js \
${wrapped_jsSHA} \
${bower_dir}/jsSHA/src/sha.js \
${bower_dir}/pako/dist/pako.min.js \
${node_modules_dir}/clusterize.js/clusterize.min.js \
${js_dir}/ugly_hacks/clusterize.js \
${js_dir}/ajax.js \
${js_dir}/log.js \
${js_dir}/tools.js \
......@@ -148,7 +135,6 @@ _files_list="${vendor_dir}/gator.min.js \
${js_dir}/configure/presets_manager.js \
${js_dir}/configure/configure.js \
${js_dir}/analyse/report.js \
${js_dir}/analyse/reports_cache.js \
${js_dir}/analyse/collections_controller.js \
${js_dir}/analyse/sites_view.js \
${js_dir}/analyse/sites_controller.js \
......@@ -227,7 +213,7 @@ _files_list="${vendor_dir}/gator.min.js \
_plot_files_list="${bower_dir}/d3/d3.min.js \
${vendor_dir}/gator.min.js \
${wrapped_jsSHA} \
${bower_dir}/jsSHA/src/sha.js \
${vendor_dir}/MiniEvent.min.js \
${bower_dir}/pako/dist/pako.min.js \
${bower_dir}/reqwest/reqwest.min.js \
......@@ -281,7 +267,7 @@ fi
mkdir -p "${static_dir}/js/vendor"
if [ ! -d "${static_dir}/js/vendor/Cesium" ];
then
cp -r "${node_modules_dir}/cesium/Build/Cesium" "${static_dir}/js/vendor/Cesium"
cp -r "${bower_dir}/cesiumjs/Cesium" "${static_dir}/js/vendor/Cesium"
fi
if [ ! -d "${static_dir}/js/vendor/OpenLayers" ];
......
This diff is collapsed.
......@@ -13,7 +13,6 @@ import os
import sys
import requests
import traceback
from collections import OrderedDict
try:
import simplejson as json
except:
......@@ -90,8 +89,8 @@ class CRUDView(TemplateView):
"""Add filters list to the context of the search form."""
context = super(CRUDView, self).get_context_data(**kwargs)
context['data_models'] = OrderedDict(sorted(data_models.items(), key=lambda x: x[0].lower()))
context['data_mappers'] = OrderedDict(sorted(data_mappers.items(), key=lambda x: x[0].lower()))
context['data_models'] = data_models
context['data_mappers'] = data_mappers
context['inv_data_models'] = inv_data_models
context['inv_data_mappers'] = inv_data_mappers
......
......@@ -8,7 +8,6 @@ from django.contrib.auth.models import User
import sys
import traceback
from collections import OrderedDict
try:
import simplejson as json
except:
......@@ -107,8 +106,8 @@ class CRUDView(TemplateView):
collections = SiteCollection.objects.all().values('name', 'pk')
collections_list = { x['name']: {'label': x['name'], 'value': x['pk']} for x in collections}
context['datasets'] = OrderedDict(sorted(datasets_list.items(), key=lambda x: x[0].lower()))
context['collections'] = OrderedDict(sorted(collections_list.items(), key=lambda x: x[0].lower()))
context['datasets'] = datasets_list
context['collections'] = collections_list
return context
......
......@@ -151,7 +151,7 @@ class CRUDView(TemplateView):
extractions = MiniprodProcessing.objects.all().select_related()
context['extractions'] = sorted(extractions, key=lambda x: x.dataset.name.lower())
context['extractions'] = extractions
return context
......@@ -176,7 +176,7 @@ class CRUDView(TemplateView):
}, steps)
presets = Preset.objects.all()
context['presets'] = sorted(presets, key=lambda x: x.name.lower())
context['presets'] = presets
return context
......@@ -448,7 +448,7 @@ class PresetsView(TemplateView):
def get_context_data(self, **kwargs):
""""""
context = super(PresetsView, self).get_context_data(**kwargs)
context['presets'] = sorted(Preset.objects.all(), key=lambda x: x.name.lower())
context['presets'] = Preset.objects.all()
extractions = MiniprodProcessing.objects.all().select_related()
context['extractions'] = sorted(extractions, key=lambda x: x.dataset.name.lower())
context['extractions'] = extractions
return context
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
pass
def backwards(self, orm):
pass
models = {
}
complete_apps = ['configure']
\ No newline at end of file
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Preset'
db.create_table(u'configure_preset', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=250)),
('json', self.gf('django.db.models.fields.TextField')()),
))
db.send_create_signal(u'configure', ['Preset'])
def backwards(self, orm):
# Deleting model 'Preset'
db.delete_table(u'configure_preset')
models = {
u'configure.preset': {
'Meta': {'object_name': 'Preset'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'json': ('django.db.models.fields.TextField', [], {}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '250'})
}
}
complete_apps = ['configure']
\ No newline at end of file
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'MetricTemplate'
db.create_table(u'configure_metrictemplate', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
('label', self.gf('django.db.models.fields.CharField')(max_length=160)),
('processing_chain_description', self.gf('django.db.models.fields.TextField')()),
))
db.send_create_signal(u'configure', ['MetricTemplate'])
# Deleting field 'Preset.json'
db.delete_column(u'configure_preset', 'json')
# Adding M2M table for field metrics on 'Preset'
m2m_table_name = db.shorten_name(u'configure_preset_metrics')
db.create_table(m2m_table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('preset', models.ForeignKey(orm[u'configure.preset'], null=False)),
('metrictemplate', models.ForeignKey(orm[u'configure.metrictemplate'], null=False))
))
db.create_unique(m2m_table_name, ['preset_id', 'metrictemplate_id'])
def backwards(self, orm):
# Deleting model 'MetricTemplate'
db.delete_table(u'configure_metrictemplate')
# Adding field 'Preset.json'
db.add_column(u'configure_preset', 'json',
self.gf('django.db.models.fields.TextField')(default='{}'),
keep_default=False)
# Removing M2M table for field metrics on 'Preset'
db.delete_table(db.shorten_name(u'configure_preset_metrics'))
models = {
u'configure.metrictemplate': {
'Meta': {'object_name': 'MetricTemplate'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '160'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'processing_chain_description': ('django.db.models.fields.TextField', [], {})
},
u'configure.preset': {
'Meta': {'object_name': 'Preset'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'metrics': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['configure.MetricTemplate']", 'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '250'})
}
}
complete_apps = ['configure']
\ No newline at end of file
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Preset.description'
db.add_column(u'configure_preset', 'description',
self.gf('django.db.models.fields.TextField')(default='N/A', max_length=160),
keep_default=False)
def backwards(self, orm):
# Deleting field 'Preset.description'
db.delete_column(u'configure_preset', 'description')
models = {
u'configure.metrictemplate': {
'Meta': {'object_name': 'MetricTemplate'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '160'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'processing_chain_description': ('django.db.models.fields.TextField', [], {})
},
u'configure.preset': {
'Meta': {'object_name': 'Preset'},
'description': ('django.db.models.fields.TextField', [], {'max_length': '160'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'metrics': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['configure.MetricTemplate']", 'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '250'})
}
}
complete_apps = ['configure']
\ No newline at end of file
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'MetricTemplate.preset'
db.add_column(u'configure_metrictemplate', 'preset',
self.gf('django.db.models.fields.related.ForeignKey')(related_name='metrics', null=True, to=orm['configure.Preset']),
keep_default=False)
# Removing M2M table for field metrics on 'Preset'
db.delete_table(db.shorten_name(u'configure_preset_metrics'))
def backwards(self, orm):
# Deleting field 'MetricTemplate.preset'
db.delete_column(u'configure_metrictemplate', 'preset_id')
# Adding M2M table for field metrics on 'Preset'
m2m_table_name = db.shorten_name(u'configure_preset_metrics')
db.create_table(m2m_table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('preset', models.ForeignKey(orm[u'configure.preset'], null=False)),
('metrictemplate', models.ForeignKey(orm[u'configure.metrictemplate'], null=False))
))
db.create_unique(m2m_table_name, ['preset_id', 'metrictemplate_id'])
models = {
u'configure.metrictemplate': {
'Meta': {'object_name': 'MetricTemplate'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '160'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'preset': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'metrics'", 'null': 'True', 'to': u"orm['configure.Preset']"}),
'processing_chain_description': ('django.db.models.fields.TextField', [], {})
},
u'configure.preset': {
'Meta': {'object_name': 'Preset'},
'description': ('django.db.models.fields.TextField', [], {'max_length': '160'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '250'})
}
}
complete_apps = ['configure']
\ No newline at end of file
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting field 'MetricTemplate.preset'
db.delete_column(u'configure_metrictemplate', 'preset_id')
# Adding M2M table for field metrics on 'Preset'
m2m_table_name = db.shorten_name(u'configure_preset_metrics')
db.create_table(m2m_table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('preset', models.ForeignKey(orm[u'configure.preset'], null=False)),
('metrictemplate', models.ForeignKey(orm[u'configure.metrictemplate'], null=False))
))
db.create_unique(m2m_table_name, ['preset_id', 'metrictemplate_id'])
def backwards(self, orm):
# Adding field 'MetricTemplate.preset'
db.add_column(u'configure_metrictemplate', 'preset',
self.gf('django.db.models.fields.related.ForeignKey')(related_name='metrics', null=True, to=orm['configure.Preset']),
keep_default=False)
# Removing M2M table for field metrics on 'Preset'
db.delete_table(db.shorten_name(u'configure_preset_metrics'))
models = {
u'configure.metrictemplate': {
'Meta': {'object_name': 'MetricTemplate'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'label': ('django.db.models.fields.CharField', [], {'max_length': '160'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'processing_chain_description': ('django.db.models.fields.TextField', [], {})
},
u'configure.preset': {
'Meta': {'object_name': 'Preset'},
'description': ('django.db.models.fields.TextField', [], {'max_length': '160'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'metrics': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['configure.MetricTemplate']", 'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '250'})
}
}
complete_apps = ['configure']
\ No newline at end of file
from felyx_django.apps.core.models import Site, SiteCollection
from felyx_django.apps.configure.forms import SiteForm, SiteCollectionForm
from felyx_django.lib import sites, collections
from felyx_django.lib.geojson import site_to_geojson
from felyx_django.lib.search import search_collections, search_sites
from django.conf import settings
......@@ -132,7 +131,7 @@ class CRUDView(TemplateView):
if 'site_id' in kwargs:
context['type'] = 'site'
context['collections'] = sorted(SiteCollection.objects.all(), key=lambda x: x.name.lower())
context['collections'] = SiteCollection.objects.all()
if 'new' == kwargs['site_id']:
context['mode'] = 'new'
else:
......@@ -144,13 +143,12 @@ class CRUDView(TemplateView):
context['site_tags'] = ','.join([x['name'] for x in site.tags.all().values('name')])
elif 'collection_id' in kwargs:
context['type'] = 'collection'
context['sites'] = sorted(Site.objects.all(), key=lambda x: x.name.lower())
context['sites'] = Site.objects.all()
if 'new' == kwargs['collection_id']:
context['mode'] = 'new'
else:
collection = SiteCollection.objects.select_related().get(pk=kwargs['collection_id'])
context['collection'] = collection
context['collection_sites'] = {site['pk'] for site in collection.site.all().values('pk')}
context['item'] = collection
context['collection_tags'] = ','.join([x['name'] for x in collection.tags.all().values('name')])
......@@ -186,11 +184,12 @@ class RESTView(View):
result = {'status': 'ok', 'msg': '%s deleted' % item_id}
return HttpResponse(json.dumps( result), mimetype='application/json')
def format_site_info(self, site_id, start, stop):
def format_site_info(self, site_id):
site = Site.objects.filter(pk=site_id)
site_obj = {}
if 1 == len(site):
site = site[0]
geometry = site_to_geojson(site, max_vertices=200)
site_obj = { 'code': site.code
, 'name': site.name
, 'owner': site.owner.username
......@@ -199,36 +198,22 @@ class RESTView(View):
, 'tags': sorted(map(lambda x: x.name, site.tags.all()))
, 'collections': sorted(map(lambda x: x.name, site.sitecollection_set.all()))
, 'shape': site.shape.wkt
, 'geojson': geometry
, 'type': 'site'
}
try:
spatial_info = sites.get_spatial_info(site.code, start, stop)
site_obj['spatial_info'] = spatial_info
except sites.SiteDoesNotExist, e:
geojson = site_to_geojson(site, max_vertices=200)
site_obj['geojson'] = geojson
except sites.DynamicCollectionsCountError, e:
# TODO: handle this case too
pass
return site_obj
def format_collection_info(self, collection_id, start, stop):
def format_collection_info(self, collection_id):
collection = SiteCollection.objects.filter(pk=collection_id)
collection_obj = {}
if 1 == len(collection):
collection = collection[0]
all_sites = collection.site.all()
site_names = [
site.name
for site in all_sites
]
site_codes = [
site.code
for site in all_sites
]
sites = []
sites_geojson = []
for site in collection.site.all():
sites.append(site.name)
sites_geojson.append(site_to_geojson(site, max_vertices=5))
if 'community' == collection.level:
collection_access = 'Public'
......@@ -244,39 +229,26 @@ class RESTView(View):
, 'access': collection_access
, 'static': collection.static
, 'tags': sorted(map(lambda x: x.name, collection.tags.all()))
, 'sites': sorted(site_names)
, 'site_codes': site_codes
, 'sites': sorted(sites)
, 'geojson': { 'type': 'FeatureCollection'
, 'features': sites_geojson
}
, 'type': 'collection'
}
return collection_obj
def get(self, request, *args, **kwargs):
""" """
mode = request.GET.get('mode', 'site')
start = request.GET.get('start')
stop = request.GET.get('stop')
if start is not None:
try:
start = int(start)
except ValueError, e:
return HttpResponseBadRequest()
if stop is not None:
try:
stop = int(stop)
except ValueError, e:
return HttpResponseBadRequest()
item_id = kwargs.get('site_id', kwargs.get('collection_id', None))
if item_id is None:
return HttpResponseBadRequest()
if 'site' == mode:
item_obj = self.format_site_info(item_id, start, stop)
item_obj = self.format_site_info(item_id)
elif 'collection' == mode:
item_obj = self.format_collection_info(item_id, start, stop)
item_obj = self.format_collection_info(item_id)
else:
return HttpResponseBadRequest()
......
......@@ -164,8 +164,7 @@ class SiteResourceBase(TaggedModelResource):
authorization = DjangoAuthorization()
authentication = AnonymousGetAuthentication()
list_allowed_methods = ['get', 'post']
validation = Validation(),
ordering=['code', 'name'],
validation = Validation()
filtering = {
'code': ALL,
'name': ALL,
......
This diff is collapsed.
......@@ -161,9 +161,6 @@ class Site(models.Model):
list_filter = ('owner', 'activation_time', 'deactivation_time')
save_as = True
class Meta:
ordering = ['code', 'name']
class TaggedDataset(TaggedItemBase):
"""Tag model for taggit and Dataset."""
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
pass
def backwards(self, orm):
pass
models = {
}
complete_apps = ['home']
\ No newline at end of file
# -*- coding: utf-8 -*-
from pkg_resources import resource_filename
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
"Write your forwards methods here."
# Note: Don't use "from appname.models import ModelName".
# Use orm.ModelName to refer to models in this application,
# and orm['appname.ModelName'] for models in other applications.
from django.core.management import call_command
fixture_path = resource_filename('felyx_django', 'fixtures/reporter_group.json')
call_command("loaddata", fixture_path)
def backwards(self, orm):
"Write your backwards methods here."
pass
......@@ -2,7 +2,6 @@
import os
import logging
import datetime
from django.views.generic import View
from django.http import HttpResponse
......@@ -12,7 +11,7 @@ from settings import MEDIA_ROOT
from felyx_django.lib.http import extract_file_from_request, MimeNotSupported
from felyx_django.lib.http import success_msg_json, error_msg_json
from felyx_django.lib.http import csrf_exempt
from felyx_django.lib.csv import parse_static_sites #, parse_dynamic_sites
from felyx_django.lib.csv import parse_static_sites, parse_dynamic_sites
from felyx_django.lib.csv import StaticSiteDuplicate, InvalidCSVFormat
from felyx_django.lib import trajectory_updates
......@@ -48,8 +47,6 @@ class CSVView(View):
def post(self, request, *args, **kwargs):
"""Import sites as CSV"""
site_type = request.POST.get('type', 'dynamic')
if site_type not in ['static', 'dynamic']:
return error_msg_json('The "type" argument must be either "static" or "dynamic"')
# Extract CSV content from request
try:
......@@ -58,27 +55,43 @@ class CSVView(View):
msg = 'The file you sent is neither CSV nor gzipped CSV'
return error_msg_json(msg)
# Notify backend that an update is available
submission_date = datetime.datetime.utcnow()
submission_date_str = submission_date.strftime('%Y-%m-%dT%H:%M:%S')
try:
# Send a trajectories update task to the backend
ok, update_id, status_url = trajectory_updates.create( filepath
, submission_date_str
, 'static' == site_type
, mime)
except Exception, e:
return error_msg_json(str(e))
if False == ok:
msg = 'Failed to create update job'
return error_msg_json(msg)
msg = [ '[Upload complete] '
, 'Trajectories update task sent to backend, '
, 'you can check status at {}. '.format(status_url)
, 'Don\'t forget to use felyx-cache '
, 'to update backend database']
return success_msg_json(''.join(msg))
# Parse CSV
if 'static' == site_type:
try:
ok, data = parse_static_sites(filepath, opener)
# Try to avoid misuse of this method to delete files other than the one
# submitted by the user
if filepath.startswith(MEDIA_ROOT):
os.remove(filepath)
msg = [ '[Upload complete] '
, 'Don\'t forget to run felyx-cache '
, 'to update backend database']
return success_msg_json(''.join(msg))
except InvalidCSVFormat, e:
return error_msg_json(str(e))
except StaticSiteDuplicate, e:
return error_msg_json(str(e))
elif 'dynamic' == site_type:
try:
ok, data = parse_dynamic_sites(filepath, opener)
if 0 >= len(data.keys()):
msg = 'No position detected in the CSV, so nothing to do...'
return success_msg_json(msg)
# Send a trajectories update task to the backend
update_id, status_url = trajectory_updates.create(data, filepath)
msg = [ '[Upload complete] '
, 'Trajectories update task sent to backend, '
, 'you can check status at {}. '.format(status_url)
, 'Don\'t forget to use felyx-cache '
, 'to update backend database']
return success_msg_json(''.join(msg))
except Exception, e:
return error_msg_json(str(e))
return error_msg_json('The "type" argument must be either "static" or "dynamic"')
This diff is collapsed.
# encoding: utf-8
"""
@author <sylvain.herledan@oceandatalab.com>
"""
import sys
import logging
from django.views.generic import View
from django.http import HttpResponse
from django.conf import settings
from settings import MEDIA_ROOT
from felyx_django.lib.http import csrf_exempt
from felyx_django.lib.http import success_msg_json, error_msg_json
from felyx_django.lib.sites import create_or_update, IncompatibleCollectionError, SiteAlreadyExists
try:
import simplejson as json
except ImportError:
import json
logger = logging.getLogger(__name__)
@csrf_exempt
class SitesView(View):
""""""
def post(self, request, *args, **kwargs):
""""""
raw_site = request.POST.get('site')
try:
site = json.loads(raw_site)
except ValueError:
_, e, _ = sys.exc_info()
logger.exception(e)
msg = 'Could not parse "{}" as JSON'.format(raw_site)
return error_msg_json(msg)
print raw_site
try:
create_or_update( site['code']
, site['name']
, site['description']
, site['shape']
, site['collections']
, site['tags']
, site['owner']
, site['static'])
except IncompatibleCollectionError:
_, e, _ = sys.exc_info()
logger.error(str(e))
return error_msg_json(str(e))
except SiteAlreadyExists:
_, e, _ = sys.exc_info()
logger.error(str(e))
return error_msg_json(str(e))
return success_msg_json('Site "{}" updated'.format(site['code']))
......@@ -11,36 +11,16 @@ class SpatialView(View):
""""""
collection = request.GET.get('collection', None)
site = request.GET.get('site', None)
site_codes = request.GET.get('sites', None)
start = request.GET.get('start', None)
stop = request.GET.get('stop', None)
if site_codes is not None:
site_codes = site_codes.split(',')
if start is not None:
try:
start = int(start)
except ValueError, e:
msg = 'Invalid "start" parameter given, expected integer'
return error_msg_json(msg)
if stop is not None:
try:
stop = int(stop)
except ValueError, e:
msg = 'Invalid "stop" parameter given, expected integer'
return error_msg_json(msg)
if site is not None:
try:
result = sites.get_spatial_info(site, start, stop)
except sites.SiteDoesNotExist, e:
return error_msg_json(str(e))
except sites.DynamicCollectionsCountError, e:
return error_msg_json(str(e))
elif collection is not None:
result = collections.get_spatial_info(collection, site_codes, start, stop)
result = collections.get_spatial_info(collection, start, stop)
else:
msg = 'You must provide either a "site" or a "collection" parameter'
return error_msg_json(msg)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -71,7 +71,7 @@ def extract_file_from_request(request):
if mime.startswith('text/'):
# Plain CSV file
opener = open
elif mime in ['application/x-gzip', 'application/gzip']:
elif 'application/x-gzip' == mime:
# GZip compressed CSV file
opener = gzip.open
else:
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.