Skip to content

Commit

Permalink
Merge pull request #191 from virtualidentityag/OB-Theme
Browse files Browse the repository at this point in the history
feat: added extensions connecta
  • Loading branch information
web-mi authored Feb 12, 2024
2 parents 4167e44 + cd948eb commit 5a75919
Show file tree
Hide file tree
Showing 49 changed files with 1,370 additions and 25 deletions.
Binary file removed public/favicon.ico
Binary file not shown.
Binary file added public/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/logo192.png
Binary file not shown.
Binary file removed public/logo512.png
Binary file not shown.
25 changes: 0 additions & 25 deletions public/manifest.json

This file was deleted.

17 changes: 17 additions & 0 deletions src/extensions/components/legalInformationLinks/Imprint.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { useTenant } from '../../../..';
import { LegalPageWrapper } from '../legalPageWrapper/LegalPageWrapper';
import useDocumentTitle from '../../utils/useDocumentTitle';

export const Imprint = () => {
const [t] = useTranslation();
const tenant = useTenant();
useDocumentTitle(t('profile.footer.imprint'));
return (
<LegalPageWrapper
content={tenant?.content?.impressum || t('profile.footer.imprint')}
className={'terms'}
/>
);
};
19 changes: 19 additions & 0 deletions src/extensions/components/legalInformationLinks/Privacy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { useTenant } from '../../../..';
import { LegalPageWrapper } from '../legalPageWrapper/LegalPageWrapper';
import useDocumentTitle from '../../utils/useDocumentTitle';

export const Privacy = () => {
const [t] = useTranslation();
const tenant = useTenant();
useDocumentTitle(t('profile.footer.dataprotection'));
return (
<LegalPageWrapper
content={
tenant?.content?.privacy || t('profile.footer.dataprotection')
}
className={'terms'}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { useTenant } from '../../../..';

import { LegalPageWrapper } from '../legalPageWrapper/LegalPageWrapper';
import useDocumentTitle from '../../utils/useDocumentTitle';

export const TermsAndConditions = () => {
const [t] = useTranslation();
const tenant = useTenant();
useDocumentTitle(t('legal.termsAndConditions.label'));
return (
<LegalPageWrapper
content={
tenant?.content?.termsAndConditions ||
t('legal.termsAndConditions.label')
}
className="terms"
/>
);
};
26 changes: 26 additions & 0 deletions src/extensions/components/legalPageWrapper/LegalPageWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import clsx from 'clsx';
import * as React from 'react';

import { Stage } from '../stage/stage';
import htmlParser from '../../resources/scripts/util/htmlParser';
import './legalPageWrapper.styles.scss';

export interface LegalPageWrapperProps {
className?: string;
content: string;
}
export const LegalPageWrapper = ({
className,
content
}: LegalPageWrapperProps) => {
return (
<div className={clsx('legalPageWrapper stageLayout', className)}>
<Stage className="stageLayout__stage" />
<div className={clsx('stageLayout__content', className)}>
<section className="template">
{typeof content === 'string' && htmlParser(content)}
</section>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.legalPageWrapper {
@include breakpoint($fromLarge) {
.stage {
display: flex;
}
}

.template {
h2 + p,
h3 + p,
h4 + p {
margin-top: 0.3rem;
}
ol {
counter-reset: item;
li {
display: block;
}

li::before {
content: counters(item, '.') '. ';
counter-increment: item;
font-weight: bold;
}

ol {
counter-reset: item;
}
}
}

.stageLayout__content {
align-items: flex-start;
justify-content: flex-start;
padding-top: 120px;

@include breakpoint($fromLarge) {
width: calc(60vw - 160px);
left: calc(40vw + 80px);
}
}
}
Binary file added src/extensions/components/stage/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
153 changes: 153 additions & 0 deletions src/extensions/components/stage/stage.styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
$loginOverlayDelayDesktop: 1s;
$loginOverlayDelayMobile: 2.5s;
$transitionDuration: 1.4s;
$transitionCurve: ease;
$iconSize: 55px;
$gridSpacing: $grid-base-four;

.stage {
background-color: var(--skin-color-primary, $primary);
color: var(--text-color-contrast-switch, $white);
flex-direction: column;
padding: $grid-base-four $grid-base-four $grid-base-eight;
display: none;

@include breakpoint($fromXLarge) {
display: flex;
padding: 60px $grid-base-ten $grid-base-ten;
}

&__headline {
margin-top: auto;
word-break: normal;
text-align: left;

h1 {
margin-bottom: $grid-base;
font-size: 32px;
font-weight: $font-weight-bold;

@include breakpoint($fromXLarge) {
margin-bottom: $grid-base-three;
font-size: 40px;
line-height: 50px;
}
}

h4 {
margin: 0;
text-align: left;
font-size: $font-size-primary;
font-weight: $font-weight-regular;

@include breakpoint($fromXLarge) {
font-size: 24px;
line-height: 32px;
}
}
}

&--animated {
display: flex;
width: 100vw;

&.stage--animation-done {
display: none;

@include breakpoint($fromXLarge) {
display: flex;
}
}

h1 {
@include breakpoint($fromXLarge) {
transform: scale(1.5);
transform-origin: bottom left;

@keyframes headlineAnimation {
from {
transform: scale(1.5);
}
to {
transform: none;
}
}

animation: headlineAnimation 1s $loginOverlayDelayDesktop
$transitionCurve forwards;
}
}

&.stage--ready {
animation: overlayAnimation $transitionDuration
$loginOverlayDelayMobile $transitionCurve forwards;
}

@keyframes overlayAnimation {
from {
left: 0;
}
to {
left: -100vw;
}
}

@include breakpoint($fromXLarge) {
&.stage--ready {
animation: overlayAnimation 1s $loginOverlayDelayDesktop
$transitionCurve forwards;
}

@keyframes overlayAnimation {
from {
width: 100vw;
}
to {
width: 40vw;
}
}
}
}

&__spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation: hideSpinner 4s 2s ease forwards;

&.spinner * {
background-color: var(--skin-color-secondary, #{$white});
}

@include breakpoint($fromXLarge) {
animation-duration: 2s;
top: auto;
left: auto;
right: 114px;
bottom: 114px;
}

@keyframes hideSpinner {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
}

&__logo {
width: 200px;
height: 200px;
background-repeat: no-repeat;
background-size: contain;
background-position: top left;

@include breakpoint($fromXXLarge) {
width: 225px;
height: 225px;
}
}
}
62 changes: 62 additions & 0 deletions src/extensions/components/stage/stage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as React from 'react';
import { useState, useRef } from 'react';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import clsx from 'clsx';
import './stage.styles';
import { Spinner, useTenant } from '../../../..';
import { config } from '../../resources/scripts/config';
import logo from './logo.png';

export interface StageProps {
className?: string;
hasAnimation?: boolean;
isReady?: boolean;
}

export const Stage = ({
className,
hasAnimation,
isReady = true
}: StageProps) => {
const [t] = useTranslation();
const rootNodeRef = useRef();
const tenant = useTenant();
const [isAnimationDone, setIsAnimationDone] = useState(false);
const isTenantLoaded = tenant != null;

function onAnimationEnd(event) {
// Ignore animations of children
if (event.target === rootNodeRef.current) {
setIsAnimationDone(true);
}
}

return (
<div
ref={rootNodeRef}
onAnimationEnd={onAnimationEnd}
id="loginLogoWrapper"
className={clsx(className, 'stage', {
'stage--animated': hasAnimation,
'stage--animation-done': isAnimationDone,
'stage--ready': isReady
})}
>
{hasAnimation ? <Spinner className="stage__spinner" /> : null}
<Link
to={config.urls.home}
className="stage__logo"
style={{
backgroundImage: `url(${
isTenantLoaded ? tenant?.theming.logo || logo : null
})`
}}
></Link>
<div className="stage__headline">
<h1>{tenant?.name || t('app.stage.title')}</h1>
<h4>{tenant?.content.claim || t('app.claim')}</h4>
</div>
</div>
);
};
24 changes: 24 additions & 0 deletions src/extensions/initApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { App } from '../components/app/app';
import { Stage } from './components/stage/stage';
import { config, routePathNames } from './resources/scripts/config';
import { TermsAndConditions } from './components/legalInformationLinks/TermsAndConditions';
import { Imprint } from './components/legalInformationLinks/Imprint';
import { Privacy } from './components/legalInformationLinks/Privacy';

ReactDOM.render(
<App
config={config}
extraRoutes={[
{
route: { path: routePathNames.termsAndConditions },
component: TermsAndConditions
},
{ route: { path: routePathNames.imprint }, component: Imprint },
{ route: { path: routePathNames.privacy }, component: Privacy }
]}
stageComponent={Stage}
/>,
document.getElementById('appRoot')
);
Loading

0 comments on commit 5a75919

Please sign in to comment.