Compare commits
6 Commits
master
...
translatio
| Author | SHA1 | Date |
|---|---|---|
|
|
a26c468a9d | 2 years ago |
|
|
0f076f4cc4 | 2 years ago |
|
|
f1865db477 | 2 years ago |
|
|
b80127e952 | 2 years ago |
|
|
5e400c5c4e | 2 years ago |
|
|
8367fa4a29 | 2 years ago |
@ -1,53 +0,0 @@
|
|||||||
name: "🐛 Bug Report"
|
|
||||||
description: Report a bug found while using Planka
|
|
||||||
title: "[Bug]: "
|
|
||||||
labels: ["Type: Bug", "Status: Triage"]
|
|
||||||
body:
|
|
||||||
- type: dropdown
|
|
||||||
id: issue-type
|
|
||||||
attributes:
|
|
||||||
label: Where is the problem occurring?
|
|
||||||
description: Select the part of the application where you encountered the issue.
|
|
||||||
options:
|
|
||||||
- "I encountered the problem while using the application (Frontend)"
|
|
||||||
- "I encountered the problem while interacting with the server (Backend)"
|
|
||||||
- "I'm not sure"
|
|
||||||
- type: dropdown
|
|
||||||
id: browsers
|
|
||||||
attributes:
|
|
||||||
label: What browsers are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Brave
|
|
||||||
- Chrome
|
|
||||||
- Firefox
|
|
||||||
- Microsoft Edge
|
|
||||||
- Safari
|
|
||||||
- Other
|
|
||||||
- type: textarea
|
|
||||||
id: current-behavior
|
|
||||||
attributes:
|
|
||||||
label: Current behaviour
|
|
||||||
description: A description of what is currently happening, including screenshots and other useful information (**DO NOT INCLUDE PRIVATE INFORMATION**).
|
|
||||||
placeholder: Currently...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: desired-behavior
|
|
||||||
attributes:
|
|
||||||
label: Desired behaviour
|
|
||||||
description: A clear description of what you think should happen.
|
|
||||||
placeholder: In this situation, I expected ...
|
|
||||||
- type: textarea
|
|
||||||
id: reproduction
|
|
||||||
attributes:
|
|
||||||
label: Steps to reproduce
|
|
||||||
description: Clearly describe which steps or actions you have taken to arrive at the problem. If you have some experience with the code, please link to the specific pieces of code.
|
|
||||||
placeholder: I did X, then Y, before arriving at Z, when ERROR ...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: other
|
|
||||||
attributes:
|
|
||||||
label: Other information
|
|
||||||
description: Any other details?
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
name: "✨ Feature Request"
|
|
||||||
description: Suggest a feature or enhancement to improve Planka.
|
|
||||||
labels: ["Type: Idea"]
|
|
||||||
body:
|
|
||||||
- type: dropdown
|
|
||||||
id: idea-type
|
|
||||||
attributes:
|
|
||||||
label: Is this a feature for the backend or frontend?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Backend
|
|
||||||
- Frontend
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: feature
|
|
||||||
attributes:
|
|
||||||
label: What would you like?
|
|
||||||
description: A clear description of the feature or enhancement wanted.
|
|
||||||
placeholder: I'd like to be able to...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: reason
|
|
||||||
attributes:
|
|
||||||
label: Why is this needed?
|
|
||||||
description: A clear description of why this would be useful to have.
|
|
||||||
placeholder: I want this because...
|
|
||||||
- type: textarea
|
|
||||||
id: other
|
|
||||||
attributes:
|
|
||||||
label: Other information
|
|
||||||
placeholder: Any other details?
|
|
||||||
@ -1,2 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
npx lint-staged
|
npx lint-staged
|
||||||
|
|||||||
@ -1,22 +1,27 @@
|
|||||||
FROM node:18-alpine
|
FROM node:lts-alpine
|
||||||
|
|
||||||
ARG VIPS_VERSION=8.14.5
|
ARG ALPINE_VERSION=3.16
|
||||||
|
ARG VIPS_VERSION=8.13.3
|
||||||
|
|
||||||
RUN apk -U upgrade \
|
RUN apk -U upgrade \
|
||||||
&& apk add \
|
&& apk add \
|
||||||
bash pkgconf \
|
bash giflib glib lcms2 libexif \
|
||||||
libjpeg-turbo libexif librsvg cgif tiff libspng libimagequant \
|
libgsf libjpeg-turbo libpng librsvg libwebp \
|
||||||
|
orc pango tiff \
|
||||||
|
--repository https://alpine.global.ssl.fastly.net/alpine/v${ALPINE_VERSION}/community/ \
|
||||||
|
--repository https://alpine.global.ssl.fastly.net/alpine/v${ALPINE_VERSION}/main/ \
|
||||||
--no-cache \
|
--no-cache \
|
||||||
&& apk add \
|
&& apk add \
|
||||||
build-base gobject-introspection-dev meson \
|
build-base giflib-dev glib-dev lcms2-dev libexif-dev \
|
||||||
libjpeg-turbo-dev libexif-dev librsvg-dev cgif-dev tiff-dev libspng-dev libimagequant-dev \
|
libgsf-dev libjpeg-turbo-dev libpng-dev librsvg-dev libwebp-dev \
|
||||||
|
orc-dev pango-dev tiff-dev \
|
||||||
--virtual vips-dependencies \
|
--virtual vips-dependencies \
|
||||||
|
--repository https://alpine.global.ssl.fastly.net/alpine/v${ALPINE_VERSION}/community/ \
|
||||||
|
--repository https://alpine.global.ssl.fastly.net/alpine/v${ALPINE_VERSION}/main/ \
|
||||||
--no-cache \
|
--no-cache \
|
||||||
&& wget -O- https://github.com/libvips/libvips/releases/download/v${VIPS_VERSION}/vips-${VIPS_VERSION}.tar.xz | tar xJC /tmp \
|
&& wget -O- https://github.com/libvips/libvips/releases/download/v${VIPS_VERSION}/vips-${VIPS_VERSION}.tar.gz | tar xzC /tmp \
|
||||||
&& cd /tmp/vips-${VIPS_VERSION} \
|
&& cd /tmp/vips-${VIPS_VERSION} \
|
||||||
&& meson setup build-dir \
|
&& ./configure \
|
||||||
&& cd build-dir \
|
&& make \
|
||||||
&& ninja \
|
&& make install-strip \
|
||||||
&& ninja test \
|
|
||||||
&& ninja install \
|
|
||||||
&& rm -rf /tmp/vips-${VIPS_VERSION}
|
&& rm -rf /tmp/vips-${VIPS_VERSION}
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
{{- if .Values.oidc.enabled }}
|
|
||||||
{{- if eq (and (not (empty .Values.oidc.clientId)) (not (empty .Values.oidc.clientSecret))) (not (empty .Values.oidc.existingSecret)) -}}
|
|
||||||
{{- fail "Either specify inline `clientId` and `clientSecret` or refer to them via `existingSecret`" -}}
|
|
||||||
{{- end }}
|
|
||||||
{{- if (and (and (not (empty .Values.oidc.clientId)) (not (empty .Values.oidc.clientSecret))) (empty .Values.oidc.existingSecret)) -}}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Secret
|
|
||||||
metadata:
|
|
||||||
name: {{ include "planka.fullname" . }}-oidc
|
|
||||||
labels:
|
|
||||||
{{- include "planka.labels" . | nindent 4 }}
|
|
||||||
type: Opaque
|
|
||||||
data:
|
|
||||||
clientId: {{ .Values.oidc.clientId | b64enc | quote }}
|
|
||||||
clientSecret: {{ .Values.oidc.clientSecret | b64enc | quote }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
REACT_APP_VERSION=1.12.0
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,17 +1,17 @@
|
|||||||
import http from './http';
|
import http from './http';
|
||||||
|
import socket from './socket';
|
||||||
|
|
||||||
/* Actions */
|
/* Actions */
|
||||||
|
|
||||||
const createAccessToken = (data, headers) =>
|
const createAccessToken = (data, headers) => http.post('/access-tokens', data, headers);
|
||||||
http.post('/access-tokens?withHttpOnlyToken=true', data, headers);
|
const exchangeOidcToken = (accessToken, headers) =>
|
||||||
|
http.post('/access-tokens/exchange', { token: accessToken }, headers);
|
||||||
|
|
||||||
const exchangeForAccessTokenUsingOidc = (data, headers) =>
|
const deleteCurrentAccessToken = (headers) =>
|
||||||
http.post('/access-tokens/exchange-using-oidc?withHttpOnlyToken=true', data, headers);
|
socket.delete('/access-tokens/me', undefined, headers);
|
||||||
|
|
||||||
const deleteCurrentAccessToken = (headers) => http.delete('/access-tokens/me', undefined, headers);
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createAccessToken,
|
createAccessToken,
|
||||||
exchangeForAccessTokenUsingOidc,
|
|
||||||
deleteCurrentAccessToken,
|
deleteCurrentAccessToken,
|
||||||
|
exchangeOidcToken,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
import http from './http';
|
|
||||||
|
|
||||||
/* Actions */
|
|
||||||
|
|
||||||
const getConfig = (headers) => http.get('/config', undefined, headers);
|
|
||||||
|
|
||||||
export default {
|
|
||||||
getConfig,
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 434 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 559 KiB |
@ -1,68 +0,0 @@
|
|||||||
import React, { useCallback } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import LinkifyReact from 'linkify-react';
|
|
||||||
|
|
||||||
import history from '../history';
|
|
||||||
|
|
||||||
const Linkify = React.memo(({ children, linkStopPropagation, ...props }) => {
|
|
||||||
const handleLinkClick = useCallback(
|
|
||||||
(event) => {
|
|
||||||
if (linkStopPropagation) {
|
|
||||||
event.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!event.target.getAttribute('target')) {
|
|
||||||
event.preventDefault();
|
|
||||||
history.push(event.target.href);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[linkStopPropagation],
|
|
||||||
);
|
|
||||||
|
|
||||||
const linkRenderer = useCallback(
|
|
||||||
({ attributes: { href, ...linkProps }, content }) => {
|
|
||||||
let url;
|
|
||||||
try {
|
|
||||||
url = new URL(href, window.location);
|
|
||||||
} catch (error) {} // eslint-disable-line no-empty
|
|
||||||
|
|
||||||
const isSameSite = !!url && url.origin === window.location.origin;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
{...linkProps} // eslint-disable-line react/jsx-props-no-spreading
|
|
||||||
href={href}
|
|
||||||
target={isSameSite ? undefined : '_blank'}
|
|
||||||
rel={isSameSite ? undefined : 'noreferrer'}
|
|
||||||
onClick={handleLinkClick}
|
|
||||||
>
|
|
||||||
{isSameSite ? url.pathname : content}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[handleLinkClick],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LinkifyReact
|
|
||||||
{...props} // eslint-disable-line react/jsx-props-no-spreading
|
|
||||||
options={{
|
|
||||||
defaultProtocol: 'https',
|
|
||||||
render: linkRenderer,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</LinkifyReact>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Linkify.propTypes = {
|
|
||||||
children: PropTypes.string.isRequired,
|
|
||||||
linkStopPropagation: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
Linkify.defaultProps = {
|
|
||||||
linkStopPropagation: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Linkify;
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { Menu } from 'semantic-ui-react';
|
|
||||||
import { Popup } from '../../lib/custom-ui';
|
|
||||||
import { ListSortTypes } from '../../constants/Enums';
|
|
||||||
|
|
||||||
import styles from './ListSortStep.module.scss';
|
|
||||||
|
|
||||||
const ListSortStep = React.memo(({ onTypeSelect, onBack }) => {
|
|
||||||
const [t] = useTranslation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Popup.Header onBack={onBack}>
|
|
||||||
{t('common.sortList', {
|
|
||||||
context: 'title',
|
|
||||||
})}
|
|
||||||
</Popup.Header>
|
|
||||||
<Popup.Content>
|
|
||||||
<Menu secondary vertical className={styles.menu}>
|
|
||||||
<Menu.Item
|
|
||||||
className={styles.menuItem}
|
|
||||||
onClick={() => onTypeSelect(ListSortTypes.NAME_ASC)}
|
|
||||||
>
|
|
||||||
{t('common.title')}
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item
|
|
||||||
className={styles.menuItem}
|
|
||||||
onClick={() => onTypeSelect(ListSortTypes.DUE_DATE_ASC)}
|
|
||||||
>
|
|
||||||
{t('common.dueDate')}
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item
|
|
||||||
className={styles.menuItem}
|
|
||||||
onClick={() => onTypeSelect(ListSortTypes.CREATED_AT_ASC)}
|
|
||||||
>
|
|
||||||
{t('common.oldestFirst')}
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item
|
|
||||||
className={styles.menuItem}
|
|
||||||
onClick={() => onTypeSelect(ListSortTypes.CREATED_AT_DESC)}
|
|
||||||
>
|
|
||||||
{t('common.newestFirst')}
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</Popup.Content>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
ListSortStep.propTypes = {
|
|
||||||
onTypeSelect: PropTypes.func.isRequired,
|
|
||||||
onBack: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
ListSortStep.defaultProps = {
|
|
||||||
onBack: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ListSortStep;
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
:global(#app) {
|
|
||||||
.menu {
|
|
||||||
margin: -7px -12px -5px;
|
|
||||||
width: calc(100% + 24px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuItem {
|
|
||||||
margin: 0;
|
|
||||||
padding-left: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
import ListSortStep from './ListSortStep';
|
|
||||||
|
|
||||||
export default ListSortStep;
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Loader } from 'semantic-ui-react';
|
|
||||||
|
|
||||||
import LoginContainer from '../containers/LoginContainer';
|
|
||||||
|
|
||||||
const LoginWrapper = React.memo(({ isInitializing }) => {
|
|
||||||
if (isInitializing) {
|
|
||||||
return <Loader active size="massive" />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <LoginContainer />;
|
|
||||||
});
|
|
||||||
|
|
||||||
LoginWrapper.propTypes = {
|
|
||||||
isInitializing: PropTypes.bool.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default LoginWrapper;
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
import React, { useCallback } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import { useSteps } from '../../hooks';
|
|
||||||
import ActionsStep from './ActionsStep';
|
|
||||||
import BoardMembershipsStep from '../BoardMembershipsStep';
|
|
||||||
|
|
||||||
const StepTypes = {
|
|
||||||
EDIT: 'EDIT',
|
|
||||||
};
|
|
||||||
|
|
||||||
const MembershipsStep = React.memo(
|
|
||||||
({
|
|
||||||
items,
|
|
||||||
permissionsSelectStep,
|
|
||||||
title,
|
|
||||||
actionsTitle,
|
|
||||||
leaveButtonContent,
|
|
||||||
leaveConfirmationTitle,
|
|
||||||
leaveConfirmationContent,
|
|
||||||
leaveConfirmationButtonContent,
|
|
||||||
deleteButtonContent,
|
|
||||||
deleteConfirmationTitle,
|
|
||||||
deleteConfirmationContent,
|
|
||||||
deleteConfirmationButtonContent,
|
|
||||||
canEdit,
|
|
||||||
canLeave,
|
|
||||||
onUpdate,
|
|
||||||
onDelete,
|
|
||||||
onClose,
|
|
||||||
}) => {
|
|
||||||
const [step, openStep, handleBack] = useSteps();
|
|
||||||
|
|
||||||
const handleUserSelect = useCallback(
|
|
||||||
(userId) => {
|
|
||||||
openStep(StepTypes.EDIT, {
|
|
||||||
userId,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[openStep],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (step && step.type === StepTypes.EDIT) {
|
|
||||||
const currentItem = items.find((item) => item.userId === step.params.userId);
|
|
||||||
|
|
||||||
if (currentItem) {
|
|
||||||
return (
|
|
||||||
<ActionsStep
|
|
||||||
membership={currentItem}
|
|
||||||
permissionsSelectStep={permissionsSelectStep}
|
|
||||||
title={actionsTitle}
|
|
||||||
leaveButtonContent={leaveButtonContent}
|
|
||||||
leaveConfirmationTitle={leaveConfirmationTitle}
|
|
||||||
leaveConfirmationContent={leaveConfirmationContent}
|
|
||||||
leaveConfirmationButtonContent={leaveConfirmationButtonContent}
|
|
||||||
deleteButtonContent={deleteButtonContent}
|
|
||||||
deleteConfirmationTitle={deleteConfirmationTitle}
|
|
||||||
deleteConfirmationContent={deleteConfirmationContent}
|
|
||||||
deleteConfirmationButtonContent={deleteConfirmationButtonContent}
|
|
||||||
canEdit={canEdit}
|
|
||||||
canLeave={canLeave}
|
|
||||||
onUpdate={(data) => onUpdate(currentItem.id, data)}
|
|
||||||
onDelete={() => onDelete(currentItem.id)}
|
|
||||||
onBack={handleBack}
|
|
||||||
onClose={onClose}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
openStep(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
// FIXME: hack
|
|
||||||
<BoardMembershipsStep
|
|
||||||
items={items}
|
|
||||||
currentUserIds={[]}
|
|
||||||
title={title}
|
|
||||||
onUserSelect={handleUserSelect}
|
|
||||||
onUserDeselect={() => {}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
MembershipsStep.propTypes = {
|
|
||||||
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
|
||||||
permissionsSelectStep: PropTypes.elementType,
|
|
||||||
title: PropTypes.string,
|
|
||||||
actionsTitle: PropTypes.string,
|
|
||||||
leaveButtonContent: PropTypes.string,
|
|
||||||
leaveConfirmationTitle: PropTypes.string,
|
|
||||||
leaveConfirmationContent: PropTypes.string,
|
|
||||||
leaveConfirmationButtonContent: PropTypes.string,
|
|
||||||
deleteButtonContent: PropTypes.string,
|
|
||||||
deleteConfirmationTitle: PropTypes.string,
|
|
||||||
deleteConfirmationContent: PropTypes.string,
|
|
||||||
deleteConfirmationButtonContent: PropTypes.string,
|
|
||||||
canEdit: PropTypes.bool.isRequired,
|
|
||||||
canLeave: PropTypes.bool.isRequired,
|
|
||||||
onUpdate: PropTypes.func,
|
|
||||||
onDelete: PropTypes.func.isRequired,
|
|
||||||
onClose: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
MembershipsStep.defaultProps = {
|
|
||||||
permissionsSelectStep: undefined,
|
|
||||||
title: undefined,
|
|
||||||
actionsTitle: undefined,
|
|
||||||
leaveButtonContent: undefined,
|
|
||||||
leaveConfirmationTitle: undefined,
|
|
||||||
leaveConfirmationContent: undefined,
|
|
||||||
leaveConfirmationButtonContent: undefined,
|
|
||||||
deleteButtonContent: undefined,
|
|
||||||
deleteConfirmationTitle: undefined,
|
|
||||||
deleteConfirmationContent: undefined,
|
|
||||||
deleteConfirmationButtonContent: undefined,
|
|
||||||
onUpdate: undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MembershipsStep;
|
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { useAuth } from 'react-oidc-context';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
let isLoggingIn = true;
|
||||||
|
const OidcLogin = React.memo(({ onAuthenticate }) => {
|
||||||
|
const auth = useAuth();
|
||||||
|
if (isLoggingIn && auth.user) {
|
||||||
|
isLoggingIn = false;
|
||||||
|
const { user } = auth;
|
||||||
|
onAuthenticate(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
OidcLogin.propTypes = {
|
||||||
|
onAuthenticate: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OidcLogin;
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import OidcLogin from './OidcLogin';
|
||||||
|
|
||||||
|
export default OidcLogin;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue