Dwayne Harris
5 years ago
10 changed files with 7727 additions and 0 deletions
-
7375package-lock.json
-
40package.json
-
67src/apps/text-app/composer/app.tsx
-
12src/apps/text-app/composer/index.ejs
-
8src/apps/text-app/composer/index.tsx
-
60src/apps/text-app/composer/webpack.config.ts
-
91src/communicator/index.ts
-
25src/server/index.ts
-
33src/styles/default.scss
-
16tsconfig.json
7375
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -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" |
|||
} |
|||
} |
@ -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 |
@ -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> |
@ -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')) |
@ -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 |
@ -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 }) |
|||
} |
|||
} |
@ -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() |
@ -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; |
|||
} |
@ -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/*" |
|||
] |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue