Skip to content

Commit

Permalink
Feature Update (#117)
Browse files Browse the repository at this point in the history
* prepare release 1.2.0
* Support array schemas
* notification popup
* rewrite identites overview to new DataGrid
  • Loading branch information
dfoxg authored Nov 5, 2023
1 parent 38eef1a commit 43fb740
Show file tree
Hide file tree
Showing 16 changed files with 1,312 additions and 396 deletions.
4 changes: 3 additions & 1 deletion kratos-admin-ui/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm ci --legacy-peer-deps
COPY .npmrc ./
RUN npm ci
COPY . ./
RUN npm run test
RUN npm run build


Expand Down
4 changes: 2 additions & 2 deletions kratos-admin-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions kratos-admin-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kratos-admin-ui",
"version": "1.1.0",
"version": "1.2.0",
"private": true,
"dependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
Expand Down Expand Up @@ -28,7 +28,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"test": "react-scripts test --watchAll=false",
"eject": "react-scripts eject",
"proxy": "node cors-proxy.js &"
},
Expand Down
124 changes: 124 additions & 0 deletions kratos-admin-ui/src/components/messages/messagebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import {
MessageBar,
MessageBarActions,
MessageBarTitle,
MessageBarBody,
MessageBarGroup,
Button,
Link,
MessageBarIntent,
} from "@fluentui/react-components";
import { DismissRegular } from "@fluentui/react-icons";
import React, { useEffect, useState } from "react";

interface Message {
intent: MessageBarIntent;
title: string;
content?: JSX.Element;
}

interface InternalMessage extends Message {
id: number;
removeAfterSeconds: number;
}

type MessageConfig = {
message: Message;
removeAfterSeconds: number;
}


export class MessageService {

private static _instance: MessageService;

private eventQueue: InternalMessage[] = [];
private id: number = 0;

public dispatchMessage(message: MessageConfig): void {
const msg: InternalMessage = {
id: this.id++,
content: message.message.content,
intent: message.message.intent,
title: message.message.title,
removeAfterSeconds: message.removeAfterSeconds
};


this.eventQueue.push(msg)
window.dispatchEvent(new Event("new_event_dispatched"));
}

public getAndCleanMessages(): InternalMessage[] {
const data = this.eventQueue;
this.eventQueue = []
return data;
}

private constructor() {

}



public static get Instance() {
return this._instance || (this._instance = new this());
}

}

export function MessageBarComponent() {

const [messages, setMessages] = useState<InternalMessage[]>([]);
const dismissMessage = (messageId: number) =>
setMessages((s) => s.filter((entry) => entry.id !== messageId));

function handleWindowClick() {
const newMessages = MessageService.Instance.getAndCleanMessages();
setMessages(messages.concat(newMessages));


newMessages.forEach(newMessage => {
setTimeout(() => {
dismissMessage(newMessage.id)
}, newMessage.removeAfterSeconds * 1000)
})
}

useEffect(() => {
window.addEventListener('new_event_dispatched', handleWindowClick);
return () => {
window.removeEventListener("new_event_dispatched", handleWindowClick);
}
}, [])

return (
<MessageBarGroup animate="both" style={{
position: "absolute",
top: 70,
right: 0
}}>
{messages.map(({ intent, id, title, content }) => (
<MessageBar key={`${intent}-${id}`} intent={intent}>
<MessageBarBody>
<MessageBarTitle>{title}</MessageBarTitle>
{content}
</MessageBarBody>
<MessageBarActions
containerAction={
<Button
onClick={() => dismissMessage(id)}
aria-label="dismiss"
appearance="transparent"
icon={<DismissRegular />}
/>
}
/>
</MessageBar>
))}
</MessageBarGroup>
)

}


88 changes: 88 additions & 0 deletions kratos-admin-ui/src/components/multiline/multiline.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Button, Input, Tooltip } from "@fluentui/react-components";
import { Add12Filled, Delete12Filled } from "@fluentui/react-icons";
import { useEffect, useState } from "react"
import { FluentUIInputDataType } from "../../service/schema-service";


interface MultilineEditProps {
defaultData?: any[]
datatype: FluentUIInputDataType;
dataChanged(any: any[]): void;
name: string;
}

export function MultilineEdit(props: MultilineEditProps) {

const [data, setData] = useState<any[]>([]);

useEffect(() => {
if (props.defaultData && props.defaultData.length > 0) {
if (JSON.stringify(data) !== JSON.stringify(props.defaultData)) {
setData(props.defaultData)
}
} else {
setData([""])
}
}, [])


return (
<>
{data.map((value, index) => {
return (
<div key={index} style={{
display: "flex",
alignItems: "center",
paddingBottom: 5
}}>
<Input
style={{
flexGrow: 2
}}
type={props.datatype}
onChange={(ev, inputData) => {
data[index] = inputData.value
props.dataChanged(data)
}}
defaultValue={value}
name={props.name + "_" + index}
></Input>
<div>
<Tooltip
content="Add another line" relationship="description">
<Button
style={{
marginLeft: 5
}}
size="small"
icon={<Add12Filled></Add12Filled>}
onClick={(event => {
setData(data.concat(""))
})}
></Button>
</Tooltip>
<Tooltip
content={"Remove line"} relationship="description">
<Button
style={{
marginLeft: 5
}}
disabled={data.length === 1}
size="small"
icon={<Delete12Filled></Delete12Filled>}
onClick={(event => {
setData(data.filter((arrayvalue, arrayIndex) => {
return arrayIndex !== index
}))
props.dataChanged(data)
})}
></Button>
</Tooltip>
</div>
</div>
)
})}
</>
)

}
11 changes: 11 additions & 0 deletions kratos-admin-ui/src/components/sessions/list-sessions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IdentityApi, Session, SessionAuthenticationMethod, SessionDevice } from
import React from "react";
import { getKratosConfig } from "../../config";
import { ToolbarItem } from "../../sites/identities/identies";
import { MessageService } from "../messages/messagebar";

interface ListSessionsProps {
identity_id: string;
Expand Down Expand Up @@ -39,6 +40,16 @@ export class ListSessions extends React.Component<ListSessionsProps, ListSession
selectedRows: [],
commandBarItems: this.getCommandbarItems(0, sessionsAPIresponse.data.length)
});

if (showBanner) {
MessageService.Instance.dispatchMessage({
removeAfterSeconds: 2,
message: {
title: "sessions refreshed",
intent: "success"
}
})
}
}

getCommandbarItems(countSelectedElements: number, countSessions: number): ToolbarItem[] {
Expand Down
Loading

0 comments on commit 43fb740

Please sign in to comment.