mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-07 14:25:37 +00:00
Final fix for workflow action with collection elements
This commit is contained in:
parent
1172105b93
commit
1a11d5a21c
27 changed files with 203 additions and 143 deletions
backend
src/baserow
contrib
builder
api/workflow_actions
data_providers
data_sources
elements
integrations/local_baserow
core/services
tests/baserow/contrib/builder
web-frontend/modules
builder
core
integrations
|
@ -396,7 +396,6 @@ class DispatchBuilderWorkflowActionView(APIView):
|
|||
dispatch_context = BuilderDispatchContext(
|
||||
request,
|
||||
workflow_action.page,
|
||||
element=workflow_action.element,
|
||||
workflow_action=workflow_action,
|
||||
)
|
||||
|
||||
|
|
|
@ -298,7 +298,9 @@ class CurrentRecordDataProviderType(DataProviderType):
|
|||
"""
|
||||
|
||||
try:
|
||||
current_record = dispatch_context.request.data["current_record"]
|
||||
current_record_data = dispatch_context.request.data["current_record"]
|
||||
current_record = current_record_data["index"]
|
||||
current_record_id = current_record_data["record_id"]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
|
@ -318,8 +320,9 @@ class CurrentRecordDataProviderType(DataProviderType):
|
|||
# Narrow down our range to just our record index.
|
||||
dispatch_context = dispatch_context.from_context(
|
||||
dispatch_context,
|
||||
offset=current_record,
|
||||
offset=0,
|
||||
count=1,
|
||||
only_record_id=current_record_id,
|
||||
)
|
||||
|
||||
return DataSourceDataProviderType().get_data_chunk(
|
||||
|
|
|
@ -33,6 +33,7 @@ class BuilderDispatchContext(DispatchContext):
|
|||
"element",
|
||||
"offset",
|
||||
"count",
|
||||
"only_record_id",
|
||||
"only_expose_public_allowed_properties",
|
||||
]
|
||||
|
||||
|
@ -44,12 +45,29 @@ class BuilderDispatchContext(DispatchContext):
|
|||
element: Optional["Element"] = None,
|
||||
offset: Optional[int] = None,
|
||||
count: Optional[int] = None,
|
||||
only_record_id: Optional[int | str] = None,
|
||||
only_expose_public_allowed_properties: Optional[bool] = True,
|
||||
):
|
||||
"""
|
||||
Dispatch context used in the builder.
|
||||
|
||||
:param request: The HTTP request from the view.
|
||||
:param page: The page related to the dispatch.
|
||||
:param workflow_action: The workflow action being executed, if any.
|
||||
:param element: An optional element that triggered the dispatch.
|
||||
:param offset: When we dispatch a list service, starts by that offset.
|
||||
:param count: When we dispatch a list service returns that max amount of record.
|
||||
:param record_id: If we want to narrow down the results of a list service to
|
||||
only the record with this Id.
|
||||
:param only_expose_public_allowed_properties: Determines whether only public
|
||||
allowed properties should be exposed. Defaults to True.
|
||||
"""
|
||||
|
||||
self.request = request
|
||||
self.page = page
|
||||
self.workflow_action = workflow_action
|
||||
self.element = element
|
||||
self.only_record_id = only_record_id
|
||||
|
||||
# Overrides the `request` GET offset/count values.
|
||||
self.offset = offset
|
||||
|
|
|
@ -517,9 +517,17 @@ class CollectionElementTypeMixin:
|
|||
.items()
|
||||
if any(options.values())
|
||||
]
|
||||
|
||||
if data_source and property_options:
|
||||
properties.setdefault(data_source.service_id, []).extend(property_options)
|
||||
|
||||
# We need the id for the element
|
||||
if data_source and data_source.service_id:
|
||||
service = data_source.service.specific
|
||||
id_property = service.get_type().get_id_property(service)
|
||||
if id_property not in properties.setdefault(service.id, []):
|
||||
properties[service.id].append(id_property)
|
||||
|
||||
return properties
|
||||
|
||||
|
||||
|
|
|
@ -1082,6 +1082,9 @@ class LocalBaserowListRowsUserServiceType(
|
|||
# Ensure that only used fields are fetched from the database.
|
||||
queryset = queryset.only(*available_fields.intersection(only_field_names))
|
||||
|
||||
if dispatch_context.only_record_id is not None:
|
||||
queryset = queryset.filter(id=dispatch_context.only_record_id)
|
||||
|
||||
offset, count = dispatch_context.range(service)
|
||||
|
||||
# We query one more row to be able to know if there is another page that can be
|
||||
|
|
|
@ -10,6 +10,13 @@ from baserow.core.services.utils import ServiceAdhocRefinements
|
|||
class DispatchContext(RuntimeFormulaContext, ABC):
|
||||
own_properties = []
|
||||
|
||||
"""
|
||||
Should return the record id requested for the given service. Used by list
|
||||
services to select only one record. For instance by the builder current record
|
||||
data provider to narrow down the result of a list service.
|
||||
"""
|
||||
only_record_id = None
|
||||
|
||||
def __init__(self):
|
||||
self.cache = {} # can be used by data providers to save queries
|
||||
super().__init__()
|
||||
|
|
|
@ -68,6 +68,29 @@ class ServiceType(
|
|||
# `DISPATCH_WORKFLOW_ACTION` should be chosen.
|
||||
dispatch_type = None
|
||||
|
||||
def get_id_property(self, service: Service) -> str:
|
||||
"""
|
||||
Returns the property name that contains the unique `ID` of a row for this
|
||||
service.
|
||||
|
||||
:param service: the instance of the service.
|
||||
:return: a string identifying the ID property name.
|
||||
"""
|
||||
|
||||
# Sane default
|
||||
return "id"
|
||||
|
||||
def get_name_property(self, service: Service) -> Optional[str]:
|
||||
"""
|
||||
We need the name of the records for some elements (like the record selector).
|
||||
This method returns it depending on the service.
|
||||
|
||||
:param service: the instance of the service.
|
||||
:return: a string identifying the name property name.
|
||||
"""
|
||||
|
||||
return None
|
||||
|
||||
def prepare_values(
|
||||
self,
|
||||
values: Dict[str, Any],
|
||||
|
@ -343,29 +366,6 @@ class ListServiceTypeMixin:
|
|||
|
||||
returns_list = True
|
||||
|
||||
def get_id_property(self, service: Service) -> str:
|
||||
"""
|
||||
Returns the property name that contains the unique `ID` of a row for this
|
||||
service.
|
||||
|
||||
:param service: the instance of the service.
|
||||
:return: a string identifying the ID property name.
|
||||
"""
|
||||
|
||||
# Sane default
|
||||
return "id"
|
||||
|
||||
def get_name_property(self, service: Service) -> Optional[str]:
|
||||
"""
|
||||
We need the name of the records for some elements (like the record selector).
|
||||
This method returns it depending on the service.
|
||||
|
||||
:param service: the instance of the service.
|
||||
:return: a string identifying the name property name.
|
||||
"""
|
||||
|
||||
return None
|
||||
|
||||
@abstractmethod
|
||||
def get_record_names(
|
||||
self,
|
||||
|
|
|
@ -1961,6 +1961,7 @@ def test_dispatch_data_sources_list_rows_with_elements(
|
|||
# Although this Data Source has 2 Fields/Columns, only one is
|
||||
# returned since only one field_id is used by the Table.
|
||||
f"field_{field_id}": getattr(row, f"field_{field_id}"),
|
||||
"id": row.id,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -2043,6 +2044,7 @@ def test_dispatch_data_sources_get_row_with_elements(
|
|||
assert response.json() == {
|
||||
str(data_source.id): {
|
||||
f"field_{field_id}": getattr(rows[db_row_id], f"field_{field_id}"),
|
||||
"id": rows[db_row_id].id,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2148,6 +2150,7 @@ def test_dispatch_data_sources_get_and_list_rows_with_elements(
|
|||
assert response.json() == {
|
||||
str(data_source_1.id): {
|
||||
f"field_{fields_1[0].id}": getattr(rows_1[0], f"field_{fields_1[0].id}"),
|
||||
"id": rows_1[0].id,
|
||||
},
|
||||
# Although this Data Source has 2 Fields/Columns, only one is returned
|
||||
# since only one field_id is used by the Table.
|
||||
|
@ -2158,6 +2161,7 @@ def test_dispatch_data_sources_get_and_list_rows_with_elements(
|
|||
f"field_{fields_2[0].id}": getattr(
|
||||
rows_2[0], f"field_{fields_2[0].id}"
|
||||
),
|
||||
"id": rows_2[0].id,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -251,9 +251,7 @@ def test_dispatch_data_sources_list_rows_with_elements(
|
|||
)
|
||||
|
||||
expected_results = [
|
||||
{
|
||||
f"field_{field_id}": getattr(row, f"field_{field_id}"),
|
||||
}
|
||||
{f"field_{field_id}": getattr(row, f"field_{field_id}"), "id": row.id}
|
||||
for row in data_source_fixture["rows"]
|
||||
]
|
||||
|
||||
|
@ -332,6 +330,7 @@ def test_dispatch_data_sources_get_row_with_elements(
|
|||
assert response.json() == {
|
||||
str(data_source.id): {
|
||||
f"field_{field_id}": getattr(rows[db_row_id], f"field_{field_id}"),
|
||||
"id": rows[db_row_id].id,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,6 +430,7 @@ def test_dispatch_data_sources_get_and_list_rows_with_elements(
|
|||
assert response.json() == {
|
||||
str(data_source_1.id): {
|
||||
f"field_{fields_1[0].id}": getattr(rows_1[0], f"field_{fields_1[0].id}"),
|
||||
"id": rows_1[0].id,
|
||||
},
|
||||
# Although this Data Source has 2 Fields/Columns, only one is returned
|
||||
# since only one field_id is used by the Table.
|
||||
|
@ -441,6 +441,7 @@ def test_dispatch_data_sources_get_and_list_rows_with_elements(
|
|||
f"field_{fields_2[0].id}": getattr(
|
||||
rows_2[0], f"field_{fields_2[0].id}"
|
||||
),
|
||||
"id": rows_2[0].id,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -537,7 +538,9 @@ def test_dispatch_data_sources_list_rows_with_elements_and_role(
|
|||
# Field should only be visible if the user's role allows them
|
||||
# to see the data source fields.
|
||||
|
||||
expected_results.append({field_name: getattr(row, field_name)})
|
||||
expected_results.append(
|
||||
{field_name: getattr(row, field_name), "id": row.id}
|
||||
)
|
||||
else:
|
||||
expected_results.append({})
|
||||
|
||||
|
|
|
@ -857,10 +857,12 @@ def test_public_dispatch_data_source_view_returns_all_fields(
|
|||
"has_next_page": False,
|
||||
"results": [
|
||||
{
|
||||
"id": rows[0].id,
|
||||
f"field_{fields[0].id}": "Paneer Tikka",
|
||||
f"field_{fields[1].id}": "5",
|
||||
},
|
||||
{
|
||||
"id": rows[1].id,
|
||||
f"field_{fields[0].id}": "Gobi Manchurian",
|
||||
f"field_{fields[1].id}": "8",
|
||||
},
|
||||
|
@ -1134,7 +1136,7 @@ def test_public_dispatch_data_sources_list_rows_with_elements_and_role(
|
|||
|
||||
expected_results = []
|
||||
for row in data_source_element_roles_fixture["rows"]:
|
||||
result = {}
|
||||
result = {"id": row.id}
|
||||
if expect_fields:
|
||||
# Field should only be visible if the user's role allows them
|
||||
# to see the data source fields.
|
||||
|
@ -1318,15 +1320,17 @@ def test_public_dispatch_data_sources_list_rows_with_page_visibility_all(
|
|||
|
||||
assert response.status_code == HTTP_200_OK
|
||||
|
||||
rows = data_source_element_roles_fixture["rows"]
|
||||
|
||||
if expect_fields:
|
||||
field_name = f"field_{field_id}"
|
||||
assert response.json() == {
|
||||
str(data_source.id): {
|
||||
"has_next_page": False,
|
||||
"results": [
|
||||
{field_name: "Apple"},
|
||||
{field_name: "Banana"},
|
||||
{field_name: "Cherry"},
|
||||
{field_name: "Apple", "id": rows[0].id},
|
||||
{field_name: "Banana", "id": rows[1].id},
|
||||
{field_name: "Cherry", "id": rows[2].id},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
@ -1632,15 +1636,17 @@ def test_public_dispatch_data_sources_list_rows_with_page_visibility_logged_in(
|
|||
|
||||
assert response.status_code == HTTP_200_OK
|
||||
|
||||
rows = data_source_element_roles_fixture["rows"]
|
||||
|
||||
if expect_fields:
|
||||
field_name = f"field_{field_id}"
|
||||
assert response.json() == {
|
||||
str(data_source.id): {
|
||||
"has_next_page": False,
|
||||
"results": [
|
||||
{field_name: "Apple"},
|
||||
{field_name: "Banana"},
|
||||
{field_name: "Cherry"},
|
||||
{field_name: "Apple", "id": rows[0].id},
|
||||
{field_name: "Banana", "id": rows[1].id},
|
||||
{field_name: "Cherry", "id": rows[2].id},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.db import transaction
|
||||
|
@ -677,7 +676,7 @@ def test_dispatch_local_baserow_upsert_row_workflow_action_with_current_record(
|
|||
}
|
||||
response = api_client.post(
|
||||
url,
|
||||
{"current_record": 123},
|
||||
{"current_record": {"index": 123, "record_id": 123}},
|
||||
format="json",
|
||||
HTTP_AUTHORIZATION=f"JWT {token}",
|
||||
)
|
||||
|
@ -689,7 +688,7 @@ def test_dispatch_local_baserow_upsert_row_workflow_action_with_current_record(
|
|||
|
||||
|
||||
@pytest.mark.django_db(transaction=True)
|
||||
def test_dispatch_local_baserow_upsert_row_workflow_action_with_adhoc_refinements(
|
||||
def test_dispatch_local_baserow_upsert_row_workflow_action_with_unmatching_index_and_record_id(
|
||||
api_client, data_fixture
|
||||
):
|
||||
with transaction.atomic():
|
||||
|
@ -705,7 +704,7 @@ def test_dispatch_local_baserow_upsert_row_workflow_action_with_adhoc_refinement
|
|||
],
|
||||
)
|
||||
field = table.field_set.get()
|
||||
RowHandler().create_rows(
|
||||
rows = RowHandler().create_rows(
|
||||
user,
|
||||
table,
|
||||
rows_values=[
|
||||
|
@ -766,17 +765,6 @@ def test_dispatch_local_baserow_upsert_row_workflow_action_with_adhoc_refinement
|
|||
kwargs={"workflow_action_id": workflow_action.id},
|
||||
)
|
||||
|
||||
advanced_filters = {
|
||||
"filter_type": "OR",
|
||||
"filters": [
|
||||
{
|
||||
"field": field.id,
|
||||
"type": "contains",
|
||||
"value": "construction",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
with patch(
|
||||
"baserow.contrib.builder.handler.get_builder_used_property_names"
|
||||
) as used_properties_mock:
|
||||
|
@ -786,36 +774,34 @@ def test_dispatch_local_baserow_upsert_row_workflow_action_with_adhoc_refinement
|
|||
}
|
||||
model = table.get_model()
|
||||
|
||||
# 1. The filters reduce it to 3 results.
|
||||
# 2. The search query reduces it to 2 results.
|
||||
# 3. We sort alphabetically, and dispatch the first one,
|
||||
# "Complex Construction Design".
|
||||
url_with_querystring = (
|
||||
f"{url}?filters={json.dumps(advanced_filters)}"
|
||||
f"&search_query=design&order_by={field.db_column}"
|
||||
)
|
||||
|
||||
# Dispatch at index=0, this will be "Complex Construction Design".
|
||||
# Dispatch at index=0 but row 3 id, this will be "Complex Construction Design".
|
||||
response = api_client.post(
|
||||
url_with_querystring,
|
||||
{"current_record": 0, "data_source": {"element": table_element.id}},
|
||||
url,
|
||||
{
|
||||
"current_record": {"index": 0, "record_id": rows[2].id},
|
||||
"data_source": {"element": table_element.id},
|
||||
},
|
||||
format="json",
|
||||
HTTP_AUTHORIZATION=f"JWT {token}",
|
||||
)
|
||||
assert response.status_code == HTTP_200_OK
|
||||
row3 = model.objects.get(pk=3)
|
||||
assert getattr(row3, f"field_{field.id}") == "Updated row 3"
|
||||
row3 = model.objects.get(pk=rows[2].id)
|
||||
assert getattr(row3, f"field_{field.id}") == f"Updated row {rows[2].id}"
|
||||
|
||||
# Dispatch at index=0, this will now be "Simple Construction Design".
|
||||
# Dispatch at index=0 but row 4 id,
|
||||
# this will now be "Simple Construction Design".
|
||||
response = api_client.post(
|
||||
url_with_querystring,
|
||||
{"current_record": 0, "data_source": {"element": table_element.id}},
|
||||
url,
|
||||
{
|
||||
"current_record": {"index": 0, "record_id": rows[3].id},
|
||||
"data_source": {"element": table_element.id},
|
||||
},
|
||||
format="json",
|
||||
HTTP_AUTHORIZATION=f"JWT {token}",
|
||||
)
|
||||
assert response.status_code == HTTP_200_OK
|
||||
row4 = model.objects.get(pk=4)
|
||||
assert getattr(row4, f"field_{field.id}") == "Updated row 4"
|
||||
row4 = model.objects.get(pk=rows[3].id)
|
||||
assert getattr(row4, f"field_{field.id}") == f"Updated row {rows[3].id}"
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
|
|
@ -1208,21 +1208,15 @@ def test_current_record_provider_get_data_chunk_without_record_index(data_fixtur
|
|||
def test_current_record_provider_get_data_chunk_for_idx():
|
||||
current_record_provider = CurrentRecordDataProviderType()
|
||||
fake_request = HttpRequest()
|
||||
fake_request.data = {"current_record": 123}
|
||||
fake_request.data = {"current_record": {"index": 123, "record_id": 123}}
|
||||
dispatch_context = BuilderDispatchContext(fake_request, None)
|
||||
assert current_record_provider.get_data_chunk(dispatch_context, ["__idx__"]) == 123
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_current_record_provider_get_data_chunk(data_fixture):
|
||||
current_record_provider = CurrentRecordDataProviderType()
|
||||
|
||||
user, token = data_fixture.create_user_and_token()
|
||||
|
||||
fake_request = HttpRequest()
|
||||
fake_request.user = user
|
||||
fake_request.data = {"current_record": 0}
|
||||
|
||||
table, fields, rows = data_fixture.build_table(
|
||||
user=user,
|
||||
columns=[
|
||||
|
@ -1252,10 +1246,16 @@ def test_current_record_provider_get_data_chunk(data_fixture):
|
|||
page=page, element=button_element, event=EventTypes.CLICK, user=user
|
||||
)
|
||||
|
||||
fake_request = HttpRequest()
|
||||
fake_request.user = user
|
||||
fake_request.data = {"current_record": {"index": 0, "record_id": rows[0].id}}
|
||||
|
||||
dispatch_context = BuilderDispatchContext(
|
||||
fake_request, page, workflow_action, only_expose_public_allowed_properties=False
|
||||
)
|
||||
|
||||
current_record_provider = CurrentRecordDataProviderType()
|
||||
|
||||
assert (
|
||||
current_record_provider.get_data_chunk(dispatch_context, [field.db_column])
|
||||
== "Badger"
|
||||
|
|
|
@ -208,7 +208,7 @@ def test_extract_properties_includes_schema_property_for_nested_collection(
|
|||
)
|
||||
|
||||
properties = RepeatElementType().extract_properties(parent_repeat)
|
||||
assert properties == {}
|
||||
assert properties == {data_source.service_id: ["id"]}
|
||||
|
||||
# Create a child Repeat with a schema_property
|
||||
child_repeat = data_fixture.create_builder_repeat_element(
|
||||
|
@ -223,8 +223,10 @@ def test_extract_properties_includes_schema_property_for_nested_collection(
|
|||
|
||||
properties = RepeatElementType().extract_properties(child_repeat, **formula_context)
|
||||
|
||||
# We expect that the schema_property field ID to be present
|
||||
assert properties == {data_source.service_id: [f"field_{multiple_select_field.id}"]}
|
||||
# We expect that the schema_property field to be present and the ID
|
||||
assert properties == {
|
||||
data_source.service_id: [f"field_{multiple_select_field.id}", "id"]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
@ -283,4 +285,6 @@ def test_extract_properties_includes_schema_property_for_single_row(
|
|||
)
|
||||
|
||||
properties = RepeatElementType().extract_properties(repeat)
|
||||
assert properties == {data_source.service_id: [f"field_{multiple_select_field.id}"]}
|
||||
assert properties == {
|
||||
data_source.service_id: [f"field_{multiple_select_field.id}", "id"]
|
||||
}
|
||||
|
|
|
@ -110,10 +110,10 @@ def test_get_builder_used_property_names_returns_all_property_names(data_fixture
|
|||
|
||||
assert list(results) == unordered(["all", "external", "internal"])
|
||||
assert results["all"][data_source.service_id] == unordered(
|
||||
[f"field_{field.id}" for field in fields]
|
||||
[f"field_{field.id}" for field in fields] + ["id"]
|
||||
)
|
||||
assert results["external"][data_source.service_id] == unordered(
|
||||
[f"field_{field.id}" for field in fields]
|
||||
[f"field_{field.id}" for field in fields] + ["id"]
|
||||
)
|
||||
assert results["internal"] == {}
|
||||
|
||||
|
@ -169,10 +169,10 @@ def test_get_builder_used_property_names_returns_some_property_names(data_fixtur
|
|||
# only one property, ensure that specific property is the only one returned.
|
||||
assert results == {
|
||||
"all": {
|
||||
data_source.service_id: [f"field_{fields[0].id}"],
|
||||
data_source.service_id: [f"field_{fields[0].id}", "id"],
|
||||
},
|
||||
"external": {
|
||||
data_source.service_id: [f"field_{fields[0].id}"],
|
||||
data_source.service_id: [f"field_{fields[0].id}", "id"],
|
||||
},
|
||||
"internal": {},
|
||||
}
|
||||
|
@ -997,6 +997,7 @@ def test_get_builder_used_property_names_returns_merged_property_names_integrati
|
|||
"all": {
|
||||
data_source.service_id: sorted(
|
||||
[
|
||||
"id",
|
||||
f"field_{fields[0].id}",
|
||||
f"field_{fields[2].id}",
|
||||
]
|
||||
|
@ -1019,6 +1020,7 @@ def test_get_builder_used_property_names_returns_merged_property_names_integrati
|
|||
"external": {
|
||||
data_source.service_id: [
|
||||
f"field_{fields[0].id}", # From heading_element_1
|
||||
"id",
|
||||
],
|
||||
data_source_2.service_id: [
|
||||
f"field_{fields[2].id}"
|
||||
|
|
|
@ -10,12 +10,13 @@
|
|||
<slot name="field-name" :field="field">{{ field.name }}</slot>
|
||||
</th>
|
||||
</template>
|
||||
<template #cell-content="{ rowIndex, value, field }">
|
||||
<template #cell-content="{ rowIndex, value, field, row }">
|
||||
<slot
|
||||
name="cell-content"
|
||||
:value="value"
|
||||
:field="field"
|
||||
:row-index="rowIndex"
|
||||
:row="row"
|
||||
>
|
||||
<td :key="field.id" class="ab-table__cell">
|
||||
<div class="ab-table__cell-content">
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
:value="row[field.name]"
|
||||
:field="field"
|
||||
:row-index="index"
|
||||
:row="row"
|
||||
>
|
||||
<td :key="field.id" class="baserow-table__cell">
|
||||
{{ row[field.name] }}
|
||||
|
@ -55,6 +56,7 @@
|
|||
:value="row[field.name]"
|
||||
:field="field"
|
||||
:row-index="rowIndex"
|
||||
:row="row"
|
||||
>
|
||||
<td
|
||||
class="baserow-table__cell"
|
||||
|
|
|
@ -28,12 +28,13 @@
|
|||
v-if="index === 0 && isEditMode"
|
||||
:key="`${child.id}-${index}`"
|
||||
:element="child"
|
||||
:application-context-additions="{
|
||||
recordIndexPath: [
|
||||
...applicationContext.recordIndexPath,
|
||||
index,
|
||||
],
|
||||
}"
|
||||
:application-context-additions="
|
||||
getPerRecordApplicationContextAddition({
|
||||
applicationContext,
|
||||
row: content,
|
||||
rowIndex: index,
|
||||
})
|
||||
"
|
||||
@move="$emit('move', $event)"
|
||||
/>
|
||||
<!-- Other iterations are not editable -->
|
||||
|
@ -44,12 +45,13 @@
|
|||
:key="`${child.id}_${index}`"
|
||||
:element="child"
|
||||
:force-mode="isEditMode ? 'public' : mode"
|
||||
:application-context-additions="{
|
||||
recordIndexPath: [
|
||||
...applicationContext.recordIndexPath,
|
||||
index,
|
||||
],
|
||||
}"
|
||||
:application-context-additions="
|
||||
getPerRecordApplicationContextAddition({
|
||||
applicationContext,
|
||||
row: content,
|
||||
rowIndex: index,
|
||||
})
|
||||
"
|
||||
:class="{
|
||||
'repeat-element__preview': index > 0 && isEditMode,
|
||||
}"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
:style="getStyleOverride('table')"
|
||||
:orientation="orientation"
|
||||
>
|
||||
<template #cell-content="{ rowIndex, field, value }">
|
||||
<template #cell-content="{ rowIndex, field, value, row }">
|
||||
<!--
|
||||
-- We force-self-alignment to `auto` here to prevent some self-positioning
|
||||
-- like in buttons or links. we want to position the content through the table
|
||||
|
@ -34,14 +34,14 @@
|
|||
:is="collectionFieldTypes[field.type].component"
|
||||
:element="element"
|
||||
:field="field"
|
||||
:application-context-additions="{
|
||||
recordIndexPath: [
|
||||
...applicationContext.recordIndexPath,
|
||||
:application-context-additions="
|
||||
getPerRecordApplicationContextAddition({
|
||||
applicationContext,
|
||||
row,
|
||||
rowIndex,
|
||||
],
|
||||
field,
|
||||
dispatchRefinements: adhocRefinements,
|
||||
}"
|
||||
field,
|
||||
})
|
||||
"
|
||||
v-bind="value"
|
||||
/>
|
||||
</div>
|
||||
|
@ -117,6 +117,7 @@ export default {
|
|||
})
|
||||
)
|
||||
newRow.__id__ = uuid()
|
||||
newRow.__recordId__ = row.__recordId__
|
||||
return newRow
|
||||
})
|
||||
},
|
||||
|
|
|
@ -384,7 +384,10 @@ export class CurrentRecordDataProviderType extends DataProviderType {
|
|||
}
|
||||
|
||||
getActionDispatchContext(applicationContext) {
|
||||
return applicationContext.recordIndexPath.at(-1)
|
||||
return {
|
||||
record_id: applicationContext.recordId,
|
||||
index: applicationContext.recordIndexPath.at(-1),
|
||||
}
|
||||
}
|
||||
|
||||
getDataChunk(applicationContext, path) {
|
||||
|
|
|
@ -64,19 +64,6 @@ export class Event {
|
|||
)
|
||||
}
|
||||
|
||||
// If we're firing a workflow action, and the collection element it's associated
|
||||
// with is currently being filtered, we must forward this on to the workflow
|
||||
// action dispatch so that the backend fires at the correct current_record.
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
applicationContext,
|
||||
'dispatchRefinements'
|
||||
)
|
||||
) {
|
||||
workflowActionContext.dispatchRefinements =
|
||||
applicationContext.dispatchRefinements
|
||||
}
|
||||
|
||||
const localResolveFormula = (formula) => {
|
||||
const formulaFunctions = {
|
||||
get: (name) => {
|
||||
|
|
|
@ -176,5 +176,22 @@ export default {
|
|||
this.contentFetchEnabled = false
|
||||
}
|
||||
},
|
||||
getPerRecordApplicationContextAddition({
|
||||
applicationContext,
|
||||
row,
|
||||
rowIndex,
|
||||
field = null,
|
||||
}) {
|
||||
const newApplicationContext = {
|
||||
recordIndexPath: [...applicationContext.recordIndexPath, rowIndex],
|
||||
}
|
||||
if (field) {
|
||||
newApplicationContext.field = field
|
||||
}
|
||||
if (this.element.data_source_id) {
|
||||
newApplicationContext.recordId = row.__recordId__
|
||||
}
|
||||
return newApplicationContext
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { prepareDispatchParams } from '@baserow/modules/builder/utils/params'
|
||||
|
||||
export default (client) => {
|
||||
return {
|
||||
create(pageId, workflowActionType, eventType, configuration = null) {
|
||||
|
@ -35,12 +33,10 @@ export default (client) => {
|
|||
payload
|
||||
)
|
||||
},
|
||||
dispatch(workflowActionId, data, dispatchRefinements) {
|
||||
const params = prepareDispatchParams(dispatchRefinements)
|
||||
dispatch(workflowActionId, data) {
|
||||
return client.post(
|
||||
`builder/workflow_action/${workflowActionId}/dispatch/`,
|
||||
data,
|
||||
{ params }
|
||||
data
|
||||
)
|
||||
},
|
||||
}
|
||||
|
|
|
@ -246,7 +246,10 @@ const actions = {
|
|||
// using the results key and set the range for future paging.
|
||||
commit('SET_CONTENT', {
|
||||
element,
|
||||
value: data.results,
|
||||
value: data.results.map((row) => ({
|
||||
...row,
|
||||
__recordId__: row[serviceType.getIdProperty(service, row)],
|
||||
})),
|
||||
range,
|
||||
})
|
||||
} else {
|
||||
|
|
|
@ -200,15 +200,10 @@ const actions = {
|
|||
updateContext.promiseResolve = resolve
|
||||
})
|
||||
},
|
||||
async dispatchAction(
|
||||
{ dispatch },
|
||||
{ workflowActionId, workflowActionContext, data }
|
||||
) {
|
||||
const { dispatchRefinements = {} } = workflowActionContext
|
||||
async dispatchAction({ dispatch }, { workflowActionId, data }) {
|
||||
const { data: result } = await WorkflowActionService(this.$client).dispatch(
|
||||
workflowActionId,
|
||||
data,
|
||||
dispatchRefinements
|
||||
data
|
||||
)
|
||||
return result
|
||||
},
|
||||
|
|
|
@ -180,10 +180,8 @@ export class RefreshDataSourceWorkflowActionType extends WorkflowActionType {
|
|||
|
||||
export class WorkflowActionServiceType extends WorkflowActionType {
|
||||
execute({ workflowAction: { id }, applicationContext, resolveFormula }) {
|
||||
const { workflowActionContext } = applicationContext
|
||||
return this.app.store.dispatch('workflowAction/dispatchAction', {
|
||||
workflowActionId: id,
|
||||
workflowActionContext,
|
||||
data: DataProviderType.getAllActionDispatchContext(
|
||||
this.app.$registry.getAll('builderDataProvider'),
|
||||
applicationContext
|
||||
|
|
|
@ -35,6 +35,22 @@ export class ServiceType extends Registerable {
|
|||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* In a service which returns a list, this method is used to
|
||||
* return the name of the given record.
|
||||
*/
|
||||
getRecordName(service, record) {
|
||||
throw new Error('Must be set on the type.')
|
||||
}
|
||||
|
||||
/**
|
||||
* In a service which returns a list, this method is used to
|
||||
* return the id of the given record.
|
||||
*/
|
||||
getIdProperty(service, record) {
|
||||
throw new Error('Must be set on the type.')
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of records that can be returned by this service
|
||||
*/
|
||||
|
|
|
@ -38,12 +38,8 @@ export class LocalBaserowTableServiceType extends ServiceType {
|
|||
return service.context_data_schema
|
||||
}
|
||||
|
||||
/**
|
||||
* In a Local Baserow service which returns a list, this method is used to
|
||||
* return the name of the given record.
|
||||
*/
|
||||
getRecordName(service, record) {
|
||||
return ''
|
||||
getIdProperty(service, record) {
|
||||
return 'id'
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue