npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

s8s-actionlist

v0.1.0

Published

List Component that renders a table, board, grid, or calendar

Downloads

2

Readme

Overview

This package creates a React-rendering of a list of items. The original concept was to create a task list, aka action list, but the underlying components can be used to render a wide range of objects.

For the purposes of this Readme, we'll use a task list to show examples. Below you will see a screenshot of each layout. The first shows the "out of the box" styling; the second shows what can be done with some simple customization. (The data is rendered semi-randomly, so the dates on each task will be different between the two - forgive the inconsistency.)

Table Layout

Table Layout Customized Table Layout

Board Layout

Board Layout Customized Board Layout

Grid Layout

Grid Layout Customized Grid Layout

Calendar Layout

Calendar Layout Customized Calendar Layout

Calendar Layout (Week View)

Calendar Layout Customized Calendar Layout

Settings

To save myself some writing, it will be best if you review the contents of the ActionListContext.ts file for a complete understanding of the available configurations and assorted data types.

These settings are manifold, and well documented in the source file (though I may add more detailed documentation here in future). You will also find an object (ActionListClasses) containing all classes applied to each element. (TODO: Document where/how these classes are applied.)

One concept that is not documented in source is "templated strings". These are strings (which are noted in source documentation) that allow the developer to use contextual details to create dynamic content. For example, link type data fields have a ref property. This is a templated string. As such, the developer might use a string that looks like

let column.ref = "/{related_to__type}/{related_to__id}";

When the table is being rendered, this string will be injected with data from each object in the list. Double underscores (__) are used to separate between object generations. During rendering, the above example equates to

// assume the object from the list being rendered is called `item`
let relatedToType = item["related_to"]["type"];
let relatedToId = item["related_to"]["id"];
tablecellLink.href = `/${relatedToType}/${relatedToId}`;

Implementation

Here is a sample implementation. More thorough documentation is a TODO.

type TaskListData = {
    activeLayout: ActionListLayouts;
    title: string;
    statuses: TaskListStatus[];
    fields: TaskListField[];
    list: TaskListObject[];
    [key:string]: any;
};

function renderTaskList(data: TaskListData) {
    let settings = new ActionListSettings();
    settings.effects = [
        () => {
            utils.enableTooltips(); // helper function that creates
                                    // bootstrap tooltips.
        }
    ];
    let refactoredData:ActionListData = {
        list:data.list
    };
    settings.defaultLayout = data.activeLayout;
    settings.components.modal = TaskListItemModal; // See below
    settings.collections = data.statuses;
    settings.title = data.title;
    settings.columns = data.fields;

    settings.tableActions = [NewTaskTableAction]; // See below

    renderActionList('tasklist-container', refactoredData, settings);
}

function TaskListItemModal(props: ActionListModalProps) {
    return (
        <ReactBootstrap.Modal
            show={props.show}
            onHide={props.onClose}
        >
            <ReactBootstrap.Modal.Header closeButton>
                <ReactBootstrap.Modal.Title>
                    {props.item['name']}
                </ReactBootstrap.Modal.Title>
            </ReactBootstrap.Modal.Header>
            <ReactBootstrap.Modal.Body>
                <div>
                    <h2>Description</h2>
                    <p>{props.item['content']}</p>
                    <h2>Status</h2>
                    <p>
                        {props.item['icon']}{" "}
                        {props.item['status']}
                    </p>
                </div>
            </ReactBootstrap.Modal.Body>
            <ReactBootstrap.Modal.Footer>
                <ReactBootstrap.Button variant="primary" onClick={props.onClose}>
                    Close
                </ReactBootstrap.Button>
            </ReactBootstrap.Modal.Footer>
        </ReactBootstrap.Modal>
    );
};



const NewTaskTableAction = () => {
    return (
        <p className={`add-new-task`}
            data-toggle="tooltip"
            title="This would pop out a New Task screen."
        >
            <i className="fas fa-plus"></i>
            Add New Task
        </p>
    );
}

I'll omit much of the customized styling (there are a few hundred lines of SCSS), but I do want to call out how the statuses were colored. The status column was defined as a pill type which adds the column's value to the class list in the status column of the Table, and is the default settings.collectionField value which adds the property's value to the loading bars of the cards in the Board, to the tiles in the Grid, and to the loading bars of events in the Calendar (as well as to the event and card themselves).

Furthermore, the progress field is defined as a ring type, which shows a loading ring in the Table and Grid, a loading bar in the Board, and a loading column in the Calendar.

From there, I was able to specify each status in the CSS as follows (I'm sure there is a more concise way to do this)


// Style the background and border of the Board's loading bars
// Note, the variable `--progress` is defined on the element when rendered
.action-list-bar {

    &.new {
        border-color: $new;
        background: linear-gradient(90deg, $new var(--progress), $white-color var(--progress));
    }

    &.inprogress {
        border-color: $inprogress;
        background: linear-gradient(90deg, $inprogress var(--progress), $white-color var(--progress));
    }

    &.pending {
        border-color: $pending;
        background: linear-gradient(90deg, $pending var(--progress), $white-color var(--progress));
    }

    &.done,
    &.complete {
        border-color: $done;
        background: linear-gradient(90deg, $done var(--progress), $white-color var(--progress));
    }
}

// Style the event's loading bar background and table's cell background and border
.action-list-event-ring,
.pill {

    &.new {
        background-color: $new;
        border-color: mix($new, #000, 70%);
    }

    &.inprogress {
        background-color: $inprogress;
        border-color: mix($inprogress, #000, 70%);
    }

    &.pending {
        background-color: $pending;
        border-color: mix($pending, #000, 70%);
    }

    &.done,
    &.complete {
        background-color: $done;
        border-color: mix($done, #000, 70%);
    }
}

// Style the event and event's loading column border
.action-list-event-ring,
.action-list-event-contents {
    &.new {
        border-color: $new;
        background-color: inherit;
    }

    &.inprogress {
        border-color: $inprogress;
        background-color: inherit;
    }

    &.pending {
        border-color: $pending;
        background-color: inherit;
    }

    &.done,
    &.complete {
        border-color: $done;
        background-color: inherit;
    }
}

Handling Updates

You can handle updates, trigged by board drag/drop, event drag/drop, or event create, using settings hooks. An example was shown