Feature: Script Tagging
Relevant source files
The following files were used as context for generating this wiki page:The Script Tagging feature is a core organizational mechanism within the Scripty application. It allows users to categorize PowerShell scripts by assigning one or more descriptive tags. This system facilitates efficient script management, filtering, and retrieval. The entire feature is built around a centralized Zustand state store, which manages the lifecycle of tags and their association with script items.
The feature encompasses three main user-facing functionalities: creating new tags, assigning existing tags to new scripts, and filtering the script list based on a selected tag. The state, including all scripts and tags, is persisted locally to a JSON file in the user's application data directory, ensuring data is retained between sessions.
Architecture and State Management
The foundation of the tagging system is the useListStore Zustand store. This store acts as a single source of truth for all script items and tags within the application. It leverages zustand/middleware/persist to save state to a local file.
Sources: src/Hooks/useListStore.js
Zustand Store (useListStore)
The store defines the state structure and actions for managing tags and their relationship with scripts.
Key State Properties:
| Property | Type | Description |
|---|---|---|
items | Array<Object> | An array of script item objects. Each object contains a tags array. |
tags | Array<string> | An array of all available tag strings. |
filterTag | string | null | The currently active tag used for filtering the script list. |
selectedItem | Object | null | The currently selected script item for viewing in the detail pane. |
Sources: src/Hooks/useListStore.js:29-37
Default Tags:
The store is initialized with a predefined set of tags.
| Default Tags |
|---|
| Routine |
| SYSTEM |
| Check |
| User |
| Admin |
| Archive |
Sources: src/Hooks/useListStore.js:33
Key Actions:
| Action | Parameters | Description |
|---|---|---|
addTag | tag: string | Adds a new tag to the tags array if it doesn't already exist. |
addItem | item: Object | Adds a new script item to the items array. The item object includes its assigned tags. |
setFilterTag | tag: string | Sets the filterTag state to enable filtering. |
getFilteredItems | () | A selector function that returns a filtered list of items based on the current filterTag. |
Sources: src/Hooks/useListStore.js:39-75
The diagram below illustrates the structure of the useListStore and its core components related to tagging.
Sources: src/Hooks/useListStore.js:27-79
Tag Creation
Users can create new tags through the FormTag component. This component is a simple form that captures a new tag name and adds it to the global state.
Sources: src/components/Form/FormTag.jsx, src/App.jsx:54
FormTag Component
The FormTag component is a modal form containing a single text input for the tag name.
- UI: A text input with
name="tn"and a submit button. - Logic: The
handletagSubmitfunction is triggered on form submission. It retrieves the tag name, calls theaddTagaction fromuseListStore, resets the form, and hides the modal.
Sources: src/components/Form/FormTag.jsx:7-13
The sequence diagram below shows the flow of creating a new tag.
Assigning Tags to Scripts
When adding a new script via the Form component, users can select one or more tags from the existing list to associate with that script.
Sources: src/components/Form/Form.jsx
Form Component
This component includes a form for the script name and a multi-select dropdown for tags.
- Tag Population: The
<select>element is populated with<option>elements by mapping over thetagsarray fromuseListStore. - Tag Selection: The
handleTagChangefunction updates a localselectedTagsstate array as the user selects/deselects options in the multi-select dropdown. - Submission: On
handleSubmit, a new script item object is created. This object includes thetitle,content,date, a uniqueid, and thetagsarray containing the values from the localselectedTagsstate. This new item is then passed to theaddItemaction inuseListStore.
Sources: src/components/Form/Form.jsx:48-55, src/components/Form/Form.jsx:78-87
This flowchart shows the process of adding a new script and assigning tags to it.
Sources: src/components/Form/Form.jsx:57-74
Script Filtering by Tag
The application allows users to filter the displayed list of scripts based on a single selected tag. The core filtering logic resides within the getFilteredItems selector in useListStore.
Filtering Logic (getFilteredItems)
The getFilteredItems function implements the following rules:
- If
filterTagis"Archive", it returns only items that include the "Archive" tag. - If
filterTagis any other string, it returns items that include that tag but do not include the "Archive" tag. - If
filterTagisnullorundefined, it returns all items that do not include the "Archive" tag.
// src/Hooks/useListStore.js:65-75
getFilteredItems: () => {
const { items, filterTag } = get();
if (filterTag === "Archive") {
return items.filter((item) => item.tags.includes(filterTag));
} else if (filterTag) {
return items.filter(
(item) =>
item.tags.includes(filterTag) && !item.tags.includes("Archive"),
);
} else {
return items.filter((item) => !item.tags.includes("Archive"));
}
},
Sources: src/Hooks/useListStore.js:65-75
Displaying Filtered Scripts (List.jsx)
The List component is responsible for rendering the list of scripts. It calls getFilteredItems() to get the appropriate list of scripts to display and then maps over the result to render ListItem components. The component automatically re-renders when the filterTag or items state changes in useListStore.
Sources: src/components/Form/List.jsx:28-30
This flowchart illustrates how scripts are filtered and displayed.
Conclusion
The Script Tagging feature in Scripty is a well-structured system for organizing scripts. It relies on a centralized Zustand store (useListStore) for robust state management and data persistence. The separation of concerns is clear, with dedicated React components for creating tags (FormTag), assigning them to scripts (Form), and displaying the filtered results (List). This architecture provides a scalable and maintainable foundation for script organization within the application.