Category Filtering: 'open-source'

gadget-ui v 7.0.0 - Part II - uploading images to a NodeJS app using FileUploader

gadget-ui, NodeJS, Open Source

In Part I of the look at the 7.0.0 release of gadget-ui, I discussed some of the new features of the library and provided some insight into the new NodeJS-based test system.  I left out the discussion of the new FileUploader example written in NodeJS. In short, the new NodeJS test system includes code to demonstrate the FileUploader functionality using NodeJS as a backend. While it isn't necessarily a production-ready solution, it should give you enough code to implement the FileUploader against a NodeJS server without any significant obstacles.


gadget-ui v 7.0.0 - Part I - NodeJS support

gadget-ui, NodeJS, Open Source

gadget-ui, my open source JavaScript component library, has reached a new milestone- v 7.0.0. This release contains several new features, the most significant of which have to do with NodeJS support. Recent versions of the library have required users to set up a CFML engine such as Lucee or ColdFusion to fully test all of the components in the library. The 7.0.0 release now includes a NodeJS-based solution for testing all of the library components.


Building and Configuring Apache James with OpenLDAP

Apache James, Open Source, OpenLDAP, Ubuntu

[ This post is part of my ongoing instructional series on setting up some baseline IT infrastructure for the fictional startup Shoestring Lab. Shoestring has committed to using Open Source wherever possible. Shoestring Lab has standardized on Ubuntu for its server and desktop/laptop computer systems.

Today's lesson

Now that you have built a central user repository for your network using OpenLDAP, you need to configure an email server to use the OpenLDAP user repository.]


Livesandbox Web app editor v 0.11.0

altseven, JavaScript, Open Source

Good news for open source JavaScript supporters- the livesandbox project is nearing a 1.0.0 release. I have added some of the missing features in the beta roadmap. You can see the project on it GitHub page.

Updates in this release:

  • add notifications on save and delete of apps and libraries
  • add confirmation dialogs when abandoning changes in apps and libraries
  • update database to change JS, CSS, and HTML fields to text from varchar to accommodate larger projects
  • update to altseven remote module to return promises from invoked remote methods so promises can be handled from calling code

These changes bring the editing experience closer to what developers (certainly myself) would expect to see in an editor application.

For a v 1.0.0 release, I expect to add a user profile page. I am also considering making public (anonymous) access part of the release. An admin system and multi-user access (viewing applications of other users) may also be part of the release, though I have not scoped these features and am not yet ready to commit to making them part of the release.


Livesandbox Web app editor v 0.9.4

altseven, JavaScript, Open Source, Web Development

Another update of the livesandbox editor is available on GitHub. I made some important fixes to the application and wanted get this code released as soon as possible.

Updates in this release.

  • fix update/read issues with saving apps
  • change editor layout
  • fix sometimes incorrect saving of esModule bit field
  • fix save/retrieval/loading of app libraries
  • add getApps and getLibraries stored procedures to git
  • update db dump
  • set editor to wrap long lines so the editor width does not grow beyond 50% of sandbox width

Upgrading from previous releases:

In addition to pulling the latest master (or the 0.9.4 tag) from GitHub, you will need to update the getApps stored procedure in the database. A SQL script has been added to ./database/getApps.sql with the updated stored procedure code. You can, if you prefer, simply replace the previous database with the new backup in the ./database folder.

The application is getting closer to being stable and feature complete for a 1.0.0 release. Outstanding tasks:

  • add notifications on successful save/delete of apps and libraries
  • add warnings when discarding unsaved changes
  • add paging for apps and libraries lists

I may or may not add an admin feature as part of the 1.0.0 release.


Livesandbox Web app editor updated

JavaScript, Open Source

Following the release of a work in progress update to gadget-ui, I've spent some time this weekend on an update to the beta release of the livesandbox web app editor. This is a minor update meant to fix some of the most egregious and annoying bugs in the initial beta release.

Oh yeah, grab the code on GitHub.

Fixes in this release (from the release notes):

  • properly set editor mode for each pane so code renders correctly
  • set editor to refresh on content load
  • prevent save for unnamed apps/libraries
  • resolve issues with saving/loading of libraries linked to apps
  • add new library function
  • fix issue with bit value as Buffer in remote/app.update
  • login now loads libraries and apps

The editor now color codes JavaScript, HTML, and CSS correctly. It also immediately shows changes to each editor pane when you load a saved app. These were minor configuration and programming issues with the editor.  Making the most of the Code Mirror editor component could involve significant configuration work, for now the settings are out-of-the-box configurations.

Saving and loading apps and libraries has also been given some attention, though there are still some issues saving apps and more generally handling server-side exceptions on the client. These issues will be addressed in a future release.

The CSS Grid layout of the sandbox still needs work, as mentioned in the initial beta release notes, and may receive attention in the next release. Once the outstanding issues are resolved, I may spend some time on a user admin area, multi-user mode, and anonymous browse/edit mode. Suggestions for enhancements/updates are welcome.


Gadget-UI Update

gadget-ui, GitHub, Open Source, Web Development

The latest gadget-ui library update is available on GitHub and npm. Version 6.1.0 makes headway in simplifying some of the components by removing inline style options and allowing CSS classes as options that override default styling. A Full list of fixes and updates:

This release simplifies the code for several of the components in the library and adds some new options to a few of them. According to semver it could be a new major release, but I am releasing it as a minor upgrade since it represents work in progress. Major features of this release:
 

  • Remove many of the inline style options for FloatingPane, CollapsiblePane, and other components.
  • Add class and headerClass options for FloatingPane and CollapsiblePane to enable easy overriding of default styles and more flexible styling via CSS classes. Note that you can also use the pre-defined styles and override with !important, which is easier for making minimal changes.
     
  • Add hideable option to ComboBox, SelectInput, TextInput to make hiding the control when not is use optional and false by default.
  • Improve ComboBox control
    • Fix styling issues with borders and input control.
    • Add new down chevron SVG as dropdown indicator. By default requires feather-icons to be accessible from the client in /node_modules/feather-icons. Change the CSS to pick a different location as needed.
    • Fix combobox export for es6, which was misspelled.
  • Upgrade various reported vulnerable devDependencies through npm.

 


Iterative Development as Software Craft

altseven, Health & Science, Open Source, Web Development

Background

The practice of software is part engineering and part craft. Academia is full of coursework designed to teach you the theory of computing and the engineering discipline of writing software. Learning software as a craft, though, seems to occur over time in the profession of software development.

Iteration as a process for software development, in my mind, has always belonged in the realm of "software as craft" rather than "software as engineering discipline". Granted, there is plenty of room to look at iteration as part of an engineering process, but I relate it to how writers of novels build a story and refine the story over a series of drafts until they arrive at a completed work.

My approach to software development has always been to build a working skeleton of an application and then refine and expand it over time using an iterative approach. I'm going to share, briefly, the why and how of my approach.

Iterative Development as Craft

Building complex software systems is hard. If you've worked in the field for a few years, you've probably had more than your share of frustrations during a complex software project where careful planning went into the requirements gathering and specification phase, only to have some significant aspect of the specification change midway through the project. These kinds of failures (yes, they are failures, though individually they might not doom an entire project) have become less common through the use of iterative software development.

Instead of trying to build every aspect of a software system in a single pass, iterative development encourages you to build a skeleton of functionality for the application, prove that it works, then layer in additional functionality in successive passes. The craft of iterative development begins with understanding how much you can build in a single iteration without compromising a primary goal of iterative development - building in small chunks to simplify the testing and debugging phase of each iteration. Knowing how much you can take on in a single pass requires enough experience to be familiar with the pace of development and the complexity of debugging for a given system.

By using source control and building iteratively, you can provide yourself with a history that shows in time how your application has developed over a series of iterations. On GitHub, I use semver and tags to mark my progress.

Iterative Development v. Versions

Speaking of semver, you might object, "But you are really talking about versions. Every software company since forever has made successive versions of their products/projects." In a sense, that's true, versions are a long version of iterative development. When I refer to iteration, though, I'm really talking about the process of iterating within the development process, though what that means may be a little fuzzy. In the tasklist altseven sample app, I have been slowly building more complexity into the application over a period of time to demonstrate how the altseven framework has been evolving. You can go to the repos for both projects and see the snapshots (as tags) at each step along the way. When I think of iterative development within a single version, what I am referring to is building in passes to get to a pre-defined end state. Version development (which you can see more clearly in the building of altseven) involves building new features with each successive pass.

Iteration as Exploration

Not too long ago, Kyle Simpson (@getify of You Don't Know JavaScript fame) pondered about having a tool for realtime execution of JavaScript - browser-based - other than the browser console. I took on the challenge to build something useful as quickly as possible. With only the barest of specs, I built a very simple mechanism to execute JavaScript from a Web page. Over a few iterations, I slowly built it into something that, while still very much a prototype, more fully meets the initial functional requirements that Kyle was looking for. You can see it for yourself at https://github.com/robertdmunn/livesandbox. It is still very much a prototype, but it has features that make it useful if you need a simple scratchpad for JavaScript code.

Iteration Within a Single Task

Even within individual version development projects, you may have isolated tasks that benefit from an iterative process. Recently, I completed a two year consulting project that involved converting large chunks of a twenty-ish year old codebase into a new framework in the same language (CFML). If you've never taken on a project like that, you might immediately think about writing some sort of parser to read in the old code and generate output code in the new framework. While that might work in certain projects, in this particular project I felt like there was no payoff for trying to write a proper parser for old CFML. Instead, I used an iterative process where I slowly ported individual pieces of code into the new framework, tested that they worked, and made successive passes at the code until I had ported the entire chunk of functionality.

One aspect of this particular task involved porting tag-based CFML code to cfscript, the ECMA-compliant script version of CFML. I have found that a series of passes using regular expressions inside a text editor/IDE can be used to convert a lot of CFML code to cfscript with very little hassle. Because of the nature of the old codebase, this approach made far more sense than trying to write a very complex parser to read in the old code base and try to output something useful for the new framework.

 

In Conclusion

I hope that I have helped you understand, in at least some minimal detail, both the motivations and the strategies behind iterative development. Going into more detail requires digging into code and showing real world examples, and might require a book length discussion to provide useful insight into the details of the process.


Livesandbox - in-browser JavaScript IDE

JavaScript, Open Source

Based on my proof of concept for live JavaScript execution, I've built a slightly more functional version and released it at https://github.com/robertdmunn/livesandbox. It runs by opening the local file so you don't need a web server running to access it.

This app is still very much a prototype, but it allows you to write JavaScript in the browser using the open source CodeMirror plugin, the same plugin used in dev tools in Chrome, Firefox, and Safari, among other places. I am planning on putting the functionality into a web app to enable more advanced functionality such as importing external libraries.

Meanwhile, if you would like a scratch pad for executing JavaScript, including writing output to a browser window, take a look at it. It is released under the MIT license, so do with it as you please.


The Altseven View Component and the Rendering Queue in 3.2.x

altseven, JavaScript, NodeJS, Open Source

As of altseven 3.2.x, I have made some changes to the way view components listen for changes and register for rendering with the render queue. The first changes come in the config() function inside the View component. The bubbling of mustRender events from child to parent has been removed. The render queue now tracks what components are being rendered and ensures that parent views are rendered before their children.

As a result, the setState() function in the View component now fires the mustRender event for all views, and the mustRender handler add the view to the queue.

setState: function( args ){
    this.state = args;
    // setting state requires a re-render
    this.fireEvent( 'mustRender' );
},

and the mustRender event handler, which now queues views for rendering:

this.on( "mustRender", function(){
    a7.ui.enqueueForRender( this.props.id );
}.bind( this ));

 

Essentially, the complexity of managing the rendering queue has largely been moved from the View component to the a7.ui component. Let's look at the enqueueForRender method. As with other methods in components in altseven, enqueueForRender references an internal component method, _enqueueForRender:

_enqueueForRender = function( id ){
  if( ! _stateTransition ){
    a7.log.info( 'enqueue: ' + id );
    if( ! _queue.length ){
      a7.log.trace( 'add first view to queue: ' + id );
      _queue.push( id );
      // wait for other possible updates and then process the queue
      setTimeout( _processRenderQueue, 18 );
    }else{
      let childIds = _getChildViewIds( id );
      if( _views[ id ].props.parentID === undefined ){
        // if the view is a root view, it should be pushed to the front of the stack
        a7.log.trace( 'add to front of queue: ' + id );
        _queue.unshift( id );
      }else{
        let parentIds = _getParentViewIds( id );

        let highParent = undefined;
        if( parentIds.length ){
          highParent = parentIds.find( function( parentId ){
            return _queue.indexOf( parentId ) >= 0;
          });
        }

        // only add if there is no parent in the queue, since parents will render children
        if( highParent === undefined ){

          a7.log.trace( 'add to end of queue: ' + id );
          _queue.push( id );
        }
      }

      // remove child views from the queue, they will be rendered by the parents
      childIds.forEach( function( childId ){
        if( _queue.indexOf( childId ) >= 0 ){
          a7.log.trace( 'remove child from queue: ' + childId );
          _queue.splice( _queue.indexOf( childId ), 1 );
        }
      });
    }
  }else{
    _deferred.push( id );
  }
},

First, let's see what variables we're using, and what they are doing. We have _stateTransition, which is a boolean value that tracks whether the current queue is rendering. If the queue is not rendering, the process will look to add the requested view to the queue, which is held in an array of string IDs in a variable called _queue. If the current queue is rendering, the view ID is instead added to another Array called _deferred. Once the current queue is rendered, _queue will be emptied and the IDs in _deferred will be added to _queue.

Next we have childIds, which holds an array of IDs of all child views of the current view being processed. The function uses this array to remove any child views of the current view from the rendering queue. Since parents render their own children by default using the rendered event handler, we don't want the children in the render queue or they will be rendered more than once.

We also have parentIds, which as you might expect holds an array of view IDs for the parents of the current view being processed, and highParent, which is the highest parent view in the chain of parentIds. We use these values in conjunction to verify that we do not add views to the queue if the view has a parent already in the queue. As with childIds, we only want to add the highest level view in a given subtree to the queue; we'll leave child view rendering to the rendered event handler.

_getChildViewIds and _getParentViewIds are functions that the enqueueForRender function calls to return these child and parent view ID arrays. Like much of the newest functionality in altseven, these functions do their jobs, but they are not optimized or expected to be particularly efficient. I don't expect deep nesting of view components in altseven apps, so I don't see optimization as a particular priority in this case.

As you can see at the beginning of the function, if the _queue.length property is 0, the function adds the view ID as the first element of _queue and then schedules the queued to be processed using setTimeout(). It leaves just enough time ( 18 ms ) for related views to register themselves for rendering as needed.

Processing the Rendering Queue

Let's look at _processRenderQueue.

    _processRenderQueue = function(){
      a7.log.trace( 'processing the queue' );
      _stateTransition = true;

      _queue.forEach( function( id ){
          _views[ id ].render();
      });
      _queue = [];
      _stateTransition = false;
      _deferred.forEach( function( id ){
        _enqueueForRender( id );
      });
      _deferred = [];
    },

Once the setTimeout function fires _processRenderQueue sets _stateTransition to true, which signals to _enqueueForRender that it should queue requested updates in the _deferred queue. It then iterates through _queue and calls the render() function for the given view ID in _views. What is significant here is that the array of views in _views is the original array that was registered by a7.ui.register(). Altseven works by registering all the views in the application, which places the views in this _views array for the duration of the application. Views are always referenced by this variable, which can be called outside the a7.ui component using the property a7.ui.views. Unlike early iterations of the framework, altseven 3.2.x does not pass views around or attempt to copy them. Once they are in a7.ui.views, that's where they stay until they are destroyed.

 

 


Categories


Recent Entries

Entries Search