Commit Graph

1035 Commits

Author SHA1 Message Date
4eefa45164 Option-menu-switch-table-kanban (#11167)
New options menu feature: table/kanban switching

This feature is the last one of the Optino Menu v2 update. It is
designed to enable the possibility to switch from table to kanban and
vice-versa.

Only the default tab is not editable for consitency in the UX of the
application as designed by our team

---------

Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
2025-03-27 16:49:44 +01:00
937a393d74 Fix missing positionInRecordFilterGroup in applyFilter legacy logic (#11230)
This PR fixes a bug where modifying a filter in the advanced filter
dropdown was making it change its position in the filter list.

This is due to the legacy logic of applyFilter(), which outlines the
importance of the needed refactor to remove this logic which requires
duplicating code modification in nearly every component that can modify
a record filter.

This refactor will be addressed over the next sprints, because there are
underlying sub-refactors to tackle first, as outlined by
https://github.com/twentyhq/core-team-issues/issues/559
2025-03-27 16:40:30 +01:00
645d76fe69 Removing advanced filter feature flag (#11219)
This PR removes the advanced filter feature flag.
2025-03-27 15:25:07 +01:00
2cc59929b8 Fixed the 'Extra space on GroupBy option menu' (#11179)
#10969 

Fixed!


![image](https://github.com/user-attachments/assets/4784891c-2c49-4098-8d1b-a8b52fdec1f6)

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-03-26 22:59:52 +01:00
b3948d2406 Add selected number to title (#11200)
Fixes https://github.com/twentyhq/core-team-issues/issues/586

<img width="633" alt="Capture d’écran 2025-03-26 à 17 37 10"
src="https://github.com/user-attachments/assets/2215aa95-1f74-4634-b76e-2b9322230fe8"
/>
2025-03-26 18:03:42 +01:00
8cc9f77417 Advanced filters bug bash (#11178) 2025-03-26 11:06:53 +01:00
3e7ec4f756 Allow empty string for primary link (#11171)
Fixes https://github.com/twentyhq/twenty/issues/11166



https://github.com/user-attachments/assets/72208ac9-c19d-4c19-b305-40d6318310ed
2025-03-25 18:17:38 +01:00
b24046b1bb Various design fixes on side panel (#11165)
- Fix background color
- Fix Menu Item height
- Fix Input design
- Fix show page summary card design
2025-03-25 15:21:10 +00:00
877d6e9304 Option-menu-v2-input (#11116)
Adding the possibility to change the view name and incon from the
Options menu dropdown

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2025-03-25 15:13:13 +01:00
f3f4dd7648 Fix record page title focus (#11145)
Fix record page title focus when creating a new record.

Before:


https://github.com/user-attachments/assets/3f032873-ef5b-4799-a6b7-6459674e4347


After:


https://github.com/user-attachments/assets/7ca4107d-cea8-477d-9e6a-2b74c3121a13
2025-03-25 11:54:29 +01:00
de1f8a4706 Fix created by filter dropdown that appears on other filter types. (#11126)
Fixes https://github.com/twentyhq/twenty/issues/11077

This PR fixes a bug where the actor source filter dropdown input was
showing on other field types filter dropdown input.

It just adds a check to show this particular actor source filter
dropdown input only if the field type is ACTOR.

Sub field name reset and lifecycle will be handled in the incoming work
on sub field filtering.
2025-03-25 11:26:39 +01:00
4680bc740a [permissions V2] Upsert object and setting permissions (#11119)
Closes https://github.com/twentyhq/core-team-issues/issues/639
2025-03-25 11:07:51 +01:00
6898a40ac3 Fix relation from many notes (#11120)
Fixes https://github.com/twentyhq/twenty/issues/3415
2025-03-24 15:19:05 +01:00
e83e7b3b40 Fix bug and refactored advanced filter field selection dropdown (#11103)
This PR is a first step towards isolating each filter dropdown use case,
here we isolate advanced filter field selection dropdown from view bar
filter field selection dropdown.

## Isolation of advanced filter field selection logic

We reimplement the previously generic logic into
AdvancedFilterFieldSelectMenu and AdvancedFilterSubFieldSelectMenu
components.

For now it contains duplicated code but, the end goal is to factorize
what's common to all object filter dropdowns in small hooks where
possible, at the end of the code path isolation first step, which will
be done for applyFilter and selectFilter logic that will be able to be
deleted after code path isolation.

A new component ObjectFilterDropdownFilterSelectMenuItemV2 has been
created to expose an onClick method instead of computing logic that
tries to guess where it is located, which allows to verticalize what
happens when we select a field in each specific use case, one layer
above.

Created the hook useSelectFieldUsedInAdvancedFilterDropdown which
contains the logic for field selection for advanced filter field select
dropdown specific use case, the first example of a good verticalized and
unique place to handle field selection in the context of advanced
filter.

The naming useAdvancedFilterDropdown was lying and is now
useAdvancedFilterFieldSelectDropdown which is now self-explanatory.

useAdvancedFilterFieldSelectDropdown has been removed from the main
object filter dropdown, thus isolating advanced filters field select
dropdown from the generic object filter field select dropdown.

## Miscellaneous

Removed states that were used in the generic filter dropdown to guess
whether it was in advanced filter context or not.
2025-03-24 15:18:53 +01:00
1c5f3ef5fa clean searchResolvers in server (#11114)
Introduces break in change

- remove search... resolvers
- rename globalSearch to search
- rename searchRecord.objectSingularName > objectNameSingular
closes https://github.com/twentyhq/core-team-issues/issues/643
2025-03-24 13:42:51 +01:00
6e7d2db58f Fix From Many relation for deleted notes crashing (#11117)
In this PR, I'm: 
- fixing the root cause (we should not try to render a RecordChip if the
record is not defined in RelationFromMany Display)
- fixing related typing issues
- we won't be able to catch the issue from TS perspective as
ObjectRecord is a Record of string, any
2025-03-24 13:29:44 +01:00
9ad8287dbc [REFACTOR] twenty-shared multi barrel and CJS/ESM build with preconstruct (#11083)
# Introduction

In this PR we've migrated `twenty-shared` from a `vite` app
[libary-mode](https://vite.dev/guide/build#library-mode) to a
[preconstruct](https://preconstruct.tools/) "atomic" application ( in
the future would like to introduce preconstruct to handle of all our
atomic dependencies such as `twenty-emails` `twenty-ui` etc it will be
integrated at the monorepo's root directly, would be to invasive in the
first, starting incremental via `twenty-shared`)

For more information regarding the motivations please refer to nor:
- https://github.com/twentyhq/core-team-issues/issues/587
-
https://github.com/twentyhq/core-team-issues/issues/281#issuecomment-2630949682

close https://github.com/twentyhq/core-team-issues/issues/589
close https://github.com/twentyhq/core-team-issues/issues/590

## How to test
In order to ease the review this PR will ship all the codegen at the
very end, the actual meaning full diff is `+2,411 −114`
In order to migrate existing dependent packages to `twenty-shared` multi
barrel new arch you need to run in local:
```sh
yarn tsx packages/twenty-shared/scripts/migrateFromSingleToMultiBarrelImport.ts && \
npx nx run-many -t lint --fix -p twenty-front twenty-ui twenty-server twenty-emails twenty-shared twenty-zapier
```
Note that `migrateFromSingleToMultiBarrelImport` is idempotent, it's atm
included in the PR but should not be merged. ( such as codegen will be
added before merging this script will be removed )

## Misc
- related opened issue preconstruct
https://github.com/preconstruct/preconstruct/issues/617

## Closed related PR
- https://github.com/twentyhq/twenty/pull/11028
- https://github.com/twentyhq/twenty/pull/10993
- https://github.com/twentyhq/twenty/pull/10960

## Upcoming enhancement: ( in others dedicated PRs )
- 1/ refactor generate barrel to export atomic module instead of `*`
- 2/ generate barrel own package with several files and tests
- 3/ Migration twenty-ui the same way
- 4/ Use `preconstruct` at monorepo global level

## Conclusion
As always any suggestions are welcomed !
2025-03-22 19:16:06 +01:00
8a21c19f03 Fix missing record field component instanceId 2025-03-22 18:52:57 +01:00
ccf60284cf Various fixes (#11108)
Fixes many bug regarding TableCell and InlineCells
2025-03-22 14:19:10 +01:00
c50cdd9510 Execute workflow form action (#11099)
- create a form filler component
- send the response on submit
- put back a field name. We need it for the step output
- validate a form is well set before activation

TODO:
- we need to refresh to see the form submitted. We need to discuss about
a strategy
- the response is not saved in the step settings. We need a new endpoint
to update workflow run step



https://github.com/user-attachments/assets/0f34a6cd-ed8c-4d9a-a1d4-51455cc83443
2025-03-21 17:38:14 +00:00
e624e8deee replace search resolvers by global search in front (#11086)
Done
- Replace global search in multi record picker and single record picker

To do
- refactor SingleRecordPicker to match MultipleRecordPicker - next 1:1
- items in this issue
https://github.com/twentyhq/core-team-issues/issues/643



closes https://github.com/twentyhq/core-team-issues/issues/535
2025-03-21 17:25:00 +01:00
081f5fa766 Sort menu Incorrect padding bottom #11078 (#11091)
##  Issue
- Closes #11078
- **visual regression** from PR - #9159 that likely might have break
visuals in several other places.
2025-03-21 16:29:30 +01:00
6a412a531f Remove useless skelettonLoader (#11096)
## After

![image](https://github.com/user-attachments/assets/772e9a8c-5df2-4bfd-95ea-5854022e82e0)
<img width="825" alt="Capture d’écran 2025-03-21 à 15 43 14"
src="https://github.com/user-attachments/assets/87818683-9cb0-4264-a6c3-f0420b0ae34d"
/>
2025-03-21 16:19:45 +01:00
c961d3a60d Reorganized components in advanced filter dropdown (#11089)
This PR essentially focuses on a refactor of the component hierarchy and
naming in advanced filter dropdown, to make it more readable and easy to
maintain.

This refactor was required because this area of the code is recursive,
so it's better to see the same abstract components in the recursion,
instead of trying to guess whether we have the same components than the
level above or not.

Also keep in mind that this refactor is meant to separate the advanced
filter code path from the view bar simple filter code path, while
reusing what's reusable, so here we have a first attempt at finding the
sweet spot, that we'll be able to duplicate on other filter dropdown use
cases.

- We now use AdvancedFilterRecordFilterGroupRow and
AdvancedFilterRecordFilterRow to make it clearer in the advanced filter
dropdown recursion where we are.
- Children component of AdvancedFilterRecordFilterRow have been
abstracted at the same level to make reading easier
- The field selection dropdown is now in a self-explanatory component
that follows the same naming pattern as other dropdowns in the app :
AdvancedFilterFieldSelectDrodownButton, together with
AdvancedFilterFieldSelectDrodownContent.
- The field selection search in the filter dropdown is now a standalone
component : AdvancedFilterFieldSelectSearchInput
- The UI container of a row has been abstracted in a new
AdvancedFilterDropdownRow

Miscellaneous : 
- Renamed a bunch of view filter old naming to record filter naming.
2025-03-21 16:19:19 +01:00
d7dabe5826 Update timeline empty state in the side panel (#11093)
Fixes https://github.com/twentyhq/twenty/issues/10914

Before:


https://github.com/user-attachments/assets/83764543-06bf-455e-8b07-fa2822691005


After:


https://github.com/user-attachments/assets/09afa15d-6352-4024-a6b9-2cccf5991d8a
2025-03-21 15:30:14 +01:00
99438a810c Error invalid link (#10288)
Don't have access to push on
https://github.com/twentyhq/twenty/pull/9942, so close it and open new
PR here

<img width="244" alt="Screenshot 2025-02-18 at 11 09 39"
src="https://github.com/user-attachments/assets/4bc1b436-147a-4d17-88c8-2aff0fffd06a"
/>
<img width="246" alt="Screenshot 2025-02-18 at 11 09 51"
src="https://github.com/user-attachments/assets/3d7b2972-ab7e-4e3b-a177-658325a3bb70"
/>

Ok for RecordInlineCell / RecordTableCell and EmailsFieldInput /
LinksFieldInput.
I think it's too complex for a so small issue (agree with you khuddite)

closes https://github.com/twentyhq/twenty/issues/9778
on top of https://github.com/twentyhq/twenty/pull/9942 from @khuddite

---------

Co-authored-by: khuddite <khuddite@gmail.com>
Co-authored-by: khuddite <62555977+khuddite@users.noreply.github.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
2025-03-21 10:18:55 +01:00
872c0e97f6 [BUGFIX] GenerateDefaultRecordChipData returns RecordChipData (#11071)
# Introduction
closes https://github.com/twentyhq/twenty/issues/11030, might not fix
the issue as it seems to be related to the passed record to
`identifierChipGeneratorPerObject` about to dig deeper in this generator
code => found nothing revelant doubled check each `RecordChip`
invocation that could provide undefined record
Fixed wrong default generated `RecordChipData` signature

## Reproducibility
I've only been able to reproduce the bug in production using the very
same opportunity than within the issue, but not all the time

https://crm.twenty-internal.com/objects/opportunities?viewId=b709d3d1-2dd2-455d-ba73-784f3ab00883
```json
// Removed timelineActivities to prevent linking ids
{
  "data": {
    "opportunity": {
      "__typename": "Opportunity",
      "closeDate": null,
      "company": null,
      "companyId": null,
      "createdAt": "2024-06-17T09:45:22.357Z",
      "deletedAt": null,
      "id": "006a22dd-6bd6-4247-a24b-42fb164cd48c",
      "name": "test",
      "pointOfContact": null,
      "pointOfContactId": null,
      "position": 0,
      "probability": "0",
      "stage": "NEW_STAGE",
      "updatedAt": "2025-03-20T16:27:51.927Z",
      "amount": {
        "__typename": "Currency",
        "amountMicros": null,
        "currencyCode": "USD"
      },
      "attachments": {
        "__typename": "AttachmentConnection",
        "edges": []
      },
      "createdBy": {
        "__typename": "Actor",
        "source": "MANUAL",
        "workspaceMemberId": null,
        "name": "",
        "context": {}
      },
      "favorites": {
        "__typename": "FavoriteConnection",
        "edges": []
      },
      "taskTargets": {
        "__typename": "TaskTargetConnection",
        "edges": []
      },
      "noteTargets": {
        "__typename": "NoteTargetConnection",
        "edges": [
          {
            "__typename": "NoteTargetEdge",
            "node": {
              "__typename": "NoteTarget",
              "appEventId": null,
              "companyId": null,
              "createdAt": "2025-01-22T17:11:07.801Z",
              "deletedAt": null,
              "feedbackId": null,
              "id": "2e8eca1c-e2c2-425a-93fc-ef2aeb65f410",
              "issueId": null,
              "listingId": null,
              "noteId": "ab586b51-6931-4a4a-9c24-0d16226211b2",
              "opportunityId": "006a22dd-6bd6-4247-a24b-42fb164cd48c",
              "personId": null,
              "somethingId": null,
              "testId": null,
              "updatedAt": "2025-01-22T17:11:07.801Z"
            }
          }
        ]
      },
    }
  }
}
```
2025-03-20 18:38:19 +01:00
24bae89ebc Fix click outside for RecordDetailRelationSection (#11072)
Fixes https://github.com/twentyhq/twenty/issues/11061
2025-03-20 16:22:28 +00:00
7dac60cfee Fix useFindManyRecords withSoftDeleterFilter (#11056)
Fixes #11038

# Fix useFindManyRecords withSoftDeleterFilter

The error came from a faulty implementation of the `withSoftDeleted`
parameter inside `useFindManyRecords` and from the fact that
`withSoftDeleted: true` was added to access deleted records actions.
However, this parameter was always set in
`useFindManyRecordsSelectedInContextStore` instead of considering
whether the filter was active or not.

```
const withSoftDeleterFilter = {
  or: [{ deletedAt: { is: 'NULL' } }, { deletedAt: { is: 'NOT_NULL' } }],
};
```

The final filter was incorrectly doing an `or` operation between the
base filter and `withSoftDeleterFilter` when it should have been an
`and`:

```
filter: {
  ...filter,
  ...(withSoftDeleted ? withSoftDeleterFilter : {}),
}
```

The correct implementation should be:

```
filter:
  filter || withSoftDeleted
    ? {
        and: [
          ...(filter ? [filter] : []),
          ...(withSoftDeleted ? [withSoftDeleterFilter] : []),
        ],
      }
    : undefined,
```

# Fix useFindManyRecordsSelectedInContextStore

- Check if the soft deleted filter is active before using the
`withSoftDeleterFilter` parameter
2025-03-20 16:27:55 +01:00
4b34aa60b1 Fix minor bugs on advanced filters (#11044)
This PR fixes some minor bugs on advanced filters.

## Dropdown menu header in filter input

The chevron down icon in the operand dropdown menu header was missing
due to a recent refactor of the DropdownMenuHeader component.

I just removed the unused EndIcon and replaced its usage by
EndComponent.

## Advanced filter dropdown staying open with 0 filters

The behavior we have for non-advanced filters is that the chip should
disappear if the filter gets empty, which is logical, an empty filter is
equivalent to not having filters, so don't want empty chips.

For advanced filters, the principle is the same, except that it's a bit
more complex to handle due to the recursive filter group hierarchy.

Here we create a useRemoveRootRecordFilterGroupIfEmpty hook, that we can
call everywhere a synchronous action should end up removing advanced
filters completely. (instead of using an effect)

This hook is distinct from removeRecordFilterGroup because we want
removeRecordFilterGroup to do only one job and we don't want it to hide
any side effect. It's better to have the side effect in a separate hook
that we call sequentially afterwards, in a self-explanatory manner.

## Miscellaneous

In this PR we add a new component selector to get the root level record
filter group, which is handy in a lot of cases.

The return type of the useChildRecordFiltersAndRecordFilterGroups hook
when it's empty has been fixed, though as discussed with Charles, it
would be better to turn it into selectors, which will certainly be done
in future PRs.
2025-03-20 11:26:14 +01:00
d99f027e8d 400 workflows webhooks trigger (#11041)
https://github.com/user-attachments/assets/dc0ece22-4d87-417f-b9e1-a11c3fd52ce8
2025-03-20 10:12:52 +00:00
369abfe424 Rename onPersist to onChange for form fields (#11047)
We are about to build forms where fields will not be persisted
immediately. It will have to be submitted.
Renaming the prop to reflect it.
2025-03-20 10:58:02 +01:00
7b0bf7c4b0 Form action field base settings (#11035)
- Add settings for text and number fields
- Settings are for now the same but I still separated with two
components because they will evolve


https://github.com/user-attachments/assets/96b7fffd-c3a1-45b9-aeaa-45d63505de3c
2025-03-19 17:44:02 +00:00
62a58816e3 Fix view groups update after field metadata update (#10995)
This PR fixes a difficult to reproduce bug, where a race condition
appears if we go back to a table with view groups before the update
field metadata logic finishes its work.

In order to reproduce this bug on localhost, you'll have to simulate a
slow network in your browser.

The problem was that the view groups are initialized only once by
useLoadRecordIndexStates, in an effect component :
RecordIndexLoadBaseOnContextStoreEffect. And that this component as an
internal state loadedViewId, which prevents subsequent updates of view
groups by useLoadRecordIndexStates, because it considers that loading
already happened, even if it's actually stale data.

So instead of creating other states to burden the effect component with
complex state management, the solution was to add the only needed update
in a synchronous way directly in updateOneFieldMetadataItem logic. This
way we are sure that our boards and tables with view groups get updated
eventually, for each field metadata update, even if the requests take
time.

Fixes https://github.com/twentyhq/twenty/issues/10947
Fixes https://github.com/twentyhq/twenty/issues/10944
2025-03-19 11:13:14 +01:00
ca9c070945 Fix activity (#11015)
Deprecating unused states and making sure that the ActivityRichText
editor loads when activity.bodyV2 is present
2025-03-19 10:45:11 +01:00
a4bd00ae29 Remove opportunity specific code on Kanban (#11000)
In this PR:
- clean board from opportunity specific logic
- remove in place creation in board
- trigger creation in right drawer instead
2025-03-18 23:54:40 +01:00
841d48b704 Creating records in side panel not working (#10999)
Fixes https://github.com/twentyhq/core-team-issues/issues/624

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-03-18 19:34:50 +01:00
2680f1d6be 583 refactor useCommandMenu hook (#10984)
Closes https://github.com/twentyhq/core-team-issues/issues/583

- Split hook into smaller hooks
- Create tests
2025-03-18 15:37:28 +01:00
606098fef6 refacto(twenty-front): improve DropdownMenuHeader api (#10961) 2025-03-18 08:19:22 +01:00
8db8d9ad00 feat(twenty-front): improve dropdown menu header (#10672) 2025-03-17 16:10:52 +01:00
3988eb7787 Fix missing fields in filter on index board (#10909)
Fixes https://github.com/twentyhq/twenty/issues/10046
2025-03-14 19:13:44 +01:00
d34ec4da2d Fix kanban view picker total count (#10898)
Fixes https://github.com/twentyhq/twenty/issues/9790

Before


https://github.com/user-attachments/assets/332ec338-ce87-4d4d-ac47-a4e76dceb5b0



After


https://github.com/user-attachments/assets/93a03842-386a-4e75-a709-85a91bbc7679

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-03-14 17:27:25 +01:00
b12b2485c5 Fixed kanban for advanced filters and other bugs (#10888)
This PR mainly fixes advanced filters on kanban view.

It also fixes various bugs and cleans some old states.

## Advanced filters on kanban views

Kanban views use a different hook to retrieve data from the backend :
useLoadRecordIndexBoardColumn, this hook wasn't using the new state
currentRecordFilterGroupsComponentState.

## Removal of confusing duplicate states

A few different states were used for filters and states, where we only
need one for filters and one for sorts for all indexes. So we remove
here the different states that can lead to confusion about what state
should be used in what case.

States removed : 
- recordIndexFilterState
- recordIndexSortState
- recordIndexViewFilterGroupsState
- tableFiltersComponentState
- tableSortsComponentState

We also remove the logic that was used to manage those states.

## Abstracted non composite field type check into a util

We abstract the check made in mapFieldMetadataToGraphQLQuery into a util
isNonCompositeField, because those kinds of checks should be stored into
a separate unique file that acts as a source of truth.

## Bug with advanced filter rule position not saved

The position of an advanced filter rule wasn't correctly saved in the
backend, here we remove the WorkspaceIsSystem decorator on the
positionInViewFilterGroup fields.

The function that saved view filters was also ignoring the field
positionInViewFilterGroup, we add it back.

## Bug with view picker option dropdown closing weirdly

The view picker option dropdown was closing as soon as we hovered
outside of the option dropdown, which was annoying for the user, here we
apply the same behavior as every dropdown in the app : closing on click
outside.
2025-03-14 14:41:30 +01:00
46c773e5ff Fix update of aggregate operation not reflected in kanban header without refresh (#10879)
Before


https://github.com/user-attachments/assets/1761c49e-3d08-413a-bebd-11f4592a7de8

After


https://github.com/user-attachments/assets/064ef28f-b131-48af-ad66-11f782298670
2025-03-14 11:13:13 +01:00
1bffe57f6b feat: added countTrue and countFalse (#10741)
fix: #10603 


https://www.loom.com/share/cebc8a19bd8e4ae684a5a215d0fd1f94?sid=cadaa395-285c-45c9-b3ce-2ae6d1330a3c

---------

Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
2025-03-14 07:34:21 +01:00
3901ff3207 Fix Side Panel v2 bugs (#10865)
Fixing:
- Export as PDF on empty note
- Command O (sub commands) not using the right contextStore
- BelongsToOne Field input triggering an error on open if no existing
relation record is pre-selected
2025-03-13 19:18:34 +01:00
cb96f019d6 Set record groups when view groups are updated (#10863)
Currently we need to refresh to see view group updates.
2025-03-13 19:17:48 +01:00
d48b2b3264 Only store current object metadata id in state (#10856)
Fix group by refresh when adding a select field
2025-03-13 17:26:07 +01:00
b1322beac3 Fix console errors (#10859)
Fixes https://github.com/twentyhq/core-team-issues/issues/276

## Before

![image](https://github.com/user-attachments/assets/d1b49746-eb9b-4f96-81af-81332ebb2e43)

![image](https://github.com/user-attachments/assets/41ceccfc-6ee3-4ff5-9d02-c621244bf36b)


## After

![image](https://github.com/user-attachments/assets/67eea9c9-d838-4211-9e75-47d895d2662e)
2025-03-13 16:50:35 +01:00
4f0fd0c9f3 Fix stories again 2025-03-13 16:50:24 +01:00