Example #1
0
    def imp(self, **params):
        stash = {}

        # Get any existing Importer
        imp = None
        imp_id = getintparam("id", None, stash, params)
        if imp_id is not None:
            imp = self.imports.get(imp_id, None)
            if imp is None:
                context = {}
                context['error'] = 'Unknown import ID'
                return render("import/choose-file.html", context)

        if imp is None:
            # No import in progress
            if cherrypy.request.method == "POST":
                return self.handle_import_start(params)
            elif cherrypy.request.method == "GET":
                return render("import/choose-file.html", {})
        else:
            # Import in progress; let it handle the request.
            if cherrypy.request.method == "POST":
                if getparam("import_cancel", None):
                    imp.cancel()
                    redirect(url("home"))
                return imp.handle_post(params)
            elif cherrypy.request.method == "GET":
                return imp.handle_get(params)

        raise cherrypy.NotFound
Example #2
0
    def from_exploratour(self, **params):
        context = {}

        if cherrypy.request.method == "POST":
            imp = import_exploratour.start_import(params)
            if imp.error:
                context['error'] = imp.error
                return render("import/from-exploratour.html", context)
            self.imports[imp.id] = imp
            redirect(url("import-status", id=imp.id))
        return render("import/from-exploratour.html", context)
Example #3
0
    def export_backup(self, export_id=None, download=False, **params):
        # Read parameters first, to ensure they all get stashed.
        stash = {}

        # Make a new exporter, and get any parameters it needs into the stash.
        exp = Exporter.get('xml')()
        exp.read_params(stash, params)

        # Handle exports which are in progress, or have finished
        if export_id is not None:
            try:
                export_id = int(export_id)
            except ValueError:
                export_id = None
        if export_id is not None:
            try:
                running_exp = exports[export_id]
            except KeyError:
                # Invalid export id (most probably due to a server restart)
                running_exp = None
            if running_exp is not None:
                # Export in progress
                progress = pool.get_progress(export_id)
                context = dict(export_id=export_id, fmt='xml', progress=progress,
                               stash=stash)
                if not progress.complete:
                    return render('export/in_progress.html', context)
                if progress.failed:
                    return render('export/failed.html', context)
                # Export complete
                if not download:
                    # Display a "Export prepared"
                    return render('export/complete.html', context)
                return running_exp.respond()

        # Read the set of things to export.
        search, desc, topcoll = self._get_export_records(stash, None, None, None, True)

        if not getparam('export', False, stash, params):
            # Not ready to start the export yet.
            context = dict(
                           export_desc = desc,
                           stash = stash,
                          )

            exp.add_to_context(context, search, stash, params)
            return render('backup/pick.html', context)

        # Start the exporter
        task = ExportRecords(exp, search)
        export_id = pool.add_task(task)
        exports[export_id] = task

        redirect(url("records-export-inprogress", export_id=export_id, fmt='xml', **stash))
Example #4
0
    def reorder(self, id, **params):
        if getparam('cancel') == '1':
            redirect(url("coll-view", id=id))
        coll = get_or_404(Collection, id)

        context = {}
        if cherrypy.request.method == "POST":
            # FIXME - check csrf token

            order, ordering = coll_order_from_request()

            if getparam('submit') == '1':
                # save order
                coll.autoorder.ordering = ordering
                Collection.objects.set(coll)
                Collection.objects.flush()
                redirect(url("coll-view", id=id))
        else:
            order = []
            for field, dir in coll.autoorder.ordering:
                order.append((len(order), field, dir))

        if not order:
            order.append((0, '', ''))

        context['coll'] = coll
        context['collorder'] = order
        return render("coll-reorder.html", context)
Example #5
0
 def handle_post(self, params, context):
     context.update(self.build_form_context(params))
     do_import = getparam('import', None, None, params)
     if do_import:
         self.set_next(ImportPerformTask(self.handler, self.importer))
         redirect(url("import", id=self.importer.id))
     return render("import/choose-mappings.html", context)
Example #6
0
    def create(self, **params):
        context = {}

        if cherrypy.request.method == "POST":
            # FIXME - check csrf token
            title = params.get('newcoll_title', u'').strip()
            parents = coll_parents_from_request()
            if getparam('create'):
                if title:
                    id = create_collection(title, parents)
                    gonext()
                    redirect(url("colls-list", id=id))
                else:
                    context['error'] = "You must set a title for the collection"
        else:
            parents = []

        allowable_parents = set(
            c.id for c in Collection.objects
        )

        context.update(dict(
            parents = tuple(enumerate(parents)),
            allowable_parents = sorted(allowable_parents),
            collections = Collection.objects,
        ))

        return render("coll-new.html", context)
Example #7
0
 def handle_post(self, params, context):
     context.update(self.build_form_context(params))
     do_import = getparam('import', None, None, params)
     if do_import:
         self.set_next(BuildExploratourRecordsTask(self.handler, self.importer))
         redirect(url("import", id=self.importer.id))
     return render("import/choose-fields.html", context)
Example #8
0
 def index(self):
     context = dict(
         records = len(Record.objects),
         collections = len(Collection.objects),
         templates = len(Template.objects),
     )
     return render("index.html", context)
Example #9
0
def missing_collection(params, context):
    invalid_collections = context['invalid_collections']
    # Only do one missing collection at a time:
    invalid_collection = invalid_collections[0]
    context = dict(invalid_collection=invalid_collection,
                   path=cherrypy.request.path_info)
    return render("missing-collection.html", context)
Example #10
0
    def reindex(self, **params):
        stash = {}
        if cherrypy.request.method == "POST":
            progress = pool.get_progress(reindexer_id[0])
            if progress.complete:
                reindexer_id[0] = pool.add_task(Reindexer())
                redirect(url("reindex"))

        context = dict(progress = pool.get_progress(reindexer_id[0]))
        return render("reindex.html", context)
Example #11
0
 def error_page_404(self, status, message, traceback, version):
     context = dict(
         status=status,
         message=message,
         traceback=traceback,
         version=version,
         records = len(Record.objects),
         collections = len(Collection.objects),
         templates = len(Template.objects),
     )
     add_search_to_context(context)
     return render('errorpages/404.html', context)
Example #12
0
 def handle_import_start(self, params):
     """Handle a POST request that starts an import."""
     if getparam("import_cancel", None):
         redirect(url("home"))
     imp = download.Importer()
     imp.start(params)
     if imp.error:
         context = {}
         context['error'] = imp.error
         return render("import/choose-file.html", context)
     self.imports[imp.id] = imp
     redirect(url("import", id=imp.id))
Example #13
0
    def create(self, **params):
        context = {}

        if cherrypy.request.method == "POST":
            context.update(tmpl_from_request(id, params))
            if context.get('invalid_collections'):
                return missing_collection(params, context)

        elif cherrypy.request.method == "GET":
            context['tmpl'] = Template(u'', None, Record())
        else:
            assert False

        return render("tmpl-new.html", context)
Example #14
0
    def view(self, id, **params):
        context = {}

        stash = {}
        showfull = int(getparam('showfull', '0', stash))
        search = build_search(stash)

        # FIXME - hack
        q = search['q']
        q.startrank = 0
        q.endrank = 20000
        items = q.results

        ids = set()
        for item in items:
            if item.data['type'][0] != 'r': continue
            ids.add(item.data['id'][0])
        points = []
        for id in sorted(ids):
            rec = Record.objects.get(unicode(id))
            date = rec.root.find("field[@type='date']")
            if date is None:
                continue
            date = date.text
            if date is None:
                continue
            mo = single_full_bamboostyle_date_re.match(date) 
            if not mo:
                continue
            day, month, year = map(lambda x: int(x), (mo.group(1), mo.group(2), mo.group(3)))
            date = datetime.date(year, month, day)

            locs = rec.root.findall(".//field[@type='location']")
            for loc in locs:
                ll = latlongparse(loc.get('latlong'))
                if ll is None:
                    continue
                points.append([ll.lat, ll.long, rec.id, date])

        points.sort(key=lambda x: x[3])
        startdate = points[0][3]
        for i in xrange(len(points)):
            days = (points[i][3] - startdate).days
            points[i][3] = points[i][3].isoformat()
            points[i].append(days)

        context['points'] = points
        context['center_point'] = [points[0][0], points[0][1], 7]

        return render("dataview.html", context)
Example #15
0
 def gallery(self, id, show=None, offset=None):
     record = get_or_404(Record, id)
     images = record.media('image')
     if offset is None:
         offset = 0
         if show is not None:
             for num, image in enumerate(images):
                 if image.src == show:
                     offset = num
                     break
     else:
         offset = int(offset)
     context = dict(record=record, images=images, offset=offset)
     return render("record-gallery.html", context)
Example #16
0
 def list(self, **params):
     coll = get_lockto_coll()
     if coll is not None:
         redirect(url("coll-view", id=coll.id))
     groups = [CollGroup(coll.id, coll.title, [coll.id])
               for coll in Collection.objects if not coll.parents]
     groupid = getparam('groupid', '')
     filtered_groups = filter(lambda group: group.id == groupid, groups)
     if len(filtered_groups) > 0:
         currgroup = filtered_groups[0]
     elif len(groups) > 0:
         currgroup = groups[0]
     else:
         currgroup = None
     context = dict(groups=groups, currgroup=currgroup)
     return render("colls-list.html", context)
Example #17
0
    def _check_delete(self, id, page):
        params = cherrypy.request.params
        if params.get('delete', '') != '':
            tmpl = get_or_404(Template, id)
            context = dict(tmpl=tmpl, page=page)
            return render("tmpl-delete-confirm.html", context)

        if cherrypy.request.method == "POST":
            if params.get('delete_conf', '') != '':
                try:
                    Template.objects.remove(id)
                    Template.objects.flush()
                except KeyError:
                    raise cherrypy.HTTPError(404)
                gonext()
                redirect(url("tmpls-list"))
Example #18
0
    def create(self, **params):
        context = {}

        if cherrypy.request.method == "POST":
            context.update(record_from_request(None))
            if context.get('invalid_collections'):
                return missing_collection(params, context)

        if cherrypy.request.method == "GET":
            tmplid = params.get('tmplid', '')
            if tmplid == '':
                context['record'] = Record()
            else:
                context['record'] = get_or_404(Template, tmplid)

        return render("record-new.html", context)
Example #19
0
 def roots(self, **params):
     error = None
     if cherrypy.request.method == "POST":
         num = 0
         roots_dict = {}
         roots = []
         dupe_names = set()
         while True:
             name = params.get('rn%d' % num)
             path = params.get('rp%d' % num)
             num += 1
             if name is None or path is None:
                 break
             if name == '':
                 if path != '':
                     error = u'No name specified for path "%s"' % path
             else:
                 if path == '':
                     error = u'Empty path specified for name "%s"' % name
             if name == '' and path == '':
                 continue
             if name != '' and name in roots_dict:
                 dupe_names.add(name)
             path = path.strip()
             roots_dict[name] = path
             roots.append((num - 1, (name, path)))
         if dupe_names:
             if len(dupe_names) == 1:
                 error = u"Duplicated name: \"%s\"" % tuple(dupe_names)[0]
             else:
                 error = u"Duplicated names: \"%s\"" % u'\", \"'.join(sorted(dupe_names))
         if error is None:
             settings = get_settings()
             settings.set_roots(roots_dict)
             Settings.objects.set(settings)
             Settings.objects.flush()
             redirect(url("settings-roots"))
     else:
         roots_dict = get_settings().get_roots()
         if not roots_dict:
             roots_dict = config.default_media_roots
         roots = tuple(enumerate(sorted(roots_dict.items())))
     context = dict(
         error = error,
         roots = roots,
     )
     return render("settings/roots.html", context)
Example #20
0
    def delete(self, id, **params):
        coll = get_or_404(Collection, id)
        if cherrypy.request.method == "POST":
            # FIXME - check csrf token
            if id:
                if params.get('delete_conf', '') == '':
                    redirect(url("colls-list"))

                coll = get_or_404(Collection, id)

                # Remove the collection's parents
                coll.set_parents(())
                Collection.objects.set(coll)

                # Remove the collection from its childrens parent lists.
                child_colls = coll.children
                for child in child_colls:
                    cparents = set(child.parents)
                    cparents.remove(id)
                    child.set_parents(cparents)
                    Collection.objects.set(child)

                # Iterate through the records in the collection, and remove the
                # collection from them.
                SearchCollection.checkpoint().wait()
                for record in SearchCollection.doc_type('record') \
                   .field.coll.is_in(id)[:]:
                    try:
                        record = record.object
                    except KeyError:
                        # Record is already gone - can't update it.
                        # (This shouldn't happen, but do this check for
                        # robustness.)
                        continue
                    record.collections = filter(lambda x: x != id, record.collections)
                    Record.objects.set(record)

                Collection.objects.remove(id)
                Record.objects.flush()
                Collection.objects.flush()
                gonext()
                redirect(url("colls-list", id=coll.id))
        elif cherrypy.request.method == "GET":
            context = dict(coll=coll)
            return render("coll-delete-confirm.html", context)

        raise cherrypy.HTTPError(404)
Example #21
0
    def mediapreview(self, path, **params):
        try:
            context = dict(path=path, info=mapper.get_file_info(path))
        except OSError:
            raise cherrypy.HTTPError(404)

        add_search_to_context(context)

        q = SearchCollection.doc_type("record").field.fileid == path
        records = []
        for r in q[:100]:
            records.append(r.object)
        # FIXME - handle more than 100 records matching

        context["records"] = records

        return render("media-view.html", context)
Example #22
0
    def edit(self, id, **params):
        context = {}

        ret = self._check_delete(id, 'tmpl-edit')
        if ret is not None:
            return ret

        if cherrypy.request.method == "POST":
            context.update(tmpl_from_request(id, params))
            if context.get('invalid_collections'):
                return missing_collection(params, context)
        elif cherrypy.request.method == "GET":
            context['tmpl'] = get_or_404(Template, id)
        else:
            assert False

        return render("tmpl-edit.html", context)
Example #23
0
    def reparent(self, id, **params):
        if getparam('cancel') == '1':
            redirect(url("coll-view", id=id))
        coll = get_or_404(Collection, id)

        if cherrypy.request.method == "POST":
            # FIXME - check csrf token

            title = getparam('title')
            parents = coll_parents_from_request()

            if getparam('submit') == '1':
                # Save parents
                changed = coll.set_parents(filter(lambda x: x != '', parents))
                if coll.title != title:
                    coll.title = title
                Collection.objects.set(coll)
                Collection.objects.flush()
                Record.objects.flush()
                redirect(url("coll-view", id=id))
        else:
            title = coll.title
            parents = []
            for parent in coll.parents:
                parents.append(parent)
        if not parents:
            parents.append('')

        not_allowed = set(coll.ancestors) - set(coll.parents)
        not_allowed.add(id)

        allowable_parents = set(
            c.id for c in Collection.objects
            if c.id != id and id not in c.ancestors
        )

        context = dict(
            title = title,
            coll = coll,
            parents = tuple(enumerate(parents)),
            allowable_parents = sorted(allowable_parents),
            collections = Collection.objects,
        )

        return render("coll-reparent.html", context)
Example #24
0
    def _check_delete(self, id, page):
        params = cherrypy.request.params
        if params.get('delete', '') != '':
            record = get_or_404(Record, id)
            context = dict(record=record, page=page)
            return render("record-delete-confirm.html", context)

        if cherrypy.request.method == "POST":
            if params.get('delete_conf', '') != '':
                record = get_or_404(Record, id)
                #print "Old collections", record.collections
                record.collections = ()
                # Set the record, to remove the collections 
                Record.objects.set(record)
                Record.objects.remove(id)
                Record.objects.flush()
                Collection.objects.flush()
                gonext()
                redirect(url("search", act='search'))
Example #25
0
    def handle_get(self, params):
        context = dict(status=self._status, import_id=self.id,
                       cancelled=self._cancelled)

        # FIXME - threadsafety of access to _info_getter, _task, _task_id ;
        # they should be atomically read and written.

        if self._info_getter is not None:
            return self._info_getter.handle_get(params, context)

        if self._task is not None:
            progress = pool.get_progress(self._task_id)
            context['status'] = "%s: %s" % (self._status, progress.msg)
            if progress.failed:
                context['status'] = "Failed: %s" % context['status']
                context['finished'] = True
            if progress.complete:
                context['finished'] = True

        if self._task is None and self._info_getter is None:
            context['finished'] = True
        return render("import/status.html", context)
Example #26
0
    def search(self, **params):
        stash = {}
        context = dict(stash=stash)
        params = SearchParams(stash)
        search = Search(params)
        if not search.validate():
            # If the search doesn't validate, always go to the search entry
            # page.
            params.action = 'entry'
        search.add_to_context(context)
        context['showfull'] = int(getparam('showfull', '0', stash))

        if params.action == 'search':
            return render("search.html", context)
        elif params.action == 'select':
            return render("search_select.html", context)

        elif params.action.startswith('createcoll'):
            if cherrypy.request.method != "POST":
                return render("search_createcoll.html", context)
            subact = params.action[11:]

            parents = []
            for num in getorderparam('parent_order'):
                parent = getparam('parent%d' % num)
                if parent is None or parent == '':
                    continue
                if subact == ('del_parent_%d' % num):
                    continue
                parents.append(unicode(parent))
            if subact == 'add_parent':
                parents.append(u'')
            context['parents'] = tuple(enumerate(parents))
            context['allowable_parents'] = set(
                c.id for c in Collection.objects
            )
            context['collections'] = Collection.objects

            if subact == 'do':
                newtitle = getparam('create_colltitle', '')
                if len(newtitle) == 0:
                    context['error'] = "Cannot create collection with no title"
                    return render("search_createcoll.html", context)

                coll = Collection.find_by_title(newtitle)
                if len(coll) != 0:
                    context['error'] = "Collection with title %s already exists" % newtitle
                    return render("search_createcoll.html", context)

                coll = Collection(None, None, newtitle)
                Collection.objects.set(coll)
                # Have to set the collection before setting the parents, to get
                # an ID for the parents to refer back to.
                coll.set_parents(filter(lambda x: x != '', parents))
                Collection.objects.set(coll)
                Record.objects.flush()
                Collection.objects.flush()

                for record in search.query:
                    record = record.object
                    record.collections = record.collections + [coll.id]
                    Record.objects.set(record)
                Record.objects.flush()
                Collection.objects.flush()

                redirect(url("coll-view", id=coll.id))
            else:
                return render("search_createcoll.html", context)

        elif params.action == 'addtocoll':
            context['all_collections'] = Collection.objects
            if cherrypy.request.method != "POST":
                return render("search_addtocoll.html", context)

            newid = getparam('addto_collid', '')
            if len(newid) == 0:
                context['error'] = "Pick a collection to add to"
                return render("search_addtocoll.html", context)

            coll = Collection.objects.get(newid)
            for record in search.query:
                record = record.object
                record.collections = record.collections + [coll.id]
                Record.objects.set(record)
            Record.objects.flush()
            Collection.objects.flush()

            redirect(url("coll-view", id=coll.id))

            return render("search_addtocoll.html", context)

        elif params.action == 'removefromcoll':
            context['all_collections'] = Collection.objects
            if cherrypy.request.method != "POST":
                return render("search_removefromcoll.html", context)

            newid = getparam('removefrom_collid', '')
            if len(newid) == 0:
                context['error'] = "Pick a collection to remove from"
                return render("search_removefromcoll.html", context)

            coll = Collection.objects.get(newid)
            for record in search.query:
                record = record.object
                record.collections = tuple(filter(lambda x: x != coll.id,
                                                  record.collections))
                Record.objects.set(record)
            Record.objects.flush()
            Collection.objects.flush()

            redirect(url("coll-view", id=coll.id))

            return render("search_removefromcoll.html", context)

        else:
            context['all_collections'] = Collection.objects
            return render("search_entry.html", context)
Example #27
0
 def status(self, id):
     imp = self.imports.get(id, None)
     context = dict(imp=imp)
     return render("import/status.html", context)
Example #28
0
    def export_records(self, export_id=None, fmt='rtf', download=False,
                       **params):
        """Export a set of records.

        """
        # Read parameters first, to ensure they all get stashed.
        stash = {}
        record_id = getparam('record_id', None, stash, params)
        issearch = getparam('issearch', None, stash, params)
        coll = getparam('coll', None, stash, params)
        incsubs = getintparam('incsubs', 1, stash, params)

        # Make a new exporter, and get any parameters it needs into the stash.
        try:
            exp = Exporter.get(fmt)()
        except KeyError:
            raise cherrypy.NotFound
        exp.read_params(stash, params)

        # Handle exports which are in progress, or have finished
        if export_id is not None:
            try:
                export_id = int(export_id)
            except ValueError:
                export_id = None
        if export_id is not None:
            try:
                running_exp = exports[export_id]
            except KeyError:
                # Invalid export id (most probably due to a server restart)
                running_exp = None
            if running_exp is not None:
                # Export in progress
                progress = pool.get_progress(export_id)
                context = dict(export_id=export_id, fmt=fmt, progress=progress,
                               stash=stash)
                if not progress.complete:
                    return render('export/in_progress.html', context)
                if progress.failed:
                    return render('export/failed.html', context)
                # Export complete
                if not download:
                    # Display a "Export prepared"
                    return render('export/complete.html', context)
                return running_exp.respond()

        # Read the set of things to export.
        search, desc, topcoll = self._get_export_records(stash, record_id, issearch,
                                                coll, incsubs)

        if not getparam('export', False, stash, params):
            # Not ready to start the export yet.
            context = dict(
                           fmts = Exporter.fmts(params),
                           fmt = fmt,
                           export_desc = desc,
                           stash = stash,
                          )

            exp.add_to_context(context, search, stash, params)
            return render('export/pickfmt.html', context)

        # Start the exporter
        task = ExportRecords(exp, search)
        export_id = pool.add_task(task)
        exports[export_id] = task

        redirect(url("records-export-inprogress", export_id=export_id, fmt=fmt, **stash))
Example #29
0
 def handle_get(self, params, context):
     context.update(self.build_form_context(params))
     return render("import/choose-fields.html", context)
Example #30
0
 def pick(self):
     context = dict(templates = Template.objects)
     return render("tmpls-pick.html", context)