Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Row actions #348

Merged
merged 9 commits into from
Oct 28, 2023
Merged

Feature: Row actions #348

merged 9 commits into from
Oct 28, 2023

Conversation

jowilf
Copy link
Owner

@jowilf jowilf commented Oct 21, 2023

  • Implemented
  • Tested
  • Documented
class ArticleView(ModelView):
    ...
    row_actions = ["view", "edit", "go_to_example", "make_published", "delete"]
    row_actions_display_type = RowActionsDisplayType.ICON_LIST # RowActionsDisplayType.DROPDOWN

   @row_action(
        name="make_published",
        text="Mark as published",
        confirmation="Are you sure you want to mark this article as published ?",
        icon_class="fas fa-check-circle",
        submit_btn_text="Yes, proceed",
        submit_btn_class="btn-success",
        action_btn_class="btn-info",
    )
    async def make_published_row_action(self, request: Request, pk: Any) -> str:
        session: Session = request.state.session
        article = await self.find_by_pk(request, pk)
        if article.status == Status.Published:
            raise ActionFailed("The article is already marked as published.")
        article.status = Status.Published
        session.add(article)
        session.commit()
        return "The article was successfully marked as published"

    @link_row_action(
        name="go_to_example",
        text="Go to example.com",
        icon_class="fas fa-arrow-up-right-from-square",
    )
    def go_to_example_row_action(self, request: Request, pk: Any) -> str:
        return f"https://example.com/?pk={pk}"

row_actions_display_type = RowActionsDisplayType.ICON_LIST

Screenshot 2023-10-21 at 4 39 58 PM

row_actions_display_type = RowActionsDisplayType.DROPDOWN

Screenshot 2023-10-21 at 4 48 06 PM

detail view

Screenshot 2023-10-21 at 4 52 57 PM

@github-actions
Copy link

github-actions bot commented Oct 21, 2023

@github-actions github-actions bot temporarily deployed to pull request October 21, 2023 21:36 Inactive
@jowilf jowilf added this to the 0.12.0 milestone Oct 21, 2023
@codecov
Copy link

codecov bot commented Oct 21, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (2d58ded) 100.00% compared to head (46e9599) 100.00%.

Additional details and impacted files
@@            Coverage Diff             @@
##              main      #348    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files           72        72            
  Lines         5254      5409   +155     
==========================================
+ Hits          5254      5409   +155     
Files Coverage Δ
starlette_admin/_types.py 100.00% <100.00%> (ø)
starlette_admin/actions.py 100.00% <100.00%> (ø)
starlette_admin/base.py 100.00% <100.00%> (ø)
starlette_admin/contrib/sqla/view.py 100.00% <100.00%> (ø)
starlette_admin/helpers.py 100.00% <100.00%> (ø)
starlette_admin/views.py 100.00% <100.00%> (ø)
tests/sqla/test_actions.py 100.00% <100.00%> (ø)
tests/test_actions.py 100.00% <100.00%> (ø)
tests/test_i18n.py 100.00% <100.00%> (ø)
tests/test_views.py 100.00% <100.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@jowilf
Copy link
Owner Author

jowilf commented Oct 21, 2023

Hello @mrharpo, I would love to hear your thoughts on this as it directly affects your work on #302

what changed (compared to #302 ):

  • Batch actions will only be available in the list
  • Row actions are now available on each row and will also appear on the detail page by default

Let me know if you see any issues with this approach! I'm open to suggestions on how to best support the row actions

@github-actions github-actions bot temporarily deployed to pull request October 21, 2023 22:40 Inactive
@jowilf jowilf linked an issue Oct 21, 2023 that may be closed by this pull request
@github-actions github-actions bot temporarily deployed to pull request October 21, 2023 22:58 Inactive
@hasansezertasan
Copy link
Contributor

It looks great, I took a look at the changes, I can't see any problem at the changes you made.

@mrharpo
Copy link
Contributor

mrharpo commented Oct 23, 2023

@jowilf This looks great! 🚀 The implementation doesn't affect our actions directly, but it might be nice if we could merge the concepts, so a task could be available as a @row_action and (batch) @action without needing to duplicate logic.

In our case, we need to start (effectively publish) one or many rows from the list page, and also start a row from the detail page. We used the batch @action on the detail page as a workaround for a row_action, where it sends a list with a single pk to the batch action API. However, it would be cleaner if (for example) we used the new @row_action instead and allow it to be run as a batch action for multiple records. E.g:

class ArticleView(ModelView):
    ...
    row_actions = ["view", "edit", "go_to_example", "make_published", "delete"]
    batch_actions = ["make_published", "delete"]

   @row_action(
        name="make_published",
        text="Mark as published",
        confirmation="Are you sure you want to mark this article as published ?",
        confirmation_multiple="Are you sure you want to mark these articles as published ?",
        icon_class="fas fa-check-circle",
        submit_btn_text="Yes, proceed",
        submit_btn_class="btn-success",
        action_btn_class="btn-info",
    )
    async def make_published_row_action(self, request: Request, pk: Any) -> str:
    ...

By including it in batch_actions, it would get run multiple times, returning possibly multiple ActionFailed errors in the process, unless some kind of stop_on_first_failure flag is set, perhaps.

We're open to suggestions, especially if there's an easier / better way I'm not seeing.

But it's also easy enough for us to include both if it ends up being too complicated, or too much of a breaking change. Again, this is all great, and will work fine for our application.

Related (but definitely a separate issue), we've discussed having some kind of @view_action for actions in a view that are unrelated to any records (e.g. sync_database).

Thanks for the heads up!

@hasansezertasan
Copy link
Contributor

hasansezertasan commented Oct 23, 2023

I agree with @mrharpo combination of those logic would be good, maybe gets harder to implement but good.

Also, I think we shouldn't remove batch actions from the details view, it's a great feature.

And also, do we need a link row action? I believe we can annotate the return type and decide the action by inspecting the return type, maybe a redirect response would be enough?

Combining these features might seem overwhelming at the beginning but I think in the end, we will gain a lot by configurations. I think we can use a parameter here to point where the action will be available, a list of places maybe?

These suggestiona/opinions might be considered in the future, when they become high demand features. For now, it all looks great to me.

@jowilf
Copy link
Owner Author

jowilf commented Oct 26, 2023

It is possible to use the same method for row actions and batch actions with this simple logic:

@action(...)
@row_action(...)
async def make_published_action(self, *args) -> str:
  request: Request = args[0]
  if isinstance(args[1], list):
      pks = args[1]
      return "BATCH ACTION"
  else:
      pk = args[1]
      return "ROW ACTION"

And also, do we need a link row action? I believe we can annotate the return type and decide the action by inspecting the return type, maybe a redirect response would be enough?

link_row_action eliminates the necessity to call the action API. The link is included directly in the href attribute of the generated <a> element.

@hasansezertasan
Copy link
Contributor

It is possible to use the same method for row actions and batch actions with this simple logic:

That's great to see.

link_row_action eliminates the necessity to call the action API. The link is included directly in the href attribute of the generated <a> element.

You have thought of everything. Nothing else, great job!

@github-actions github-actions bot temporarily deployed to pull request October 28, 2023 21:03 Inactive
@github-actions github-actions bot temporarily deployed to pull request October 28, 2023 21:30 Inactive
@github-actions github-actions bot temporarily deployed to pull request October 28, 2023 21:53 Inactive
@github-actions github-actions bot temporarily deployed to pull request October 28, 2023 21:58 Inactive
@jowilf jowilf merged commit 63dca61 into main Oct 28, 2023
10 checks passed
@jowilf jowilf deleted the row_actions branch November 6, 2023 06:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enhancement: How to add custom action toolbar icons/buttons in List View
3 participants