def csv_export( request, repo, org, cid, model=None ): """ """ if (not model) or (not (model in ['entity','file'])): raise Http404 collection = Collection.from_request(request) things = {'entity':'objects', 'file':'files'} csv_path = settings.CSV_EXPORT_PATH[model] % collection.id csv_filename = os.path.basename(csv_path) if model == 'entity': file_url = reverse('webui-collection-csv-entities', args=collection.idparts) elif model == 'file': file_url = reverse('webui-collection-csv-files', args=collection.idparts) # do it result = csv_export_model.apply_async( (collection.path,model), countdown=2) # add celery task_id to session celery_tasks = request.session.get(settings.CELERY_TASKS_SESSION_KEY, {}) # IMPORTANT: 'action' *must* match a message in webui.tasks.TASK_STATUS_MESSAGES. task = {'task_id': result.task_id, 'action': 'webui-csv-export-model', 'collection_id': collection.id, 'collection_url': collection.absolute_url(), 'things': things[model], 'file_name': csv_filename, 'file_url': file_url, 'start': datetime.now().strftime(settings.TIMESTAMP_FORMAT),} celery_tasks[result.task_id] = task request.session[settings.CELERY_TASKS_SESSION_KEY] = celery_tasks return HttpResponseRedirect(collection.absolute_url())
def csv_download( request, repo, org, cid, model=None ): """Offers CSV file in settings.CSV_TMPDIR for download. File must actually exist in settings.CSV_EXPORT_PATH and be readable. File must be readable by Python csv module. If all that is true then it must be a legal CSV file. """ collection = Collection.from_request(request) path = settings.CSV_EXPORT_PATH[model] % collection.id filename = os.path.basename(path) if not os.path.exists(path): raise Http404 import csv response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="%s"' % filename writer = csv.writer( response, delimiter=fileio.CSV_DELIMITER, quotechar=fileio.CSV_QUOTECHAR, quoting=fileio.CSV_QUOTING ) with open(path, 'rb') as f: reader = csv.reader( f, delimiter=fileio.CSV_DELIMITER, quotechar=fileio.CSV_QUOTECHAR, quoting=fileio.CSV_QUOTING ) for row in reader: writer.writerow(row) return response
def changelog( request, repo, org, cid ): collection = Collection.from_request(request) alert_if_conflicted(request, collection) return render_to_response( 'webui/collections/changelog.html', {'collection': collection,}, context_instance=RequestContext(request, processors=[]) )
def newexpert( request, repo, org, cid ): """Ask for Entity ID, then create new Entity. """ git_name = request.session.get('git_name') git_mail = request.session.get('git_mail') if not git_name and git_mail: messages.error(request, WEBUI_MESSAGES['LOGIN_REQUIRED']) collection = Collection.from_request(request) if collection.locked(): messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_LOCKED'].format(collection.id)) return HttpResponseRedirect(entity.absolute_url()) collection.repo_fetch() if collection.repo_behind(): messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_BEHIND'].format(collection.id)) return HttpResponseRedirect(entity.absolute_url()) if request.method == 'POST': form = NewEntityForm(request.POST) if form.is_valid(): # TODO replace with Identifier entity_id = '-'.join([repo, org, str(cid), str(form.cleaned_data['eid'])]) entity_ids = [entity.id for entity in collection.entities(quick=True)] is_legal = False already_exists = False if '-'.join([repo, org, str(cid)]) == collection.id: is_legal = True else: messages.error(request, "Can only create objects in this collection. Try again.") if entity_id in entity_ids: already_exists = True messages.error(request, "That object ID already exists. Try again.") if entity_id and is_legal and not already_exists: collection_entity_newexpert( request, collection, entity_id, git_name, git_mail ) return HttpResponseRedirect(reverse('webui-collection-children', args=collection.idparts)) else: data = { 'repo':repo, 'org':org, 'cid':cid, } form = NewEntityForm(data) return render_to_response( 'webui/entities/new.html', {'repo': repo, 'org': org, 'cid': cid, 'collection': collection, 'form': form, }, context_instance=RequestContext(request, processors=[]) )
def merge( request, repo, org, cid ): """ Decides how to merge the various files in a merge conflict. Sends user around to different editors and things until everything is merged. """ collection = Collection.from_request(request) repository = dvcs.repository(collection.path_abs) task_id = collection.locked() status = commands.status(collection) ahead = collection.repo_ahead() behind = collection.repo_behind() diverged = collection.repo_diverged() conflicted = collection.repo_conflicted() unmerged = dvcs.list_conflicted(repository) staged = dvcs.list_staged(repository) if request.method == 'POST': form = MergeCommitForm(request.POST) if form.is_valid(): which = form.cleaned_data['which'] if which == 'merge': dvcs.merge_commit(repository) committed = 1 elif which == 'commit': dvcs.diverge_commit(repository) committed = 1 else: committed = 0 if committed: if task_id: collection.unlock(task_id) messages.error(request, 'Merge conflict has been resolved. Please sync to make your changes available to other users.') return HttpResponseRedirect( reverse('webui-collection', args=[repo,org,cid]) ) return HttpResponseRedirect( reverse('webui-merge', args=[repo,org,cid]) ) else: which = 'unknown' if conflicted and not unmerged: which = 'merge' elif diverged and staged: which = 'commit' form = MergeCommitForm({'path':collection.path, 'which':which,}) return render_to_response( 'webui/merge/index.html', {'repo': repo, 'org': org, 'cid': cid, 'collection_path': collection.path, 'collection': collection, 'status': status, 'conflicted': conflicted, 'ahead': ahead, 'behind': behind, 'unmerged': unmerged, 'diverged': diverged, 'staged': staged, 'form': form,}, context_instance=RequestContext(request, processors=[]) )
def sync_status_ajax( request, repo, org, cid ): collection = Collection.from_request(request) gitstatus = collection.gitstatus() if gitstatus: sync_status = gitstatus['sync_status'] if sync_status.get('timestamp',None): sync_status['timestamp'] = sync_status['timestamp'].strftime(settings.TIMESTAMP_FORMAT) return HttpResponse(json.dumps(sync_status), content_type="application/json") raise Http404
def detail( request, repo, org, cid ): collection = Collection.from_request(request) collection.model_def_commits() collection.model_def_fields() alert_if_conflicted(request, collection) return render_to_response( 'webui/collections/detail.html', {'collection': collection, 'collection_unlock_url': collection.unlock_url(collection.locked()),}, context_instance=RequestContext(request, processors=[]) )
def unlock( request, repo, org, cid, task_id ): """Provides a way to remove collection lockfile through the web UI. """ git_name = request.session.get('git_name') git_mail = request.session.get('git_mail') if not git_name and git_mail: messages.error(request, WEBUI_MESSAGES['LOGIN_REQUIRED']) collection = Collection.from_request(request) if task_id and collection.locked() and (task_id == collection.locked()): collection.unlock(task_id) messages.success(request, 'Collection <b>%s</b> unlocked.' % collection.id) return HttpResponseRedirect(collection.absolute_url())
def git_status( request, repo, org, cid ): collection = Collection.from_request(request) alert_if_conflicted(request, collection) gitstatus = collection.gitstatus() remotes = dvcs.remotes(dvcs.repository(collection.path)) return render_to_response( 'webui/collections/git-status.html', {'collection': collection, 'status': gitstatus.get('status', 'git-status unavailable'), 'astatus': gitstatus.get('annex_status', 'annex-status unavailable'), 'timestamp': gitstatus.get('timestamp'), 'remotes': remotes, }, context_instance=RequestContext(request, processors=[]) )
def children( request, repo, org, cid ): collection = Collection.from_request(request) alert_if_conflicted(request, collection) objects = collection.children(quick=True) # paginate thispage = request.GET.get('page', 1) paginator = Paginator(objects, settings.RESULTS_PER_PAGE) page = paginator.page(thispage) return render_to_response( 'webui/collections/entities.html', {'collection': collection, 'paginator': paginator, 'page': page, 'thispage': thispage,}, context_instance=RequestContext(request, processors=[]) )
def edit( request, repo, org, cid ): git_name = request.session.get('git_name') git_mail = request.session.get('git_mail') if not git_name and git_mail: messages.error(request, WEBUI_MESSAGES['LOGIN_REQUIRED']) collection = Collection.from_request(request) module = collection.identifier.fields_module() collection.model_def_commits() collection.model_def_fields() if collection.locked(): messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_LOCKED'].format(collection.id)) return HttpResponseRedirect(collection.absolute_url()) collection.repo_fetch() if collection.repo_behind(): messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_BEHIND'].format(collection.id)) return HttpResponseRedirect(collection.absolute_url()) if request.method == 'POST': form = DDRForm(request.POST, fields=module.FIELDS) if form.is_valid(): collection.form_post(form) collection.write_json() collection.write_ead() updated_files = [collection.json_path, collection.ead_path,] # if inheritable fields selected, propagate changes to child objects inheritables = collection.selected_inheritables(form.cleaned_data) modified_ids,modified_files = collection.update_inheritables(inheritables, form.cleaned_data) if modified_files: updated_files = updated_files + modified_files # commit files, delete cache, update search index, update git status collection_edit(request, collection, updated_files, git_name, git_mail) return HttpResponseRedirect(collection.absolute_url()) else: form = DDRForm(collection.form_prep(), fields=module.FIELDS) return render_to_response( 'webui/collections/edit-json.html', {'collection': collection, 'form': form, }, context_instance=RequestContext(request, processors=[]) )
def edit_auto( request, repo, org, cid ): git_name = request.session.get('git_name') git_mail = request.session.get('git_mail') if not git_name and git_mail: messages.error(request, WEBUI_MESSAGES['LOGIN_REQUIRED']) collection = Collection.from_request(request) filename = request.GET.get('filename', None) filepath = os.path.join(collection.path, filename) with open(filepath, 'r') as f: text = f.read() merged = dvcs.automerge_conflicted(text, 'left') with open(filepath, 'w') as f: f.write(merged) # TODO git add FILENAME return HttpResponseRedirect(reverse('webui-merge', args=[repo,org,cid]))
def sync( request, repo, org, cid ): try: collection = Collection.from_request(request) except: raise Http404 git_name = request.session.get('git_name') git_mail = request.session.get('git_mail') if not git_name and git_mail: messages.error(request, WEBUI_MESSAGES['LOGIN_REQUIRED']) alert_if_conflicted(request, collection) if collection.locked(): messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_LOCKED'].format(collection.id)) return HttpResponseRedirect(collection.absolute_url()) if request.method == 'POST': form = SyncConfirmForm(request.POST) form_is_valid = form.is_valid() if form.is_valid() and form.cleaned_data['confirmed']: result = collection_sync.apply_async( (git_name,git_mail,collection.path), countdown=2) lockstatus = collection.lock(result.task_id) # add celery task_id to session celery_tasks = request.session.get(settings.CELERY_TASKS_SESSION_KEY, {}) # IMPORTANT: 'action' *must* match a message in webui.tasks.TASK_STATUS_MESSAGES. task = {'task_id': result.task_id, 'action': 'webui-collection-sync', 'collection_id': collection.id, 'collection_url': collection.absolute_url(), 'start': datetime.now().strftime(settings.TIMESTAMP_FORMAT),} celery_tasks[result.task_id] = task request.session[settings.CELERY_TASKS_SESSION_KEY] = celery_tasks return HttpResponseRedirect(collection.absolute_url()) #else: # assert False else: form = SyncConfirmForm() return render_to_response( 'webui/collections/sync-confirm.html', {'collection': collection, 'form': form,}, context_instance=RequestContext(request, processors=[]) )
def edit_json( request, repo, org, cid ): """ """ collection = Collection.from_request(request) repository = dvcs.repository(collection.path) filename = '' if request.method == 'POST': filename = request.POST.get('filename', None) elif request.method == 'GET': filename = request.GET.get('filename', None) fields = [] if filename: path = os.path.join(collection.path, filename) with open(path, 'r') as f: txt = f.read() fields = dvcs.conflicting_fields(txt) if request.method == 'POST': #form = MergeJSONForm(request.POST) #if form.is_valid(): # text = form.cleaned_data['text'] # # TODO validate XML # with open(filepath, 'w') as f: # f.write(text) # # git add file # dvcs.merge_add(repository, filename) assert False elif request.method == 'GET': form = MergeJSONForm(fields=fields) return render_to_response( 'webui/merge/edit-json.html', {'filename':filename, 'fields':fields, 'form':form,}, context_instance=RequestContext(request, processors=[]) ) return HttpResponseRedirect( reverse('webui-merge', args=[repo,org,cid]) )
def edit_raw( request, repo, org, cid ): """ """ git_name = request.session.get('git_name') git_mail = request.session.get('git_mail') if not git_name and git_mail: messages.error(request, WEBUI_MESSAGES['LOGIN_REQUIRED']) collection = Collection.from_request(request) repository = dvcs.repository(collection.path) filename = '' if request.method == 'POST': filename = request.POST.get('filename', None) elif request.method == 'GET': filename = request.GET.get('filename', None) filepath = os.path.join(collection.path, filename) if request.method == 'POST': form = MergeRawForm(request.POST) if form.is_valid(): text = form.cleaned_data['text'] # TODO validate XML with open(filepath, 'w') as f: f.write(text) # git add file dvcs.merge_add(repository, filename) return HttpResponseRedirect( reverse('webui-merge', args=[repo,org,cid]) ) else: with open(filepath, 'r') as f: text = f.read() form = MergeRawForm({'filename': filename, 'text': text,}) return render_to_response( 'webui/merge/edit-raw.html', {'repo': repo, 'org': org, 'cid': cid, 'filename':filename, 'form': form,}, context_instance=RequestContext(request, processors=[]) )
def new( request, repo, org, cid ): """Gets new EID from workbench, creates new entity record. If it messes up, goes back to collection. """ git_name = request.session.get('git_name') git_mail = request.session.get('git_mail') if not (git_name and git_mail): messages.error(request, WEBUI_MESSAGES['LOGIN_REQUIRED']) collection = Collection.from_request(request) if collection.locked(): messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_LOCKED'].format(collection.id)) return HttpResponseRedirect(collection.absolute_url()) collection.repo_fetch() if collection.repo_behind(): messages.error(request, WEBUI_MESSAGES['VIEWS_COLL_BEHIND'].format(collection.id)) return HttpResponseRedirect(collection.absolute_url()) ic = idservice.IDServiceClient() # resume session auth_status,auth_reason = ic.resume(request.session['idservice_token']) if auth_status != 200: request.session['idservice_username'] = None request.session['idservice_token'] = None messages.warning( request, 'Session resume failed: %s %s (%s)' % ( auth_status,auth_reason,settings.IDSERVICE_API_BASE ) ) return HttpResponseRedirect(collection.absolute_url()) # get new entity ID http_status,http_reason,new_entity_id = ic.next_object_id( collection.identifier, 'entity' ) if http_status not in [200,201]: err = '%s %s' % (http_status, http_reason) msg = WEBUI_MESSAGES['VIEWS_ENT_ERR_NO_IDS'] % (settings.IDSERVICE_API_BASE, err) logger.error(msg) messages.error(request, msg) return HttpResponseRedirect(collection.absolute_url()) eidentifier = Identifier(id=new_entity_id) # create new entity entity_path = eidentifier.path_abs() # write entity.json template to entity location fileio.write_text( Entity(entity_path).dump_json(template=True), settings.TEMPLATE_EJSON ) # commit files exit,status = commands.entity_create( git_name, git_mail, collection, eidentifier, [collection.json_path_rel, collection.ead_path_rel], [settings.TEMPLATE_EJSON, settings.TEMPLATE_METS], agent=settings.AGENT ) # load Entity object, inherit values from parent, write back to file entity = Entity.from_identifier(eidentifier) entity.inherit(collection) entity.write_json() updated_files = [entity.json_path] exit,status = commands.entity_update( git_name, git_mail, collection, entity, updated_files, agent=settings.AGENT ) collection.cache_delete() if exit: logger.error(exit) logger.error(status) messages.error(request, WEBUI_MESSAGES['ERROR'].format(status)) else: # update search index try: entity.post_json(settings.DOCSTORE_HOSTS, settings.DOCSTORE_INDEX) except ConnectionError: logger.error('Could not post to Elasticsearch.') gitstatus_update.apply_async((collection.path,), countdown=2) # positive feedback return HttpResponseRedirect(reverse('webui-entity-edit', args=entity.idparts)) # something happened... logger.error('Could not create new entity!') messages.error(request, WEBUI_MESSAGES['VIEWS_ENT_ERR_CREATE']) return HttpResponseRedirect(collection.absolute_url())
def ead_xml( request, repo, org, cid ): collection = Collection.from_request(request) alert_if_conflicted(request, collection) soup = BeautifulSoup(collection.ead().xml, 'xml') return HttpResponse(soup.prettify(), content_type="application/xml")
def collection_json( request, repo, org, cid ): collection = Collection.from_request(request) alert_if_conflicted(request, collection) return HttpResponse(json.dumps(collection.json().data), content_type="application/json")