Exemple #1
0
    def delete(self, request, view_sort_id):
        """Deletes an existing sort if the user belongs to the group."""

        view = ViewHandler().get_sort(request.user, view_sort_id)
        ViewHandler().delete_sort(request.user, view)

        return Response(status=204)
Exemple #2
0
def test_get_view(data_fixture):
    user = data_fixture.create_user()
    user_2 = data_fixture.create_user()
    grid = data_fixture.create_grid_view(user=user)

    handler = ViewHandler()

    with pytest.raises(ViewDoesNotExist):
        handler.get_view(user=user, view_id=99999)

    with pytest.raises(UserNotInGroupError):
        handler.get_view(user=user_2, view_id=grid.id)

    view = handler.get_view(user=user, view_id=grid.id)

    assert view.id == grid.id
    assert view.name == grid.name
    assert view.filter_type == 'AND'
    assert not view.filters_disabled
    assert isinstance(view, View)

    view = handler.get_view(user=user, view_id=grid.id, view_model=GridView)

    assert view.id == grid.id
    assert view.name == grid.name
    assert view.filter_type == 'AND'
    assert not view.filters_disabled
    assert isinstance(view, GridView)

    # If the error is raised we know for sure that the query has resolved.
    with pytest.raises(AttributeError):
        handler.get_view(
            user=user,
            view_id=grid.id,
            base_queryset=View.objects.prefetch_related('UNKNOWN'))
Exemple #3
0
def test_update_view(data_fixture):
    user = data_fixture.create_user()
    user_2 = data_fixture.create_user()
    table = data_fixture.create_database_table(user=user)
    grid = data_fixture.create_grid_view(table=table)

    handler = ViewHandler()

    with pytest.raises(UserNotInGroupError):
        handler.update_view(user=user_2, view=grid, name='Test 1')

    with pytest.raises(ValueError):
        handler.update_view(user=user, view=object(), name='Test 1')

    handler.update_view(user=user, view=grid, name='Test 1')

    grid.refresh_from_db()
    assert grid.name == 'Test 1'
    assert grid.filter_type == 'AND'
    assert not grid.filters_disabled

    handler.update_view(user=user,
                        view=grid,
                        filter_type='OR',
                        filters_disabled=True)

    grid.refresh_from_db()
    assert grid.filter_type == 'OR'
    assert grid.filters_disabled
Exemple #4
0
    def fill_example_table_data(self, user, table):
        """
        Fills the table with some initial example data. A new table is expected that
        already has the a primary field named 'name'.

        :param user: The user on whose behalf the table is filled.
        :type: user: User
        :param table: The table that needs the initial data.
        :type table: User
        """

        view_handler = ViewHandler()
        field_handler = FieldHandler()

        view = view_handler.create_view(user, table, GridViewType.type, name='Grid')
        notes = field_handler.create_field(user, table, LongTextFieldType.type,
                                           name='Notes')
        active = field_handler.create_field(user, table, BooleanFieldType.type,
                                            name='Active')

        field_options = {
            notes.id: {'width': 400},
            active.id: {'width': 100}
        }
        fields = [notes, active]
        view_handler.update_grid_view_field_options(view, field_options, fields=fields)

        model = table.get_model(attribute_names=True)
        model.objects.create(name='Tesla', active=True)
        model.objects.create(name='Amazon', active=False)
Exemple #5
0
def test_single_select_field_type_get_order(data_fixture):
    user = data_fixture.create_user()
    database = data_fixture.create_database_application(user=user,
                                                        name='Placeholder')
    table = data_fixture.create_database_table(name='Example',
                                               database=database)
    field = data_fixture.create_single_select_field(table=table)
    option_c = data_fixture.create_select_option(field=field,
                                                 value='C',
                                                 color='blue')
    option_a = data_fixture.create_select_option(field=field,
                                                 value='A',
                                                 color='blue')
    option_b = data_fixture.create_select_option(field=field,
                                                 value='B',
                                                 color='blue')
    grid_view = data_fixture.create_grid_view(table=table)

    view_handler = ViewHandler()
    row_handler = RowHandler()

    row_1 = row_handler.create_row(user=user,
                                   table=table,
                                   values={f'field_{field.id}': option_b.id})
    row_2 = row_handler.create_row(user=user,
                                   table=table,
                                   values={f'field_{field.id}': option_a.id})
    row_3 = row_handler.create_row(user=user,
                                   table=table,
                                   values={f'field_{field.id}': option_c.id})
    row_4 = row_handler.create_row(user=user,
                                   table=table,
                                   values={f'field_{field.id}': option_b.id})
    row_5 = row_handler.create_row(user=user,
                                   table=table,
                                   values={f'field_{field.id}': None})

    sort = data_fixture.create_view_sort(view=grid_view,
                                         field=field,
                                         order='ASC')
    model = table.get_model()
    rows = view_handler.apply_sorting(grid_view, model.objects.all())
    row_ids = [row.id for row in rows]
    assert row_ids == [row_5.id, row_2.id, row_1.id, row_4.id, row_3.id]

    sort.order = 'DESC'
    sort.save()
    rows = view_handler.apply_sorting(grid_view, model.objects.all())
    row_ids = [row.id for row in rows]
    assert row_ids == [row_3.id, row_1.id, row_4.id, row_2.id, row_5.id]

    option_a.value = 'Z'
    option_a.save()
    sort.order = 'ASC'
    sort.save()
    model = table.get_model()
    rows = view_handler.apply_sorting(grid_view, model.objects.all())
    row_ids = [row.id for row in rows]
    assert row_ids == [row_5.id, row_1.id, row_4.id, row_3.id, row_2.id]
Exemple #6
0
def test_get_filter(data_fixture):
    user = data_fixture.create_user()
    user_2 = data_fixture.create_user()
    equal_filter = data_fixture.create_view_filter(user=user)

    handler = ViewHandler()

    with pytest.raises(ViewFilterDoesNotExist):
        handler.get_filter(user=user, view_filter_id=99999)

    with pytest.raises(UserNotInGroupError):
        handler.get_filter(user=user_2, view_filter_id=equal_filter.id)

    with pytest.raises(AttributeError):
        handler.get_filter(
            user=user,
            view_filter_id=equal_filter.id,
            base_queryset=ViewFilter.objects.prefetch_related('UNKNOWN'))

    filter = handler.get_filter(user=user, view_filter_id=equal_filter.id)

    assert filter.id == equal_filter.id
    assert filter.view_id == equal_filter.view_id
    assert filter.field_id == equal_filter.field_id
    assert filter.type == equal_filter.type
    assert filter.value == equal_filter.value
Exemple #7
0
def test_get_sort(data_fixture):
    user = data_fixture.create_user()
    user_2 = data_fixture.create_user()
    equal_sort = data_fixture.create_view_sort(user=user)

    handler = ViewHandler()

    with pytest.raises(ViewSortDoesNotExist):
        handler.get_sort(user=user, view_sort_id=99999)

    with pytest.raises(UserNotInGroupError):
        handler.get_sort(user=user_2, view_sort_id=equal_sort.id)

    with pytest.raises(AttributeError):
        handler.get_sort(
            user=user,
            view_sort_id=equal_sort.id,
            base_queryset=ViewSort.objects.prefetch_related('UNKNOWN'))

    sort = handler.get_sort(user=user, view_sort_id=equal_sort.id)

    assert sort.id == equal_sort.id
    assert sort.view_id == equal_sort.view_id
    assert sort.field_id == equal_sort.field_id
    assert sort.order == equal_sort.order
Exemple #8
0
    def get(self, request, view_id, field_options):
        """
        Lists all the rows of a grid view, paginated either by a page or offset/limit.
        If the limit get parameter is provided the limit/offset pagination will be used
        else the page number pagination.

        Optionally the field options can also be included in the response if the the
        `field_options` are provided in the include GET parameter.
        """

        search = request.GET.get('search')

        view_handler = ViewHandler()
        view = view_handler.get_view(view_id, GridView)
        view.table.database.group.has_user(request.user,
                                           raise_error=True,
                                           allow_if_template=True)

        model = view.table.get_model()
        queryset = model.objects.all().enhance_by_fields()

        # Applies the view filters and sortings to the queryset if there are any.
        queryset = view_handler.apply_filters(view, queryset)
        queryset = view_handler.apply_sorting(view, queryset)
        if search:
            queryset = queryset.search_all_fields(search)

        if 'count' in request.GET:
            return Response({'count': queryset.count()})

        if LimitOffsetPagination.limit_query_param in request.GET:
            paginator = LimitOffsetPagination()
        else:
            paginator = PageNumberPagination()

        page = paginator.paginate_queryset(queryset, request, self)
        serializer_class = get_row_serializer_class(model,
                                                    RowSerializer,
                                                    is_response=True)
        serializer = serializer_class(page, many=True)

        response = paginator.get_paginated_response(serializer.data)

        if field_options:
            # The serializer has the GridViewFieldOptionsField which fetches the
            # field options from the database and creates them if they don't exist,
            # but when added to the context the fields don't have to be fetched from
            # the database again when checking if they exist.
            context = {
                'fields': [o['field'] for o in model._field_objects.values()]
            }
            serialized_view = GridViewSerializer(view, context=context).data
            response.data['field_options'] = serialized_view['field_options']

        return response
def test_update_view(send_mock, data_fixture):
    user = data_fixture.create_user()
    user_2 = data_fixture.create_user()
    table = data_fixture.create_database_table(user=user)
    grid = data_fixture.create_grid_view(table=table)

    handler = ViewHandler()

    with pytest.raises(UserNotInGroupError):
        handler.update_view(user=user_2, view=grid, name='Test 1')

    with pytest.raises(ValueError):
        handler.update_view(user=user, view=object(), name='Test 1')

    view = handler.update_view(user=user, view=grid, name='Test 1')

    send_mock.assert_called_once()
    assert send_mock.call_args[1]['view'].id == view.id
    assert send_mock.call_args[1]['user'].id == user.id

    grid.refresh_from_db()
    assert grid.name == 'Test 1'
    assert grid.filter_type == 'AND'
    assert not grid.filters_disabled

    handler.update_view(user=user, view=grid, filter_type='OR', filters_disabled=True)

    grid.refresh_from_db()
    assert grid.filter_type == 'OR'
    assert grid.filters_disabled
Exemple #10
0
def test_create_view(send_mock, data_fixture):
    user = data_fixture.create_user()
    user_2 = data_fixture.create_user()
    table = data_fixture.create_database_table(user=user)
    table_2 = data_fixture.create_database_table(user=user)

    handler = ViewHandler()
    view = handler.create_view(user=user, table=table, type_name='grid',
                               name='Test grid')

    send_mock.assert_called_once()
    assert send_mock.call_args[1]['view'].id == view.id
    assert send_mock.call_args[1]['user'].id == user.id

    assert View.objects.all().count() == 1
    assert GridView.objects.all().count() == 1

    grid = GridView.objects.all().first()
    assert grid.name == 'Test grid'
    assert grid.order == 1
    assert grid.table == table
    assert grid.filter_type == 'AND'
    assert not grid.filters_disabled

    handler.create_view(user=user, table=table, type_name='grid',
                        name='Something else', filter_type='OR', filters_disabled=True)

    assert View.objects.all().count() == 2
    assert GridView.objects.all().count() == 2

    grid = GridView.objects.all().last()
    assert grid.name == 'Something else'
    assert grid.order == 2
    assert grid.table == table
    assert grid.filter_type == 'OR'
    assert grid.filters_disabled

    grid = handler.create_view(user=user, table=table_2, type_name='grid', name='Name',
                               filter_type='OR', filters_disabled=False)

    assert View.objects.all().count() == 3
    assert GridView.objects.all().count() == 3

    assert grid.name == 'Name'
    assert grid.order == 1
    assert grid.table == table_2
    assert grid.filter_type == 'OR'
    assert not grid.filters_disabled

    with pytest.raises(UserNotInGroupError):
        handler.create_view(user=user_2, table=table, type_name='grid', name='')

    with pytest.raises(ViewTypeDoesNotExist):
        handler.create_view(user=user, table=table, type_name='UNKNOWN', name='')
Exemple #11
0
    def post(self, request, data, view_id):
        """Creates a new sort for the provided view."""

        view_handler = ViewHandler()
        view = view_handler.get_view(request.user, view_id)
        # We can safely assume the field exists because the CreateViewSortSerializer
        # has already checked that.
        field = Field.objects.get(pk=data['field'])
        view_sort = view_handler.create_sort(request.user, view, field, data['order'])

        serializer = ViewSortSerializer(view_sort)
        return Response(serializer.data)
Exemple #12
0
    def post(self, request, data, view_id):
        """Creates a new filter for the provided view."""

        view_handler = ViewHandler()
        view = view_handler.get_view(request.user, view_id)
        # We can safely assume the field exists because the CreateViewFilterSerializer
        # has already checked that.
        field = Field.objects.get(pk=data['field'])
        view_filter = view_handler.create_filter(request.user, view, field,
                                                 data['type'], data['value'])

        serializer = ViewFilterSerializer(view_filter)
        return Response(serializer.data)
Exemple #13
0
def test_create_view(data_fixture):
    user = data_fixture.create_user()
    user_2 = data_fixture.create_user()
    table = data_fixture.create_database_table(user=user)

    handler = ViewHandler()
    handler.create_view(user=user,
                        table=table,
                        type_name='grid',
                        name='Test grid')

    assert View.objects.all().count() == 1
    assert GridView.objects.all().count() == 1

    grid = GridView.objects.all().first()
    assert grid.name == 'Test grid'
    assert grid.order == 1
    assert grid.table == table

    with pytest.raises(UserNotInGroupError):
        handler.create_view(user=user_2,
                            table=table,
                            type_name='grid',
                            name='')

    with pytest.raises(ViewTypeDoesNotExist):
        handler.create_view(user=user,
                            table=table,
                            type_name='UNKNOWN',
                            name='')
Exemple #14
0
    def patch(self, request, view_id):
        """Updates the view if the user belongs to the group."""

        view = ViewHandler().get_view(request.user, view_id).specific
        view_type = view_type_registry.get_by_model(view)
        data = validate_data_custom_fields(
            view_type.type, view_type_registry, request.data,
            base_serializer_class=UpdateViewSerializer
        )

        view = ViewHandler().update_view(request.user, view, **data)

        serializer = view_type_registry.get_serializer(view, ViewSerializer)
        return Response(serializer.data)
Exemple #15
0
    def patch(self, request, data, view_sort_id):
        """Updates the view sort if the user belongs to the group."""

        handler = ViewHandler()
        view_sort = handler.get_sort(request.user, view_sort_id)

        if 'field' in data:
            # We can safely assume the field exists because the
            # UpdateViewSortSerializer has already checked that.
            data['field'] = Field.objects.get(pk=data['field'])

        view_sort = handler.update_sort(request.user, view_sort, **data)

        serializer = ViewSortSerializer(view_sort)
        return Response(serializer.data)
Exemple #16
0
def test_update_grid_view_field_options(data_fixture):
    user = data_fixture.create_user()
    table = data_fixture.create_database_table(user=user)
    grid_view = data_fixture.create_grid_view(table=table)
    field_1 = data_fixture.create_text_field(table=table)
    field_2 = data_fixture.create_text_field(table=table)
    field_3 = data_fixture.create_text_field()

    with pytest.raises(ValueError):
        ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={
            'strange_format': {'height': 150},
        })

    with pytest.raises(UnrelatedFieldError):
        ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={
            99999: {'width': 150},
        })

    with pytest.raises(UnrelatedFieldError):
        ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={
            field_3.id: {'width': 150},
        })

    ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={
        str(field_1.id): {'width': 150},
        field_2.id: {'width': 250}
    })
    options_4 = grid_view.get_field_options()

    assert len(options_4) == 2
    assert options_4[0].width == 150
    assert options_4[0].field_id == field_1.id
    assert options_4[1].width == 250
    assert options_4[1].field_id == field_2.id

    field_4 = data_fixture.create_text_field(table=table)
    ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={
        field_2.id: {'width': 300},
        field_4.id: {'width': 50}
    })
    options_4 = grid_view.get_field_options()
    assert len(options_4) == 3
    assert options_4[0].width == 150
    assert options_4[0].field_id == field_1.id
    assert options_4[1].width == 300
    assert options_4[1].field_id == field_2.id
    assert options_4[2].width == 50
    assert options_4[2].field_id == field_4.id
Exemple #17
0
    def fill_initial_table_data(self, user, table, fields, data, model):
        """
        Fills the provided table with the normalized data that needs to be created upon
        creation of the table.

        :param user: The user on whose behalf the table is created.
        :type user: User`
        :param table: The newly created table where the initial data has to be inserted
            into.
        :type table: Table
        :param fields: A list containing the field names.
        :type fields: list
        :param data: A list containing the rows that need to be inserted.
        :type data: list
        :param model: The generated table model of the table that needs to be filled
            with initial data.
        :type model: TableModel
        """

        ViewHandler().create_view(user, table, GridViewType.type, name='Grid')

        bulk_data = [
            model(**{
                f'field_{fields[index].id}': str(value)
                for index, value in enumerate(row)
            })
            for row in data
        ]
        model.objects.bulk_create(bulk_data)
Exemple #18
0
    def patch(self, request, view_id, data):
        """
        Updates the field options for the provided grid view.

        The following example body data will only update the width of the FIELD_ID
        and leaves the others untouched.
            {
                FIELD_ID: {
                    'width': 200
                }
            }
        """

        handler = ViewHandler()
        view = handler.get_view(request.user, view_id, GridView)
        handler.update_grid_view_field_options(view, data['field_options'])
        return Response(GridViewSerializer(view).data)
Exemple #19
0
    def get(self, request, view_id, filters, sortings):
        """Selects a single view and responds with a serialized version."""

        view = ViewHandler().get_view(request.user, view_id)
        serializer = view_type_registry.get_serializer(view,
                                                       ViewSerializer,
                                                       filters=filters,
                                                       sortings=sortings)
        return Response(serializer.data)
Exemple #20
0
    def get(self, request, view_id, filters, sortings):
        """Selects a single view and responds with a serialized version."""

        view = ViewHandler().get_view(view_id)
        view.table.database.group.has_user(request.user, raise_error=True)
        serializer = view_type_registry.get_serializer(
            view, ViewSerializer, filters=filters, sortings=sortings
        )
        return Response(serializer.data)
Exemple #21
0
    def patch(self, request, data, view_filter_id):
        """Updates the view filter if the user belongs to the group."""

        handler = ViewHandler()
        view_filter = handler.get_filter(request.user, view_filter_id)

        if 'field' in data:
            # We can safely assume the field exists because the
            # UpdateViewFilterSerializer has already checked that.
            data['field'] = Field.objects.get(pk=data['field'])

        if 'type' in data:
            data['type_name'] = data.pop('type')

        view_filter = handler.update_filter(request.user, view_filter, **data)

        serializer = ViewFilterSerializer(view_filter)
        return Response(serializer.data)
Exemple #22
0
    def post(self, request, data, table_id):
        """Creates a new view for a user."""

        table = TableHandler().get_table(request.user, table_id)
        view = ViewHandler().create_view(
            request.user, table, data.pop('type'), **data)

        serializer = view_type_registry.get_serializer(view, ViewSerializer)
        return Response(serializer.data)
Exemple #23
0
    def get(self, request, view_id):
        """
        Responds with a list of serialized sortings that belong to the view if the user
        has access to that group.
        """

        view = ViewHandler().get_view(request.user, view_id)
        sortings = ViewSort.objects.filter(view=view)
        serializer = ViewSortSerializer(sortings, many=True)
        return Response(serializer.data)
Exemple #24
0
    def post(self, request, data, table_id, filters, sortings):
        """Creates a new view for a user."""

        table = TableHandler().get_table(table_id)
        view = ViewHandler().create_view(request.user, table, data.pop("type"), **data)

        serializer = view_type_registry.get_serializer(
            view, ViewSerializer, filters=filters, sortings=sortings
        )
        return Response(serializer.data)
Exemple #25
0
    def get(self, request, view_id):
        """
        Responds with a list of serialized filters that belong to the view if the user
        has access to that group.
        """

        view = ViewHandler().get_view(view_id)
        view.table.database.group.has_user(request.user, raise_error=True)
        filters = ViewFilter.objects.filter(view=view)
        serializer = ViewFilterSerializer(filters, many=True)
        return Response(serializer.data)
Exemple #26
0
def test_views_reordered(mock_broadcast_to_channel_group, data_fixture):
    user = data_fixture.create_user()
    view = data_fixture.create_grid_view(user=user)
    ViewHandler().order_views(user=user, table=view.table, order=[view.id])

    mock_broadcast_to_channel_group.delay.assert_called_once()
    args = mock_broadcast_to_channel_group.delay.call_args
    assert args[0][0] == f"table-{view.table.id}"
    assert args[0][1]["type"] == "views_reordered"
    assert args[0][1]["table_id"] == view.table.id
    assert args[0][1]["order"] == [view.id]
Exemple #27
0
def test_view_sort_updated(mock_broadcast_to_channel_group, data_fixture):
    user = data_fixture.create_user()
    view_sort = data_fixture.create_view_sort(user=user)
    view_sort = ViewHandler().update_sort(user=user, view_sort=view_sort, order="DESC")

    mock_broadcast_to_channel_group.delay.assert_called_once()
    args = mock_broadcast_to_channel_group.delay.call_args
    assert args[0][0] == f"table-{view_sort.view.table.id}"
    assert args[0][1]["type"] == "view_sort_updated"
    assert args[0][1]["view_sort_id"] == view_sort.id
    assert args[0][1]["view_sort"]["id"] == view_sort.id
def test_view_filter_updated(mock_broadcast_to_channel_group, data_fixture):
    user = data_fixture.create_user()
    view_filter = data_fixture.create_view_filter(user=user)
    view_filter = ViewHandler().update_filter(user=user, view_filter=view_filter,
                                              value='test2')

    mock_broadcast_to_channel_group.delay.assert_called_once()
    args = mock_broadcast_to_channel_group.delay.call_args
    assert args[0][0] == f'table-{view_filter.view.table.id}'
    assert args[0][1]['type'] == 'view_filter_updated'
    assert args[0][1]['view_filter_id'] == view_filter.id
    assert args[0][1]['view_filter']['id'] == view_filter.id
def test_view_sort_updated(mock_broadcast_to_channel_group, data_fixture):
    user = data_fixture.create_user()
    view_sort = data_fixture.create_view_sort(user=user)
    view_sort = ViewHandler().update_sort(user=user, view_sort=view_sort,
                                          order='DESC')

    mock_broadcast_to_channel_group.delay.assert_called_once()
    args = mock_broadcast_to_channel_group.delay.call_args
    assert args[0][0] == f'table-{view_sort.view.table.id}'
    assert args[0][1]['type'] == 'view_sort_updated'
    assert args[0][1]['view_sort_id'] == view_sort.id
    assert args[0][1]['view_sort']['id'] == view_sort.id
def test_view_created(mock_broadcast_to_channel_group, data_fixture):
    user = data_fixture.create_user()
    table = data_fixture.create_database_table(user=user)
    view = ViewHandler().create_view(user=user, table=table, type_name='grid',
                                     name='Grid')

    mock_broadcast_to_channel_group.delay.assert_called_once()
    args = mock_broadcast_to_channel_group.delay.call_args
    assert args[0][0] == f'table-{table.id}'
    assert args[0][1]['type'] == 'view_created'
    assert args[0][1]['view']['id'] == view.id
    assert 'filters' in args[0][1]['view']
    assert 'sortings' in args[0][1]['view']