@bigbinary/neeto-trash-frontend
v3.2.3
Published
A repo acts as the source of truth for the new nano's structure, configs, data etc.
Readme
neeto-trash-nano
The neeto-trash-nano acts as the source of truth for the new nano's structure, configs, data etc.
Contents
Development with Host Application
Engine
Installation
Add this line to your application's Gemfile:
source "NEETO_GEM_SERVER_URL" do # ..existing gems gem 'neeto-trash-engine' endAnd then execute:
bundle installAdd this line to your application's
config/routes.rbfilemount NeetoTrashEngine::Engine, at: "/neeto_trash"Add required migrations in the
db/migratefolder. Run the following commands to copy the migrations from the engine to the host application.bundle exec rails neeto_trash_engine:install:migrations bundle exec rails db:migrate
Setup generators
rails g neeto_trash_engine:installSets up everything a host application needs to use the engine:
- Mounts
NeetoTrashEngine::Engineat/neeto_trashinconfig/routes.rb. - Copies
app/lib/neeto_trash_engine/callbacks.rb, the authorization contract the engine delegates permission/organization-scoping decisions to. - Copies
config/initializers/neeto_trash_engine.rb, which configures the retention period, the current user resolver, and the callbacks class. - Adds a
trash_cleanupentry toconfig/scheduled_jobs.ymlthat runsNeetoTrashEngine::CleanupJobdaily. Ifconfig/scheduled_jobs.ymldoesn't exist, the generator prints the entry to add manually instead of creating the file.
Running the generator again is safe: it skips any step whose target file already exists or already contains the expected entry.
- Mounts
rails g neeto_trash_engine:trashable ArticleGenerates a migration (
db/migrate/add_neeto_trash_to_articles.rb) that adds the columns a model needs to support trashing:is_trashed,trashed_at, atrashed_byreference tousers, and a composite index on[:is_trashed, :trashed_at]. The table name is taken from the model when it already exists, and thetrashed_byreference type matches the host application's configured primary key type (e.g.:uuid).
Usage
Models including NeetoTrashEngine::Trashable can override their deletion methods.
Single deletion and retention cleanup call permanently_delete!, which defaults
to destroy!. Bulk deletion calls permanently_delete_all! on the authorized
scope. Its default calls destroy_all and raises when a callback stops deletion,
so the bulk transaction rolls back.
An asynchronous implementation must immediately hide the record from the trash
list and enqueue cleanup after the transaction commits. For models that include
NeetoCommonsBackend::Deletable, use the existing methods for both deletion paths:
def permanently_delete!
destroy_async
end
def self.permanently_delete_all!
destroy_async_multiple(pluck(:id))
endThe bulk override hides the selected records in one update and queues one job after commit. Retention cleanup keeps its per-record lock and eligibility check.
Overrides must preserve the host model's destroy callbacks and dependent cleanup.
Use destroy! or the application's existing deletion service for physical deletion.
For asynchronous deletion, the background worker must perform this cleanup.
Replace NeetoTrashNano with your project name
Create a
script.rbfile in the project root and paste the script from the following file.Run the file using the following command:
ruby script.rb
Notes ⚠️
- Don't commit this file.
- Project name should be given in PascalCase.
Frontend package
Installation
Add the
neeto-trash-frontendpackage to thepackage.jsonyarn add @bigbinary/neeto-trash-frontend
Instructions for development
Check the Frontend package development guide for step-by-step instructions to develop the frontend package.
Usage
Mount the trash page by importing
TrashListfrom "@bigbinary/neeto-trash-frontend" and telling it which item types your app trashes:import React from "react"; import { TrashList } from "@bigbinary/neeto-trash-frontend"; const Trash = () => <TrashList itemTypes={{ Article: { label: "Articles" } }} />; export default Trash;Wire the delete action in your app's menus to move items to trash instead of hard-deleting:
import { MoveToTrashAction } from "@bigbinary/neeto-trash-frontend"; <MoveToTrashAction ids={[article.id]} type="Article" onSuccess={refetchArticles} />;The package also exports
TrashBanner,RestoreButton,DeletePermanentlyAction, the data hooks (useFetchTrashedItems,useMoveToTrash,useRestore,usePermanentlyDelete,useInvalidateTrashList),getDaysUntilDeletion, andQUERY_KEYS.Keep the Trash page in sync when you trash from your own endpoint.
If you move items to trash with
MoveToTrashAction/useMoveToTrash(step 2), the Trash page's list and counts refresh automatically — that hook invalidates the trash query for you, so there is nothing extra to do.Most apps, however, trash through their own delete endpoint instead, so the same request can run app-specific side effects (analytics, cascades) and refresh their own lists. That path never runs the package's mutation, so the Trash page stays stale until you invalidate its query yourself. Drop
useInvalidateTrashListinto that mutation'sonSuccess:import { useInvalidateTrashList } from "@bigbinary/neeto-trash-frontend"; const useDestroyArticle = () => { const queryClient = useQueryClient(); const invalidateTrashList = useInvalidateTrashList(); return useMutation({ mutationFn: articlesApi.destroy, onSuccess: () => { queryClient.invalidateQueries({ queryKey: [ARTICLE_LIST] }); // your list invalidateTrashList(); // refreshes the Trash page list + counts }, }); };useInvalidateTrashListreturns a callback that invalidatesQUERY_KEYS.TRASHED_ITEMS, so you never hardcode the trash query key. (Restore and permanent-delete insideTrashListalready invalidate it themselves — this is only needed for your own move-to-trash path.)
Instructions for Publishing
Consult the building and releasing packages guide for details on how to publish.
