@standardnotes/authenticator 2.3.9 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [2.4.0](https://github.com/standardnotes/plugins/compare/@standardnotes/authenticator@2.3.9...@standardnotes/authenticator@2.4.0) (2023-05-03)
7
+
8
+ ### Features
9
+
10
+ * **authenticator:** add export option for entries ([6704483](https://github.com/standardnotes/plugins/commit/67044839b3bc45e366795ecbfb12c78bdbcc22cb))
11
+
6
12
  ## [2.3.9](https://github.com/standardnotes/plugins/compare/@standardnotes/authenticator@2.3.7...@standardnotes/authenticator@2.3.9) (2022-11-04)
7
13
 
8
14
  **Note:** Version bump only for package @standardnotes/authenticator
@@ -114,7 +114,7 @@ export default class AuthEntry extends React.Component {
114
114
 
115
115
  render() {
116
116
  const { service, account, notes, password, secret } = this.props.entry
117
- const { id, onEdit, onRemove, canEdit, style, innerRef, ...divProps } = this.props
117
+ const { id, onEdit, onRemove, onExport, canEdit, style, innerRef, ...divProps } = this.props
118
118
  const { token, timeLeft, entryStyle } = this.state
119
119
 
120
120
  delete divProps.onCopyValue
@@ -178,6 +178,7 @@ export default class AuthEntry extends React.Component {
178
178
  <AuthMenu
179
179
  onEdit={onEdit.bind(this, id)}
180
180
  onRemove={onRemove.bind(this, id)}
181
+ onExport={onExport.bind(this, id)}
181
182
  buttonColor={entryStyle.color}
182
183
  />
183
184
  </div>
@@ -193,6 +194,7 @@ AuthEntry.propTypes = {
193
194
  entry: PropTypes.object.isRequired,
194
195
  onEdit: PropTypes.func.isRequired,
195
196
  onRemove: PropTypes.func.isRequired,
197
+ onExport: PropTypes.func.isRequired,
196
198
  onEntryChange: PropTypes.func,
197
199
  onCopyValue: PropTypes.func.isRequired,
198
200
  canEdit: PropTypes.bool.isRequired,
@@ -26,6 +26,11 @@ export default class AuthMenu extends React.Component {
26
26
  this.props.onRemove()
27
27
  }
28
28
 
29
+ onExport = () => {
30
+ this.onToggle()
31
+ this.props.onExport()
32
+ }
33
+
29
34
  render() {
30
35
  const { buttonColor } = this.props
31
36
 
@@ -49,6 +54,9 @@ export default class AuthMenu extends React.Component {
49
54
  <div className="sk-menu-panel-row" onClick={this.onRemove}>
50
55
  <div className="sk-label">Remove</div>
51
56
  </div>
57
+ <div className="sk-menu-panel-row" onClick={this.onExport}>
58
+ <div className="sk-label">Export</div>
59
+ </div>
52
60
  </div>
53
61
  ))}
54
62
  </div>
@@ -59,5 +67,6 @@ export default class AuthMenu extends React.Component {
59
67
  AuthMenu.propTypes = {
60
68
  onEdit: PropTypes.func.isRequired,
61
69
  onRemove: PropTypes.func.isRequired,
70
+ onExport: PropTypes.func.isRequired,
62
71
  buttonColor: PropTypes.string,
63
72
  }
@@ -1,15 +1,15 @@
1
- import ConfirmDialog from '@Components/ConfirmDialog'
2
- import DataErrorAlert from '@Components/DataErrorAlert'
3
- import EditEntry from '@Components/EditEntry'
4
- import ViewEntries from '@Components/ViewEntries'
5
- import EditorKit from '@standardnotes/editor-kit'
6
- import update from 'immutability-helper'
7
- import React from 'react'
8
- import ReorderIcon from '../assets/svg/reorder-icon.svg'
9
- import CopyNotification from './CopyNotification'
1
+ import ConfirmDialog from "@Components/ConfirmDialog"
2
+ import DataErrorAlert from "@Components/DataErrorAlert"
3
+ import EditEntry from "@Components/EditEntry"
4
+ import ViewEntries from "@Components/ViewEntries"
5
+ import EditorKit from "@standardnotes/editor-kit"
6
+ import update from "immutability-helper"
7
+ import React from "react"
8
+ import ReorderIcon from "../assets/svg/reorder-icon.svg"
9
+ import CopyNotification from "./CopyNotification"
10
10
 
11
11
  const initialState = {
12
- text: '',
12
+ text: "",
13
13
  entries: [],
14
14
  parseError: false,
15
15
  editMode: false,
@@ -18,7 +18,7 @@ const initialState = {
18
18
  confirmReorder: false,
19
19
  displayCopy: false,
20
20
  canEdit: true,
21
- searchValue: '',
21
+ searchValue: "",
22
22
  lastUpdated: 0,
23
23
  }
24
24
 
@@ -84,7 +84,7 @@ export default class Home extends React.Component {
84
84
  }
85
85
 
86
86
  this.editorKit = new EditorKit(delegate, {
87
- mode: 'json',
87
+ mode: "json",
88
88
  })
89
89
  }
90
90
 
@@ -97,12 +97,12 @@ export default class Home extends React.Component {
97
97
  }
98
98
 
99
99
  for (const entry of entries) {
100
- if (!('service' in entry)) {
101
- throw Error('Service key is missing for an entry.')
100
+ if (!("service" in entry)) {
101
+ throw Error("Service key is missing for an entry.")
102
102
  }
103
103
 
104
- if (!('secret' in entry) && !('password' in entry)) {
105
- throw Error('An entry does not have a secret key or a password.')
104
+ if (!("secret" in entry) && !("password" in entry)) {
105
+ throw Error("An entry does not have a secret key or a password.")
106
106
  }
107
107
  }
108
108
 
@@ -180,6 +180,24 @@ export default class Home extends React.Component {
180
180
  }))
181
181
  }
182
182
 
183
+ onExport = (id) => {
184
+ const entry = this.state.entries[id]
185
+ const blob = new Blob([JSON.stringify(entry, null, 2)], {
186
+ type: "application/json",
187
+ })
188
+
189
+ const link = document.createElement("a")
190
+ link.setAttribute("download", `${entry.service}-${entry.account}.json`)
191
+
192
+ const objUrl = window.URL.createObjectURL(blob)
193
+ link.href = objUrl
194
+ document.body.appendChild(link)
195
+ link.click()
196
+
197
+ link.remove()
198
+ window.URL.revokeObjectURL(objUrl)
199
+ }
200
+
183
201
  onCancel = () => {
184
202
  this.setState({
185
203
  confirmRemove: false,
@@ -252,7 +270,7 @@ export default class Home extends React.Component {
252
270
 
253
271
  clearSearchValue = () => {
254
272
  this.setState({
255
- searchValue: '',
273
+ searchValue: "",
256
274
  })
257
275
  }
258
276
 
@@ -297,7 +315,11 @@ export default class Home extends React.Component {
297
315
  <CopyNotification isVisible={displayCopy} />
298
316
  {!editMode && (
299
317
  <div id="header">
300
- <div className={`sk-horizontal-group left align-items-center ${!canEdit && 'full-width'}`}>
318
+ <div
319
+ className={`sk-horizontal-group left align-items-center ${
320
+ !canEdit && "full-width"
321
+ }`}
322
+ >
301
323
  <input
302
324
  name="search"
303
325
  className="sk-input contrast search-bar"
@@ -308,7 +330,10 @@ export default class Home extends React.Component {
308
330
  type="text"
309
331
  />
310
332
  {searchValue && (
311
- <div onClick={this.clearSearchValue} className="sk-button danger">
333
+ <div
334
+ onClick={this.clearSearchValue}
335
+ className="sk-button danger"
336
+ >
312
337
  <div className="sk-label">✕</div>
313
338
  </div>
314
339
  )}
@@ -316,7 +341,10 @@ export default class Home extends React.Component {
316
341
  {canEdit && (
317
342
  <div className="sk-horizontal-group right">
318
343
  <div className="sk-button-group stretch">
319
- <div onClick={this.onReorderEntries} className="sk-button info">
344
+ <div
345
+ onClick={this.onReorderEntries}
346
+ className="sk-button info"
347
+ >
320
348
  <ReorderIcon />
321
349
  </div>
322
350
  <div onClick={this.onAddNew} className="sk-button info">
@@ -329,13 +357,19 @@ export default class Home extends React.Component {
329
357
  )}
330
358
  <div id="content">
331
359
  {editMode ? (
332
- <EditEntry id={editEntry.id} entry={editEntry.entry} onSave={this.onSave} onCancel={this.onCancel} />
360
+ <EditEntry
361
+ id={editEntry.id}
362
+ entry={editEntry.entry}
363
+ onSave={this.onSave}
364
+ onCancel={this.onCancel}
365
+ />
333
366
  ) : (
334
367
  <ViewEntries
335
368
  entries={entries}
336
369
  searchValue={searchValue}
337
370
  onEdit={this.onEdit}
338
371
  onRemove={this.onRemove}
372
+ onExport={this.onExport}
339
373
  onCopyValue={this.onCopyValue}
340
374
  canEdit={canEdit}
341
375
  lastUpdated={lastUpdated}
@@ -352,7 +386,7 @@ export default class Home extends React.Component {
352
386
  )}
353
387
  {confirmReorder && (
354
388
  <ConfirmDialog
355
- title={'Auto-sort entries'}
389
+ title={"Auto-sort entries"}
356
390
  message="Are you sure you want to auto-sort all entries alphabetically based on service name?"
357
391
  onConfirm={this.reorderEntries}
358
392
  onCancel={this.onCancel}
@@ -1,6 +1,6 @@
1
- import AuthEntry from '@Components/AuthEntry'
2
- import PropTypes from 'prop-types'
3
- import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd'
1
+ import AuthEntry from "@Components/AuthEntry"
2
+ import PropTypes from "prop-types"
3
+ import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd"
4
4
 
5
5
  const reorderEntries = (list, startIndex, endIndex) => {
6
6
  const result = Array.from(list)
@@ -10,14 +10,28 @@ const reorderEntries = (list, startIndex, endIndex) => {
10
10
  return result
11
11
  }
12
12
 
13
- const ViewEntries = ({ entries, onEdit, onRemove, onCopyValue, canEdit, updateEntries, searchValue, lastUpdated }) => {
13
+ const ViewEntries = ({
14
+ entries,
15
+ onEdit,
16
+ onRemove,
17
+ onExport,
18
+ onCopyValue,
19
+ canEdit,
20
+ updateEntries,
21
+ searchValue,
22
+ lastUpdated,
23
+ }) => {
14
24
  const onDragEnd = (result) => {
15
25
  const droppedOutsideList = !result.destination
16
26
  if (droppedOutsideList) {
17
27
  return
18
28
  }
19
29
 
20
- const orderedEntries = reorderEntries(entries, result.source.index, result.destination.index)
30
+ const orderedEntries = reorderEntries(
31
+ entries,
32
+ result.source.index,
33
+ result.destination.index
34
+ )
21
35
 
22
36
  updateEntries(orderedEntries)
23
37
  }
@@ -26,12 +40,17 @@ const ViewEntries = ({ entries, onEdit, onRemove, onCopyValue, canEdit, updateEn
26
40
  <DragDropContext onDragEnd={onDragEnd}>
27
41
  <Droppable droppableId="droppable" isDropDisabled={!canEdit}>
28
42
  {(provided) => (
29
- <div {...provided.droppableProps} ref={provided.innerRef} className="auth-list">
43
+ <div
44
+ {...provided.droppableProps}
45
+ ref={provided.innerRef}
46
+ className="auth-list"
47
+ >
30
48
  {entries.map((entry, index) => {
31
49
  /**
32
50
  * Filtering entries by account, service and notes properties.
33
51
  */
34
- const combinedString = `${entry.account}${entry.service}${entry.notes}`.toLowerCase()
52
+ const combinedString =
53
+ `${entry.account}${entry.service}${entry.notes}`.toLowerCase()
35
54
  if (searchValue && !combinedString.includes(searchValue)) {
36
55
  return
37
56
  }
@@ -52,6 +71,7 @@ const ViewEntries = ({ entries, onEdit, onRemove, onCopyValue, canEdit, updateEn
52
71
  entry={entry}
53
72
  onEdit={onEdit}
54
73
  onRemove={onRemove}
74
+ onExport={onExport}
55
75
  onCopyValue={onCopyValue}
56
76
  canEdit={canEdit}
57
77
  lastUpdated={lastUpdated}
@@ -72,6 +92,7 @@ ViewEntries.propTypes = {
72
92
  entries: PropTypes.arrayOf(PropTypes.object),
73
93
  onEdit: PropTypes.func.isRequired,
74
94
  onRemove: PropTypes.func.isRequired,
95
+ onExport: PropTypes.func.isRequired,
75
96
  onCopyValue: PropTypes.func.isRequired,
76
97
  canEdit: PropTypes.bool.isRequired,
77
98
  lastUpdated: PropTypes.number.isRequired,