Skip to content

Commit

Permalink
ESLint
Browse files Browse the repository at this point in the history
  • Loading branch information
boonya committed Feb 3, 2021
1 parent aa16c10 commit cbdbea6
Show file tree
Hide file tree
Showing 24 changed files with 2,498 additions and 150 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 120

[*.md]
indent_style = space

[*.yml]
indent_style = space
indent_size = 2
Expand Down
1 change: 0 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
.meteor/
build/
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module.exports = {
extends: [
'bluedrop',
'bluedrop/config/node',
'bluedrop/config/babel',
// 'bluedrop/config/babel',
],
globals: {
NODE_ENV: true,
Expand All @@ -19,7 +19,7 @@ module.exports = {
settings: {
'import/resolver': 'meteor',
react: {
version: '16.3',
version: '17.0',
},
},
rules: {
Expand Down
8 changes: 8 additions & 0 deletions client/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
env: {
browser: true,
},
extends: [
'bluedrop/config/react',
],
};
8 changes: 8 additions & 0 deletions client/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {App} from '../imports/ui/App';
import {Meteor} from 'meteor/meteor';
import React from 'react';
import {render} from 'react-dom';

Meteor.startup(() => {
render(<App />, document.getElementById('react-target'));
});
8 changes: 0 additions & 8 deletions client/main.jsx

This file was deleted.

33 changes: 21 additions & 12 deletions imports/api/camera.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Mongo } from 'meteor/mongo';
import { Discovery, Cam } from 'onvif';
import {CAMERA_STATE} from '../constants';
import {logError} from '../utils/logger';
import {Mongo} from 'meteor/mongo';
import {Discovery, Cam} from 'onvif';

const Collection = new Mongo.Collection('camera');

Expand All @@ -9,12 +10,17 @@ export default Collection;
export function discover() {
return new Promise((resolve, reject) => {
try {
// eslint-disable-next-line promise/prefer-await-to-callbacks
Discovery.probe((err, cams) => {
if (err) throw new Error(err);
if (err) {
logError('Failed to discover.')(err);
reject(err);
}
resolve(cams);
});
} catch (error) {
console.error(error);
}
catch (error) {
logError('Failed to discover.')(error);
reject(error);
}
});
Expand Down Expand Up @@ -43,20 +49,23 @@ export const toggle = (recorder) => (_id) => {
export function getStream(hostname, port = '8899', username = 'admin', password = '') {
return new Promise((resolve, reject) => {
try {
new Cam({hostname, port, username, password}, function(err) {
if (err) {
reject(err);
// eslint-disable-next-line no-new
new Cam({hostname, port, username, password}, function (camError) {
if (camError) {
reject(camError);
return;
}
this.getStreamUri({protocol: 'RTSP'}, (err, stream) => {
if (err) {
reject(err);
// eslint-disable-next-line no-invalid-this
this.getStreamUri({protocol: 'RTSP'}, (getStreamError, stream) => {
if (getStreamError) {
reject(getStreamError);
return;
}
resolve(stream);
});
});
} catch (error) {
}
catch (error) {
reject(error);
}
});
Expand Down
67 changes: 27 additions & 40 deletions imports/api/recorder.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import {EventEmitter} from 'events';
import RtspRecorder, {RecorderEvents} from 'rtsp-video-recorder';
import {getStream} from './camera';
import {RECORDER} from '../config';
import {CAMERA_STATE} from '../constants';
import {logInfo, logError} from '../utils/logger';
import {getStream} from './camera';
import {EventEmitter} from 'events';
import RtspRecorder, {RecorderEvents} from 'rtsp-video-recorder';

const log = (event) => (...args) => {
console.log(new Date().toString());
console.log(`Event "${event}": `, ...args);
console.log();
logInfo(`Event "${event}" \nat ${new Date().toString()}:`)(...args);
};

export const Events = {
INIT: 'init',
INITIALIZED: 'initialized',

START: 'start',
STARTED: 'started',

STOP: 'stopp',
STOP: 'stop',
STOPPED: 'stopped',
};

Expand All @@ -38,21 +35,24 @@ export default class Recorder {
}
}
catch (err) {
console.error(err);
return;
logError('Camera failed to initialize.')({_id, title, hostname, err});
}
});
}

_createRecorder(uri, title) {
_createRecorder(_id, uri, title) {
const recorder = new RtspRecorder(uri, RECORDER.FOLDER, {
title,
filePattern: title && `${title.replace(/%/g, '%%').replace(/ /g, '_')}/%Y.%m.%d/%H.%M.%S`,
filePattern: title && `${title.replace(/%/ug, '%%').replace(/ /ug, '_')}/%Y.%m.%d/%H.%M.%S`,
segmentTime: RECORDER.SEGMENT_TIME,
dirSizeThreshold: RECORDER.DIR_SIZE_THRESHOLD,
autoClear: RECORDER.AUTO_CLEAR,
});

recorder
.on(RecorderEvents.STARTED, (...args) => this.eventEmitter.emit(Events.STARTED, _id, ...args))
.on(RecorderEvents.STOPPED, (...args) => this.eventEmitter.emit(Events.STOPPED, _id, ...args));

recorder
.on(RecorderEvents.STARTED, log(RecorderEvents.STARTED))
.on(RecorderEvents.STOPPED, log(RecorderEvents.STOPPED))
Expand All @@ -69,51 +69,38 @@ export default class Recorder {

async init(_id, title, hostname, port, username, password) {
const {uri} = await getStream(hostname, port, username, password);
const recorder = this._createRecorder(uri, title);
recorder
.on(RecorderEvents.STARTED, (...args) => this.eventEmitter.emit(Events.STARTED, _id, ...args))
.on(RecorderEvents.STOPPED, (...args) => this.eventEmitter.emit(Events.STOPPED, _id, ...args));
const recorder = this._createRecorder(_id, uri, title);
this.process.set(_id, recorder);
return recorder;
}

start(_id) {
try {
const recorder = this.process.get(_id);
if (recorder.isRecording()) {
return;
}
recorder.start();
this.process.set(_id, recorder);
}
catch (err) {
console.log({process: this.process, _id});
throw err;
const recorder = this.process.get(_id);
if (recorder.isRecording()) {
return;
}
recorder.start();
this.process.set(_id, recorder);
}

stop(_id) {
try {
const recorder = this.process.get(_id);
if (!recorder.isRecording()) {
return;
}
recorder.stop();
this.process.set(_id, recorder);
}
catch (err) {
console.log({process: this.process, _id});
throw err;
const recorder = this.process.get(_id);
if (!recorder.isRecording()) {
return;
}
recorder.stop();
this.process.set(_id, recorder);
}

// eslint-disable-next-line promise/prefer-await-to-callbacks
on(eventType, callback) {
this.eventEmitter.on(eventType, callback);
return this;
}

// eslint-disable-next-line promise/prefer-await-to-callbacks
removeListener(eventType, callback) {
this.eventEmitter.removeListener(eventType, callback);
return this;
}
};
}
20 changes: 15 additions & 5 deletions imports/config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import ENV from './env';
import {
RECORDER_FOLDER,
RECORDER_SEGMENT_TIME,
RECORDER_DIR_SIZE_THRESHOLD,
RECORDER_AUTO_CLEAR,
LOGGING,
} from './env';

export const RECORDER = {
FOLDER: ENV.RECORDER_FOLDER,
SEGMENT_TIME: ENV.RECORDER_SEGMENT_TIME || undefined,
DIR_SIZE_THRESHOLD: ENV.RECORDER_DIR_SIZE_THRESHOLD || undefined,
AUTO_CLEAR: ENV.RECORDER_AUTO_CLEAR === 'true',
FOLDER: RECORDER_FOLDER,
SEGMENT_TIME: RECORDER_SEGMENT_TIME || undefined,
DIR_SIZE_THRESHOLD: RECORDER_DIR_SIZE_THRESHOLD || undefined,
AUTO_CLEAR: RECORDER_AUTO_CLEAR === 'true',
};

export const ENV = {
LOGGING: LOGGING === 'true',
}
4 changes: 3 additions & 1 deletion imports/env.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export default {
export const {
RECORDER_FOLDER,
RECORDER_SEGMENT_TIME,
RECORDER_DIR_SIZE_THRESHOLD,
RECORDER_AUTO_CLEAR,
LOGGING,
// eslint-disable-next-line node/no-process-env
} = process.env;
8 changes: 8 additions & 0 deletions imports/ui/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
env: {
browser: true,
},
extends: [
'bluedrop/config/react',
],
};
4 changes: 2 additions & 2 deletions imports/ui/App.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import List from './List';
import Discover from './Discover';
import List from './List';
import React from 'react';

export function App() {
return (
Expand Down
19 changes: 17 additions & 2 deletions imports/ui/Discover/Content.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import Item from './Item';
import PropTypes from 'prop-types';
import React from 'react';

export default function Content({pending, processing, error, list, added}) {
if (pending) {
Expand All @@ -11,7 +12,7 @@ export default function Content({pending, processing, error, list, added}) {
}

if (error) {
return <pre>{JSON.stringify(error, null, "\t")}</pre>;
return <pre>{JSON.stringify(error, null, '\t')}</pre>;
}

if (list.length === 0) {
Expand All @@ -24,3 +25,17 @@ export default function Content({pending, processing, error, list, added}) {
</ul>
);
}

Content.propTypes = {
added: PropTypes.arrayOf(PropTypes.string).isRequired,
error: PropTypes.instanceOf(Error),
list: PropTypes.arrayOf(PropTypes.shape({hostname: PropTypes.string.isRequired})).isRequired,
pending: PropTypes.bool,
processing: PropTypes.bool,
};

Content.defaultProps = {
error: undefined,
pending: false,
processing: false,
};
24 changes: 19 additions & 5 deletions imports/ui/Discover/Item.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react'
import METHODS from '../../methods';
import {logError} from '../../utils/logger';
import PropTypes from 'prop-types';
import React from 'react';

export default function Item({hostname, port, path, uri, added}) {
const [processing, setProcessing] = React.useState(false);
Expand All @@ -8,21 +10,33 @@ export default function Item({hostname, port, path, uri, added}) {
e.preventDefault();
const title = e.target.elements.title.value.trim() || hostname;
setProcessing(true);
// eslint-disable-next-line promise/prefer-await-to-callbacks
Meteor.call(METHODS.CAMERA_CREATE, title, hostname, port, path, uri, (err) => {
if (err) console.error(err);
if (err) { logError('Failed to create camera.')(err); }
setProcessing(false);
});
}, []);
}, [hostname, path, port, uri]);

return (
<form onSubmit={handleAdd}>
{hostname}{' / '}
{added ? 'added' : 'not added'}{' / '}
<button type="submit" disabled={processing || added}>Add</button>{' / '}
<label>
Title:
<input type="text" name="title" placeholder={hostname} disabled={processing || added} />
Title: <input type="text" name="title" placeholder={hostname} disabled={processing || added} />
</label>
</form>
);
}

Item.propTypes = {
added: PropTypes.bool,
hostname: PropTypes.string.isRequired,
path: PropTypes.string.isRequired,
port: PropTypes.string.isRequired,
uri: PropTypes.object.isRequired,
};

Item.defaultProps = {
added: false,
};
Loading

0 comments on commit cbdbea6

Please sign in to comment.