Removed the old `d4cience.v2` theme and `admin` part of the `d4science` base theme

This commit is contained in:
Mauro Mugnaini 2024-04-18 12:13:03 +02:00
parent b9deaea561
commit b9ae2f9b6b
Signed by: mauro.mugnaini
GPG Key ID: 2440CFD0EB321EA8
16 changed files with 0 additions and 1052 deletions

View File

@ -16,15 +16,10 @@
"name": "d4science",
"types": [
"account",
"admin",
"email",
"login"
]
},
{
"name": "d4science.v2",
"types": [ "account" ]
},
{
"name": "dante.d4science.org",
"types": [ "login" ]

View File

@ -1,293 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>${msg("accountManagementTitle")}</title>
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="robots" content="noindex, nofollow">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
<#if properties.developmentMode?has_content && properties.developmentMode == "true">
var developmentMode = true;
var reactRuntime = 'react.development.js';
var reactDOMRuntime = 'react-dom.development.js';
var reactRouterRuntime = 'react-router-dom.js';
<#else>
var developmentMode = false;
var reactRuntime = 'react.production.min.js';
var reactDOMRuntime = 'react-dom.production.min.js';
var reactRouterRuntime = 'react-router-dom.min.js';
</#if>
var authUrl = '${authUrl}';
var baseUrl = '${baseUrl}';
var realm = '${realm.name}';
var resourceUrl = '${resourceUrl}';
var isReactLoading = false;
<#if properties.logo?has_content>
var brandImg = resourceUrl + '${properties.logo}';
<#else>
var brandImg = resourceUrl + '/public/logo.svg';
</#if>
<#if properties.logoUrl?has_content>
var brandUrl = '${properties.logoUrl}';
<#else>
var brandUrl = baseUrl;
</#if>
var features = {
isRegistrationEmailAsUsername : ${realm.registrationEmailAsUsername?c},
isEditUserNameAllowed : ${realm.editUsernameAllowed?c},
isInternationalizationEnabled : ${realm.isInternationalizationEnabled()?c},
isLinkedAccountsEnabled : ${realm.identityFederationEnabled?c},
isMyResourcesEnabled : ${(realm.userManagedAccessAllowed && isAuthorizationEnabled)?c},
deleteAccountAllowed : ${deleteAccountAllowed?c},
updateEmailFeatureEnabled: ${updateEmailFeatureEnabled?c},
updateEmailActionEnabled: ${updateEmailActionEnabled?c},
isViewGroupsEnabled : ${isViewGroupsEnabled?c}
}
var availableLocales = [];
<#list supportedLocales as locale, label>
availableLocales.push({locale : '${locale}', label : '${label}'});
</#list>
<#if referrer??>
var referrer = '${referrer}';
var referrerName = '${referrerName}';
var referrerUri = '${referrer_uri}'.replace('&amp;', '&');
</#if>
<#if msg??>
var locale = '${locale}';
<#outputformat "JavaScript">
var l18nMsg = JSON.parse('${msgJSON?js_string}');
</#outputformat>
<#else>
var locale = 'en';
var l18Msg = {};
</#if>
</script>
<#if properties.favIcon?has_content>
<link rel="icon" href="${resourceUrl}${properties.favIcon}" type="image/x-icon"/>
<#else>
<link rel="icon" href="${resourceUrl}/public/favicon.ico" type="image/x-icon"/>
</#if>
<script src="${authUrl}js/keycloak.js"></script>
<#if properties.developmentMode?has_content && properties.developmentMode == "true">
<!-- Don't use this in production: -->
<script src="${resourceUrl}/node_modules/react/umd/react.development.js" crossorigin></script>
<script src="${resourceUrl}/node_modules/react-dom/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
</#if>
<#if properties.extensions?has_content>
<#list properties.extensions?split(' ') as script>
<#if properties.developmentMode?has_content && properties.developmentMode == "true">
<script type="text/babel" src="${resourceUrl}/${script}"></script>
<#else>
<script type="text/javascript" src="${resourceUrl}/${script}"></script>
</#if>
</#list>
</#if>
<#if properties.scripts?has_content>
<#list properties.scripts?split(' ') as script>
<script type="text/javascript" src="${resourceUrl}/${script}"></script>
</#list>
</#if>
<script>
var content = <#include "resources/content.json"/>
</script>
<link rel="stylesheet" href="${resourceCommonUrl}/node_modules/@patternfly/react-core/dist/styles/base.css"/>
<link rel="stylesheet" href="${resourceCommonUrl}/node_modules/@patternfly/patternfly/patternfly-addons.css"/>
<link rel="stylesheet" href="${resourceUrl}/public/app.css"/>
<link rel="stylesheet" href="${resourceUrl}/public/layout.css"/>
<#if properties.styles?has_content>
<#list properties.styles?split(' ') as style>
<link href="${resourceUrl}/${style}" rel="stylesheet"/>
</#list>
</#if>
</head>
<body>
<script>
var keycloak = new Keycloak({
authServerUrl: authUrl,
realm: realm,
clientId: 'account-console'
});
keycloak.init({onLoad: 'check-sso', pkceMethod: 'S256', promiseType: 'native'}).then((authenticated) => {
isReactLoading = true;
toggleReact();
if (!keycloak.authenticated) {
document.getElementById("landingSignInButton").style.display='inline';
document.getElementById("landingSignInLink").style.display='inline';
} else {
document.getElementById("landingSignOutButton").style.display='inline';
document.getElementById("landingSignOutLink").style.display='inline';
document.getElementById("landingLoggedInUser").innerHTML = loggedInUserName('${msg("unknownUser")}', '${msg("fullName")}');
}
loadjs("/Main.js");
}).catch(() => {
alert('failed to initialize keycloak');
});
</script>
<div id="main_react_container" style="display:none;height:100%"></div>
<div id="spinner_screen" style="display:block; height:100%">
<div style="width: 320px; height: 328px; text-align: center; position: absolute; top:0; bottom: 0; left: 0; right: 0; margin: auto;">
<#if properties.logo?has_content>
<img src="${resourceUrl}${properties.logoOnLoading}" alt="Logo" class="brand">
<#else>
<img src="${resourceUrl}/public/logo.svg" alt="Logo" class="brand">
</#if>
<p>${msg("loadingMessage")}</p>
<div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: rgb(255, 255, 255); display: block; shape-rendering: auto;" width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<path d="M10 50A40 40 0 0 0 90 50A40 42 0 0 1 10 50" fill="#5DBCD2" stroke="none" transform="rotate(16.3145 50 51)">
<animateTransform attributeName="transform" type="rotate" dur="1s" repeatCount="indefinite" keyTimes="0;1" values="0 50 51;360 50 51"></animateTransform>
</path>
</svg>
</div>
</div>
</div>
<div id="welcomeScreen" style="display:none;height:100%">
<div class="pf-c-page" id="page-layout-default-nav">
<header role="banner" class="pf-c-page__header">
<div class="pf-c-page__header-brand">
<#if properties.logoUrl?has_content>
<a id="landingLogo" class="pf-c-page__header-brand-link" href="${properties.logoUrl}">
<#else>
<a id="landingLogo" class="pf-c-page__header-brand-link" href="${baseUrl}">
</#if>
<#if properties.logo?has_content>
<img class="pf-c-brand brand" src="${resourceUrl}${properties.logo}" alt="Logo">
<#else>
<img class="pf-c-brand brand" src="${resourceUrl}/public/logo.svg" alt="Logo">
</#if>
</a>
</div>
<div class="pf-c-page__header-tools">
<#if referrer?has_content && referrer_uri?has_content>
<div class="pf-c-page__header-tools-group pf-m-icons pf-u-display-none pf-u-display-flex-on-md">
<a id="landingReferrerLink" href="${referrer_uri}" class="pf-c-button pf-m-link" tabindex="0">
<span class="pf-c-button__icon pf-m-start">
<i class="pf-icon pf-icon-arrow" aria-hidden="true"></i>
</span>
${msg("backTo",referrerName)}
</a>
</div>
</#if>
<div class="pf-c-page__header-tools-group pf-m-icons pf-u-display-none pf-u-display-flex-on-md pf-u-mr-md">
<button id="landingSignInButton" tabindex="0" style="display:none" onclick="keycloak.login();" class="pf-c-button pf-m-primary" type="button">${msg("doSignIn")}</button>
<button id="landingSignOutButton" tabindex="0" style="display:none" onclick="keycloak.logout();" class="pf-c-button pf-m-primary" type="button">${msg("doSignOut")}</button>
</div>
<!-- Kebab for mobile -->
<div class="pf-c-page__header-tools-group pf-u-display-none-on-md">
<div id="landingMobileKebab" class="pf-c-dropdown pf-m-mobile" onclick="toggleMobileDropdown();"> <!-- pf-m-expanded -->
<button aria-label="Actions" tabindex="0" id="landingMobileKebabButton" class="pf-c-dropdown__toggle pf-m-plain" type="button" aria-expanded="true" aria-haspopup="true">
<svg fill="currentColor" height="1em" width="1em" viewBox="0 0 192 512" aria-hidden="true" role="img" style="vertical-align: -0.125em;"><path d="M96 184c39.8 0 72 32.2 72 72s-32.2 72-72 72-72-32.2-72-72 32.2-72 72-72zM24 80c0 39.8 32.2 72 72 72s72-32.2 72-72S135.8 8 96 8 24 40.2 24 80zm0 352c0 39.8 32.2 72 72 72s72-32.2 72-72-32.2-72-72-72-72 32.2-72 72z" transform=""></path></svg>
</button>
<ul id="landingMobileDropdown" aria-labelledby="landingMobileKebabButton" class="pf-c-dropdown__menu pf-m-align-right" role="menu" style="display:none">
<#if referrer?has_content && referrer_uri?has_content>
<li role="none">
<a id="landingMobileReferrerLink" href="${referrer_uri}" role="menuitem" tabindex="0" aria-disabled="false" class="pf-c-dropdown__menu-item">${msg("backTo",referrerName)}</a>
</li>
</#if>
<li id="landingSignInLink" role="none" style="display:none">
<a onclick="keycloak.login();" role="menuitem" tabindex="0" aria-disabled="false" class="pf-c-dropdown__menu-item">${msg("doLogIn")}</a>
</li>
<li id="landingSignOutLink" role="none" style="display:none">
<a onclick="keycloak.logout();" role="menuitem" tabindex="0" aria-disabled="false" class="pf-c-dropdown__menu-item">${msg("doSignOut")}</a>
</li>
</ul>
</div>
</div>
<span id="landingLoggedInUser"></span>
</div> <!-- end header tools -->
</header>
<main role="main" class="pf-c-page__main">
<section class="pf-c-page__main-section pf-m-limit-width pf-m-light pf-m-shadow-bottom">
<div class="pf-c-page__main-body">
<div class="pf-c-content" id="landingWelcomeMessage">
<h1>${msg("accountManagementWelcomeMessage")}</h1>
</div>
</div>
</section>
<section class="pf-c-page__main-section pf-m-limit-width pf-m-overflow-scroll">
<div class="pf-c-page__main-body">
<div class="pf-l-gallery pf-m-gutter">
<#assign content=theme.apply("content.json")?eval>
<#list content as item>
<div class="pf-l-gallery__item" id="landing-${item.id}">
<div class="pf-c-card pf-m-full-height">
<div>
<div class="pf-c-card__title pf-c-content">
<h2 class="pf-u-display-flex pf-u-w-100 pf-u-flex-direction-column">
<#if item.icon??>
<i class="pf-icon ${item.icon}"></i>
<#elseif item.iconSvg??>
<img src="${item.iconSvg}" alt="icon"/>
</#if>
${msg(item.label)}
</h2>
</div>
<div class="pf-c-card__body">
<#if item.descriptionLabel??>
<p class="pf-u-mb-md">${msg(item.descriptionLabel)}</p>
</#if>
<#if item.content??>
<#list item.content as sub>
<div id="landing-${sub.id}">
<a onclick="toggleReact(); window.location.hash='${sub.path}'">${msg(sub.label)}</a>
</div>
</#list>
<#else>
<a id="landing-${item.id}" onclick="toggleReact(); window.location.hash = '${item.path}'">${msg(item.label)}</a>
</#if>
</div>
</div>
</div>
</div>
</#list>
</div>
</div>
</section>
</main>
</div>
</div>
<script>
const removeHidden = (content) => {
content.forEach(c => {
if (c.hidden && eval(c.hidden)) {
document.getElementById('landing-' + c.id).remove();
}
if (c.content) removeHidden(c.content);
});
}
removeHidden(content);
</script>
</body>
</html>

View File

@ -1,24 +0,0 @@
accountManagementWelcomeMessage=Welcome to Keycloak Extended Account Console
personalBasicInfoHtmlTitle=Basic information
accountExtraInfoHtmlTitleHome=Profile settings
accountExtraSubMessageHome=Handle extra profile settings
accountExtraInfoHtmlTitle=Profile settings
accountExtraSubMessage=Handle profile: add/update your avatar, delete your account
avatarLabel=Avatar
uploadLabel=Select image file
dragdropInfo=Drag and drop an image file or upload one
browseButton=Browse
clearButton=Clear
avatarInfo=A 100x100px size is suggested. Images exceding 250x250px will be resized to 250px width or height mantaining their ratio. The maximum file size permitted is 1MB.
avatarUpdatedMessage=Avatar successfully updated
error-noAvatarFound=No avatar found on server
deleteAccount=Delete Account
deleteAccountInfoMessage=Deleting your account will disable your profile and remove your name and photo you''ve shared on D4Science gateway(s). Some information may still be visible to others, such as your name in the posts and private messages you sent.<br/>All files and folders you created of your workspace will be removed.
deleteAccountDialogHeader=Confirm account delete
deleteAccountWarningMessage=Clicking on the "Confirm" button is an undoable operation, your account will be removed and you'll be automatically logged out from all your sessions.
deleteAccountConfirmMessage=<br/>Do you really want to remove your account? <strong>NOTE: This action is irreversible!</strong>
doDeleteConfirm=Confirm
accountDeletedMessage=Your account has been deleted

View File

@ -1,24 +0,0 @@
accountManagementWelcomeMessage=Benvenuto nella gestione estesa degli account di Keycloak
personalBasicInfoHtmlTitle=Informazioni base
accountExtraInfoHtmlTitleHome=Impostazioni profilo
accountExtraSubMessageHome=Gestisce ulteriori impostazioni associate al profilo
accountExtraInfoHtmlTitle=Impostazioni del profilo
accountExtraSubMessage=Gestisce il profilo: aggiunta/modifica dell''avatar, cancellazione dell''account
avatarLabel=Avatar
uploadLabel=Seleziona un''immagine
dragdropInfo=Trascina qui un file immagine o selezionalo
browseButton=Seleziona
clearButton=Cancella
avatarInfo=Si consiglia una dimensione di 100x100px. Le immagini che eccedono 250x250px saranno ridimensionate a 250px di larghezza o altezza mantenendo il loro rapporto. La massima dimensione consentita del file \u00e8 di 1MB.
avatarUpdatedMessage=Avatar aggiornato con successo
error-noAvatarFound=Avatar non trovato sul server
deleteAccount=Delete Account
deleteAccountInfoMessage=La cancellazione del proprio account disabiliter\u00e0 il profilo e rimuover\u00e0 il nome e le foto condivise sul/sui gateway D4Science. Alcune informazioni potrebbero risultare ancora visibili agli altri utenti, come il nome nei post e nei messaggi privati inviati.<br/>Tutti i file e le cartelle create nel workspace personale saranno rimosse.
deleteAccountDialogHeader=Conferma cancellazione account
deleteAccountWarningMessage=Cliccando sul bottone "Conferma" si avvier\u00e0 un''operazione non annullabile, l''account personale sar\u00e0 rimosso e saranno terminate tutte le sessioni aperte nei vari siti.
deleteAccountConfirmMessage=<br/>Si vuole veramente cancellare il proprio account? <strong>NOTA BENE: Questa azione \u00e8 irreversibile!</strong>
doDeleteConfirm=Conferma
accountDeletedMessage=L''account \u00e8 stato cancellato

View File

@ -1,84 +0,0 @@
[
{
"id": "personal-info",
"path": "personal-info",
"icon": "pf-icon-user",
"label": "personalInfoSidebarTitle",
"descriptionLabel": "personalInfoIntroMessage",
"content" : [
{
"id": "personal-info-base",
"path": "personal-info-base",
"label": "personalBasicInfoHtmlTitle",
"modulePath": "/content/account-page/AccountPage.js",
"componentName": "AccountPage"
},
{
"id": "account-extra",
"path": "account-extra",
"label": "accountExtraInfoHtmlTitleHome",
"modulePath": "/content/d4science-page/AccountExtraPage.js",
"componentName": "AccountExtraPage"
}
]
},
{
"id": "security",
"icon": "pf-icon-security",
"label": "accountSecuritySidebarTitle",
"descriptionLabel": "accountSecurityIntroMessage",
"content": [
{
"id": "signingin",
"path": "security/signingin",
"label": "signingInSidebarTitle",
"modulePath": "/content/signingin-page/SigningInPage.js",
"componentName": "SigningInPage"
},
{
"id": "device-activity",
"path": "security/device-activity",
"label": "deviceActivitySidebarTitle",
"modulePath": "/content/device-activity-page/DeviceActivityPage.js",
"componentName": "DeviceActivityPage"
},
{
"id": "linked-accounts",
"path": "security/linked-accounts",
"label": "linkedAccountsSidebarTitle",
"modulePath": "/content/linked-accounts-page/LinkedAccountsPage.js",
"componentName": "LinkedAccountsPage",
"hidden": "!features.isLinkedAccountsEnabled"
}
]
},
{
"id": "applications",
"icon": "pf-icon-applications",
"path": "applications",
"label": "applications",
"descriptionLabel": "applicationsIntroMessage",
"modulePath": "/content/applications-page/ApplicationsPage.js",
"componentName": "ApplicationsPage"
},
{
"id": "groups",
"path": "groups",
"icon": "pf-icon-server-group",
"label": "groupLabel",
"descriptionLabel": "groupDescriptionLabel",
"modulePath": "/content/group-page/GroupsPage.js",
"componentName": "GroupsPage",
"hidden": "!features.isViewGroupsEnabled"
},
{
"id": "resources",
"icon": "pf-icon-repository",
"path": "resources",
"label": "resources",
"descriptionLabel": "resourceIntroMessage",
"modulePath": "/content/my-resources-page/MyResourcesPage.js",
"componentName": "MyResourcesPage",
"hidden": "!features.isMyResourcesEnabled"
}
]

View File

@ -1,110 +0,0 @@
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
import * as React from "../../../resources/web_modules/react.js";
import { PageSection, PageSectionVariants, Button, Grid, GridItem, ExpandableSection, Modal } from "../../../resources/web_modules/@patternfly/react-core.js";
import { AccountServiceContext } from "../../account-service/AccountServiceContext.js";
import { Msg } from "../../widgets/Msg.js";
import { ContentPage } from "../ContentPage.js";
import { ContentAlert } from "../ContentAlert.js";
import { AvatarForm } from "./AvatarForm.js";
export class AccountExtraPage extends React.Component {
constructor(props, context) {
super(props);
_defineProperty(this, "context", void 0);
_defineProperty(this, "DEFAULT_STATE", {
isModalOpen: false
});
_defineProperty(this, "state", this.DEFAULT_STATE);
_defineProperty(this, "handleModalToggle", open => {
this.setState({
isModalOpen: open
});
});
_defineProperty(this, "modalConfirmDelete", event => {
const accountUrl = this.context["accountUrl"];
const deleteUrl = accountUrl + "-delete/request-delete";
this.context.doPost(deleteUrl, {}).then(() => {
ContentAlert.success('accountDeletedMessage');
window.location.reload();
});
this.setState({
isModalOpen: false
});
});
this.context = context;
}
render() {
const accountUrl = this.context["accountUrl"];
return /*#__PURE__*/React.createElement(ContentPage, {
title: "accountExtraInfoHtmlTitle",
introMessage: "accountExtraSubMessage"
}, /*#__PURE__*/React.createElement(PageSection, {
isFilled: true,
variant: PageSectionVariants.light
}, /*#__PURE__*/React.createElement(AvatarForm, {
accountUrl: accountUrl
}), /*#__PURE__*/React.createElement("div", {
id: "delete-account",
style: {
marginTop: "30px"
}
}, /*#__PURE__*/React.createElement(ExpandableSection, {
toggleText: Msg.localize('deleteAccount'),
displaySize: "large"
}, /*#__PURE__*/React.createElement(Grid, {
hasGutter: true
}, /*#__PURE__*/React.createElement(GridItem, {
span: 8
}, /*#__PURE__*/React.createElement("p", {
dangerouslySetInnerHTML: {
__html: Msg.localize('deleteAccountInfoMessage')
}
})), /*#__PURE__*/React.createElement(GridItem, {
span: 4
}, /*#__PURE__*/React.createElement(Button, {
id: "delete-account-btn",
variant: "danger",
onClick: e => this.handleModalToggle(true),
className: "delete-button"
}, /*#__PURE__*/React.createElement(Msg, {
msgKey: "doDelete"
}))))), /*#__PURE__*/React.createElement(Modal, {
width: '50%',
title: Msg.localize('deleteAccountDialogHeader'),
isOpen: this.state.isModalOpen,
onClose: () => this.handleModalToggle(false),
actions: [/*#__PURE__*/React.createElement(Button, {
key: "confirm",
variant: "danger",
onClick: this.modalConfirmDelete
}, /*#__PURE__*/React.createElement(Msg, {
msgKey: "doDeleteConfirm"
})), /*#__PURE__*/React.createElement(Button, {
key: "cancel",
variant: "secondary",
onClick: e => this.handleModalToggle(false)
}, /*#__PURE__*/React.createElement(Msg, {
msgKey: "doCancel"
}))]
}, /*#__PURE__*/React.createElement("div", {
dangerouslySetInnerHTML: {
__html: Msg.localize('deleteAccountWarningMessage')
}
}), /*#__PURE__*/React.createElement("div", {
dangerouslySetInnerHTML: {
__html: Msg.localize('deleteAccountConfirmMessage')
}
})))));
}
}
_defineProperty(AccountExtraPage, "contextType", AccountServiceContext);
//# sourceMappingURL=AccountExtraPage.js.map

View File

@ -1,193 +0,0 @@
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
import * as React from "../../../resources/web_modules/react.js";
import { Form, FormGroup, ActionGroup, FileUpload, Avatar, Button, Tooltip } from "../../../resources/web_modules/@patternfly/react-core.js";
import { OutlinedQuestionCircleIcon } from "../../../resources/web_modules/@patternfly/react-icons.js";
import { AccountServiceContext } from "../../account-service/AccountServiceContext.js";
import { ContentAlert } from "../ContentAlert.js";
import { Msg } from "../../widgets/Msg.js";
export class AvatarForm extends React.Component {
constructor(props, context) {
super(props);
_defineProperty(this, "context", void 0);
_defineProperty(this, "handleFileInputChange", void 0);
_defineProperty(this, "imageScale", (imgData, callback) => {
var img = new Image();
img.src = imgData;
img.onload = event => {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 250;
var MAX_HEIGHT = 250;
var width = img.width;
var height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob(callback);
};
});
_defineProperty(this, "handleSubmit", event => {
event.preventDefault();
const form = event.target;
var formData = new FormData(form);
formData.append("image", this.state.imageBlob);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
if (200 <= xhr.status && xhr.status <= 204) {
ContentAlert.success('avatarUpdatedMessage');
} else {
ContentAlert.danger(xhr.response);
} // force reload avatar
this.setState({
errors: {
avatar: ""
},
imageBlob: null,
filename: "",
avatarSrc: this.state.avatarUrl
});
}
};
xhr.open(form.method, form.action, true);
xhr.send(formData);
});
_defineProperty(this, "handleError", event => {
this.setState({
errors: {
avatar: Msg.localize('error-noAvatarFound')
},
avatarSrc: ""
});
});
this.context = context;
var currentAvatar = props.accountUrl + "-avatar";
this.state = {
errors: {
avatar: ''
},
imageBlob: null,
filename: "",
avatarUrl: currentAvatar,
avatarSrc: currentAvatar,
noAvatarSrc: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMiwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzNiAzNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzYgMzY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRjBGMEYwO30KCS5zdDF7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRDJEMkQyO30KCS5zdDJ7ZmlsbDojQjhCQkJFO30KCS5zdDN7ZmlsbDojRDJEMkQyO30KPC9zdHlsZT4KPHJlY3QgY2xhc3M9InN0MCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjM2Ii8+CjxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0xNy43LDIwLjFjLTMuNSwwLTYuNC0yLjktNi40LTYuNHMyLjktNi40LDYuNC02LjRzNi40LDIuOSw2LjQsNi40UzIxLjMsMjAuMSwxNy43LDIwLjF6Ii8+CjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMy4zLDM2bDAtNi43Yy0yLDAuNC0yLjksMS40LTMuMSwzLjVMMTAuMSwzNkgxMy4zeiIvPgo8cGF0aCBjbGFzcz0ic3QzIiBkPSJNMTAuMSwzNmwwLjEtMy4yYzAuMi0yLjEsMS4xLTMuMSwzLjEtMy41bDAsNi43aDkuNGwwLTYuN2MyLDAuNCwyLjksMS40LDMuMSwzLjVsMC4xLDMuMmg0LjcKCWMtMC40LTMuOS0xLjMtOS0yLjktMTFjLTEuMS0xLjQtMi4zLTIuMi0zLjUtMi42cy0xLjgtMC42LTYuMy0wLjZzLTYuMSwwLjctNi4xLDAuN2MtMS4yLDAuNC0yLjQsMS4yLTMuNCwyLjYKCUM2LjcsMjcsNS44LDMyLjIsNS40LDM2SDEwLjF6Ii8+CjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0yNS45LDM2bC0wLjEtMy4yYy0wLjItMi4xLTEuMS0zLjEtMy4xLTMuNWwwLDYuN0gyNS45eiIvPgo8L3N2Zz4="
};
var reader = new FileReader();
reader.onloadend = event => {
var imgData = String(event.target.result);
this.imageScale(imgData, blob => {
this.setState({
imageBlob: blob,
avatarSrc: URL.createObjectURL(blob)
});
});
};
this.handleFileInputChange = (file, filename) => {
if (filename != "") {
this.setState({
filename: filename
});
reader.readAsDataURL(file);
} else {
this.setState({
imageBlob: null,
filename: "",
avatarSrc: currentAvatar
});
}
};
}
render() {
const {
filename,
avatarUrl,
avatarSrc,
noAvatarSrc
} = this.state;
const avatarStyle = {
objectFit: 'cover',
width: '150px',
height: '150px',
border: '1px solid lightgray',
boxShadow: 'lightgray 6px 3px 10px 2px'
};
return /*#__PURE__*/React.createElement(Form, {
id: "avatarForm",
method: "post",
action: avatarUrl,
encType: "multipart/form-data",
onSubmit: event => this.handleSubmit(event)
}, /*#__PURE__*/React.createElement(FormGroup, {
label: Msg.localize('avatarLabel'),
fieldId: "avatar-current-or-preview",
helperTextInvalid: this.state.errors.avatar,
validated: this.state.errors.avatar === '' ? 'success' : 'error'
}, avatarSrc !== "" ? /*#__PURE__*/React.createElement(Avatar, {
src: avatarSrc,
style: avatarStyle,
alt: "Avatar image preview",
onError: this.handleError
}) : /*#__PURE__*/React.createElement(Avatar, {
src: noAvatarSrc,
style: avatarStyle,
alt: "No avatar found"
})), /*#__PURE__*/React.createElement(FormGroup, {
fieldId: "avatar-upload",
label: /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Msg, {
msgKey: "uploadLabel"
}), ' ', /*#__PURE__*/React.createElement(Tooltip, {
content: /*#__PURE__*/React.createElement(Msg, {
msgKey: "avatarInfo"
})
}, /*#__PURE__*/React.createElement(OutlinedQuestionCircleIcon, null)))
}, /*#__PURE__*/React.createElement(FileUpload, {
id: "simple-file",
filename: filename,
filenamePlaceholder: Msg.localize('dragdropInfo'),
browseButtonText: Msg.localize('browseButton'),
clearButtonText: Msg.localize('clearButton'),
onChange: this.handleFileInputChange
})), /*#__PURE__*/React.createElement(ActionGroup, null, /*#__PURE__*/React.createElement(Button, {
id: "save-btn",
type: "submit",
variant: "primary",
isDisabled: filename === ""
}, /*#__PURE__*/React.createElement(Msg, {
msgKey: "doSave"
}))));
}
}
_defineProperty(AvatarForm, "contextType", AccountServiceContext);
//# sourceMappingURL=AvatarForm.js.map

View File

@ -1,23 +0,0 @@
body {
/* --pf-global--FontFamily--sans-serif: Comic Sans MS; */
/* --pf-global--FontFamily--heading--sans-serif: Comic Sans MS; */
--pf-global--BackgroundColor--dark-100: #303030;
--pf-global--Color--100: #151515;
}
.pf-c-nav__list .pf-c-nav__link {
--pf-c-nav__list-link--Color: #303030;
--pf-c-nav__list-link--m-current--Color: #151515;
}
.pf-c-nav__simple-list .pf-c-nav__link {
--pf-c-nav__simple-list-link--Color: #303030;
--pf-c-nav__simple-list-link--m-current--Color: #151515;
}
.brand {
height: 50px !important;
}

View File

@ -1,90 +0,0 @@
import * as React from 'react';
import { PageSection, PageSectionVariants,Button, Grid, GridItem, ExpandableSection, Modal } from '@patternfly/react-core';
import { AccountServiceContext } from '../../account-service/AccountServiceContext';
import { Msg } from '../../widgets/Msg';
import { ContentPage } from '../ContentPage';
import { ContentAlert } from '../ContentAlert';
import { AvatarForm } from './AvatarForm';
interface AccountExtraPageProps {
}
interface AccountExtraPageState {
isModalOpen: boolean;
}
export class AccountExtraPage extends React.Component<AccountExtraPageProps, AccountExtraPageState> {
static contextType = AccountServiceContext;
context: React.ContextType<typeof AccountServiceContext>;
constructor(props: any) {
super(props)
this.state = { isModalOpen: false }
}
private handleModalToggle = (open: boolean) => {
this.setState({ isModalOpen: open })
}
private modalConfirmDelete = (event: any) => {
const accountUrl = this.context!["accountUrl"]
const deleteUrl = accountUrl + "-delete/request-delete"
this.context!.doPost<void>(deleteUrl, {})
.then(() => {
ContentAlert.success('accountDeletedMessage')
window.location.reload();
})
this.setState({ isModalOpen: false })
}
public render(): React.ReactNode {
const accountUrl = this.context!["accountUrl"]
return (
<ContentPage title="accountExtraInfoHtmlTitle"
introMessage="accountExtraSubMessage"
>
<PageSection isFilled variant={PageSectionVariants.light}>
<AvatarForm accountUrl={accountUrl} />
<div id="delete-account" style={{marginTop:"30px"}}>
<ExpandableSection toggleText={Msg.localize('deleteAccount')} displaySize="large">
<Grid hasGutter>
<GridItem span={8}>
<p dangerouslySetInnerHTML={{ __html: Msg.localize('deleteAccountInfoMessage')}} />
</GridItem>
<GridItem span={4}>
<Button id="delete-account-btn" variant="danger"
onClick={(e) => this.handleModalToggle(true)} className="delete-button"
>
<Msg msgKey="doDelete" />
</Button>
</GridItem>
</Grid>
</ExpandableSection>
<Modal
width={'50%'}
title={Msg.localize('deleteAccountDialogHeader')}
isOpen={this.state.isModalOpen}
onClose={() => this.handleModalToggle(false)}
actions={[
<Button key="confirm" variant="danger" onClick={this.modalConfirmDelete}>
<Msg msgKey="doDeleteConfirm" />
</Button>,
<Button key="cancel" variant="secondary" onClick={(e) => this.handleModalToggle(false)}>
<Msg msgKey="doCancel" />
</Button>
]}
>
<div dangerouslySetInnerHTML={{ __html: Msg.localize('deleteAccountWarningMessage')}} />
<div dangerouslySetInnerHTML={{ __html: Msg.localize('deleteAccountConfirmMessage')}} />
</Modal>
</div>
</PageSection>
</ContentPage>
)
}
}

View File

@ -1,190 +0,0 @@
import * as React from 'react';
import * as CSS from 'csstype';
import { Form, FormGroup, ActionGroup, FileUpload, Avatar, Button, Tooltip } from "@patternfly/react-core";
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
import { AccountServiceContext } from '../../account-service/AccountServiceContext';
import { ContentAlert } from '../ContentAlert';
import { Msg } from '../../widgets/Msg';
interface AvatarFormProps {
accountUrl: string;
}
interface AvatarFormState {
errors: any;
imageBlob: any;
filename: string;
avatarUrl: string;
avatarSrc: string;
noAvatarSrc: string;
}
export class AvatarForm extends React.Component<AvatarFormProps, AvatarFormState> {
static contextType = AccountServiceContext;
context: React.ContextType<typeof AccountServiceContext>;
private handleFileInputChange: any;
constructor(props: AvatarFormProps, context: React.ContextType<typeof AccountServiceContext>) {
super(props);
this.context = context;
var currentAvatar = props.accountUrl + "-avatar"
this.state = {
errors: {avatar: ''},
imageBlob: null,
filename: "",
avatarUrl: currentAvatar,
avatarSrc: currentAvatar,
noAvatarSrc: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI0LjAuMiwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzNiAzNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzYgMzY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRjBGMEYwO30KCS5zdDF7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojRDJEMkQyO30KCS5zdDJ7ZmlsbDojQjhCQkJFO30KCS5zdDN7ZmlsbDojRDJEMkQyO30KPC9zdHlsZT4KPHJlY3QgY2xhc3M9InN0MCIgd2lkdGg9IjM2IiBoZWlnaHQ9IjM2Ii8+CjxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0xNy43LDIwLjFjLTMuNSwwLTYuNC0yLjktNi40LTYuNHMyLjktNi40LDYuNC02LjRzNi40LDIuOSw2LjQsNi40UzIxLjMsMjAuMSwxNy43LDIwLjF6Ii8+CjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0xMy4zLDM2bDAtNi43Yy0yLDAuNC0yLjksMS40LTMuMSwzLjVMMTAuMSwzNkgxMy4zeiIvPgo8cGF0aCBjbGFzcz0ic3QzIiBkPSJNMTAuMSwzNmwwLjEtMy4yYzAuMi0yLjEsMS4xLTMuMSwzLjEtMy41bDAsNi43aDkuNGwwLTYuN2MyLDAuNCwyLjksMS40LDMuMSwzLjVsMC4xLDMuMmg0LjcKCWMtMC40LTMuOS0xLjMtOS0yLjktMTFjLTEuMS0xLjQtMi4zLTIuMi0zLjUtMi42cy0xLjgtMC42LTYuMy0wLjZzLTYuMSwwLjctNi4xLDAuN2MtMS4yLDAuNC0yLjQsMS4yLTMuNCwyLjYKCUM2LjcsMjcsNS44LDMyLjIsNS40LDM2SDEwLjF6Ii8+CjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik0yNS45LDM2bC0wLjEtMy4yYy0wLjItMi4xLTEuMS0zLjEtMy4xLTMuNWwwLDYuN0gyNS45eiIvPgo8L3N2Zz4="
}
var reader = new FileReader()
reader.onloadend = function (event: any) {
var imgData = String(event.target!.result)
this.imageScale(imgData, (blob: Blob) => {
this.setState({
imageBlob: blob,
avatarSrc: URL.createObjectURL(blob)
})
})
}.bind(this)
this.handleFileInputChange = (file: File, filename: string) => {
if (filename != "") {
this.setState({ filename: filename })
reader.readAsDataURL(file)
} else {
this.setState({
imageBlob: null,
filename: "",
avatarSrc: currentAvatar
})
}
}
}
private imageScale = (imgData: string, callback: any) => {
var img = new Image()
img.src = imgData
img.onload = (event: Event) => {
var canvas = document.createElement("canvas")
var ctx = canvas.getContext("2d")
ctx!.drawImage(img, 0, 0)
var MAX_WIDTH = 250
var MAX_HEIGHT = 250
var width = img.width
var height = img.height
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width
width = MAX_WIDTH
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height
height = MAX_HEIGHT
}
}
canvas.width = width
canvas.height = height
ctx = canvas.getContext("2d")
ctx!.drawImage(img, 0, 0, width, height)
canvas.toBlob(callback)
}
}
private handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
event.preventDefault()
const form = event.target as HTMLFormElement
var formData = new FormData(form)
formData.append("image", this.state.imageBlob)
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4) {
if (200 <= xhr.status && xhr.status <= 204) {
ContentAlert.success('avatarUpdatedMessage')
} else {
ContentAlert.danger(xhr.response)
}
// force reload avatar
this.setState({
errors: {avatar: ""},
imageBlob: null,
filename: "",
avatarSrc: this.state.avatarUrl
})
}
}
xhr.open(form.method, form.action, true);
xhr.send(formData);
}
private handleError = (event: any) => {
this.setState({
errors: {avatar: Msg.localize('error-noAvatarFound')},
avatarSrc: ""
})
}
render() {
const { filename, avatarUrl, avatarSrc, noAvatarSrc } = this.state
const avatarStyle: CSS.Properties = {
objectFit: 'cover',
width: '150px', height: '150px',
border: '1px solid lightgray',
boxShadow: 'lightgray 6px 3px 10px 2px'
}
return (
<Form id="avatarForm" method="post"
action={avatarUrl} encType="multipart/form-data"
onSubmit={event => this.handleSubmit(event)}
>
<FormGroup label={Msg.localize('avatarLabel')}
fieldId="avatar-current-or-preview"
helperTextInvalid={this.state.errors.avatar}
validated={this.state.errors.avatar === '' ? 'success' : 'error'}
>
{ avatarSrc !== ""
? <Avatar src={avatarSrc} style={avatarStyle} alt="Avatar image preview" onError={this.handleError}/>
: <Avatar src={noAvatarSrc} style={avatarStyle} alt="No avatar found" />
}
</FormGroup>
<FormGroup
fieldId="avatar-upload"
label={<span>
<Msg msgKey="uploadLabel" />
{' '}
<Tooltip content={<Msg msgKey="avatarInfo" />}>
<OutlinedQuestionCircleIcon />
</Tooltip>
</span>}
>
<FileUpload
id="simple-file"
filename={filename}
filenamePlaceholder={Msg.localize('dragdropInfo')}
browseButtonText={Msg.localize('browseButton')}
clearButtonText={Msg.localize('clearButton')}
onChange={this.handleFileInputChange}
/>
</FormGroup>
<ActionGroup>
<Button
id="save-btn" type="submit"
variant="primary"
isDisabled={filename === ""}
>
<Msg msgKey="doSave" />
</Button>
</ActionGroup>
</Form>
)
}
}

View File

@ -1,14 +0,0 @@
parent=keycloak.v2
# This is the logo in upper lefthand corner.
# It must be a relative path.
logo=/public/d4science-logo.png
logoOnLoading=/public/d4science-logo-black.png
# This is the link followed when clicking on the logo.
# It can be any valid URL, including an external site.
logoUrl=https://www.d4science.org/
# This is the icon for the account console.
# It must be a relative path.
favIcon=/public/favicon.ico