Compare commits

..

27 Commits

Author SHA1 Message Date
655b4a6e11 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-13 11:38:05 +02:00
286603e9aa Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-13 09:38:32 +02:00
d177e2dc3f Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-12 21:56:48 +02:00
c1d7e0daab Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-12 21:15:30 +02:00
42f7ba3473 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-12 15:59:57 +02:00
0db3539627 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-12 14:36:11 +02:00
057a5c1fd0 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-12 13:30:02 +02:00
e32dd866a5 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-12 10:07:04 +02:00
3a102bde60 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-05 17:25:28 +02:00
1a0456ee84 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-05 16:04:30 +02:00
b6b5512471 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-05 14:19:43 +02:00
d02ae87a55 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-10-02 16:39:56 +02:00
aed0048d95 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-09-10 19:28:31 +02:00
98334bafa0 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-09-10 11:21:04 +02:00
8681776283 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-09-08 10:18:51 +02:00
c026b33954 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-08-31 16:13:33 +02:00
ac7fec9e01 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-08-31 15:51:54 +02:00
bbc8f65a47 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-08-26 14:54:34 +02:00
9749ede28a Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-07-23 08:58:04 +02:00
bd133fa9d9 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-07-23 08:29:17 +02:00
ab90365c9c Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-07-17 09:40:03 +02:00
ec6de8a217 Création du lien symbolique vers la configuration du client 2020-07-17 09:24:03 +02:00
17cd58d68f Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-07-16 22:51:53 +02:00
99fb4ac6d9 Correction recette packaging 2020-07-16 22:50:55 +02:00
2ceba1f219 Merge branch 'develop' into dist/ubuntu/bionic/develop 2020-07-16 22:35:27 +02:00
7122677351 Mise à jour règles packaging Debian 2020-07-16 22:33:51 +02:00
1d526a37d0 Empaquetage Debian basique 2020-06-17 18:58:27 +02:00
22 changed files with 190 additions and 48 deletions

View File

@ -9,14 +9,14 @@ import { createClient } from '../util/apollo';
import { ApolloProvider } from '@apollo/client'; import { ApolloProvider } from '@apollo/client';
import { AppLoader } from './AppLoader'; import { AppLoader } from './AppLoader';
const LazyHomePage = React.lazy(() => import(/* webpackChunkName: "HomePage" */'./HomePage/HomePage')); const LazyHomePage = React.lazy(() => import('./HomePage/HomePage'));
const LazyDashboardPage = React.lazy(() => import(/* webpackChunkName: "DashboardPage" */'./DashboardPage/DashboardPage')); const LazyDashboardPage = React.lazy(() => import('./DashboardPage/DashboardPage'));
const LazyUnauthorizedPage = React.lazy(() => import(/* webpackChunkName: "UnauthorizedPage" */'./UnauthorizedPage/UnauthorizedPage')); const LazyUnauthorizedPage = React.lazy(() => import('./UnauthorizedPage/UnauthorizedPage'));
const LazyConferencePage = React.lazy(() => import(/* webpackChunkName: "ConferencePage" */'./ConferencePage/ConferencePage')); const LazyConferencePage = React.lazy(() => import('./ConferencePage/ConferencePage'));
const LazyDecisionSupportFilePage = React.lazy(() => import(/* webpackChunkName: "DecisionSupportFilePage" */'./DecisionSupportFilePage/DecisionSupportFilePage')); const LazyDecisionSupportFilePage = React.lazy(() => import('./DecisionSupportFilePage/DecisionSupportFilePage'));
const LazyProfilePage = React.lazy(() => import(/* webpackChunkName: "ProfilePage" */'./ProfilePage/ProfilePage')); const LazyProfilePage = React.lazy(() => import('./ProfilePage/ProfilePage'));
const LazyWorkgroupPage = React.lazy(() => import(/* webpackChunkName: "WorkgroupPage" */'./WorkgroupPage/WorkgroupPage')); const LazyWorkgroupPage = React.lazy(() => import('./WorkgroupPage/WorkgroupPage'));
const LazyLogoutPage = React.lazy(() => import(/* webpackChunkName: "LogoutPage" */'./LogoutPage')); const LazyLogoutPage = React.lazy(() => import('./LogoutPage'));
export interface AppProps { export interface AppProps {

View File

@ -2,8 +2,6 @@ import React, { FunctionComponent } from "react";
export const AppLoader:FunctionComponent = () => { export const AppLoader:FunctionComponent = () => {
return ( return (
<div className="app-loader"> <div className="loader"></div>
<i className="fas fa-spinner fa-spin fa-5x"></i>
</div>
) )
} }

View File

@ -1,5 +1,6 @@
import React, { FunctionComponent, useState, useEffect } from "react"; import React, { FunctionComponent, useState, useEffect } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { WithLoader } from "./WithLoader";
export interface Item { export interface Item {
id: string id: string

View File

@ -2,16 +2,19 @@ import React from 'react';
import { Page } from '../Page'; import { Page } from '../Page';
import { UserForm } from '../UserForm'; import { UserForm } from '../UserForm';
import { User } from '../../types/user'; import { User } from '../../types/user';
import { useUserProfile } from '../../gql/queries/profile'; import { useUserProfileQuery } from '../../gql/queries/profile';
import { useUpdateUserProfileMutation } from '../../gql/mutations/profile'; import { useUpdateUserProfileMutation } from '../../gql/mutations/profile';
import { WithLoader } from '../WithLoader';
export function ProfilePage() { export function ProfilePage() {
const { user, loading } = useUserProfile(); const userProfileQuery = useUserProfileQuery();
const [ updateProfile, updateUserProfileMutation ] = useUpdateUserProfileMutation(); const [ updateProfile, updateUserProfileMutation ] = useUpdateUserProfileMutation();
const isLoading = updateUserProfileMutation.loading || loading; const isLoading = updateUserProfileMutation.loading || userProfileQuery.loading;
const { userProfile } = (userProfileQuery.data || {});
const onUserChange = (user: User) => { const onUserChange = (user: User) => {
if (user.name !== user.name) { if (userProfile.name !== user.name) {
updateProfile({ variables: {changes: { name: user.name }}}); updateProfile({ variables: {changes: { name: user.name }}});
} }
}; };
@ -24,7 +27,11 @@ export function ProfilePage() {
<div className="column is-6 is-offset-3"> <div className="column is-6 is-offset-3">
<div className="box"> <div className="box">
<h2 className="is-size-2 subtitle">Mon profil</h2> <h2 className="is-size-2 subtitle">Mon profil</h2>
{ !isLoading ? <UserForm onChange={onUserChange} user={user} /> : null } <WithLoader loading={isLoading || !userProfile}>
{
<UserForm onChange={onUserChange} user={userProfile} />
}
</WithLoader>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,18 @@
import React, { Fragment, PropsWithChildren, FunctionComponent } from 'react';
export interface WithLoaderProps {
loading?: boolean|boolean[]
}
export const WithLoader: FunctionComponent<WithLoaderProps> = ({ loading, children }) => {
const isLoading = Array.isArray(loading) ? loading.some(l => l) : loading;
return (
<Fragment>
{
isLoading ?
<div>Chargement</div> :
children
}
</Fragment>
)
}

View File

@ -1,6 +1,8 @@
import React, { FunctionComponent } from 'react'; import React, { FunctionComponent } from 'react';
import { User } from '../../types/user';
import { Workgroup } from '../../types/workgroup'; import { Workgroup } from '../../types/workgroup';
import { InfoForm } from './InfoForm'; import { InfoForm } from './InfoForm';
import { WithLoader } from '../WithLoader';
import { useUpdateWorkgroupMutation, useCreateWorkgroupMutation } from '../../gql/mutations/workgroups'; import { useUpdateWorkgroupMutation, useCreateWorkgroupMutation } from '../../gql/mutations/workgroups';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
@ -41,7 +43,9 @@ export const InfoPanel: FunctionComponent<InfoPanelProps> = ({ workgroup }) => {
Informations Informations
</p> </p>
<div className="panel-block"> <div className="panel-block">
{ !isLoading ? <InfoForm workgroup={workgroup} onChange={onWorkgroupChange} /> : null } <WithLoader loading={isLoading}>
<InfoForm workgroup={workgroup} onChange={onWorkgroupChange} />
</WithLoader>
</div> </div>
</nav> </nav>
); );

View File

@ -4,7 +4,6 @@ export const Config = {
graphQLEndpoint: get<string>("graphQLEndpoint", "http://localhost:8081/api/v1/graphql"), graphQLEndpoint: get<string>("graphQLEndpoint", "http://localhost:8081/api/v1/graphql"),
subscriptionEndpoint: get<string>("subscriptionEndpoint", "ws://localhost:8081/api/v1/graphql"), subscriptionEndpoint: get<string>("subscriptionEndpoint", "ws://localhost:8081/api/v1/graphql"),
conferenceHeartbeatInterval: get<number>("conferenceHeartbeatInterval", 10000), conferenceHeartbeatInterval: get<number>("conferenceHeartbeatInterval", 10000),
frontendBaseURL: get<string>("frontendBaseURL", window.location.protocol + '//' + window.location.host + '/'),
}; };
function get<T>(key: string, defaultValue: T):T { function get<T>(key: string, defaultValue: T):T {

View File

@ -1,8 +1,3 @@
import { Config } from './config';
declare var __webpack_public_path__: string;
__webpack_public_path__ = Config.frontendBaseURL;
import './sass/_all.scss'; import './sass/_all.scss';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
@ -14,7 +9,6 @@ import '@fortawesome/fontawesome-free/js/regular'
import '@fortawesome/fontawesome-free/js/brands' import '@fortawesome/fontawesome-free/js/brands'
import './resources/favicon.png'; import './resources/favicon.png';
ReactDOM.render( ReactDOM.render(
<App />, <App />,
document.getElementById('app') document.getElementById('app')

View File

@ -1,16 +1,44 @@
.app-loader { .loader-container {
@extend body; display: flex;
width: 100%;
display: flex; justify-content: center;
position: absolute; height: 100%;
z-index: 10000; align-items: center;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100vh;
width: 100vw;
align-items: center;
justify-content: center;
flex-direction: column;
} }
.lds-ripple {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
transform: scale(2);
}
.lds-ripple div {
position: absolute;
border: 4px solid $grey;
opacity: 1;
border-radius: 50%;
animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite;
}
.lds-ripple div:nth-child(2) {
animation-delay: -0.5s;
}
@keyframes lds-ripple {
0% {
top: 36px;
left: 36px;
width: 0;
height: 0;
opacity: 1;
}
100% {
top: 0px;
left: 0px;
width: 72px;
height: 72px;
opacity: 0;
}
}

View File

@ -79,9 +79,8 @@ func getServiceContainer(ctx context.Context, conf *config.Config) (*service.Con
// Define default cookie options // Define default cookie options
sessionStore.SessionOpts.Path = "/" sessionStore.SessionOpts.Path = "/"
sessionStore.SessionOpts.HttpOnly = true sessionStore.SessionOpts.HttpOnly = true
sessionStore.SessionOpts.Secure = conf.HTTP.CookieSecure
sessionStore.SessionOpts.MaxAge = conf.HTTP.CookieMaxAge sessionStore.SessionOpts.MaxAge = conf.HTTP.CookieMaxAge
sessionStore.SessionOpts.SameSite = http.SameSiteLaxMode sessionStore.SessionOpts.SameSite = http.SameSiteStrictMode
ctn.Provide( ctn.Provide(
session.ServiceName, session.ServiceName,

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
9

14
debian/control vendored Normal file
View File

@ -0,0 +1,14 @@
Source: daddy
Section: unknown
Priority: optional
Maintainer: Cadoles <contact@cadoles.com>
Build-Depends: debhelper (>= 8.0.0), wget, ca-certificates, tar
Standards-Version: 3.9.4
Homepage: http://forge.cadoles.com/Cadoles/daddy
Vcs-Git: http://forge.cadoles.com/Cadoles/daddy.git
Vcs-Browser: http://forge.cadoles.com/Cadoles/daddy
Package: daddy
Architecture: amd64
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Daddy app

1
debian/daddy.links vendored Normal file
View File

@ -0,0 +1 @@
/etc/daddy/client-config.js /usr/share/daddy/public/config.js

11
debian/daddy.service vendored Normal file
View File

@ -0,0 +1,11 @@
[Unit]
Description=Daddy app
After=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/daddy -workdir /usr/share/daddy -config /etc/daddy/config.yml
Restart=on-failure
[Install]
WantedBy=multi-user.target

56
debian/rules vendored Normal file
View File

@ -0,0 +1,56 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
GO_VERSION := 1.13.5
OS := linux
ARCH := amd64
GOPATH=$(HOME)/go
ifeq (, $(shell which go 2>/dev/null))
override_dh_auto_build: install-go
override_dh_auto_clean: install-go
endif
ifeq (, $(shell which node 2>/dev/null))
override_dh_auto_build: install-nodejs
endif
%:
dh $@ --with systemd
override_dh_auto_build: $(GOPATH)
GOPATH=$(GOPATH) PATH="$(PATH):/usr/local/go/bin:$(GOPATH)/bin" make deps
GOPATH=$(GOPATH) PATH="$(PATH):/usr/local/go/bin:$(GOPATH)/bin" ARCH_TARGETS=$(ARCH) make release
$(GOPATH):
mkdir -p $(GOPATH)
install-go:
wget -nc https://dl.google.com/go/go$(GO_VERSION).$(OS)-$(ARCH).tar.gz
tar -C /usr/local -xzf go$(GO_VERSION).$(OS)-$(ARCH).tar.gz
install-nodejs:
wget -O- https://deb.nodesource.com/setup_12.x | bash -
apt-get install -y nodejs
override_dh_auto_install:
mkdir -p debian/daddy/usr/share/daddy
mkdir -p debian/daddy/etc/daddy
mkdir -p debian/daddy/usr/bin
cp -r release/server-$(OS)-$(ARCH)/* debian/daddy/usr/share/daddy/
mv debian/daddy/usr/share/daddy/bin/server debian/daddy/usr/bin/daddy
mv debian/daddy/usr/share/daddy/server.conf debian/daddy/etc/daddy/config.yml
mv debian/daddy/usr/share/daddy/public/config.js debian/daddy/etc/daddy/client-config.js
install -d debian/daddy
override_dh_strip:
override_dh_auto_test:

1
debian/source/format vendored Normal file
View File

@ -0,0 +1 @@
3.0 (native)

2
go.mod
View File

@ -3,7 +3,7 @@ module forge.cadoles.com/Cadoles/daddy
go 1.14 go 1.14
require ( require (
forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013125038-8d8d1519a52d forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013085949-5d5592098f13
forge.cadoles.com/wpetit/hydra-passwordless v0.0.0-20200908094025-38ac4422dddc // indirect forge.cadoles.com/wpetit/hydra-passwordless v0.0.0-20200908094025-38ac4422dddc // indirect
github.com/99designs/gqlgen v0.11.3 github.com/99designs/gqlgen v0.11.3
github.com/alecthomas/chroma v0.8.1 // indirect github.com/alecthomas/chroma v0.8.1 // indirect

4
go.sum
View File

@ -39,10 +39,6 @@ forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20200619080035-4bbf7b016032 h1:qTYaLP
forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20200619080035-4bbf7b016032/go.mod h1:gkfqGyk7fCj2Z0ngEOCJ3K0FVmqft/8dFV/OnYT1vec= forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20200619080035-4bbf7b016032/go.mod h1:gkfqGyk7fCj2Z0ngEOCJ3K0FVmqft/8dFV/OnYT1vec=
forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013085949-5d5592098f13 h1:gZCo9pX3I3A0xVvXkbhdTDBbW44CypCxjiP5LtNV5bo= forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013085949-5d5592098f13 h1:gZCo9pX3I3A0xVvXkbhdTDBbW44CypCxjiP5LtNV5bo=
forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013085949-5d5592098f13/go.mod h1:phGAWHUGKNZj044478BvRg0jk049uK1IiX2Amh8krAk= forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013085949-5d5592098f13/go.mod h1:phGAWHUGKNZj044478BvRg0jk049uK1IiX2Amh8krAk=
forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013111944-d43b43b636ed h1:7dTCXOGxvAulu9vnOjpt2cTgsuxMHX4FH795/JJgo08=
forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013111944-d43b43b636ed/go.mod h1:phGAWHUGKNZj044478BvRg0jk049uK1IiX2Amh8krAk=
forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013125038-8d8d1519a52d h1:o+Ppy/MyT5UgbtUYI2J1YqS3iuThxOuNFenYoPgKZKk=
forge.cadoles.com/wpetit/goweb-oidc v0.0.0-20201013125038-8d8d1519a52d/go.mod h1:phGAWHUGKNZj044478BvRg0jk049uK1IiX2Amh8krAk=
forge.cadoles.com/wpetit/hydra-passwordless v0.0.0-20200908094025-38ac4422dddc h1:9gc/1qizPtK6/iMVlizknWUFii75ntl2xSUV/FSC92Y= forge.cadoles.com/wpetit/hydra-passwordless v0.0.0-20200908094025-38ac4422dddc h1:9gc/1qizPtK6/iMVlizknWUFii75ntl2xSUV/FSC92Y=
forge.cadoles.com/wpetit/hydra-passwordless v0.0.0-20200908094025-38ac4422dddc/go.mod h1:nANHORi270d5jDXjeJ7B3pMgK9R4J0/17p1IIc+rhOk= forge.cadoles.com/wpetit/hydra-passwordless v0.0.0-20200908094025-38ac4422dddc/go.mod h1:nANHORi270d5jDXjeJ7B3pMgK9R4J0/17p1IIc+rhOk=
github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4= github.com/99designs/gqlgen v0.11.3 h1:oFSxl1DFS9X///uHV3y6CEfpcXWrDUxVblR4Xib2bs4=

View File

@ -47,7 +47,6 @@ type HTTPConfig struct {
CookieAuthenticationKey string `yaml:"cookieAuthenticationKey" env:"HTTP_COOKIE_AUTHENTICATION_KEY"` CookieAuthenticationKey string `yaml:"cookieAuthenticationKey" env:"HTTP_COOKIE_AUTHENTICATION_KEY"`
CookieEncryptionKey string `yaml:"cookieEncryptionKey" env:"HTTP_COOKIE_ENCRYPTION_KEY"` CookieEncryptionKey string `yaml:"cookieEncryptionKey" env:"HTTP_COOKIE_ENCRYPTION_KEY"`
CookieMaxAge int `yaml:"cookieMaxAge" env:"HTTP_COOKIE_MAX_AGE"` CookieMaxAge int `yaml:"cookieMaxAge" env:"HTTP_COOKIE_MAX_AGE"`
CookieSecure bool `yaml:"cookieSecure" env:"HTTP_COOKIE_SECURE"`
TemplateDir string `yaml:"templateDir" env:"HTTP_TEMPLATE_DIR"` TemplateDir string `yaml:"templateDir" env:"HTTP_TEMPLATE_DIR"`
PublicDir string `yaml:"publicDir" env:"HTTP_PUBLIC_DIR"` PublicDir string `yaml:"publicDir" env:"HTTP_PUBLIC_DIR"`
FrontendURL string `yaml:"frontendURL" env:"HTTP_FRONTEND_URL"` FrontendURL string `yaml:"frontendURL" env:"HTTP_FRONTEND_URL"`

View File

@ -0,0 +1,15 @@
server {
listen 80 default_server;
server_name daddy.local;
root /usr/share/daddy/client/public;
index index.html;
location / {
try_files $uri /index.html =404;
}
location /api/v1/graphql {
proxy_pass http://127.0.0.1:8080/api/v1/graphql;
}
}

View File

@ -0,0 +1 @@
GO_ENV=prod

View File

@ -19,7 +19,6 @@ modd.conf {
prep: make test prep: make test
} }
client/webpack.config.js
{ {
daemon: cd client && NODE_ENV=development npm run server -- --display=minimal daemon: cd client && NODE_ENV=development npm run server -- --display=minimal
} }