Пример #1
0
def context_dict_for_resource(request, resource, **kwargs):
    context = context_dict_for_map_feature(request, resource, **kwargs)
    instance = request.instance

    # Give them 2 for adding the resource and answering its questions
    total_progress_items = 3
    completed_progress_items = 2

    context['external_link'] = None

    photos = resource.photos()
    context['photos'] = [context_dict_for_photo(request, photo)
                         for photo in photos]

    has_photos = len(photos) > 0

    if has_photos:
        completed_progress_items += 1

    context['upload_photo_endpoint'] = reverse(
        'add_photo_to_map_feature',
        kwargs={'instance_url_name': instance.url_name,
                'feature_id': resource.pk})

    context['progress_percent'] = int(100 * (
        completed_progress_items / total_progress_items) + .5)

    context['progress_messages'] = []
    if not has_photos:
        context['progress_messages'].append(_('Add a photo'))

    audits = _map_feature_audits(request.user, request.instance, resource)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    object_name_alias = to_object_name(context['feature'].__class__.__name__)
    # some features that were originally written to support plot and tree
    # have grown to support other resource types, but they expect a context
    # entry for their type, not just for 'feature'.
    # For example:
    # * Plot detail expects 'plot' and 'tree'
    # * Foo detail would expect 'foo'
    context[object_name_alias] = context['feature']

    if isinstance(resource, PolygonalMapFeature):
        context['contained_plots'] = resource.contained_plots()
        area = resource.calculate_area()
        __, display_area = get_display_value(instance,
                                             'greenInfrastructure', 'area',
                                             area, digits=0)
        display_units = get_unit_abbreviation(
            get_units(instance, 'greenInfrastructure', 'area'))
        context['area'] = area
        context['display_area'] = display_area
        context['area_units'] = display_units

    return context
Пример #2
0
def context_dict_for_resource(request, resource, **kwargs):
    context = context_dict_for_map_feature(request, resource, **kwargs)
    instance = request.instance

    # Give them 2 for adding the resource and answering its questions
    total_progress_items = 3
    completed_progress_items = 2

    context['external_link'] = None

    photos = resource.photos()
    context['photos'] = [
        context_dict_for_photo(request, photo) for photo in photos
    ]

    has_photos = len(photos) > 0

    if has_photos:
        completed_progress_items += 1

    context['upload_photo_endpoint'] = reverse('add_photo_to_map_feature',
                                               kwargs={
                                                   'instance_url_name':
                                                   instance.url_name,
                                                   'feature_id': resource.pk
                                               })

    context['progress_percent'] = int(
        100 * (completed_progress_items / total_progress_items) + .5)

    context['progress_messages'] = []
    if not has_photos:
        context['progress_messages'].append(_('Add a photo'))

    audits = _map_feature_audits(request.user, request.instance, resource)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    object_name_alias = to_object_name(context['feature'].__class__.__name__)
    # some features that were originally written to support plot and tree
    # have grown to support other resource types, but they expect a context
    # entry for their type, not just for 'feature'.
    # For example:
    # * Plot detail expects 'plot' and 'tree'
    # * Foo detail would expect 'foo'
    context[object_name_alias] = context['feature']

    if isinstance(resource, PolygonalMapFeature):
        context['contained_plots'] = resource.contained_plots()
        __, display_area = get_display_value(instance, 'greenInfrastructure',
                                             'area', resource.calculate_area())
        display_units = get_unit_abbreviation(
            get_units(instance, 'greenInfrastructure', 'area'))
        context['area'] = '{} {}'.format(display_area, display_units)

    return context
Пример #3
0
 def wrapper(request, instance, feature_id, *args, **kwargs):
     error = None
     try:
         fn(request, instance, feature_id, *args, **kwargs)
     except ValidationError as e:
         error = "; ".join(e.messages)
     feature = get_map_feature_or_404(feature_id, instance)
     photos = feature.photos()
     return {"photos": [context_dict_for_photo(request, photo) for photo in photos], "error": error}
Пример #4
0
 def wrapper(request, instance, feature_id, *args, **kwargs):
     error = None
     try:
         fn(request, instance, feature_id, *args, **kwargs)
     except ValidationError as e:
         error = '; '.join(e.messages)
     feature = get_map_feature_or_404(feature_id, instance)
     photos = feature.photos()
     return {'photos': [context_dict_for_photo(request, photo)
                        for photo in photos],
             'feature': feature,
             'error': error}
Пример #5
0
def add_tree_photo(request, instance, feature_id, tree_id=None):
    error = None
    try:
        _, tree = add_tree_photo_helper(request, instance, feature_id, tree_id)
        photos = tree.photos()
    except ValidationError as e:
        trees = Tree.objects.filter(pk=tree_id)
        if len(trees) == 1:
            photos = trees[0].photos()
        else:
            photos = []
        # TODO: Better display error messages in the view
        error = '; '.join(e.messages)
    return {'photos': [context_dict_for_photo(request, photo)
                       for photo in photos],
            'error': error}
Пример #6
0
def add_tree_photo(request, instance, feature_id, tree_id=None):
    error = None
    try:
        __, tree = add_tree_photo_helper(
            request, instance, feature_id, tree_id)
        photos = tree.photos()
    except ValidationError as e:
        trees = Tree.objects.filter(pk=tree_id)
        if len(trees) == 1:
            photos = trees[0].photos()
        else:
            photos = []
        # TODO: Better display error messages in the view
        error = '; '.join(e.messages)
    return {'photos': [context_dict_for_photo(request, photo)
                       for photo in photos],
            'error': error}
Пример #7
0
def context_dict_for_resource(request, resource, **kwargs):
    context = context_dict_for_map_feature(request, resource, **kwargs)
    instance = request.instance

    # Give them 2 for adding the resource and answering its questions
    total_progress_items = 3
    completed_progress_items = 2

    photos = resource.photos()
    context["photos"] = [context_dict_for_photo(request, photo) for photo in photos]

    has_photos = len(photos) > 0

    if has_photos:
        completed_progress_items += 1

    context["upload_photo_endpoint"] = reverse(
        "add_photo_to_map_feature", kwargs={"instance_url_name": instance.url_name, "feature_id": resource.pk}
    )

    context["progress_percent"] = int(100 * (completed_progress_items / total_progress_items) + 0.5)

    context["progress_messages"] = []
    if not has_photos:
        context["progress_messages"].append(_("Add a photo"))

    audits = _map_feature_audits(request.user, request.instance, resource)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    object_name_alias = to_object_name(context["feature"].__class__.__name__)
    # some features that were originally written to support plot and tree
    # have grown to support other resource types, but they expect a context
    # entry for their type, not just for 'feature'.
    # For example:
    # * Plot detail expects 'plot' and 'tree'
    # * Foo detail would expect 'foo'
    context[object_name_alias] = context["feature"]

    if isinstance(resource, PolygonalMapFeature):
        context["contained_plots"] = resource.contained_plots()

    return context
Пример #8
0
def context_dict_for_resource(request, resource):
    context = context_dict_for_map_feature(request, resource)
    instance = request.instance

    # Give them 2 for adding the resource and answering its questions
    total_progress_items = 3
    completed_progress_items = 2

    photos = resource.photos()
    context['photos'] = [
        context_dict_for_photo(request, photo) for photo in photos
    ]

    has_photos = len(photos) > 0

    if has_photos:
        completed_progress_items += 1

    context['upload_photo_endpoint'] = reverse('add_photo_to_map_feature',
                                               kwargs={
                                                   'instance_url_name':
                                                   instance.url_name,
                                                   'feature_id': resource.pk
                                               })

    context['progress_percent'] = int(
        100 * (completed_progress_items / total_progress_items) + .5)

    context['progress_messages'] = []
    if not has_photos:
        context['progress_messages'].append(trans('Add a photo'))

    audits = _map_feature_audits(request.user, request.instance, resource)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    return context
Пример #9
0
def context_dict_for_resource(request, resource, **kwargs):
    context = context_dict_for_map_feature(request, resource, **kwargs)
    instance = request.instance

    # Give them 2 for adding the resource and answering its questions
    total_progress_items = 3
    completed_progress_items = 2

    photos = resource.photos()
    context['photos'] = [context_dict_for_photo(request, photo)
                         for photo in photos]

    has_photos = len(photos) > 0

    if has_photos:
        completed_progress_items += 1

    context['upload_photo_endpoint'] = reverse(
        'add_photo_to_map_feature',
        kwargs={'instance_url_name': instance.url_name,
                'feature_id': resource.pk})

    context['progress_percent'] = int(100 * (
        completed_progress_items / total_progress_items) + .5)

    context['progress_messages'] = []
    if not has_photos:
        context['progress_messages'].append(_('Add a photo'))

    audits = _map_feature_audits(request.user, request.instance, resource)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    return context
Пример #10
0
def add_photo(request, instance, plot_id):
    treephoto, __ = add_tree_photo_helper(request, instance, plot_id)

    return context_dict_for_photo(request, treephoto)
Пример #11
0
def map_feature_photo_detail(request, instance, feature_id, photo_id):
    feature = get_map_feature_or_404(feature_id, instance)
    photo = get_object_or_404(MapFeaturePhoto,
                              pk=photo_id,
                              map_feature=feature)
    return {'photo': context_dict_for_photo(request, photo)}
Пример #12
0
def map_feature_photo_detail(request, instance, feature_id, photo_id):
    feature = get_map_feature_or_404(feature_id, instance)
    photo = get_object_or_404(MapFeaturePhoto, pk=photo_id,
                              map_feature=feature)
    return {'photo': context_dict_for_photo(request, photo)}
Пример #13
0
def context_dict_for_plot(request, plot, tree_id=None, **kwargs):
    context = context_dict_for_map_feature(request, plot, **kwargs)

    instance = request.instance
    user = request.user

    if tree_id:
        tree = get_object_or_404(Tree,
                                 instance=instance,
                                 plot=plot,
                                 pk=tree_id)
    else:
        tree = plot.current_tree()

    if tree:
        tree.convert_to_display_units()

    if tree is not None:
        photos = tree.photos()
        # can't send a regular photo qs because the API will
        # serialize this to JSON, which is not supported for qs
        context['photos'] = [context_dict_for_photo(request, photo)
                             for photo in photos]
    else:
        photos = []

    has_tree_diameter = tree is not None and tree.diameter is not None
    has_tree_species_with_code = tree is not None \
        and tree.species is not None and tree.species.otm_code is not None
    has_photo = tree is not None and len(photos) > 0

    total_progress_items = 4
    completed_progress_items = 1  # there is always a plot

    if has_tree_diameter:
        completed_progress_items += 1
    if has_tree_species_with_code:
        completed_progress_items += 1
    if has_photo:
        completed_progress_items += 1

    context['progress_percent'] = int(100 * (
        completed_progress_items / total_progress_items))

    context['progress_messages'] = []
    if not tree:
        context['progress_messages'].append(_('Add a tree'))
    if not has_tree_diameter:
        context['progress_messages'].append(_('Add the diameter'))
    if not has_tree_species_with_code:
        context['progress_messages'].append(_('Add the species'))
    if not has_photo:
        context['progress_messages'].append(_('Add a photo'))

    url_kwargs = {'instance_url_name': instance.url_name,
                  'feature_id': plot.pk}
    if tree:
        url_name = 'add_photo_to_tree'
        url_kwargs = dict(url_kwargs.items() + [('tree_id', tree.pk)])
    else:
        url_name = 'add_photo_to_plot'

    context['upload_photo_endpoint'] = reverse(url_name, kwargs=url_kwargs)

    context['plot'] = plot
    context['has_tree'] = tree is not None
    # Give an empty tree when there is none in order to show tree fields easily
    context['tree'] = tree or Tree(plot=plot, instance=instance)

    context['photo_upload_share_text'] = _photo_upload_share_text(
        plot, tree is not None)

    pmfs = PolygonalMapFeature.objects.filter(polygon__contains=plot.geom)

    if pmfs:
        context['containing_polygonalmapfeature'] = pmfs[0].cast_to_subtype()

    audits = _plot_audits(user, instance, plot)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    return context
Пример #14
0
def add_photo(request, instance, plot_id):
    treephoto, _ = add_tree_photo_helper(request, instance, plot_id)

    return context_dict_for_photo(treephoto)
Пример #15
0
def context_dict_for_plot(request, plot, tree_id=None, **kwargs):
    context = context_dict_for_map_feature(request, plot, **kwargs)

    instance = request.instance
    user = request.user

    if tree_id:
        tree = get_object_or_404(Tree,
                                 instance=instance,
                                 plot=plot,
                                 pk=tree_id)
    else:
        tree = plot.current_tree()

    if tree:
        tree.convert_to_display_units()

    if tree is not None:
        photos = tree.photos()
        # can't send a regular photo qs because the API will
        # serialize this to JSON, which is not supported for qs
        context['photos'] = [
            context_dict_for_photo(request, photo) for photo in photos
        ]
    else:
        photos = []

    def get_external_link_url(user, feature, tree=None):
        if not user or not feature or not feature.is_plot:
            return None
        instance = feature.instance
        external_link_config =  \
            get_attr_from_json_field(instance, 'config.externalLink') or None
        if not external_link_config or \
                not external_link_config.get('url', None) or \
                not external_link_config.get('text', None):
            return None
        role = Role.objects.get_role(instance, user)
        if not role.has_permission('view_external_link'):
            return None
        external_url = external_link_config['url']
        if not tree and -1 < external_url.find(r'#{tree.id}'):
            return None

        plot = feature.cast_to_subtype()
        substitutes = {
            'planting_site.id': str(plot.pk),
            'planting_site.custom_id': plot.owner_orig_id or '',
            'tree.id': tree and str(tree.pk) or ''
        }

        class UrlTemplate(Template):
            delimiter = '#'
            pattern = '''
            \#(?:
                (?P<escaped>\#)         |  # escape with repeated delimiter
                (?P<named>(?:{0}))      |  # "#foo" substitutes foo keyword
                {{(?P<braced>(?:{0}))}} |  # "#{{foo}}" substitutes foo keyword
                (?P<invalid>{{}})          # requires a name
            )
            '''.format(get_external_link_choice_pattern())

        return UrlTemplate(external_url).safe_substitute(substitutes)

    context['external_link'] = get_external_link_url(user, plot, tree)

    has_tree_diameter = tree is not None and tree.diameter is not None
    has_tree_species_with_code = tree is not None \
        and tree.species is not None and tree.species.otm_code is not None
    has_photo = tree is not None and len(photos) > 0

    total_progress_items = 4
    completed_progress_items = 1  # there is always a plot

    if has_tree_diameter:
        completed_progress_items += 1
    if has_tree_species_with_code:
        completed_progress_items += 1
    if has_photo:
        completed_progress_items += 1

    context['progress_percent'] = int(
        100 * (completed_progress_items / total_progress_items))

    context['progress_messages'] = []
    if not tree:
        context['progress_messages'].append(_('Add a tree'))
    if not has_tree_diameter:
        context['progress_messages'].append(_('Add the diameter'))
    if not has_tree_species_with_code:
        context['progress_messages'].append(_('Add the species'))
    if not has_photo:
        context['progress_messages'].append(_('Add a photo'))

    url_kwargs = {
        'instance_url_name': instance.url_name,
        'feature_id': plot.pk
    }
    if tree:
        url_name = 'add_photo_to_tree'
        url_kwargs = dict(url_kwargs.items() + [('tree_id', tree.pk)])
    else:
        url_name = 'add_photo_to_plot'

    context['upload_photo_endpoint'] = reverse(url_name, kwargs=url_kwargs)

    context['plot'] = plot
    context['has_tree'] = tree is not None
    # Give an empty tree when there is none in order to show tree fields easily
    context['tree'] = tree or Tree(plot=plot, instance=instance)

    context['photo_upload_share_text'] = _photo_upload_share_text(
        plot, tree is not None)

    pmfs = PolygonalMapFeature.objects.filter(
        polygon__contains=plot.geom, mapfeature_ptr__instance_id=instance.id)

    if pmfs:
        context['containing_polygonalmapfeature'] = pmfs[0].cast_to_subtype()

    audits = _plot_audits(user, instance, plot)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    return context
Пример #16
0
def context_dict_for_plot(request, plot, tree_id=None, **kwargs):
    context = context_dict_for_map_feature(request, plot, **kwargs)

    instance = request.instance
    user = request.user

    if tree_id:
        tree = get_object_or_404(Tree,
                                 instance=instance,
                                 plot=plot,
                                 pk=tree_id)
    else:
        tree = plot.current_tree()

    if tree:
        tree.convert_to_display_units()

    if tree is not None:
        photos = tree.photos()
        # can't send a regular photo qs because the API will
        # serialize this to JSON, which is not supported for qs
        context['photos'] = [context_dict_for_photo(request, photo)
                             for photo in photos]
    else:
        photos = []

    has_tree_diameter = tree is not None and tree.diameter is not None
    has_tree_species_with_code = tree is not None \
        and tree.species is not None and tree.species.otm_code is not None
    has_photo = tree is not None and len(photos) > 0

    total_progress_items = 4
    completed_progress_items = 1  # there is always a plot

    if has_tree_diameter:
        completed_progress_items += 1
    if has_tree_species_with_code:
        completed_progress_items += 1
    if has_photo:
        completed_progress_items += 1

    context['progress_percent'] = int(100 * (
        completed_progress_items / total_progress_items))

    context['progress_messages'] = []
    if not tree:
        context['progress_messages'].append(_('Add a tree'))
    if not has_tree_diameter:
        context['progress_messages'].append(_('Add the diameter'))
    if not has_tree_species_with_code:
        context['progress_messages'].append(_('Add the species'))
    if not has_photo:
        context['progress_messages'].append(_('Add a photo'))

    url_kwargs = {'instance_url_name': instance.url_name,
                  'feature_id': plot.pk}
    if tree:
        url_name = 'add_photo_to_tree'
        url_kwargs = dict(url_kwargs.items() + [('tree_id', tree.pk)])
    else:
        url_name = 'add_photo_to_plot'

    context['upload_photo_endpoint'] = reverse(url_name, kwargs=url_kwargs)

    context['plot'] = plot
    context['has_tree'] = tree is not None
    # Give an empty tree when there is none in order to show tree fields easily
    context['tree'] = tree or Tree(plot=plot, instance=instance)

    context['photo_upload_share_text'] = _photo_upload_share_text(
        plot, tree is not None)

    pmfs = PolygonalMapFeature.objects.filter(polygon__contains=plot.geom)

    if pmfs:
        context['containing_polygonalmapfeature'] = pmfs[0].cast_to_subtype()

    audits = _plot_audits(user, instance, plot)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    return context
Пример #17
0
def context_dict_for_plot(request, plot, tree_id=None, **kwargs):
    context = context_dict_for_map_feature(request, plot, **kwargs)

    instance = request.instance
    user = request.user

    if tree_id:
        tree = get_object_or_404(Tree,
                                 instance=instance,
                                 plot=plot,
                                 pk=tree_id)
    else:
        tree = plot.current_tree()

    if tree:
        tree.convert_to_display_units()

    if tree is not None:
        photos = tree.photos()
        # can't send a regular photo qs because the API will
        # serialize this to JSON, which is not supported for qs
        context['photos'] = [context_dict_for_photo(request, photo)
                             for photo in photos]
    else:
        photos = []

    def get_external_link_url(user, feature, tree=None):
        if not user or not feature or not feature.is_plot:
            return None
        instance = feature.instance
        external_link_config =  \
            get_attr_from_json_field(instance, 'config.externalLink') or None
        if not external_link_config or \
                not external_link_config.get('url', None) or \
                not external_link_config.get('text', None):
            return None
        role = Role.objects.get_role(instance, user)
        if not role.has_permission('view_external_link'):
            return None
        external_url = external_link_config['url']
        if not tree and -1 < external_url.find(r'#{tree.id}'):
            return None

        plot = feature.cast_to_subtype()
        substitutes = {
            'planting_site.id': str(plot.pk),
            'planting_site.custom_id': plot.owner_orig_id or '',
            'tree.id': tree and str(tree.pk) or ''
        }

        class UrlTemplate(Template):
            delimiter = '#'
            pattern = '''
            \#(?:
                (?P<escaped>\#)         |  # escape with repeated delimiter
                (?P<named>(?:{0}))      |  # "#foo" substitutes foo keyword
                {{(?P<braced>(?:{0}))}} |  # "#{{foo}}" substitutes foo keyword
                (?P<invalid>{{}})          # requires a name
            )
            '''.format(get_external_link_choice_pattern())

        return UrlTemplate(external_url).safe_substitute(substitutes)

    context['external_link'] = get_external_link_url(user, plot, tree)

    has_tree_diameter = tree is not None and tree.diameter is not None
    has_tree_species_with_code = tree is not None \
        and tree.species is not None and tree.species.otm_code is not None
    has_photo = tree is not None and len(photos) > 0

    total_progress_items = 4
    completed_progress_items = 1  # there is always a plot

    if has_tree_diameter:
        completed_progress_items += 1
    if has_tree_species_with_code:
        completed_progress_items += 1
    if has_photo:
        completed_progress_items += 1

    context['progress_percent'] = int(100 * (
        completed_progress_items / total_progress_items))

    context['progress_messages'] = []
    if not tree:
        context['progress_messages'].append(_('Add a tree'))
    if not has_tree_diameter:
        context['progress_messages'].append(_('Add the diameter'))
    if not has_tree_species_with_code:
        context['progress_messages'].append(_('Add the species'))
    if not has_photo:
        context['progress_messages'].append(_('Add a photo'))

    url_kwargs = {'instance_url_name': instance.url_name,
                  'feature_id': plot.pk}
    if tree:
        url_name = 'add_photo_to_tree'
        url_kwargs = dict(url_kwargs.items() + [('tree_id', tree.pk)])
    else:
        url_name = 'add_photo_to_plot'

    context['upload_photo_endpoint'] = reverse(url_name, kwargs=url_kwargs)

    context['plot'] = plot
    context['has_tree'] = tree is not None
    # Give an empty tree when there is none in order to show tree fields easily
    context['tree'] = tree or Tree(plot=plot, instance=instance)

    context['photo_upload_share_text'] = _photo_upload_share_text(
        plot, tree is not None)

    pmfs = PolygonalMapFeature.objects.filter(
        polygon__contains=plot.geom,
        mapfeature_ptr__instance_id=instance.id)

    if pmfs:
        context['containing_polygonalmapfeature'] = pmfs[0].cast_to_subtype()

    audits = _plot_audits(user, instance, plot)

    _add_audits_to_context(audits, context)

    _add_share_context(context, request, photos)

    return context