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

derby-entity

v1.2.2

Published

A Perfect DerbyJS CRUD Component

Downloads

5

Readme

A Perfect DerbyJS CRUD Component

This is a completely generic, responsive, and realtime collaborative DerbyJS component to create, read, update, and delete entities in a database using Racer. The items of an entity are displayed using either the great jQuery DataTables plugin, or a native DerbyJS implementation. Realtime collaboration and conflict resolution is achieved through RacerJS and ShareJS.

That said, perfection is hard to achieve and there always seems something more that could be done. You are welcome to provide ideas or pull requests.

Screenshots

TODO

Prerequisites

derby-entity depends on the following packages:

  • my DerbyJS fork because I added

    • support for component styles
    • support for subcomponents
    • support for components written using ES6 inheritance

    all of which are currently needed for derby-entity, derby-entities-lib, and derby-select2. Also, I merged Racer's pull request 238 for much better performance.

  • derby-router

  • derby-entities-lib, which contains some purely model- and entity-specific functions as well as view components that are needed and shared by derby-entity and derby-entity-visualization

  • derby-sass for being able to compile scss files on the fly... actually, a better way is to do it using gulp, see below.

  • i18n: derby-lang, derby-lang-locale and derby-locale, plus the following shortcuts:

    • model path $locale.locale to point the current lowercase locale (en, de, ...)
    • view function t($locale, path, params) to return the translation of path in the current locale

    See below for detailed i18n information.

  • in case you want the DataTables implementation: a browserify bundle that provides jQuery and exposes the following DataTables requires:

require('datatables')
require('datatables.bootstrap')
require('datatables.responsive')
require('datatables.colReorder')
require('datatables.colResize')
require('jquery.highlight')
require('datatables.searchHighlight')
  • my Bootstrap fork where I added proper placement support for popovers when combining trigger: manual with container and selector.

  • Font-Awesome, use bower for that one.

Usage

An object with entity definitions is needed to tell derby-entity what to display, it doesn't analyze the database by itself. Each entity, the items of which are to be displayed and edited, has to be defined with all its attributes. How that is to be done is documented in derby-entities-lib.

Since I wanted this component to be really real-time, I created an unusual editing model: there is no cancel or save when you select an item, changes are instantly written to the model and visible from all clients. This carries a drawback I haven't been able to solve yet: there is no undo (hard to implement with Derby at the moment), and it is thus possible to inadvertently change something, maybe even without noticing. I need a good idea on this one. So far I thought about saving the current item in local storage as soon as it is changed, but I am not sure if that is an ideal way... how to recover it? How to display it?

Now, about technical usage: you need to load the component with

app.component require('derby-entity')

then in your view, use

<view name="entity" entity="{{_page.entity}}" item="{{_page.item}}" />

to instantiate it, and provide it with an entity schema object. Optionally, pass along an item that should already be selected initially.

jQuery DataTables vs native DerbyJS implementation

Depending on which version you want to use, comment the correct line in index.ls (line 3 or 4) and index.scss (line 27 or 30).

i18n

You need to provide the following strings. All entities need to define their name to be displayed, singular and plural:

  • .title
  • .one

In addition to that, each entity attribute needs to be defined.

The actions and dialogs of this component are using these strings:

actions
{
    "title": "Actions",

    "new": "New {ITEM}",
    "edit": "Edit",
    "add": "Add",
    "delete": "Delete",
    "done": "Done",
    "cancel": "Cancel"
},

dialogs
{
    "deleteEntityTitle": "Delete {ENTITY}",

    "referencePopoverTitle": "<em>{ITEM}</em> is used by:",
    "referencePopoverUnused": "This {ENTITY} is not referenced."
},

messages
{
    "entityAdded": "New {ENTITY} \"{ITEM}\" added.",
    "deleteEntity": "Do you really want to delete this {ENTITY}?",
    "entityDeleted": "{ENTITY} \"{ITEM}\" deleted.",
    "itemReferenced": "Cannot delete {ENTITY} because it is still referenced by:"
}

Style

To be more flexible I added some fine-graned color definition variables to the standard $brand-primary. derby-entity uses:

    $brand-primary
    $brand-primary-light
    $brand-secondary
    $brand-aux-1-med-light

CSS Compilation

I am not using a task runner anymore, I just call the shell commands directly. I used to have gulp but found it to be too much code and too many dependencies to download. Even though, jake seems to be a beautiful alternative should the build become more complex in the future.

If you really want to use gulp, you can use something like the following code to compile the scss. Note that the sass call has to be sync, otherwise the includes get messed up and random errors occur. Also note that I was using nconf, replace those paths with whatever is correct for you.

    require! {
        lodash: _
        fs
        path
        'node-sass'
        gulp
        'merge-stream': merge    # to be able to use several streams in one task
    }

    notify     = require 'gulp-notify'
    plumber    = require 'gulp-plumber'
    sass       = require 'gulp-sass'
    prefix     = require 'gulp-autoprefixer'
    cssmin     = require 'gulp-cssmin'
    sourcemaps = require 'gulp-sourcemaps'


    # create CSS from Sass, autoprefix it to target 99% of web browsers, minifies it.
    gulp.task 'components:sass', ->
        streams = _.map componentsDirs, (dir) ->
            gulp.src path.join dir, 'index.scss'
                .pipe plumber!
                #.pipe sourcemaps.init!
                .pipe sass.sync {
                    includePaths: nconf.get 'paths:sass-includes'
                    outputStyle: if nconf.get 'debug:css' then 'expanded' else 'compressed'
                    sourceComments: nconf.get 'debug:css'

                    # url is the path in import as is, which libsass encountered.
                    # prev is the previously resolved path.
                    # done is an optional callback, either consume it or return value synchronously.
                    # @options contains this options hash
                    # @callback contains the node-style callback
                    importer: (url, prev, done) ->
                        if _.endsWith url, '.css'
                            for sassIncludePath in @options.includePaths.split path.delimiter
                                try
                                    cssData = fs.readFileSync path.resolve(process.cwd!, sassIncludePath, url), "utf8"
                                    return contents: cssData
                        else
                            return node-sass.NULL
                }
                .on 'error', sass.logError
                #.pipe prefix "> 1%"
                #.pipe cssmin keepSpecialComments: 0
                #.pipe sourcemaps.write './maps' # relative to gulp.dest
                .pipe gulp.dest dir

        merge streams

TODO

  • more documentation...
  • drop jQuery DataTables, it is just too fat and slow (takes at least 500ms to display after the page has been rendered, and with just around 150 items it slows down to 1.5s)
  • reimplement the DataTables features using what Derby already provides, as well as using:

License

MIT

Copyright (c) 2015-2016 Michael Brade