Skip to content

Commit

Permalink
Improved frontend for activity logs
Browse files Browse the repository at this point in the history
  • Loading branch information
vmatsiiako committed Jan 2, 2023
1 parent 4576e8f commit 0167342
Show file tree
Hide file tree
Showing 12 changed files with 757 additions and 300 deletions.
1 change: 1 addition & 0 deletions backend/src/ee/controllers/v1/workspaceController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const getWorkspaceLogs = async (req: Request, res: Response) => {
filters.workspace = workspaceId;

logs = await Log.find(filters)
.sort({ createdAt: -1 })
.skip(offset)
.limit(limit)
.populate('actions')
Expand Down
52 changes: 21 additions & 31 deletions frontend/components/basic/EventFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,50 @@
import React from 'react';
import { Fragment } from 'react';
import { useTranslation } from "next-i18next";
import {
faAngleDown,
faCheck,
faDownload,
faEye,
faPlus,
faUpload,
faShuffle,
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: 'addSecrets',
icon: faPlus
},
{
name: 'readSecrets',
icon: faEye
},
{
name: 'Secrets Pulled',
icon: faDownload
name: 'updateSecrets',
icon: faShuffle
}
];

/**
* This is the component that we use for drop down lists.
* This is the component that we use for the event picker in the activity logs tab.
* @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
* @param {string} obj.selected - the event that is currently selected
* @param {function} obj.select - an action that happens when an item is selected
*/
export default function EventFilter({
selected,
select,
data,
text,
buttonAction,
isFull
select
}: ListBoxProps): JSX.Element {
const { t } = useTranslation();

return (
<Listbox value={selected} onChange={select}>
<Listbox value={t("activity:event." + 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 != '' ? (
Expand Down Expand Up @@ -84,9 +74,9 @@ export default function EventFilter({
<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'
selected == t("activity:event." + event.name) && 'bg-mineshaft-700'
}`}
value={event.name}
value={t("activity:event." + event.name)}
>
{({ selected }) => (
<>
Expand All @@ -96,7 +86,7 @@ export default function EventFilter({
}`}
>
<FontAwesomeIcon icon={event.icon} className="pr-4" />{' '}
{event.name}
{t("activity:event." + event.name)}
</span>
</>
)}
Expand Down
141 changes: 0 additions & 141 deletions frontend/components/basic/table/ActivityTable.tsx

This file was deleted.

43 changes: 43 additions & 0 deletions frontend/ee/api/secrets/GetProjectLogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import SecurityClient from '~/utilities/SecurityClient';


interface workspaceProps {
workspaceId: string;
offset: number;
limit: number;
filters: object;
}

/**
* This function fetches the activity logs for a certain project
* @param {object} obj
* @param {string} obj.workspaceId - workspace id for which we are trying to get project log
* @param {object} obj.offset - teh starting point of logs that we want to pull
* @param {object} obj.limit - how many logs will we output
* @param {object} obj.filters
* @returns
*/
const getProjectLogs = async ({ workspaceId, offset, limit, filters }: workspaceProps) => {
return SecurityClient.fetchCall(
'/api/v1/workspace/' + workspaceId + '/logs?' +
new URLSearchParams({
offset: String(offset),
limit: String(limit),
filters: JSON.stringify(filters)
}),
{
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
).then(async (res) => {
if (res && res.status == 200) {
return (await res.json()).logs;
} else {
console.log('Failed to get project logs');
}
});
};

export default getProjectLogs;
4 changes: 2 additions & 2 deletions frontend/ee/api/secrets/GetSecretVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface secretVersionProps {
*/
const getSecretVersions = async ({ secretId, offset, limit }: secretVersionProps) => {
return SecurityClient.fetchCall(
'/api/v1/secret/' + secretId + '/secret-versions?'+
'/api/v1/secret/' + secretId + '/secret-versions?' +
new URLSearchParams({
offset: String(offset),
limit: String(limit)
Expand All @@ -32,7 +32,7 @@ const getSecretVersions = async ({ secretId, offset, limit }: secretVersionProps
if (res && res.status == 200) {
return await res.json();
} else {
console.log('Failed to get project secrets');
console.log('Failed to get secret version history');
}
});
};
Expand Down
80 changes: 80 additions & 0 deletions frontend/ee/components/ActivitySideBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useTranslation } from "next-i18next";
import { faX } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import patienceDiff from 'ee/utilities/findTextDifferences';

import DashboardInputField from '../../components/dashboard/DashboardInputField';


const secretChanges = [{
"oldSecret": "secret1",
"newSecret": "ecret2"
}, {
"oldSecret": "secret1",
"newSecret": "sercet2"
}, {
"oldSecret": "localhosta:8080",
"newSecret": "aaaalocalhoats:3000"
}]


interface SideBarProps {
toggleSidebar: (value: string[]) => void;
sidebarData: string[];
currentEvent: string;
}

/**
* @param {object} obj
* @param {function} obj.toggleSidebar - function that opens or closes the sidebar
* @param {string[]} obj.secretIds - data of payload
* @param {string} obj.currentEvent - the event name for which a sidebar is being displayed
* @returns the sidebar with the payload of user activity logs
*/
const ActivitySideBar = ({
toggleSidebar,
sidebarData,
currentEvent
}: SideBarProps) => {
const { t } = useTranslation();

return <div className='absolute border-l border-mineshaft-500 bg-bunker fixed h-full w-96 top-14 right-0 z-50 shadow-xl flex flex-col justify-between'>
<div className='h-min overflow-y-auto'>
<div className="flex flex-row px-4 py-3 border-b border-mineshaft-500 justify-between items-center">
<p className="font-semibold text-lg text-bunker-200">{t("activity:event." + currentEvent)}</p>
<div className='p-1' onClick={() => toggleSidebar([])}>
<FontAwesomeIcon icon={faX} className='w-4 h-4 text-bunker-300 cursor-pointer'/>
</div>
</div>
<div className='flex flex-col px-4'>
{currentEvent == 'readSecrets' && sidebarData.map((item, id) =>
<>
<div className='text-sm text-bunker-200 mt-4 pl-1'>Key {id}</div>
<DashboardInputField
key={id}
onChangeHandler={() => {}}
type="varName"
position={1}
value={"a" + item}
isDuplicate={false}
blurred={false}
/>
</>
)}
{currentEvent == 'updateSecrets' && sidebarData.map((item, id) =>
secretChanges.map(secretChange =>
<>
<div className='text-sm text-bunker-200 mt-4 pl-1'>Secret Name {id}</div>
<div className='text-bunker-100 font-mono rounded-md overflow-hidden'>
<div className='bg-red/30 px-2'>- {patienceDiff(secretChange.oldSecret.split(''), secretChange.newSecret.split(''), false).lines.map((character, id) => character.aIndex != -1 && <span key={id} className={`${character.bIndex == -1 && "bg-red-700/80"}`}>{character.line}</span>)}</div>
<div className='bg-green-500/30 px-2'>+ {patienceDiff(secretChange.oldSecret.split(''), secretChange.newSecret.split('')).lines.map((character, id) => character.bIndex != -1 && <span key={id} className={`${character.aIndex == -1 && "bg-green-700/80"}`}>{character.line}</span>)}</div>
</div>
</>
))}
</div>
</div>

</div>
};

export default ActivitySideBar;
Loading

0 comments on commit 0167342

Please sign in to comment.