# -*- coding: utf-8 -*- from datetime import datetime import json import logging import os import shutil import unicodedata from sqlalchemy.orm import load_only import ox import sqlalchemy as sa from changelog import add_record from db import MutableDict import db import json_pickler import settings import state import utils import media from websocket import trigger_event logger = logging.getLogger(__name__) class Annotation(db.Model): __tablename__ = 'annotation' _id = sa.Column(sa.Integer(), primary_key=True) id = sa.Column(sa.String(43)) created = sa.Column(sa.DateTime()) modified = sa.Column(sa.DateTime()) user_id = sa.Column(sa.String(43), sa.ForeignKey('user.id')) user = sa.orm.relationship('User', backref=sa.orm.backref('annotations', lazy='dynamic')) item_id = sa.Column(sa.String(43), sa.ForeignKey('item.id')) item = sa.orm.relationship('Item', backref=sa.orm.backref('items', lazy='dynamic')) data = sa.Column(MutableDict.as_mutable(sa.PickleType(pickler=json_pickler))) findquotes = sa.Column(sa.Text(), index=True) findnotes = sa.Column(sa.Text(), index=True) def __init__(self, item_id, user_id, data): self.created = datetime.utcnow() self.modified = datetime.utcnow() self.item_id = item_id self.user_id = user_id self.data = data @classmethod def create(cls, item_id, user_id, data): a = cls(item_id, user_id, data) a.save() return a def delete(self): state.db.session.delete(self) state.db.session.commit() @classmethod def get(cls, user, item_id, annotation_id): if isinstance(user, str): qs = cls.query.filter_by(item_id=item_id, user_id=user, id=annotation_id) else: qs = cls.query.filter_by(item_id=item_id, user=user, id=annotation_id) for a in qs: return a @classmethod def get_by_item(cls, item_id): annotations = [] for a in cls.query.filter_by(item_id=item_id): annotations.append(a.json()) return annotations def save(self): id = self.data.get('id') if id: self.id = id self.findquotes = unicodedata.normalize('NFKD', self.data.get('text', '')).lower() note = self.data.get('notes', {}) if isinstance(note, list) and note: note = note[0] if isinstance(note, dict): note = note.get('value', '') else: note = '' self.findnotes = unicodedata.normalize('NFKD', note).lower() state.db.session.add(self) state.db.session.commit() def json(self): data = self.data.copy() data['created'] = self.created data['modified'] = self.modified data['user'] = self.user_id data['_id'] = ox.toAZ(self._id) if isinstance(data.get('notes'), dict): note = data['notes'] if self.user_id != settings.USER_ID: note['user'] = self.user_id if not note.get('id'): note['id'] = 'A' data['notes'] = [data['notes']] if 'notes' not in data: data['notes'] = [] return data def add_record(self, action): args = [self.item_id] if action == 'addannotation': args.append(self.data) elif action == 'editannotation': args.append(self.id) args.append({ 'notes': self.data['notes'] }) elif action == 'removeannotation': args.append(self.id) else: raise Exception('unknown action') add_record(action, *args)