Skip to content

Commit

Permalink
conflict fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mohandast52 committed May 31, 2024
2 parents 31d4fa8 + d83af3c commit dbbe25b
Show file tree
Hide file tree
Showing 17 changed files with 595 additions and 17 deletions.
5 changes: 5 additions & 0 deletions electron/install.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,4 +370,9 @@ module.exports = {
OperateDirectory,
OperateCmd,
Env,
dirs: {
VersionFile,
LogFile,
OperateInstallationLog,
},
};
100 changes: 100 additions & 0 deletions electron/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ const {
Menu,
Notification,
ipcMain,
dialog,
shell,
} = require('electron');
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const os = require('os');
const next = require('next');
const http = require('http');
const AdmZip = require('adm-zip');
const { TRAY_ICONS, TRAY_ICONS_PATHS } = require('./icons');

const {
Expand All @@ -23,6 +26,7 @@ const {
OperateDirectory,
startDocker,
Env,
dirs,
} = require('./install');
const { killProcesses } = require('./processes');
const { isPortAvailable, findAvailablePort } = require('./ports');
Expand Down Expand Up @@ -560,3 +564,99 @@ process.on('uncaughtException', (error) => {
});
});
});

// OPEN PATH
ipcMain.on('open-path', (_, filePath) => {
shell.openPath(filePath);
});

function getSanitizedLogs({ name, filePath, data }) {
const logs = filePath ? fs.readFileSync(filePath, 'utf-8') : data;
const tempDir = os.tmpdir();

const usernameRegex = /\/Users\/([^/]+)/g;
const sanitizedData = logs.replace(usernameRegex, '/Users/*****');

const sanitizedLogsFilePath = path.join(tempDir, name);
fs.writeFileSync(sanitizedLogsFilePath, sanitizedData);

return sanitizedLogsFilePath;
}

// EXPORT LOGS
ipcMain.handle('save-logs', async (_, data) => {
// version.txt
const versionFile = dirs.VersionFile;
// logs.txt
const logFile = getSanitizedLogs({ name: 'log.txt', filePath: dirs.LogFile });
// operate.log
const installationLog = getSanitizedLogs({
name: 'installation_log.txt',
filePath: dirs.OperateInstallationLog,
});

const tempDir = os.tmpdir();

// OS info
const osInfo = `
OS Type: ${os.type()}
OS Platform: ${os.platform()}
OS Arch: ${os.arch()}
OS Release: ${os.release()}
Total Memory: ${os.totalmem()}
Free Memory: ${os.freemem()}
`;
const osInfoFilePath = path.join(tempDir, 'os_info.txt');
fs.writeFileSync(osInfoFilePath, osInfo);

// Persistent store
let storeFilePath;
if (data.store) {
storeFilePath = path.join(tempDir, 'store.txt');
fs.writeFileSync(storeFilePath, JSON.stringify(data.store, null, 2));
}

// Other debug data: balances, addresses, etc.
let debugDataFilePath;
if (data.debugData) {
debugDataFilePath = getSanitizedLogs({
name: 'debug_data.txt',
data: JSON.stringify(data.debugData, null, 2),
});
}

// Create a zip archive
const zip = new AdmZip();
zip.addLocalFile(versionFile);
zip.addLocalFile(logFile);
zip.addLocalFile(installationLog);
zip.addLocalFile(osInfoFilePath);
zip.addLocalFile(storeFilePath);
zip.addLocalFile(debugDataFilePath);

// Show save dialog
const { filePath } = await dialog.showSaveDialog({
title: 'Save Logs',
defaultPath: path.join(os.homedir(), 'pearl_logs.zip'),
filters: [{ name: 'Zip Files', extensions: ['zip'] }],
});

let result;

if (filePath) {
// Write the zip file to the selected path
zip.writeZip(filePath);
result = { success: true, dirPath: path.dirname(filePath) };
} else {
result = { success: false };
}

// Remove temporary files
fs.unlinkSync(logFile);
fs.unlinkSync(installationLog);
fs.unlinkSync(osInfoFilePath);
if (storeFilePath) fs.unlinkSync(storeFilePath);
if (debugDataFilePath) fs.unlinkSync(debugDataFilePath);

return result;
});
2 changes: 2 additions & 0 deletions electron/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ contextBridge.exposeInMainWorld('electronAPI', {
setAppHeight: (height) => ipcRenderer.send('set-height', height),
showNotification: (title, description) =>
ipcRenderer.send('show-notification', title, description),
saveLogs: (data) => ipcRenderer.invoke('save-logs', data),
openPath: (filePath) => ipcRenderer.send('open-path', filePath),

// update downloads
startDownload: () => ipcRenderer.send('start-download'),
Expand Down
2 changes: 1 addition & 1 deletion frontend/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type ChainData = {
export type Service = {
name: string;
hash: string;
keys: ServiceKeys;
keys: ServiceKeys[];
readme?: string;
ledger: LedgerConfig;
chain_data: ChainData;
Expand Down
121 changes: 121 additions & 0 deletions frontend/components/HelpAndSupport/HelpAndSupport.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { CloseOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { Button, Card, Flex, message, Typography } from 'antd';
import { useCallback, useEffect, useState } from 'react';

import { FAQ_URL, SUPPORT_URL } from '@/constants';
import { UNICODE_SYMBOLS } from '@/constants/unicode';
import { PageState } from '@/enums';
import { useLogs, usePageState } from '@/hooks';
import { useElectronApi } from '@/hooks/useElectronApi';

import { CardTitle } from '../common/CardTitle';
import { CardSection } from '../styled/CardSection';

const { Title, Paragraph } = Typography;

const SettingsTitle = () => (
<CardTitle
title={
<Flex gap={10}>
<QuestionCircleOutlined />
Help & support
</Flex>
}
/>
);

const LogsSavedMessage = ({ onClick }: { onClick: () => void }) => {
return (
<span>
Logs saved
<Button type="link" size="small" onClick={onClick}>
Open folder
</Button>
</span>
);
};

export const HelpAndSupport = () => {
const { goto } = usePageState();
const { openPath, saveLogs } = useElectronApi();

const logs = useLogs();

const [isLoading, setIsLoading] = useState(false);
const [canSaveLogs, setCanSaveLogs] = useState(false);

const onSaveLogs = useCallback(() => setCanSaveLogs(true), []);

useEffect(() => {
if (canSaveLogs && logs && !isLoading) {
setIsLoading(true);
saveLogs?.(logs)
.then((result) => {
if (result.success) {
message.success({
content: (
<LogsSavedMessage onClick={() => openPath?.(result.dirPath)} />
),
duration: 10,
});
} else {
message.error('Save logs failed or cancelled');
}
})
.finally(() => {
setIsLoading(false);
setCanSaveLogs(false);
});
}
}, [canSaveLogs, isLoading, logs, openPath, saveLogs]);

return (
<Card
title={<SettingsTitle />}
bordered={false}
extra={
<Button
size="large"
icon={<CloseOutlined />}
onClick={() => goto(PageState.Main)}
/>
}
>
<CardSection borderbottom="true" padding="16px 24px 24px" vertical>
<Title level={5} className="m-0 mb-16 text-base">
Frequently asked questions
</Title>
<a target="_blank" href={FAQ_URL}>
Read FAQ {UNICODE_SYMBOLS.EXTERNAL_LINK}
</a>
</CardSection>

<CardSection borderbottom="true" padding="16px 24px 24px" vertical>
<Title level={5} className="m-0 mb-8 text-base">
Ask for help
</Title>
<Paragraph type="secondary" className="mb-16 text-sm">
Get your questions answered by the community.
</Paragraph>
<a target="_blank" href={SUPPORT_URL}>
Olas community Discord server {UNICODE_SYMBOLS.EXTERNAL_LINK}
</a>
</CardSection>

<CardSection padding="16px 24px 24px" vertical align="start">
<Title level={5} className="m-0 mb-16 text-base ">
Export logs for troubleshooting
</Title>
<Button
type="primary"
ghost
size="large"
loading={isLoading || canSaveLogs}
onClick={onSaveLogs}
>
Export logs
</Button>
</CardSection>
</Card>
);
};
23 changes: 15 additions & 8 deletions frontend/components/Main/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SettingOutlined } from '@ant-design/icons';
import { QuestionCircleOutlined, SettingOutlined } from '@ant-design/icons';
import { Button, Card, Flex } from 'antd';
import { useEffect } from 'react';

Expand Down Expand Up @@ -32,13 +32,20 @@ export const Main = () => {
<Card
title={<MainHeader />}
extra={
<Button
type="default"
size="large"
onClick={() => goto(PageState.Settings)}
>
<SettingOutlined />
</Button>
<Flex gap={8}>
<Button
type="default"
size="large"
icon={<QuestionCircleOutlined />}
onClick={() => goto(PageState.HelpAndSupport)}
/>
<Button
type="default"
size="large"
icon={<SettingOutlined />}
onClick={() => goto(PageState.Settings)}
/>
</Flex>
}
style={{ borderTopColor: 'transparent' }}
>
Expand Down
Loading

0 comments on commit dbbe25b

Please sign in to comment.