mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
UX fixes around the app
This commit is contained in:
@@ -333,7 +333,7 @@ Infisical officially launched as v.1.0 on November 21st, 2022. There are a lot o
|
|||||||
<!-- prettier-ignore-start -->
|
<!-- prettier-ignore-start -->
|
||||||
<!-- markdownlint-disable -->
|
<!-- markdownlint-disable -->
|
||||||
|
|
||||||
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mv-turtle"><img src="https://avatars.githubusercontent.com/u/78047717?s=96&v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/reginaldbondoc"><img src="https://avatars.githubusercontent.com/u/7693108?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/SH5H"><img src="https://avatars.githubusercontent.com/u/25437192?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gmgale"><img src="https://avatars.githubusercontent.com/u/62303146?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/asharonbaltazar"><img src="https://avatars.githubusercontent.com/u/58940073?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/jon4hz"><img src="https://avatars.githubusercontent.com/u/26183582?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/edgarrmondragon"><img src="https://avatars.githubusercontent.com/u/16805946?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/arjunyel"><img src="https://avatars.githubusercontent.com/u/11153289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/LemmyMwaura"><img src="https://avatars.githubusercontent.com/u/20738858?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Zamion101"><img src="https://avatars.githubusercontent.com/u/8071263?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/akhilmhdh"><img src="https://avatars.githubusercontent.com/u/31166322?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/naorpeled"><img src="https://avatars.githubusercontent.com/u/6171622?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/jonerrr"><img src="https://avatars.githubusercontent.com/u/73760377?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/adrianmarinwork"><img src="https://avatars.githubusercontent.com/u/118568289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/arthurzenika"><img src="https://avatars.githubusercontent.com/u/445200?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/hanywang2"><img src="https://avatars.githubusercontent.com/u/44352119?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/tobias-mintlify"><img src="https://avatars.githubusercontent.com/u/110702161?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/wjhurley"><img src="https://avatars.githubusercontent.com/u/15939055?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/0xflotus"><img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/wanjohiryan"><img src="https://avatars.githubusercontent.com/u/71614375?v=4" width="50" height="50" alt=""/></a>
|
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mv-turtle"><img src="https://avatars.githubusercontent.com/u/78047717?s=96&v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/reginaldbondoc"><img src="https://avatars.githubusercontent.com/u/7693108?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/SH5H"><img src="https://avatars.githubusercontent.com/u/25437192?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gmgale"><img src="https://avatars.githubusercontent.com/u/62303146?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/asharonbaltazar"><img src="https://avatars.githubusercontent.com/u/58940073?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/JoaoVictor6"><img src="https://avatars.githubusercontent.com/u/68869379?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mocherfaoui"><img src="https://avatars.githubusercontent.com/u/37941426?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/jon4hz"><img src="https://avatars.githubusercontent.com/u/26183582?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/edgarrmondragon"><img src="https://avatars.githubusercontent.com/u/16805946?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/arjunyel"><img src="https://avatars.githubusercontent.com/u/11153289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/LemmyMwaura"><img src="https://avatars.githubusercontent.com/u/20738858?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Zamion101"><img src="https://avatars.githubusercontent.com/u/8071263?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/akhilmhdh"><img src="https://avatars.githubusercontent.com/u/31166322?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/naorpeled"><img src="https://avatars.githubusercontent.com/u/6171622?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/jonerrr"><img src="https://avatars.githubusercontent.com/u/73760377?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/adrianmarinwork"><img src="https://avatars.githubusercontent.com/u/118568289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/arthurzenika"><img src="https://avatars.githubusercontent.com/u/445200?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/hanywang2"><img src="https://avatars.githubusercontent.com/u/44352119?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/tobias-mintlify"><img src="https://avatars.githubusercontent.com/u/110702161?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/wjhurley"><img src="https://avatars.githubusercontent.com/u/15939055?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/0xflotus"><img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/wanjohiryan"><img src="https://avatars.githubusercontent.com/u/71614375?v=4" width="50" height="50" alt=""/></a>
|
||||||
|
|
||||||
## 🌎 Translations
|
## 🌎 Translations
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export default function EventFilter({
|
|||||||
{selected != '' ? (
|
{selected != '' ? (
|
||||||
<p className="select-none text-bunker-100">{t("activity:event." + selected)}</p>
|
<p className="select-none text-bunker-100">{t("activity:event." + selected)}</p>
|
||||||
) : (
|
) : (
|
||||||
<p className="select-none">Select an event</p>
|
<p className="select-none">{String(t("common:select-event"))}</p>
|
||||||
)}
|
)}
|
||||||
{selected != '' ? (
|
{selected != '' ? (
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const AddProjectMemberDialog = ({
|
|||||||
selected={email ? email : data[0]}
|
selected={email ? email : data[0]}
|
||||||
onChange={setEmail}
|
onChange={setEmail}
|
||||||
data={data}
|
data={data}
|
||||||
width="full"
|
isFull={true}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ export const DeleteEnvVar = ({ isOpen, onClose, onSubmit }: Props) => {
|
|||||||
<div>
|
<div>
|
||||||
<Transition appear show={isOpen} as={Fragment}>
|
<Transition appear show={isOpen} as={Fragment}>
|
||||||
<Dialog as="div" className="relative z-10" onClose={() => {}}>
|
<Dialog as="div" className="relative z-10" onClose={() => {}}>
|
||||||
|
|
||||||
<div className="fixed inset-0 overflow-y-auto">
|
<div className="fixed inset-0 overflow-y-auto">
|
||||||
<Transition.Child
|
<Transition.Child
|
||||||
as={Fragment}
|
as={Fragment}
|
||||||
@@ -27,7 +26,7 @@ export const DeleteEnvVar = ({ isOpen, onClose, onSubmit }: Props) => {
|
|||||||
leaveFrom="opacity-100"
|
leaveFrom="opacity-100"
|
||||||
leaveTo="opacity-0"
|
leaveTo="opacity-0"
|
||||||
>
|
>
|
||||||
<div className="fixed inset-0 bg-black bg-opacity-25" onClick={onClose} />
|
<div className="fixed inset-0 bg-black bg-opacity-70" onClick={onClose} />
|
||||||
</Transition.Child>
|
</Transition.Child>
|
||||||
<div className="flex min-h-full items-center justify-center p-4 text-center">
|
<div className="flex min-h-full items-center justify-center p-4 text-center">
|
||||||
<Transition.Child
|
<Transition.Child
|
||||||
@@ -39,7 +38,7 @@ export const DeleteEnvVar = ({ isOpen, onClose, onSubmit }: Props) => {
|
|||||||
leaveFrom="opacity-100 scale-100"
|
leaveFrom="opacity-100 scale-100"
|
||||||
leaveTo="opacity-0 scale-95"
|
leaveTo="opacity-0 scale-95"
|
||||||
>
|
>
|
||||||
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-2xl bg-grey border border-gray-700 p-6 text-left align-middle shadow-xl transition-all">
|
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-md bg-grey border border-gray-700 p-6 text-left align-middle shadow-xl transition-all">
|
||||||
<Dialog.Title
|
<Dialog.Title
|
||||||
as="h3"
|
as="h3"
|
||||||
className="text-lg font-medium leading-6 text-gray-400"
|
className="text-lg font-medium leading-6 text-gray-400"
|
||||||
@@ -51,17 +50,17 @@ export const DeleteEnvVar = ({ isOpen, onClose, onSubmit }: Props) => {
|
|||||||
{t('dashboard:sidebar.delete-key-dialog.confirm-delete-message')}
|
{t('dashboard:sidebar.delete-key-dialog.confirm-delete-message')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-6 flex justify-end">
|
<div className="mt-6 flex justify-start">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="inline-flex justify-center rounded-md border border-transparent hover:border-white bg-red-800 hover:bg-red-600 px-4 py-2 text-sm font-medium text-gray-400 hover:text-white text-semibold duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
|
className="inline-flex justify-center rounded-md border border-transparent bg-red-700 hover:bg-red-600 px-4 py-2 text-sm font-medium text-bunker-200 hover:text-white text-semibold duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
|
||||||
onClick={onSubmit}
|
onClick={onSubmit}
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="ml-2 inline-flex justify-center rounded-md border border-transparent bg-gray-800 px-4 py-2 text-sm font-medium text-gray-400 hover:border-white hover:text-white hover:text-semibold duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
|
className="ml-2 inline-flex justify-center rounded-md border border-transparent bg-bunker-500 px-4 py-2 text-sm font-medium text-gray-400 hover:bg-mineshaft-500 hover:text-white hover:text-semibold duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@@ -117,13 +117,13 @@ const UserTable = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="table-container bg-bunker rounded-md mb-6 border border-mineshaft-700 relative mt-1">
|
<div className="table-container bg-bunker rounded-md mb-6 border border-mineshaft-700 relative mt-1">
|
||||||
<div className="absolute rounded-t-md w-full h-14 bg-white/5"></div>
|
<div className="absolute rounded-t-md w-full h-[3.25rem] bg-white/5"></div>
|
||||||
<table className="w-full my-1">
|
<table className="w-full my-0.5">
|
||||||
<thead className="text-gray-400">
|
<thead className="text-gray-400 text-sm font-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="text-left pl-6 py-3.5">First Name</th>
|
<th className="text-left pl-6 py-3.5">FIRST NAME</th>
|
||||||
<th className="text-left pl-6 py-3.5">Last Name</th>
|
<th className="text-left pl-6 py-3.5">LAST NAME</th>
|
||||||
<th className="text-left pl-6 py-3.5">Email</th>
|
<th className="text-left pl-6 py-3.5">EMAIL</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import Image from 'next/image';
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import {
|
import {
|
||||||
faAngleDown,
|
faAngleDown,
|
||||||
@@ -69,23 +69,25 @@ const ActivityLogsRow = ({ row, toggleSidebar }: { row: logData, toggleSidebar:
|
|||||||
{payloadOpened &&
|
{payloadOpened &&
|
||||||
<tr className='h-9 text-bunker-200 border-mineshaft-700 border-t text-sm'>
|
<tr className='h-9 text-bunker-200 border-mineshaft-700 border-t text-sm'>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>Timestamp</td>
|
<td>{String(t("common:timestamp"))}</td>
|
||||||
<td>{row.createdAt}</td>
|
<td>{row.createdAt}</td>
|
||||||
</tr>}
|
</tr>}
|
||||||
{payloadOpened &&
|
{payloadOpened &&
|
||||||
row.payload?.map((action, index) =>
|
row.payload?.map((action, index) => {
|
||||||
<tr key={index} className="h-9 text-bunker-200 border-mineshaft-700 border-t text-sm">
|
action.secretVersions.length > 0 &&
|
||||||
<td></td>
|
<tr key={index} className="h-9 text-bunker-200 border-mineshaft-700 border-t text-sm">
|
||||||
<td className="">{t("activity:event." + action.name)}</td>
|
<td></td>
|
||||||
<td className="text-primary-300 cursor-pointer hover:text-primary duration-200" onClick={() => toggleSidebar(action._id)}>
|
<td className="">{t("activity:event." + action.name)}</td>
|
||||||
{action.secretVersions.length + (action.secretVersions.length != 1 ? " secrets" : " secret")}
|
<td className="text-primary-300 cursor-pointer hover:text-primary duration-200" onClick={() => toggleSidebar(action._id)}>
|
||||||
<FontAwesomeIcon icon={faUpRightFromSquare} className="ml-2 mb-0.5 font-light w-3 h-3"/>
|
{action.secretVersions.length + (action.secretVersions.length != 1 ? " secrets" : " secret")}
|
||||||
</td>
|
<FontAwesomeIcon icon={faUpRightFromSquare} className="ml-2 mb-0.5 font-light w-3 h-3"/>
|
||||||
</tr>)}
|
</td>
|
||||||
|
</tr>
|
||||||
|
})}
|
||||||
{payloadOpened &&
|
{payloadOpened &&
|
||||||
<tr className='h-9 text-bunker-200 border-mineshaft-700 border-t text-sm'>
|
<tr className='h-9 text-bunker-200 border-mineshaft-700 border-t text-sm'>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>IP Address</td>
|
<td>{String(t("common:ip-address"))}</td>
|
||||||
<td>{row.ipAddress}</td>
|
<td>{row.ipAddress}</td>
|
||||||
</tr>}
|
</tr>}
|
||||||
</>
|
</>
|
||||||
@@ -97,9 +99,12 @@ const ActivityLogsRow = ({ row, toggleSidebar }: { row: logData, toggleSidebar:
|
|||||||
* @param {object} obj
|
* @param {object} obj
|
||||||
* @param {logData} obj.data - data for user activity logs
|
* @param {logData} obj.data - data for user activity logs
|
||||||
* @param {function} obj.toggleSidebar - function that opens or closes the sidebar
|
* @param {function} obj.toggleSidebar - function that opens or closes the sidebar
|
||||||
|
* @param {boolean} obj.isLoading - whether the log data has been loaded yet or not
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
const ActivityTable = ({ data, toggleSidebar }: { data: logData[], toggleSidebar: (value: string) => void; }) => {
|
const ActivityTable = ({ data, toggleSidebar, isLoading }: { data: logData[], toggleSidebar: (value: string) => void; isLoading: boolean; }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full px-6 mt-8">
|
<div className="w-full px-6 mt-8">
|
||||||
<div className="table-container w-full bg-bunker rounded-md mb-6 border border-mineshaft-700 relative">
|
<div className="table-container w-full bg-bunker rounded-md mb-6 border border-mineshaft-700 relative">
|
||||||
@@ -108,10 +113,10 @@ const ActivityTable = ({ data, toggleSidebar }: { data: logData[], toggleSidebar
|
|||||||
<thead className="text-bunker-300">
|
<thead className="text-bunker-300">
|
||||||
<tr className='text-sm'>
|
<tr className='text-sm'>
|
||||||
<th className="text-left pl-6 pt-2.5 pb-3"></th>
|
<th className="text-left pl-6 pt-2.5 pb-3"></th>
|
||||||
<th className="text-left font-semibold pt-2.5 pb-3">EVENT</th>
|
<th className="text-left font-semibold pt-2.5 pb-3">{String(t("common:event")).toUpperCase()}</th>
|
||||||
<th className="text-left font-semibold pl-6 pt-2.5 pb-3">USER</th>
|
<th className="text-left font-semibold pl-6 pt-2.5 pb-3">{String(t("common:user")).toUpperCase()}</th>
|
||||||
<th className="text-left font-semibold pl-6 pt-2.5 pb-3">SOURCE</th>
|
<th className="text-left font-semibold pl-6 pt-2.5 pb-3">{String(t("common:source")).toUpperCase()}</th>
|
||||||
<th className="text-left font-semibold pl-6 pt-2.5 pb-3">TIME</th>
|
<th className="text-left font-semibold pl-6 pt-2.5 pb-3">{String(t("common:time")).toUpperCase()}</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -122,6 +127,12 @@ const ActivityTable = ({ data, toggleSidebar }: { data: logData[], toggleSidebar
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
{isLoading && <div className='w-full flex justify-center mb-8 mt-4'><Image
|
||||||
|
src="/images/loading/loading.gif"
|
||||||
|
height={60}
|
||||||
|
width={100}
|
||||||
|
alt="loading animation"
|
||||||
|
></Image></div>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export default function Activity() {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [eventChosen, setEventChosen] = useState('');
|
const [eventChosen, setEventChosen] = useState('');
|
||||||
const [logsData, setLogsData] = useState<logDataPoint[]>([]);
|
const [logsData, setLogsData] = useState<logDataPoint[]>([]);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [currentOffset, setCurrentOffset] = useState(0);
|
const [currentOffset, setCurrentOffset] = useState(0);
|
||||||
const currentLimit = 10;
|
const currentLimit = 10;
|
||||||
const [currentSidebarAction, toggleSidebar] = useState<string>()
|
const [currentSidebarAction, toggleSidebar] = useState<string>()
|
||||||
@@ -60,6 +61,7 @@ export default function Activity() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentOffset(0);
|
setCurrentOffset(0);
|
||||||
const getLogData = async () => {
|
const getLogData = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
const tempLogsData = await getProjectLogs({ workspaceId: String(router.query.id), offset: 0, limit: currentLimit, userId: "", actionNames: eventChosen })
|
const tempLogsData = await getProjectLogs({ workspaceId: String(router.query.id), offset: 0, limit: currentLimit, userId: "", actionNames: eventChosen })
|
||||||
setLogsData(tempLogsData.map((log: logData) => {
|
setLogsData(tempLogsData.map((log: logData) => {
|
||||||
return {
|
return {
|
||||||
@@ -77,6 +79,7 @@ export default function Activity() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
getLogData();
|
getLogData();
|
||||||
}, [eventChosen]);
|
}, [eventChosen]);
|
||||||
@@ -84,6 +87,7 @@ export default function Activity() {
|
|||||||
// this use effect adds more data in case 'View More' button is clicked
|
// this use effect adds more data in case 'View More' button is clicked
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getLogData = async () => {
|
const getLogData = async () => {
|
||||||
|
setIsLoading(true);
|
||||||
const tempLogsData = await getProjectLogs({ workspaceId: String(router.query.id), offset: currentOffset, limit: currentLimit, userId: "", actionNames: eventChosen })
|
const tempLogsData = await getProjectLogs({ workspaceId: String(router.query.id), offset: currentOffset, limit: currentLimit, userId: "", actionNames: eventChosen })
|
||||||
setLogsData(logsData.concat(tempLogsData.map((log: logData) => {
|
setLogsData(logsData.concat(tempLogsData.map((log: logData) => {
|
||||||
return {
|
return {
|
||||||
@@ -101,6 +105,7 @@ export default function Activity() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
getLogData();
|
getLogData();
|
||||||
}, [currentLimit, currentOffset]);
|
}, [currentLimit, currentOffset]);
|
||||||
@@ -115,10 +120,10 @@ export default function Activity() {
|
|||||||
{currentSidebarAction && <ActivitySideBar toggleSidebar={toggleSidebar} currentAction={currentSidebarAction} />}
|
{currentSidebarAction && <ActivitySideBar toggleSidebar={toggleSidebar} currentAction={currentSidebarAction} />}
|
||||||
<div className="flex flex-col justify-between items-start mx-4 mt-6 mb-4 text-xl max-w-5xl px-2">
|
<div className="flex flex-col justify-between items-start mx-4 mt-6 mb-4 text-xl max-w-5xl px-2">
|
||||||
<div className="flex flex-row justify-start items-center text-3xl">
|
<div className="flex flex-row justify-start items-center text-3xl">
|
||||||
<p className="font-semibold mr-4 text-bunker-100">Activity Logs</p>
|
<p className="font-semibold mr-4 text-bunker-100">{t("activity:title")}</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="mr-4 text-base text-gray-400">
|
<p className="mr-4 text-base text-gray-400">
|
||||||
Event history for this Infisical project.
|
{t("activity:subtitle")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-6 h-8 mt-2">
|
<div className="px-6 h-8 mt-2">
|
||||||
@@ -130,10 +135,11 @@ export default function Activity() {
|
|||||||
<ActivityTable
|
<ActivityTable
|
||||||
data={logsData}
|
data={logsData}
|
||||||
toggleSidebar={toggleSidebar}
|
toggleSidebar={toggleSidebar}
|
||||||
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
<div className='flex justify-center w-full mb-6'>
|
<div className='flex justify-center w-full mb-6'>
|
||||||
<div className='items-center w-60'>
|
<div className='items-center w-60'>
|
||||||
<Button text="View More" textDisabled="End of History" active={logsData.length % 10 == 0 ? true : false} onButtonPressed={loadMoreLogs} size="md" color="mineshaft"/>
|
<Button text={String(t("common:view-more"))} textDisabled={String(t("common:end-of-history"))} active={logsData.length % 10 == 0 ? true : false} onButtonPressed={loadMoreLogs} size="md" color="mineshaft"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,4 +148,4 @@ export default function Activity() {
|
|||||||
|
|
||||||
Activity.requireAuth = true;
|
Activity.requireAuth = true;
|
||||||
|
|
||||||
export const getServerSideProps = getTranslatedServerSideProps(["activity"]);
|
export const getServerSideProps = getTranslatedServerSideProps(["activity", "common"]);
|
||||||
@@ -20,6 +20,22 @@ import addUserToWorkspace from '../api/workspace/addUserToWorkspace';
|
|||||||
import getWorkspaceUsers from '../api/workspace/getWorkspaceUsers';
|
import getWorkspaceUsers from '../api/workspace/getWorkspaceUsers';
|
||||||
import uploadKeys from '../api/workspace/uploadKeys';
|
import uploadKeys from '../api/workspace/uploadKeys';
|
||||||
|
|
||||||
|
interface UserProps {
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
email: string;
|
||||||
|
_id: string;
|
||||||
|
publicKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MembershipProps {
|
||||||
|
user: UserProps
|
||||||
|
inviteEmail: string;
|
||||||
|
role: string;
|
||||||
|
status: string;
|
||||||
|
_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
// #TODO: Update all the workspaceIds
|
// #TODO: Update all the workspaceIds
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const {
|
const {
|
||||||
@@ -30,10 +46,10 @@ const nacl = require('tweetnacl');
|
|||||||
nacl.util = require('tweetnacl-util');
|
nacl.util = require('tweetnacl-util');
|
||||||
|
|
||||||
export default function Users() {
|
export default function Users() {
|
||||||
let [isAddOpen, setIsAddOpen] = useState(false);
|
const [isAddOpen, setIsAddOpen] = useState(false);
|
||||||
// let [isDeleteOpen, setIsDeleteOpen] = useState(false);
|
// let [isDeleteOpen, setIsDeleteOpen] = useState(false);
|
||||||
// let [userIdToBeDeleted, setUserIdToBeDeleted] = useState(false);
|
// let [userIdToBeDeleted, setUserIdToBeDeleted] = useState(false);
|
||||||
let [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
const [personalEmail, setPersonalEmail] = useState('');
|
const [personalEmail, setPersonalEmail] = useState('');
|
||||||
const [searchUsers, setSearchUsers] = useState('');
|
const [searchUsers, setSearchUsers] = useState('');
|
||||||
|
|
||||||
@@ -59,7 +75,7 @@ export default function Users() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
async function submitAddModal() {
|
async function submitAddModal() {
|
||||||
let result = await addUserToWorkspace(email, router.query.id);
|
const result = await addUserToWorkspace(email, String(router.query.id));
|
||||||
if (result?.invitee && result?.latestKey) {
|
if (result?.invitee && result?.latestKey) {
|
||||||
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY');
|
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY');
|
||||||
|
|
||||||
@@ -77,7 +93,7 @@ export default function Users() {
|
|||||||
privateKey: PRIVATE_KEY
|
privateKey: PRIVATE_KEY
|
||||||
});
|
});
|
||||||
|
|
||||||
uploadKeys(router.query.id, result.invitee._id, ciphertext, nonce);
|
uploadKeys(String(router.query.id), result.invitee._id, ciphertext, nonce);
|
||||||
}
|
}
|
||||||
setEmail('');
|
setEmail('');
|
||||||
setIsAddOpen(false);
|
setIsAddOpen(false);
|
||||||
@@ -88,41 +104,45 @@ export default function Users() {
|
|||||||
setIsAddOpen(true);
|
setIsAddOpen(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [userList, setUserList] = useState();
|
const [userList, setUserList] = useState([]);
|
||||||
const [orgUserList, setOrgUserList] = useState([]);
|
const [orgUserList, setOrgUserList] = useState([]);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
useEffect(async () => {
|
|
||||||
const user = await getUser();
|
|
||||||
setPersonalEmail(user.email);
|
|
||||||
|
|
||||||
workspaceId = router.query.id;
|
useEffect(() => {
|
||||||
let workspaceUsers = await getWorkspaceUsers({
|
(async () => {
|
||||||
workspaceId
|
const user = await getUser();
|
||||||
});
|
setPersonalEmail(user.email);
|
||||||
const tempUserList = workspaceUsers.map((user) => ({
|
|
||||||
key: guidGenerator(),
|
// This part quiries the current users of a project
|
||||||
firstName: user.user?.firstName,
|
const workspaceUsers = await getWorkspaceUsers({
|
||||||
lastName: user.user?.lastName,
|
workspaceId: String(router.query.id)
|
||||||
email: user.user?.email == null ? user.inviteEmail : user.user?.email,
|
});
|
||||||
role: user?.role,
|
const tempUserList = workspaceUsers.map((membership: MembershipProps) => ({
|
||||||
status: user?.status,
|
key: guidGenerator(),
|
||||||
userId: user.user?._id,
|
firstName: membership.user?.firstName,
|
||||||
membershipId: user._id,
|
lastName: membership.user?.lastName,
|
||||||
publicKey: user.user?.publicKey
|
email: membership.user?.email == null ? membership.inviteEmail : membership.user?.email,
|
||||||
}));
|
role: membership?.role,
|
||||||
setUserList(tempUserList);
|
status: membership?.status,
|
||||||
const orgUsers = await getOrganizationUsers({
|
userId: membership.user?._id,
|
||||||
orgId: localStorage.getItem('orgData.id')
|
membershipId: membership._id,
|
||||||
});
|
publicKey: membership.user?.publicKey
|
||||||
setOrgUserList(orgUsers);
|
}));
|
||||||
setEmail(
|
setUserList(tempUserList);
|
||||||
orgUsers
|
|
||||||
?.filter((user) => user.status == 'accepted')
|
// This is needed to know wha users from an org (if any), we are able to add to a certain project
|
||||||
.map((user) => user.user.email)
|
const orgUsers = await getOrganizationUsers({
|
||||||
.filter(
|
orgId: String(localStorage.getItem('orgData.id'))
|
||||||
(email) => !tempUserList?.map((user1) => user1.email).includes(email)
|
});
|
||||||
)[0]
|
setOrgUserList(orgUsers);
|
||||||
);
|
setEmail(
|
||||||
|
orgUsers
|
||||||
|
?.filter((membership: MembershipProps) => membership.status == 'accepted')
|
||||||
|
.map((membership: MembershipProps) => membership.user.email)
|
||||||
|
.filter(
|
||||||
|
(email: string) => !tempUserList?.map((user1: UserProps) => user1.email).includes(email)
|
||||||
|
)[0]
|
||||||
|
);
|
||||||
|
})();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return userList ? (
|
return userList ? (
|
||||||
@@ -151,17 +171,17 @@ export default function Users() {
|
|||||||
submitModal={submitAddModal}
|
submitModal={submitAddModal}
|
||||||
email={email}
|
email={email}
|
||||||
data={orgUserList
|
data={orgUserList
|
||||||
?.filter((user) => user.status == 'accepted')
|
?.filter((membership: MembershipProps) => membership.status == 'accepted')
|
||||||
.map((user) => user.user.email)
|
.map((membership: MembershipProps) => membership.user.email)
|
||||||
.filter(
|
.filter(
|
||||||
(email) => !userList?.map((user1) => user1.email).includes(email)
|
(email) => !userList?.map((user1: UserProps) => user1.email).includes(email)
|
||||||
)}
|
)}
|
||||||
workspaceId={workspaceId}
|
workspaceId={workspaceId}
|
||||||
setEmail={setEmail}
|
setEmail={setEmail}
|
||||||
/>
|
/>
|
||||||
{/* <DeleteUserDialog isOpen={isDeleteOpen} closeModal={closeDeleteModal} submitModal={deleteMembership} userIdToBeDeleted={userIdToBeDeleted}/> */}
|
{/* <DeleteUserDialog isOpen={isDeleteOpen} closeModal={closeDeleteModal} submitModal={deleteMembership} userIdToBeDeleted={userIdToBeDeleted}/> */}
|
||||||
<div className="px-2 pb-1 w-full flex flex-row items-start max-w-5xl">
|
<div className="px-6 pb-1 w-full flex flex-row items-start min-w-6xl max-w-6xl">
|
||||||
<div className="h-10 w-full bg-white/5 mt-2 flex items-center rounded-md flex flex-row items-center ml-4">
|
<div className="h-10 w-full bg-white/5 mt-2 flex items-center rounded-md flex flex-row items-center">
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
className="bg-white/5 rounded-l-md py-3 pl-4 pr-2 text-gray-400"
|
className="bg-white/5 rounded-l-md py-3 pl-4 pr-2 text-gray-400"
|
||||||
icon={faMagnifyingGlass}
|
icon={faMagnifyingGlass}
|
||||||
@@ -170,12 +190,12 @@ export default function Users() {
|
|||||||
className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none"
|
className="pl-2 text-gray-400 rounded-r-md bg-white/5 w-full h-full outline-none"
|
||||||
value={searchUsers}
|
value={searchUsers}
|
||||||
onChange={(e) => setSearchUsers(e.target.value)}
|
onChange={(e) => setSearchUsers(e.target.value)}
|
||||||
placeholder={t("section-members:search-members")}
|
placeholder={String(t("section-members:search-members"))}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 ml-2 min-w-max flex flex-row items-start justify-start mr-4">
|
<div className="mt-2 ml-2 min-w-max flex flex-row items-start justify-start">
|
||||||
<Button
|
<Button
|
||||||
text={t("section-members:add-member")}
|
text={String(t("section-members:add-member"))}
|
||||||
onButtonPressed={openAddModal}
|
onButtonPressed={openAddModal}
|
||||||
color="mineshaft"
|
color="mineshaft"
|
||||||
size="md"
|
size="md"
|
||||||
@@ -183,7 +203,7 @@ export default function Users() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-y-auto max-w-5xl mx-6">
|
<div className="block overflow-y-auto min-w-6xl max-w-6xl px-6">
|
||||||
<UserTable
|
<UserTable
|
||||||
userData={userList}
|
userData={userList}
|
||||||
changeData={setUserList}
|
changeData={setUserList}
|
||||||
@@ -194,7 +214,6 @@ export default function Users() {
|
|||||||
// onClick={openDeleteModal}
|
// onClick={openDeleteModal}
|
||||||
// deleteUser={deleteMembership}
|
// deleteUser={deleteMembership}
|
||||||
// setUserIdToBeDeleted={setUserIdToBeDeleted}
|
// setUserIdToBeDeleted={setUserIdToBeDeleted}
|
||||||
className="w-full mx-6"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
"title": "Activity Logs",
|
||||||
|
"subtitle": "Event history for this Infisical project.",
|
||||||
"event": {
|
"event": {
|
||||||
"readSecrets": "Secrets Viewed",
|
"readSecrets": "Secrets Viewed",
|
||||||
"updateSecrets": "Secrets Updated",
|
"updateSecrets": "Secrets Updated",
|
||||||
"addSecrets": "Secrets Added",
|
"addSecrets": "Secrets Added",
|
||||||
"deleteSecrets": "Secrets Deleted"
|
"deleteSecrets": "Secrets Deleted"
|
||||||
}
|
},
|
||||||
|
"ip-address": "IP Address"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,5 +22,13 @@
|
|||||||
"expired-in": "Expires in",
|
"expired-in": "Expires in",
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
"search": "Search...",
|
"search": "Search...",
|
||||||
"note": "Note"
|
"note": "Note",
|
||||||
|
"view-more": "View More",
|
||||||
|
"end-of-history": "End of History",
|
||||||
|
"select-event": "Select an event",
|
||||||
|
"event": "Event",
|
||||||
|
"user": "User",
|
||||||
|
"source": "Source",
|
||||||
|
"time": "Time",
|
||||||
|
"timestamp": "Timestamp"
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.9 MiB After Width: | Height: | Size: 2.8 MiB |
Reference in New Issue
Block a user