Example #1
0
    def ac(self, **params):
        """Autocomplete API.

        """
        field = params['field']
        term = params['term']
        colls = params['colls'].split(",")
        # FIXME - allow restricting search to a set of collections

        if field == '*':
            return jsonresp([])

        fieldname, fieldtype = field.rsplit('_', 1)
        fieldconfigs = SearchCollection.config['types'] \
            .get('record', {}) \
            .get('fields', {})

        if '*' in colls:
            target = SearchCollection.all()
        else:
            target = SearchCollection.field.coll.is_or_is_descendant(colls)

        return jsonresp(
            field_item_types[fieldtype]
            .autocomplete(target, fieldconfigs,
                          fieldname, term)
        )
Example #2
0
    def position_in(self, coll):
        """Get the ids of the previous and next records according to the named
        collection.

        """
        from apps.store.search import Collection as SearchCollection
        q = SearchCollection.doc_type('record').field.coll.is_in(coll.id)
        for name, asc in coll.autoorder.ordering:
            asc = {'+': True, '-': False}[asc]
            q = q.order_by(name, asc)
        r = [(r.data['id'][0], r.rank) for r in q.fromdoc('record', self.id, -1, 3)]
        if len(r) == 0:
            return dict(pos=0, size=0)

        if r[0][0] == self.id:
            index = 0
        elif len(r) == 1:
            return dict(pos=0, size=0)
        else:
            index = 1

        rank = r[index][1]
        result = dict(pos=rank + 1, size=len(q))
        if index > 0:
            result['prev'] = r[index - 1][0]
        if index + 1 < len(r):
            result['next'] = r[index + 1][0]
        return result
Example #3
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 #4
0
 def make_media_view(self, mediafile):
     info = self.get_file_info(mediafile)
     assert info is not None # Should have already checked that file exists
         
     records = []
     q = SearchCollection.doc_type('record').field.fileid == mediafile
     for r in q[:100]:
         records.append(r.object)
     context = dict(info=info, records=records)
     self.render('mediapreview', (), dict(path=mediafile),
                 "export/html/media-view.html", context)
Example #5
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 #6
0
 def _get_query(self, type, incsubs):
     key = (type, incsubs)
     q = self._cached_queries.get(key, None)
     if False and q is not None:
         # FIXME re-enable this cache, but make it persist only for the
         # duration of a single request.
         return q
     from apps.store.search import Collection as SearchCollection
     q = SearchCollection.doc_type(type)
     if incsubs:
         q = q.field.coll.is_or_is_descendant(self.id)
     else:
         q = q.field.coll.is_in(self.id)
     for name, asc in self.autoorder.ordering:
         asc = {'+': True, '-': False}[asc]
         q = q.order_by(name, asc)
     q = q.check_at_least(-1)
     self._cached_queries[key] = q
     return q
Example #7
0
    def set_parents(self, parents):
        from apps.store.search import Collection as SearchCollection
        hier = SearchCollection.taxonomy('coll_hierarchy')
        hier.add_category(self.id)
        changed = False
        new_parents = set()
        for parent in parents:
            if parent == self.id or parent == '':
                continue
            new_parents.add(parent)

        # Remove the collection from old parents which are no longer parents
        for parent in self._parents:
            if parent in new_parents:
                continue
            try:
                pcoll = Collection.objects.get(parent)
            except KeyError:
                continue # Can get KeyError if some of the ancestors don't exist - this would need to be fixed, but failing here would make it impossible for the user to fix it.
            pcoll._remove_child(self.id)
            Collection.objects.set(pcoll)
            hier.remove_parent(self.id, parent)
            changed = True

        for parent in new_parents:
            if parent in self._parents:
                continue
            pcoll = Collection.objects.get(parent)
            pcoll._add_child(self.id)
            Collection.objects.set(pcoll)
            hier.add_parent(self.id, parent)
            changed = True

        self._parents = tuple(sorted(new_parents))
        if changed:
            self._calced_ancestors = False

        return changed
Example #8
0
def calendar_items(id, incsubs, calstyle, startdate,
                   year, month, day, datefield):
    # If date was supplied as year,month,day, convert it.
    if year is not None:
        startdate = '%04.d' % int(year)
        if month is not None:
            startdate += '-%02.d' % int(month)
            if day is not None:
                startdate += '-%02.d' % int(day)

    record_docs = SearchCollection.doc_type('record')
    if incsubs:
        q = record_docs.field.coll.is_or_is_descendant(id)
    else:
        q = record_docs.field.coll.is_in(id)

    info = q.calc_facet_count(datefield).check_at_least(-1).info
    counts = info[0]['counts']
    counts.sort()

    prevdate = None
    nextdate = None
    firstdate = None
    years = set()
    dates = {}

    if not startdate:
        # No start date supplied.
        if len(counts) > 0:
            startdate = '%04.d-%02.d-%02.d' % tuple(counts[0][0])
        else:
            startdate = None

    # Adjust the accuracy of startdate according to the calendar style, and set
    # enddate accordingly.
    if startdate is not None:
        startdate, enddate = date_range(calstyle, startdate)
        q = q.filter(Field(datefield).range(startdate, enddate))

        # Set prevdate, nextdate, firstdate, years
        startdate_tuple = (int(startdate[:4]),
                           int(startdate[5:7]),
                           int(startdate[8:10]))
        enddate_tuple = (int(enddate[:4]),
                         int(enddate[5:7]),
                         int(enddate[8:10]))
        for (date_tuple, count) in counts:
            date_tuple = tuple(date_tuple)
            years.add(date_tuple[0])
            if date_tuple < startdate_tuple:
                if prevdate is None or prevdate < date_tuple:
                    prevdate = date_tuple
            elif date_tuple > enddate_tuple:
                if nextdate is None or nextdate > date_tuple:
                    nextdate = date_tuple
        years = tuple(sorted(years))
        if prevdate is not None:
            prevdate = '%04.d-%02.d-%02.d' % tuple(prevdate)
        if nextdate is not None:
            nextdate = '%04.d-%02.d-%02.d' % tuple(nextdate)

        # Set dates
        for r in q:
            for date in r.data.get(datefield, []):
                dates.setdefault(date, []).append(r.object)
                if firstdate is None:
                    firstdate = date
                elif firstdate > date:
                    firstdate = date

    # Set year, month, day
    year = 1
    month = 1
    day = 1
    if startdate is not None:
        if len(startdate) > 0:
            year = int(startdate[:4])
        if len(startdate) > 4:
            month = max(1, int(startdate[5:7]))
        if len(startdate) > 7:
            day = max(1, int(startdate[8:10]))

    # Months is always the list of all months.
    months = [(i, calendar.month_name[i]) for i in xrange(1, 13)]

    # Count the number of entries on each day, and set the groupings
    # accordingly.
    groupnames, groups = mkgroups(dates)

    result = dict(calstyle=calstyle, dates=dates,
                  years=years, months=months,
                  startdate=startdate,
                  year=year, month=month, day=day,
                  groupnames=groupnames,
                  nextdate=nextdate, prevdate=prevdate)

    if int(year) <= 0:
        # FIXME - hack to handle missing data, and out of range dates.
	year = datetime.datetime.now().year
	month = datetime.datetime.now().month
	day = datetime.datetime.now().day

    if calstyle == 'year':
        months = []
        for month in range(1, 13):
            months.append(mkmonth(year, month, dates, groups))
        result['months'] = months

    if calstyle == 'month':
        result['month_grid'] = mkmonth(year, month, dates, groups)

    elif calstyle == 'day':
        records = dates.get(startdate, ())
        result['records'] = records

    return result