[Improvement] Move to create-react-app (#17, #15)

This commit is contained in:
Qolzam
2018-02-04 11:19:18 +07:00
parent 5875f97685
commit 36f77ba99d
91 changed files with 26204 additions and 720 deletions

View File

@@ -1,12 +0,0 @@
{
"plugins": [
"react-hot-loader/babel",
"transform-decorators-legacy",
"transform-runtime"
],
"presets": [
["env", { "modules": false }],
"react",
"stage-0"
]
}

View File

@@ -1,35 +0,0 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
},
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"indent": [
"error",
"tab"
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"never"
]
}
}

28
.gitignore vendored
View File

@@ -1,7 +1,25 @@
node_modules/
public/bundle*.js
config/
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.vscode/
src/data/awsClient
src/components/AWS.tsx
npm-debug.log
src/components/AWS.tsx

View File

@@ -1,11 +1,7 @@
{
"hosting": {
"public": "public",
"public": "build",
"rewrites": [
{
"source": "/bundle-v0.4.js",
"destination": "/bundle-v0.4.js"
},
{
"source": "/favicon.ico",
"destination": "/favicon.ico"

View File

@@ -1,27 +0,0 @@
var webpackConfig = require('./webpack.config.js');
module.exports = function (config) {
config.set({
browsers: ['Chrome'],
browserNoActivityTimeout: 100000,
singleRun: true,
frameworks: ['mocha'],
files: [
'node_modules/jquery/dist/jquery.min.js',
'app/tests/**/*.test.jsx'
],
preprocessors: {
'app/tests/**/*.test.jsx': ['webpack', 'sourcemap']
},
reporters: ['mocha'],
client: {
mocha: {
timeout: '5000'
}
},
webpack: webpackConfig,
webpackServer: {
noInfo: true
}
});
};

16403
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,30 +3,29 @@
"version": "1.0.0",
"description": "Simple react socail app",
"main": "index.js",
"private": true,
"scripts": {
"test": "NODE_ENV=test karma start",
"build": "NODE_ENV=production webpack -p",
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start-js": "react-scripts-ts start",
"start": "npm-run-all -p watch-css start-js",
"build-js": "react-scripts-ts build",
"build": "npm-run-all build-css build-js",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject",
"watch": "webpack -w",
"deploy:firebase": "npm run build && firebase deploy",
"start": "node server.js"
"deploy:firebase": "npm run build && firebase deploy"
},
"author": "Amir Movahedi",
"license": "MIT",
"dependencies": {
"@types/react-hot-loader": "^3.0.5",
"@types/react-infinite-scroller": "^1.0.4",
"amazon-cognito-identity-js": "^1.21.0",
"aws-sdk": "^2.132.0",
"axios": "^0.16.2",
"babel-runtime": "^6.26.0",
"classnames": "^2.2.5",
"copy-to-clipboard": "^3.0.8",
"crypto-js": "^3.1.9-1",
"css-loader": "^0.28.0",
"deep-freeze-strict": "^1.1.1",
"expect": "^1.20.2",
"express": "^4.15.2",
"faker": "^4.1.0",
"file-loader": "^0.11.1",
"firebase": "^4.6.2",
"install": "^0.10.2",
"inversify": "^4.6.0",
@@ -36,16 +35,15 @@
"material-ui-icons": "^1.0.0-beta.17",
"moment": "^2.18.1",
"morgan": "^1.8.1",
"node-env-file": "^0.1.8",
"node-sass": "^4.5.2",
"node-sass-chokidar": "0.0.3",
"npm": "^5.6.0",
"npm-run-all": "^4.1.2",
"prop-types": "^15.6.0",
"react": "^16.2.0",
"react-addons-test-utils": "^15.6.2",
"react-avatar-editor": "^10.3.0",
"react-dom": "^16.0.0",
"react-dom": "^16.2.0",
"react-event-listener": "^0.5.1",
"react-hot-loader": "^3.1.3",
"react-infinite-scroller": "^1.1.2",
"react-linkify": "^0.2.1",
"react-parallax": "^1.4.4",
@@ -53,28 +51,26 @@
"react-router": "^4.1.1 ",
"react-router-dom": "^4.1.1",
"react-router-redux": "^5.0.0-alpha.6",
"react-scripts-ts": "2.13.0",
"react-string-replace": "^0.4.0",
"react-tap-event-plugin": "^3.0.2",
"redux": "^3.7.2",
"redux-actions": "^2.0.3",
"redux-thunk": "^2.2.0",
"reflect-metadata": "^0.1.10",
"sass-loader": "^6.0.3",
"save": "^2.3.0",
"script-loader": "^0.7.0",
"style-loader": "^0.16.1",
"typeface-roboto": "0.0.50",
"url-loader": "^0.5.8",
"uuid": "^3.0.1"
},
"devDependencies": {
"@types/react-infinite-scroller": "^1.0.4",
"@types/classnames": "^2.2.3",
"@types/lodash": "^4.14.77",
"@types/moment": "^2.13.0",
"@types/node": "^8.0.33",
"@types/jest": "^22.1.1",
"@types/node": "^9.4.0",
"@types/prop-types": "^15.5.2",
"@types/react": "^16.0.35",
"@types/react-dom": "^16.0.1",
"@types/react": "^16.0.36",
"@types/react-dom": "^16.0.3",
"@types/react-event-listener": "^0.4.4",
"@types/react-redux": "^5.0.10",
"@types/react-router-dom": "^4.0.8",
@@ -82,38 +78,15 @@
"@types/react-tap-event-plugin": "0.0.30",
"@types/redux-logger": "^3.0.4",
"@types/uuid": "^3.4.3",
"@types/webpack": "^3.0.13",
"babel-core": "^6.24.1",
"babel-loader": "^7.1.2",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"css-loader": "^0.28.7",
"eslint": "^4.9.0",
"karma": "^1.6.0",
"karma-chrome-launcher": "^2.0.0",
"karma-mocha": "^1.3.0",
"karma-mocha-reporter": "^2.2.3",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.3",
"mocha": "^3.2.0",
"open-browser-webpack-plugin": "0.0.5",
"redux-logger": "^3.0.1",
"redux-mock-store": "^1.2.3",
"source-map-loader": "^0.2.2",
"ts-loader": "^2.3.7",
"typescript": "^2.7.1",
"ts-node": "^3.3.0",
"tslint": "^5.7.0",
"tslint-config-standard": "^6.0.1",
"typescript": "^2.5.3",
"webpack": "^3.6.0",
"webpack-hot-middleware": "^2.20.0"
"tslint-config-standard": "^6.0.1"
},
"engines": {
"node": "7.3.0",
"npm": "3.10.10"
"node": "8.9.4",
"npm": "5.6.0"
}
}

View File

@@ -121,8 +121,6 @@
</div>
</div>
<script src="/bundle-v0.5.2.js"></script>
</body>
</html>

View File

@@ -1,6 +1,5 @@
// - Import react components
import moment from 'moment'
import { push } from 'react-router-redux'
// -Import domain
@@ -21,32 +20,69 @@ import * as globalActions from 'actions/globalActions'
import { provider } from '../socialEngine'
import { SocialProviderTypes } from 'core/socialProviderTypes'
/* _____________ CRUD State _____________ */
/**
* Loing user
* @param {string} uids
*/
export const login = (uid: string, isVerifide: boolean) => {
return {
type: AuthorizeActionType.LOGIN,
payload: { authed: true, isVerifide, uid }
}
}
/**
* Logout user
*/
export const logout = () => {
return { type: AuthorizeActionType.LOGOUT }
}
/**
* User registeration call
* @param user for registering
*/
export const signup = (user: UserRegisterModel) => {
return {
type: AuthorizeActionType.SIGNUP,
payload: { ...user }
}
}
/**
* Update user's password
*/
export const updatePassword = () => {
return { type: AuthorizeActionType.UPDATE_PASSWORD }
}
/**
* Get service providers
*/
const authorizeService: IAuthorizeService = provider.get<IAuthorizeService>(SocialProviderTypes.AuthorizeService)
/* _____________ CRUD DB _____________ */
/* _____________ CRUD DB _____________ */
/**
* Log in user in server
* @param {string} email
* @param {string} password
*/
/**
* Log in user in server
*/
export const dbLogin = (email: string, password: string) => {
return (dispatch: any, getState: any) => {
dispatch(globalActions.showNotificationRequest())
return authorizeService.login(email, password).then((result) => {
dispatch(globalActions.showNotificationSuccess())
dispatch(login(result.uid,result.emailVerified))
dispatch(login(result.uid, result.emailVerified))
dispatch(push('/'))
}, (error: SocialError) => dispatch(globalActions.showErrorMessage(error.code)))
}
}
/**
* Log out user in server
*/
/**
* Log out user in server
*/
export const dbLogout = () => {
return (dispatch: any, getState: any) => {
return authorizeService.logout().then((result) => {
@@ -58,10 +94,30 @@ export const dbLogout = () => {
}
/**
*
* @param user for registering
*/
/**
* Send email verification
*/
export const dbSendEmailVerfication = () => {
return (dispatch: any, getState: any) => {
dispatch(globalActions.showNotificationRequest())
return authorizeService.sendEmailVerification().then(() => {
// Send email verification successful.
dispatch(globalActions.showNotificationSuccess())
dispatch(push('/'))
})
.catch((error: SocialError) => {
// An error happened.
dispatch(globalActions.showErrorMessage(error.code))
})
}
}
/**
*
* @param user for registering
*/
export const dbSignup = (user: UserRegisterModel) => {
return (dispatch: Function, getState: Function) => {
dispatch(globalActions.showNotificationRequest())
@@ -83,46 +139,46 @@ export const dbSignup = (user: UserRegisterModel) => {
}
/**
* Change user's password
* @param {string} newPassword
*/
/**
* Change user's password
* @param {string} newPassword
*/
export const dbUpdatePassword = (newPassword: string) => {
return (dispatch: any, getState: any) => {
dispatch(globalActions.showNotificationRequest())
return authorizeService.updatePassword(newPassword).then(() => {
// Update successful.
// Update successful.
dispatch(globalActions.showNotificationSuccess())
dispatch(updatePassword())
dispatch(push('/'))
})
.catch((error: SocialError) => {
// An error happened.
switch (error.code) {
case 'auth/requires-recent-login':
dispatch(globalActions.showErrorMessage(error.code))
dispatch(dbLogout())
break
default:
.catch((error: SocialError) => {
// An error happened.
switch (error.code) {
case 'auth/requires-recent-login':
dispatch(globalActions.showErrorMessage(error.code))
dispatch(dbLogout())
break
default:
}
})
}
})
}
}
/**
* Reset user's password
* @param {string} newPassword
*/
/**
* Reset user's password
* @param {string} newPassword
*/
export const dbResetPassword = (email: string) => {
return (dispatch: any, getState: any) => {
dispatch(globalActions.showNotificationRequest())
return authorizeService.resetPassword(email).then(() => {
// Reset password successful.
// Reset password successful.
dispatch(globalActions.showNotificationSuccess())
dispatch(push('/login'))
})
@@ -134,35 +190,15 @@ export const dbResetPassword = (email: string) => {
}
}
/**
* Send email verification
*/
export const dbSendEmailVerfication = () => {
return (dispatch: any, getState: any) => {
dispatch(globalActions.showNotificationRequest())
return authorizeService.sendEmailVerification().then(() => {
// Send email verification successful.
dispatch(globalActions.showNotificationSuccess())
dispatch(push('/'))
})
.catch((error: SocialError) => {
// An error happened.
dispatch(globalActions.showErrorMessage(error.code))
})
}
}
/**
* Login user with OAuth
*/
/**
* Login user with OAuth
*/
export const dbLoginWithOAuth = (type: OAuthType) => {
return (dispatch: any, getState: any) => {
dispatch(globalActions.showNotificationRequest())
return authorizeService.loginWithOAuth(type).then((result: LoginUser) => {
// Send email verification successful.
// Send email verification successful.
dispatch(globalActions.showNotificationSuccess())
dispatch(login(result.uid, true))
dispatch(push('/'))
@@ -174,42 +210,3 @@ export const dbLoginWithOAuth = (type: OAuthType) => {
})
}
}
/* _____________ CRUD State _____________ */
/**
* Loing user
* @param {string} uids
*/
export const login = (uid: string, isVerifide: boolean) => {
return {
type: AuthorizeActionType.LOGIN,
payload: { authed: true, isVerifide, uid }
}
}
/**
* Logout user
*/
export const logout = () => {
return { type: AuthorizeActionType.LOGOUT }
}
/**
* User registeration call
* @param user for registering
*/
export const signup = (user: UserRegisterModel) => {
return {
type: AuthorizeActionType.SIGNUP,
payload: { ...user }
}
}
/**
* Update user's password
*/
export const updatePassword = () => {
return { type: AuthorizeActionType.UPDATE_PASSWORD }
}

View File

@@ -1,22 +1,18 @@
// - Import domain
import { User, Profile } from 'core/domain/users'
import { User } from 'core/domain/users'
import { Circle, UserTie } from 'core/domain/circles'
import { SocialError } from 'core/domain/common'
// - Import utility components
import moment from 'moment'
import * as moment from 'moment/moment'
// - Import action types
import { CircleActionType } from 'constants/circleActionType'
// - Import actions
import * as globalActions from 'actions/globalActions'
import * as postActions from 'actions/postActions'
import * as userActions from 'actions/userActions'
import * as notifyActions from 'actions/notifyActions'
import * as serverActions from 'actions/serverActions'
import { IServiceProvider, ServiceProvide } from 'core/factories'
import { ICircleService } from 'core/services/circles'
import { SocialProviderTypes } from 'core/socialProviderTypes'
import { provider } from '../socialEngine'

View File

@@ -1,5 +1,5 @@
// - Import react components
import moment from 'moment'
import moment from 'moment/moment'
import _ from 'lodash'
// - Import domain
@@ -33,9 +33,6 @@ const commentService: ICommentService = provider.get<ICommentService>(SocialProv
/**
* Add comment to database
* @param {object} ownerPostUserId the identifier of the user who is the owner of the post which comment belong to
* @param {object} newComment user comment
* @param {function} callBack will be fired when server responsed
*/
export const dbAddComment = (ownerPostUserId: string, newComment: Comment, callBack: Function) => {
return (dispatch: any, getState: Function) => {
@@ -43,13 +40,13 @@ export const dbAddComment = (ownerPostUserId: string, newComment: Comment, callB
dispatch(globalActions.showTopLoading())
const state = getState()
let uid: string = getState().authorize.uid
let uid: string = state.authorize.uid
let comment: Comment = {
score : 0,
creationDate : moment().unix(),
userDisplayName : getState().user.info[uid].fullName,
userAvatar : getState().user.info[uid].avatar,
userDisplayName : state.user.info[uid].fullName,
userAvatar : state.user.info[uid].avatar,
userId : uid,
postId: newComment.postId,
text: newComment.text
@@ -102,7 +99,6 @@ export const dbGetComments = (ownerUserId: string, postId: string) => {
*/
dispatch(addCommentList(comments))
let commentsCount: number
const state = getState()
const post: Post = state.post.userPosts[ownerUserId][postId]
if (!post) {
return
@@ -131,18 +127,12 @@ export const dbGetComments = (ownerUserId: string, postId: string) => {
/**
* Update a comment from database
* @param {string} id of comment
* @param {string} postId is the identifier of the post which comment belong to
* @param {string} text is the text of comment
*/
export const dbUpdateComment = (comment: Comment) => {
return (dispatch: any, getState: Function) => {
delete comment.editorStatus
dispatch(globalActions.showTopLoading())
// Get current user id
let uid: string = getState().authorize.uid
return commentService.updateComment(comment)
.then(() => {
dispatch(updateComment( comment))
@@ -158,8 +148,6 @@ export const dbUpdateComment = (comment: Comment) => {
/**
* Delete a comment from database
* @param {string} id of comment
* @param {string} postId is the identifier of the post which comment belong to
*/
export const dbDeleteComment = (id?: string | null, postId?: string) => {
return (dispatch: any, getState: Function) => {
@@ -169,9 +157,6 @@ export const dbDeleteComment = (id?: string | null, postId?: string) => {
}
dispatch(globalActions.showTopLoading())
// Get current user id
let uid: string = getState().authorize.uid
return commentService.deleteComment(id!)
.then(() => {
dispatch(deleteComment(id!, postId!))
@@ -214,10 +199,7 @@ export const addComment = (comment: Comment) => {
}
/**
*
* @param id comment identifier
* @param postId post identefier which comment belong to
* @param text the new text for comment
* Update comment
*/
export const updateComment = ( comment: Comment) => {
@@ -241,8 +223,6 @@ export const addCommentList = (postComments: {[postId: string]: {[commentId: str
/**
* Delete a comment
* @param {string} id of comment
* @param {string} postId is the identifier of the post which comment belong to
*/
export const deleteComment = (id: string, postId: string) => {
return { type: CommentActionType.DELETE_COMMENT, payload: { id, postId } }

View File

@@ -2,9 +2,6 @@
import { GlobalActionType } from 'constants/globalActionType'
// - Import actions
import * as postActions from 'actions/postActions'
import * as commentActions from 'actions/commentActions'
import * as userActions from 'actions/userActions'
import * as serverActions from 'actions/serverActions'
import { ICommonService } from 'core/services/common/ICommonService'
@@ -23,8 +20,6 @@ const commonService: ICommonService = provider.get<ICommonService>(SocialProvide
/**
* Add a normal feed
* @param {any} newFeed
* @param {Function} callBack
*/
export let dbSendFeed = (newFeed: Feed) => {
return (dispatch: any, getState: Function) => {
@@ -52,8 +47,6 @@ export let dbSendFeed = (newFeed: Feed) => {
/**
* Progress change
* @param {string} percent
* @param {boolean} visible
*/
export const progressChange = (percent: number, visible: Boolean) => {
return {
@@ -257,29 +250,6 @@ export const loadDataGuest = () => {
}
/**
* Show error report dialog
*/
const showErrorReport = (message: string) => {
const appElement = document.getElementById('app')
const masterElement = document.getElementById('master')
const container = document.createElement('div')
const div = document.createElement('div')
div.innerHTML = message
container.style.position = '100000'
container.style.position = 'fixed'
container.style.backgroundColor = '#32c3e4b8'
container.style.width = '100%'
container.style.height = '100%'
container.style.display = 'flex'
container.style.alignItems = 'center'
container.style.alignItems = 'center'
container.style.flexDirection = 'row'
container.appendChild(div)
appElement!.insertBefore(container, masterElement)
}
/**
* Create send feedback serevr request model
*/

View File

@@ -1,6 +1,5 @@
import { IStorageService } from 'core/services/files'
// - Import react componetns
import moment from 'moment'
import moment from 'moment/moment'
// - Import domain
import { Image } from 'core/domain/imageGallery'
@@ -12,9 +11,6 @@ import { ImageGalleryActionType } from 'constants/imageGalleryActionType'
// - Import actions
import * as globalActions from 'actions/globalActions'
// - Import app API
import FileAPI from 'api/FileAPI'
import { IImageGalleryService } from 'core/services/imageGallery'
import { FileResult } from 'models/files/fileResult'
import { SocialProviderTypes } from 'core/socialProviderTypes'
@@ -24,7 +20,6 @@ import { provider } from '../socialEngine'
* Get service providers
*/
const imageGalleryService: IImageGalleryService = provider.get<IImageGalleryService>(SocialProviderTypes.ImageGalleryService)
const storageService: IStorageService = provider.get<IStorageService>(SocialProviderTypes.StorageService)
/* _____________ UI Actions _____________ */
@@ -52,8 +47,6 @@ export const dbGetImageGallery = () => {
/**
* Save image URL in the server
* @param {string} imageURL is the URL of image
* @param {string} imageFullPath is the folder name + / + file name
*/
export const dbSaveImage = (imageURL: string,imageFullPath: string) => {
return (dispatch: any, getState: Function) => {
@@ -104,8 +97,6 @@ export const dbDeleteImage = (id: string) => {
/**
* Upload image on the server
* @param {file} file
* @param {string} fileName
*/
export const dbUploadImage = (image: any, imageName: string) => {
return (dispatch: any, getState: Function) => {
@@ -137,10 +128,10 @@ export const dbDownloadImage = (fileName: string) => {
return {}
}
if (getState().imageGallery.imageURLList[fileName] && fileName !== '') {
return
return undefined
}
if (getState().imageGallery.imageRequests.indexOf(fileName) > -1) {
return
return undefined
}
dispatch(sendImageRequest(fileName))
@@ -213,5 +204,4 @@ export const sendImageRequest = (name: string) => {
payload: name
}
}
}

View File

@@ -1,5 +1,3 @@
// - Import react components
import moment from 'moment'
// - Import domain
import { Notification } from 'core/domain/notifications'
@@ -30,8 +28,6 @@ const notificationService: INotificationService = provider.get<INotificationServ
export const dbAddNotification = (newNotify: Notification) => {
return (dispatch: any, getState: Function) => {
let uid: string = getState().authorize.uid
let notify: Notification = {
isSeen: false,
description: newNotify.description,

View File

@@ -1,13 +1,9 @@
// - Import react components
import { Action } from 'redux'
// - Import domain
import { Post } from 'core/domain/posts'
import { Comment } from 'core/domain/comments'
import { SocialError } from 'core/domain/common'
// - Import utility components
import moment from 'moment'
import moment from 'moment/moment'
// - Import action types
import { PostActionType } from 'constants/postActionType'
@@ -28,8 +24,6 @@ const postService: IPostService = provider.get<IPostService>(SocialProviderTypes
/**
* Add a normal post
* @param {any} newPost
* @param {Function} callBack
*/
export let dbAddPost = (newPost: Post, callBack: Function) => {
return (dispatch: any, getState: Function) => {
@@ -71,8 +65,6 @@ export let dbAddPost = (newPost: Post, callBack: Function) => {
/**
* Add a post with image
* @param {object} newPost
* @param {function} callBack
*/
export const dbAddImagePost = (newPost: Post, callBack: Function) => {
return (dispatch: any, getState: Function) => {
@@ -118,15 +110,11 @@ export const dbAddImagePost = (newPost: Post, callBack: Function) => {
/**
* Update a post from database
* @param {object} newPost
* @param {func} callBack //TODO: anti pattern should change to parent state or move state to redux
*/
export const dbUpdatePost = (updatedPost: Post, callBack: Function) => {
return (dispatch: any, getState: Function) => {
dispatch(globalActions.showTopLoading())
// Get current user id
let uid: string = getState().authorize.uid
return postService.updatePost(updatedPost).then(() => {
@@ -178,7 +166,6 @@ export const dbGetPosts = (page: number = 0, limit: number = 10) => {
const {stream} = state.post
const lastPageRequest = stream.lastPageRequest
const lastPostId = stream.lastPostId
const hasMoreData = stream.hasMoreData
let uid: string = state.authorize.uid
if (uid && lastPageRequest !== page) {
@@ -224,7 +211,6 @@ export const dbGetPostsByUserId = (userId: string, page: number = 0, limit: numb
const {profile} = state.post
const lastPageRequest = profile[userId] ? profile[userId].lastPageRequest : -1
const lastPostId = profile[userId] ? profile[userId].lastPostId : ''
const hasMoreData = profile[userId] ? profile[userId].hasMoreData : true
let uid: string = state.authorize.uid
@@ -265,8 +251,6 @@ export const dbGetPostsByUserId = (userId: string, page: number = 0, limit: numb
/**
* Get all user posts from data base
* @param uid post owner identifier
* @param postId post identifier
*/
export const dbGetPostById = (uid: string, postId: string) => {
return (dispatch: any, getState: Function) => {
@@ -287,8 +271,6 @@ export const dbGetPostById = (uid: string, postId: string) => {
/**
* Add a normal post
* @param {string} uid is user identifier
* @param {Post} post
*/
export const addPost = (uid: string, post: Post) => {
return {
@@ -299,8 +281,6 @@ export const addPost = (uid: string, post: Post) => {
/**
* Update a post
* @param {string} uid is user identifier
* @param {Post} post
*/
export const updatePost = (post: Post) => {
return {
@@ -311,8 +291,6 @@ export const updatePost = (post: Post) => {
/**
* Delete a post
* @param {string} uid is user identifier
* @param {string} id is post identifier
*/
export const deletePost = (uid: string, id: string) => {
return {
@@ -323,8 +301,6 @@ export const deletePost = (uid: string, id: string) => {
/**
* Add a list of post
* @param {string} uid
* @param {[object]} posts
*/
export const addPosts = (userPosts: { [userId: string]: {[postId: string]: Post} }) => {
return {
@@ -395,7 +371,6 @@ export const lastPostStream = (lastPostId: string) => {
}
/**
* Set profile posts has more data to show
*/
@@ -437,4 +412,4 @@ export const lastPostProfile = (userId: string, lastPostId: string) => {
payload: { userId, lastPostId}
}
}
}

View File

@@ -1,12 +1,9 @@
import moment from 'moment'
// - Import action types
import { ServerActionType } from 'constants/serverActionType'
// - Import domain
// - Import actions
import * as globalActions from 'actions/globalActions'
import { ServerRequestModel } from 'models/server/serverRequestModel'
import { SocialError } from 'core/domain/common/socialError'

View File

@@ -1,6 +1,5 @@
// - Import react components
import { provider } from '../socialEngine'
import _ from 'lodash'
// - Import domain
import { Profile } from 'core/domain/users'
import { SocialError } from 'core/domain/common'
@@ -10,7 +9,6 @@ import { UserActionType } from 'constants/userActionType'
// - Import actions
import * as globalActions from 'actions/globalActions'
import * as userActions from 'actions/userActions'
import { IUserService } from 'core/services/users'
import { SocialProviderTypes } from 'core/socialProviderTypes'
@@ -47,8 +45,6 @@ export const dbGetUserInfo = () => {
/**
* Get user info from database
* @param {string} uid
* @param {string} callerKey
*/
export const dbGetUserInfoByUserId = (uid: string, callerKey: string) => {
return (dispatch: Function, getState: Function) => {
@@ -56,7 +52,7 @@ export const dbGetUserInfoByUserId = (uid: string, callerKey: string) => {
let caller = getState().global.temp.caller
if ( caller && caller.indexOf(`dbGetUserInfoByUserId-${uid}`) > -1) {
return
return undefined
}
dispatch(globalActions.temp({caller: `dbGetUserInfoByUserId-${uid}`}))
return userService.getUserProfile(uid).then((userProfile: Profile) => {
@@ -122,7 +118,6 @@ export const dbGetPeopleInfo = (page: number, limit: number) => {
const {people} = state.user
const lastPageRequest = people.lastPageRequest
const lastUserId = people.lastUserId
const hasMoreData = people.hasMoreData
let uid: string = state.authorize.uid
@@ -159,8 +154,6 @@ export const dbGetPeopleInfo = (page: number, limit: number) => {
/**
* Add user information
* @param {string} uid is the user identifier
* @param {Profile} info is the information about user
*/
export const addUserInfo = (uid: string, info: Profile) => {
return {
@@ -182,8 +175,6 @@ export const addPeopleInfo = (infoList: {[userId: string]: Profile}) => {
/**
* Update user information
* @param {string} uid is the user identifier
* @param {Profile} info is the information about user
*/
export const updateUserInfo = (uid: string, info: Profile) => {
return {

View File

@@ -1,4 +1,4 @@
import moment from 'moment'
import moment from 'moment/moment'
// - Import action types
import { VoteActionType } from 'constants/voteActionType'

View File

@@ -1,4 +1,4 @@
import * as moment from 'moment'
import * as moment from 'moment/moment'
/**
* Log the data
* @param title log title
@@ -7,7 +7,7 @@ import * as moment from 'moment'
const logger = (title: string, data: any) => {
const randomColor = getRandomColor()
console.log(`\n\n%c ======= ${title} ======= %c${moment().format('HH:mm:ss SSS')} \n`, `color:${getRandomColor()};font-size:15`
console.log(`\n\n%c ======= ${title} ======= %c${moment().format('HH:mm:ss SSS')} \n`, `color:${randomColor};font-size:15`
, `color:${getRandomColor()};font-size:15`, data,`\n\n =========================================`)
}

View File

@@ -1,19 +1,16 @@
// - Import react components
import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { push } from 'react-router-redux'
import { grey } from 'material-ui/colors'
import List, {
ListItem,
ListItemIcon,
ListItemSecondaryAction,
ListItemText,
ListSubheader
ListItemText
} from 'material-ui/List'
import SvgGroup from 'material-ui-icons/groupWork'
import SvgGroup from 'material-ui-icons/GroupWork'
import IconButton from 'material-ui/IconButton'
import MoreVertIcon from 'material-ui-icons/moreVert'
import MoreVertIcon from 'material-ui-icons/MoreVert'
import TextField from 'material-ui/TextField'
import { MenuList, MenuItem } from 'material-ui/Menu'
import { withStyles } from 'material-ui/styles'
@@ -31,7 +28,7 @@ import Dialog, {
import Divider from 'material-ui/Divider'
import Button from 'material-ui/Button'
import RaisedButton from 'material-ui/Button'
import SvgClose from 'material-ui-icons/close'
import SvgClose from 'material-ui-icons/Close'
import AppBar from 'material-ui/AppBar'
import Paper from 'material-ui/Paper'
import Collapse from 'material-ui/transitions/Collapse'
@@ -102,7 +99,7 @@ export class CircleComponent extends Component<ICircleComponentProps, ICircleCom
* Component constructor
* @param {object} props is an object properties of component
*/
constructor(props: ICircleComponentProps) {
constructor (props: ICircleComponentProps) {
super(props)
// Defaul state
@@ -229,7 +226,7 @@ export class CircleComponent extends Component<ICircleComponentProps, ICircleCom
* Reneder component DOM
* @return {react element} return the DOM which rendered by component
*/
render() {
render () {
const { circle, classes } = this.props
const { isMenuOpen } = this.state
@@ -242,7 +239,7 @@ export class CircleComponent extends Component<ICircleComponentProps, ICircleCom
<Manager>
<Target>
<IconButton
aria-owns={isMenuOpen! ? 'circle-menu' : null}
aria-owns={isMenuOpen! ? 'circle-menu' : ''}
aria-haspopup='true'
onClick={this.handleOpenMenu}
>
@@ -255,7 +252,7 @@ export class CircleComponent extends Component<ICircleComponentProps, ICircleCom
className={classNames({ [classes.popperClose]: !isMenuOpen }, { [classes.popperOpen]: isMenuOpen })}
>
<ClickAwayListener onClickAway={this.handleCloseMenu}>
<Grow in={isMenuOpen} id='circle-menu' style={{ transformOrigin: '0 0 0' }}>
<Grow in={isMenuOpen} style={{ transformOrigin: '0 0 0' }}>
<Paper>
<MenuList role='menu'>
<MenuItem onClick={this.handleDeleteCircle} > Delete circle </MenuItem>
@@ -300,7 +297,7 @@ export class CircleComponent extends Component<ICircleComponentProps, ICircleCom
</ListItemIcon>
<ListItemText inset primary={<span style={this.styles}>{this.props.circle.name}</span>} />
<ListItemSecondaryAction>
{ circle.isSystem ? null : rightIconMenu }
{circle.isSystem ? null : rightIconMenu}
</ListItemSecondaryAction>
</ListItem>
<Collapse component='li' in={this.state.open} timeout='auto' unmountOnExit>

View File

@@ -3,7 +3,7 @@ import React, { Component } from 'react'
import { connect } from 'react-redux'
import { NavLink } from 'react-router-dom'
import PropTypes from 'prop-types'
import moment from 'moment'
import moment from 'moment/moment'
import Linkify from 'react-linkify'
import { Comment } from 'core/domain/comments'
@@ -14,7 +14,7 @@ import Paper from 'material-ui/Paper'
import Button from 'material-ui/Button'
import { grey } from 'material-ui/colors'
import IconButton from 'material-ui/IconButton'
import MoreVertIcon from 'material-ui-icons/moreVert'
import MoreVertIcon from 'material-ui-icons/MoreVert'
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'
import Menu, { MenuList, MenuItem } from 'material-ui/Menu'
import TextField from 'material-ui/TextField'
@@ -167,11 +167,11 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
/**
* Comment text
*/
text: this.props.comment.text,
text: this.props.comment.text!,
/**
* Comment text to match edit with new comment that is edited
*/
initialText: this.props.comment.text,
initialText: this.props.comment.text!,
/**
* If comment text dosn't take any change it will be true
*/
@@ -212,7 +212,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
handleCancelEdit = (evt: any) => {
this.setState({
text: this.state.initialText
text: this.state.initialText!
})
this.props.closeEditor!()
}
@@ -303,7 +303,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
>
<Target>
<IconButton
aria-owns={openMenu! ? 'comment-menu' : null}
aria-owns={openMenu! ? 'comment-menu' : ''}
aria-haspopup='true'
onClick={this.handleCommentMenu}
>
@@ -316,7 +316,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
className={classNames({ [classes.popperClose]: !openMenu! }, { [classes.popperOpen]: openMenu! })}
>
<ClickAwayListener onClickAway={this.handleCloseCommentMenu}>
<Grow in={openMenu!} id='comment-menu' style={{ transformOrigin: '0 0 0' }}>
<Grow in={openMenu!} style={{ transformOrigin: '0 0 0' }}>
<Paper>
<MenuList role='menu'>
<MenuItem className={classes.rightIconMenuItem}>Reply</MenuItem>
@@ -426,4 +426,4 @@ const mapStateToProps = (state: any, ownProps: any) => {
}
// - Connect component to redux store
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(CommentComponent as any) as any)
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles as any)(CommentComponent as any) as any)

View File

@@ -54,7 +54,7 @@ export interface ICommentComponentProps {
*
* @memberof ICommentComponentProps
*/
delete?: (id?: string| null, postId?: string) => any
delete?: (id?: string | null, postId?: string) => any
/**
* Get user profile
@@ -98,6 +98,6 @@ export interface ICommentComponentProps {
/**
* Styles
*/
classes: any
classes?: any
}

View File

@@ -7,7 +7,7 @@ export interface ICommentComponentState {
* @type {string}
* @memberof ICommentComponentProps
*/
initialText?: string | null
initialText?: string
/**
* Initialt text comment

View File

@@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import _ from 'lodash'
import { NavLink } from 'react-router-dom'
import { connect } from 'react-redux'
import moment from 'moment'
import moment from 'moment/moment'
import Paper from 'material-ui/Paper'
import Button from 'material-ui/Button'
@@ -24,16 +24,16 @@ import classNames from 'classnames'
import * as commentActions from 'actions/commentActions'
// - Import app components
import CommentListComponent from 'components/CommentList'
import CommentListComponent from 'components/commentList'
import UserAvatar from 'components/userAvatar'
import { ICommentGroupComponentProps } from './ICommentGroupComponentProps'
import { ICommentGroupComponentState } from './ICommentGroupComponentState'
import { Comment } from 'core/domain/comments/comment'
import { ServerRequestModel } from 'models/server';
import StringAPI from 'api/StringAPI';
import { ServerRequestType } from 'constants/serverRequestType';
import { ServerRequestStatusType } from 'actions/serverRequestStatusType';
import { ServerRequestModel } from 'models/server'
import StringAPI from 'api/StringAPI'
import { ServerRequestType } from 'constants/serverRequestType'
import { ServerRequestStatusType } from 'actions/serverRequestStatusType'
const styles = (theme: any) => ({
textField: {
@@ -254,7 +254,7 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
<Card elevation={0}>
<CardHeader
className={classes.header}
title={ <Author />}
title={<Author />}
avatar={<UserAvatar fullName={commentFullName!} fileName={commentAvatar!} size={24} />}
subheader={commentBody}
>
@@ -278,7 +278,8 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
/**
* Comment list box
*/
const commentWriteBox = (<div>
const commentWriteBox = (
<div>
<Divider />
<Paper key={postId! + '-commentwrite'} elevation={0} className='animate2-top10'>
<Card elevation={0}>
@@ -313,7 +314,8 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
)
const showComments = ( comments && Object.keys(comments).length > 0
? (<Paper elevation={0} style={open ? { display: 'block', padding: '0px 0px' } : { display: 'none', padding: '12px 16px' }}>
? (
<Paper elevation={0} style={open ? { display: 'block', padding: '0px 0px' } : { display: 'none', padding: '12px 16px' }}>
<CommentListComponent comments={comments!} isPostOwner={this.props.isPostOwner} disableComments={this.props.disableComments} />
</Paper>)
: '')
@@ -391,4 +393,4 @@ const mapStateToProps = (state: any, ownProps: ICommentGroupComponentProps) => {
}
// - Connect component to redux store
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(CommentGroupComponent as any) as any)
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles as any)(CommentGroupComponent as any) as any)

View File

@@ -5,7 +5,7 @@ import PropTypes from 'prop-types'
import List, { ListItem, ListItemText } from 'material-ui/List'
// - Import app components
import CommentComponent from 'components/Comment'
import CommentComponent from 'components/comment'
import * as PostAPI from 'api/PostAPI'

View File

@@ -4,8 +4,8 @@ import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { grey } from 'material-ui/colors'
import IconButton from 'material-ui/IconButton'
import MoreVertIcon from 'material-ui-icons/moreVert'
import SvgCamera from 'material-ui-icons/photoCamera'
import MoreVertIcon from 'material-ui-icons/MoreVert'
import SvgCamera from 'material-ui-icons/PhotoCamera'
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'
import Menu, { MenuList, MenuItem } from 'material-ui/Menu'
import Button from 'material-ui/Button'

View File

@@ -59,5 +59,5 @@ export interface IEditProfileComponentProps {
/**
* Styles
*/
classes: any
classes?: any
}

View File

@@ -73,7 +73,7 @@ export class EmailVerificationComponent extends Component<IEmailVerificationComp
}}>Green</h1>
<div className='animate-bottom'>
<Paper style={paperStyle} elevation={1} rounded={false} >
<Paper style={paperStyle} elevation={1} >
<div style={{ padding: '48px 40px 36px' }}>
<div style={{
paddingLeft: '40px',
@@ -93,8 +93,8 @@ export class EmailVerificationComponent extends Component<IEmailVerificationComp
An verificiation email has been already sent to you. Please check your inbox. If you couldn't see the emai, please resend email verification.
</p>
<div style={this.styles.buttons}>
<Button raised style={this.styles.homeButton} label='Home' color='primary' onClick={() => this.props.homePage()} />
<Button raised label='Send Email Verification' color='primary' onClick={() => this.props.sendEmailVerification()} />
<Button raised style={this.styles.homeButton} color='primary' onClick={() => this.props.homePage()}> Home </Button>
<Button raised color='primary' onClick={() => this.props.sendEmailVerification()}> Send Email Verification </Button>
</div>
<div>
</div>
@@ -135,4 +135,4 @@ const mapStateToProps = (state: any, ownProps: IEmailVerificationComponentProps)
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(EmailVerificationComponent as any))
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(EmailVerificationComponent as any) as any)

View File

@@ -1,5 +1,4 @@
export interface IEmailVerificationComponentState {
}

View File

@@ -57,7 +57,7 @@ export class FindPeopleComponent extends Component<IFindPeopleComponentProps, IF
loadMore={this.scrollLoad}
hasMore={hasMorePeople}
useWindow={true}
loader={ <LoadMoreProgressComponent />}
loader={<LoadMoreProgressComponent />}
>
<div className='tracks'>

View File

@@ -8,7 +8,7 @@ import UserBoxList from 'components/userBoxList'
import { IFollowersComponentProps } from './IFollowersComponentProps'
import { IFollowersComponentState } from './IFollowersComponentState'
import { Circle } from 'core/domain/circles';
import { Circle } from 'core/domain/circles'
// - Import API

View File

@@ -9,12 +9,12 @@ import Menu from 'material-ui/Menu'
import { MenuList, MenuItem } from 'material-ui/Menu'
import { ListItemIcon, ListItemText } from 'material-ui/List'
import Divider from 'material-ui/Divider'
import SvgArrowLeft from 'material-ui-icons/keyboardArrowLeft'
import SvgHome from 'material-ui-icons/home'
import SvgFeedback from 'material-ui-icons/feedback'
import SvgSettings from 'material-ui-icons/settings'
import SvgAccountCircle from 'material-ui-icons/accountCircle'
import SvgPeople from 'material-ui-icons/people'
import SvgArrowLeft from 'material-ui-icons/KeyboardArrowLeft'
import SvgHome from 'material-ui-icons/Home'
import SvgFeedback from 'material-ui-icons/Feedback'
import SvgSettings from 'material-ui-icons/Settings'
import SvgAccountCircle from 'material-ui-icons/AccountCircle'
import SvgPeople from 'material-ui-icons/People'
// - Import app components
import Sidebar from 'components/sidebar'
@@ -130,6 +130,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
* @memberof Home
*/
render () {
const HR = HomeRouter as any
const { loaded, authed, loadDataStream, mergedPosts, hasMorePosts, showSendFeedback } = this.props
return (
<div id='home'>
@@ -184,7 +185,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
<ListItemText inset primary='Settings' />
</MenuItem>
</NavLink>
<MenuItem onClick={() => showSendFeedback()} style={{ color: 'rgb(117, 117, 117)' }}>
<MenuItem onClick={() => showSendFeedback!()} style={{ color: 'rgb(117, 117, 117)' }}>
<ListItemIcon>
<SvgFeedback />
</ListItemIcon>
@@ -194,7 +195,7 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
</SidebarContent>
<SidebarMain>
<HomeRouter enabled={loaded!} data={{ mergedPosts, loadDataStream, hasMorePosts }} />
<HR enabled={loaded!} data={{ mergedPosts, loadDataStream, hasMorePosts }} />
</SidebarMain>
</Sidebar>
@@ -274,4 +275,4 @@ const mapStateToProps = (state: any, ownProps: IHomeComponentProps) => {
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(HomeComponent as any) as any)
export default withRouter<any>(connect(mapStateToProps, mapDispatchToProps)(HomeComponent as any)) as typeof HomeComponent

View File

@@ -37,7 +37,7 @@ export interface IHomeComponentProps {
/**
* Load the data for stream
*/
loadDataStream: (lastPostId: string, page: number, limit: number) => any
loadDataStream?: (lastPostId: string, page: number, limit: number) => any
/**
* Global state
@@ -101,11 +101,11 @@ export interface IHomeComponentProps {
/**
* Show send feedback form
*/
showSendFeedback: () => any
showSendFeedback?: () => any
/**
* Hide send feedback form
*/
hideSendFeedback: () => any
hideSendFeedback?: () => any
}

View File

@@ -2,7 +2,7 @@
import React, { Component } from 'react'
import { NavLink } from 'react-router-dom'
import { connect } from 'react-redux'
import SvgDehaze from 'material-ui-icons/dehaze'
import SvgDehaze from 'material-ui-icons/Dehaze'
import { grey, blue } from 'material-ui/colors'
import Toolbar from 'material-ui/Toolbar'
import IconButton from 'material-ui/IconButton'
@@ -10,7 +10,7 @@ import Popover from 'material-ui/Popover'
import AppBar from 'material-ui/AppBar'
import Menu, { MenuList, MenuItem } from 'material-ui/Menu'
import Paper from 'material-ui/Paper'
import NotificationsIcon from 'material-ui-icons/notifications'
import NotificationsIcon from 'material-ui-icons/Notifications'
import EventListener, { withOptions } from 'react-event-listener'
import Tooltip from 'material-ui/Tooltip'
import Typography from 'material-ui/Typography'

View File

@@ -4,11 +4,11 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import GridList, { GridListTile, GridListTileBar } from 'material-ui/GridList'
import IconButton from 'material-ui/IconButton'
import StarBorder from 'material-ui-icons/starBorder'
import StarBorder from 'material-ui-icons/StarBorder'
import Button from 'material-ui/Button'
import SvgUpload from 'material-ui-icons/cloudUpload'
import SvgAddImage from 'material-ui-icons/addAPhoto'
import SvgDelete from 'material-ui-icons/delete'
import SvgUpload from 'material-ui-icons/CloudUpload'
import SvgAddImage from 'material-ui-icons/AddAPhoto'
import SvgDelete from 'material-ui-icons/Delete'
import { grey } from 'material-ui/colors'
import uuid from 'uuid'
@@ -174,8 +174,7 @@ export class ImageGalleryComponent extends Component<IImageGalleryComponentProps
title={<SvgDelete style={this.styles.deleteImage as any} onClick={evt => this.handleDeleteImage(evt, image.id!)} />}
titlePosition='top'
actionIcon={
<SvgAddImage style={this.styles.addImage as any} onClick={evt => this.handleSetImage(evt, image.URL,image.fullPath)} />
}
<SvgAddImage style={this.styles.addImage as any} onClick={evt => this.handleSetImage(evt, image.URL,image.fullPath)} />}
actionPosition='left'
/>
</GridListTile>)

View File

@@ -2,7 +2,7 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import SvgImage from 'material-ui-icons/image'
import SvgImage from 'material-ui-icons/Image'
import { withStyles } from 'material-ui/styles'
// - Import app components
@@ -91,7 +91,7 @@ export class ImgComponent extends Component<IImgComponentProps,IImgComponentStat
return (
<div>
<img className={classes.image} onLoad={this.handleLoadImage} src={fileName || ''} style={isImageLoaded ? style : { display: 'none' }} />
<div style={Object.assign({},{ backgroundColor: 'white' }, isImageLoaded ? { display: 'none' } : this.styles.loding) }>
<div style={Object.assign({},{ backgroundColor: 'white' }, isImageLoaded ? { display: 'none' } : this.styles.loding)}>
<div style={this.styles.loadingContent as any}>
<SvgImage style={this.styles.loadingImage} />
<div>Image has not loaded</div>

View File

@@ -2,7 +2,7 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import SvgImage from 'material-ui-icons/image'
import SvgImage from 'material-ui-icons/Image'
// - Import app components

View File

@@ -9,7 +9,7 @@ import RaisedButton from 'material-ui/Button'
import Button from 'material-ui/Button'
import IconButton from 'material-ui/IconButton'
import Divider from 'material-ui/Divider'
import ActionAndroid from 'material-ui-icons/android'
import ActionAndroid from 'material-ui-icons/Android'
import { withStyles } from 'material-ui/styles'
// - Import actions
@@ -259,4 +259,4 @@ const mapStateToProps = (state: any, ownProps: ILoginComponentProps) => {
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(LoginComponent as any) as any))
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(LoginComponent as any) as any) as any)

View File

@@ -112,8 +112,10 @@ export class NotifyComponent extends Component<INotifyComponentProps, INotifyCom
*/
render () {
let { open, anchorEl, onRequestClose, classes } = this.props
const noNotify = ( <div className={classes.noNotify}>
All caught up! </div>)
const noNotify = (
<div className={classes.noNotify}>
All caught up! </div>
)
const items = this.notifyItemList()
return (
<Popper
@@ -162,4 +164,4 @@ const mapStateToProps = (state: any, ownProps: INotifyComponentProps) => {
}
// - Connect component to redux store
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(NotifyComponent as any) as any)
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles as any)(NotifyComponent as any) as any)

View File

@@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { NavLink } from 'react-router-dom'
import { push } from 'react-router-redux'
import SvgClose from 'material-ui-icons/close'
import SvgClose from 'material-ui-icons/Close'
import { grey } from 'material-ui/colors'
import { withStyles } from 'material-ui/styles'
import List, { ListItem, ListItemSecondaryAction, ListItemText } from 'material-ui/List'

View File

@@ -130,7 +130,7 @@ export class PeopleComponent extends Component<IPeopleComponentProps,IPeopleComp
return (
<div style={styles.people}>
<AppBar position='static' color='default'>
<Tabs indicatorColor= {grey[50]}
<Tabs indicatorColor={grey[50]}
onChange={this.handleChangeTab}
value={tabIndex} centered
textColor='primary'
@@ -197,4 +197,4 @@ const mapStateToProps = (state: any, ownProps: IPeopleComponentProps) => {
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(PeopleComponent as any))
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(PeopleComponent as any) as any)

View File

@@ -4,18 +4,18 @@ import { connect } from 'react-redux'
import { NavLink } from 'react-router-dom'
import { push } from 'react-router-redux'
import PropTypes from 'prop-types'
import moment from 'moment'
import moment from 'moment/moment'
import Linkify from 'react-linkify'
import copy from 'copy-to-clipboard'
// - Material UI
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
import Typography from 'material-ui/Typography'
import SvgShare from 'material-ui-icons/share'
import SvgLink from 'material-ui-icons/link'
import SvgComment from 'material-ui-icons/comment'
import SvgFavorite from 'material-ui-icons/favorite'
import SvgFavoriteBorder from 'material-ui-icons/favoriteBorder'
import SvgShare from 'material-ui-icons/Share'
import SvgLink from 'material-ui-icons/Link'
import SvgComment from 'material-ui-icons/Comment'
import SvgFavorite from 'material-ui-icons/Favorite'
import SvgFavoriteBorder from 'material-ui-icons/FavoriteBorder'
import Checkbox from 'material-ui/Checkbox'
import Button from 'material-ui/Button'
import Divider from 'material-ui/Divider'
@@ -26,7 +26,7 @@ import { MenuList, MenuItem } from 'material-ui/Menu'
import TextField from 'material-ui/TextField'
import Dialog from 'material-ui/Dialog'
import IconButton from 'material-ui/IconButton'
import MoreVertIcon from 'material-ui-icons/moreVert'
import MoreVertIcon from 'material-ui-icons/MoreVert'
import { ListItemIcon, ListItemText } from 'material-ui/List'
import { withStyles } from 'material-ui/styles'
import { Manager, Target, Popper } from 'react-popper'
@@ -342,7 +342,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
<Manager>
<Target>
<IconButton
aria-owns={isPostMenuOpen! ? 'post-menu' : null}
aria-owns={isPostMenuOpen! ? 'post-menu' : ''}
aria-haspopup='true'
onClick={this.openPostMenu.bind(this)}
>
@@ -356,7 +356,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
className={classNames({ [classes.popperClose]: !isPostMenuOpen! }, { [classes.popperOpen]: isPostMenuOpen! })}
>
<ClickAwayListener onClickAway={this.closePostMenu}>
<Grow in={isPostMenuOpen!} id='post-menu' style={{ transformOrigin: '0 0 0' }}>
<Grow in={isPostMenuOpen!} style={{ transformOrigin: '0 0 0' }}>
<Paper>
<MenuList role='menu'>
<MenuItem onClick={this.handleOpenPostWrite} > Edit </MenuItem>
@@ -537,4 +537,4 @@ const mapStateToProps = (state: any, ownProps: IPostComponentProps) => {
}
// - Connect component to redux store
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(PostComponent as any) as any)
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles as any)(PostComponent as any) as any)

View File

@@ -49,8 +49,9 @@ export class PostPageComponent extends Component<IPostPageComponentProps,IPostPa
* @return {react element} return the DOM which rendered by component
*/
render () {
const St = Stream as any
return (
<Stream posts={this.props.posts} displayWriting={false} />
<St posts={this.props.posts} displayWriting={false} />
)
}
}

View File

@@ -25,9 +25,9 @@ import IconButton from 'material-ui/IconButton'
import TextField from 'material-ui/TextField'
import Tooltip from 'material-ui/Tooltip'
import { MenuList, MenuItem } from 'material-ui/Menu'
import SvgRemoveImage from 'material-ui-icons/removeCircle'
import SvgCamera from 'material-ui-icons/photoCamera'
import MoreVertIcon from 'material-ui-icons/moreVert'
import SvgRemoveImage from 'material-ui-icons/RemoveCircle'
import SvgCamera from 'material-ui-icons/PhotoCamera'
import MoreVertIcon from 'material-ui-icons/MoreVert'
import { withStyles } from 'material-ui/styles'
import { Manager, Target, Popper } from 'react-popper'
import Grow from 'material-ui/transitions/Grow'
@@ -87,7 +87,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
* Component constructor
* @param {object} props is an object properties of component
*/
constructor(props: IPostWriteComponentProps) {
constructor (props: IPostWriteComponentProps) {
super(props)
@@ -323,7 +323,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
})
}
componentWillReceiveProps(nextProps: IPostWriteComponentProps) {
componentWillReceiveProps (nextProps: IPostWriteComponentProps) {
if (!nextProps.open) {
const { postModel } = this.props
this.setState({
@@ -364,7 +364,7 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
* Reneder component DOM
* @return {react element} return the DOM which rendered by component
*/
render() {
render () {
const { classes } = this.props
const { menuOpen } = this.state
@@ -421,7 +421,8 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
* Provide post image
*/
const loadImage = (this.state.image && this.state.image !== '')
? (<div>
? (
<div>
<div style={{ position: 'relative', overflowY: 'hidden', overflowX: 'auto' }}>
<ul style={{ position: 'relative', whiteSpace: 'nowrap', padding: '0 0 0 16px', margin: '8px 0 0 0', paddingRight: '16px', verticalAlign: 'bottom', flexShrink: 0, listStyleType: 'none' }}>
<div style={{ display: 'flex', position: 'relative' }}>
@@ -442,7 +443,8 @@ export class PostWriteComponent extends Component<IPostWriteComponentProps, IPos
</ul>
</div>
</div>) : ''
</div>
) : ''
const styles = {
dialog: {
@@ -579,4 +581,4 @@ const mapStateToProps = (state: any, ownProps: IPostWriteComponentProps) => {
}
// - Connect component to redux store
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(PostWriteComponent as any) as any)
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles as any)(PostWriteComponent as any) as any)

View File

@@ -78,7 +78,7 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
}
}
const {loadPosts, hasMorePosts} = this.props
const St = StreamComponent as any
return (
<div style={styles.profile}>
<div style={styles.header}>
@@ -92,7 +92,7 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
</div>
<div style={{ height: '24px' }}></div>
<StreamComponent
<St
posts={this.props.posts}
loadStream={loadPosts}
hasMorePosts={hasMorePosts}

View File

@@ -1,8 +1,8 @@
// - Import react components
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { grey400 } from 'material-ui/styles/colors'
import SvgClose from 'material-ui-icons/close'
import { grey } from 'material-ui/colors'
import SvgClose from 'material-ui-icons/Close'
import Button from 'material-ui/Button'
import Divider from 'material-ui/Divider'
import { IDialogTitleComponentProps } from './IDialogTitleComponentProps'
@@ -76,13 +76,15 @@ export default class DialogTitleComponent extends Component<IDialogTitleComponen
<div className='g__dialog-title'>
<div style={this.styles.contain as any}>
<div style={{ paddingRight: '10px' }}>
<SvgClose onClick={onRequestClose} hoverColor={grey400} style={{ cursor: 'pointer' }} />
<SvgClose onClick={onRequestClose} style={{ cursor: 'pointer' }} />
</div>
<div style={this.styles.title}>
{title || ''}
</div>
{ buttonLabel ? (<div style={{ marginTop: '-9px' }}>
<Button label={buttonLabel || ''} color='primary' disabled={disabledButton ? disabledButton : false} onClick={onClickButton || (x => x)} />
<Button color='primary' disabled={disabledButton ? disabledButton : false} onClick={onClickButton || (x => x)}>
{buttonLabel || ''}
</Button>
</div>) : ''}
</div>
<Divider />

View File

@@ -4,7 +4,7 @@ import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { grey } from 'material-ui/colors'
import IconButton from 'material-ui/IconButton'
import MoreVertIcon from 'material-ui-icons/moreVert'
import MoreVertIcon from 'material-ui-icons/MoreVert'
import { MenuList, MenuItem } from 'material-ui/Menu'
import Button from 'material-ui/Button'
import RaisedButton from 'material-ui/Button'

View File

@@ -189,4 +189,4 @@ const mapStateToProps = (state: any, ownProps: IResetPasswordComponentProps) =>
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(ResetPasswordComponent as any) as any))
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(ResetPasswordComponent as any) as any) as any)

View File

@@ -5,9 +5,9 @@ import { connect } from 'react-redux'
import Paper from 'material-ui/Paper'
import TextField from 'material-ui/TextField'
import IconButton from 'material-ui/IconButton'
import SvgHappy from 'material-ui-icons/tagFaces'
import SvgSad from 'material-ui-icons/face'
import SvgClose from 'material-ui-icons/clear'
import SvgHappy from 'material-ui-icons/TagFaces'
import SvgSad from 'material-ui-icons/Face'
import SvgClose from 'material-ui-icons/Clear'
import { CircularProgress } from 'material-ui/Progress'
import Tooltip from 'material-ui/Tooltip'
@@ -122,7 +122,8 @@ export class SendFeedbackComponent extends Component<ISendFeedbackComponentProps
}
loadingForm = () => {
return (<div className='loading'>
return (
<div className='loading'>
<p>
Your feedback is sending!
</p>

View File

@@ -228,4 +228,4 @@ const mapStateToProps = (state: any, ownProps: ISettingComponentProps) => {
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(SettingComponent as any) as any))
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(SettingComponent as any) as any) as any)

View File

@@ -171,7 +171,7 @@ export class SidebarComponent extends Component<ISidebarComponentProps,ISidebarC
if (!this.state.auto && this.state.open) {
this.open(false, 'auto')
}else {
} else {
this.setState({
overlayOpen: true,
overlay: this.state.open

View File

@@ -10,7 +10,7 @@ import { ISidebarContentComponentState } from './ISidebarContentComponentState'
// - Create component class
export default class SidebarContentComponent extends Component<ISidebarContentComponentProps,ISidebarContentComponentState> {
static qcName= 'SidebarContent'
static qcName = 'SidebarContent'
/**
* Component constructor

View File

@@ -228,7 +228,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
<TextField
className={classes.textField}
onChange={this.handleInputChange}
helperText={this.state.passwordInputError }
helperText={this.state.passwordInputError}
error={this.state.passwordInputError.trim() !== ''}
name='passwordInput'
label='Password'
@@ -237,7 +237,7 @@ export class SignupComponent extends Component<ISignupComponentProps,ISignupComp
<TextField
className={classes.textField}
onChange={this.handleInputChange}
helperText={this.state.confirmInputError }
helperText={this.state.confirmInputError}
error={this.state.confirmInputError.trim() !== ''}
name='confirmInput'
label='Confirm Password'
@@ -296,4 +296,4 @@ const mapStateToProps = (state: any,ownProps: ISignupComponentProps) => {
}
// - Connect component to redux store
export default withRouter(connect(mapStateToProps,mapDispatchToProps)(withStyles(styles)(SignupComponent as any) as any))
export default withRouter(connect(mapStateToProps,mapDispatchToProps)(withStyles(styles)(SignupComponent as any) as any) as any)

View File

@@ -69,12 +69,12 @@ export interface IStreamComponentProps {
/**
* Load the data for stream
*/
loadStream: (page: number, limit: number) => any
loadStream?: (page: number, limit: number) => any
/**
* If there is more post {true} or not {false}
*/
hasMorePosts: boolean
hasMorePosts?: boolean
/**
* Posts for stream
@@ -87,5 +87,5 @@ export interface IStreamComponentProps {
/**
* Router match property
*/
match: any
match?: any
}

View File

@@ -5,7 +5,7 @@ import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import Button from 'material-ui/Button'
import { grey,teal } from 'material-ui/colors'
import SvgCamera from 'material-ui-icons/photoCamera'
import SvgCamera from 'material-ui-icons/PhotoCamera'
import Paper from 'material-ui/Paper'
import List, { ListItem, ListItemIcon, ListItemText } from 'material-ui/List'
import InfiniteScroll from 'react-infinite-scroller'
@@ -149,7 +149,7 @@ export class StreamComponent extends Component<IStreamComponentProps,IStreamComp
if (postMatch !== null) {
parsedPosts.push({ ...posts[postId]})
}
}else {
} else {
parsedPosts.push({ ...posts[postId]})
}
@@ -174,7 +174,7 @@ export class StreamComponent extends Component<IStreamComponentProps,IStreamComp
if ((index % 2) === 1 && postBack.divided) {
postBack.oddPostList.push(newPost as never)
}else {
} else {
postBack.evenPostList.push(newPost as never)
}
})
@@ -188,7 +188,7 @@ export class StreamComponent extends Component<IStreamComponentProps,IStreamComp
*/
scrollLoad = (page: number) => {
const {loadStream} = this.props
loadStream(page, 10)
loadStream!(page, 10)
}
componentWillMount () {
@@ -211,10 +211,10 @@ export class StreamComponent extends Component<IStreamComponentProps,IStreamComp
loadMore={this.scrollLoad}
hasMore={hasMorePosts}
useWindow={true}
loader={ <LoadMoreProgressComponent />}
loader={<LoadMoreProgressComponent />}
>
<div className='grid grid__gutters grid__1of2 grid__space-around animate-top'>
<div className='grid-cell animate-top' style= {{maxWidth: '530px', minWidth: '280px'}}>
<div className='grid-cell animate-top' style={{maxWidth: '530px', minWidth: '280px'}}>
{displayWriting && !tag
? (<PostWriteComponent open={this.state.openPostWrite} onRequestClose={this.handleClosePostWrite} edit={false} >
<Paper elevation={2}>

View File

@@ -19,5 +19,5 @@ export interface IUserAvatarComponentProps {
/**
* Trigger on touch tap
*/
onClick?: (event: any) => anys
onClick?: (event: any) => any
}

View File

@@ -41,7 +41,7 @@ export interface IUserBoxComponentProps {
/**
* Whether current user followed this user
*/
isFollowed: boolean
isFollowed?: boolean
/**
* The number of circles

View File

@@ -1,6 +1,6 @@
// - Import react components
import React, { Component } from 'react'
import moment from 'moment'
import moment from 'moment/moment'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { push } from 'react-router-redux'
@@ -21,7 +21,7 @@ import Dialog, {
DialogTitle,
withMobileDialog
} from 'material-ui/Dialog'
import SvgAdd from 'material-ui-icons/add'
import SvgAdd from 'material-ui-icons/Add'
import IconButton from 'material-ui/IconButton'
import { grey } from 'material-ui/colors'

View File

@@ -0,0 +1,10 @@
export const environment = {
firebase: {
apiKey: 'AIzaSyAHOZ7rWGDODCwJMB3WIt63CAIa90qI-jg',
authDomain: 'test-4515a.firebaseapp.com',
databaseURL: 'https://test-4515a.firebaseio.com',
projectId: 'test-4515a',
storageBucket: 'test-4515a.appspot.com',
messagingSenderId: '964743099489'
}
}

View File

@@ -0,0 +1,10 @@
export const environment = {
firebase: {
apiKey: 'AIzaSyAHOZ7rWGDODCwJMB3WIt63CAIa90qI-jg',
authDomain: 'test-4515a.firebaseapp.com',
databaseURL: 'https://test-4515a.firebaseio.com',
projectId: 'test-4515a',
storageBucket: 'test-4515a.appspot.com',
messagingSenderId: '964743099489'
}
}

17
src/config/index.ts Normal file
View File

@@ -0,0 +1,17 @@
import {environment as prod } from './environment.prod'
import {environment as dev } from './environment.dev'
const config = {
// Add common config values here
}
const configEnv = process.env.NODE_ENV === 'production'
? prod
: dev
export default {
// Add common config values here
...config,
...configEnv
}

View File

@@ -1,5 +1,5 @@
import { Circle } from './circle'
import { UserTie } from './UserTie'
import { UserTie } from './userTie'
export {
Circle,

View File

@@ -1,4 +1,4 @@
export class BaseDomain{
export class BaseDomain {
}

View File

@@ -1,5 +1,5 @@
import { User } from 'core/domain/users'
import { Feed } from 'core/domain/common';
import { Feed } from 'core/domain/common'
/**
* Common service interface

View File

@@ -44,6 +44,4 @@ export const useFirestore = (container: Container) => {
container.bind<IGraphService>(FirestoreClientTypes.GraphService).to(GraphService)
container.bind<IUserTieService>(SocialProviderTypes.UserTieService).to(UserTieService)
}

View File

@@ -1,16 +1,17 @@
import firebase from 'firebase'
import 'firebase/firestore'
import config from 'src/config'
try {
let config = {
apiKey: process.env.API_KEY,
authDomain: process.env.AUTH_DOMAIN,
databaseURL: process.env.DATABASE_URL,
projectId: process.env.PROJECT_ID,
storageBucket: process.env.STORAGE_BUCKET,
messagingSenderId: process.env.MESSAGING_SENDER_ID
let firebaseConfig = {
apiKey: config.firebase.apiKey,
authDomain: config.firebase.authDomain,
databaseURL: config.firebase.databaseURL,
projectId: config.firebase.projectId,
storageBucket: config.firebase.storageBucket,
messagingSenderId: config.firebase.messagingSenderId
}
firebase.initializeApp(config)
firebase.initializeApp(firebaseConfig)
} catch (error) {
console.log('=========Firebase firestore initializer==============')
console.log(error)

View File

@@ -9,7 +9,7 @@ import { LoginUser, RegisterUserResult } from 'core/domain/authorize'
import { SocialError } from 'core/domain/common'
import { OAuthType } from 'core/domain/authorize/oauthType'
import moment from 'moment'
import moment from 'moment/moment'
import { injectable } from 'inversify'
/**
* Firbase authorize service

View File

@@ -1,7 +1,7 @@
// - Import react components
import { datumString } from 'aws-sdk/clients/athena'
import firebase, { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
import moment from 'moment'
import moment from 'moment/moment'
import { SocialError } from 'core/domain/common'
import { Profile, UserProvider, User } from 'core/domain/users'

View File

@@ -96,7 +96,7 @@ export class GraphService implements IGraphService {
// Delete documents in a batch
let batch = db.batch()
snapshot.docs.forEach(function (doc) {
snapshot.docs.forEach(function (doc: any) {
batch.delete(doc.ref)
})
@@ -115,7 +115,7 @@ export class GraphService implements IGraphService {
private getGraphsQuery: (collection: string, leftNode?: string | null, edgeType?: string, rightNode?: string | null)
=> Promise<firebase.firestore.QuerySnapshot> = (collection, leftNode, edgeType, rightNode) => {
return new Promise<firebase.firestore.QuerySnapshot>((resolve,reject) => {
let graphsRef = db.collection(`graphs:${collection}`)
let graphsRef = db.collection(`graphs:${collection}`) as any
if (leftNode != null) {
graphsRef = graphsRef.where('leftNode', '==', leftNode)
@@ -129,14 +129,14 @@ export class GraphService implements IGraphService {
}
if (graphsRef) {
graphsRef.get().then((result) => {
graphsRef.get().then((result: any) => {
resolve(result)
}).catch((error) => reject(error))
}).catch((error: any) => reject(error))
} else {
graphsRef.get().then((result) => {
graphsRef.get().then((result: any) => {
resolve(result)
}).catch((error) => reject(error))
}).catch((error: any) => reject(error))
}
})

View File

@@ -1,5 +1,5 @@
import { VoteService } from './VoteService'
import { GraphService } from './GraphService'
export {
VoteService
GraphService
}

View File

@@ -108,7 +108,7 @@ export class PostService implements IPostService {
postList = [
...postList,
...result.posts
];
]
resolve(this.pagingPosts(postList, lastPostId, limit))
})

View File

@@ -1,6 +1,6 @@
// - Import react components
import firebase, { firebaseRef, firebaseAuth, db } from 'data/firestoreClient'
import moment from 'moment'
import moment from 'moment/moment'
import { SocialError } from 'core/domain/common'
import { Profile, UserProvider } from 'core/domain/users'

View File

@@ -1,11 +1,11 @@
// Import external components refrence
import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import injectTapEventPlugin from 'react-tap-event-plugin'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles'
import 'reflect-metadata'
import 'typeface-roboto'
import registerServiceWorker from './registerServiceWorker'
import { Provider } from 'react-redux'
import store, { history } from 'store/configureStore'
@@ -21,7 +21,7 @@ store.subscribe(() => { })
// Needed for onClick
// http://stackoverflow.com/a/34015469/988941
try { injectTapEventPlugin() } catch (e) { }
try { injectTapEventPlugin() } catch (e) {}
const theme = createMuiTheme({
palette: {
@@ -30,7 +30,7 @@ const theme = createMuiTheme({
}
})
// App css
import 'applicationStyles'
import './styles/app.css'
/**
* Execute startup functions
@@ -38,24 +38,14 @@ import 'applicationStyles'
import './socialEngine'
const supportsHistory = 'pushState' in window.history
const render = (Component: any) => {
ReactDOM.render(
<AppContainer warnings={false}>
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<MuiThemeProvider theme={theme}>
<Component />
<Master />
</MuiThemeProvider>
</ConnectedRouter>
</Provider>
</AppContainer>,
document.getElementById('app')
)
}
render(Master)
// Webpack Hot Module Replacement API
if (module.hot) {
module.hot.accept()
}
</Provider>,
document.getElementById('app') as HTMLElement
)
registerServiceWorker()

View File

@@ -2,7 +2,7 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { grey } from 'material-ui/colors'
import SvgClose from 'material-ui-icons/close'
import SvgClose from 'material-ui-icons/Close'
import Button from 'material-ui/Button'
import Divider from 'material-ui/Divider'
import { IDialogTitleComponentProps } from './IDialogTitleComponentProps'
@@ -76,13 +76,13 @@ export default class DialogTitleComponent extends Component<IDialogTitleComponen
<div className='g__dialog-title'>
<div style={this.styles.contain as any}>
<div style={{ paddingRight: '10px' }}>
<SvgClose onClick={onRequestClose} hoverColor={grey[400]} style={{ cursor: 'pointer' }} />
<SvgClose onClick={onRequestClose} style={{ cursor: 'pointer' }} />
</div>
<div style={this.styles.title}>
{title || ''}
</div>
{ buttonLabel ? (<div style={{ marginTop: '-9px' }}>
<Button label={buttonLabel || ''} color='primary' disabled={disabledButton ? disabledButton : false} onClick={onClickButton || (x => x)} />
<Button color='primary' disabled={disabledButton ? disabledButton : false} onClick={onClickButton || (x => x)}> {buttonLabel || ''} </Button>
</div>) : ''}
</div>
<Divider />

View File

@@ -1,7 +1,7 @@
// - Import react components
import React, { Component } from 'react'
import IconButton from 'material-ui/IconButton'
import MoreVertIcon from 'material-ui-icons/moreVert'
import MoreVertIcon from 'material-ui-icons/MoreVert'
import { grey } from 'material-ui/colors'
/**

View File

@@ -1,5 +1,5 @@
// - Import react components
import moment from 'moment'
import moment from 'moment/moment'
import _ from 'lodash'
// - Import domain

View File

@@ -1,5 +1,5 @@
// - Import react components
import moment from 'moment'
import moment from 'moment/moment'
import _ from 'lodash'
// - Import domain

View File

@@ -1,5 +1,5 @@
// - Import react components
import moment from 'moment'
import moment from 'moment/moment'
import _ from 'lodash'
// - Import domain

View File

@@ -1,5 +1,5 @@
// - Import react components
import moment from 'moment'
import moment from 'moment/moment'
import _ from 'lodash'
import { Reducer, Action } from 'redux'

View File

@@ -1,5 +1,5 @@
// - Import react components
import moment from 'moment'
import moment from 'moment/moment'
import _ from 'lodash'
// - Import action types

View File

@@ -0,0 +1,108 @@
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export default function register() {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl);
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl);
}
});
}
}
function registerValidSW(swUrl) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log('New content is available; please refresh.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}

View File

@@ -0,0 +1,114 @@
// tslint:disable:no-console
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the 'N+1' visit to a page, since previously
// cached resources are updated in the background.
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
)
export default function register() {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(
process.env.PUBLIC_URL!,
window.location.toString()
)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (!isLocalhost) {
// Is not local host. Just register service worker
registerValidSW(swUrl)
} else {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl)
}
})
}
}
function registerValidSW(swUrl: string) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing
if (installingWorker) {
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a 'New content is
// available; please refresh.' message in your web app.
console.log('New content is available; please refresh.')
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// 'Content is cached for offline use.' message.
console.log('Content is cached for offline use.')
}
}
}
}
}
})
.catch(error => {
console.error('Error during service worker registration:', error)
})
}
function checkValidServiceWorker(swUrl: string) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get('content-type')!.indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload()
})
})
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl)
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
)
})
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister()
})
}
}

View File

@@ -19,18 +19,20 @@ import { IRouterProps } from './IRouterProps'
export class HomeRouter extends Component<IRouterProps, any> {
render () {
const { enabled, match, data } = this.props
const St = StreamComponent as any
return (
enabled ? (<Switch>
enabled ? (
<Switch>
<PrivateRoute path='/people/:tab?' component={<People />} />
<PrivateRoute path='/tag/:tag' component={(
<div className='blog'><StreamComponent displayWriting={false} homeTitle={`#${match.params.tag}`} posts={data.mergedPosts} /></div>
<div className='blog'><St displayWriting={false} homeTitle={`#${match.params.tag}`} posts={data.mergedPosts} /></div>
)} />
<Route path='/:userId/posts/:postId/:tag?' component={PostPage} />
<Route path='/:userId' component={Profile} />
<PrivateRoute path='/' component={(
<div className='blog'>
<StreamComponent
<St
homeTitle='Home'
posts={data.mergedPosts}
loadStream={data.loadDataStream}
@@ -38,10 +40,11 @@ export class HomeRouter extends Component<IRouterProps, any> {
displayWriting={true} />
</div>
)} />
</Switch>)
</Switch>
)
: ''
)
}
}
export default withRouter(connect(null, null)(HomeRouter as any))
export default withRouter(connect(null, null)(HomeRouter as any) as any)

View File

@@ -21,6 +21,6 @@ export interface IRouterProps {
* @type {*}
* @memberof IRouterProps
*/
match: any
match?: any
}

View File

@@ -23,7 +23,8 @@ export class MasterRouter extends Component<IRouterProps, any> {
render () {
const { enabled, match, data } = this.props
return (
enabled ? (<Switch>
enabled ? (
<Switch>
<Route path='/signup' component={Signup} />
<Route path='/emailVerification' component={EmailVerification} />
<Route path='/settings' component={Setting} />
@@ -36,4 +37,4 @@ export class MasterRouter extends Component<IRouterProps, any> {
)
}
}
export default withRouter(connect(null, null)(MasterRouter as any))
export default withRouter<any>(connect(null, null)(MasterRouter as any)) as typeof MasterRouter

948
src/styles/app.css Normal file
View File

@@ -0,0 +1,948 @@
.grid {
display: flex;
flex-flow: row;
flex-wrap: wrap; }
.grid__gutters {
margin-left: -1em; }
.grid__gutters .grid-cell {
padding-left: 1em; }
/* Justify per row*/
.grid__right {
justify-content: flex-end; }
.grid__left {
justify-content: flex-start; }
.grid__center {
justify-content: center; }
.grid__space-around {
justify-content: space-around; }
/* Alignment per row */
.grid__top {
align-items: flex-start; }
.grid__bottom {
align-items: flex-end; }
.grid__center {
align-items: center; }
/* Alignment per cell */
.grid-cell__top {
align-self: flex-start; }
.grid-cell__bottom {
align-self: flex-end; }
.grid-cell__center {
align-self: center; }
.grid__fit > .grid-cell {
flex: 1; }
.grid__full > .grid-cell {
flex: 0 0 100%; }
@media (min-width: 400px) {
.grid__cols-2 > .grid-cell,
.grid__cols-3 > .grid-cell,
.grid__cols-4 > .grid-cell,
.grid__cols-6 > .grid-cell,
.grid__cols-12 > .grid-cell {
flex: 1; }
.grid__1of2 > .grid-cell {
flex: 1; }
.grid__1of6 > .grid-cell {
flex: 0 0 16.6666%; }
.grid__1of4 > .grid-cell {
flex: 0 0 calc(48.6666% - 1em); }
.grid__1of3 > .grid-cell {
flex: 0 0 30%; } }
@media (min-width: 600px) {
.grid__cols-2 > .grid-cell,
.grid__cols-3 > .grid-cell,
.grid__cols-4 > .grid-cell,
.grid__cols-6 > .grid-cell,
.grid__cols-12 > .grid-cell {
flex: 1; }
.grid__1of2 > .grid-cell {
flex: 1; }
.grid__1of6 > .grid-cell {
flex: 0 0 16.6666%; }
.grid__1of4 > .grid-cell {
flex: 0 0 calc(48.6666% - 1em); }
.grid__1of3 > .grid-cell {
flex: 0 0 30%; } }
@media (min-width: 1000px) {
.grid__cols-2 > .grid-cell,
.grid__cols-3 > .grid-cell,
.grid__cols-4 > .grid-cell,
.grid__cols-6 > .grid-cell,
.grid__cols-12 > .grid-cell {
flex: 1; }
.grid__1of2 > .grid-cell {
flex: 0 0 50%;
flex-grow: 1; }
.grid__1of6 > .grid-cell {
flex: 0 0 16.6666%; }
.grid__1of4 > .grid-cell {
flex: 0 0 calc(24.33333% - 1em);
flex-grow: 1; }
.grid__1of3 > .grid-cell {
flex: 0 0 30%; } }
.animate__up {
animation-duration: .3s;
animation-name: staggerItems;
animation-timing-function: ease-out; }
@keyframes staggerItems {
0% {
-webkit-transform: translateY(30px);
transform: translateY(30px); } }
.spin {
animation: spin 2s infinite linear; }
@keyframes spin {
0% {
transform: rotate(0deg); }
100% {
transform: rotate(359deg); } }
.animate-fading {
animation: fading 10s infinite; }
@keyframes fading {
0% {
opacity: 0; }
50% {
opacity: 1; }
100% {
opacity: 0; } }
.animate-fading2 {
animation: fading 2s infinite; }
@keyframes fading {
0% {
opacity: 0; }
50% {
opacity: 1; }
100% {
opacity: 0; } }
.animate-opacity {
animation: opac 0.8s; }
@keyframes opac {
from {
opacity: 0; }
to {
opacity: 1; } }
.animate-top {
position: relative;
animation: animatetop 0.4s; }
@keyframes animatetop {
from {
top: -300px;
opacity: 0; }
to {
top: 0;
opacity: 1; } }
.animate2-top10 {
position: relative;
animation: animatetop 0.2s; }
@keyframes animatetop {
from {
top: -10px;
opacity: 0; }
to {
top: 0;
opacity: 1; } }
.animate-left {
position: relative;
animation: animateleft 0.4s; }
@keyframes animateleft {
from {
left: -300px;
opacity: 0; }
to {
left: 0;
opacity: 1; } }
.animate-right {
position: relative;
animation: animateright 0.4s; }
@keyframes animateright {
from {
right: -300px;
opacity: 0; }
to {
right: 0;
opacity: 1; } }
.animate-bottom {
position: relative;
animation: animatebottom 0.4s; }
@keyframes animatebottom {
from {
bottom: -300px;
opacity: 0; }
to {
bottom: 0;
opacity: 1; } }
.animate-bottom50 {
position: relative;
animation: animatebottom 0.4s; }
@keyframes animatebottom {
from {
bottom: -50px;
opacity: 0; }
to {
bottom: 0;
opacity: 1; } }
.animated {
animation-duration: .5s;
animation-fill-mode: both; }
.animated.infinite {
animation-iteration-count: infinite; }
.animated.hinge {
animation-duration: 2s; }
@keyframes zoomOutUp {
40% {
opacity: 1;
transform: scale3d(1, 1, 1) translate3d(0, 0px, 0);
animation-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19); }
to {
transform: scale3d(0.8, 0.8, 0.8) translate3d(-80px, -40px, 0);
transform-origin: center bottom;
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1); } }
.zoomOutLCorner {
animation-name: zoomOutUp; }
.icon {
width: 24px;
height: 24px;
display: inline-block; }
.icon-github {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20fill%3D%22#24292e%22%20stroke%3D%22transparent%22%20stroke-width%3D%220%22%20style%3D%22%22%20d%3D%22M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12%22%20%2F%3E%3C%2Fsvg%3E"); }
.icon-google {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20fill%3D%22#db4437%22%20stroke%3D%22transparent%22%20stroke-width%3D%220%22%20style%3D%22%22%20d%3D%22M7.635 10.909v2.619h4.335c-.173 1.125-1.31 3.295-4.331 3.295-2.604 0-4.731-2.16-4.731-4.823 0-2.662 2.122-4.822 4.728-4.822 1.485 0 2.479.633 3.045 1.178l2.073-1.994c-1.33-1.245-3.056-1.995-5.115-1.995C3.412 4.365 0 7.785 0 12s3.414 7.635 7.635 7.635c4.41 0 7.332-3.098 7.332-7.461 0-.501-.054-.885-.12-1.265H7.635zm16.365 0h-2.183V8.726h-2.183v2.183h-2.182v2.181h2.184v2.184h2.189V13.09H24%22%20%2F%3E%3C%2Fsvg%3E"); }
.icon-fb {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20fill%3D%22#4267b2%22%20stroke%3D%22transparent%22%20stroke-width%3D%220%22%20style%3D%22%22%20d%3D%22M22.676 0H1.324C.593 0 0 .593 0 1.324v21.352C0 23.408.593 24 1.324 24h11.494v-9.294H9.689v-3.621h3.129V8.41c0-3.099 1.894-4.785 4.659-4.785 1.325 0 2.464.097 2.796.141v3.24h-1.921c-1.5 0-1.792.721-1.792 1.771v2.311h3.584l-.465 3.63H16.56V24h6.115c.733 0 1.325-.592 1.325-1.324V1.324C24 .593 23.408 0 22.676 0%22%20%2F%3E%3C%2Fsvg%3E"); }
.icon__svg {
padding: 10px;
display: block;
font-family: "Flaticon";
font-size: 64px;
line-height: 1;
transform: translate(-10px, -9px); }
/*
Flaticon icon font: Flaticon
*/
@font-face {
font-family: "Flaticon";
src: url("../assets/fonts/Flaticon.eot");
src: url("../assets/fonts/Flaticon.eot?#iefix") format("embedded-opentype"), url("../assets/fonts/Flaticon.woff") format("woff"), url("../assets/fonts/Flaticon.ttf") format("truetype"), url("../assets/images/Flaticon.svg#Flaticon") format("svg");
font-weight: normal;
font-style: normal; }
@media screen and (-webkit-min-device-pixel-ratio: 0) {
@font-face {
font-family: "Flaticon";
src: url("../assets/images/Flaticon.svg#Flaticon") format("svg"); } }
.fi:before {
display: inline-block;
font-family: "Flaticon";
font-style: normal;
font-weight: normal;
font-variant: normal;
line-height: 1;
text-decoration: inherit;
text-rendering: optimizeLegibility;
text-transform: none;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-smoothing: antialiased; }
.flaticon-sad-2:before {
content: "\f100"; }
.flaticon-sad-1:before {
content: "\f101"; }
.flaticon-neutral:before {
content: "\f102"; }
.flaticon-happy-2:before {
content: "\f103"; }
.flaticon-sad:before {
content: "\f104"; }
.flaticon-happy-1:before {
content: "\f105"; }
.flaticon-happy:before {
content: "\f106"; }
html {
box-sizing: border-box; }
html {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%; }
body {
margin: 0; }
a {
background-color: transparent;
-webkit-text-decoration-skip: objects;
text-decoration: none;
color: black; }
a:active,
a:hover {
outline-width: 0; }
img {
border-style: none; }
html,
body {
font-family: Verdana, sans-serif;
font-size: 15px;
line-height: 1.5; }
html {
overflow-x: hidden; }
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Roboto', sans-serif; }
/* Change autocomplete styles in WebKit */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus input:-webkit-autofill,
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover textarea:-webkit-autofill:focus,
select:-webkit-autofill,
select:-webkit-autofill:hover,
select:-webkit-autofill:focus {
border: 0px solid white;
-webkit-text-fill-color: black;
-webkit-box-shadow: 0 0 0px 1000px white inset;
transition: background-color 5000s ease-in-out 0s; }
.g__dialog-title {
margin: 0px;
padding: 24px 24px 20px;
color: rgba(0, 0, 0, 0.87);
font-size: 22px;
line-height: 32px;
font-weight: 400; }
.g__circle-black {
color: rgba(0, 0, 0, 0.87);
background: rgba(0, 0, 0, 0.26);
transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;
box-sizing: border-box;
font-family: Roboto, sans-serif;
-webkit-tap-highlight-color: transparent;
box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 6px, rgba(0, 0, 0, 0.12) 0px 1px 4px;
border-radius: 50%;
display: inline-block;
margin: 0px 8px;
height: 36px;
cursor: pointer;
width: 36px; }
.g__circle-black:hover {
transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;
background: rgba(0, 0, 0, 0.42);
top: 0px; }
.g__circle {
color: rgba(0, 0, 0, 0.87);
background-color: #eeeeee;
transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;
box-sizing: border-box;
font-family: Roboto, sans-serif;
-webkit-tap-highlight-color: transparent;
box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 6px, rgba(0, 0, 0, 0.12) 0px 1px 4px;
border-radius: 50%;
display: inline-block;
margin: 0px 8px;
height: 36px;
cursor: pointer;
width: 36px; }
.g__circle:hover {
transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;
background-color: rgba(0, 0, 0, 0.04);
top: 0px; }
.g__title, .g__title-center {
color: rgba(0, 0, 0, 0.54);
font-size: 16px;
font-weight: 500;
margin: 32px 0 0;
white-space: nowrap;
-webkit-flex-shrink: 1;
flex-shrink: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis; }
.g__title-center {
display: flex;
justify-content: center;
padding: 10px;
margin: 22px auto;
max-width: 300px; }
.g__greenColor {
color: #6d9828; }
.g__greenBox {
background-color: #6d9828 !important; }
.glob__shadow {
box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.2), 0 4px 20px 0 rgba(0, 0, 0, 0.19); }
.global__color-teal {
color: #58d09f; }
.global__color-gold {
color: #FFD700; }
.global__color-lightGrey {
color: #ada7a7; }
input[type="file"] {
display: none; }
.global__hidden {
display: none; }
.global__scroll-CH::-webkit-scrollbar {
width: 5px; }
.global__scroll-CH::-webkit-scrollbar-track {
background: #ddd; }
.global__scroll-CH::-webkit-scrollbar-thumb {
background: #666; }
.global__scroll-IE {
scrollbar-base-color: #C0C0C0;
scrollbar-base-color: #C0C0C0;
scrollbar-dlight-color: #C0C0C0;
scrollbar-highlight-color: #C0C0C0;
scrollbar-track-color: #EBEBEB;
scrollbar-arrow-color: black;
scrollbar-shadow-color: #C0C0C0;
scrollbar-dark-shadow-color: #C0C0C0; }
.g-load-more {
text-align: center;
padding-top: 4px;
background-color: #ffffff59;
padding-bottom: 4px;
width: 76px;
margin: 3px auto 15px;
border-radius: 9px; }
g__input-underline::before {
display: none; }
g__input-underline::after {
display: none; }
.master__progress {
position: fixed;
top: 0;
top: 56px;
z-index: 1501;
width: 100%; }
.master__loading {
position: fixed;
top: 67px;
z-index: 1501;
width: 100%;
justify-content: center; }
.master__loading div.title {
color: white;
font-size: 11px;
text-align: center;
font-weight: 500;
white-space: nowrap;
-webkit-flex-shrink: 1;
flex-shrink: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
background-color: #db4437;
padding: 7px;
border-radius: 40px; }
.master__message {
position: fixed;
top: 5;
left: 0;
text-align: center;
z-index: 1001;
width: 100%; }
.profile__parallax {
height: 455px;
border-radius: 2px;
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.14); }
.profile__title, .people__title {
color: rgba(0, 0, 0, 0.54);
font-size: 16px;
font-weight: 500;
margin: 32px 0 0;
white-space: nowrap;
-webkit-flex-shrink: 1;
flex-shrink: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis; }
.profile__head-info {
justify-content: space-between;
position: relative;
box-sizing: border-box;
height: 108px;
margin-top: -108px;
padding: 24px;
flex-direction: row;
align-items: center;
background-color: transparent;
background-image: -webkit-linear-gradient(transparent, rgba(0, 0, 0, 0.46));
background-image: linear-gradient(transparent, rgba(0, 0, 0, 0.46));
display: flex; }
.profile__head-info div.left {
display: flex;
flex-direction: row;
justify-content: space-between; }
.profile__head-info div.left div.info {
display: flex;
text-align: left;
margin-left: 24px;
flex-direction: column; }
.profile__head-info div.left div.info div.fullName {
font-size: 30px;
font-weight: 500;
color: #fff; }
.profile__head-info div.left div.info div.tagLine {
background: rgba(255, 255, 255, 0.2);
color: #eae9e9;
padding: 4px;
border-radius: 2px; }
.profile__head-info div.left div.info div.followers {
color: #fff;
margin-top: 8px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
font-size: 14px; }
.profile__head-info div.right {
display: flex;
flex-direction: row;
justify-content: space-between; }
.profile__head-info-s, .profile__edit {
display: flex;
justify-content: space-between;
position: relative;
box-sizing: border-box;
height: 241px;
margin-top: -45px;
padding: 0 24px;
flex-direction: column;
justify-content: center;
align-items: center; }
.profile__head-info-s div.left, .profile__edit div.left {
display: flex;
flex-direction: column;
justify-content: space-between; }
.profile__head-info-s div.left div.profile__avatar, .profile__edit div.left div.profile__avatar {
display: flex;
justify-content: center; }
.profile__head-info-s div.left div.info, .profile__edit div.left div.info {
display: flex;
text-align: left;
margin-top: 24px;
flex-direction: column; }
.profile__head-info-s div.left div.info div.fullName, .profile__edit div.left div.info div.fullName {
font-size: 30px;
font-weight: 500;
color: #191818;
display: flex;
justify-content: center; }
.profile__head-info-s div.left div.info div.followers, .profile__edit div.left div.info div.followers {
color: #383838;
margin-top: 8px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-break: break-all;
font-size: 14px;
display: flex;
justify-content: center; }
.profile__head-info-s div.right, .profile__edit div.right {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 24px; }
.profile__edit {
margin-top: -60px;
height: 171px; }
.sendFeedback__content {
position: fixed;
right: 5px;
bottom: 5px;
z-index: 1; }
.sendFeedback__content .paper {
width: 350px;
height: 100%;
margin: 20px;
text-align: center; }
.sendFeedback__content .main-box {
padding: 26px 26px 0px 26px; }
.sendFeedback__content .buttons {
margin-top: 20px;
margin-left: 50px;
position: relative; }
.sendFeedback__content .close {
position: absolute;
top: 13px;
right: 13px; }
.sendFeedback__content .success {
padding: 30px; }
.sendFeedback__content .error {
padding: 30px; }
.sendFeedback__content .loading {
padding: 18px 0px 0px 0px; }
.sendFeedback__content .loading .icon {
justify-content: center;
align-items: center;
align-content: center;
align-self: center; }
.user-box__add-circle {
position: absolute;
right: 16px;
bottom: 69px; }
.homeHeader__title-root {
flex: 1; }
.homeHeader__title {
border-left: 1px solid #fff;
padding-left: 24px;
margin-left: 24px;
line-height: 32px;
font-weight: 500;
font-family: Roboto, RobotoDraft, Helvetica, Arial, sans-serif;
font-size: 20px;
-webkit-font-smoothing: antialiased;
color: #fff; }
.homeHeader__right {
padding-left: 30px;
padding-right: 30px;
position: relative;
margin-left: -24px;
display: flex;
justify-content: space-between;
align-items: center; }
.homeHeader__left {
padding-left: 30px;
padding-right: 30px; }
.homeHeader__notify {
color: rgba(0, 0, 0, 0.87);
background-color: #ff1717;
transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;
box-sizing: border-box;
font-family: Roboto, sans-serif;
-webkit-tap-highlight-color: transparent;
border-radius: 50%;
display: inline-block;
height: 20px;
cursor: pointer;
width: 21px;
display: flex;
justify-content: center;
align-items: center; }
.homeHeader__notify div.title {
color: white;
font-size: 10px;
font-weight: 100;
white-space: nowrap;
-webkit-flex-shrink: 1;
flex-shrink: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis; }
.homeHeader__notify-menu {
background-color: #eee !important;
background: #e5e5e5 !important;
border: 1px solid #ccc !important;
color: #000 !important;
min-width: 376px !important;
width: 376px !important;
height: 380px !important;
display: block !important;
outline: none !important;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2) !important; }
.homeHeader__notify-menu div.container {
padding: 10px 0px 10px 0px;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
position: relative; }
.homeHeader__notify-menu div.container div.title {
display: flex;
justify-content: center;
color: rgba(102, 102, 102, 0.57);
font-size: 26px;
font-weight: 500;
width: 100%; }
.homeHeader__notify-menu div.container div.content {
width: 100%;
height: 100%;
padding: 10px 0px; }
.homeHeader__notify-menu div.container div.content div.item {
width: 100%;
height: 54px;
background-color: white;
margin-bottom: 10px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
display: flex;
padding: 10px 0px 10px 0px;
flex-direction: row;
align-items: center;
position: relative; }
.homeHeader__notify-menu div.container div.content div.item div.avatar {
margin-left: 5px; }
.homeHeader__notify-menu div.container div.content div.item div.info {
margin-left: 10px;
height: 100%;
width: 100%;
overflow: hidden; }
.homeHeader__notify-menu div.container div.content div.item div.info div.user-name {
color: rgba(0, 0, 0, 0.77);
font-size: 15px;
font-weight: 500;
white-space: nowrap;
-webkit-flex-shrink: 1;
flex-shrink: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis; }
.homeHeader__notify-menu div.container div.content div.item div.info div.description {
color: rgba(0, 0, 0, 0.54);
font-size: 14px;
font-weight: 200;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis; }
.homeHeader__notify-menu div.container div.content div.item div.close {
position: absolute;
right: 17px;
top: 3px;
height: 10px;
width: 10px; }
.home__main {
background-color: #eeeeee;
transition: margin-left .4s; }
@media screen and (max-width: 750px) {
.home__main {
margin-left: 0 !important;
margin-right: 0 !important; } }
.sidebar {
padding-top: 64px;
background-color: #fff;
max-width: 210px;
height: 100%;
width: 200px;
position: fixed !important;
z-index: 1;
overflow: hidden; }
.sidebar__large {
background-color: #eeeeee !important;
z-index: 1000; }
.sidebar__over {
z-index: 1102;
padding-top: 0;
background-color: #ffffff;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
z-index: 1111; }
.sidebar__title {
font-size: 20px;
font-weight: 500;
padding-right: 16px;
font-family: Roboto, sans-serif;
position: relative;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
margin-left: 15px; }
.blog {
margin: 0 auto;
width: 90%; }
@media (min-width: 993px) {
.blog__right-list {
margin-left: 2%; } }
.comment__list-show > div:nth-of-type(1) {
z-index: 3;
animation: commentSlideShow 12s linear 0s infinite;
position: absolute;
top: 0;
left: 0;
background-color: white;
height: 60px;
width: 100%; }
.comment__list-show > div:nth-of-type(2) {
z-index: 2;
animation: commentSlideShow 12s linear 4s infinite;
position: absolute;
top: 0;
left: 0;
background-color: white;
height: 60px;
width: 100%; }
.comment__list-show > div:nth-of-type(3) {
z-index: 1;
animation: commentSlideShow 12s linear 8s infinite;
position: absolute;
top: 0;
left: 0;
background-color: white;
height: 60px;
width: 100%; }
@keyframes commentSlideShow {
25% {
opacity: 1; }
33.33% {
opacity: 0; }
91.66% {
opacity: 0; }
100% {
opacity: 1; } }
.people__name {
display: flex;
word-break: break-word;
max-width: 100%;
align-items: center;
padding: 10px;
justify-content: center; }
.people__name div {
color: rgba(0, 0, 0, 0.87);
font-size: 16px;
line-height: 20px;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
overflow: hidden;
text-overflow: ellipsis;
max-height: 40px; }
.login__button-box, .signup__button-box, .settings__button-box {
display: flex;
justify-content: space-around; }
.signup__button-box {
margin-top: 30px; }
.mLoading__body {
background-color: #d8d8d8; }
.mLoading__loading {
position: fixed;
z-index: 2001;
height: 2em;
width: 2em;
overflow: show;
margin: auto;
top: 0;
left: 0;
bottom: 0;
right: 0; }
/* Transparent Overlay */
.mLoading__loading:before {
content: '';
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.65); }
/* :not(:required) hides these rules from IE9 and below */
.mLoading__loading:not(:required) {
/* hide "mLoading__loading..." text */
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0; }

View File

@@ -1,7 +0,0 @@
let expect = require('expect')
describe('App', () => {
it('should properly run tests', () => {
expect(1).toBe(1)
})
})

View File

@@ -1,9 +1,6 @@
{
"compilerOptions": {
"module": "es6",
"target": "es6",
"lib": ["es7", "dom"],
"types": ["reflect-metadata"],
"allowSyntheticDefaultImports": true, // see below
"baseUrl": "./src/", // enables you to import relative to this folder
@@ -18,20 +15,35 @@
"layouts/*": ["layouts/*"],
"models/*": ["models/*"]
},
"sourceMap": true, // make TypeScript generate sourcemaps
"outDir": "public", // output directory to build to (irrelevant because we use Webpack most of the time)
"jsx": "preserve", // enable JSX mode, but "preserve" tells TypeScript to not transform it (we'll use Babel)
"strict": true,
"outDir": "build/dist",
"module": "esnext",
"target": "es5",
"lib": ["es7", "dom"],
"sourceMap": true,
"allowJs": true,
"jsx": "react",
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowJs": true
"rootDir": "src",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": false,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": false,
"experimentalDecorators": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
"node_modules",
"build",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts"
]
}

View File

@@ -1,3 +1,102 @@
{
"extends": "tslint-config-standard"
}
"extends": ["tslint-react"],
"rules": {
"ban": false,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"eofline": false,
"forin": true,
"ter-indent": [
true,
2,
{
"SwitchCase": 1
}
],
"interface-name": [false, "always-prefix"],
"jsdoc-format": true,
"no-extra-boolean-cast": true,
"jsx-self-close": false,
"jsx-no-lambda": false,
"jsx-no-multiline-js": false,
"jsx-no-bind": false,
"jsx-boolean-value": false,
"jsx-alignment": false,
"label-position": true,
"member-ordering": [
true,
"public-before-private",
"static-before-instance",
"variables-before-functions"
],
"no-any": false,
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-consecutive-blank-lines": true,
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-eval": true,
"no-shadowed-variable": false,
"no-string-literal": false,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": false,
"no-unused-expression": true,
"no-use-before-declare": false,
"one-line": [
true,
"check-catch",
"check-else",
"check-open-brace",
"check-whitespace"
],
"quotemark": [true, "single", "avoid-escape", "jsx-single"],
"radix": true,
"semicolon": [true, "never"],
"switch-default": true,
"trailing-comma": [false],
"triple-equals": [ true, "allow-null-check" ],
"typedef": [
true,
"parameter",
"property-declaration"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-rest-spread",
"check-type",
"check-typecast",
"check-type-operator",
"check-preblock"
]
}
}

View File

@@ -1,156 +0,0 @@
var webpack = require('webpack');
var path = require('path');
var envFile = require('node-env-file');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
console.log(process.env.NODE_ENV);
try {
envFile(path.join(__dirname, 'config/' + process.env.NODE_ENV + '.env'));
} catch (e) {
}
const devEntry = [
'react-hot-loader/patch',
'webpack-hot-middleware/client',
'./src/index.tsx'
];
module.exports = {
entry: (process.env.NODE_ENV === 'production') ? ['./src/index.tsx'] : devEntry,
externals: {
jquery: 'jQuery'
},
plugins: (process.env.NODE_ENV === 'production') ? [
new webpack.optimize.UglifyJsPlugin({
minimize: true,
compressor: {
warnings: false
}
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
API_KEY: JSON.stringify(process.env.API_KEY),
AUTH_DOMAIN: JSON.stringify(process.env.AUTH_DOMAIN),
DATABASE_URL: JSON.stringify(process.env.DATABASE_URL),
STORAGE_BUCKET: JSON.stringify(process.env.STORAGE_BUCKET),
PROJECT_ID: JSON.stringify(process.env.PROJECT_ID),
MESSAGING_SENDER_ID: JSON.stringify(process.env.MESSAGING_SENDER_ID),
HOST_URL: JSON.stringify(process.env.HOST_URL)
}
})
] : [
new webpack.HotModuleReplacementPlugin(),
new OpenBrowserPlugin({ url: `http://localhost:${process.env.PORT}` }),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
API_KEY: JSON.stringify(process.env.API_KEY),
AUTH_DOMAIN: JSON.stringify(process.env.AUTH_DOMAIN),
DATABASE_URL: JSON.stringify(process.env.DATABASE_URL),
STORAGE_BUCKET: JSON.stringify(process.env.STORAGE_BUCKET),
PROJECT_ID: JSON.stringify(process.env.PROJECT_ID),
MESSAGING_SENDER_ID: JSON.stringify(process.env.MESSAGING_SENDER_ID),
HOST_URL: JSON.stringify(process.env.HOST_URL),
PORT: JSON.stringify(process.env.PORT)
}
})
],
output: {
publicPath: '/',
path: path.resolve(__dirname, './public'),
filename: 'bundle-v0.5.2.js',
},
resolve: {
modules: [
__dirname,
path.resolve(__dirname, 'node_modules')
],
alias: {
src: 'src',
components: 'src/components',
reducers: 'src/reducers',
constants: 'src/constants',
core: 'src/core',
data: 'src/data',
api: 'src/api',
layouts: 'src/layouts',
routes: 'src/routes',
models: 'src/models',
store: 'src/store',
applicationStyles: 'src/styles/app.scss',
actions: 'src/actions',
actionTypes: 'src/constants/actionTypes.jsx'
},
extensions: [' ', '.scss', ".ts", ".tsx", ".js", '.jsx']
},
module: {
rules: [{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader'
},
{
loader: 'ts-loader',
options: { transpileOnly: true }
}
]
},
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
},
{
test: /\.js(x?)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.scss$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "sass-loader",
options: {
includePaths: [
]
}
}]
},
{
test: /\.css$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader"
}]
},
{
test: /\.(woff|woff2|eot|ttf|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
loader: 'url-loader'
}, {
test: /\.(jpe?g|png|webp|gif|cur)$/,
loader: 'file-loader?name=/images/[name].[ext]'
}
]
},
devtool: process.env.NODE_ENV === 'production' ? undefined : 'cheap-module-eval-source-map'
};

8124
yarn.lock Normal file

File diff suppressed because it is too large Load Diff