mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-25 14:05:03 +00:00
Merge branch 'activity-logs' of https://github.com/Infisical/infisical into activity-logs
This commit is contained in:
112
frontend/components/basic/EventFilter.tsx
Normal file
112
frontend/components/basic/EventFilter.tsx
Normal file
@ -0,0 +1,112 @@
|
||||
import React from 'react';
|
||||
import { Fragment } from 'react';
|
||||
import {
|
||||
faAngleDown,
|
||||
faCheck,
|
||||
faDownload,
|
||||
faPlus,
|
||||
faUpload,
|
||||
faX
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Listbox, Transition } from '@headlessui/react';
|
||||
|
||||
import guidGenerator from '../utilities/randomId';
|
||||
import Button from './buttons/Button';
|
||||
|
||||
interface ListBoxProps {
|
||||
selected: string;
|
||||
select: (event: string) => void;
|
||||
data: string[];
|
||||
text?: string;
|
||||
buttonAction?: () => void;
|
||||
isFull?: boolean;
|
||||
}
|
||||
|
||||
const eventOptions = [
|
||||
{
|
||||
name: 'Secrets Pushed',
|
||||
icon: faUpload
|
||||
},
|
||||
{
|
||||
name: 'Secrets Pulled',
|
||||
icon: faDownload
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* This is the component that we use for drop down lists.
|
||||
* @param {object} obj
|
||||
* @param {string} obj.selected - the item that is currently selected
|
||||
* @param {function} obj.select - what happends if you select the item inside a list
|
||||
* @param {string[]} obj.data - all the options available
|
||||
* @param {string} obj.text - the text that shows us in front of the select option
|
||||
* @param {function} obj.buttonAction - if there is a button at the bottom of the list, this is the action that happens when you click the button
|
||||
* @param {string} obj.width - button width
|
||||
* @returns
|
||||
*/
|
||||
export default function EventFilter({
|
||||
selected,
|
||||
select,
|
||||
data,
|
||||
text,
|
||||
buttonAction,
|
||||
isFull
|
||||
}: ListBoxProps): JSX.Element {
|
||||
return (
|
||||
<Listbox value={selected} onChange={select}>
|
||||
<div className="relative">
|
||||
<Listbox.Button className="bg-mineshaft-800 hover:bg-mineshaft-700 duration-200 cursor-pointer rounded-md h-10 flex items-center justify-between pl-4 pr-2 w-52 text-bunker-200 text-sm">
|
||||
{selected != '' ? (
|
||||
<p className="select-none text-bunker-100">{selected}</p>
|
||||
) : (
|
||||
<p className="select-none">Select an event</p>
|
||||
)}
|
||||
{selected != '' ? (
|
||||
<FontAwesomeIcon
|
||||
icon={faX}
|
||||
className="pl-2 w-2 p-2"
|
||||
onClick={() => select('')}
|
||||
/>
|
||||
) : (
|
||||
<FontAwesomeIcon icon={faAngleDown} className="pl-4 pr-2" />
|
||||
)}
|
||||
</Listbox.Button>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
leave="transition ease-in duration-100"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<Listbox.Options className="border border-mineshaft-700 z-50 w-52 p-1 absolute mt-1 max-h-60 overflow-auto rounded-md bg-bunker text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
|
||||
{eventOptions.map((event, id) => {
|
||||
return (
|
||||
<Listbox.Option
|
||||
key={id}
|
||||
className={`px-4 h-10 flex items-center text-sm cursor-pointer hover:bg-mineshaft-700 text-bunker-200 rounded-md ${
|
||||
selected == event.name && 'bg-mineshaft-700'
|
||||
}`}
|
||||
value={event.name}
|
||||
>
|
||||
{({ selected }) => (
|
||||
<>
|
||||
<span
|
||||
className={`block truncate ${
|
||||
selected ? 'font-semibold' : 'font-normal'
|
||||
}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={event.icon} className="pr-4" />{' '}
|
||||
{event.name}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
{/* <FontAwesomeIcon icon={event.icon} className="pr-4" /> {event.name} */}
|
||||
</Listbox.Option>
|
||||
);
|
||||
})}
|
||||
</Listbox.Options>
|
||||
</Transition>
|
||||
</div>
|
||||
</Listbox>
|
||||
);
|
||||
}
|
@ -4,12 +4,12 @@ import { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import {
|
||||
faBook,
|
||||
faBookOpen,
|
||||
faGear,
|
||||
faKey,
|
||||
faMobile,
|
||||
faPlug,
|
||||
faTimeline,
|
||||
faUser
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
@ -153,8 +153,8 @@ export default function Layout({ children }: LayoutProps) {
|
||||
},
|
||||
{
|
||||
href: '/activity/' + workspaceMapping[workspaceSelected as any],
|
||||
title: 'Activity',
|
||||
emoji: <FontAwesomeIcon icon={faBook} />
|
||||
title: 'Activity Logs',
|
||||
emoji: <FontAwesomeIcon icon={faTimeline} />
|
||||
},
|
||||
{
|
||||
href: '/settings/project/' + workspaceMapping[workspaceSelected as any],
|
||||
|
@ -1,19 +1,19 @@
|
||||
import React from "react";
|
||||
import { Fragment } from "react";
|
||||
import React from 'react';
|
||||
import { Fragment } from 'react';
|
||||
import {
|
||||
faAngleDown,
|
||||
faCheck,
|
||||
faPlus,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
faPlus
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Listbox, Transition } from '@headlessui/react';
|
||||
|
||||
interface ListBoxProps {
|
||||
selected: string;
|
||||
onChange: () => void;
|
||||
data: string[];
|
||||
text: string;
|
||||
buttonAction: () => void;
|
||||
text?: string;
|
||||
buttonAction?: () => void;
|
||||
isFull?: boolean;
|
||||
}
|
||||
|
||||
@ -34,20 +34,20 @@ export default function ListBox({
|
||||
data,
|
||||
text,
|
||||
buttonAction,
|
||||
isFull,
|
||||
isFull
|
||||
}: ListBoxProps): JSX.Element {
|
||||
return (
|
||||
<Listbox value={selected} onChange={onChange}>
|
||||
<div className="relative">
|
||||
<Listbox.Button
|
||||
className={`text-gray-400 relative ${
|
||||
isFull ? "w-full" : "w-52"
|
||||
isFull ? 'w-full' : 'w-52'
|
||||
} cursor-default rounded-md bg-white/[0.07] hover:bg-white/[0.11] duration-200 py-2.5 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm`}
|
||||
>
|
||||
<div className="flex flex-row">
|
||||
{text}
|
||||
<span className="ml-1 cursor-pointer block truncate font-semibold text-gray-300">
|
||||
{" "}
|
||||
{' '}
|
||||
{selected}
|
||||
</span>
|
||||
</div>
|
||||
@ -70,11 +70,11 @@ export default function ListBox({
|
||||
key={personIdx}
|
||||
className={({ active, selected }) =>
|
||||
`my-0.5 relative cursor-default select-none py-2 pl-10 pr-4 rounded-md ${
|
||||
selected ? "bg-white/10 text-gray-400 font-bold" : ""
|
||||
selected ? 'bg-white/10 text-gray-400 font-bold' : ''
|
||||
} ${
|
||||
active && !selected
|
||||
? "bg-white/5 text-mineshaft-200 cursor-pointer"
|
||||
: "text-gray-400"
|
||||
? 'bg-white/5 text-mineshaft-200 cursor-pointer'
|
||||
: 'text-gray-400'
|
||||
} `
|
||||
}
|
||||
value={person}
|
||||
@ -83,7 +83,7 @@ export default function ListBox({
|
||||
<>
|
||||
<span
|
||||
className={`block truncate text-primary${
|
||||
selected ? "font-medium" : "font-normal"
|
||||
selected ? 'font-medium' : 'font-normal'
|
||||
}`}
|
||||
>
|
||||
{person}
|
||||
|
@ -49,17 +49,14 @@ const ActivityLogsRow = ({ row }: { row: ActivityTableProps }): JSX.Element => {
|
||||
const [payloadOpened, setPayloadOpened] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<tr
|
||||
key={guidGenerator()}
|
||||
className="bg-bunker-800 duration-100 cursor-pointer w-full"
|
||||
>
|
||||
<tr key={guidGenerator()} className="bg-bunker-800 duration-100 w-full">
|
||||
<div
|
||||
onClick={() => setPayloadOpened(!payloadOpened)}
|
||||
className="border-mineshaft-700 border-t text-gray-300 flex items-center"
|
||||
className="border-mineshaft-700 border-t text-gray-300 flex items-center cursor-pointer"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={payloadOpened ? faAngleDown : faAngleRight}
|
||||
className={`mt-3.5 ml-6 text-bunker-100 hover:bg-primary-100/[0.15] ${
|
||||
className={`mt-3 ml-6 text-bunker-100 hover:bg-primary-100/[0.15] ${
|
||||
payloadOpened && 'bg-primary-100/10'
|
||||
} p-1 duration-100 h-4 w-4 rounded-md`}
|
||||
/>
|
||||
|
@ -1,11 +1,96 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
import EventFilter from '~/components/basic/EventFilter';
|
||||
import ActivityTable from '~/components/basic/table/ActivityTable';
|
||||
import NavHeader from '~/components/navigation/NavHeader';
|
||||
import onboardingCheck from '~/components/utilities/checks/OnboardingCheck';
|
||||
|
||||
const data = [
|
||||
{
|
||||
eventName: 'Secrets Pulled',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'CLI',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pushed',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'Web',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pulled',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'CLI',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pushed',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'Web',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pulled',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'CLI',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pushed',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'Web',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pulled',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'CLI',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pushed',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'Web',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pulled',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'CLI',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pushed',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'Web',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pulled',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'CLI',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pushed',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'Web',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pulled',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'CLI',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pushed',
|
||||
user: 'matsiiako@gmail.com',
|
||||
source: 'Web',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
eventName: 'Secrets Pulled',
|
||||
user: 'matsiiako@gmail.com',
|
||||
@ -32,6 +117,7 @@ export default function Activity() {
|
||||
const [hasUserStarred, setHasUserStarred] = useState(false);
|
||||
const [hasUserPushedSecrets, setHasUserPushedSecrets] = useState(false);
|
||||
const [usersInOrg, setUsersInOrg] = useState(false);
|
||||
const [eventChosen, setEventChosen] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
onboardingCheck({
|
||||
@ -54,7 +140,20 @@ export default function Activity() {
|
||||
Event history limited to the last 12 months.
|
||||
</p>
|
||||
</div>
|
||||
<ActivityTable data={data} />
|
||||
{/* Licence Required
|
||||
<div className="px-6 h-8 mt-2">
|
||||
<EventFilter
|
||||
selected={eventChosen}
|
||||
select={setEventChosen}
|
||||
data={["Secrets Pulled", "Secrets Pushed"]}
|
||||
isFull={false}
|
||||
/>
|
||||
</div> */}
|
||||
<ActivityTable
|
||||
data={data.filter((event) =>
|
||||
eventChosen != '' ? event.eventName == eventChosen : event
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user