tag.py 3.97 KB
Newer Older
Ryan Herbert's avatar
Ryan Herbert committed
1
2
import defs
import re
3
import json
Ryan Herbert's avatar
Ryan Herbert committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

class TagManager(object):

    def __init__(self, prefix):
        self.prefix = prefix

    def expression(self):
        return r'%s(\w+)' % self.prefix

class TagExtractor(TagManager):

    def __init__(self, prefix, db):
        super(TagExtractor, self).__init__(prefix)
        self.db = db

    def create(self, name):
        db = self.db
        try:
            tid = db.tag.insert(name=name)
            db.commit()
        except:
            tid = db(db.tag.name == name).select(db.tag.id).first()
        return tid
27
28
29
30
31
32
33
34
35
36
37

    def link_to_group(self, tag_id, group_id):
        db = self.db
        assocs = db((db.group_tag.tag_id == tag_id) &
                    (db.group_tag.group_id == group_id)
                ).select()
        if len(assocs) == 0:
            db.group_tag.insert(group_id=group_id, tag_id=tag_id)
            db.commit()

    def link_to_record(self, tag_id, table, record_id):
Ryan Herbert's avatar
Ryan Herbert committed
38
        db = self.db
39
        db.tag_ref.insert(tag_id=tag_id,
Ryan Herbert's avatar
Ryan Herbert committed
40
41
42
43
44
45
46
47
48
49
50
51
                          table_name=table,
                          record_id=record_id)
        db.commit()

    def remove_tags(self, table, record_id):
        db = self.db
        db((db.tag_ref.table_name == table) &
           (db.tag_ref.record_id == record_id)
          ).delete()
        db.commit()

    def parse_text(self, text):
52
        return list(set(re.findall(self.expression(), text)))
Ryan Herbert's avatar
Ryan Herbert committed
53

54
    def execute(self, table, record_id, text, group_id, reset=False):
Ryan Herbert's avatar
Ryan Herbert committed
55
56
57
58
        if (reset):
            self.remove_tags(table, record_id)
        tags = self.parse_text(text)
        for tag in tags:
59
60
61
            tag_id = self.create(tag)
            self.link_to_group(tag_id, group_id)
            self.link_to_record(tag_id, table, record_id)
Ryan Herbert's avatar
Ryan Herbert committed
62
63
64
65
66
67
68
        return tags

class TagDecorator(TagManager):

    def __init__(self, prefix):
        super(TagDecorator, self).__init__(prefix)

69
70
    def decoration(self, ltype, stype, target):
        this = "$(this)" # hack to solve some character escaping issues
71
        return r'<a onclick="event.preventDefault();event.stopPropagation();db.callLinkable(%s)" href="%s" class="%s-link" data-sample-type="%s" data-linkable-type="%s" data-linkable-target-param="%s" data-linkable-name="%s\1">%s\1</a>' % (this, target, ltype, stype, ltype, "filter", self.prefix, self.prefix)
Ryan Herbert's avatar
Ryan Herbert committed
72

73
    def decorate(self, text, ltype, stype, target):
Ryan Herbert's avatar
Ryan Herbert committed
74
75
        if (text is None):
            return None
76
        return re.sub(self.expression(), self.decoration(ltype, stype, target), text)
Ryan Herbert's avatar
Ryan Herbert committed
77

78
79
80
81
    def sanitize(self, text):
        return XML(text,
                sanitize=True,
                permitted_tags=['a'],
82
                allowed_attributes={'a':['class', 'href', 'onclick', 'data-sample-type', 'data-linkable-type', 'data-linkable-target-param', 'data-linkable-name']})
83

Ryan Herbert's avatar
Ryan Herbert committed
84
85
86
87
88
89
90
def get_tag_prefix():
    try:
        tag_prefix = defs.TAG_PREFIX
    except:
        tag_prefix = '#'
    return tag_prefix

91
def register_tags(db, table, record_id, text, group_id, reset=False):
Ryan Herbert's avatar
Ryan Herbert committed
92
93
    tag_prefix = get_tag_prefix()
    tag_extractor = TagExtractor(tag_prefix, db)
94
    tags = tag_extractor.execute(table, record_id, text, group_id, reset)
95

96
def get_tags(db, group_ids):
97
    return db((db.tag.id == db.group_tag.tag_id) &
98
99
              (db.group_tag.group_id.belongs(group_ids))
            ).select(db.group_tag.group_id, db.tag.ALL)
100
101

def tags_to_json(tags):
102
    tag_map = {}
103
    prefix = get_tag_prefix()
104
105
106
107
    for row in tags:
        group_id = row.group_tag.group_id
        if group_id not in tag_map:
            tag_map[group_id] = []
108
        tag_dict = {}
109
110
111
        tag_dict['id'] = row.tag.id
        tag_dict['name'] = row.tag.name
        tag_map[group_id].append(tag_dict)
112

113
    return json.dumps(tag_map)
114
115
116
117
118
119
120
121
122

def parse_search(search_string):
    split = search_string.split()
    tag_prefix = get_tag_prefix()
    plen = len(tag_prefix)
    tags = [t[plen:] for t in split if t[:plen] == tag_prefix]
    searches = [s for s in split if s[:plen] != tag_prefix]
    search_string = " ".join(searches)
    return search_string, tags