ajax_pattern_view.py 7.7 KB
# -*- coding: utf-8 -*-
from collections import OrderedDict
import datetime
from common.util import error_messages, format_date
from common.decorators import render, ajax, AjaxError, render_ajax

from dictionary.models import Pattern, Ending, BaseFormLabel, PatternType, \
    editable_qualifiers, readonly_vocabularies, visible_vocabularies, Gender, \
    LexicalClass
from patterns.forms import PatternEditForm, QualifierForm
from dictionary.ajax_slickgrid import SlickGridQuery

COLOR_SCHEMES = dict(LexicalClass.objects.values_list('symbol', 'color_scheme'))


class PatternQuery(SlickGridQuery):
    model = Pattern
    sort_field = 'name'
    select_related = ['type__lexical_class']
    default_columns = ('name', 'type')
    column_data = {
        'id': lambda pattern: pattern.id,
        'scheme': lambda pattern: COLOR_SCHEMES[pattern.type.lexical_class_id],
        'name': lambda pattern: pattern.name,
        'type': lambda pattern: pattern.type.symbol,
        'lexical_class': lambda pattern: pattern.type.lexical_class_id,
        'example':
            lambda pattern: pattern.example + u'·' + pattern.basic_form_ending,
    }

    filter_field_translation = {
        'lexical_class': 'type__lexical_class__symbol',
        'base_form_label': 'endings__base_form_label__symbol',
    }


# Zapytanie o indeks wiersza o pewnym id przy danym sortowaniu
@ajax(login_required=False, method='get')
def row_index(request, id, sort_rules, filter):
    query = PatternQuery(filter=filter, sort_rules=sort_rules)
    return {'index': query.row_index(id)}


# Zapytanie o id oraz indeks wiersza przy danym sortowaniu
# pierwszego wiersza, którego hasło rozpoczyna się od search.
# 'selected_id' < 0, jeśli takiego nie ma
@ajax(method='get')
def search_index(request, sort_rules, filter, search=''):
    query = PatternQuery(filter=filter, sort_rules=sort_rules)
    return {'index': query.search_index(search)}


@ajax(method='get')
def get_patterns(request, from_page, to_page, rows, sort_rules, filter):
    request.session['pattern-sort_rules'] = sort_rules
    request.session['pattern-filter'] = filter
    columns = request.session.get('pattern-columns')
    query = PatternQuery(filter=filter, sort_rules=sort_rules, columns=columns)
    rows, count = query.get_page(from_page, to_page, rows)
    return {
        'rows': rows,
        'count': count,
        'page': from_page,
    }


@render_ajax(template='pattern_preview.html', method='get')
def pattern_preview(request, id):
    try:
        pattern = Pattern.all_objects.get(id=id)
    except Pattern.DoesNotExist:
        raise AjaxError('Wzór nie istnieje')
    lips = pattern.lexemeinflectionpattern_set.filter(
        lexeme__vocabularies__in=visible_vocabularies(request.user))
    detailed_counts = []

    def lexeme_count(q):
        return q.values('lexeme').distinct().count()

    if pattern.type.lexical_class_id == 'subst':
        for gender in Gender.objects.all():
            gender_count = lexeme_count(lips.filter(gender=gender))
            if gender_count > 0:
                detailed_counts.append((gender.symbol, gender_count))
    return {
        'pattern': pattern,
        'lexeme_count': lexeme_count(lips),
        'detailed_counts': detailed_counts,
    }


@render_ajax(template='pattern_edit_form.html', method='get')
def pattern_edit_form(request, id):
    if not request.user.has_perm('dictionary.view_pattern'):
        raise AjaxError('access denied')
    p = Pattern.all_objects.get(pk=id)
    editable = request.user.has_perm('dictionary.change_pattern')
    ending_groups = OrderedDict(
        (bfl, []) for bfl in p.type.base_form_labels.all())
    endings = p.endings.order_by('index')
    for e in endings:
        ro_qualifers = e.qualifiers.filter(
            vocabulary__in=readonly_vocabularies(request.user))
        q_form = QualifierForm(
            qualified=e, user=request.user, editable=editable,
            prefix='end%s' % e.pk)
        if e.base_form_label in ending_groups:
            ending_groups[e.base_form_label].append((e, ro_qualifers, q_form))
        else:
            e.delete()
    return {
        'pattern': p,
        'form': PatternEditForm(instance=p, editable=editable),
        'editable': editable,
        'ending_groups': ending_groups,
    }


# mogłoby iść przez js_vars...
@render('ending_row.html')
@ajax(method='get', encode_result=False)
def new_ending_row(request, pattern_id):
    p = Pattern.all_objects.get(id=pattern_id)
    ending = {'string': '', 'id': 'add-NUM'}
    form = QualifierForm(user=request.user, prefix='add-NUM')
    return {'ending': ending, 'editable': True, 'form': form, 'pattern': p}


@ajax(method='post')
def update_pattern(request, form_data):
    if not request.user.has_perm('dictionary.change_pattern'):
        raise AjaxError('access denied')
    form_dict = dict((x['name'], x['value']) for x in form_data)
    p = Pattern.all_objects.get(pk=form_dict['id'])
    lc = p.type.lexical_class
    form = PatternEditForm(data=form_dict, instance=p)
    if form.is_valid():
        form.save()
        p.deleted = False
        p.save()
        for ending_pk in form_dict['deleted']:
            Ending.objects.get(pk=int(ending_pk)).delete()
        qualifiers = editable_qualifiers(request.user)
        for bfl_endings in form_dict['ending_list']:
            endings_data = bfl_endings['endings']
            bfl = BaseFormLabel.objects.get(
                symbol=bfl_endings['base_form_label'], lexical_class=lc)
            endings = []
            for index, ending_data in enumerate(endings_data, 1):
                quals = set(int(q) for q in ending_data['qualifiers'])
                if ending_data['id'] == 'add':
                    ending = Ending.objects.create(
                        pattern=p, base_form_label=bfl,
                        string=ending_data['string'],
                        index=index)
                else:
                    ending = Ending.objects.get(pk=int(ending_data['id']))
                    ending.index = index
                    ending.string = ending_data['string']
                    ending.save()
                for qualifier in qualifiers:
                    qualifier.set_for(ending, qualifier.pk in quals)
                endings.append(ending)
    else:
        raise AjaxError(error_messages(form))
    return {}


@ajax(method='post')
def save_columns(request, columns):
    request.session['pattern-columns'] = columns
    return {}


@ajax(method='post')
def create_pattern(request):
    new_name = u'nowy wzór %s'
    i = 1
    while Pattern.all_objects.filter(name=new_name % i).exists():
        i += 1
    pt = PatternType.objects.get(lexical_class_id='subst', symbol='m')
    p = Pattern.objects.create(
        name=new_name % i, type=pt, example='...', status=Pattern.STATUS_NEW,
        deleted=True)
    return {'id': p.id}


@ajax(method='post')
def clone_pattern(request, pattern_id):
    if not request.user.has_perm('dictionary.change_pattern'):
        raise AjaxError(u'Brak uprawnień')
    pattern = Pattern.objects.get(id=pattern_id)
    comment = u'Wzór sklonowany %s' % (format_date(datetime.datetime.now()))
    i = 1
    while Pattern.all_objects.filter(name='%s-%s' % (pattern.name, i)).exists():
        i += 1
    new_name = '%s-%s' % (pattern.name, i)
    new_pattern = Pattern.objects.create(
        name=new_name, type=pattern.type, example=pattern.example,
        basic_form_ending=pattern.basic_form_ending, status=Pattern.STATUS_NEW,
        comment=comment, deleted=False)
    for ending in pattern.endings.all():
        new_ending = Ending.objects.create(
            pattern=new_pattern, index=ending.index,
            base_form_label=ending.base_form_label, string=ending.string)
        new_ending.qualifiers = ending.qualifiers.all()
    return {'new_id': new_pattern.id}