Skip to content

Commit

Permalink
fix: disable all relevant context menu buttons when readOnly (see #411)
Browse files Browse the repository at this point in the history
  • Loading branch information
josdejong committed Mar 8, 2024
1 parent 4b3af48 commit c66ee09
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 47 deletions.
3 changes: 3 additions & 0 deletions src/lib/components/modes/tablemode/TableMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -926,14 +926,17 @@
const defaultItems: ContextMenuItem[] = createTableContextMenuItems({
json,
documentState,
readOnly,
parser,
onEditValue: handleEditValue,
onEditRow: handleEditRow,
onToggleEnforceString: handleToggleEnforceString,
onCut: handleCut,
onCopy: handleCopy,
onPaste: handlePasteFromMenu,
onRemove: handleRemove,
onDuplicateRow: handleDuplicateRow,
onInsertBeforeRow: handleInsertBeforeRow,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { getEnforceString } from '$lib/logic/documentState'
export default function ({
json,
documentState,
readOnly,
parser,
onEditValue,
onEditRow,
Expand All @@ -34,6 +35,7 @@ export default function ({
}: {
json: unknown | undefined
documentState: DocumentState
readOnly: boolean
parser: JSONParser
onEditValue: () => void
onEditRow: () => void
Expand All @@ -58,9 +60,11 @@ export default function ({
hasJson &&
(isMultiSelection(selection) || isKeySelection(selection) || isValueSelection(selection))

const canEditValue = hasJson && selection != null && singleItemSelected(selection)
const canEditValue = !readOnly && hasJson && selection != null && singleItemSelected(selection)
const canEnforceString = canEditValue && !isObjectOrArray(focusValue)

const canCut = !readOnly && hasSelectionContents

const enforceString =
selection != null && focusValue !== undefined
? getEnforceString(
Expand Down Expand Up @@ -118,7 +122,7 @@ export default function ({
icon: faCut,
text: 'Cut',
title: 'Cut selected contents, formatted with indentation (Ctrl+X)',
disabled: !hasSelectionContents
disabled: !canCut
},
width: '10em',
items: [
Expand All @@ -128,15 +132,15 @@ export default function ({
text: 'Cut formatted',
title: 'Cut selected contents, formatted with indentation (Ctrl+X)',
onClick: () => onCut(true),
disabled: !hasSelectionContents
disabled: readOnly || !hasSelectionContents
},
{
type: 'button',
icon: faCut,
text: 'Cut compacted',
title: 'Cut selected contents, without indentation (Ctrl+Shift+X)',
onClick: () => onCut(false),
disabled: !hasSelectionContents
disabled: readOnly || !hasSelectionContents
}
]
},
Expand Down Expand Up @@ -176,15 +180,15 @@ export default function ({
icon: faPaste,
text: 'Paste',
title: 'Paste clipboard contents (Ctrl+V)',
disabled: !hasSelection
disabled: readOnly || !hasSelection
},
{
type: 'button',
onClick: () => onRemove(),
icon: faTrashCan,
text: 'Remove',
title: 'Remove selected contents (Delete)',
disabled: !hasSelectionContents
disabled: readOnly || !hasSelectionContents
}
]
},
Expand All @@ -198,39 +202,39 @@ export default function ({
icon: faPen,
text: 'Edit row',
title: 'Edit the current row',
disabled: !hasSelectionContents
disabled: readOnly || !hasSelectionContents
},
{
type: 'button',
onClick: () => onDuplicateRow(),
icon: faClone,
text: 'Duplicate row',
title: 'Duplicate the current row',
disabled: !hasSelection
disabled: readOnly || !hasSelection
},
{
type: 'button',
onClick: () => onInsertBeforeRow(),
icon: faPlus,
text: 'Insert before',
title: 'Insert a row before the current row',
disabled: !hasSelection
disabled: readOnly || !hasSelection
},
{
type: 'button',
onClick: () => onInsertAfterRow(),
icon: faPlus,
text: 'Insert after',
title: 'Insert a row after the current row',
disabled: !hasSelection
disabled: readOnly || !hasSelection
},
{
type: 'button',
onClick: () => onRemoveRow(),
icon: faTrashCan,
text: 'Remove row',
title: 'Remove current row',
disabled: !hasSelection
disabled: readOnly || !hasSelection
}
]
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/components/modes/treemode/TreeMode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -1811,6 +1811,7 @@
const defaultItems: ContextMenuItem[] = createTreeContextMenuItems({
json,
documentState,
readOnly,
parser,
onEditKey: handleEditKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
isValueSelection,
singleItemSelected
} from '$lib/logic/selection'
import type { DocumentState, InsertType, JSONParser } from 'svelte-jsoneditor'
import type { ConvertType, DocumentState, InsertType, JSONParser } from '$lib/types'
import { initial, isEmpty } from 'lodash-es'
import { compileJSONPointer, getIn } from 'immutable-json-patch'
import { isObjectOrArray, isObject } from '$lib/utils/typeUtils'
Expand All @@ -33,8 +33,8 @@ import type { ContextMenuItem } from 'svelte-jsoneditor'
export default function ({
json,
documentState,
readOnly,
parser,

onEditKey,
onEditValue,
onToggleEnforceString,
Expand All @@ -53,8 +53,8 @@ export default function ({
}: {
json: unknown
documentState: DocumentState
readOnly: boolean
parser: JSONParser

onEditKey: () => void
onEditValue: () => void
onToggleEnforceString: () => void
Expand All @@ -66,7 +66,7 @@ export default function ({
onExtract: () => void
onInsertBefore: () => void
onInsert: (type: InsertType) => void
onConvert: (type: InsertType) => void
onConvert: (type: ConvertType) => void
onInsertAfter: () => void
onSort: () => void
onTransform: () => void
Expand All @@ -87,36 +87,38 @@ export default function ({
hasJson &&
(isMultiSelection(selection) || isKeySelection(selection) || isValueSelection(selection))

const canDuplicate = hasJson && hasSelectionContents && !rootSelected // must not be root
const canExtract =
hasJson &&
selection != null &&
(isMultiSelection(selection) || isValueSelection(selection)) &&
!rootSelected // must not be root

const canEditKey =
!readOnly &&
hasJson &&
selection != null &&
singleItemSelected(selection) &&
!rootSelected &&
!Array.isArray(getIn(json, initial(getFocusPath(selection))))

const canEditValue = hasJson && selection != null && singleItemSelected(selection)
const canEditValue = !readOnly && hasJson && selection != null && singleItemSelected(selection)
const canEnforceString = canEditValue && !isObjectOrArray(focusValue)

const canCut = !readOnly && hasSelectionContents
const canCopy = hasSelectionContents
const canPaste = !readOnly && hasSelection
const canDuplicate = !readOnly && hasJson && hasSelectionContents && !rootSelected // must not be root
const canExtract =
!readOnly &&
hasJson &&
selection != null &&
(isMultiSelection(selection) || isValueSelection(selection)) &&
!rootSelected // must not be root

const convertMode = hasSelectionContents
const insertOrConvertText = convertMode ? 'Convert to:' : 'Insert:'

const canInsertOrConvertStructure = convertMode ? false : hasSelection
const canInsertOrConvertObject = convertMode
? canConvert(selection) && !isObject(focusValue)
: hasSelection
const canInsertOrConvertArray = convertMode
? canConvert(selection) && !Array.isArray(focusValue)
: hasSelection
const canInsertOrConvertValue = convertMode
? canConvert(selection) && isObjectOrArray(focusValue)
: hasSelection
const canInsertOrConvertStructure = readOnly || convertMode ? false : hasSelection
const canInsertOrConvertObject =
!readOnly && (convertMode ? canConvert(selection) && !isObject(focusValue) : hasSelection)
const canInsertOrConvertArray =
!readOnly && (convertMode ? canConvert(selection) && !Array.isArray(focusValue) : hasSelection)
const canInsertOrConvertValue =
!readOnly && (convertMode ? canConvert(selection) && isObjectOrArray(focusValue) : hasSelection)

const enforceString =
selection != null && focusValue
Expand All @@ -130,7 +132,9 @@ export default function ({

function handleInsertOrConvert(type: InsertType) {
if (hasSelectionContents) {
onConvert(type)
if (type !== 'structure') {
onConvert(type)
}
} else {
onInsert(type)
}
Expand Down Expand Up @@ -192,7 +196,7 @@ export default function ({
icon: faCut,
text: 'Cut',
title: 'Cut selected contents, formatted with indentation (Ctrl+X)',
disabled: !hasSelectionContents
disabled: !canCut
},
width: '10em',
items: [
Expand All @@ -202,15 +206,15 @@ export default function ({
text: 'Cut formatted',
title: 'Cut selected contents, formatted with indentation (Ctrl+X)',
onClick: () => onCut(true),
disabled: !hasSelectionContents
disabled: !canCut
},
{
type: 'button',
icon: faCut,
text: 'Cut compacted',
title: 'Cut selected contents, without indentation (Ctrl+Shift+X)',
onClick: () => onCut(false),
disabled: !hasSelectionContents
disabled: !canCut
}
]
},
Expand All @@ -222,7 +226,7 @@ export default function ({
icon: faCopy,
text: 'Copy',
title: 'Copy selected contents, formatted with indentation (Ctrl+C)',
disabled: !hasSelectionContents
disabled: !canCopy
},
width: '12em',
items: [
Expand All @@ -232,15 +236,15 @@ export default function ({
text: 'Copy formatted',
title: 'Copy selected contents, formatted with indentation (Ctrl+C)',
onClick: () => onCopy(true),
disabled: !hasSelectionContents
disabled: !canCopy
},
{
type: 'button',
icon: faCopy,
text: 'Copy compacted',
title: 'Copy selected contents, without indentation (Ctrl+Shift+C)',
onClick: () => onCopy(false),
disabled: !hasSelectionContents
disabled: !canCopy
}
]
},
Expand All @@ -250,7 +254,7 @@ export default function ({
icon: faPaste,
text: 'Paste',
title: 'Paste clipboard contents (Ctrl+V)',
disabled: !hasSelection
disabled: !canPaste
}
]
},
Expand Down Expand Up @@ -283,23 +287,23 @@ export default function ({
icon: faSortAmountDownAlt,
text: 'Sort',
title: 'Sort array or object contents',
disabled: !hasSelectionContents
disabled: readOnly || !hasSelectionContents
},
{
type: 'button',
onClick: () => onTransform(),
icon: faFilter,
text: 'Transform',
title: 'Transform array or object contents (filter, sort, project)',
disabled: !hasSelectionContents
disabled: readOnly || !hasSelectionContents
},
{
type: 'button',
onClick: () => onRemove(),
icon: faTrashCan,
text: 'Remove',
title: 'Remove selected contents (Delete)',
disabled: !hasSelectionContents
disabled: readOnly || !hasSelectionContents
}
]
},
Expand Down Expand Up @@ -355,15 +359,15 @@ export default function ({
icon: faCaretSquareUp,
text: 'Insert before',
title: 'Select area before current entry to insert or paste contents',
disabled: !hasSelectionContents || rootSelected
disabled: readOnly || !hasSelectionContents || rootSelected
},
{
type: 'button',
onClick: () => onInsertAfter(),
icon: faCaretSquareDown,
text: 'Insert after',
title: 'Select area after current entry to insert or paste contents',
disabled: !hasSelectionContents || rootSelected
disabled: readOnly || !hasSelectionContents || rootSelected
}
]
}
Expand Down
2 changes: 1 addition & 1 deletion src/routes/development/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@
function onRenderContextMenu(items: ContextMenuItem[], context: RenderMenuContext) {
console.log('onRenderContextMenu', items, context)
return context.readOnly ? false : items // This return is equivalent to onRenderContextMenu is undefined
return items // This return is equivalent to onRenderContextMenu is undefined
}
function openInWindow() {
Expand Down

0 comments on commit c66ee09

Please sign in to comment.