Skip to content

Commit

Permalink
#118 - add Variables to SettingsModal
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Giek committed Jan 13, 2025
1 parent 1c8452e commit 3350094
Show file tree
Hide file tree
Showing 11 changed files with 275 additions and 14 deletions.
13 changes: 13 additions & 0 deletions src/main/environment/service/environment-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ export class EnvironmentService implements Initializable {
}
}

/**
* Sets and saves all variables in the current collection.
* @param variables
*/
public setAndSaveAllVariables(variables: VariableObject[]) {
this.currentCollection.variables = {};
variables.forEach((variable) => (this.currentCollection.variables[variable.key] = variable));
}

/**
* Enables or disables a variable in the current collection.
*
Expand Down Expand Up @@ -96,4 +105,8 @@ export class EnvironmentService implements Initializable {
private getVariableValue(key: string) {
return this.getVariable(key)?.value;
}

public setVariable(variable: VariableObject) {
return this.currentCollection.variables[variable.key] = variable;
}
}
6 changes: 6 additions & 0 deletions src/main/event/main-event-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { PersistenceService } from '../persistence/service/persistence-service';
import { TrufosObject } from 'shim/objects';
import { EnvironmentService } from 'main/environment/service/environment-service';
import './stream-events';
import { VariableObject } from '../../shim/variables';

const persistenceService = PersistenceService.instance;
const environmentService = EnvironmentService.instance;
Expand Down Expand Up @@ -100,4 +101,9 @@ export class MainEventService implements IEventService {
async getVariable(key: string) {
return environmentService.getVariable(key);
}

async setAndSaveAllVariables(variables: VariableObject[]) {
environmentService.setAndSaveAllVariables(variables);
await persistenceService.saveCollection(environmentService.currentCollection);
}
}
50 changes: 40 additions & 10 deletions src/renderer/components/shared/settings/SettingsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,57 @@
import {
Dialog,
Dialog, DialogClose,
DialogContent,
DialogDescription,
DialogDescription, DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
import { FiSettings } from 'react-icons/fi';
import { VariableTab } from '@/components/shared/settings/VariableTab/VariableTab';
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
import { useVariableStore } from '@/state/settingsStore';
import { Button } from '@/components/ui/button';
import * as React from 'react';

export const SettingsModal = () => {
const { save, cancel, openModal } = useVariableStore.getState();
const isOpen = useVariableStore((state) => state.isOpen);

return (
<Dialog>
<DialogTrigger>
<Dialog open={isOpen} onOpenChange={cancel}>
<DialogTrigger onClick={openModal}>
<FiSettings className="text-xl ml-2" />
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Lorem ipsusm?</DialogTitle>
<DialogDescription>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quos blanditiis tenetur
<DialogContent
style={{ minWidth: '60vh'}}
>
<DialogHeader className={'mt-auto'}>
<DialogTitle>Settings</DialogTitle>
<DialogDescription className={'disabled'}>

</DialogDescription>
</DialogHeader>
<Tabs defaultValue="variables" className={'h-[calc(50vh)]'}>
<TabsList>
<TabsTrigger value="variables">Variables</TabsTrigger>
</TabsList>
<TabsContent value="variables" className="max-h-[50vh] overflow-y-auto">
<VariableTab/>
</TabsContent>
</Tabs>
<DialogFooter style={{margin: '-20px'}}>
<DialogClose asChild className={'bottom-0 mr-3'}>
<div>
<Button className={'mt-4 mr-2 mb-4'} onClick={save} variant="secondary">
<span className="leading-4 font-bold">Save</span>
</Button>
<Button className={'mt-4 mr-2 ,b-4'} onClick={cancel} variant="destructive">
<span className="leading-4 font-bold">Cancel</span>
</Button>
</div>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
};
129 changes: 129 additions & 0 deletions src/renderer/components/shared/settings/VariableTab/VariableTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { Divider } from '@/components/shared/Divider';
import { Button } from '@/components/ui/button';
import { AddIcon, CheckedIcon, DeleteIcon } from '@/components/icons';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { cn } from '@/lib/utils';
import { useVariableStore } from '@/state/settingsStore';

export function VariableTab() {

const { addNewVariable, deleteVariable, update } = useVariableStore();
const allVariables = useVariableStore((state) => state.variables);

return (
<div className={'p-4 relative'}>
<div className={'absolute top-[16px] right-[16px] left-[16px] z-10'}>
<div className={'flex'}>
<Button
className={'hover:bg-transparent gap-1 h-fit'}
size={'sm'}
variant={'ghost'}
onClick={addNewVariable}
>
<AddIcon />
Add Variable
</Button>
</div>

<Divider className={'mt-2'} />
</div>

<div className="absolute top-[68px] left-[16px] bottom-[16px] right-[16px]">
<Table className="table-auto w-full">
<TableHeader>
<TableRow>
<TableHead className="w-auto">Key</TableHead>
<TableHead className="w-auto">Value</TableHead>
<TableHead className="w-full"> Description </TableHead>
<TableHead className="w-16"> {/* Action Column */} </TableHead>
</TableRow>
</TableHeader>

<TableBody>
{allVariables.map((variable, index) => (
<TableRow key={index}>
<TableCell className="w-1/4 break-all">
<input
type="text"
value={variable.key}
className="w-full bg-transparent outline-none"
placeholder="Enter variable key"
onChange={(e) => update(index, e.target.value, 'key')}
/>
</TableCell>

<TableCell className="w-1/4 break-all">
<input
type="text"
value={variable.value}
className="w-full bg-transparent outline-none"
placeholder="Enter variable value"
onChange={(e) => update(index, e.target.value, 'value')}
/>
</TableCell>

<TableCell className="w-full break-all">
<input
type="text"
value={variable.description}
onChange={(e) => update(index, e.target.value, 'description')}
className="w-full bg-transparent outline-none"
placeholder="Enter variable description"
/>
</TableCell>

<TableCell className="w-16 text-right">
<div className="flex items-center justify-center gap-2">
<div className={'relative h-4 z-10 cursor-pointer'}>
<input
type="checkbox"
checked={variable.isActive}
onChange={(e) => update(index, e.target.checked, 'isActive')}
className={cn(
'form-checkbox h-4 w-4 appearance-none border rounded-[2px] ',
variable.isActive
? 'border-[rgba(107,194,224,1)] bg-[rgba(25,54,65,1)]'
: 'border-[rgba(238,238,238,1)] bg-transparent'
)}
/>

{variable.isActive && (
<div
className={
'absolute left-0 top-0 h-4 w-4 flex items-center justify-center pointer-events-none rotate-6'
}
>
<CheckedIcon
size={16}
viewBox={'0 0 16 16'}
color={'rgba(107,194,224,1)'}
/>
</div>
)}
</div>

<Button
variant="ghost"
size="icon"
className="hover:bg-transparent hover:text-[rgba(107,194,224,1)] active:text-[#12B1E7] h-6 w-6"
onClick={() => deleteVariable(index)}
>
<DeleteIcon />
</Button>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
);
}
3 changes: 2 additions & 1 deletion src/renderer/components/sidebar/FooterBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';

import { RendererEventService } from '@/services/event/renderer-event-service';
import { GithubIcon } from '@/components/icons';
import { SettingsModal } from '@/components/shared/settings/SettingsModal';

export function FooterBar() {
const [appVersion, setAppVersion] = useState<string>(undefined);
Expand All @@ -25,7 +26,7 @@ export function FooterBar() {
>
<GithubIcon /> {/* Adjust the size as needed */}
</a>
{/*<SettingsModal />*/}
<SettingsModal/>
</div>
);
}
3 changes: 2 additions & 1 deletion src/renderer/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const DialogContent = React.forwardRef<
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DialogPortal>
<DialogOverlay />
<DialogOverlay>
<DialogPrimitive.Content
ref={ref}
className={cn(
Expand All @@ -47,6 +47,7 @@ const DialogContent = React.forwardRef<
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogOverlay>
</DialogPortal>
));
DialogContent.displayName = DialogPrimitive.Content.displayName;
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/ui/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const Tabs = React.forwardRef<
>(({ className, ...props }, ref) => (
<TabsPrimitive.Root
ref={ref}
className={cn('h-[calc(100vh-112px)] flex flex-col bg-background rounded-md', className)}
className={cn('flex flex-col bg-background rounded-md', className)}
{...props}
/>
));
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ RendererEventService.instance.loadCollection().then((collection) => {
const requests = collection.children.filter((c) => c.type === 'request') as TrufosRequest[];
initialize({ requests, collectionId: collection.id });
root.render(<App />);
});
});
1 change: 1 addition & 0 deletions src/renderer/services/event/renderer-event-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const METHOD_NAMES = new Set<keyof IEventService>([
'deleteObject',
'getActiveEnvironmentVariables',
'getVariable',
'setAndSaveAllVariables',
]);

const INSTANCE = {} as IEventService;
Expand Down
74 changes: 74 additions & 0 deletions src/renderer/state/settingsStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { VariableObject } from 'shim/variables';
import { RendererEventService } from '@/services/event/renderer-event-service';

interface VariableState {
variables: VariableObject[];
collectionId: string;
isOpen: boolean;
}

interface VariableStateAction {
openModal: () => void;
addNewVariable: () => void;
deleteVariable: (index: number) => void;
update: (index: number, changeValue: string | boolean, key: keyof VariableObject) => void;
save: () => void;
cancel: () => void;
}

export const useVariableStore = create<VariableState & VariableStateAction>()(
immer((set, get) => ({
variables: [],
collectionId: '',
isOpen: false,
openModal: () => {
RendererEventService.instance.loadCollection().then((collection) => {
const variables = Object.values(collection.variables);
set({
variables: variables,
collectionId: collection.id,
isOpen: true,
});
});
},
addNewVariable: () => {
set((state) => {
console.log('addNewVariable', state.variables);
state.variables.push({
key: '',
value: '',
description: '',
isActive: false,
});
});
},
deleteVariable: (index: number) => {
console.log('deleteVariable', index);
set((state) => {
state.variables.splice(index, 1);
});
},
update: async (index: number, changeValue: string | boolean, key: keyof VariableObject) =>
set((state) => {
console.log('update', index, changeValue, key);
state.variables[index] = {
...state.variables[index],
[key]: changeValue,
};
}),
save: async () => {
RendererEventService.instance.setAndSaveAllVariables(get().variables);
set((state) => {
state.variables = [];
state.isOpen = false;
});
},
cancel: async () =>
set((state) => {
state.variables = [];
state.isOpen = false;
}),
}))
);
6 changes: 6 additions & 0 deletions src/shim/event-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,10 @@ export interface IEventService {
* @param key The key of the variable.
*/
getVariable(key: string): Promise<VariableObject>;

/**
* Set a variable.
* @param variables
*/
setAndSaveAllVariables(variables: VariableObject[]): void;
}

0 comments on commit 3350094

Please sign in to comment.