Note: This is a work in progress.
Shopping List is a series of Offline First demo apps, each built using a different stack. These demo apps cover Progressive Web Apps, hybrid mobile apps, native mobile apps, and desktop apps.
The Shopping List demo apps are brought to you by:
These demo apps will each serve multiple purposes:
Shopping List is a simple demo app, with a limited feature set. Here is a list of features written as user stories grouped by Epic:
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-vanillajs-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-polymer-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-react-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-preact-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-vuejs-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-emberjs-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-react-native-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-react-native-cloudant-sync
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-ionic-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-ionic-cloudant-sync
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-cordova-pouchdb
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-cordova-cloudant-sync
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-swift-cloudant-sync
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-kotlin-cloudant-sync
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-electron-pouchdb
Implementations of the Shopping List demo app share a data model. This allows the demo apps to be interoperable with one another. For example, a user could plan a shopping trip with a desktop app built using Electron and PouchDB. The same user could then use a native app built using Kotlin and Cloudant Sync while shopping for groceries. Much of the design of this data model is inspired by the CouchDB Best Practices collection from eHealth Africa.
{
"_id": "list:cj6mj1zfj000001n1ugjfkj33",
"type": "list",
"version": 1,
"title": "Groceries",
"checked": false,
"place": {
"title": "Healthy Living",
"license": "Data © OpenStreetMap contributors, ODbL 1.0. http://www.openstreetmap.org/copyright",
"lat": "44.46282415",
"lon": "-73.1799710198028",
"address": {
"supermarket": "Healthy Living",
"road": "Dorset Street",
"city": "South Burlington",
"county": "Chittenden County",
"state": "Vermont",
"postcode": "05406",
"country": "United States of America",
"countryCode": "us"
}
},
"createdAt": "2017-08-21T18:40:00.000Z",
"updatedAt": "2017-08-21T18:40:00.000Z"
}
Notes:
_id
: Unique identifier for the document. Generated from the following values, separated by colons:
list
).type
: Document type (will always have a value of list
for a shopping list).version
: Document schema version.title
: User-generated title for the shopping list.checked
: Has this shopping list been fully checked off?place
: Associates the shopping list with a geolocation. Derived from OpenStreetMap's Nominatim search tool. The example above is derived from the following search:
http://nominatim.openstreetmap.org/search/Healthy%20Living%20Vermont?format=json&addressdetails=1&namedetails=1
createdAt
: Date and time at which the document was created. Expressed as a simplified extended ISO format in zero UTC offset (which can be generated in JavaScript with new Date().toISOString()
).updatedAt
: Date and time at which the document was last updated. Expressed as a simplified extended ISO format in zero UTC offset.{
"_id": "item:cj6mn7e36000001p9n14fgk6s",
"type": "item",
"version": 1,
"list": "list:cj6mj1zfj000001n1ugjfkj33",
"title": "Mangos",
"checked": false,
"createdAt": "2017-08-21T18:43:00.000Z",
"updatedAt": "2017-08-21T18:43:00.000Z"
}
Notes:
_id
: Unique identifier for the document. Generated from the following values, separated by colons:
item
).type
: Document type (will always have a value of item
for a shopping list item).version
: Document schema version.list
: The unique identifier of the parent shopping listtitle
: User-generated title for the shopping list item.checked
: Has this shopping list item been checked off?createdAt
: Date and time at which the document was created. Expressed as a simplified extended ISO format in zero UTC offset (which can be generated in JavaScript with new Date().toISOString()
).updatedAt
: Date and time at which the document was last updated. Expressed as a simplified extended ISO format in zero UTC offset.Here is an example of a Mango / pouchdb-find
/ Cloudant Query selector that fetches a single shopping list's items:
{
"selector": {
"type": "item",
"list": "list:cj6mj1zfj000001n1ugjfkj33"
}
}
Note that the above query can also be used to get a count of items within a shopping list by simply using the Array.length
property (or equivalent) and accounting for the shopping list document being included in the results. Since PouchDB just runs every reduce function in memory, there is no benefit to using a _count
reduce function when using PouchDB. The Cloudant Sync libraries for iOS and Android do not support map/reduce (but do support Cloudant Query / Mango).
A geolocation context is used to notify the user when the geolocation capability of their device has indicated that they are near a place associated with a shopping list. This provides the user with quick access to the shopping list for their current geographic context.
{
"_id": "geo:drguywpyxp4t:cj6mn7e36000001p1q02dlz5q",
"type": "geo",
"list": "list:cj6mj1zfj000001n1ugjfkj33",
"version": 1,
"notified": false,
"createdAt": "2017-08-21T18:57:00.000Z",
"updatedAt": "2017-08-21T18:57:00.000Z"
}
Notes:
_id
: Unique identifier for the document. Generated from the following values, separated by colons:
geo
).place.lat
and place.lon
values from the associated shopping list at a precision of 12 (which can be generated in JavaScript using the latlon-geohash
module).type
: Document type (will always have a value of geo
for a geolocation context item).list
: The unique identifier of the parent shopping listversion
: Document schema version.notified
: Has a notification already been sent for this geolocation context? Note that the geolocation context document may be deleted after a notification has been sent and the corresponding shopping list has been fully checked off.createdAt
: Date and time at which the document was created. Expressed as a simplified extended ISO format in zero UTC offset (which can be generated in JavaScript with new Date().toISOString()
).updatedAt
: Date and time at which the document was last updated. Expressed as a simplified extended ISO format in zero UTC offset.Here is an example of a Mango / pouchdb-find
/ Cloudant Query selector that utilizes the built-in _all_docs
view to query for geolocation contexts near the current geolocation coordinates of the device (the value drguyw
below is the geohash of the user's location at a precision of 6, or ±0.61 km):
{
"selector": {
"_id": {
"$gte": "geo:drguyw",
"$lte": "geo:drguyw\uffff"
}
}
}
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-model-js
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-model-swift
GitHub Repository:
https://github.com/ibm-watson-data-lab/shopping-list-model-kotlin
General guidelines:
Implementations:
See the templates
directory for templates that can be used for each demo app implementation. This includes the following files:
LICENSE
README.md