Developing Angular2 Dart Asset Services, Part 3
Continued from Part 2
This article continues an effort to externalize content assets for a fictitious app. In Part 1 and Part 2, we developed an external HTML content repository and an Angular service to retrieve these assets. But our fictive scenario requires that we include not only external HTML but photo assets as well. In this article, we’ll provide that support in a similar strategy as was done for HTML content.
I’ll demonstrate how, relying on Dart and specifically Dart Angular’s strengths, we can easily automate much of the tedium of dealing with photo assets, including license compliance and converting raw images to production web assets.
Photo Service Interface
Just as with our HTML content provider, our interface of a Photo provider is simple:
getPhoto method expects a PhotoId, which is simple container:
and returns a Future Photo:
Image License Compliance
We know our app will need to use external images, but we also understand that most images are provided under license which may come with obligations on our part. Commonly authors must be attributed or licenses linked. Our app must abide by these rules, and therefore the image asset provider must supply this information to our app.
Photo class above contains an
Attribution, which dictates how attribution should be handled:
Note that information about the specific license is not included. Our app does not particularly care what the license is, only how any specific photo must be attributed. Later in the article, we’ll handle the translation of specific licenses into attribution details further down the stack (in fact, external to this app).
Client-based Photo Service
Our photo provider implementation needs to provide a Photo, meaning our implementation must determine the photo URL and attribution details. Starting with the URL part, we implement a simple solution:
Following the logic in
getPhoto, we are simply constructing a URL based on the provided photo identifier and category. There’s no need to physically fetch anything, since a web browser is very capable of fetching external image resources. We simply provide a URL and rely on our asset repository to conform to this structure.
We will have to fetch the licensing information via network request, however. We dictate a convention that our asset source include a JSON license file, with a
.license extension, for each photo. The format of the JSON is proscribed per the following example:
With this convention defined, we update the
ClientPhotoService implementation to retrieve this information and instantiate the correct attribution details:
The implementation of
_getPhotoAttribution is similar to the
ClientContentService implementation of
getContent discussed in Part 2. We fetch a remote file, in this case the JSON license file, using an injected Client. Instead of sanitizing response as we did for HTML content, we simply decode the JSON and assign
Attribution fields parameters from the decoded data.
Our app is now free to inject and use this photo asset provider. Our app will decide exactly how to properly attribute photos based on the simple Attribution instructions provided from the service.
An External Photo Repository
While technically we’ve completed our obligations to our app, we don’t actually have any photo assets to show or test with. We can construct alternate providers for use in testing (there are a few in the repo), but we can also make our own photo repo for use with
ClientPhotoService. However, resizing and cropping photos and hand-writing JSON certainly isn’t our style, so what can an impatient Dart author do?
Recall in Part 2 we built a HTML content repo that would allow copywriters to author in Markdown. Our content repo, with some custom transformers, would automatically convert these markdown files into production-ready HTML. We’ll use a similar approach here, allowing our photographers to simply store raw images and specify basic licensing info. Our repo will take care of the work of transforming these into production-ready assets.
To start, we create a new repo and define our photo assets with all pertinent info in a yaml file
assets/image/section_photo.yaml. An excerpt:
Here we’ve described two input photo assets, along with our their desired output name and any pertinent licensing info.
We now define the licenses used above, including the necessary attribution requirements for each. Example:
There are additional licenses and some helpers, such as a
LicenseFactory, that I omit here for clarity. See source for more detail.
Finally, we create a Dart bin script to generate our production assets and license JSON from the above yaml. Our script will loop through each entry in the yaml, for each performing cropping/scaling/resizing using the ImageMagic convert binary and writing the JSON license file.
The example above is fairly simple, but the script could be updated to apply effects, watermark images, modify image metadata, etc.
Now, if we place source images in
assets/photo/section and update our
section_photos.yaml accordingly, then when we run
pub bin/gen_section_photos our processed images and JSON license info will be deposited into the
web/content/images/section directory, just like our photo asset provider expects.
We can then
pub serve this repo for development use or, for production, simply copy our generated assets to a static web server.
In these three articles, I’ve illustrated how relying on the strengths of Angular Dart and Dart in general can greatly boost productivity and flexibility.
Dart and Angular Dart’s features, including dependency injection, futures, transformers, and robust web-centric libraries make web development fun again.
Originally published at ilikerobots.github.io on February 13, 2017.