Added react for photos face and identity editor
Signed-off-by: James Ketrenos <james_gitlab@ketrenos.com>
This commit is contained in:
parent
2037a3f636
commit
ae4022f657
4
.babelrc
Normal file
4
.babelrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": [ "@babel/env", "@babel/preset-react" ],
|
||||
"plugins": [ "@babel/plugin-proposal-class-properties" ]
|
||||
}
|
@ -1,20 +1,18 @@
|
||||
{
|
||||
"db": {
|
||||
"photos": {
|
||||
"host": "sqlite:db/photos.db",
|
||||
"options": {
|
||||
"logging" : false,
|
||||
"timezone": "+00:00",
|
||||
"operatorsAliases": false
|
||||
}
|
||||
"dialect": "sqlite",
|
||||
"host": "db/photos.db",
|
||||
"logging" : false,
|
||||
"timezone": "+00:00",
|
||||
"operatorsAliases": 0
|
||||
},
|
||||
"users": {
|
||||
"host": "sqlite:db/users.db",
|
||||
"options": {
|
||||
"logging" : false,
|
||||
"timezone": "+00:00",
|
||||
"operatorsAliases": false
|
||||
}
|
||||
"dialect": "sqlite",
|
||||
"host": "db/users.db",
|
||||
"logging" : false,
|
||||
"timezone": "+00:00",
|
||||
"operatorsAliases": 0
|
||||
}
|
||||
},
|
||||
"ldap": {
|
||||
|
52
package.json
52
package.json
@ -5,7 +5,13 @@
|
||||
"main": "server/app.js",
|
||||
"scripts": {
|
||||
"start": "node ./server/app.js",
|
||||
"faces": "node ./server/face-recognizer.js"
|
||||
"faces": "node ./server/face-recognizer.js",
|
||||
"dev": "webpack-dev-server --mode development --host 0.0.0.0 --config webpack.dev.js",
|
||||
"build": "webpack --config webpack.prod.js",
|
||||
"commit-build": "./commit-build.sh",
|
||||
"watch": "webpack --config webpack.prod.js --watch",
|
||||
"update": "./update.sh",
|
||||
"backend": "NODE_CONFIG_ENV='production' node server/app.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -17,20 +23,25 @@
|
||||
"face-recognition": "^0.9.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tensorflow/tfjs-core": "^1.5.1",
|
||||
"@tensorflow/tfjs-node": "^1.5.1",
|
||||
"@tensorflow/tfjs-core": "^1.5.2",
|
||||
"@tensorflow/tfjs-node": "^1.5.2",
|
||||
"animakit-expander": "^2.1.4",
|
||||
"bluebird": "^3.7.2",
|
||||
"body-parser": "^1.19.0",
|
||||
"bootstrap": "^4.4.1",
|
||||
"canvas": "^2.6.1",
|
||||
"config": "^1.31.0",
|
||||
"config": "^3.1.0",
|
||||
"connect-sqlite3": "^0.9.11",
|
||||
"cookie-parser": "^1.4.4",
|
||||
"core-js": "^3.2.1",
|
||||
"exif-reader": "github:paras20xx/exif-reader",
|
||||
"express": "^4.17.1",
|
||||
"express-session": "^1.17.0",
|
||||
"face-api.js": "^0.22.0",
|
||||
"handlebars": "^4.5.3",
|
||||
"ldapauth-fork": "^4.2.0",
|
||||
"googleapis": "^40.0.0",
|
||||
"handlebars": "^4.7.2",
|
||||
"jira-connector": "^2.10.0",
|
||||
"ldapauth-fork": "^4.3.0",
|
||||
"ldapjs": "^1.0.2",
|
||||
"mariasql": "^0.2.6",
|
||||
"moment": "^2.24.0",
|
||||
@ -38,13 +49,38 @@
|
||||
"morgan": "^1.9.1",
|
||||
"mustache": "^3.2.1",
|
||||
"node-fetch": "^2.6.0",
|
||||
"nodemailer": "^4.7.0",
|
||||
"node-gzip": "^1.1.2",
|
||||
"nodemailer": "^6.3.0",
|
||||
"qs": "^6.9.1",
|
||||
"sequelize": "^4.44.3",
|
||||
"react-app-polyfill": "^1.0.2",
|
||||
"react-bootstrap": "^1.0.0-beta.16",
|
||||
"react-date-range": "^1.0.0-beta",
|
||||
"react-markdown": "^4.2.2",
|
||||
"react-router-dom": "^5.0.1",
|
||||
"react-scroll": "^1.7.14",
|
||||
"react-syntax-highlighter": "^11.0.2",
|
||||
"sequelize": "^5.21.3",
|
||||
"sequelize-mysql": "^1.7.0",
|
||||
"sharp": "^0.20.8",
|
||||
"sqlite3": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.1.0",
|
||||
"@babel/core": "^7.1.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.4.4",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"babel-loader": "^8.0.2",
|
||||
"css-loader": "^1.0.0",
|
||||
"file-loader": "^4.1.0",
|
||||
"react": "^16.8",
|
||||
"react-dom": "^16.8",
|
||||
"style-loader": "^0.23.0",
|
||||
"webpack": "^4.19.1",
|
||||
"webpack-cli": "^3.1.1",
|
||||
"webpack-dev-server": "^3.3.1",
|
||||
"webpack-merge": "^4.2.1"
|
||||
},
|
||||
"jshintConfig": {
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
|
@ -20,7 +20,7 @@ const fs = require('fs'),
|
||||
|
||||
function init() {
|
||||
const db = {
|
||||
sequelize: new Sequelize(config.get("db.photos.host"), config.get("db.photos.options")),
|
||||
sequelize: new Sequelize(config.get("db.photos")),
|
||||
Sequelize: Sequelize
|
||||
};
|
||||
|
||||
|
@ -18,7 +18,7 @@ const Sequelize = require('sequelize'),
|
||||
|
||||
function init() {
|
||||
const db = {
|
||||
sequelize: new Sequelize(config.get("db.users.host"), config.get("db.users.options")),
|
||||
sequelize: new Sequelize(config.get("db.users")),
|
||||
Sequelize: Sequelize
|
||||
};
|
||||
|
||||
|
180
src/App.css
Executable file
180
src/App.css
Executable file
@ -0,0 +1,180 @@
|
||||
body {
|
||||
font-family: 'Droid Sans', 'Arial Narrow', Arial, sans-serif;
|
||||
}
|
||||
|
||||
#spinner {
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-left: -30px;
|
||||
margin-top: -30px;
|
||||
z-index: 100;
|
||||
background-image: url(../frontend/icons-512.png);
|
||||
background-color: #0071C5;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#spinner.spin {
|
||||
display: inline-block;
|
||||
-webkit-animation:spin 1s linear infinite;
|
||||
-moz-animation:spin 1s linear infinite;
|
||||
animation:spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
|
||||
@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
|
||||
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
|
||||
|
||||
.Header {
|
||||
background-color: #252525;
|
||||
color: #ffffff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.Header .Group {
|
||||
height: 60px;
|
||||
display: flex;
|
||||
padding-left: 1em;
|
||||
padding-right: calc(1em + 52px);
|
||||
background-color: #0071C5;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.Header .Group .Subtitle {
|
||||
font-size: 0.7em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.Header .Group .Heading {
|
||||
margin: 0 auto;
|
||||
width: calc(100% - 8em);
|
||||
max-width: 90em;
|
||||
}
|
||||
|
||||
.Header .Pages {
|
||||
height: 60px;
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
width: calc(100% - 8em);
|
||||
max-width: 90em;
|
||||
/* justify-content: space-between;*/
|
||||
font-size: 1.2em;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.Header .Pages .Link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0.5em 1em;
|
||||
border-bottom: 3px solid transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.Header .Pages .Link.Highlight {
|
||||
border-bottom-color: #0071C5 !important;
|
||||
}
|
||||
|
||||
.Header .Pages .Link.Active,
|
||||
.Header .Pages .Link:hover {
|
||||
border-bottom-color: #003663;
|
||||
/*border-bottom-color: #00A7FF;*/
|
||||
}
|
||||
|
||||
a.Link {
|
||||
font-family: Oswald;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.Footer {
|
||||
position: fixed;
|
||||
background-color: #252525;
|
||||
color: #ffffff;
|
||||
height: 64px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 0.9em;
|
||||
font-family: Droid Sans;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.Footer .Copyright {
|
||||
position: absolute;
|
||||
line-height: 64px;
|
||||
text-align: center;
|
||||
left: 64px;
|
||||
right: 64px;
|
||||
}
|
||||
|
||||
.Body {
|
||||
position: absolute;
|
||||
margin-top: 120px; /* .Header's two 60px chunks */
|
||||
margin-bottom: 64px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
box-sizing: border-box;
|
||||
background-image: linear-gradient(#090B1A, #131524);
|
||||
color: #ffffff;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.Body > * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.Main {
|
||||
display: inline-flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-image: url(../frontend/icons-512.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
|
||||
.Content {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
margin: 1em auto;
|
||||
width: calc(100% - 8em);
|
||||
max-width: 90em;
|
||||
color: black;
|
||||
z-index: 10;
|
||||
background-color: #fff;
|
||||
overflow-y: scroll;
|
||||
scroll-behavior: smooth;
|
||||
padding: 1.5em 1.5em 0 1.5em;
|
||||
box-sizing: border-box;
|
||||
transition: top 1s ease-in-out;
|
||||
top: -100%;
|
||||
}
|
||||
|
||||
.Content #MinBox {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
min-height: calc(100% - 2.5em);
|
||||
padding-bottom: 1.3em;
|
||||
}
|
||||
|
||||
.OnScreen {
|
||||
top: 0px;
|
||||
}
|
91
src/App.js
Executable file
91
src/App.js
Executable file
@ -0,0 +1,91 @@
|
||||
/* Polyfills for IE */
|
||||
import 'react-app-polyfill/ie11';
|
||||
import 'core-js/features/array/find';
|
||||
import 'core-js/features/array/includes';
|
||||
import 'core-js/features/number/is-nan';
|
||||
|
||||
/* App starts here */
|
||||
import React from "react";
|
||||
import { withRouter, NavLink, Route, Switch } from "react-router-dom";
|
||||
import Modal from "react-bootstrap/Modal";
|
||||
import Button from "react-bootstrap/Button";
|
||||
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
|
||||
/* Custom components */
|
||||
|
||||
import './modest.css';
|
||||
import "./App.css";
|
||||
|
||||
class Header extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="Header">
|
||||
<Logo/>
|
||||
<div>Header</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Logo extends React.Component {
|
||||
render() {
|
||||
return <NavLink to="/"><div className="Logo"></div></NavLink>
|
||||
}
|
||||
}
|
||||
|
||||
class Footer extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="Footer">
|
||||
<div className="Copyright">Copyright 2020 James Ketrenos</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function noChange() {};
|
||||
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const location = this.props.history.location.pathname;
|
||||
console.log(`App.mounted at ${location}`);
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log("App");
|
||||
return (
|
||||
<div className="App" ref={ ref => (this.app = ref) }>
|
||||
<Header/>
|
||||
<div className="Body">
|
||||
<div className="Main">
|
||||
<Switch>
|
||||
<Route path="/identities" render={ (props) => <div {...props}/> }/>
|
||||
<Route path="/faces" render={ props => <div {...props}/> }/>
|
||||
<Route path="/photos" render={ props => <div {...props}/> }/>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(App);
|
15
src/index.js
Normal file
15
src/index.js
Normal file
@ -0,0 +1,15 @@
|
||||
import React from "react";
|
||||
import { render } from "react-dom";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import App from "./App.js";
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log('DEVELOPMENT mode!');
|
||||
}
|
||||
|
||||
render(
|
||||
<BrowserRouter basename="/">
|
||||
<App/>
|
||||
</BrowserRouter>,
|
||||
document.getElementById("root")
|
||||
)
|
200
src/modest.css
Normal file
200
src/modest.css
Normal file
@ -0,0 +1,200 @@
|
||||
@media print {
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
background: transparent !important;
|
||||
color: #000 !important;
|
||||
box-shadow: none !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
a,
|
||||
a:visited {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a[href]:after {
|
||||
content: " (" attr(href) ")";
|
||||
}
|
||||
|
||||
abbr[title]:after {
|
||||
content: " (" attr(title) ")";
|
||||
}
|
||||
|
||||
a[href^="#"]:after,
|
||||
a[href^="javascript:"]:after {
|
||||
content: "";
|
||||
}
|
||||
|
||||
pre,
|
||||
blockquote {
|
||||
border: 1px solid #999;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
thead {
|
||||
display: table-header-group;
|
||||
}
|
||||
|
||||
tr,
|
||||
img {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
p,
|
||||
h2,
|
||||
h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
pre,
|
||||
code {
|
||||
font-family: Menlo, Monaco, "Courier New", monospace;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: .5rem;
|
||||
line-height: 1.25;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
a,
|
||||
a:visited {
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus,
|
||||
a:active {
|
||||
color: #2980b9;
|
||||
}
|
||||
|
||||
.modest-no-decoration {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 32rem) and (max-width: 48rem) {
|
||||
html {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 48rem) {
|
||||
html {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
p,
|
||||
.modest-p {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 1.3rem;
|
||||
}
|
||||
|
||||
h1,
|
||||
.modest-h1,
|
||||
h2,
|
||||
.modest-h2,
|
||||
h3,
|
||||
.modest-h3,
|
||||
h4,
|
||||
.modest-h4 {
|
||||
margin: 1.414rem 0 .5rem;
|
||||
font-weight: inherit;
|
||||
line-height: 1.42;
|
||||
}
|
||||
|
||||
h1,
|
||||
.modest-h1 {
|
||||
margin-top: 0;
|
||||
font-size: 3.998rem;
|
||||
}
|
||||
|
||||
h2,
|
||||
.modest-h2 {
|
||||
font-size: 2.827rem;
|
||||
}
|
||||
|
||||
h3,
|
||||
.modest-h3 {
|
||||
font-size: 1.999rem;
|
||||
}
|
||||
|
||||
h4,
|
||||
.modest-h4 {
|
||||
font-size: 1.414rem;
|
||||
}
|
||||
|
||||
h5,
|
||||
.modest-h5 {
|
||||
font-size: 1.121rem;
|
||||
}
|
||||
|
||||
h6,
|
||||
.modest-h6 {
|
||||
font-size: .88rem;
|
||||
}
|
||||
|
||||
small,
|
||||
.modest-small {
|
||||
font-size: .707em;
|
||||
}
|
||||
|
||||
/* https://github.com/mrmrs/fluidity */
|
||||
|
||||
img,
|
||||
canvas,
|
||||
iframe,
|
||||
video,
|
||||
svg,
|
||||
select,
|
||||
textarea {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@import url(https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300,300italic,700);
|
||||
|
||||
@import url(https://fonts.googleapis.com/css?family=Arimo:700,700italic);
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: Arimo, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
border-bottom: 2px solid #fafafa;
|
||||
margin-bottom: 1.15rem;
|
||||
padding-bottom: .5rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 8px solid #fafafa;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
pre,
|
||||
code {
|
||||
background-color: #fafafa;
|
||||
}
|
33
webpack.common.js
Normal file
33
webpack.common.js
Normal file
@ -0,0 +1,33 @@
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/index.js",
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
loader: "babel-loader",
|
||||
options: { presets: ["@babel/env"] }
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ["style-loader", "css-loader"]
|
||||
},
|
||||
{
|
||||
test: /\.(png|svg|jpg|md)$/,
|
||||
use: [ "file-loader" ]
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ["*", ".js", ".jsx"]
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist/"),
|
||||
publicPath: "./dist/",
|
||||
filename: "bundle.js"
|
||||
}
|
||||
};
|
||||
|
18
webpack.dev.js
Normal file
18
webpack.dev.js
Normal file
@ -0,0 +1,18 @@
|
||||
const path = require("path");
|
||||
const merge = require('webpack-merge')
|
||||
const common = require('./webpack.common.js');
|
||||
const webpack = require('webpack');
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: "development",
|
||||
devServer: {
|
||||
contentBase: path.join(__dirname, "/"),
|
||||
port: 8765,
|
||||
publicPath: "http://localhost:8765/dist/",
|
||||
hotOnly: true,
|
||||
disableHostCheck: true,
|
||||
historyApiFallback: true
|
||||
},
|
||||
plugins: [new webpack.HotModuleReplacementPlugin()]
|
||||
});
|
||||
|
8
webpack.prod.js
Normal file
8
webpack.prod.js
Normal file
@ -0,0 +1,8 @@
|
||||
const merge = require('webpack-merge')
|
||||
const common = require('./webpack.common.js');
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: "production",
|
||||
devtool: 'source-map'
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user