Skip to content

Commit 74c95a6

Browse files
philippottobulldozer-boy[bot]
authored andcommitted
Prefix local storage access with user email address (#4217)
* prefix local storage access with user email address * update changelog * Merge branch 'master' into prefix-localstorage * Apply suggestions from code review Co-Authored-By: Daniel <[email protected]> * add prefixKey to UserLocalStorage.clear()
1 parent fa344fd commit 74c95a6

File tree

8 files changed

+67
-19
lines changed

8 files changed

+67
-19
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.md).
4747
- Fixed a bug where for uint24 color layers, scrambled data was shown for missing magnifications. [#4188](https://github.com/scalableminds/webknossos/pull/4188)
4848
- Fixed a bug where collapsing/expanding all tree groups would trigger when toggling a single tree [#4178](https://github.com/scalableminds/webknossos/pull/4178)
4949
- Fixed performance for time logging. [#4196](https://github.com/scalableminds/webknossos/pull/4196)
50+
- Personal tracing layouts are saved per user now. [#4217](https://github.com/scalableminds/webknossos/pull/4217)
5051
- Fixed an error message when quickly resizing the browser window. [#4205](https://github.com/scalableminds/webknossos/pull/4205)
5152

5253
### Removed

frontend/javascripts/dashboard/dashboard_view.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import DatasetView from "dashboard/dataset_view";
1414
import ExplorativeAnnotationsView from "dashboard/explorative_annotations_view";
1515
import NmlUploadZoneContainer from "oxalis/view/nml_upload_zone_container";
1616
import Request from "libs/request";
17+
import UserLocalStorage from "libs/user_local_storage";
1718

1819
const { TabPane } = Tabs;
1920

@@ -45,7 +46,7 @@ class DashboardView extends React.PureComponent<PropsWithRouter, State> {
4546

4647
const validTabKeys = this.getValidTabKeys();
4748
const { initialTabKey } = this.props;
48-
const lastUsedTabKey = localStorage.getItem("lastUsedDashboardTab");
49+
const lastUsedTabKey = UserLocalStorage.getItem("lastUsedDashboardTab");
4950
const defaultTabKey = this.props.isAdminView ? "tasks" : "datasets";
5051

5152
// Flow doesn't allow validTabKeys[key] where key may be null, so check that first
@@ -132,7 +133,7 @@ class DashboardView extends React.PureComponent<PropsWithRouter, State> {
132133
const tabKeyToURLMap = _.invert(urlTokenToTabKeyMap);
133134
const url = tabKeyToURLMap[activeTabKey];
134135
if (url) {
135-
localStorage.setItem("lastUsedDashboardTab", activeTabKey);
136+
UserLocalStorage.setItem("lastUsedDashboardTab", activeTabKey);
136137
if (!this.props.isAdminView) {
137138
this.props.history.push(`/dashboard/${url}`);
138139
}

frontend/javascripts/dashboard/dataset_view.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Persistence from "libs/persistence";
1414
import SampleDatasetsModal from "dashboard/dataset/sample_datasets_modal";
1515
import * as Utils from "libs/utils";
1616
import renderIndependently from "libs/render_independently";
17+
import UserLocalStorage from "libs/user_local_storage";
1718

1819
const { Search, Group: InputGroup } = Input;
1920

@@ -46,13 +47,13 @@ const persistence: Persistence<State> = new Persistence(
4647
export const wkDatasetsCacheKey = "wk.datasets";
4748
export const datasetCache = {
4849
set(datasets: APIMaybeUnimportedDataset[]): void {
49-
localStorage.setItem(wkDatasetsCacheKey, JSON.stringify(datasets));
50+
UserLocalStorage.setItem(wkDatasetsCacheKey, JSON.stringify(datasets));
5051
},
5152
get(): APIMaybeUnimportedDataset[] {
52-
return Utils.parseAsMaybe(localStorage.getItem(wkDatasetsCacheKey)).getOrElse([]);
53+
return Utils.parseAsMaybe(UserLocalStorage.getItem(wkDatasetsCacheKey)).getOrElse([]);
5354
},
5455
clear(): void {
55-
localStorage.removeItem(wkDatasetsCacheKey);
56+
UserLocalStorage.removeItem(wkDatasetsCacheKey);
5657
},
5758
};
5859

frontend/javascripts/dashboard/explorative_annotations_view.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import Toast from "libs/toast";
3030
import * as Utils from "libs/utils";
3131
import messages from "messages";
3232
import { trackAction } from "oxalis/model/helpers/analytics";
33+
import UserLocalStorage from "libs/user_local_storage";
3334

3435
const { Column } = Table;
3536
const { Search } = Input;
@@ -99,7 +100,7 @@ class ExplorativeAnnotationsView extends React.PureComponent<Props, State> {
99100

100101
restoreSearchTags() {
101102
// restore the search query tags from the last session
102-
const searchTagString = localStorage.getItem("lastDashboardSearchTags");
103+
const searchTagString = UserLocalStorage.getItem("lastDashboardSearchTags");
103104
if (searchTagString) {
104105
try {
105106
const searchTags = JSON.parse(searchTagString);
@@ -297,7 +298,7 @@ class ExplorativeAnnotationsView extends React.PureComponent<Props, State> {
297298
if (!this.state.tags.includes(tag)) {
298299
this.setState(prevState => {
299300
const newTags = update(prevState.tags, { $push: [tag] });
300-
localStorage.setItem("lastDashboardSearchTags", JSON.stringify(newTags));
301+
UserLocalStorage.setItem("lastDashboardSearchTags", JSON.stringify(newTags));
301302
return { tags: newTags };
302303
});
303304
}
@@ -306,7 +307,7 @@ class ExplorativeAnnotationsView extends React.PureComponent<Props, State> {
306307
removeTagFromSearch = (tag: string): void => {
307308
this.setState(prevState => {
308309
const newTags = prevState.tags.filter(t => t !== tag);
309-
localStorage.setItem("lastDashboardSearchTags", JSON.stringify(newTags));
310+
UserLocalStorage.setItem("lastDashboardSearchTags", JSON.stringify(newTags));
310311
return { tags: newTags };
311312
});
312313
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// @flow
2+
3+
import Store from "oxalis/store";
4+
5+
function prefixKey(key) {
6+
const { activeUser } = Store.getState();
7+
const prefix = !activeUser ? "Anonymous" : activeUser.email;
8+
return `${prefix}-${key}`;
9+
}
10+
11+
const UserLocalStorage = {
12+
getItem(key: string): ?string {
13+
return localStorage.getItem(prefixKey(key));
14+
},
15+
16+
setItem(key: string, value: string): void {
17+
return localStorage.setItem(prefixKey(key), value);
18+
},
19+
20+
removeItem(key: string): void {
21+
return localStorage.removeItem(prefixKey(key));
22+
},
23+
24+
clear(): void {
25+
localStorage.clear();
26+
},
27+
};
28+
29+
export default UserLocalStorage;

frontend/javascripts/oxalis/view/action-bar/add_new_layout_modal.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,18 @@ class AddNewLayoutModal extends React.PureComponent<Props, State> {
1818
value: "",
1919
};
2020

21+
onConfirm = () => {
22+
const value = this.state.value;
23+
this.setState({ value: "" });
24+
this.props.addLayout(value);
25+
};
26+
2127
render() {
2228
return (
2329
<Modal
2430
title="Add a new layout"
2531
visible={this.props.visible}
26-
onOk={() => {
27-
const value = this.state.value;
28-
this.setState({ value: "" });
29-
this.props.addLayout(value);
30-
}}
32+
onOk={this.onConfirm}
3133
onCancel={this.props.onCancel}
3234
>
3335
<Input
@@ -36,6 +38,8 @@ class AddNewLayoutModal extends React.PureComponent<Props, State> {
3638
onChange={evt => {
3739
this.setState({ value: evt.target.value });
3840
}}
41+
autoFocus
42+
onPressEnter={this.onConfirm}
3943
/>
4044
</Modal>
4145
);

frontend/javascripts/oxalis/view/layouting/layout_persistence.js

+16-5
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import NanoEvents from "nanoevents";
33
import _ from "lodash";
44

55
import { getIsInIframe } from "libs/utils";
6+
import { listenToStoreProperty } from "oxalis/model/helpers/listener_helpers";
67
import { setStoredLayoutsAction } from "oxalis/model/actions/ui_actions";
78
import Store from "oxalis/store";
89
import Toast from "libs/toast";
10+
import UserLocalStorage from "libs/user_local_storage";
911

1012
import getDefaultLayouts, {
1113
currentLayoutVersion,
@@ -25,12 +27,12 @@ const localStorageKeys = {
2527
};
2628

2729
function readStoredLayoutConfigs() {
28-
const storedLayoutVersion = localStorage.getItem(localStorageKeys.currentLayoutVersion);
30+
const storedLayoutVersion = UserLocalStorage.getItem(localStorageKeys.currentLayoutVersion);
2931
const defaultLayoutConfig = getCurrentDefaultLayoutConfig();
3032
if (getIsInIframe() || !storedLayoutVersion || disableLayoutPersistance) {
3133
return defaultLayoutConfig;
3234
}
33-
const layoutString = localStorage.getItem(localStorageKeys.goldenWkLayouts);
35+
const layoutString = UserLocalStorage.getItem(localStorageKeys.goldenWkLayouts);
3436
if (!layoutString) {
3537
return defaultLayoutConfig;
3638
}
@@ -80,16 +82,25 @@ function readStoredLayoutConfigs() {
8082
return defaultLayoutConfig;
8183
}
8284

83-
Store.dispatch(setStoredLayoutsAction(readStoredLayoutConfigs()));
85+
listenToStoreProperty(
86+
storeState => storeState.activeUser,
87+
() => {
88+
Store.dispatch(setStoredLayoutsAction(readStoredLayoutConfigs()));
89+
},
90+
true,
91+
);
8492

8593
function persistLayoutConfigs() {
8694
if (getIsInIframe()) {
8795
// Don't persist layout in iframe
8896
return;
8997
}
9098
const { storedLayouts } = Store.getState().uiInformation;
91-
localStorage.setItem(localStorageKeys.goldenWkLayouts, JSON.stringify(storedLayouts));
92-
localStorage.setItem(localStorageKeys.currentLayoutVersion, JSON.stringify(currentLayoutVersion));
99+
UserLocalStorage.setItem(localStorageKeys.goldenWkLayouts, JSON.stringify(storedLayouts));
100+
UserLocalStorage.setItem(
101+
localStorageKeys.currentLayoutVersion,
102+
JSON.stringify(currentLayoutVersion),
103+
);
93104
}
94105

95106
layoutEmitter.on("resetLayout", (layoutKey: LayoutKeys, activeLayout: string) => {

frontend/javascripts/oxalis/view/layouting/tracing_layout_view.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class TracingLayoutView extends React.PureComponent<Props, State> {
9595
) {
9696
lastActiveLayout = props.storedLayouts.LastActiveLayouts[layoutType];
9797
} else {
98-
// added as a valide fallback when there are no stored last active layouts
98+
// added as a fallback when there are no stored last active layouts
9999
const firstStoredLayout = Object.keys(props.storedLayouts[layoutType])[0];
100100
lastActiveLayout = firstStoredLayout;
101101
}

0 commit comments

Comments
 (0)