Exemple #1
0
def instance_info(request, instance):
    """
    Get all the info we need about a given instance

    If also includes info about the fields available for the
    instance. If a user has been specified the field info
    will be tailored to that user
    """
    user = request.user

    role = instance.default_role
    if user and not user.is_anonymous():
        instance_user = user.get_instance_user(instance)
        if instance_user:
            role = instance_user.role

    perms = {}

    for fp in role.fieldpermission_set.all():
        model = fp.model_name.lower()
        if fp.allows_reads:
            if model not in perms:
                perms[model] = []

            if is_json_field_reference(fp.field_name):
                choices = None
                data_type = "string"
            else:
                model_inst = safe_get_model_class(fp.model_name)(instance=instance)

                data_type, _, choices = field_type_label_choices(model_inst, fp.field_name, fp.display_field_name)

            digits = get_digits_if_formattable(instance, model, fp.field_name)

            units = get_units_if_convertible(instance, model, fp.field_name)

            perms[model].append(
                {
                    "data_type": data_type,
                    "choices": choices,
                    "units": units,
                    "digits": digits,
                    "can_write": fp.allows_writes,
                    "display_name": fp.display_field_name,
                    "field_name": fp.field_name,
                }
            )

    info = _instance_info_dict(instance)
    info["fields"] = perms
    info["search"] = instance.advanced_search_fields

    return info
Exemple #2
0
    def add_perms(field_permissions, perms):
        for fp in field_permissions:
            model = fp.model_name.lower()
            field_key = '%s.%s' % (model, fp.field_name)
            if fp.allows_reads:
                if field_key in collection_udf_dict:
                    choices = []
                    data_type = json.loads(
                        collection_udf_dict[field_key].datatype)
                elif is_json_field_reference(fp.field_name):
                    choices = None
                    data_type = "string"
                else:
                    model_inst = safe_get_model_class(
                        fp.model_name)(instance=instance)
                    data_type, __, __, choices = field_type_label_choices(
                        model_inst, fp.field_name, fp.display_field_name)

                digits = get_digits_if_formattable(instance, model,
                                                   fp.field_name)

                units = get_units_if_convertible(instance, model,
                                                 fp.field_name)

                factor = 1.0

                try:
                    factor = storage_to_instance_units_factor(
                        instance, model, fp.field_name)
                except KeyError:
                    pass

                perms[field_key] = {
                    'data_type': data_type,
                    'choices': choices,
                    'units': units,
                    'digits': digits,
                    'canonical_units_factor': 1.0 / factor,
                    'can_write': fp.allows_writes,
                    'display_name': fp.display_field_name,
                    'field_name': fp.field_name,
                    'field_key': field_key,
                    'is_collection': field_key in collection_udf_dict
                }
Exemple #3
0
    def add_perms(field_permissions, perms):
        for fp in field_permissions:
            model = fp.model_name.lower()
            field_key = '%s.%s' % (model, fp.field_name)
            if fp.allows_reads:
                if field_key in collection_udf_dict:
                    choices = []
                    data_type = json.loads(
                        collection_udf_dict[field_key].datatype)
                elif is_json_field_reference(fp.field_name):
                    choices = None
                    data_type = "string"
                else:
                    model_inst = safe_get_model_class(fp.model_name)(
                        instance=instance)
                    data_type, __, __, choices = field_type_label_choices(
                        model_inst, fp.field_name, fp.display_field_name)

                digits = get_digits_if_formattable(
                    instance, model, fp.field_name)

                units = get_units_if_convertible(
                    instance, model, fp.field_name)

                factor = 1.0

                try:
                    factor = storage_to_instance_units_factor(
                        instance, model, fp.field_name)
                except KeyError:
                    pass

                perms[field_key] = {
                    'data_type': data_type,
                    'choices': choices,
                    'units': units,
                    'digits': digits,
                    'canonical_units_factor': 1.0 / factor,
                    'can_write': fp.allows_writes,
                    'display_name': fp.display_field_name,
                    'field_name': fp.field_name,
                    'field_key': field_key,
                    'is_collection': field_key in collection_udf_dict
                }
Exemple #4
0
def mobile_search_fields(instance):
    from treemap.templatetags.form_extras import (field_type_label_choices,
                                                  ADD_BLANK_NEVER)
    search_fields = copy.deepcopy(instance.mobile_search_fields)
    for field in search_fields['standard']:
        identifier = field['identifier']
        alert_info = get_alert_field_info(identifier, instance)
        if alert_info is not None:
            field.update(alert_info)
            continue

        Model, field_name = _parse_field_info(instance, field)
        set_search_field_label(instance, field)
        field_type, __, __, choices = field_type_label_choices(
            Model, field_name, add_blank=ADD_BLANK_NEVER)

        if identifier == 'species.id':
            field['search_type'] = 'SPECIES'
        elif field_type in {'int', 'float'}:
            field['search_type'] = 'RANGE'
        elif field_type in {'date', 'datetime'}:
            field['search_type'] = 'DATERANGE'
        elif field_type == 'string':
            field['search_type'] = 'STRING'
        elif field_type == 'bool':
            field['search_type'] = 'BOOL'
        elif field_type == 'choice':
            field['search_type'] = 'CHOICE'
        elif field_type == 'multichoice':
            field['search_type'] = 'MULTICHOICE'

        if choices:
            field['choices'] = choices

    for field in search_fields['missing']:
        _set_missing_search_label(instance, field)

    return search_fields
Exemple #5
0
def mobile_search_fields(instance):
    from treemap.templatetags.form_extras import (field_type_label_choices,
                                                  ADD_BLANK_NEVER)
    search_fields = copy.deepcopy(instance.mobile_search_fields)
    for field in search_fields['standard']:
        identifier = field['identifier']
        alert_info = get_alert_field_info(identifier, instance)
        if alert_info is not None:
            field.update(alert_info)
            continue

        Model, field_name = _parse_field_info(instance, field)
        set_search_field_label(instance, field)
        field_type, __, __, choices = field_type_label_choices(
            Model, field_name, add_blank=ADD_BLANK_NEVER)

        if identifier == 'species.id':
            field['search_type'] = 'SPECIES'
        elif field_type in {'int', 'float'}:
            field['search_type'] = 'RANGE'
        elif field_type in {'date', 'datetime'}:
            field['search_type'] = 'DATERANGE'
        elif field_type == 'string':
            field['search_type'] = 'STRING'
        elif field_type == 'bool':
            field['search_type'] = 'BOOL'
        elif field_type == 'choice':
            field['search_type'] = 'CHOICE'
        elif field_type == 'multichoice':
            field['search_type'] = 'MULTICHOICE'

        if choices:
            field['choices'] = choices

    for field in search_fields['missing']:
        _set_missing_search_label(instance, field)

    return search_fields
Exemple #6
0
def get_search_field_label(instance, field_info):
    """
    Searches for missing data are controlled by fields, and those fields
    need labels. Two wrinkles: 1) Fields like species.id and mapFeaturePhoto.id
    need special handling. 2) Fields from all models are shown in the
    "Missing Data" category, so prefix the field name with the model name.
    """
    from treemap.templatetags.form_extras import field_type_label_choices
    Model, field_name = _parse_field_info(instance, field_info)
    if field_name == 'id':
        if hasattr(Model, 'terminology'):
            label = Model.terminology(instance)['plural']
        else:
            label = Model._meta.verbose_name_plural
    else:
        __, label, __, __ = field_type_label_choices(Model, field_name, '')
        if hasattr(Model, 'terminology'):
            prefix = force_text(Model.terminology(instance)['singular'])
        else:
            prefix = force_text(Model._meta.verbose_name)
        label = force_text(label)
        if not label.startswith(prefix):
            label = "%s %s" % (prefix, label)
    return label
Exemple #7
0
def get_search_field_label(instance, field_info):
    """
    Searches for missing data are controlled by fields, and those fields
    need labels. Two wrinkles: 1) Fields like species.id and mapFeaturePhoto.id
    need special handling. 2) Fields from all models are shown in the
    "Missing Data" category, so prefix the field name with the model name.
    """
    from treemap.templatetags.form_extras import field_type_label_choices
    Model, field_name = _parse_field_info(instance, field_info)
    if field_name == 'id':
        if hasattr(Model, 'terminology'):
            label = Model.terminology(instance)['plural']
        else:
            label = Model._meta.verbose_name_plural
    else:
        __, label, __, __ = field_type_label_choices(Model, field_name, '')
        if hasattr(Model, 'terminology'):
            prefix = force_text(Model.terminology(instance)['singular'])
        else:
            prefix = force_text(Model._meta.verbose_name)
        label = force_text(label)
        if not label.startswith(prefix):
            label = "%s %s" % (prefix, label)
    return label
Exemple #8
0
def instance_info(request, instance):
    """
    Get all the info we need about a given instance

    If also includes info about the fields available for the
    instance. If a user has been specified the field info
    will be tailored to that user
    """
    user = request.user

    role = instance.default_role
    if user and not user.is_anonymous():
        instance_user = user.get_instance_user(instance)
        if instance_user:
            role = instance_user.role

    perms = {}

    fields_to_allow = instance.mobile_api_fields

    for fp in role.fieldpermission_set.all():
        model = fp.model_name.lower()

        if fields_to_allow and \
           fp.field_name not in fields_to_allow.get(model, []):
            continue

        if fp.allows_reads:
            if model not in perms:
                perms[model] = []

            if is_json_field_reference(fp.field_name):
                choices = None
                data_type = "string"
            else:
                model_inst = safe_get_model_class(fp.model_name)(
                    instance=instance)

                data_type, _, choices = field_type_label_choices(
                    model_inst, fp.field_name, fp.display_field_name)

            digits = get_digits_if_formattable(
                instance, model, fp.field_name)

            units = get_units_if_convertible(
                instance, model, fp.field_name)

            factor = 1.0

            try:
                factor = get_conversion_factor(
                    instance, model, fp.field_name)
            except KeyError:
                pass

            perms[model].append({
                'data_type': data_type,
                'choices': choices,
                'units': units,
                'digits': digits,
                'canonical_units_factor': 1.0 / factor,
                'can_write': fp.allows_writes,
                'display_name': fp.display_field_name,
                'field_name': fp.field_name,
                'field_key': '%s.%s' % (model, fp.field_name)
            })

    info = _instance_info_dict(instance)
    info['fields'] = perms
    info['search'] = instance.mobile_search_fields

    public_config_keys = ['scss_variables']

    info['config'] = {x: instance.config[x]
                      for x in instance.config
                      if x in public_config_keys}

    if instance.logo:
        info['logoUrl'] = instance.logo.url

    return info
Exemple #9
0
def instance_info(request, instance):
    """
    Get all the info we need about a given instance

    It also includes info about the fields available for the
    instance. If a user has been specified the field info
    will be tailored to that user
    """
    user = request.user

    role = instance.default_role
    if user and not user.is_anonymous():
        instance_user = user.get_instance_user(instance)
        if instance_user:
            role = instance_user.role

    collection_udfs = instance.userdefinedfielddefinition_set\
                              .filter(iscollection=True)
    collection_udf_dict = {
        "%s.%s" % (udf.model_type.lower(), udf.canonical_name): udf
        for udf in collection_udfs
    }

    # collect perms for the given role/instance into a serializable
    # dictionary. If a field isn't at least readable, it doesn't
    # get sent over at all.
    perms = {}
    for fp in role_permissions(role, instance):
        model = fp.model_name.lower()
        field_key = '%s.%s' % (model, fp.field_name)
        if fp.allows_reads:
            if field_key in collection_udf_dict:
                choices = []
                data_type = json.loads(collection_udf_dict[field_key].datatype)
            elif is_json_field_reference(fp.field_name):
                choices = None
                data_type = "string"
            else:
                model_inst = safe_get_model_class(
                    fp.model_name)(instance=instance)
                data_type, __, choices = field_type_label_choices(
                    model_inst, fp.field_name, fp.display_field_name)

            digits = get_digits_if_formattable(instance, model, fp.field_name)

            units = get_units_if_convertible(instance, model, fp.field_name)

            factor = 1.0

            try:
                factor = get_conversion_factor(instance, model, fp.field_name)
            except KeyError:
                pass

            perms[field_key] = {
                'data_type': data_type,
                'choices': choices,
                'units': units,
                'digits': digits,
                'canonical_units_factor': 1.0 / factor,
                'can_write': fp.allows_writes,
                'display_name': fp.display_field_name,
                'field_name': fp.field_name,
                'field_key': field_key,
                'is_collection': field_key in collection_udf_dict
            }

    def get_key_for_group(field_group):
        for key in ('collection_udf_keys', 'field_keys'):
            if key in field_group:
                return key
        return None

    # Remove fields from mobile_api_fields if they are not present in perms
    # (Generally because the user doesn't have read permissions)
    # If no fields are left in a group, remove the group
    mobile_api_fields = copy.deepcopy(instance.mobile_api_fields)

    for field_group in mobile_api_fields:
        # Field group headers are stored in English, and translated when they
        # are sent out to the client
        field_group['header'] = _(field_group['header'])
        key = get_key_for_group(field_group)
        if key:
            field_group[key] = [
                field for field in field_group[key] if field in perms
            ]

    readable_mobile_api_fields = [
        group for group in mobile_api_fields
        if group.get(get_key_for_group(group), None)
    ]

    info = _instance_info_dict(instance)
    info['fields'] = perms
    info['field_key_groups'] = readable_mobile_api_fields
    info['search'] = instance.mobile_search_fields
    info['date_format'] = _unicode_dateformat(instance.date_format)
    info['short_date_format'] = _unicode_dateformat(instance.short_date_format)

    info['meta_perms'] = {
        'can_add_tree': perms_lib.plot_is_creatable(role),
        'can_edit_tree': perms_lib.plot_is_writable(role),
        'can_edit_tree_photo': perms_lib.treephoto_is_writable(role),
    }

    public_config_keys = ['scss_variables']

    info['config'] = {
        x: instance.config[x]
        for x in instance.config if x in public_config_keys
    }

    if instance.logo:
        info['logoUrl'] = instance.logo.url

    return info
Exemple #10
0
def instance_info(request, instance):
    """
    Get all the info we need about a given instance

    It also includes info about the fields available for the
    instance. If a user has been specified the field info
    will be tailored to that user
    """
    user = request.user

    role = instance.default_role
    if user and not user.is_anonymous():
        instance_user = user.get_instance_user(instance)
        if instance_user:
            role = instance_user.role

    collection_udfs = instance.collection_udfs
    collection_udf_dict = {"%s.%s" % (udf.model_type.lower(),
                                      udf.canonical_name): udf
                           for udf in collection_udfs}

    # collect perms for the given role/instance into a serializable
    # dictionary. If a field isn't at least readable, it doesn't
    # get sent over at all.
    perms = {}
    for fp in role_permissions(role, instance):
        model = fp.model_name.lower()
        field_key = '%s.%s' % (model, fp.field_name)
        if fp.allows_reads:
            if field_key in collection_udf_dict:
                choices = []
                data_type = json.loads(collection_udf_dict[field_key].datatype)
            elif is_json_field_reference(fp.field_name):
                choices = None
                data_type = "string"
            else:
                model_inst = safe_get_model_class(fp.model_name)(
                    instance=instance)
                data_type, __, choices = field_type_label_choices(
                    model_inst, fp.field_name, fp.display_field_name)

            digits = get_digits_if_formattable(
                instance, model, fp.field_name)

            units = get_units_if_convertible(
                instance, model, fp.field_name)

            factor = 1.0

            try:
                factor = storage_to_instance_units_factor(
                    instance, model, fp.field_name)
            except KeyError:
                pass

            perms[field_key] = {
                'data_type': data_type,
                'choices': choices,
                'units': units,
                'digits': digits,
                'canonical_units_factor': 1.0 / factor,
                'can_write': fp.allows_writes,
                'display_name': fp.display_field_name,
                'field_name': fp.field_name,
                'field_key': field_key,
                'is_collection': field_key in collection_udf_dict
            }

    def get_key_for_group(field_group):
        for key in ('collection_udf_keys', 'field_keys'):
            if key in field_group:
                return key
        return None

    # Remove fields from mobile_api_fields if they are not present in perms
    # (Generally because the user doesn't have read permissions)
    # If no fields are left in a group, remove the group
    mobile_api_fields = copy.deepcopy(instance.mobile_api_fields)

    for field_group in mobile_api_fields:
        # Field group headers are stored in English, and translated when they
        # are sent out to the client
        field_group['header'] = _(field_group['header'])
        key = get_key_for_group(field_group)
        if key:
            field_group[key] = [field for field in field_group[key]
                                if field in perms]

    readable_mobile_api_fields = [group for group in mobile_api_fields
                                  if group.get(get_key_for_group(group), None)]

    info = _instance_info_dict(instance)
    info['fields'] = perms
    info['field_key_groups'] = readable_mobile_api_fields
    info['search'] = mobile_search_fields(instance)
    info['date_format'] = _unicode_dateformat(instance.date_format)
    info['short_date_format'] = _unicode_dateformat(instance.short_date_format)

    info['meta_perms'] = {
        'can_add_tree': perms_lib.plot_is_creatable(role),
        'can_edit_tree': perms_lib.plot_is_writable(role),
        'can_edit_tree_photo': perms_lib.treephoto_is_writable(role),
    }

    public_config_keys = ['scss_variables']

    info['config'] = {x: instance.config[x]
                      for x in instance.config
                      if x in public_config_keys}

    if instance.logo:
        info['logoUrl'] = instance.logo.url

    return info
Exemple #11
0
def instance_info(request, instance):
    """
    Get all the info we need about a given instance

    It also includes info about the fields available for the
    instance. If a user has been specified the field info
    will be tailored to that user
    """
    user = request.user

    role = instance.default_role
    if user and not user.is_anonymous():
        instance_user = user.get_instance_user(instance)
        if instance_user:
            role = instance_user.role

    collection_udfs = instance.userdefinedfielddefinition_set\
                              .filter(iscollection=True)
    collection_udf_dict = {"%s.%s" % (udf.model_type.lower(),
                                      udf.canonical_name): udf
                           for udf in collection_udfs}

    # collect perms for the given role/instance into a serializable
    # dictionary. If a field isn't at least readable, it doesn't
    # get sent over at all.
    perms = {}
    for fp in role_permissions(role, instance):
        model = fp.model_name.lower()
        field_key = '%s.%s' % (model, fp.field_name)
        if fp.allows_reads:
            if field_key in collection_udf_dict:
                choices = []
                data_type = collection_udf_dict[field_key].datatype
            elif is_json_field_reference(fp.field_name):
                choices = None
                data_type = "string"
            else:
                model_inst = safe_get_model_class(fp.model_name)(
                    instance=instance)
                data_type, _, choices = field_type_label_choices(
                    model_inst, fp.field_name, fp.display_field_name)

            digits = get_digits_if_formattable(
                instance, model, fp.field_name)

            units = get_units_if_convertible(
                instance, model, fp.field_name)

            factor = 1.0

            try:
                factor = get_conversion_factor(
                    instance, model, fp.field_name)
            except KeyError:
                pass

            perms[field_key] = {
                'data_type': data_type,
                'choices': choices,
                'units': units,
                'digits': digits,
                'canonical_units_factor': 1.0 / factor,
                'can_write': fp.allows_writes,
                'display_name': fp.display_field_name,
                'field_name': fp.field_name,
                'field_key': field_key,
                'is_collection': field_key in collection_udf_dict
            }

    info = _instance_info_dict(instance)
    info['fields'] = perms
    info['field_key_groups'] = instance.mobile_api_fields
    info['search'] = instance.mobile_search_fields
    info['date_format'] = _unicode_dateformat(instance.date_format)
    info['short_date_format'] = _unicode_dateformat(instance.short_date_format)

    info['meta_perms'] = {
        'can_add_tree': perms_lib.plot_is_creatable(role),
        'can_edit_tree': perms_lib.plot_is_writable(role),
        'can_edit_tree_photo': perms_lib.treephoto_is_writable(role),
    }

    public_config_keys = ['scss_variables']

    info['config'] = {x: instance.config[x]
                      for x in instance.config
                      if x in public_config_keys}

    if instance.logo:
        info['logoUrl'] = instance.logo.url

    return info
Exemple #12
0
def instance_info(request, instance):
    """
    Get all the info we need about a given instance

    If also includes info about the fields available for the
    instance. If a user has been specified the field info
    will be tailored to that user
    """
    user = request.user

    role = instance.default_role
    if user and not user.is_anonymous():
        instance_user = user.get_instance_user(instance)
        if instance_user:
            role = instance_user.role

    perms = {}

    collection_udfs = instance.userdefinedfielddefinition_set\
                              .filter(iscollection=True)
    collection_udf_dict = {
        "%s.%s" % (udf.model_type.lower(), udf.canonical_name): udf
        for udf in collection_udfs
    }

    for fp in role.fieldpermission_set.all():
        model = fp.model_name.lower()
        field_key = '%s.%s' % (model, fp.field_name)
        if fp.allows_reads:
            if field_key in collection_udf_dict:
                choices = []
                data_type = collection_udf_dict[field_key].datatype
            elif is_json_field_reference(fp.field_name):
                choices = None
                data_type = "string"
            else:
                model_inst = safe_get_model_class(
                    fp.model_name)(instance=instance)
                data_type, _, choices = field_type_label_choices(
                    model_inst, fp.field_name, fp.display_field_name)

            digits = get_digits_if_formattable(instance, model, fp.field_name)

            units = get_units_if_convertible(instance, model, fp.field_name)

            factor = 1.0

            try:
                factor = get_conversion_factor(instance, model, fp.field_name)
            except KeyError:
                pass

            perms[field_key] = {
                'data_type': data_type,
                'choices': choices,
                'units': units,
                'digits': digits,
                'canonical_units_factor': 1.0 / factor,
                'can_write': fp.allows_writes,
                'display_name': fp.display_field_name,
                'field_name': fp.field_name,
                'field_key': field_key,
                'is_collection': field_key in collection_udf_dict
            }

    info = _instance_info_dict(instance)
    info['fields'] = perms
    info['field_key_groups'] = instance.mobile_api_fields
    info['search'] = instance.mobile_search_fields

    public_config_keys = ['scss_variables']

    info['config'] = {
        x: instance.config[x]
        for x in instance.config if x in public_config_keys
    }

    if instance.logo:
        info['logoUrl'] = instance.logo.url

    return info
Exemple #13
0
def advanced_search_fields(instance, user):
    from treemap.util import get_model_for_instance
    from treemap.templatetags.form_extras import field_type_label_choices
    from treemap.models import Tree, MapFeature  # prevent circular import

    def make_display_filter(feature_name):
        if feature_name == 'Plot':
            plural = _('empty planting sites')
            feature_name = 'EmptyPlot'
        else:
            plural = get_plural_feature_name(feature_name)

        return {
            'label': _('Show %(models)s') % {
                'models': plural.lower()
            },
            'model': feature_name
        }

    def get_plural_feature_name(feature_name):
        if feature_name == 'Tree':
            Feature = Tree
        else:
            Feature = MapFeature.get_subclass(feature_name)
        return Feature.terminology(instance)['plural']

    def parse_field_info(field_info):
        model_name, field_name = field_info['identifier'].split('.', 2)
        model = get_model_for_instance(model_name, instance)
        return model, field_name

    def get_visible_fields(fields, user):
        visible_fields = []
        for field in fields:
            model, field_name = parse_field_info(field)
            if model.field_is_visible(user, field_name):
                visible_fields.append(field)
        return visible_fields

    fields = copy.deepcopy(instance.search_config)
    fields = {
        model: get_visible_fields(fields, user)
        for model, fields in fields.iteritems()
    }

    for field_info in fields.get('missing', []):
        model, field_name = parse_field_info(field_info)

        if field_name == 'id':
            if hasattr(model, 'terminology'):
                label = model.terminology(instance)['plural']
            else:
                label = model._meta.verbose_name_plural
        else:
            __, label, __ = field_type_label_choices(model, field_name, '')

        field_info['label'] = _('Show missing %(field)s') % {
            'field': label.lower()
        }
        field_info['search_type'] = 'ISNULL'
        field_info['value'] = 'true'

    fields['display'] = [
        make_display_filter('Tree'),
        make_display_filter('Plot')
    ]
    fields['display'] += [
        make_display_filter(feature)
        for feature in sorted(instance.map_feature_types) if feature != 'Plot'
    ]

    num = 0
    for filters in fields.itervalues():
        for field in filters:
            # It makes styling easier if every field has an identifier
            field['id'] = "%s_%s" % (field.get('identifier', ''), num)
            num += 1

    more = []
    for feature_name in sorted(instance.map_feature_types):
        if feature_name in fields and feature_name != 'Plot':
            filters = fields.pop(feature_name)
            filters = get_visible_fields(filters, user)

            if len(filters) > 0:
                more.append({
                    'name': feature_name,
                    'title': get_plural_feature_name(feature_name),
                    'fields': filters
                })
    fields['more'] = more

    return fields
Exemple #14
0
def advanced_search_fields(instance, user):
    from treemap.util import get_model_for_instance
    from treemap.templatetags.form_extras import field_type_label_choices
    from treemap.models import Tree, MapFeature  # prevent circular import

    def make_display_filter(feature_name):
        if feature_name == 'Plot':
            plural = _('empty planting sites')
            feature_name = 'EmptyPlot'
        else:
            plural = get_plural_feature_name(feature_name)

        return {
            'label': _('Show %(models)s') % {'models': plural.lower()},
            'model': feature_name
        }

    def get_plural_feature_name(feature_name):
        if feature_name == 'Tree':
            Feature = Tree
        else:
            Feature = MapFeature.get_subclass(feature_name)
        return Feature.terminology(instance)['plural']

    def parse_field_info(field_info):
        model_name, field_name = field_info['identifier'].split('.', 2)
        model = get_model_for_instance(model_name, instance)
        return model, field_name

    def get_visible_fields(fields, user):
        visible_fields = []
        for field in fields:
            model, field_name = parse_field_info(field)
            if model.field_is_visible(user, field_name):
                visible_fields.append(field)
        return visible_fields

    fields = copy.deepcopy(instance.search_config)
    fields = {model: get_visible_fields(fields, user)
              for model, fields in fields.iteritems()}

    for field_info in fields.get('missing', []):
        model, field_name = parse_field_info(field_info)

        if field_name == 'id':
            if hasattr(model, 'terminology'):
                label = model.terminology(instance)['plural']
            else:
                label = model._meta.verbose_name_plural
        else:
            __, label, __ = field_type_label_choices(model, field_name, '')

        field_info['label'] = _('Show missing %(field)s') % {
            'field': label.lower()}
        field_info['search_type'] = 'ISNULL'
        field_info['value'] = 'true'

    fields['display'] = [make_display_filter('Tree'),
                         make_display_filter('Plot')]
    fields['display'] += [
        make_display_filter(feature)
        for feature in sorted(instance.map_feature_types) if feature != 'Plot']

    num = 0
    for filters in fields.itervalues():
        for field in filters:
            # It makes styling easier if every field has an identifier
            field['id'] = "%s_%s" % (field.get('identifier', ''), num)
            num += 1

    more = []
    for feature_name in sorted(instance.map_feature_types):
        if feature_name in fields and feature_name != 'Plot':
            filters = fields.pop(feature_name)
            filters = get_visible_fields(filters, user)

            if len(filters) > 0:
                more.append({
                    'name': feature_name,
                    'title': get_plural_feature_name(feature_name),
                    'fields': filters
                })
    fields['more'] = more

    return fields