def update_adherence_confidence(request, domain): try: request_json = json.loads(request.body) except ValueError: return json_response({"error": "Malformed JSON"}, status_code=400) beneficiary_id = request_json.get("beneficiary_id") start_date = request_json.get("start_date") end_date = request_json.get("end_date") confidence_level = request_json.get("confidence_level") try: validate_beneficiary_id(beneficiary_id) validate_dates(start_date, end_date) validate_confidence_level(confidence_level) update_adherence_confidence_level( domain=domain, person_id=beneficiary_id, start_date=parse_datetime(start_date), end_date=parse_datetime(end_date), new_confidence=confidence_level, ) except AdherenceException as e: return json_response({"error": e.message}, status_code=400) return json_response({"success": "Patient adherences updated."})
def stats_data(request): histo_type = request.GET.get('histogram_type') interval = request.GET.get("interval", "week") datefield = request.GET.get("datefield") individual_domain_limit = request.GET.get("individual_domain_limit[]") or 16 if not request.GET.get("enddate"): # datespan should include up to the current day when unspecified request.datespan.enddate += timedelta(days=1) params, __ = parse_args_for_es(request, prefix='es_') if histo_type == "domains": return json_response(get_domain_stats_data(params, request.datespan, interval=interval, datefield=datefield)) if params: domain_results = es_domain_query(params, fields=["name"], size=99999, show_stats=False) domains = [d["fields"]["name"] for d in domain_results["hits"]["hits"]] if len(domains) <= individual_domain_limit: domain_info = [{"names": [d], "display_name": d} for d in domains] elif len(domains) < ES_MAX_CLAUSE_COUNT: domain_info = [{"names": [d for d in domains], "display_name": _("Domains Matching Filter")}] else: domain_info = [{ "names": None, "display_name": _("All Domains (NOT applying filters. > %s projects)" % ES_MAX_CLAUSE_COUNT) }] else: domain_info = [{"names": None, "display_name": _("All Domains")}] stats_data = get_stats_data(domain_info, histo_type, request.datespan, interval=interval) return json_response(stats_data)
def data_types(request, domain, data_type_id): if data_type_id: data_type = FixtureDataType.get(data_type_id) assert(data_type.doc_type == FixtureDataType._doc_type) assert(data_type.domain == domain) if request.method == 'GET': return json_response(strip_json(data_type)) elif request.method == 'PUT': new = FixtureDataType(domain=domain, **_to_kwargs(request)) for attr in 'tag', 'name', 'fields': setattr(data_type, attr, getattr(new, attr)) data_type.save() return json_response(strip_json(data_type)) elif request.method == 'DELETE': for item in FixtureDataItem.by_data_type(domain, data_type.get_id): item.delete() data_type.delete() return json_response({}) elif data_type_id is None: if request.method == 'POST': data_type = FixtureDataType(domain=domain, **_to_kwargs(request)) data_type.save() return json_response(strip_json(data_type)) elif request.method == 'GET': return json_response([strip_json(x) for x in FixtureDataType.by_domain(domain)]) return HttpResponseBadRequest()
def post(self, request, *args, **kwargs): def update_dataset_map(instance, dict_): for key, value in dict_.items(): if key == 'datavalue_maps': value = [DataValueMap(**v) for v in value] instance[key] = value try: new_dataset_maps = json.loads(request.POST['dataset_maps']) current_dataset_maps = get_dataset_maps(request.domain) i = -1 for i, dataset_map in enumerate(current_dataset_maps): if i < len(new_dataset_maps): # Update current dataset maps update_dataset_map(dataset_map, new_dataset_maps[i]) dataset_map.save() else: # Delete removed dataset maps dataset_map.delete() if i + 1 < len(new_dataset_maps): # Insert new dataset maps for j in range(i + 1, len(new_dataset_maps)): dataset_map = DataSetMap(domain=request.domain) update_dataset_map(dataset_map, new_dataset_maps[j]) dataset_map.save() get_dataset_maps.clear(request.domain) return json_response({'success': _('DHIS2 DataSet Maps saved')}) except Exception as err: return json_response({'error': str(err)}, status_code=500)
def patch_xform(request, domain, app_id, unique_form_id): patch = request.POST['patch'] sha1_checksum = request.POST['sha1'] case_references = _get_case_references(request.POST) app = get_app(domain, app_id) form = app.get_form(unique_form_id) current_xml = form.source if hashlib.sha1(current_xml.encode('utf-8')).hexdigest() != sha1_checksum: return json_response({'status': 'conflict', 'xform': current_xml}) dmp = diff_match_patch() xform, _ = dmp.patch_apply(dmp.patch_fromText(patch), current_xml) save_xform(app, form, xform) if "case_references" in request.POST or "references" in request.POST: form.case_references = case_references response_json = { 'status': 'ok', 'sha1': hashlib.sha1(form.source.encode('utf-8')).hexdigest() } app.save(response_json) notify_form_changed(domain, request.couch_user, app_id, unique_form_id) return json_response(response_json)
def get_ledgers(request, domain): """ Returns ledgers associated with a case in the format: { "section_id": { "product_id": amount, "product_id": amount, ... }, ... } """ case_id = request.REQUEST.get('case_id') if not case_id: return json_response( {'message': 'You must specify a case id to make this query.'}, status_code=400 ) case = get_document_or_404(CommCareCase, domain, case_id) ledger_map = get_current_ledger_transactions(case._id) def custom_json_handler(obj): if isinstance(obj, StockTransaction): return obj.stock_on_hand return json_handler(obj) return json_response( { 'entity_id': case_id, 'ledger': ledger_map, }, default=custom_json_handler, )
def post(self, request, *args, **kwargs): try: export_id = self.commit(request) except Exception as e: if self.is_async: # todo: this can probably be removed as soon as # http://manage.dimagi.com/default.asp?157713 is resolved notify_exception(request, 'problem saving an export! {}'.format(str(e))) response = json_response({ 'error': str(e) or type(e).__name__ }) response.status_code = 500 return response elif isinstance(e, ExportAppException): return HttpResponseRedirect(request.META['HTTP_REFERER']) else: raise else: try: post_data = json.loads(self.request.body) url = self.export_home_url # short circuit to check if the submit is from a create or edit feed # to redirect it to the list view from corehq.apps.export.views.list import DashboardFeedListView, DailySavedExportListView if isinstance(self, DashboardFeedMixin): url = reverse(DashboardFeedListView.urlname, args=[self.domain]) elif post_data['is_daily_saved_export']: url = reverse(DailySavedExportListView.urlname, args=[self.domain]) except ValueError: url = self.export_home_url if self.is_async: return json_response({ 'redirect': url, }) return HttpResponseRedirect(url)
def release_build(request, domain, app_id, saved_app_id): is_released = request.POST.get('is_released') == 'true' if not is_released: if LatestEnabledBuildProfiles.objects.filter(build_id=saved_app_id).exists(): return json_response({'error': _('Please disable any enabled profiles to un-release this build.')}) ajax = request.POST.get('ajax') == 'true' saved_app = get_app(domain, saved_app_id) if saved_app.copy_of != app_id: raise Http404 saved_app.is_released = is_released saved_app.is_auto_generated = False saved_app.save(increment_version=False) from corehq.apps.app_manager.signals import app_post_release app_post_release.send(Application, application=saved_app) if is_released: if saved_app.build_profiles and domain_has_privilege(domain, privileges.BUILD_PROFILES): create_build_files_for_all_app_profiles.delay(domain, saved_app_id) _track_build_for_app_preview(domain, request.couch_user, app_id, 'User starred a build') if ajax: return json_response({ 'is_released': is_released, 'latest_released_version': get_latest_released_app_version(domain, app_id) }) else: return HttpResponseRedirect(reverse('release_manager', args=[domain, app_id]))
def child_locations_for_select2(request, domain): id = request.GET.get('id') query = request.GET.get('name', '').lower() user = request.couch_user def loc_to_payload(loc): return {'id': loc.location_id, 'name': loc.display_name} if id: try: loc = SQLLocation.objects.get(location_id=id) except SQLLocation.DoesNotExist: return json_response( {'message': 'no location with id %s found' % id}, status_code=404, ) else: return json_response(loc_to_payload(loc)) else: locs = [] user_loc = user.get_sql_location(domain) if user_can_edit_any_location(user, request.project): locs = SQLLocation.objects.filter(domain=domain) elif user_loc: locs = user_loc.get_descendants(include_self=True) if locs != [] and query: locs = locs.filter(name__icontains=query) return json_response(map(loc_to_payload, locs[:10]))
def prepare_form_multimedia(request, domain): """Gets the download_id for the multimedia zip and sends it to the exportDownloadService in download_export.ng.js to begin polling for the zip file download. """ form_or_case = request.POST.get('form_or_case') sms_export = json.loads(request.POST.get('sms_export')) permissions = ExportsPermissionsManager(form_or_case, domain, request.couch_user) permissions.access_download_export_or_404() view_helper = DownloadExportViewHelper.get(request, domain, form_or_case, sms_export) filter_form_data = json.loads(request.POST.get('form_data')) export_specs = json.loads(request.POST.get('exports')) try: filter_form = view_helper.get_filter_form(filter_form_data) except ExportFormValidationException: return json_response({ 'error': _("Please check that you've submitted all required filters."), }) download = DownloadBase() export_object = view_helper.get_export(export_specs[0]['export_id']) task_kwargs = filter_form.get_multimedia_task_kwargs(export_object, download.download_id, filter_form_data) from corehq.apps.reports.tasks import build_form_multimedia_zip download.set_task(build_form_multimedia_zip.delay(**task_kwargs)) return json_response({ 'success': True, 'download_id': download.download_id, })
def non_administrative_locations_for_select2(request, domain): id = request.GET.get('id') query = request.GET.get('name', '').lower() if id: try: loc = SQLLocation.objects.get(location_id=id) if loc.domain != domain: raise SQLLocation.DoesNotExist() except SQLLocation.DoesNotExist: return json_response( {'message': 'no location with id %s found' % id}, status_code=404, ) else: return json_response(loc_to_payload(loc)) locs = [] user = request.couch_user user_loc = user.get_sql_location(domain) if user.is_domain_admin(domain): locs = SQLLocation.objects.filter(domain=domain, location_type__administrative=False) elif user_loc: locs = user_loc.get_descendants(include_self=True, location_type__administrative=False) if locs != [] and query: locs = locs.filter(name__icontains=query) return json_response(list(map(loc_to_payload, locs[:10])))
def reinvite_web_user(request, domain): invitation_id = request.POST['invite'] try: invitation = DomainInvitation.get(invitation_id) invitation.send_activation_email() return json_response({'response': _("Invitation resent"), 'status': 'ok'}) except ResourceNotFound: return json_response({'response': _("Error while attempting resend"), 'status': 'error'})
def filter_cases(request, domain, app_id, module_id): app = Application.get(app_id) module = app.get_module(module_id) delegation = request.GET.get('task-list') == 'true' auth_cookie = request.COOKIES.get('sessionid') suite_gen = SuiteGenerator(app) xpath = suite_gen.get_filter_xpath(module, delegation=delegation) extra_instances = [{'id': inst.id, 'src': inst.src} for inst in suite_gen.get_instances_for_module(module, additional_xpaths=[xpath])] # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) if delegation: case_type = DELEGATION_STUB_CASE_TYPE else: case_type = module.case_type if xpath: # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } helper = SessionDataHelper(domain, request.couch_user) result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie), extra_instances=extra_instances) if result.get('status', None) == 'error': return HttpResponseServerError( result.get("message", _("Something went wrong filtering your cases."))) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [res.id for res in get_filtered_cases( domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, ids_only=True )] cases = [CommCareCase.wrap(doc) for doc in iter_docs(CommCareCase.get_db(), case_ids)] # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.get_json(lite=True) for c in cases if c] parents = [] if delegation: for case in cases: parent_id = case['indices']['parent']['case_id'] parents.append(CommCareCase.get(parent_id)) return json_response({ 'cases': cases, 'parents': parents }) else: return json_response(cases)
def prepare_custom_export(request, domain): """Uses the current exports download framework (with some nasty filters) to return the current download id to POLL for the download status. :return: { 'success': True, 'download_id': '<some uuid>', } """ form_or_case = request.POST.get('form_or_case') sms_export = json.loads(request.POST.get('sms_export')) permissions = ExportsPermissionsManager(form_or_case, domain, request.couch_user) permissions.access_download_export_or_404() view_helper = DownloadExportViewHelper.get(request, domain, form_or_case, sms_export) filter_form_data = json.loads(request.POST.get('form_data')) try: filter_form = view_helper.get_filter_form(filter_form_data) except ExportFormValidationException: return json_response({ 'error': _("Form did not validate."), }) export_filters = filter_form.get_export_filters(request, filter_form_data) export_specs = json.loads(request.POST.get('exports')) export_ids = [spec['export_id'] for spec in export_specs] export_instances = [view_helper.get_export(export_id) for export_id in export_ids] try: _check_deid_permissions(permissions, export_instances) _check_export_size(domain, export_instances, export_filters) except ExportAsyncException as e: return json_response({ 'error': six.text_type(e), }) # Generate filename if len(export_instances) > 1: filename = "{}_custom_bulk_export_{}".format(domain, date.today().isoformat()) else: filename = "{} {}".format(export_instances[0].name, date.today().isoformat()) download = get_export_download( domain, export_ids, view_helper.model, request.couch_user.username, filters=export_filters, filename=filename, ) view_helper.send_preparation_analytics(export_instances, export_filters) return json_response({ 'success': True, 'download_id': download.download_id, })
def reinvite_web_user(request, domain): invitation_id = request.POST["invite"] try: invitation = DomainInvitation.get(invitation_id) invitation.invited_on = datetime.utcnow() invitation.save() invitation.send_activation_email() return json_response({"response": _("Invitation resent"), "status": "ok"}) except ResourceNotFound: return json_response({"response": _("Error while attempting resend"), "status": "error"})
def clear_data(request, mapping_id, domain=None): if mapping_id: try: mapping = SqlExtractMapping.get(mapping_id) get_extractor(mapping.backend).clear_all_data(mapping) return json_response({'status': 'success', 'message': _('Data successfully cleared.')}) except ResourceNotFound: return json_response({'status': 'error', 'message': _('Mapping not found.')}) return json_response({'status': 'error', 'message': _('Mapping not found.')})
def filter_cases(request, domain, app_id, module_id, parent_id=None): app = Application.get(app_id) module = app.get_module(module_id) auth_cookie = request.COOKIES.get('sessionid') suite_gen = SuiteGenerator(app) xpath = SuiteGenerator.get_filter_xpath(module) extra_instances = [{'id': inst.id, 'src': inst.src} for inst in suite_gen.get_instances_for_module(module, additional_xpaths=[xpath])] # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) case_type = module.case_type if xpath: # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } helper = SessionDataHelper(domain, request.couch_user) result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie), extra_instances=extra_instances) if result.get('status', None) == 'error': code = result.get('code', 500) message = result.get('message', _("Something went wrong filtering your cases.")) if code == 500: notify_exception(None, message=message) return json_response(message, status_code=code) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [res.id for res in get_filtered_cases( domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, footprint=True, ids_only=True, )] cases = [CommCareCase.wrap(doc) for doc in iter_docs(CommCareCase.get_db(), case_ids)] if parent_id: cases = filter(lambda c: c.parent and c.parent.case_id == parent_id, cases) # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.get_json(lite=True) for c in cases if c] return json_response(cases)
def submit_app_data_drilldown_form(request, domain): if json.loads(request.POST.get('is_deid')): raise Http404() model_type = request.POST.get('model_type') permissions = ExportsPermissionsManager(model_type, domain, request.couch_user) permissions.access_list_exports_or_404(is_deid=False) form_data = json.loads(request.POST.get('form_data')) is_daily_saved_export = json.loads(request.POST.get('is_daily_saved_export')) is_feed = json.loads(request.POST.get('is_feed')) create_form = CreateExportTagForm( permissions.has_form_export_permissions, permissions.has_case_export_permissions, form_data ) if not create_form.is_valid(): return json_response({ 'success': False, 'error': _("The form did not validate."), }) from corehq.apps.export.views.new import ( CreateNewCaseFeedView, CreateNewCustomCaseExportView, CreateNewCustomFormExportView, CreateNewDailySavedCaseExport, CreateNewDailySavedFormExport, CreateNewFormFeedView, ) if is_daily_saved_export: if create_form.cleaned_data['model_type'] == "case": export_tag = create_form.cleaned_data['case_type'] cls = CreateNewCaseFeedView if is_feed else CreateNewDailySavedCaseExport else: export_tag = create_form.cleaned_data['form'] cls = CreateNewFormFeedView if is_feed else CreateNewDailySavedFormExport elif model_type == 'form': export_tag = create_form.cleaned_data['form'] cls = CreateNewCustomFormExportView elif model_type == 'case': export_tag = create_form.cleaned_data['case_type'] cls = CreateNewCustomCaseExportView url_params = '?export_tag="{}"'.format(export_tag) app_id = create_form.cleaned_data['application'] if app_id != ApplicationDataRMIHelper.UNKNOWN_SOURCE: url_params += '&app_id={}'.format(app_id) return json_response({ 'success': True, 'url': reverse(cls.urlname, args=[domain]) + url_params, })
def system_ajax(request): """ Utility ajax functions for polling couch and celerymon """ type = request.GET.get('api', None) task_limit = getattr(settings, 'CELERYMON_TASK_LIMIT', 12) celery_monitoring = getattr(settings, 'CELERY_FLOWER_URL', None) db = XFormInstance.get_db() if type == "_active_tasks": tasks = [] if is_bigcouch() else filter(lambda x: x['type'] == "indexer", db.server.active_tasks()) #for reference structure is: # tasks = [{'type': 'indexer', 'pid': 'foo', 'database': 'mock', # 'design_document': 'mockymock', 'progress': 0, # 'started_on': 1349906040.723517, 'updated_on': 1349905800.679458, # 'total_changes': 1023}, # {'type': 'indexer', 'pid': 'foo', 'database': 'mock', # 'design_document': 'mockymock', 'progress': 70, # 'started_on': 1349906040.723517, 'updated_on': 1349905800.679458, # 'total_changes': 1023}] return json_response(tasks) elif type == "_stats": return json_response({}) elif type == "_logs": pass elif type == 'pillowtop': return json_response(get_all_pillows_json()) elif type == 'stale_pillows': es_index_status = [ check_case_es_index(interval=3), check_xform_es_index(interval=3), check_reportcase_es_index(interval=3), check_reportxform_es_index(interval=3) ] return json_response(es_index_status) if celery_monitoring: cresource = Resource(celery_monitoring, timeout=3) if type == "flower_poll": ret = [] try: t = cresource.get("api/tasks", params_dict={'limit': task_limit}).body_string() all_tasks = json.loads(t) except Exception, ex: all_tasks = {} logging.error("Error with getting from celery_flower: %s" % ex) for task_id, traw in all_tasks.items(): # it's an array of arrays - looping through [<id>, {task_info_dict}] if 'name' in traw and traw['name']: traw['name'] = '.'.join(traw['name'].split('.')[-2:]) else: traw['name'] = None ret.append(traw) ret = sorted(ret, key=lambda x: x['succeeded'], reverse=True) return HttpResponse(json.dumps(ret), mimetype = 'application/json')
def poll_state(request, domain=None, job_id=None): if not job_id: kwargs = {'domain': domain} if domain else {} return redirect('sql_mappings_list', **kwargs) job = AsyncResult(job_id) data = job.result or job.state try: return json_response(data) except TypeError: return json_response(dict(error=str(data)))
def run_command(request): cmd = request.POST.get('command') if cmd not in ['remove_duplicate_domains']: # only expose this one command for now return json_response({"success": False, "output": "Command not available"}) output_buf = StringIO() management.call_command(cmd, stdout=output_buf) output = output_buf.getvalue() output_buf.close() return json_response({"success": True, "output": output})
def dismiss_notification(request): note_id = request.POST.get('note_id', None) note = Notification.get(note_id) if note: if note.user != request.couch_user.username: return json_response({"status": "failure: Not the same user"}) note.dismissed = True note.save() return json_response({"status": "success"}) return json_response({"status": "failure: No note by that name"})
def delete_user_role(request, domain): if not domain_has_privilege(domain, privileges.ROLE_BASED_ACCESS): return json_response({}) role_data = json.loads(request.body) try: role = UserRole.get(role_data["_id"]) except ResourceNotFound: return json_response({}) copy_id = role._id role.delete() # return removed id in order to remove it from UI return json_response({"_id": copy_id})
def post_user_role(request, domain): if not domain_has_privilege(domain, privileges.ROLE_BASED_ACCESS): return json_response({}) role_data = json.loads(request.raw_post_data) role_data = dict([(p, role_data[p]) for p in set(UserRole.properties().keys() + ['_id', '_rev']) if p in role_data]) role = UserRole.wrap(role_data) role.domain = domain if role.get_id: old_role = UserRole.get(role.get_id) assert(old_role.doc_type == UserRole.__name__) assert(old_role.domain == domain) role.save() return json_response(role)
def post_user_role(request, domain): if not domain_has_privilege(domain, privileges.ROLE_BASED_ACCESS): return json_response({}) role_data = json.loads(request.body) role_data = dict([(p, role_data[p]) for p in set(UserRole.properties().keys() + ["_id", "_rev"]) if p in role_data]) role = UserRole.wrap(role_data) role.domain = domain if role.get_id: old_role = UserRole.get(role.get_id) assert old_role.doc_type == UserRole.__name__ assert old_role.domain == domain role.save() role.__setattr__("hasUsersAssigned", True if len(role.ids_of_assigned_users) > 0 else False) return json_response(role)
def update_emailed_export_data(request, domain): permissions = ExportsPermissionsManager(request.GET.get('model_type'), domain, request.couch_user) permissions.access_list_exports_or_404(is_deid=json.loads(request.POST.get('is_deid'))) export_instance_id = request.POST.get('export_id') try: rebuild_saved_export(export_instance_id, manual=True) except XlsLengthException: return json_response({ 'error': _('This file has more than 256 columns, which is not supported by xls. ' 'Please change the output type to csv or xlsx in the export configuration page ' 'to export this file.') }) return json_response({'success': True})
def get_session_context(request, domain, session_id): try: session = EntrySession.objects.get(session_id=session_id) except EntrySession.DoesNotExist: session = None if request.method == 'DELETE': if session: session.delete() return json_response({'status': 'success'}) else: helper = SessionDataHelper(domain, request.couch_user) return json_response(helper.get_full_context({ 'session_id': session_id, 'app_id': session.app_id if session else None }))
def get_cases(request, domain): if request.couch_user.is_commcare_user(): user_id = request.couch_user.get_id else: user_id = request.REQUEST.get("user_id", "") if not user_id and not request.couch_user.is_web_user(): return HttpResponseBadRequest("Must specify user_id!") ids_only = string_to_boolean(request.REQUEST.get("ids_only", "false")) case_id = request.REQUEST.get("case_id", "") footprint = string_to_boolean(request.REQUEST.get("footprint", "false")) include_children = string_to_boolean(request.REQUEST.get("include_children", "false")) if case_id and not footprint and not include_children: # short circuit everything else and just return the case # NOTE: this allows any user in the domain to access any case given # they know its ID, which is slightly different from the previous # behavior (can only access things you own + footprint). If we want to # change this contract we would need to update this to check the # owned case list + footprint case = CommCareCase.get(case_id) assert case.domain == domain cases = [CaseAPIResult(id=case_id, couch_doc=case, id_only=ids_only)] else: filters = get_filters_from_request(request) status = api_closed_to_status(request.REQUEST.get('closed', 'false')) case_type = filters.get('properties/case_type', None) cases = get_filtered_cases(domain, status=status, case_type=case_type, user_id=user_id, filters=filters, footprint=footprint, ids_only=ids_only, strip_history=True, include_children=include_children) return json_response(cases)
def stats_data(request, org): params, _ = parse_args_for_es(request) domains = [{"name": d.name, "hr_name": d.hr_name} for d in Domain.get_by_organization(org).all()] histo_type = request.GET.get("histogram_type") period = request.GET.get("daterange", "month") today = date.today() startdate = today - timedelta(days={"month": 30, "week": 7, "quarter": 90, "year": 365}[period]) histo_data = dict( [ ( d["hr_name"], es_histogram(histo_type, [d["name"]], startdate.strftime("%Y-%m-%d"), today.strftime("%Y-%m-%d")), ) for d in domains ] ) return json_response( { "histo_data": histo_data, "range": period, "startdate": [startdate.year, startdate.month, startdate.day], "enddate": [today.year, today.month, today.day], } )
def stats_data(request): histo_type = request.GET.get('histogram_type') interval = request.GET.get("interval", "week") datefield = request.GET.get("datefield") get_request_params_json = request.GET.get("get_request_params", None) get_request_params = ( json.loads(HTMLParser.HTMLParser().unescape(get_request_params_json)) if get_request_params_json is not None else {} ) stats_kwargs = { k: get_request_params[k] for k in get_request_params if k != "domain_params_es" } if datefield is not None: stats_kwargs['datefield'] = datefield domain_params_es = get_request_params.get("domain_params_es", {}) if not request.GET.get("enddate"): # datespan should include up to the current day when unspecified request.datespan.enddate += timedelta(days=1) domain_params, __ = parse_args_for_es(request, prefix='es_') domain_params.update(domain_params_es) domains = get_project_spaces(facets=domain_params) return json_response(get_stats_data( histo_type, domains, request.datespan, interval, **stats_kwargs ))
def get_apps_api(request, domain): return json_response(get_cloudcare_apps(domain))
def edit_module_attr(request, domain, app_id, module_unique_id, attr): """ Called to edit any (supported) module attribute, given by attr """ attributes = { "all": None, "auto_select_case": None, "case_list": ('case_list-show', 'case_list-label'), "case_list-menu_item_media_audio": None, "case_list-menu_item_media_image": None, "case_list_form_id": None, "case_list_form_label": None, "case_list_form_media_audio": None, "case_list_form_media_image": None, "case_list_post_form_workflow": None, "case_type": None, 'comment': None, "display_separately": None, "has_schedule": None, "media_audio": None, "media_image": None, "module_filter": None, "name": None, "parent_module": None, "put_in_root": None, "root_module_id": None, "source_module_id": None, "task_list": ('task_list-show', 'task_list-label'), "excl_form_ids": None, "display_style": None, "custom_icon_form": None, "custom_icon_text_body": None, "custom_icon_xpath": None, } if attr not in attributes: return HttpResponseBadRequest() def should_edit(attribute): if attribute == attr: return True if 'all' == attr: if attributes[attribute]: for param in attributes[attribute]: if not request.POST.get(param): return False return True else: return request.POST.get(attribute) is not None app = get_app(domain, app_id) try: module = app.get_module_by_unique_id(module_unique_id) except ModuleNotFoundException: # temporary fallback module = app.get_module(module_unique_id) lang = request.COOKIES.get('lang', app.langs[0]) resp = {'update': {}, 'corrections': {}} if should_edit("custom_icon_form"): error_message = handle_custom_icon_edits(request, module, lang) if error_message: return json_response( {'message': error_message}, status_code=400 ) if should_edit("case_type"): case_type = request.POST.get("case_type", None) if case_type == USERCASE_TYPE and not isinstance(module, AdvancedModule): return HttpResponseBadRequest('"{}" is a reserved case type'.format(USERCASE_TYPE)) elif case_type and not is_valid_case_type(case_type, module): return HttpResponseBadRequest("case type is improperly formatted") else: old_case_type = module["case_type"] module["case_type"] = case_type # rename other reference to the old case type all_advanced_modules = [] modules_with_old_case_type_exist = False for mod in app.modules: if isinstance(mod, AdvancedModule): all_advanced_modules.append(mod) modules_with_old_case_type_exist |= mod.case_type == old_case_type for mod in all_advanced_modules: for form in mod.forms: for action in form.actions.get_load_update_actions(): if action.case_type == old_case_type and action.details_module == module_unique_id: action.case_type = case_type if mod.unique_id == module_unique_id or not modules_with_old_case_type_exist: for action in form.actions.get_open_actions(): if action.case_type == old_case_type: action.case_type = case_type if should_edit("put_in_root"): module["put_in_root"] = json.loads(request.POST.get("put_in_root")) if should_edit("display_style"): module["display_style"] = request.POST.get("display_style") if should_edit("source_module_id"): module["source_module_id"] = request.POST.get("source_module_id") if should_edit("display_separately"): module["display_separately"] = json.loads(request.POST.get("display_separately")) if should_edit("parent_module"): parent_module = request.POST.get("parent_module") module.parent_select.module_id = parent_module if module_case_hierarchy_has_circular_reference(module): return HttpResponseBadRequest(_("The case hierarchy contains a circular reference.")) if should_edit("auto_select_case"): module["auto_select_case"] = request.POST.get("auto_select_case") == 'true' if app.enable_module_filtering and should_edit('module_filter'): module['module_filter'] = request.POST.get('module_filter') if should_edit('case_list_form_id'): module.case_list_form.form_id = request.POST.get('case_list_form_id') if should_edit('case_list_form_label'): module.case_list_form.label[lang] = request.POST.get('case_list_form_label') if should_edit('case_list_post_form_workflow'): module.case_list_form.post_form_workflow = request.POST.get('case_list_post_form_workflow') if should_edit('case_list_form_media_image'): new_path = process_media_attribute( 'case_list_form_media_image', resp, request.POST.get('case_list_form_media_image') ) module.case_list_form.set_icon(lang, new_path) if should_edit('case_list_form_media_audio'): new_path = process_media_attribute( 'case_list_form_media_audio', resp, request.POST.get('case_list_form_media_audio') ) module.case_list_form.set_audio(lang, new_path) if should_edit('case_list-menu_item_media_image'): val = process_media_attribute( 'case_list-menu_item_media_image', resp, request.POST.get('case_list-menu_item_media_image') ) module.case_list.set_icon(lang, val) if should_edit('case_list-menu_item_media_audio'): val = process_media_attribute( 'case_list-menu_item_media_audio', resp, request.POST.get('case_list-menu_item_media_audio') ) module.case_list.set_audio(lang, val) if should_edit("name"): name = request.POST.get("name", None) module["name"][lang] = name resp['update'] = {'.variable-module_name': trans(module.name, [lang], use_delim=False)} if should_edit('comment'): module.comment = request.POST.get('comment') for SLUG in ('case_list', 'task_list'): show = '{SLUG}-show'.format(SLUG=SLUG) label = '{SLUG}-label'.format(SLUG=SLUG) if request.POST.get(show) == 'true' and (request.POST.get(label) == ''): # Show item, but empty label, was just getting ignored return HttpResponseBadRequest("A label is required for {SLUG}".format(SLUG=SLUG)) if should_edit(SLUG): module[SLUG].show = json.loads(request.POST[show]) module[SLUG].label[lang] = request.POST[label] if should_edit("root_module_id"): if not request.POST.get("root_module_id"): module["root_module_id"] = None else: module["root_module_id"] = request.POST.get("root_module_id") if should_edit('excl_form_ids') and isinstance(module, ShadowModule): excl = request.POST.getlist('excl_form_ids') excl.remove('0') # Placeholder value to make sure excl_form_ids is POSTed when no forms are excluded module.excluded_form_ids = excl handle_media_edits(request, module, should_edit, resp, lang) app.save(resp) resp['case_list-show'] = module.requires_case_details() return HttpResponse(json.dumps(resp))
def data_source_status(request, domain, config_id): config = get_document_or_404(DataSourceConfiguration, domain, config_id) return json_response({'isBuilt': config.meta.build.finished})
def get_app_api(request, domain, app_id): try: return json_response(look_up_app_json(domain, app_id)) except RemoteAppError: raise Http404()
instance_id).get_xml() except XFormNotFound: raise Http404() session_extras = {'session_name': session_name, 'app_id': app._id} session_extras.update( get_cloudcare_session_data(domain, form, request.couch_user)) delegation = request.GET.get('task-list') == 'true' session_helper = CaseSessionDataHelper(domain, request.couch_user, case_id, app, form, delegation=delegation) return json_response( session_helper.get_full_context(root_context, session_extras)) cloudcare_api = login_or_digest_ex(allow_cc_users=True) def get_cases_vary_on(request, domain): request_params = request.GET return [ request.couch_user.get_id if request.couch_user.is_commcare_user() else request_params.get('user_id', ''), request_params.get('ids_only', 'false'), request_params.get('case_id', ''), request_params.get('footprint', 'false'), request_params.get('closed', 'false'),
def app_source(request, domain, app_id): app = get_app(domain, app_id) return json_response(app.export_json(dump_json=False))
def location_descendants_count(request, domain, loc_id): loc = get_object_or_404(SQLLocation, domain=domain, location_id=loc_id) count = loc.get_descendants(include_self=True).count() return json_response({'count': count})
def submit_app_data_drilldown_form(request, domain): if json.loads(request.POST.get('is_deid')): raise Http404() model_type = request.POST.get('model_type') permissions = ExportsPermissionsManager(model_type, domain, request.couch_user) permissions.access_list_exports_or_404(is_deid=False) form_data = json.loads(request.POST.get('form_data')) is_daily_saved_export = json.loads( request.POST.get('is_daily_saved_export')) is_feed = json.loads(request.POST.get('is_feed')) is_odata = json.loads(request.POST.get('is_odata')) create_form = CreateExportTagForm(permissions.has_form_export_permissions, permissions.has_case_export_permissions, form_data) if not create_form.is_valid(): return json_response({ 'success': False, 'error': _("The form did not validate."), }) from corehq.apps.export.views.new import ( CreateNewCaseFeedView, CreateNewCustomCaseExportView, CreateNewCustomFormExportView, CreateNewDailySavedCaseExport, CreateNewDailySavedFormExport, CreateNewFormFeedView, CreateODataCaseFeedView, CreateODataFormFeedView, ) if is_odata: if create_form.cleaned_data['model_type'] == "case": export_tag = create_form.cleaned_data['case_type'] cls = CreateODataCaseFeedView else: export_tag = create_form.cleaned_data['form'] cls = CreateODataFormFeedView elif is_daily_saved_export: if create_form.cleaned_data['model_type'] == "case": export_tag = create_form.cleaned_data['case_type'] cls = CreateNewCaseFeedView if is_feed else CreateNewDailySavedCaseExport else: export_tag = create_form.cleaned_data['form'] cls = CreateNewFormFeedView if is_feed else CreateNewDailySavedFormExport elif model_type == 'form': export_tag = create_form.cleaned_data['form'] cls = CreateNewCustomFormExportView elif model_type == 'case': export_tag = create_form.cleaned_data['case_type'] cls = CreateNewCustomCaseExportView url_params = '?export_tag="{}"'.format(export_tag) app_id = create_form.cleaned_data['application'] if app_id != ApplicationDataRMIHelper.UNKNOWN_SOURCE: url_params += '&app_id={}'.format(app_id) return json_response({ 'success': True, 'url': reverse(cls.urlname, args=[domain]) + url_params, })
def dashboard_tile(request, domain, slug): tile = _get_tile(request, slug) current_page = int(request.GET.get('currentPage', 1)) items_per_page = int(request.GET.get('itemsPerPage', 5)) items = list(tile.paginator.paginated_items(current_page, items_per_page)) return json_response({'items': items})
def dashboard_tile_total(request, domain, slug): tile = _get_tile(request, slug) return json_response({'total': tile.paginator.total})
def error(msg, code=400): return json_response({ 'status': 'error', 'message': msg }, status_code=code)
def delete_request(request, domain): DomainRequest.objects.get(id=request.POST['id']).delete() return json_response({'status': 'ok'})
def filter_cases(request, domain, app_id, module_id): app = Application.get(app_id) module = app.get_module(module_id) delegation = request.GET.get('task-list') == 'true' auth_cookie = request.COOKIES.get('sessionid') suite_gen = SuiteGenerator(app) xpath = suite_gen.get_filter_xpath(module, delegation=delegation) extra_instances = [{ 'id': inst.id, 'src': inst.src } for inst in suite_gen.get_instances_for_module( module, additional_xpaths=[xpath])] # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) if delegation: case_type = DELEGATION_STUB_CASE_TYPE else: case_type = module.case_type if xpath: # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } helper = SessionDataHelper(domain, request.couch_user) result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie), extra_instances=extra_instances) if result.get('status', None) == 'error': return HttpResponseServerError( result.get("message", _("Something went wrong filtering your cases."))) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [ res.id for res in get_filtered_cases(domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, ids_only=True) ] cases = [ CommCareCase.wrap(doc) for doc in iter_docs(CommCareCase.get_db(), case_ids) ] # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.get_json(lite=True) for c in cases if c] parents = [] if delegation: for case in cases: parent_id = case['indices']['parent']['case_id'] parents.append(CommCareCase.get(parent_id)) return json_response({'cases': cases, 'parents': parents}) else: return json_response(cases)
def delete_invitation(request, domain): invitation_id = request.POST['id'] invitation = Invitation.get(invitation_id) invitation.delete() return json_response({'status': 'ok'})
assert case.domain == domain cases = [CaseAPIResult(id=case_id, couch_doc=case, id_only=ids_only)] else: filters = get_filters_from_request(request) status = api_closed_to_status(request.REQUEST.get('closed', 'false')) case_type = filters.get('properties/case_type', None) cases = get_filtered_cases(domain, status=status, case_type=case_type, user_id=user_id, filters=filters, footprint=footprint, ids_only=ids_only, strip_history=True, include_children=include_children) return json_response(cases) @cloudcare_api def filter_cases(request, domain, app_id, module_id): app = Application.get(app_id) module = app.get_module(module_id) delegation = request.GET.get('task-list') == 'true' auth_cookie = request.COOKIES.get('sessionid') suite_gen = SuiteGenerator(app) xpath = suite_gen.get_filter_xpath(module, delegation=delegation) extra_instances = [{ 'id': inst.id, 'src': inst.src } for inst in suite_gen.get_instances_for_module(
def location_descendants_count(request, domain, loc_id): location = SQLLocation.objects.get(location_id=loc_id) if location.domain != domain: raise Http404() count = len(location.get_descendants(include_self=True)) return json_response({'count': count})
def json_response(self): """ Intention: Not to be overridden in general. Renders the json version for the report, if available. """ return json_response(self.json_dict)
def tables(request, domain): if request.method == 'GET': return json_response( [strip_json(x) for x in FixtureDataType.by_domain(domain)])
def filter_cases(request, domain, app_id, module_id, parent_id=None): app = Application.get(app_id) module = app.get_module(module_id) auth_cookie = request.COOKIES.get('sessionid') requires_parent_cases = string_to_boolean( request.GET.get('requires_parent_cases', 'false')) xpath = EntriesHelper.get_filter_xpath(module) instances = get_instances_for_module(app, module, additional_xpaths=[xpath]) extra_instances = [{'id': inst.id, 'src': inst.src} for inst in instances] use_formplayer = toggles.USE_FORMPLAYER.enabled(domain) accessor = CaseAccessors(domain) # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) case_type = module.case_type if xpath or should_use_sql_backend(domain): # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } helper = BaseSessionDataHelper(domain, request.couch_user) result = helper.filter_cases(xpath, additional_filters, DjangoAuth(auth_cookie), extra_instances=extra_instances, use_formplayer=use_formplayer) if result.get('status', None) == 'error': code = result.get('code', 500) message = result.get( 'message', _("Something went wrong filtering your cases.")) if code == 500: notify_exception(None, message=message) return json_response(message, status_code=code) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [ res.id for res in get_filtered_cases( domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, footprint=True, ids_only=True, ) ] cases = accessor.get_cases(case_ids) if parent_id: cases = filter(lambda c: c.parent and c.parent.case_id == parent_id, cases) # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.to_api_json(lite=True) for c in cases if c] response = {'cases': cases} if requires_parent_cases: # Subtract already fetched cases from parent list parent_ids = set(map(lambda c: c['indices']['parent']['case_id'], cases)) - \ set(map(lambda c: c['case_id'], cases)) parents = accessor.get_cases(list(parent_ids)) parents = [c.to_api_json(lite=True) for c in parents] response.update({'parents': parents}) return json_response(response)
def data_source_json(request, domain, config_id): config, _ = get_datasource_config_or_404(config_id, domain) del config._doc['_rev'] return json_response(config)
def update_tables(request, domain, data_type_id=None): """ receives a JSON-update patch like following { "_id":"0920fe1c6d4c846e17ee33e2177b36d6", "tag":"growth", "view_link":"/a/gsid/fixtures/view_lookup_tables/?table_id:0920fe1c6d4c846e17ee33e2177b36d6", "is_global":false, "fields":{"genderr":{"update":"gender"},"grade":{}} } """ if data_type_id: try: data_type = FixtureDataType.get(data_type_id) except ResourceNotFound: raise Http404() if data_type.domain != domain: raise Http404() if request.method == 'GET': return json_response(strip_json(data_type)) elif request.method == 'DELETE': with CouchTransaction() as transaction: data_type.recursive_delete(transaction) clear_fixture_cache(domain) return json_response({}) elif not request.method == 'PUT': return HttpResponseBadRequest() if request.method == 'POST' or request.method == "PUT": fields_update = _to_kwargs(request) fields_patches = fields_update["fields"] data_tag = fields_update["tag"] is_global = fields_update["is_global"] description = fields_update["description"] # validate tag and fields validation_errors = [] if is_identifier_invalid("{}_list".format(data_tag)): validation_errors.append(data_tag) for field_name, options in fields_update['fields'].items(): method = list(options.keys()) if 'update' in method: field_name = options['update'] if is_identifier_invalid(field_name) and 'remove' not in method: validation_errors.append(field_name) validation_errors = [ _("\"%s\" cannot include special characters, begin or end with a space, " "or begin with \"xml\" or a number") % e for e in validation_errors ] if len(data_tag) < 1 or len(data_tag) > 31: validation_errors.append( _("Table ID must be between 1 and 31 characters.")) if validation_errors: return json_response({ 'validation_errors': validation_errors, 'error_msg': _("Could not update table because field names were not " "correctly formatted"), }) with CouchTransaction() as transaction: if data_type_id: data_type = _update_types(fields_patches, domain, data_type_id, data_tag, is_global, description, transaction) _update_items(fields_patches, domain, data_type_id, transaction) else: if FixtureDataType.fixture_tag_exists(domain, data_tag): return HttpResponseBadRequest("DuplicateFixture") else: data_type = _create_types(fields_patches, domain, data_tag, is_global, description, transaction) clear_fixture_cache(domain) return json_response(strip_json(data_type))
instance_id).get_xml() except XFormNotFound: raise Http404() session_extras = {'session_name': session_name, 'app_id': app._id} session_extras.update( get_cloudcare_session_data(domain, form, request.couch_user)) delegation = request.GET.get('task-list') == 'true' session_helper = CaseSessionDataHelper(domain, request.couch_user, case_id, app, form, delegation=delegation) return json_response( session_helper.get_full_context(root_context, session_extras)) cloudcare_api = login_or_digest_ex(allow_cc_users=True) class ReadableQuestions(View): urlname = 'readable_questions' @csrf_exempt @method_decorator(cloudcare_api) def dispatch(self, request, *args, **kwargs): return super(ReadableQuestions, self).dispatch(request, *args, **kwargs)
def fixture_metadata(request, domain): """ Returns list of fixtures and metadata needed for itemsets in vellum """ return json_response(item_lists_by_domain(domain))
def get_app_api(request, domain, app_id): return json_response(look_up_app_json(domain, app_id))
def report_source_json(request, domain, report_id): config = get_document_or_404(ReportConfiguration, domain, report_id) del config._doc['_rev'] return json_response(config)
def edit_module_detail_screens(request, domain, app_id, module_unique_id): """ Overwrite module case details. Only overwrites components that have been provided in the request. Components are short, long, filter, parent_select, fixture_select and sort_elements. """ params = json_request(request.POST) detail_type = params.get('type') short = params.get('short', None) long_ = params.get('long', None) tabs = params.get('tabs', None) filter = params.get('filter', ()) custom_xml = params.get('custom_xml', None) parent_select = params.get('parent_select', None) fixture_select = params.get('fixture_select', None) sort_elements = params.get('sort_elements', None) persist_case_context = params.get('persistCaseContext', None) persistent_case_context_xml = params.get('persistentCaseContextXML', None) use_case_tiles = params.get('useCaseTiles', None) persist_tile_on_forms = params.get("persistTileOnForms", None) persistent_case_tile_from_module = params.get("persistentCaseTileFromModule", None) pull_down_tile = params.get("enableTilePullDown", None) sort_nodeset_columns = params.get("sortNodesetColumns", None) print_template = params.get('printTemplate', None) case_list_lookup = params.get("case_list_lookup", None) search_properties = params.get("search_properties") custom_variables = { 'short': params.get("short_custom_variables", None), 'long': params.get("long_custom_variables", None) } app = get_app(domain, app_id) try: module = app.get_module_by_unique_id(module_unique_id) except ModuleNotFoundException: # temporary fallback module = app.get_module(module_unique_id) if detail_type == 'case': detail = module.case_details else: try: detail = getattr(module, '{0}_details'.format(detail_type)) except AttributeError: return HttpResponseBadRequest("Unknown detail type '%s'" % detail_type) lang = request.COOKIES.get('lang', app.langs[0]) if short is not None: detail.short.columns = list(map(DetailColumn.from_json, short)) if persist_case_context is not None: detail.short.persist_case_context = persist_case_context detail.short.persistent_case_context_xml = persistent_case_context_xml if use_case_tiles is not None: detail.short.use_case_tiles = use_case_tiles if persist_tile_on_forms is not None: detail.short.persist_tile_on_forms = persist_tile_on_forms if persistent_case_tile_from_module is not None: detail.short.persistent_case_tile_from_module = persistent_case_tile_from_module if pull_down_tile is not None: detail.short.pull_down_tile = pull_down_tile if case_list_lookup is not None: _save_case_list_lookup_params(detail.short, case_list_lookup, lang) if long_ is not None: detail.long.columns = list(map(DetailColumn.from_json, long_)) if tabs is not None: detail.long.tabs = list(map(DetailTab.wrap, tabs)) if print_template is not None: detail.long.print_template = print_template if filter != (): # Note that we use the empty tuple as the sentinel because a filter # value of None represents clearing the filter. detail.short.filter = filter if custom_xml is not None: detail.short.custom_xml = custom_xml if custom_variables['short'] is not None: try: etree.fromstring("<variables>{}</variables>".format(custom_variables['short'])) except etree.XMLSyntaxError as error: return HttpResponseBadRequest( "There was an issue with your custom variables: {}".format(error.message) ) detail.short.custom_variables = custom_variables['short'] if custom_variables['long'] is not None: try: etree.fromstring("<variables>{}</variables>".format(custom_variables['long'])) except etree.XMLSyntaxError as error: return HttpResponseBadRequest( "There was an issue with your custom variables: {}".format(error.message) ) detail.long.custom_variables = custom_variables['long'] if sort_nodeset_columns is not None: detail.long.sort_nodeset_columns = sort_nodeset_columns if sort_elements is not None: # Attempt to map new elements to old so we don't lose translations # Imperfect because the same field may be used multiple times, or user may change field old_elements_by_field = {e['field']: e for e in detail.short.sort_elements} detail.short.sort_elements = [] for sort_element in sort_elements: item = SortElement() item.field = sort_element['field'] item.type = sort_element['type'] item.direction = sort_element['direction'] item.blanks = sort_element['blanks'] if item.field in old_elements_by_field: item.display = old_elements_by_field[item.field].display item.display[lang] = sort_element['display'] if toggles.SORT_CALCULATION_IN_CASE_LIST.enabled(domain): item.sort_calculation = sort_element['sort_calculation'] else: item.sort_calculation = "" detail.short.sort_elements.append(item) if parent_select is not None: module.parent_select = ParentSelect.wrap(parent_select) if module_case_hierarchy_has_circular_reference(module): return HttpResponseBadRequest(_("The case hierarchy contains a circular reference.")) if fixture_select is not None: module.fixture_select = FixtureSelect.wrap(fixture_select) if search_properties is not None: if ( search_properties.get('properties') is not None or search_properties.get('default_properties') is not None ): module.search_config = CaseSearch( properties=[ CaseSearchProperty.wrap(p) for p in _update_search_properties( module, search_properties.get('properties'), lang ) ], relevant=( search_properties.get('relevant') if search_properties.get('relevant') is not None else CLAIM_DEFAULT_RELEVANT_CONDITION ), include_closed=bool(search_properties.get('include_closed')), search_button_display_condition=search_properties.get('search_button_display_condition', ""), blacklisted_owner_ids_expression=search_properties.get('blacklisted_owner_ids_expression', ""), default_properties=[ DefaultCaseSearchProperty.wrap(p) for p in search_properties.get('default_properties') ] ) resp = {} app.save(resp) return json_response(resp)
def download_item_lists(request, domain, html_response=False): """ Is used to serve excel_download and html_view for view_lookup_tables """ table_ids = request.GET.getlist("table_id") if table_ids and table_ids[0]: try: data_types_view = [ FixtureDataType.get(id) for id in request.GET.getlist("table_id") ] except ResourceNotFound as Ex: if html_response: messages.info( request, _("Sorry, we couldn't find that table. If you think this is a mistake please report an issue." )) raise data_types_view = FixtureDataType.by_domain(domain) else: data_types_view = FixtureDataType.by_domain(domain) if html_response: data_types_view = list(data_types_view)[0:1] # book-keeping data from view_results for repeated use data_types_book = [] data_items_book_by_type = {} item_helpers_by_type = {} """ Contains all excel sheets in following format excel_sheets = { "types": { "headers": [], "rows": [(row), (row), (row)] } "next-sheet": { "headers": [], "rows": [(row), (row), (row)] }, ... } """ excel_sheets = {} def empty_padding_list(length): return ["" for x in range(0, length)] max_fields = 0 """ - Helper to generate headers like "field 2: property 1" - Captures max_num_of_properties for any field of any type at the list-index. Example values: [0, 1] -> "field 2: property 1" (first-field has zero-props, second has 1 property) [1, 1] -> "field 1: property 1" (first-field has 1 property, second has 1 property) [0, 2] -> "field 2: property 1", "field 2: property 2" """ field_prop_count = [] """ captures all possible 'field-property' values for each data-type Example value {u'clinics': {'field 2 : property 1': u'lang'}, u'growth_chart': {'field 2 : property 2': u'maxWeight'}} """ type_field_properties = {} get_field_prop_format = lambda x, y: "field " + str( x) + " : property " + str(y) for data_type in data_types_view: # Helpers to generate 'types' sheet type_field_properties[data_type.tag] = {} data_types_book.append(data_type) if len(data_type.fields) > max_fields: max_fields = len(data_type.fields) for index, field in enumerate(data_type.fields): if len(field_prop_count) <= index: field_prop_count.append(len(field.properties)) elif field_prop_count[index] <= len(field.properties): field_prop_count[index] = len(field.properties) if len(field.properties) > 0: for prop_index, property in enumerate(field.properties): prop_key = get_field_prop_format(index + 1, prop_index + 1) type_field_properties[data_type.tag][prop_key] = property # Helpers to generate item-sheets data_items_book_by_type[data_type.tag] = [] max_users = 0 max_groups = 0 max_field_prop_combos = { field_name: 0 for field_name in data_type.fields_without_attributes } for item_row in FixtureDataItem.by_data_type(domain, data_type.get_id): data_items_book_by_type[data_type.tag].append(item_row) group_len = len(item_row.groups) max_groups = group_len if group_len > max_groups else max_groups user_len = len(item_row.users) max_users = user_len if user_len > max_users else max_users for field_key in item_row.fields: max_combos = max_field_prop_combos[field_key] cur_combo_len = len(item_row.fields[field_key].field_list) max_combos = cur_combo_len if cur_combo_len > max_combos else max_combos max_field_prop_combos[field_key] = max_combos item_helpers = { "max_users": max_users, "max_groups": max_groups, "max_field_prop_combos": max_field_prop_combos, } item_helpers_by_type[data_type.tag] = item_helpers # Prepare 'types' sheet data types_sheet = {"headers": [], "rows": []} types_sheet["headers"] = [DELETE_HEADER, "table_id", 'is_global?'] types_sheet["headers"].extend( ["field %d" % x for x in range(1, max_fields + 1)]) field_prop_headers = [] for field_num, prop_num in enumerate(field_prop_count): if prop_num > 0: for c in range(0, prop_num): prop_key = get_field_prop_format(field_num + 1, c + 1) field_prop_headers.append(prop_key) types_sheet["headers"].append(prop_key) for data_type in data_types_book: common_vals = ["N", data_type.tag, yesno(data_type.is_global)] field_vals = [ field.field_name for field in data_type.fields ] + empty_padding_list(max_fields - len(data_type.fields)) prop_vals = [] if type_field_properties.has_key(data_type.tag): props = type_field_properties.get(data_type.tag) prop_vals.extend( [props.get(key, "") for key in field_prop_headers]) row = tuple(common_vals[2 if html_response else 0:] + field_vals + prop_vals) types_sheet["rows"].append(row) types_sheet["rows"] = tuple(types_sheet["rows"]) types_sheet["headers"] = tuple(types_sheet["headers"]) excel_sheets["types"] = types_sheet # Prepare 'items' sheet data for each data-type for data_type in data_types_book: item_sheet = {"headers": [], "rows": []} item_helpers = item_helpers_by_type[data_type.tag] max_users = item_helpers["max_users"] max_groups = item_helpers["max_groups"] max_field_prop_combos = item_helpers["max_field_prop_combos"] common_headers = ["UID", DELETE_HEADER] user_headers = ["user %d" % x for x in range(1, max_users + 1)] group_headers = ["group %d" % x for x in range(1, max_groups + 1)] field_headers = [] for field in data_type.fields: if len(field.properties) == 0: field_headers.append("field: " + field.field_name) else: prop_headers = [] for x in range(1, max_field_prop_combos[field.field_name] + 1): for property in field.properties: prop_headers.append("%(name)s: %(prop)s %(count)s" % { "name": field.field_name, "prop": property, "count": x }) prop_headers.append("field: %(name)s %(count)s" % { "name": field.field_name, "count": x }) field_headers.extend(prop_headers) item_sheet["headers"] = tuple( common_headers[2 if html_response else 0:] + field_headers + user_headers + group_headers) excel_sheets[data_type.tag] = item_sheet for item_row in data_items_book_by_type[data_type.tag]: common_vals = [str(_id_from_doc(item_row)), "N"] user_vals = [ user.raw_username for user in item_row.users ] + empty_padding_list(max_users - len(item_row.users)) group_vals = [ group.name for group in item_row.groups ] + empty_padding_list(max_groups - len(item_row.groups)) field_vals = [] for field in data_type.fields: if len(field.properties) == 0: if any(item_row.fields.get(field.field_name).field_list): value = item_row.fields.get( field.field_name).field_list[0].field_value else: value = "" field_vals.append(value) else: field_prop_vals = [] cur_combo_count = len( item_row.fields.get(field.field_name).field_list) cur_prop_count = len(field.properties) for count, field_prop_combo in enumerate( item_row.fields.get(field.field_name).field_list): for property in field.properties: field_prop_vals.append( field_prop_combo.properties.get( property, None) or "") field_prop_vals.append(field_prop_combo.field_value) padding_list_len = ( max_field_prop_combos[field.field_name] - cur_combo_count) * (cur_prop_count + 1) field_prop_vals.extend( empty_padding_list(padding_list_len)) # import pdb; pdb.set_trace(); field_vals.extend(field_prop_vals) row = tuple(common_vals[2 if html_response else 0:] + field_vals + user_vals + group_vals) item_sheet["rows"].append(row) item_sheet["rows"] = tuple(item_sheet["rows"]) excel_sheets[data_type.tag] = item_sheet if html_response: return excel_sheets header_groups = [("types", excel_sheets["types"]["headers"])] value_groups = [("types", excel_sheets["types"]["rows"])] for data_type in data_types_book: header_groups.append( (data_type.tag, excel_sheets[data_type.tag]["headers"])) value_groups.append( (data_type.tag, excel_sheets[data_type.tag]["rows"])) fd, path = tempfile.mkstemp() with os.fdopen(fd, 'w') as temp: export_raw(tuple(header_groups), tuple(value_groups), temp) format = Format.XLS_2007 fl = open(path, 'r') fileref = expose_download( fl.read(), 60 * 10, mimetype=Format.from_format(format).mimetype, content_disposition='attachment; filename="%s_fixtures.xlsx"' % domain, ) return json_response({"download_id": fileref.download_id})
def get_sessions(request, domain): # is it ok to pull user from the request? other api calls seem to have an explicit 'user' param skip = request.GET.get('skip') or 0 limit = request.GET.get('limit') or 10 return json_response( get_open_form_sessions(request.user, skip=skip, limit=limit))
def delete_invitation(request, domain): uuid = request.POST['uuid'] invitation = Invitation.objects.get(uuid=uuid) invitation.delete() return json_response({'status': 'ok'})
def _edit_form_attr(request, domain, app_id, form_unique_id, attr): """ Called to edit any (supported) form attribute, given by attr """ ajax = json.loads(request.POST.get('ajax', 'true')) resp = {} app = get_app(domain, app_id) try: form = app.get_form(form_unique_id) except FormNotFoundException as e: if ajax: return HttpResponseBadRequest(six.text_type(e)) else: messages.error(request, _("There was an error saving, please try again!")) return back_to_main(request, domain, app_id=app_id) lang = request.COOKIES.get('lang', app.langs[0]) def should_edit(attribute): return attribute in request.POST if should_edit("name"): name = request.POST['name'] form.name[lang] = name if not form.form_type == "shadow_form": xform = form.wrapped_xform() if xform.exists(): xform.set_name(name) save_xform(app, form, xform.render()) resp['update'] = { '.variable-form_name': trans(form.name, [lang], use_delim=False) } if should_edit('comment'): form.comment = request.POST['comment'] if should_edit("xform") or "xform" in request.FILES: try: # support FILES for upload and POST for ajax post from Vellum try: xform = request.FILES.get('xform').read() except Exception: xform = request.POST.get('xform') else: try: xform = six.text_type(xform, encoding="utf-8") except Exception: raise Exception( "Error uploading form: Please make sure your form is encoded in UTF-8" ) if request.POST.get('cleanup', False): try: # First, we strip all newlines and reformat the DOM. px = parseString(xform.replace('\r\n', '')).toprettyxml() # Then we remove excess newlines from the DOM output. text_re = re.compile('>\n\s+([^<>\s].*?)\n\s+</', re.DOTALL) prettyXml = text_re.sub('>\g<1></', px) xform = prettyXml except Exception: pass if xform: save_xform(app, form, xform) else: raise Exception("You didn't select a form to upload") except Exception as e: if ajax: return HttpResponseBadRequest(six.text_type(e)) else: messages.error(request, six.text_type(e)) if should_edit("references") or should_edit("case_references"): form.case_references = _get_case_references(request.POST) if should_edit("show_count"): show_count = request.POST['show_count'] form.show_count = True if show_count == "True" else False if should_edit("put_in_root"): put_in_root = request.POST['put_in_root'] form.put_in_root = True if put_in_root == "True" else False if should_edit('form_filter'): form.form_filter = request.POST['form_filter'] if should_edit('post_form_workflow'): form.post_form_workflow = request.POST['post_form_workflow'] if should_edit('auto_gps_capture'): form.auto_gps_capture = request.POST['auto_gps_capture'] == 'true' if should_edit('no_vellum'): form.no_vellum = request.POST['no_vellum'] == 'true' if (should_edit("form_links_xpath_expressions") and should_edit("form_links_form_ids") and toggles.FORM_LINK_WORKFLOW.enabled(domain)): form_links = zip( request.POST.getlist('form_links_xpath_expressions'), request.POST.getlist('form_links_form_ids'), [ json.loads(datum_json) if datum_json else [] for datum_json in request.POST.getlist('datums_json') ], ) form.form_links = [ FormLink(xpath=link[0], form_id=link[1], datums=[ FormDatum(name=datum['name'], xpath=datum['xpath']) for datum in link[2] ]) for link in form_links ] if should_edit('post_form_workflow_fallback'): form.post_form_workflow_fallback = request.POST.get( 'post_form_workflow_fallback') if should_edit('custom_instances'): instances = json.loads(request.POST.get('custom_instances')) try: # validate that custom instances can be added into the XML for instance in instances: etree.fromstring("<instance id='{}' src='{}' />".format( instance.get('instanceId'), instance.get('instancePath'))) except etree.XMLSyntaxError as error: return json_response( { 'message': _("There was an issue with your custom instances: {}"). format(error.message) }, status_code=400) form.custom_instances = [ CustomInstance( instance_id=instance.get("instanceId"), instance_path=instance.get("instancePath"), ) for instance in instances ] if should_edit("shadow_parent"): form.shadow_parent_form_id = request.POST['shadow_parent'] if should_edit("custom_icon_form"): error_message = handle_custom_icon_edits(request, form, lang) if error_message: return json_response({'message': error_message}, status_code=400) handle_media_edits(request, form, should_edit, resp, lang) app.save(resp) notify_form_changed(domain, request.couch_user, app_id, form_unique_id) if ajax: return HttpResponse(json.dumps(resp)) else: return back_to_main(request, domain, app_id=app_id, form_unique_id=form_unique_id)