Browse Source

Initial commit

master
Dwayne Harris 5 years ago
parent
commit
c635df41fd
  1. 7375
      package-lock.json
  2. 40
      package.json
  3. 67
      src/apps/text-app/composer/app.tsx
  4. 12
      src/apps/text-app/composer/index.ejs
  5. 8
      src/apps/text-app/composer/index.tsx
  6. 60
      src/apps/text-app/composer/webpack.config.ts
  7. 91
      src/communicator/index.ts
  8. 25
      src/server/index.ts
  9. 33
      src/styles/default.scss
  10. 16
      tsconfig.json

7375
package-lock.json
File diff suppressed because it is too large
View File

40
package.json

@ -0,0 +1,40 @@
{
"name": "flexor-apps",
"description": "Default set of Flexor Apps.",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "node dist/server/index.js",
"build": "tsc",
"build:text-app": "webpack --config src/apps/text-app/composer/webpack.config.ts"
},
"devDependencies": {
"@types/html-webpack-plugin": "^3.2.1",
"@types/mini-css-extract-plugin": "^0.8.0",
"@types/react": "^16.9.9",
"@types/react-dom": "^16.9.2",
"@types/webpack": "^4.39.5",
"bulma": "^0.8.0",
"css-loader": "^3.2.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.12.0",
"pino-pretty": "^3.2.2",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"ts-loader": "^6.2.0",
"ts-node": "^8.4.1",
"typescript": "^3.6.4",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.9"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.25",
"@fortawesome/free-solid-svg-icons": "^5.11.2",
"@fortawesome/react-fontawesome": "^0.1.7",
"fastify": "^2.10.0",
"fastify-static": "^2.5.0",
"react": "^16.10.2",
"react-dom": "^16.10.2"
}
}

67
src/apps/text-app/composer/app.tsx

@ -0,0 +1,67 @@
import React, { FC, useState, useEffect } from 'react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faEyeSlash } from '@fortawesome/free-solid-svg-icons'
import { Communicator } from '../../../communicator'
import '../../../styles/default.scss'
interface Props {
communicator: Communicator
}
const App: FC<Props> = ({ communicator }) => {
const maxCharacters = 256
const [content, setContent] = useState('')
const [cover, setCover] = useState('')
const charactersLeft = maxCharacters - content.length
const showCharactersLeft = charactersLeft < (maxCharacters / 2)
const showCharactersStyle = charactersLeft > (maxCharacters * 0.1) ? 'has-text-danger' : ''
const buttonStyle = 'button is-primary is-small' + (charactersLeft < 1 ? ' is-disabled' : '')
useEffect(() => {
const init = async () => {
try {
await communicator.setHeight(document.body.offsetHeight)
} catch (err) {
console.error('App Component: ', err)
}
}
init()
}, [])
return (
<div>
<div className="field">
<div className="control">
<textarea className="textarea" placeholder="What it do?" value={content} onChange={(e) => setContent(e.target.value)} />
</div>
</div>
<div className="field">
<p className="control has-icons-left">
<input className="input" type="text" placeholder="Cover Text" value={cover} onChange={(e) => setCover(e.target.value)} />
<span className="icon is-small is-left">
<FontAwesomeIcon icon={faEyeSlash} />
</span>
</p>
</div>
<nav className="level">
<div className="level-left">
<div className="level-item">
{showCharactersLeft && <p className={showCharactersStyle}>{charactersLeft} Chars Left</p>}
</div>
</div>
<div className="level-right">
<div className="level-item">
<button className={buttonStyle}>Post!</button>
</div>
</div>
</nav>
</div>
)
}
export default App

12
src/apps/text-app/composer/index.ejs

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Flexor</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app"></div>
</body>
</html>

8
src/apps/text-app/composer/index.tsx

@ -0,0 +1,8 @@
import React from 'react'
import { render } from 'react-dom'
import App from './app'
import { Communicator } from '../../../communicator'
const communicator = new Communicator('f279a4e81056b0db2d0f')
render(<App communicator={communicator} />, document.getElementById('app'))

60
src/apps/text-app/composer/webpack.config.ts

@ -0,0 +1,60 @@
import { resolve } from 'path'
import { Configuration } from 'webpack'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'
const config: Configuration = {
mode: 'development',
devtool: 'eval-source-map',
entry: {
app: resolve(__dirname, './index.tsx'),
},
output: {
path: resolve(__dirname, '../../../../dist/apps/text-app/'),
// publicPath: '/',
filename: '[name].js',
},
optimization: {
splitChunks: {
chunks: 'all',
},
},
resolve: {
extensions: ['.ts', '.tsx', '.js'],
},
module: {
rules: [
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: 'ts-loader',
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
title: 'Text App',
hash: true,
template: resolve(__dirname, './index.ejs'),
filename: 'composer.html',
}),
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
}
export default config

91
src/communicator/index.ts

@ -0,0 +1,91 @@
export interface MessageContent {
[key: string]: any
height?: number
}
export interface IncomingMessageData {
name: string
content: MessageContent
publicKey: string
}
export interface OutgoingMessageData {
name: string
content?: MessageContent
error?: string
settings?: object
}
interface Listener {
resolve: (value: unknown) => void
reject: (reason: any) => void
once: boolean
}
interface ListenerCollection {
[name: string]: Listener
}
interface AppSettings {
[key: string]: any
}
export class Communicator {
private origin = 'http://localhost:8080'
private publicKey: string
private listeners: ListenerCollection
private settings?: AppSettings
constructor(publicKey: string) {
this.publicKey = publicKey
this.listeners = {}
window.addEventListener('message', (event: MessageEvent) => {
if (event.origin !== this.origin) return
try {
const data = JSON.parse(event.data) as OutgoingMessageData
this.emit(data)
} catch (err) {
console.error(err)
return
}
}, false)
}
private emit(data: OutgoingMessageData) {
const listener = this.listeners[data.name]
if (listener) {
if (data.content) listener.resolve(data.content)
if (data.error) listener.reject(data.error)
if (listener.once) delete this.listeners[data.name]
}
}
private async postAndReceive(name: string, content?: MessageContent) {
if (window.parent) {
window.parent.postMessage(JSON.stringify({
name,
content,
publicKey: this.publicKey,
}), this.origin)
return new Promise((resolve, reject) => {
this.listeners[name] = {
resolve,
reject,
once: true,
}
})
}
}
async init() {
return this.postAndReceive('init')
}
async setHeight(height: number) {
return this.postAndReceive('setHeight', { height })
}
}

25
src/server/index.ts

@ -0,0 +1,25 @@
import { resolve } from 'path'
import fastify from 'fastify'
import fastifyStatic from 'fastify-static'
const port = 8082
const server = fastify({
logger: {
level: 'info',
prettyPrint: true,
}
})
server.register(fastifyStatic, {
root: resolve(__dirname, '..', 'apps'),
})
const start = async () => {
try {
await server.listen(port)
} catch (err) {
process.exit(1)
}
}
start()

33
src/styles/default.scss

@ -0,0 +1,33 @@
@charset "utf-8";
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700&display=swap');
// Colors
$orange: hsl(14, 100%, 53%);
$yellow: hsl(48, 100%, 67%);
$green: hsl(141, 65%, 31%);
$turquoise: hsl(171, 100%, 41%);
$cyan: hsl(204, 86%, 53%);
$blue: hsl(217, 72%, 30%);
$purple: hsl(271, 63%, 32%);
$red: hsl(348, 71%, 42%);
$grey: hsl(0, 0%, 48%);
$grey-light: hsl(0, 0%, 71%);
$grey-lighter: hsl(0, 0%, 86%);
$white-ter: hsl(0, 0%, 96%);
$white-bis: hsl(0, 0%, 98%);
$family-sans-serif: "Open Sans", sans-serif;
$primary: $blue;
$body-size: 14px;
@import "../../node_modules/bulma/sass/utilities/_all.sass";
@import "../../node_modules/bulma/sass/base/_all.sass";
@import "../../node_modules/bulma/sass/form/_all.sass";
@import "../../node_modules/bulma/sass/elements/button.sass";
@import "../../node_modules/bulma/sass/elements/icon.sass";
@import "../../node_modules/bulma/sass/components/level.sass";
body {
padding: 10px;
}

16
tsconfig.json

@ -0,0 +1,16 @@
{
"compilerOptions": {
"outDir": "./dist/server/",
"baseUrl": ".",
"sourceMap": true,
"strict": true,
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"jsx": "react",
"resolveJsonModule": true
},
"include": [
"src/server/*"
]
}
Loading…
Cancel
Save