Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
Merge 740c0ef into 2511dca
Browse files Browse the repository at this point in the history
  • Loading branch information
wtrocki committed Nov 15, 2017
2 parents 2511dca + 740c0ef commit 9309a3c
Show file tree
Hide file tree
Showing 59 changed files with 1,667 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,5 @@ docs/

npm-shrinkwrap.json
package-lock.json

.vscode/
6 changes: 6 additions & 0 deletions client/camera/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# generated code
src/**/*.js
src/**/*.map
test/**/*.js
test/**/*.map
coverage_report/
1 change: 1 addition & 0 deletions client/camera/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/
3 changes: 3 additions & 0 deletions client/camera/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# RainCatcher Camera Plugin

Simple wrapper around the [Cordova Camera Plugin](https://github.com/apache/cordova-plugin-camera) that uses the File Store client.
58 changes: 58 additions & 0 deletions client/camera/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"name": "@raincatcher/camera",
"version": "1.1.0-alpha.f71975b7",
"description": "RainCatcher Camera Plugin",
"types": "src/index.ts",
"author": "feedhenry-raincatcher@redhat.com",
"license": "Apache-2.0",
"main": "src/",
"scripts": {
"clean": "del coverage_report src/**/*.js src/**/*.map test/**/*.js test/**/*.map",
"build": "tsc",
"test": "nyc mocha"
},
"publishConfig": {
"access": "public"
},
"nyc": {
"include": [
"src/**/*.ts"
],
"extension": [
".ts"
],
"require": [
"ts-node/register"
],
"reporter": [
"lcov",
"text"
],
"report-dir": "coverage_report",
"lines": 75,
"functions": 100,
"branches": 80
},
"devDependencies": {
"@types/cordova-plugin-camera": "0.0.3",
"@types/lodash": "^4.14.73",
"@types/mocha": "^2.2.41",
"@types/proxyquire": "^1.3.27",
"del-cli": "^1.1.0",
"mocha": "^4.0.1",
"nyc": "^11.1.0",
"proxyquire": "^1.8.0",
"source-map-support": "^0.5.0",
"ts-node": "^3.3.0",
"typescript": "^2.5.0",
"sinon": "^4.0.1",
"@types/sinon": "^4.0.0",
"@types/chai": "^4.0.3",
"chai": "^4.1.1",
"@types/chai-as-promised": "7.1.0",
"chai-as-promised": "^7.1.1"
},
"dependencies": {
"b64-to-blob": "^1.2.19"
}
}
74 changes: 74 additions & 0 deletions client/camera/src/Camera.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
'use strict';

import * as Promise from 'bluebird';
import * as _ from 'lodash';

import { buildCameraOptions } from './buildCameraOptions';

declare var window;

/**
* Defines response for camera capture
*/
export interface CaptureResponse {
type: 'base64' | 'uri';
value: string;
}

type optionsBuilderFn = (camera: any) => CameraOptions;

export class Camera {
public options: CameraOptions;
public initPromise: Promise<CameraOptions>;

constructor(optionsBuilderFunction?: optionsBuilderFn) {
this.init(optionsBuilderFunction);
}

public init(optionsFn?: optionsBuilderFn): Promise<CameraOptions> {
return this.initPromise = new Promise((resolve, reject) => {
if (window.cordova) {
document.addEventListener('deviceready', function() {
if (!window.navigator.camera) {
return reject(new Error('This module requires the Cordova Camera plugin to be available'));
}
return resolve();
}, false);
} else {
resolve();
}
}).then(() => {
let options = buildCameraOptions(navigator.camera);
if (_.isFunction(optionsFn)) {
const userOptions = optionsFn(navigator.camera);
options = _.merge(options, userOptions);
}
// assign options object to self for convenience
this.options = options;
return options;
});
}

public cleanup(): Promise<void> {
const cleanup = window.navigator.camera.cleanup;
return this.initPromise.then(() =>
new Promise((resolve, reject) => cleanup(resolve, reject)));
}

public capture(): Promise<CaptureResponse> {
const getPicture = window.navigator.camera.getPicture;
const self = this;
return this.initPromise.then((cameraOptions) =>
new Promise<string>((resolve, reject) => getPicture(resolve, reject, cameraOptions)))
.then(uri => new Promise<CaptureResponse>((resolve, reject) => window.resolveLocalFileSystemURL(uri, function() {
return resolve({ value: uri, type: 'uri' });
}, function onFileSystemURIError() {
// Can be a base64 string when running in a browser, resolveLocalFileSystemURL will fail
// in this case, send value as dataURI
const mimeType = self.options.mediaType === window.navigator.camera.EncodingType.JPEG ?
'image/jpg' : 'image/png';
resolve({ value: `data:${mimeType};base64,${uri}`, type: 'base64' });
}))
);
}
}
21 changes: 21 additions & 0 deletions client/camera/src/buildCameraOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Default options for the cordova camera plugin
* @param cordovaCamera Apache Cordova's Camera object
*/
export function buildCameraOptions(cordovaCamera): CameraOptions {
// try to access global camera object if none provided
cordovaCamera = cordovaCamera || navigator.camera;
const options: CameraOptions = {
// Some common settings are 20, 50, and 100
'quality': 20,
'destinationType': cordovaCamera.DestinationType.FILE_URI,
// In this app, dynamically set the picture source, Camera or photo gallery
'sourceType': cordovaCamera.PictureSourceType.CAMERA,
'encodingType': cordovaCamera.EncodingType.JPEG,
'mediaType': cordovaCamera.MediaType.PICTURE,
'allowEdit': false,
'correctOrientation': true // corrects Android orientation quirks
};

return options;
}
1 change: 1 addition & 0 deletions client/camera/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Camera';
57 changes: 57 additions & 0 deletions client/camera/test/Camera-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as Promise from 'bluebird';
import { expect } from 'chai';
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
import * as sinon from 'sinon';
import { buildCameraOptions } from '../src/buildCameraOptions';
import { Camera } from '../src/Camera';
import { mockCordovaCamera } from './mocks/camera';
import { resolveLocalFileSystemURL } from './mocks/file';

declare var global: any;

chai.use(chaiAsPromised);

describe('Camera', function() {
const subject = new Camera(function() {
return { quality: 80 };
});

describe('init', function() {
it('should take a function to partially supply options', function() {
return expect(subject.initPromise).to.eventually.have.property('quality', 80);
});
});
describe('cleanup', function() {
it('should call the cordova cleanup function', function() {
return subject.cleanup().then(function() {
sinon.assert.called(mockCordovaCamera.cleanup);
});
});
});
describe('capture', function() {
it('return a local uri when successful', function() {
return subject.capture().then(result => {
expect(result).to.deep.equal({
type: 'uri',
value: 'some-uri'
});
sinon.assert.called(resolveLocalFileSystemURL);
});
});

it('should return a base64 data-uri when not a local file', function() {
// replace cordova file function to call error callback
const failingResolveLocalFileSystemURL = sinon.stub().callsArg(2);
global.window.resolveLocalFileSystemURL = failingResolveLocalFileSystemURL;

return subject.capture().then(result => {
sinon.assert.called(failingResolveLocalFileSystemURL);
expect(result).to.deep.equal({
value: 'data:image/jpg;base64,some-uri',
type: 'base64'
});
});
});
});
});
17 changes: 17 additions & 0 deletions client/camera/test/buildCameraOptions-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { expect } from 'chai';
import { buildCameraOptions } from '../src/buildCameraOptions';
import { mockCordovaCamera } from './mocks/camera';

describe('buildCameraOptions', function() {
it('should accept a given camera object', function() {
return expect(buildCameraOptions(mockCordovaCamera)).to.be.ok;
});
it('should return a configuration object', function() {
const opts = buildCameraOptions(mockCordovaCamera);
expect(opts).to.have.property('quality');
expect(opts).to.have.property('sourceType');
expect(opts).to.have.property('destinationType');
expect(opts).to.have.property('encodingType');
expect(opts).to.have.property('mediaType');
});
});
1 change: 1 addition & 0 deletions client/camera/test/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="mocha" />
3 changes: 3 additions & 0 deletions client/camera/test/mocha.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--compilers ts:ts-node/register
--require source-map-support/register
test/**.ts
27 changes: 27 additions & 0 deletions client/camera/test/mocks/camera.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { stub } from 'sinon';
export const mockCordovaCamera = {
// properties
DestinationType: {
FILE_URI: 1
},
EncodingType: {
JPEG: 1
},
PictureSourceType: {
CAMERA: 1
},
MediaType: {
PICTURE: 1
},
// methods
cleanup: stub().callsArgAsync(0),
getPicture: stub().callsArgWithAsync(0, 'some-uri')
};

declare var global: any;
global.window = global.window || {};
global.navigator = global.navigator || {};
global.window.navigator = global.navigator;

global.window.camera = mockCordovaCamera;
global.navigator.camera = mockCordovaCamera;
7 changes: 7 additions & 0 deletions client/camera/test/mocks/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { stub } from 'sinon';
declare var global: any;

export const resolveLocalFileSystemURL = stub().callsArgAsync(1);

global.window = global.window || {};
global.window.resolveLocalFileSystemURL = resolveLocalFileSystemURL;
14 changes: 14 additions & 0 deletions client/camera/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"experimentalDecorators": true,
"strictNullChecks": true,
"sourceMap": true
},
"include": [
"src/",
"test/"
]
}
2 changes: 1 addition & 1 deletion client/datasync-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@types/lodash": "^4.14.73",
"@types/mocha": "^2.2.41",
"@types/proxyquire": "^1.3.27",
"@types/sinon": "^2.3.3",
"@types/sinon": "^4.0.0",
"assert": "^1.4.1",
"browserify": "^14.4.0",
"browserify-shim": "^3.8.14",
Expand Down
6 changes: 6 additions & 0 deletions client/filestore-client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# generated code
src/**/*.js
src/**/*.map
test/**/*.js
test/**/*.map
coverage_report/
1 change: 1 addition & 0 deletions client/filestore-client/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/
25 changes: 25 additions & 0 deletions client/filestore-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# RainCatcher FileStore client

RainCatcher FileStore Client provides a manager which provides the support for:
- Downloading files from a server.
- Uploading files from a mobile device to a server.

## Usage
1. Implement the [HttpClient](./src/HttpClient.ts) Interface

2. Import FileManager
```javascript
var FileManager = require('@raincatcher/filestore-client').FileManager;
...
var fileManager = new FileManager(serverUrl, fileQueueName, httpClient);
```

3. Use the FileManager for uploading/downloading files to and from the server.
```javascript
fileManager.scheduleFileToBeUploaded(fileQueueEntry);
fileManager.scheduleFileToBeDownloaded(fileQueueEntry);
```
- Ensure the fileQueueEntry adheres to the [FileQueueEntry](./src/FileQueueEntry.ts) interface.

## HttpClient Interface
The [HttpClient](./src/HttpClient.ts) interface should be implemented in order to enable the FileStore client to make network requests for uploading and downloading files to and from a server.
Loading

0 comments on commit 9309a3c

Please sign in to comment.