Skip to content

Commit

Permalink
Merge pull request #249 from edlerd/improve-idp-forms
Browse files Browse the repository at this point in the history
Improve identity provider forms in UI
  • Loading branch information
shipperizer authored Mar 27, 2024
2 parents cb918fb + a4acd46 commit 76eb985
Show file tree
Hide file tree
Showing 31 changed files with 408 additions and 233 deletions.
2 changes: 1 addition & 1 deletion pkg/idp/third_party.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type Configuration struct {

// SubjectSource is a flag which controls from which endpoint the subject identifier is taken by microsoft provider.
// Can be either `userinfo` or `me`.
// If the value is `uerinfo` then the subject identifier is taken from sub field of uderifo standard endpoint response.
// If the value is `userinfo` then the subject identifier is taken from sub field of userinfo standard endpoint response.
// If the value is `me` then the `id` field of https://graph.microsoft.com/v1.0/me response is taken as subject.
// The default is `userinfo`.
SubjectSource string `json:"subject_source" yaml:"subject_source"`
Expand Down
1 change: 1 addition & 0 deletions ui/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ module.exports = {
semi: ["error", "always"],
"object-curly-spacing": ["error", "always"],
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"react/react-in-jsx-scope": "off",
},
};
1 change: 1 addition & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"dependencies": {
"@canonical/react-components": "0.51.0",
"@tanstack/react-query": "^5.28.6",
"@use-it/event-listener": "0.1.7",
"formik": "2.4.5",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, Suspense } from "react";
import { FC, Suspense } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import Loader from "components/Loader";
import ClientList from "pages/clients/ClientList";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/CheckboxList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import { CheckboxInput, Col, Row } from "@canonical/react-components";

interface Props {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/Loader.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import { Spinner } from "@canonical/react-components";

interface Props {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/Logo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import { NavLink } from "react-router-dom";

const Logo: FC = () => {
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/Navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import { NavLink } from "react-router-dom";
import { Button, Icon } from "@canonical/react-components";
import classnames from "classnames";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/NoMatch.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import { Row, Col } from "@canonical/react-components";

const NoMatch: FC = () => {
Expand Down
1 change: 0 additions & 1 deletion ui/src/components/Panels.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from "react";
import ProviderCreate from "pages/providers/ProviderCreate";
import usePanelParams, { panels } from "util/usePanelParams";
import ProviderEdit from "pages/providers/ProviderEdit";
Expand Down
41 changes: 41 additions & 0 deletions ui/src/components/ScrollableContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { DependencyList, FC, ReactNode, useEffect, useRef } from "react";
import useEventListener from "@use-it/event-listener";
import { getAbsoluteHeightBelow, getParentsBottomSpacing } from "util/helpers";

interface Props {
children: ReactNode;
dependencies: DependencyList;
belowId?: string;
}

const ScrollableContainer: FC<Props> = ({
dependencies,
children,
belowId = "",
}) => {
const ref = useRef<HTMLDivElement>(null);

const updateChildContainerHeight = () => {
const childContainer = ref.current?.children[0];
if (!childContainer) {
return;
}
const above = childContainer.getBoundingClientRect().top + 1;
const below = getAbsoluteHeightBelow(belowId);
const parentsBottomSpacing = getParentsBottomSpacing(childContainer);
const offset = Math.ceil(above + below + parentsBottomSpacing);
const style = `height: calc(100vh - ${offset}px); min-height: calc(100vh - ${offset}px)`;
childContainer.setAttribute("style", style);
};

useEventListener("resize", updateChildContainerHeight);
useEffect(updateChildContainerHeight, [...dependencies, ref]);

return (
<div ref={ref} className="scrollable-container">
<div className="content-details">{children}</div>
</div>
);
};

export default ScrollableContainer;
2 changes: 1 addition & 1 deletion ui/src/components/SidePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, PropsWithChildren, ReactNode } from "react";
import { FC, PropsWithChildren, ReactNode } from "react";
import Loader from "components/Loader";
import classnames from "classnames";
import { Spinner } from "@canonical/react-components";
Expand Down
1 change: 0 additions & 1 deletion ui/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter as Router } from "react-router-dom";
import Navigation from "components/Navigation";
Expand Down
57 changes: 31 additions & 26 deletions ui/src/pages/clients/ClientCreate.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import {
ActionButton,
Button,
Expand All @@ -14,6 +14,7 @@ import { useNavigate } from "react-router-dom";
import ClientForm, { ClientFormTypes } from "pages/clients/ClientForm";
import { createClient } from "api/client";
import SidePanel from "components/SidePanel";
import ScrollableContainer from "components/ScrollableContainer";

const ClientCreate: FC = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -57,31 +58,35 @@ const ClientCreate: FC = () => {

return (
<SidePanel hasError={false} loading={false} className="p-panel">
<SidePanel.Header>
<SidePanel.HeaderTitle>Add client</SidePanel.HeaderTitle>
</SidePanel.Header>
<SidePanel.Content>
<Row>
<ClientForm formik={formik} />
</Row>
</SidePanel.Content>
<SidePanel.Footer>
<Row className="u-align-text--right">
<Col size={12}>
<Button appearance="base" onClick={() => navigate("/client")}>
Cancel
</Button>
<ActionButton
appearance="positive"
loading={formik.isSubmitting}
disabled={!formik.isValid}
onClick={submitForm}
>
Save
</ActionButton>
</Col>
</Row>
</SidePanel.Footer>
<ScrollableContainer dependencies={[]} belowId="panel-footer">
<SidePanel.Header>
<SidePanel.HeaderTitle>Add client</SidePanel.HeaderTitle>
</SidePanel.Header>
<SidePanel.Content>
<Row>
<ClientForm formik={formik} />
</Row>
</SidePanel.Content>
</ScrollableContainer>
<div id="panel-footer">
<SidePanel.Footer>
<Row className="u-align-text--right">
<Col size={12}>
<Button appearance="base" onClick={() => navigate("/client")}>
Cancel
</Button>
<ActionButton
appearance="positive"
loading={formik.isSubmitting}
disabled={!formik.isValid}
onClick={submitForm}
>
Save
</ActionButton>
</Col>
</Row>
</SidePanel.Footer>
</div>
</SidePanel>
);
};
Expand Down
67 changes: 36 additions & 31 deletions ui/src/pages/clients/ClientEdit.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import {
ActionButton,
Button,
Expand All @@ -15,6 +15,7 @@ import ClientForm, { ClientFormTypes } from "pages/clients/ClientForm";
import { fetchClient, updateClient } from "api/client";
import usePanelParams from "util/usePanelParams";
import SidePanel from "components/SidePanel";
import ScrollableContainer from "components/ScrollableContainer";

const ClientEdit: FC = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -69,36 +70,40 @@ const ClientEdit: FC = () => {

return (
<SidePanel hasError={false} loading={false} className="p-panel">
<SidePanel.Header>
<SidePanel.HeaderTitle>Edit client</SidePanel.HeaderTitle>
</SidePanel.Header>
<SidePanel.Content className="u-no-padding">
<Row>
<ClientForm formik={formik} />
</Row>
</SidePanel.Content>
<SidePanel.Footer className="u-align--right">
<Row>
<Col size={12}>
<Button
appearance="base"
className="u-no-margin--bottom u-sv2"
onClick={() => navigate(`/client`)}
>
Cancel
</Button>
<ActionButton
appearance="positive"
className="u-no-margin--bottom"
loading={formik.isSubmitting}
disabled={!formik.isValid}
onClick={submitForm}
>
Update
</ActionButton>
</Col>
</Row>
</SidePanel.Footer>
<ScrollableContainer dependencies={[]} belowId="panel-footer">
<SidePanel.Header>
<SidePanel.HeaderTitle>Edit client</SidePanel.HeaderTitle>
</SidePanel.Header>
<SidePanel.Content className="u-no-padding">
<Row>
<ClientForm formik={formik} />
</Row>
</SidePanel.Content>
</ScrollableContainer>
<div id="panel-footer">
<SidePanel.Footer className="u-align--right">
<Row>
<Col size={12}>
<Button
appearance="base"
className="u-no-margin--bottom u-sv2"
onClick={() => navigate(`/client`)}
>
Cancel
</Button>
<ActionButton
appearance="positive"
className="u-no-margin--bottom"
loading={formik.isSubmitting}
disabled={!formik.isValid}
onClick={submitForm}
>
Update
</ActionButton>
</Col>
</Row>
</SidePanel.Footer>
</div>
</SidePanel>
);
};
Expand Down
52 changes: 26 additions & 26 deletions ui/src/pages/clients/ClientForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import { Form, Input } from "@canonical/react-components";
import { FormikProps } from "formik";
import CheckboxList from "components/CheckboxList";
Expand Down Expand Up @@ -40,25 +40,40 @@ const ClientForm: FC<Props> = ({ formik }) => {
required
/>
<Input
id="client_uri"
name="client_uri"
id="scope"
name="scope"
type="text"
label="Client uri"
label="Scope"
onBlur={formik.handleBlur}
onChange={formik.handleChange}
value={formik.values.client_uri}
error={formik.touched.client_uri ? formik.errors.client_uri : null}
value={formik.values.scope}
error={formik.touched.scope ? formik.errors.scope : null}
required
/>
<Input
id="scope"
name="scope"
id="redirect_uris"
name="redirect_uris"
type="text"
label="Scope"
label="Redirect uri"
onBlur={formik.handleBlur}
onChange={(e) =>
void formik.setFieldValue("redirect_uris", [e.target.value])
}
value={formik.values.redirect_uris}
error={
formik.touched.redirect_uris ? formik.errors.redirect_uris : null
}
required
/>
<Input
id="client_uri"
name="client_uri"
type="text"
label="Client uri"
onBlur={formik.handleBlur}
onChange={formik.handleChange}
value={formik.values.scope}
error={formik.touched.scope ? formik.errors.scope : null}
value={formik.values.client_uri}
error={formik.touched.client_uri ? formik.errors.client_uri : null}
required
/>
<Input
Expand All @@ -76,21 +91,6 @@ const ClientForm: FC<Props> = ({ formik }) => {
}
required
/>
<Input
id="redirect_uris"
name="redirect_uris"
type="text"
label="Redirect uri"
onBlur={formik.handleBlur}
onChange={(e) =>
void formik.setFieldValue("redirect_uris", [e.target.value])
}
value={formik.values.redirect_uris}
error={
formik.touched.redirect_uris ? formik.errors.redirect_uris : null
}
required
/>
<CheckboxList
label="Grant types"
values={["authorization_code", "refresh_token"]}
Expand Down
3 changes: 1 addition & 2 deletions ui/src/pages/clients/ClientList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { FC } from "react";
import { FC } from "react";
import { Button, Col, MainTable, Row } from "@canonical/react-components";
import { useQuery } from "@tanstack/react-query";
import { queryKeys } from "util/queryKeys";
import { Link } from "react-router-dom";
import { NotificationConsumer } from "@canonical/react-components/dist/components/NotificationProvider/NotificationProvider";
import { fetchClients } from "api/client";
import { isoTimeToString } from "util/date";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/pages/clients/DeleteClientBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, useState } from "react";
import { FC, useState } from "react";
import { useNavigate } from "react-router-dom";
import { queryKeys } from "util/queryKeys";
import { useQueryClient } from "@tanstack/react-query";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/pages/clients/EditClientBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import { Button, Icon } from "@canonical/react-components";
import usePanelParams from "util/usePanelParams";

Expand Down
2 changes: 1 addition & 1 deletion ui/src/pages/providers/DeleteProviderBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, useState } from "react";
import { FC, useState } from "react";
import { useNavigate } from "react-router-dom";
import { queryKeys } from "util/queryKeys";
import { useQueryClient } from "@tanstack/react-query";
Expand Down
2 changes: 1 addition & 1 deletion ui/src/pages/providers/EditProviderBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from "react";
import { FC } from "react";
import { Button, Icon } from "@canonical/react-components";
import usePanelParams from "util/usePanelParams";

Expand Down
Loading

0 comments on commit 76eb985

Please sign in to comment.