diff --git a/admin/src/App.js b/admin/src/App.js index 89f2dc0..b5d5fb9 100644 --- a/admin/src/App.js +++ b/admin/src/App.js @@ -3,6 +3,7 @@ import { Route, NavLink } from 'react-router-dom' import ProtectedRoute from './components/common/protected-route' import AuthPage from './routes/auth' import AdminPage from './routes/admin' +import EventListPage from './routes/event-list' class App extends Component { render() { @@ -18,7 +19,13 @@ class App extends Component { auth +
+ + events + +
+ ) diff --git a/admin/src/components/event/event-list.js b/admin/src/components/event/event-list.js new file mode 100644 index 0000000..e8deff6 --- /dev/null +++ b/admin/src/components/event/event-list.js @@ -0,0 +1,47 @@ +import React, { Component } from 'react' +import { connect } from 'react-redux' +import { eventSelector, getListEvent } from '../../ducks/event' +import Event from './event' + +class EventList extends Component { + static propTypes = {} + + componentDidMount() { + this.props.getListEvent() + } + + render() { + const { loaded, error, loading } = this.props.event + if (loading) { + return ( +
+

Загрузка...

+
+ ) + } else if (error) { + return ( +
+

Произошла ошибка

+
+ ) + } else if (loaded) { + return ( +
+ {this.props.eventList.map((event) => ( + + ))} +
+ ) + } + + return null + } +} + +export default connect( + (state) => ({ + eventList: eventSelector(state), + event: state.event + }), + { getListEvent } +)(EventList) diff --git a/admin/src/components/event/event.js b/admin/src/components/event/event.js new file mode 100644 index 0000000..4c00ea6 --- /dev/null +++ b/admin/src/components/event/event.js @@ -0,0 +1,31 @@ +import React, { Component } from 'react' + +export default class Event extends Component { + render() { + const { + title, + url, + where, + when, + month, + submissionDeadline + } = this.props.event + return ( +
+

{title}

+

+ + {url} + +

+

{where}

+

{when}

+

{month}

+

{submissionDeadline}

+
+
+
+
+ ) + } +} diff --git a/admin/src/config.js b/admin/src/config.js index aa22b3b..0e4cb41 100644 --- a/admin/src/config.js +++ b/admin/src/config.js @@ -2,15 +2,15 @@ import firebase from 'firebase/app' import 'firebase/auth' import 'firebase/database' -export const appName = 'advreact-10-05' +export const appName = 'react-advanced-nikolay' export const config = { - apiKey: 'AIzaSyCbMQM0eQUSQ0SuLVAu9ZNPUcm4rdbiB8U', + apiKey: 'AIzaSyAAwv7Zb7tJbu5VjbyI6O7kQ06nm4BAiIs', authDomain: `${appName}.firebaseapp.com`, databaseURL: `https://${appName}.firebaseio.com`, projectId: appName, - storageBucket: '', - messagingSenderId: '1094825197832' + storageBucket: `${appName}.appspot.com`, + messagingSenderId: '806752161129' } firebase.initializeApp(config) diff --git a/admin/src/ducks/auth.js b/admin/src/ducks/auth.js index 55ae8d0..f0579be 100644 --- a/admin/src/ducks/auth.js +++ b/admin/src/ducks/auth.js @@ -77,7 +77,7 @@ export function signIn(email, password) { */ export function* signUpSaga({ payload: { email, password } }) { - const auth = firebase.auth() + const auth = yield call(firebase.auth) try { const user = yield call( [auth, auth.createUserWithEmailAndPassword], @@ -97,7 +97,7 @@ export function* signInSaga() { payload: { email, password } } = yield take(SIGN_IN_REQUEST) - const auth = firebase.auth() + const auth = yield call(firebase.auth) try { const user = yield apply(auth, auth.signInWithEmailAndPassword, [ diff --git a/admin/src/ducks/auth.test.js b/admin/src/ducks/auth.test.js new file mode 100644 index 0000000..16cf40b --- /dev/null +++ b/admin/src/ducks/auth.test.js @@ -0,0 +1,122 @@ +import { put, apply, call, take } from 'redux-saga/effects' +import firebase from 'firebase/app' +import { + signInSaga, + signUpSaga, + SIGN_IN_SUCCESS, + SIGN_IN_REQUEST, + SIGN_IN_ERROR, + SIGN_IN_REQUESTS_LIMIT, + SIGN_UP_REQUEST, + SIGN_UP_SUCCESS, + SIGN_UP_ERROR +} from './auth' + +describe('people auth', () => { + // Удачный логин + it('should sign-in', () => { + const data = { email: 'test@mail.ru', password: '12345678' } + + const sagaProcess = signInSaga({ + type: SIGN_IN_REQUEST, + payload: data + }) + + expect(sagaProcess.next().value).toEqual(take(SIGN_IN_REQUEST)) + + // НЕ понятно зачем передавать {payload: data}. И как это вообще работает + expect(sagaProcess.next({ payload: data }).value).toEqual( + call(firebase.auth) + ) + + const auth = firebase.auth() + + // НЕ понятно зачем передавать auth. И как это вообще работает. + expect(sagaProcess.next(auth).value).toEqual( + apply(auth, auth.signInWithEmailAndPassword, [data.email, data.password]) + ) + + const user = apply(auth, auth.signInWithEmailAndPassword, [ + data.email, + data.password + ]) + + expect(sagaProcess.next(user).value).toEqual( + put({ type: SIGN_IN_SUCCESS, payload: { user } }) + ) + }) + + // Limit по авторизации + it('should sign-in limit', () => { + const data = { email: 'test@mail.ru', password: '123456' } + + const sagaProcess = signInSaga({ + type: SIGN_IN_REQUEST, + payload: data + }) + + for (let i = 3; i > 0; i--) { + expect(sagaProcess.next().value).toEqual(take(SIGN_IN_REQUEST)) + + // НЕ понятно зачем передавать {payload: data}. И как это вообще работает + expect(sagaProcess.next({ payload: data }).value).toEqual( + call(firebase.auth) + ) + + const auth = firebase.auth() + + // НЕ понятно зачем передавать auth. И как это вообще работает. + expect(sagaProcess.next(auth).value).toEqual( + apply(auth, auth.signInWithEmailAndPassword, [ + data.email, + data.password + ]) + ) + + const user = apply(auth, auth.signInWithEmailAndPassword, [ + data.email, + data.password + ]) + + sagaProcess.next() + } + + expect(sagaProcess.next().value).toEqual( + put({ type: SIGN_IN_REQUESTS_LIMIT }) + ) + }) + + // Удачное добавление нового пользователя + it('should sign-up', () => { + const data = { email: 'test1@mail.ru', password: '12345678' } + + const sagaProcess = signUpSaga({ + type: SIGN_UP_REQUEST, + payload: data + }) + + // НЕ понятно зачем передавать {payload: data}. И как это вообще работает + expect(sagaProcess.next({ payload: data }).value).toEqual( + call(firebase.auth) + ) + + const auth = firebase.auth() + + // НЕ понятно зачем передавать auth. И как это вообще работает. + expect(sagaProcess.next(auth).value).toEqual( + apply(auth, auth.createUserWithEmailAndPassword, [ + data.email, + data.password + ]) + ) + + const user = apply(auth, auth.createUserWithEmailAndPassword, [ + data.email, + data.password + ]) + + expect(sagaProcess.next(user).value).toEqual( + put({ type: SIGN_UP_SUCCESS, payload: { user } }) + ) + }) +}) diff --git a/admin/src/ducks/event.js b/admin/src/ducks/event.js new file mode 100644 index 0000000..d66b8f9 --- /dev/null +++ b/admin/src/ducks/event.js @@ -0,0 +1,99 @@ +import { appName } from '../config' +import { Record, List } from 'immutable' +import { createSelector } from 'reselect' +import { takeEvery, all, put } from 'redux-saga/effects' +import firebase from 'firebase/app' + +/** + * Constants + * */ +export const moduleName = 'event' +const prefix = `${appName}/${moduleName}` +export const GET_LIST_REQUEST = `${prefix}/GET_LIST_REQUEST` +export const GET_LIST_FAIL = `${prefix}/GET_LIST_FAIL` +export const GET_LIST_SUCCESS = `${prefix}/GET_LIST_SUCCESS` + +/** + * Reducer + * */ +const ReducerState = Record({ + entities: new List([]), + loading: false, + loaded: false, + error: null +}) + +const EventRecord = Record({ + id: null, + month: '', + submissionDeadline: '', + title: '', + url: '', + when: '', + where: '' +}) + +export default function reducer(state = new ReducerState(), action) { + const { type, payload, error } = action + + switch (type) { + case GET_LIST_REQUEST: + return state.set('loading', true) + case GET_LIST_FAIL: + return state.set('loading', false).set('error', error) + case GET_LIST_SUCCESS: + const eventList = Object.keys(payload.list).map((key) => ({ + id: key, + ...payload.list[key] + })) + return state + .set( + 'entities', + new List(eventList.map((item) => new EventRecord(item))) + ) + .set('loading', false) + .set('loaded', true) + .set('error', null) + default: + return state + } +} +/** + * Selectors + * */ + +export const stateSelector = (state) => state[moduleName] +export const eventSelector = createSelector(stateSelector, (state) => { + return state.entities.valueSeq().toArray() +}) + +/** + * Action Creators + * */ + +export function getListEvent() { + return { + type: GET_LIST_REQUEST, + payload: {} + } +} + +/** + * Sagas + * */ + +export function* getEventListSaga() { + try { + const eventsRef = yield firebase.database().ref('/events') + + const events = yield eventsRef.once('value') + + yield put({ type: GET_LIST_SUCCESS, payload: { list: events.val() } }) + } catch (error) { + yield put({ type: GET_LIST_FAIL, error }) + } +} + +export function* saga() { + yield all([takeEvery(GET_LIST_REQUEST, getEventListSaga)]) +} diff --git a/admin/src/redux/reducer.js b/admin/src/redux/reducer.js index f9c1879..82e8fb3 100644 --- a/admin/src/redux/reducer.js +++ b/admin/src/redux/reducer.js @@ -3,10 +3,12 @@ import { routerReducer as router } from 'react-router-redux' import { reducer as form } from 'redux-form' import authReducer, { moduleName as authModule } from '../ducks/auth' import peopleReducer, { moduleName as peopleModule } from '../ducks/people' +import eventReducer, { moduleName as eventModule } from '../ducks/event' export default combineReducers({ router, form, [authModule]: authReducer, - [peopleModule]: peopleReducer + [peopleModule]: peopleReducer, + [eventModule]: eventReducer }) diff --git a/admin/src/redux/saga.js b/admin/src/redux/saga.js index 8f1e0cd..33203a6 100644 --- a/admin/src/redux/saga.js +++ b/admin/src/redux/saga.js @@ -1,7 +1,8 @@ import { all } from 'redux-saga/effects' import { saga as authSaga } from '../ducks/auth' import { saga as peopleSaga } from '../ducks/people' +import { saga as eventSaga } from '../ducks/event' export default function*() { - yield all([authSaga(), peopleSaga()]) + yield all([authSaga(), peopleSaga(), eventSaga()]) } diff --git a/admin/src/routes/event-list.js b/admin/src/routes/event-list.js new file mode 100644 index 0000000..63e63af --- /dev/null +++ b/admin/src/routes/event-list.js @@ -0,0 +1,15 @@ +import React, { Component } from 'react' +import EventList from '../components/event/event-list' + +export default class EventListPage extends Component { + static propTypes = {} + + render() { + return ( +
+

Events

+ +
+ ) + } +} diff --git a/admin/yarn.lock b/admin/yarn.lock index 1517b7e..6d7c5e3 100644 --- a/admin/yarn.lock +++ b/admin/yarn.lock @@ -496,7 +496,7 @@ babel-code-frame@6.26.0, babel-code-frame@^6.11.0, babel-code-frame@^6.22.0, bab esutils "^2.0.2" js-tokens "^3.0.2" -babel-core@6.26.0: +babel-core@6.26.0, babel-core@^6.0.0, babel-core@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" dependencies: @@ -520,30 +520,6 @@ babel-core@6.26.0: slash "^1.0.0" source-map "^0.5.6" -babel-core@^6.0.0, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - babel-eslint@7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.2.3.tgz#b2fe2d80126470f5c19442dc757253a897710827" @@ -1817,7 +1793,7 @@ content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" -convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1: +convert-source-map@^1.4.0, convert-source-map@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" @@ -1833,7 +1809,7 @@ copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" -core-js@2.5.5: +core-js@2.5.5, core-js@^2.4.0, core-js@^2.5.0: version "2.5.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.5.tgz#b14dde936c640c0579a6b50cabcc132dd6127e3b" @@ -1841,10 +1817,6 @@ core-js@^1.0.0: version "1.2.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" -core-js@^2.4.0, core-js@^2.5.0: - version "2.5.6" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.6.tgz#0fe6d45bf3cac3ac364a9d72de7576f4eb221b9d" - core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2886,14 +2858,10 @@ extract-text-webpack-plugin@3.0.2: schema-utils "^0.3.0" webpack-sources "^1.0.1" -extsprintf@1.3.0: +extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" @@ -5126,7 +5094,7 @@ minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: +minimist@0.0.8, minimist@~0.0.1: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" @@ -5134,10 +5102,6 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - minipass@^2.2.1, minipass@^2.2.4: version "2.3.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.0.tgz#2e11b1c46df7fe7f1afbe9a490280add21ffe384" @@ -5482,18 +5446,12 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -opn@5.2.0: +opn@5.2.0, opn@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225" dependencies: is-wsl "^1.1.0" -opn@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" - dependencies: - is-wsl "^1.1.0" - optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -6118,7 +6076,7 @@ pretty-format@^22.4.3: ansi-regex "^3.0.0" ansi-styles "^3.2.0" -private@^0.1.6, private@^0.1.7, private@^0.1.8: +private@^0.1.6, private@^0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -6212,14 +6170,10 @@ q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" -qs@6.5.1: +qs@6.5.1, qs@~6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" -qs@~6.5.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -6667,7 +6621,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" -request@2.83.0: +request@2.83.0, request@^2.79.0, request@^2.83.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" dependencies: @@ -6694,59 +6648,6 @@ request@2.83.0: tunnel-agent "^0.6.0" uuid "^3.1.0" -request@^2.79.0: - version "2.85.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@^2.83.0: - version "2.86.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.86.0.tgz#2b9497f449b0a32654c081a5cf426bbfb5bf5b69" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -6811,18 +6712,12 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@1.6.0: +resolve@1.6.0, resolve@^1.3.2, resolve@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.6.0.tgz#0fbd21278b27b4004481c395349e7aba60a9ff5c" dependencies: path-parse "^1.0.5" -resolve@^1.3.2, resolve@^1.5.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" - dependencies: - path-parse "^1.0.5" - restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -6886,11 +6781,11 @@ rxjs@^5.4.2: dependencies: symbol-observable "1.0.1" -safe-buffer@5.1.1: +safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -7269,11 +7164,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - -statuses@~1.4.0: +"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2", statuses@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" @@ -8109,14 +8000,10 @@ window-size@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" -wordwrap@0.0.2: +wordwrap@0.0.2, wordwrap@~0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..fb57ccd --- /dev/null +++ b/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + +