initial commit
This commit is contained in:
36
app/config.js
Normal file
36
app/config.js
Normal file
@ -0,0 +1,36 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const { app } = require('electron');
|
||||
const userDataPath = app.getPath('userData');
|
||||
const CONFIG_FILE_NAME = 'timesheet-config.json';
|
||||
const configPath = path.join(userDataPath, CONFIG_FILE_NAME);
|
||||
|
||||
function initializeConfig() {
|
||||
const initial = require('./config.json');
|
||||
saveConfig(initial);
|
||||
}
|
||||
|
||||
function saveConfig(config) {
|
||||
console.log('Saving: ' + JSON.stringify(config));
|
||||
fs.writeJSONSync(configPath, config, {
|
||||
encoding: 'utf-8',
|
||||
spaces: 2
|
||||
});
|
||||
}
|
||||
|
||||
function getConfig() {
|
||||
if (!fs.existsSync(configPath)) {
|
||||
initializeConfig();
|
||||
}
|
||||
const options = fs.readJSONSync(configPath, 'utf-8');
|
||||
return options;
|
||||
}
|
||||
|
||||
function setConfig(config) {
|
||||
saveConfig(config);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getConfig,
|
||||
setConfig
|
||||
};
|
6
app/config.json
Normal file
6
app/config.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"secondsToReload": 60,
|
||||
"cutDay": 6,
|
||||
"cutHour": 4,
|
||||
"timezone": "America/Denver"
|
||||
}
|
18
app/dist/index.html
vendored
Normal file
18
app/dist/index.html
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="./vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Salud y Vida PA | Timesheet - 1.5.0</title>
|
||||
<script type="module" crossorigin src="./assets/index.680f16a8.js"></script>
|
||||
<link rel="stylesheet" href="./assets/index.6a5e126f.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
1
app/dist/vite.svg
vendored
Normal file
1
app/dist/vite.svg
vendored
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
BIN
app/favicon-32x32.png
Normal file
BIN
app/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
33
app/index.htm_
Normal file
33
app/index.htm_
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; connect-src *;">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>Fire Sale</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<section class="controls">
|
||||
<button id="new-file">New File</button>
|
||||
<button id="open-file">Open File</button>
|
||||
<button id="save-markdown" disabled>Save File</button>
|
||||
<button id="revert" disabled>Revert</button>
|
||||
<button id="save-html">Save HTML</button>
|
||||
<button id="show-file" disabled>Show File</button>
|
||||
<button id="open-in-default" disabled>Open in Default Application</button>
|
||||
</section>
|
||||
|
||||
<section class="content">
|
||||
<label for="markdown" hidden>Markdown Content</label>
|
||||
<textarea class="raw-markdown" id="markdown"></textarea>
|
||||
<div class="rendered-html" id="html"></div>
|
||||
</section>
|
||||
</body>
|
||||
|
||||
<script src="./renderer.js"></script>
|
||||
|
||||
</html>
|
34
app/index.html
Normal file
34
app/index.html
Normal file
@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'" />
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'" />
|
||||
<title>Hello from Electron renderer!</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Hello from Electron renderer!</h1>
|
||||
<p>👋</p>
|
||||
<p id="info"></p>
|
||||
<section class="controls">
|
||||
<button id="new-file">New File</button>
|
||||
<button id="open-file">Open File</button>
|
||||
<button id="save-markdown" disabled>Save File</button>
|
||||
<button id="revert" disabled>Revert</button>
|
||||
<button id="save-html">Save HTML</button>
|
||||
<button id="show-file" disabled>Show File</button>
|
||||
<button id="open-in-default" disabled>Open in Default Application</button>
|
||||
</section>
|
||||
|
||||
<section class="content">
|
||||
<label for="markdown" hidden>Markdown Content</label>
|
||||
<textarea class="raw-markdown" id="markdown"></textarea>
|
||||
<div class="rendered-html" id="html"></div>
|
||||
</section>
|
||||
</body>
|
||||
<script src="./renderer.js"></script>
|
||||
|
||||
</html>
|
57
app/main.js
Normal file
57
app/main.js
Normal file
@ -0,0 +1,57 @@
|
||||
const { app, BrowserWindow, ipcMain } = require('electron');
|
||||
const path = require('path');
|
||||
const { post } = require('./request')
|
||||
const { deputyUrl, deputyToken } = require('../env.json');
|
||||
const { getConfig, setConfig } = require('./config');
|
||||
|
||||
function createWindow() {
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 1440 ,
|
||||
height: 900,
|
||||
show: false,
|
||||
icon: path.join(__dirname, 'favicon-32x32.png'),
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
allowRunningInsecureContent: true,
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('getTimesheet', async(event, body) => {
|
||||
try {
|
||||
const { apitoken } = getConfig();
|
||||
const token = apitoken || deputyToken;
|
||||
return await post(deputyUrl, body, { Authorization: `OAuth ${token}` });
|
||||
} catch (err) {
|
||||
console.log('err :>> ', err);
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('getAppConfig', () => {
|
||||
const config = getConfig();
|
||||
return {... { apitoken: deputyToken }, ...config };
|
||||
});
|
||||
|
||||
ipcMain.handle('setAppConfig', (event, config) => {
|
||||
return setConfig(config);
|
||||
})
|
||||
|
||||
mainWindow.maximize();
|
||||
mainWindow.removeMenu();
|
||||
mainWindow.loadFile(path.join(__dirname, '..', 'ui', 'dist', 'index.html'));
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools();
|
||||
mainWindow.show();
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
||||
})
|
||||
});
|
||||
|
||||
app.on('window-all-closed', function() {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
});
|
16
app/preload.js
Normal file
16
app/preload.js
Normal file
@ -0,0 +1,16 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron');
|
||||
|
||||
contextBridge.exposeInMainWorld('IS_ELECTRON', true);
|
||||
|
||||
contextBridge.exposeInMainWorld('versions', {
|
||||
node: () => process.versions.node,
|
||||
chrome: () => process.versions.chrome,
|
||||
electron: () => process.versions.electron,
|
||||
app: () => '1.2.2',
|
||||
});
|
||||
|
||||
contextBridge.exposeInMainWorld('services', {
|
||||
getTimesheet: (body) => ipcRenderer.invoke('getTimesheet', body),
|
||||
getConfig: () => ipcRenderer.invoke('getAppConfig'),
|
||||
setConfig: config => ipcRenderer.invoke('setAppConfig', config),
|
||||
});
|
7
app/renderer.js
Normal file
7
app/renderer.js
Normal file
@ -0,0 +1,7 @@
|
||||
const func = async() => {
|
||||
const response = window.versions.app
|
||||
console.log(response);
|
||||
window.title += ` ${window.versions.app}`;
|
||||
}
|
||||
|
||||
func();
|
64
app/request.js
Normal file
64
app/request.js
Normal file
@ -0,0 +1,64 @@
|
||||
const { net } = require('electron');
|
||||
|
||||
async function get(url, headers) {
|
||||
return request({ url, method: 'GET', headers })
|
||||
}
|
||||
|
||||
async function post(url, body, headers) {
|
||||
return request({ url, method: 'POST', headers }, body)
|
||||
}
|
||||
|
||||
async function request(options, body) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const responseBody = [];
|
||||
let responseHeaders;
|
||||
let responseStatus;
|
||||
|
||||
const request = net.request(options);
|
||||
|
||||
request.on('response', (response) => {
|
||||
responseStatus = response.statusCode;
|
||||
responseHeaders = response.headers;
|
||||
|
||||
response.on('data', (chunk) => {
|
||||
if (chunk) {
|
||||
responseBody.push(`${chunk}`);
|
||||
}
|
||||
});
|
||||
response.on('end', () => {
|
||||
resolve({
|
||||
status: responseStatus,
|
||||
headers: responseHeaders,
|
||||
body: parseReponseBody(responseBody),
|
||||
});
|
||||
});
|
||||
|
||||
response.on('aborted', () => console.log('request aborted'));
|
||||
response.on('error', (error) => reject(error));
|
||||
});
|
||||
|
||||
request.on('error', (error) => reject(error));
|
||||
|
||||
request.setHeader('Content-Type', 'application/json');
|
||||
if (['POST'].includes(options.method.toUpperCase())) {
|
||||
request.write(JSON.stringify(body), 'utf-8')
|
||||
}
|
||||
request.end();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function parseReponseBody(body) {
|
||||
if (Array.isArray(body)) {
|
||||
if (body.length) {
|
||||
return JSON.parse(body.join(''));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
get,
|
||||
post
|
||||
};
|
99
app/style.css
Normal file
99
app/style.css
Normal file
@ -0,0 +1,99 @@
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
body,
|
||||
input {
|
||||
font: menu;
|
||||
}
|
||||
|
||||
textarea,
|
||||
input,
|
||||
div,
|
||||
button {
|
||||
outline: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.controls {
|
||||
background-color: rgb(217, 241, 238);
|
||||
padding: 10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: 14px;
|
||||
background-color: rgb(181, 220, 216);
|
||||
border: none;
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: rgb(156, 198, 192);
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: rgb(144, 182, 177);
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
background-color: rgb(196, 204, 202);
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
min-width: 100vw;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.content {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.raw-markdown,
|
||||
.rendered-html {
|
||||
min-height: 100%;
|
||||
max-width: 50%;
|
||||
flex-grow: 1;
|
||||
padding: 1em;
|
||||
overflow: scroll;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.raw-markdown {
|
||||
border: 5px solid rgb(238, 252, 250);
|
||||
;
|
||||
background-color: rgb(238, 252, 250);
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.raw-markdown.drag-over {
|
||||
background-color: rgb(181, 220, 216);
|
||||
border-color: rgb(75, 160, 151);
|
||||
}
|
||||
|
||||
.raw-markdown.drag-error {
|
||||
background-color: rgba(170, 57, 57, 1);
|
||||
border-color: rgba(255, 170, 170, 1);
|
||||
}
|
Reference in New Issue
Block a user