Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate old db #1053

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 2 additions & 71 deletions __tests__/__main__/import-export.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
const {
exportDatabaseToFile,
importDatabaseFromFile,
migrateFixedDbToFlexible,
validEntry
} = require('../../js/import-export');

Expand All @@ -16,51 +15,30 @@ describe('Import export', function()
{
process.env.NODE_ENV = 'test';

// TODO: Regular store entries are still here to test import of old dbs. Please remove on the next release.
describe('validEntry(entry)', function()
{
const goodRegularEntry = {'type': 'regular', 'date': '2020-06-03', 'data': 'day-begin', 'hours': '08:00'};
const goodFlexibleEntry = {'type': 'flexible', 'date': '2020-06-03', 'values': ['08:00', '12:00', '13:00', '14:00']};
const goodWaivedEntry = {'type': 'waived', 'date': '2020-06-03', 'data': 'waived', 'hours': '08:00'};
const badRegularEntry = {'type': 'regular', 'date': 'not-a-date', 'data': 'day-begin', 'hours': '08:00'};
const badFlexibleEntry = {'type': 'flexible', 'date': '2020-06-03', 'values': ['not-an-hour']};
const badFlexibleEntry2 = {'type': 'flexible', 'date': '2020-06-03', 'values': 'not-an-array'};
const badWaivedEntry = {'type': 'regular', 'date': '2020-06-03', 'data': 'day-begin', 'hours': 'not-an-hour'};
test('should be valid', () =>
{
expect(validEntry(goodRegularEntry)).toBeTruthy();
expect(validEntry(goodWaivedEntry)).toBeTruthy();
expect(validEntry(goodFlexibleEntry)).toBeTruthy();
});

test('should not be valid', () =>
{
expect(validEntry(badRegularEntry)).not.toBeTruthy();
expect(validEntry(badWaivedEntry)).not.toBeTruthy();
expect(validEntry(badFlexibleEntry)).not.toBeTruthy();
expect(validEntry(badFlexibleEntry2)).not.toBeTruthy();
});
});

const store = new Store();
const flexibleStore = new Store({name: 'flexible-store'});
const waivedWorkdays = new Store({name: 'waived-workdays'});

// TODO: Regular store is still here to test migration of dbs. Please remove on the next release.
store.clear();
const regularEntries = {
'2020-3-1-day-begin': '08:00',
'2020-3-1-day-end': '17:00',
'2020-3-1-day-total': '08:00',
'2020-3-1-lunch-begin': '12:00',
'2020-3-1-lunch-end': '13:00',
'2020-3-1-lunch-total': '01:00',
'2020-3-2-day-begin': '10:00',
'2020-3-2-day-end': '18:00',
'2020-3-2-day-total': '08:00',
};
store.set(regularEntries);

flexibleStore.clear();
const flexibleEntries = {
'2020-3-1': {'values': ['08:00', '12:00', '13:00', '17:00']},
Expand Down Expand Up @@ -88,9 +66,9 @@ describe('Import export', function()
});

const invalidEntriesContent =
`[{"type": "regular", "date": "not-a-date", "data": "day-begin", "hours": "08:00"},
`[{"type": "flexible", "date": "not-a-date", "data": "day-begin", "hours": "08:00"},
{"type": "waived", "date": "2020-01-01", "data": "example waiver 2", "hours": "not-an-hour"},
{"type": "regular", "date": "not-a-date", "data": "day-end", "hours": "17:00"},
{"type": "flexible", "date": "not-a-date", "data": "day-end", "hours": "17:00"},
{"type": "flexible", "date": "not-a-date", "values": "not-an-array"},
{"type": "not-a-type", "date": "not-a-date", "data": "day-end", "hours": "17:00"}
]`;
Expand All @@ -109,53 +87,6 @@ describe('Import export', function()
});
});

const migratedFlexibleEntries = {
'2020-3-1': {'values': ['08:00', '12:00', '13:00', '17:00']},
'2020-3-2': {'values': ['10:00', '18:00']}
};

describe('migrateFixedDbToFlexible', function()
{
test('Check that migration works', () =>
{
expect(flexibleStore.size).toBe(2);
flexibleStore.clear();
expect(flexibleStore.size).toBe(0);
migrateFixedDbToFlexible();
expect(flexibleStore.size).toBe(2);
expect(flexibleStore.get('2020-3-1')).toStrictEqual(migratedFlexibleEntries['2020-3-1']);
expect(flexibleStore.get('2020-3-2')).toStrictEqual(migratedFlexibleEntries['2020-3-2']);
});
});

// TODO: Mixed importing is still here due to compatibility with old dbs. Please remove on the next release.
const mixedEntriesContent =
`[{"type": "regular", "date": "2020-6-3", "data": "day-end", "hours": "10:00"},
{"type": "regular", "date": "2020-6-3", "data": "day-begin", "hours": "08:00"},
{"type": "flexible", "date": "2020-3-1", "values": ["08:00", "12:00", "13:00", "17:00"]}
]`;
const mixedEntriesFile = path.join(folder, 'mixed.ttldb');
fs.writeFileSync(mixedEntriesFile, mixedEntriesContent, 'utf8');

// Expected values have month-1, due to how the db saves them starting from 0
const expectedMixedEntries = {
'2020-2-1': {'values': ['08:00', '12:00', '13:00', '17:00']},
'2020-5-3': {'values': ['08:00', '10:00']}
};

describe('importDatabaseFromFile (mixedContent)', function()
{
test('Check that import works', () =>
{
flexibleStore.clear();
expect(flexibleStore.size).toBe(0);
expect(importDatabaseFromFile([mixedEntriesFile])['result']).toBeTruthy();
expect(flexibleStore.size).toBe(2);
expect(flexibleStore.get('2020-2-1')).toStrictEqual(expectedMixedEntries['2020-2-1']);
expect(flexibleStore.get('2020-5-3')).toStrictEqual(expectedMixedEntries['2020-5-3']);
});
});

afterAll(() =>
{
fs.rmSync(folder, {recursive: true});
Expand Down
2 changes: 1 addition & 1 deletion __tests__/__main__/validate-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('Validate json', function()
});
});

describe('validate date with and without leading 0', function()
describe('validate date with and without leading 0', function()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be in a separate pr/commit?

{
const validFlexibleDate1 = [{ 'type': 'flexible', 'date': '2020-06-03', 'values': ['08:00', '12:00', '13:00', '14:00'] }];
const validFlexibleDate2 = [{ 'type': 'flexible', 'date': '2020-6-3', 'values': ['08:00', '12:00', '13:00', '14:00'] }];
Expand Down
75 changes: 4 additions & 71 deletions js/import-export.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import fs from 'fs';

import { validateTime } from './time-math.js';
import { generateKey } from './date-db-formatter.js';
import { assert } from 'console';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to keep all external imports at the top of the file, and local imports below


/**
* Returns the database (only flexible calendar entries) as an array of:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we can also remove the "flexible" comments and name functions now that the other doesn't exist anymore

Expand Down Expand Up @@ -76,8 +77,7 @@ function _validateDate(dateStr)

function validEntry(entry)
{
// TODO: 'regular' is still here while we allow importing old DB data. Please remove on the next release.
if (entry.hasOwnProperty('type') && ['regular', 'waived', 'flexible'].indexOf(entry.type) !== -1)
if (entry.hasOwnProperty('type') && ['waived', 'flexible'].indexOf(entry.type) !== -1)
{
const validatedDate = entry.hasOwnProperty('date') && _validateDate(entry.date);
let hasExpectedProperties;
Expand Down Expand Up @@ -106,20 +106,6 @@ function validEntry(entry)
return false;
}

function mergeOldStoreDataIntoFlexibleStore(flexibleEntry, oldStoreHours)
{
let index = 0;
for (const hour of flexibleEntry.values)
{
if (oldStoreHours > hour)
{
index++;
}
}
flexibleEntry.values.splice(index, 0, oldStoreHours);
return flexibleEntry;
}

function importDatabaseFromFile(filename)
{
const flexibleStore = new Store({name: 'flexible-store'});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise this doesn't need to be called flexibleStore anymore
Maybe just store or entryStore

Expand All @@ -144,26 +130,12 @@ function importDatabaseFromFile(filename)
}
else
{
assert(entry.type === 'flexible');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we write something on the test that hit this assert?

const [year, month, day] = entry.date.split('-');
//The main database uses a JS-based month index (0-11)
//So we need to adjust it from human month index (1-12)
const date = generateKey(year, (parseInt(month) - 1), day);
if (entry.type === 'flexible')
{
flexibleEntries[date] = {values: entry.values};
}
else if (entry.type === 'regular')
{
// TODO: 'regular' is still here while we allow importing old DB data. Please remove on the next release.
const [/*event*/, key] = entry.data.split('-');
if (['begin', 'end'].indexOf(key) !== -1)
{
let currentFlexibleEntry = flexibleEntries[date];
if (currentFlexibleEntry === undefined)
currentFlexibleEntry = { values: [] };
flexibleEntries[date] = mergeOldStoreDataIntoFlexibleStore(currentFlexibleEntry, entry.hours);
}
}
flexibleEntries[date] = {values: entry.values};
}
}

Expand All @@ -182,47 +154,8 @@ function importDatabaseFromFile(filename)
return {'result': true};
}

function migrateFixedDbToFlexible()
{
const store = new Store();
const flexibleStore = new Store({name: 'flexible-store'});
flexibleStore.clear();
const regularEntryArray = [];
for (const entry of store)
{
const key = entry[0];
const value = entry[1];

const [year, month, day, /*stage*/, step] = key.split('-');
if (['begin', 'end'].indexOf(step) !== -1)
{
const date = generateKey(year, month, day);
if (regularEntryArray[date] === undefined)
{
regularEntryArray[date] = { values: []};
}
regularEntryArray[date].values.push(value);
}
}
try
{
for (const key of Object.keys(regularEntryArray))
{
regularEntryArray[key].values.sort();
flexibleStore.set(key, regularEntryArray[key]);
}
}
catch (err)
{
console.log(err);
return {'result': false, 'err': err};
}
return {'result': true, 'err': ''};
}

module.exports = {
exportDatabaseToFile,
importDatabaseFromFile,
migrateFixedDbToFlexible,
validEntry,
};
106 changes: 2 additions & 104 deletions js/main-window.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
'use strict';

import { app, BrowserWindow, dialog, ipcMain, Menu, shell, Tray } from 'electron';
import { app, BrowserWindow, ipcMain, Menu, Tray } from 'electron';
import path from 'path';
import Store from 'electron-store';

const { checkForUpdates, shouldCheckForUpdates } = require('./update-manager');
const { migrateFixedDbToFlexible } = require('./import-export.js');
const {
getContextMenuTemplate,
getDockMenuTemplate,
Expand All @@ -18,7 +16,7 @@ const { getCurrentTranslation } = require('../src/configs/i18next.config');
let { contextMenu, tray } = require('./windows.js');

import { getDefaultWidthHeight, getUserPreferences, switchCalendarView } from './user-preferences.js';
import { appConfig, getDetails } from './app-config.cjs';
import { appConfig } from './app-config.cjs';
import { createLeaveNotification } from './notification.js';

// Keep a global reference of the window object, if you don't, the window will
Expand Down Expand Up @@ -168,104 +166,6 @@ function triggerStartupDialogs()
{
checkForUpdates(/*showUpToDateDialog=*/false);
}

if (shouldProposeFlexibleDbMigration())
{
proposeFlexibleDbMigration();
}
}

function proposeFlexibleDbMigration()
{
const options = {
type: 'question',
buttons: [getCurrentTranslation('$Menu.migrate'), getCurrentTranslation('$Menu.fresh-start')],
defaultId: 2,
title: getCurrentTranslation('$Menu.migrate-calendar-to-flexible'),
message: getCurrentTranslation('$Menu.should-migrate-to-flexible'),
};

const response = dialog.showMessageBoxSync(BrowserWindow.getFocusedWindow(), options);
if (response === 0 /*migrate*/)
{
const migrateResult = migrateFixedDbToFlexible();
mainWindow.webContents.send('RELOAD_CALENDAR');
if (migrateResult['result'] === true)
{
dialog.showMessageBox(BrowserWindow.getFocusedWindow(),
{
title: 'Time to Leave',
message: getCurrentTranslation('$Menu.database-migrated'),
type: 'info',
icon: appConfig.iconpath,
detail: getCurrentTranslation('$Menu.migration-successful')
});
}
else
{
handleFailedFlexibleDbMigration(migrateResult);
}
}
else if (response === 1 /*fresh-start*/)
{
const confirmOptions = {
type: 'question',
buttons: [getCurrentTranslation('$Menu.cancel'), getCurrentTranslation('$Menu.yes-please')],
defaultId: 2,
title: getCurrentTranslation('$Menu.fresh-start'),
message: getCurrentTranslation('$Menu.fresh-start-confirm'),
};

const confirmResponse = dialog.showMessageBoxSync(BrowserWindow.getFocusedWindow(), confirmOptions);
if (confirmResponse === 0 /*cancel*/)
{
proposeFlexibleDbMigration();
}
}
}

/**
* @param {Object} migrateResult Result of migrateFixedDbToFlexible() call
*/
function handleFailedFlexibleDbMigration(migrateResult)
{
const warningResponse = dialog.showMessageBoxSync({
type: 'warning',
buttons: [getCurrentTranslation('$Menu.report'), getCurrentTranslation('$Menu.quit')],
title: getCurrentTranslation('$Menu.failed-migrating'),
message: getCurrentTranslation('$Menu.something-went-wrong')
});

if (warningResponse === 0 /*report*/)
{
const issueTitle = 'Failed Migrating Database';
const err = migrateResult['err'];
const LB = '%0D%0A'; // Line Break char in html encoding
const encodedDetails = getDetails().replaceAll('\n', LB);
const issueBody = `While performing database migration, my application failed with the following issue:${LB}` +
LB +
'```' + LB +
err + LB +
'```' + LB +
LB +
'Environment:' + LB +
LB +
encodedDetails + LB +
LB +
'Please look into it.';
shell.openExternal(`https://github.com/thamara/time-to-leave/issues/new?labels=bug&title=${issueTitle}&body=${issueBody}`);
}

app.quit();
}

function shouldProposeFlexibleDbMigration()
{
const store = new Store();
const flexibleStore = new Store({name: 'flexible-store'});

// There is data saved on the old store, but nothing yet on the flexible store.
return store.size !== 0 && flexibleStore.size === 0;
}

function resetMainWindow()
Expand All @@ -292,8 +192,6 @@ module.exports = {
getLeaveByInterval: () => leaveByInterval,
getMainWindow,
getWindowTray: () => tray,
proposeFlexibleDbMigration,
resetMainWindow,
shouldProposeFlexibleDbMigration,
triggerStartupDialogs,
};
Loading