Skip to content

Commit

Permalink
feat: save settings locally
Browse files Browse the repository at this point in the history
Re RM:27156
Re #418
  • Loading branch information
cristinecula committed Oct 15, 2021
1 parent db61b0d commit f636fc7
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 22 deletions.
14 changes: 11 additions & 3 deletions cosmoz-omnitable.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
<cosmoz-omnitable-header-row
columns="[[ normalizedColumns ]]"
group-on-column="[[ groupOnColumn ]]"
content="[[ _renderSettings(normalizedSettings, collapsedColumns) ]]"
content="[[ _renderSettings(normalizedSettings, collapsedColumns, settingsId, hasChangedSettings) ]]"
>
</div>
<div class="tableContent" id="tableContent">
Expand Down Expand Up @@ -411,6 +411,10 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
},
computedBarHeight: {
type: Number
},
settingsId: {
type: String,
value: undefined
}
};
}
Expand Down Expand Up @@ -1281,11 +1285,15 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
};
}

_renderSettings(normalizedSettings, collapsed) {
_renderSettings(normalizedSettings, collapsed, settingsId, hasChangedSettings) {
return litHtml`<cosmoz-omnitable-settings
.settings=${ normalizedSettings }
.onSettings=${ this.setSettings }
.collapsed=${ collapsed.map(c => c.name) }
.collapsed=${ collapsed?.map(c => c.name) }
.settingsId=${ settingsId }
.hasChanges=${ hasChangedSettings }
.onSave=${ this.onSettingsSave }
.onReset=${ this.onSettingsReset }
>`;
}
}
Expand Down
2 changes: 1 addition & 1 deletion demo/helpers/x-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class XPage extends translatable(PolymerElement) {
<cosmoz-omnitable loading="[[ loading ]]" id="omnitable"
data="[[ data ]]" selection-enabled selected-items="{{ selectedItems }}"
hash-param="[[ hashParam ]]">
hash-param="[[ hashParam ]]" settings-id="test">
<cosmoz-omnitable-column priority="-1" title="Name" name="name" value-path="name" sort-on="name" group-on="name" flex="2" render-cell="[[ renderNameCell ]]">
</cosmoz-omnitable-column>
<cosmoz-omnitable-column-amount title="[[ _('Amount', t) ]]" name="amount"
Expand Down
37 changes: 31 additions & 6 deletions lib/cosmoz-omnitable-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useFocus } from '@neovici/cosmoz-autocomplete/lib/use-focus';
import { portal } from '@neovici/cosmoz-utils/lib/directives/portal';
import { useMeta } from '@neovici/cosmoz-utils/lib/hooks/use-meta';
import { checkbox } from '../cosmoz-omnitable-styles';
import { nothing } from 'lit-html';
const settingsStyles = `
:host {
position: fixed;
Expand Down Expand Up @@ -54,6 +55,16 @@ const settingsStyles = `
flex: 1;
}
${ checkbox }
.footer {
display: flex;
margin-top: 10px;
}
.footer > button {
flex: 1;
}
.footer > button:first-child {
margin-right: 5px;
}
`,

parseIndex = str => {
Expand All @@ -75,6 +86,11 @@ const settingsStyles = `
settings: host.settings,
collapsed: host.collapsed,

settingsId: host.settingsId,
hasChanges: host.hasChanges,
onSave: host.onSave,
onReset: host.onReset,

onDown: useCallback(e => {
if (!e.target.closest('.sort')) {
return;
Expand Down Expand Up @@ -169,15 +185,23 @@ const settingsStyles = `
},

SettingsUI = host => {
const { settings, ...thru } = useSettings(host);
return html`
<style>${ settingsStyles }</style>
<div class="list"> ${ settings.map(renderItem(thru)) }</div>`;

const { settings, settingsId, onSave, onReset, hasChanges, ...thru } = useSettings(host);
return [
html`
<style>${ settingsStyles }</style>
<div class="list">${ settings.map(renderItem(thru)) }</div>
`,
settingsId
? html`<div class="footer">
<button @click=${ onSave } ?disabled=${ !hasChanges }>Save</button>
<button @click=${ onReset } ?disabled=${ !hasChanges }>Reset</button>
</div>`
: nothing
];
},

Settings = host => {
const { settings, onSettings, collapsed } = host,
const { settings, onSettings, onSave, onReset, collapsed, settingsId, hasChanges } = host,
{ active, onFocus, onToggle } = useFocus(host),
anchor = useCallback(() => host.shadowRoot.querySelector('.anchor'), []);

Expand All @@ -204,6 +228,7 @@ const settingsStyles = `
${ active
? portal(html`<cosmoz-omnitable-settings-ui
tabindex="-1" .anchor=${ anchor } .settings=${ settings } .onSettings=${ onSettings } .collapsed=${ collapsed }
.settingsId=${ settingsId } .hasChanges=${ hasChanges } .onSave=${ onSave } .onReset=${ onReset }
@focusin=${ onFocus } @focusout=${ onFocus } data-dropdown>`)
: [] }
`;
Expand Down
31 changes: 22 additions & 9 deletions lib/normalize-settings.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
const byName = name => item => item.name === name;

export const
columnSymbol = Symbol('column'),
normalizeSettings = (columns = [], settings = []) => {
const cols = columns.slice();
for (const setting of settings) {
const idx = cols.findIndex(c => c.name === setting.name);
if (idx < 0) {
continue;
}
cols.splice(idx, 1);
}
normalizeSettings = (columns = [], settings = [], savedSettings = []) => {
const
cols = columns.filter(column => !settings.some(byName(column.name)) && !savedSettings.some(byName(column.name))),
_savedSettings = savedSettings.filter(column => !settings.some(byName(column.name)));

return [
...settings,
..._savedSettings
.flatMap(setting => {
const column = columns.find(c => c.name === setting.name);

if (!column) {
return [];
}

return {
...setting,
title: column.title,
minWidth: parseInt(column.minWidth, 10),
[columnSymbol]: column
};
}),
...cols.map(column => {
const { name, title, priority, minWidth, width, flex } = column;
return {
Expand Down
11 changes: 8 additions & 3 deletions lib/use-omnitable.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useMemo, useState } from 'haunted';
import { columnSymbol, normalizeSettings } from './normalize-settings';
import { useFastLayout } from './use-fast-layout';
import { useSavedSettings } from './use-saved-settings';

// eslint-disable-next-line max-lines-per-function
export const useOmnitable = host => {
const
{ columns, groupOnColumn, resizeSpeedFactor } = host,
{ columns, groupOnColumn, resizeSpeedFactor, settingsId } = host,
[settings, setSettings] = useState([]),
normalizedSettings = useMemo(() => normalizeSettings(columns, settings), [columns, settings]),
{ savedSettings, onSettingsSave, onSettingsReset, hasChangedSettings } = useSavedSettings(settingsId, settings, setSettings),
normalizedSettings = useMemo(() => normalizeSettings(columns, settings, savedSettings), [columns, settings, savedSettings]),
normalizedColumns = useMemo(() => normalizedSettings.map(s => s[columnSymbol]), [columns, ...normalizedSettings.map(s => s.name)]),
{ layoutCss, collapsedColumns } = useFastLayout({ host, settings: normalizedSettings, setSettings, groupOnColumn, resizeSpeedFactor });

Expand All @@ -16,6 +18,9 @@ export const useOmnitable = host => {
setSettings,
normalizedSettings,
normalizedColumns,
collapsedColumns
collapsedColumns,
onSettingsSave,
onSettingsReset,
hasChangedSettings
};
};
45 changes: 45 additions & 0 deletions lib/use-saved-settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useCallback, useMemo, useState } from 'haunted';
import { omit } from '@neovici/cosmoz-utils/lib/object';

const storagePrefix = 'omnitable-';

export const useSavedSettings = (settingsId, settings, setSettings) => {
const
[counter, setCounter] = useState(0),
savedSettings = useMemo(() => {
if (!settingsId) {
return [];
}

try {
return JSON.parse(localStorage.getItem(storagePrefix + settingsId)) ?? [];
} catch (e) {
return [];
}
}, [settingsId, counter]);

return {
savedSettings,

onSettingsSave: useCallback(() => {
if (!settingsId) {
return;
}

try {
localStorage.setItem(storagePrefix + settingsId, JSON.stringify(settings.map(omit(['title', 'minWidth']))));
setSettings([]);
setCounter(counter => counter + 1);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
}, [settings]),

onSettingsReset: () => {
setSettings([]);
},

hasChangedSettings: settings.length !== 0
};
};

0 comments on commit f636fc7

Please sign in to comment.