def edit(self, id): """ Action for updating a single user, denoted by the ID passed in @param id: ID of the user to update """ # Kick unauthorized users out straight away if not self.current_user.access_level == 'Admin': return render('not_found.html') c.user_to_edit = self._user_service.get_user_by_id(id) if not c.user_to_edit: return render('not_found.html') # GET request... if not request.method == 'POST': return render("edit_user.html") else: schema = UpdateUserForm() c.form_errors = {} # POST try: c.form_result = schema.to_python(request.params) except formencode.Invalid, error: c.form_result = error.value c.form_errors = error.error_dict or {} user_email = str(c.form_result.get('email')) user_id = int(c.form_result.get('user_id')) # Username of the user will be set as the user's email address # Generate an error if the email address (and hence username) is already taken existing_user = self._user_service.get_user_by_email_address(user_email) if existing_user and existing_user.id != user_id: c.form_errors = dict(c.form_errors.items() + { 'email': 'Email address is already taken - please choose another.' }.items()) if c.form_errors: html = render('edit_user.html') return htmlfill.render(html, defaults=c.form_result, errors=c.form_errors, auto_error_formatter=custom_formatter) else: # By default a user will be an external user self._user_service.update(c.form_result.get('first_name'), c.form_result.get('last_name'), user_email, "Admin" if c.form_result.get('is_admin') else "CEH", c.form_result.get('user_id')) return redirect(url(controller="user"))
def publish(self): """Action for publishing a set of results """ if request.POST: analysis_id = request.params.get('analysis_id') user_obj = self.current_user c.username = user_obj.name analysis = self._analysis_service.get_analysis_by_id(analysis_id, user_obj.id) if analysis: if analysis.result_dataset: # Get the result attributes from the NetCDF file associated with the result dataset analysis.attributes = self._netcdf_service.get_attributes(analysis.result_dataset.netcdf_url) c.analysis = analysis try: c.form_result = request.params except: added_successfully = False else: self._analysis_service.publish_analysis(int(analysis_id)) added_successfully = True return render('analysis_view.html', extra_vars={'added_successfully': added_successfully}) else: return render('not_found.html') else: return render('not_found.html')
def sort_and_filter(self): """Action for sorting the analysis table using a particular column. Also responsible for filtering the table based on the model variable. """ user = self.current_user query_string = request.query_string params = urlparse.parse_qs(query_string) column = get_parameter_value(params,'column') order = get_parameter_value(params,'order') filter_variable = get_parameter_value(params,'filter_variable') is_public = get_parameter_value(params,'is_public') c.order = order c.sorting_column = column c.filter_variable = filter_variable if is_public == "true": c.public_analyses = self._analysis_service.sort_and_filter_public_analyses_by_column(column,order,filter_variable) if not c.public_analyses: c.empty_public_table = "true" return render('public_analyses_table.html') else: c.private_analyses = self._analysis_service.sort_and_filter_private_analyses_by_column(user.id,column,order,filter_variable) if not c.private_analyses: c.empty_private_table = "true" return render('private_analyses_table.html')
def edit(self, id): """Enables a dataset's details to be updated, intended as an admin-only function @param id: ID of the dataset to edit """ # Kick unauthorized users out straight away if not self.current_user.access_level == 'Admin': return render('not_found.html') c.dataset_to_edit = self._dataset_service.get_dataset_by_id(id, user_id=self.current_user.id) # GET request... if not request.method == 'POST': return render('edit_dataset.html') else: # Define our form schema schema = UpdateDatasetForm() c.form_errors = {} try: c.form_result = schema.to_python(request.params) except formencode.Invalid, error: c.form_result = error.value c.form_errors = error.error_dict or {} if c.form_errors: html = render('edit_dataset.html') return htmlfill.render(html, defaults=c.form_result, errors=c.form_errors, auto_error_formatter=custom_formatter) else: # Perform the update self._dataset_service.update(c.form_result.get('dataset_id'), c.form_result.get('data_range_from'), c.form_result.get('data_range_to'), c.form_result.get('is_categorical')) # By default a user will be an external user # self._user_service.update(c.form_result.get('first_name'), # c.form_result.get('last_name'), # user_email, # "Admin" if c.form_result.get('is_admin') else "CEH", # c.form_result.get('user_id')) return redirect(url(controller="dataset"))
def create(self): """Create a new user """ if not self.current_user.access_level == 'Admin': return render('not_found.html') if not request.POST: return render('new_user.html') schema = CreateUserForm() c.form_errors = {} if request.POST: try: c.form_result = schema.to_python(request.params) except formencode.Invalid, error: c.form_result = error.value c.form_errors = error.error_dict or {} user_email = str(c.form_result.get('email')) # Username of the user will be set as the user's email address # Generate an error if the email address (and hence username) is already taken if self._user_service.get_user_by_email_address(user_email): c.form_errors = dict(c.form_errors.items() + { 'email': 'Email address is already taken - please choose another.' }.items()) if c.form_errors: html = render('new_user.html') return htmlfill.render(html, defaults=c.form_result, errors=c.form_errors, auto_error_formatter=custom_formatter) else: # By default a user will be an external user self._user_service.create(c.form_result.get('user_name'), c.form_result.get('first_name'), c.form_result.get('last_name'), user_email, "Admin" if c.form_result.get('is_admin') else "CEH") return redirect(url(controller="user"))
def index(self): """Allow admin-user to see all available datasets. If user is non-admin, redirect to page not found. """ identity = request.environ.get('REMOTE_USER') user = self._user_service.get_user_by_username(identity) if user.access_level == "Admin": c.datasets = self._dataset_service.get_all_datasets() return render('all_datasets.html') else: return render('not_found.html')
def index(self): """Allow admin-user to see all users of the system. If user is non-admin, redirect to page not found. """ identity = request.environ.get('REMOTE_USER') user = self._user_service.get_user_by_username(identity) if user.access_level == "Admin": c.all_users = self._user_service.get_all_users() return render('list_of_users.html') else: return render('not_found.html')
def add(self): "Add a new dataset" if not request.POST: return render('add_dataset.html') schema = AddDatasetForm() c.form_errors = {} if request.POST: try: c.form_result = schema.to_python(request.params) except formencode.Invalid, error: c.form_result = error.value c.form_errors = error.error_dict or {} if c.form_errors: html = render('add_dataset.html') return htmlfill.render(html, defaults=c.form_result, errors=c.form_errors, auto_error_formatter=custom_formatter) else: dataset_type = c.form_result.get('type') if dataset_type == "Coverage": self._dataset_service.create_coverage_dataset(c.form_result.get('name'), c.form_result.get('wms_url'), c.form_result.get('netcdf_url'), c.form_result.get('low_res_url'), c.form_result.get('data_range_from'), c.form_result.get('data_range_to'), c.form_result.get('is_categorical')) else: # Point data, so we only need the netcdf OpenDAP url, # we need to generate a gridded copy for the WMS opendap_url = c.form_result.get('netcdf_url') wms_url = self._netcdf_service.overlay_point_data(opendap_url) self._dataset_service.create_point_dataset(c.form_result.get('name'), wms_url, opendap_url) return redirect(url(controller="dataset"))
def error_window(self): """Renders a page containing an error window with a specified message. """ log.debug("running viewdata.error_window") if "message" in request.params: c.message = request.params["message"] else: c.message = "Unknown error" return render("viewdata_error.html")
def index(self): """Default action for the map controller""" user = self._user_service.get_user_by_username(request.environ['REMOTE_USER']) c.dataset_types = self._dataset_service.get_datasets_for_user(user.id) return render('map.html')
def login(self): """Action for the 'log in' view""" identity = request.environ.get('REMOTE_USER') came_from = request.params.get('came_from', None) message = request.params.get('message', None) if identity is not None: if came_from: redirect(url(str(came_from))) return render('login.html', extra_vars={'came_from': came_from, 'message': message})
def index(self): """Default action for the analysis controller""" # Who am I? user = self.current_user # Grab the analyses... c.private_analyses = self._analysis_service.get_analyses_for_user(user.id) c.public_analyses = self._analysis_service.get_public_analyses() #Get the model variables - used to populate the filter dropdown c.all_model_variables = self._analysis_service.get_all_model_variables() return render('analysis_list.html')
def timeselection(self, id): """ Gets the possible time points for a temporal dataset @param id: ID of the dataset to get time points for """ ds = self._dataset_service.get_dataset_by_id(id, user_id = self.current_user.id) c.time_points = self._netcdf_service.get_time_points(ds.netcdf_url) c.dataset_name = ds.name c.column_name = request.params.get('col', '') c.identifier = "%s_%s" % (ds.id, c.column_name) if c.time_points: # Render the points back return render("dataset_time_values.html")
def view(self, id): """Action for looking in detail at a single analysis id - ID of the analysis to look at """ user_obj = self.current_user analysis = self._analysis_service.get_analysis_by_id(id, user_obj.id) c.run_by_user = analysis.run_by_user.name if analysis: if analysis.result_dataset: # Get the result attributes from the NetCDF file associated with the result dataset analysis.attributes = self._netcdf_service.get_attributes(analysis.result_dataset.netcdf_url) c.analysis = analysis if 'compact' in request.params: return render('analysis_compact.html') else: return render('analysis_view.html', extra_vars={'added_successfully': None}) else: c.object_type = 'analysis' return render('not_found.html')
def rerun(self, id): """Action for re-running a particular analysis with same parameters as before id - ID of the analysis to look at """ user_id = self.current_user.id c.point_datasets = self._dataset_service.get_datasets_for_user(user_id,'Point') coverage_datasets = self._dataset_service.get_datasets_for_user(user_id, 'Coverage') # Be sure to populate the column names for each coverage dataset, this # will populate the list correctly for ds in coverage_datasets: ds.column_names = self._netcdf_service.get_variable_column_names(ds.netcdf_url) c.coverage_datasets = coverage_datasets c.all_models = self._model_service.get_all_models() current_analysis = self._analysis_service.get_analysis_by_id(id, user_id) point_dataset_id = current_analysis.point_data_dataset_id model_id = current_analysis.model_id # For each coverage dataset that was linked to the original analysis, there # will be a number of column names chosen... cds = current_analysis.coverage_datasets coverage_dataset_ids = [] # So create the right type of "ID" based on the convention we're using # which is <id>_<column-name> for dataset in cds: coverage_dataset_ids.extend(["%s_%s" % (dataset.dataset_id, col.column) for col in dataset.columns]) unit_of_time = current_analysis.unit_of_time random_group = current_analysis.random_group model_variable = current_analysis.model_variable data_type = current_analysis.data_type return render('configure_analysis.html', extra_vars={'current_model_id': model_id, 'current_point_dataset_id': point_dataset_id, 'current_coverage_dataset_ids': coverage_dataset_ids, 'unit_of_time': unit_of_time, 'random_group': random_group, 'model_variable': model_variable, 'data_type': data_type})
def preview(self, id): """ Renders a preview view of the first 10 rows of a dataset (currently point data only!) """ # Need to make sure the user has access to the dataset in question user = self._user_service.get_user_by_username(request.environ['REMOTE_USER']) ds = self._dataset_service.get_dataset_by_id(id, user_id = user.id) c.dataset_name = ds.name # This should contain the first 10 rows preview_data = self._netcdf_service.get_point_data_preview(ds.netcdf_url, 10) c.columns = preview_data.keys() # Number of rows - 1 for the row range--------------------------------------v c.row_set = [[preview_data[col][row] for col in c.columns] for row in range(9)] return render('dataset_preview.html')
def layers(self, id): """ Returns a view on a dataset's map layers @param dataset_id: The ID of the dataset to get the layer data for """ dataset = self._dataset_service.get_dataset_by_id(id, user_id=self.current_user.id) c.dataset = dataset if dataset.dataset_type.type == "Result": c.analysis_id = self._analysis_service.get_analysis_for_result_dataset(dataset.id) c.layers = self.get_layers_for_dataset(dataset) c.dimensions = [] # Check for dimensionality if c.layers and c.layers[0]["dimensions"]: c.dimensions = c.layers[0]["dimensions"] return render("layers.html")
def index(self): """ Default controller method to handle the initial requests to the page """ st = time.time() params = self._getParams() #get the list of default WCS endpoints ep = EndpointConfigFileParser() endpointList = ep.buildEndpointList('wcsdown') wcsEPList = utils.filterEnpointList(endpointList, 'WCS') #log.debug("wcsEPList = %s" % (pprint.pformat(wcsEPList),)) c.defaultWCSEndpoints = utils.toJSON(wcsEPList) log.debug("params = %s" % (params,)) endpoint = params.get('ENDPOINT', None) bbox = params.get('BBOX', None) c.time = params.get('TIME', None) c.time_end = params.get('TIME_END', None) layer = params.get('LAYER', None) format = params.get('FORMAT', None) crs = params.get('CRS', None) c.message = params.get('MESSAGE', "") c.singleTimePoint = params.get('SINGLE_TIME', "") layers = [] supportedFormats = [] supportedCRS = [] bboxLimits = None timepositions = None if endpoint != None: st1 = time.time() wcs, layers = self._getWCSObj(endpoint) log.debug("retrieved wcs metadata in = %s" % (time.time() - st1,)) if layer != None: st1 = time.time() layerMetadata, bboxLimits, timepositions, supportedFormats, supportedCRS =\ self._getWCSMetadata(wcs, layer) log.debug("retrieved layer metadata in = %s" % (time.time() - st1,)) if bbox != None: c.selected_bbox = bbox elif bboxLimits != None: c.selected_bbox = bboxLimits else: c.selected_bbox = '-180.0,-90.0,180.0,90.0' log.debug("timepositions = %s" % (timepositions,)) if timepositions != None and timepositions != [None]: builder = DateTimeOptionsBuilder(timepositions) options = builder.buildOptions() #log.debug("options = %s" % (options,)) c.timedata = utils.toJSON(options) c.endpoint = endpoint c.selected_layer = layer c.layer_options = [(x,x) for x in layers] c.layer_options.insert(0, ("","")) #add an empty value at the start c.selected_format = format c.format_options = [(x,x) for x in supportedFormats] c.format_options.insert(0, ("","")) #add an empty value at the start c.selected_crs = crs c.crs_options = [(x,x) for x in supportedCRS] c.crs_options.insert(0, ("","")) #add an empty value at the start # get server information from config file g.server=config['app_conf']['serverurl'] lp = OutlineLayersConfigParser() layersList = lp.getOutlineLayerList('wcsdown') log.debug("layerList = %s" % (layersList,)) c.baseLayerJSON = utils.toJSON(layersList) log.debug("rendering template after %ss" % (time.time() - st,)) return render('wcsdown.html')
message = 'The EcoMaps database is unavailable, please contact technical support' log.error("EcoMaps database unavailable: %s" % sx) else: # Authentication not successful message = 'Login failed: check your username and/or password.' else: # Forcefully forget any existing credentials. _, headers = who_api.login({}) request.response_headerlist = headers if 'REMOTE_USER' in request.environ: del request.environ['REMOTE_USER'] return htmlfill.render( render('login.html', extra_vars={'came_from': came_from, 'message': message}), defaults=c.form_result, errors=c.form_errors, auto_error_formatter=custom_formatter ) def logout(self): """Action to log the user out of ecomaps - removing their session""" who_api = get_api(request.environ) headers = who_api.logout() return HTTPFound(location='/account/login', headers=headers) def custom_formatter(error): """Custom error formatter"""
def about(self): """Action for when the user selects the about tab""" return render("about.html")
def index(self): """Default action, shows the home page""" c.name = self.current_user.first_name return render("home.html")
def test(self, id): c.analysis_id = id return render('analysis_progress.html')
def create(self): """ Creates the configure analysis page""" user_id = self.current_user.id c.all_models = self._model_service.get_all_models() c.point_datasets = self._dataset_service.get_datasets_for_user(user_id,'Point') coverage_datasets = self._dataset_service.get_datasets_for_user(user_id, 'Coverage') for ds in coverage_datasets: ds.column_names = self._netcdf_service.get_variable_column_names(ds.netcdf_url) c.coverage_datasets = coverage_datasets if not request.POST: unit_of_time = None random_group = None model_variable = None data_type = None return render('configure_analysis.html', extra_vars={'unit_of_time': unit_of_time, 'random_group': random_group, 'model_variable': model_variable, 'data_type': data_type}) else: schema = ConfigureAnalysisForm() c.form_errors = {} try: c.form_result = schema.to_python(request.params) except formencode.Invalid, error: c.form_result = error.value c.form_errors = error.error_dict or {} # If coverage_dataset_ids is not populated on the form # the validation doesn't throw an error, but instead returns an empty # array. Hence we have to do the error-handling ourselves if not c.form_result.get('coverage_dataset_ids'): c.form_errors = dict(c.form_errors.items() + { 'coverage_dataset_ids': 'Please select at least one coverage dataset' }.items()) if c.form_errors: html = render('configure_analysis.html') return htmlfill.render(html, defaults=c.form_result, errors=c.form_errors, auto_error_formatter=custom_formatter) else: # OK, the form has been processed successfully, now # to see if this combination of inputs has been used # before hash = get_hash_for_inputs(c.form_result, ['point_dataset_id', 'coverage_dataset_ids', 'unit_of_time', 'random_group', 'model_variable', 'data_type', 'model_id', 'analysis_description']) # Almost ready to create, although first we need to create a collection of # time point indicies based on any temporal datasets we may have chosen time_indicies = {} for column in c.form_result.get('coverage_dataset_ids'): # Is there a time selection field for this coverage ds column ? # If so, it'll have been given a name starting with 'time' - see dataset_time_values.html if c.form_result.get('time_%s' % column): time_indicies[column] = int(c.form_result.get('time_%s' % column)) test_analysis = self._analysis_service.get_public_analyses_with_identical_input(hash) if test_analysis and not any(time_indicies): return redirect(url(controller='analysis', action='view', id=test_analysis.id)) analysis_id = self._analysis_service.create(c.form_result.get('analysis_name'), c.form_result.get('point_dataset_id'), c.form_result.get('coverage_dataset_ids'), user_id, c.form_result.get('unit_of_time'), c.form_result.get('random_group'), c.form_result.get('model_variable'), c.form_result.get('data_type'), c.form_result.get('model_id'), c.form_result.get('analysis_description'), hash, time_indicies) c.analysis_id = analysis_id analysis_to_run = self._analysis_service.get_analysis_by_id(analysis_id, user_id) model = self._model_service.get_model_by_id(analysis_to_run.model_id) # The path to the code may need to be made dynamic # if we start running multiple analyses runner = AnalysisRunner(model.code_path) runner.run_async(analysis_to_run) return render('analysis_progress.html')