-
Notifications
You must be signed in to change notification settings - Fork 2
Frontend architecture
The UI of Concert is fairly complex, which is why steps have been taken to ensure that the code is very modular, extensible, and maintainable. Backbone.js powers all of the UI, and thus the components of the interface have been separated into an MVC architecture to follow Backbone.js conventions.
The basic entities that comprise the UI architecture in Concert are Models
, Pages
, Panels
, Widgets
, and Components
. Here is how they are related graphically:
Overview of UI Entities Diagram (full size).
The basic philosophy behind the interaction of these components is as follows:
The Page
is the central "controller" for the UI. It handles incoming URLs, and throws events which contain all the models necessary for any UI component to deal with a new URL. Panels
and Components
watch these events and change their appearance/functionality appropriately. Widgets
are UI entities which are bound to model instances, so they are typically just watching a model instance for changes.
The Models
on the Frontend are fairly straightforward, except for seenInstances
. In order to ensure that no model instances are duplicated, we maintain a seenInstances
object which contains the instances of every model instance we have come across. Before any model is instantiated, seenInstances
is checked first to see if there is already an instance, and if so, we use that one instead of creating it again. Hopefully we can devise a better solution in the future, backbone-atlas is looking promising.
Here are the different types of Models
we represent on the Frontend:
Model class hierarchy (full size).
The Page
object is the first object to be instantiated on load. This is a Backbone.Controller
subclass that will handle all incoming routes appropriately.
The Page
does not "ensure" that the UI is maintained, but instead ensures that the proper events are thrown and the proper data is sent with these events. This allows for the UI components to manage themselves.
We utilize Backbone's route
method to provide a URL for any repeatable action such as selecting an AudioSegment
. Any entity that is the starting point for functionality must notify the Page
(either by simply changing the URL or calling a method directly) and no other entities.
For example, when an AudioFile
is selected in the AudioListPanel
, all the Widget
is doing is changing the URL (i.e. a link). From there, the Page
will handle this "route" change and throw a route:collection_audio_segment
event which will contain the relevant models (selected AudioSegment
object, etc.).
Panels
are divided sections on the UI that serve a particular purpose, such as displaying a list of AudioFileWidgets
and AudioSegmentWidgets
or displaying a waveform. These classes watch the Page
for route changes, and change state accordingly. When initialized, a Panel
will create Components
and depending on which state the Panel
is in, will render lists of Widgets
linked to model instances.
Widgets
are small sections of the user interface, usually contained within Panels
. Widgets
are data-driven, and for this reason are typically duplicated many times. A Widget
is bound to a model instance, and subscribes to that instance for changes.
A Component
is a member of a Panel
, much like a Widget
, but is not data driven, and is instead something like a playhead, which will typically not be duplicated. The Component
will likely subscribe the page for changes, much like the Panel
does.
When a user is logged in, they are directed to the "Collections" listing where they will see the list of collections they are a member of. From there, the user can navigate to any functionality of the application without reloading the page. Below is a diagram that shows basic relationships between the Page
, Panel
, Widget
and Component
instances on the UI. It is a work in progress ;)
UI classes (full size)