Skip to content
This repository was archived by the owner on Jul 30, 2025. It is now read-only.

Commit f7f6918

Browse files
myan9starpit
authored andcommitted
feat(plugins/plugin-client-common): allow users to reorder blocks by MoveUp and MoveDown buttons
Fixes #5589
1 parent 55ce899 commit f7f6918

File tree

11 files changed

+178
-13
lines changed

11 files changed

+178
-13
lines changed

packages/test/src/api/selectors.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ export const PROMPT_BLOCK_FINAL = `${PROMPT_BLOCK}:nth-last-child(1)`
137137
export const OVERFLOW_MENU = '.kui--repl-block-right-element.kui--toolbar-button-with-icon'
138138
export const PROMPT_BLOCK_MENU = (N: number) => `${PROMPT_BLOCK_N(N)} ${OVERFLOW_MENU}`
139139
export const BLOCK_REMOVE_BUTTON = `.kui--block-action [icon="WindowClose"]`
140+
export const BLOCK_UP_BUTTON = `.kui--block-action [icon="MoveUp"]`
141+
export const BLOCK_UP_BUTTON_N = (N: number) => `${PROMPT_BLOCK_N(N)} .kui--block-action [icon="MoveUp"]`
142+
export const BLOCK_DOWN_BUTTON = `.kui--block-action [icon="MoveDown"]`
143+
export const BLOCK_DOWN_BUTTON_N = (N: number) => `${PROMPT_BLOCK_N(N)} .kui--block-action [icon="MoveDown"]`
140144
export const COMMAND_COPY_BUTTON = `.kui--block-action [icon="Copy"]`
141145
export const COMMAND_COPY_DONE_BUTTON = `.kui--block-action [icon="Checkmark"]`
142146
export const COMMAND_RERUN_BUTTON = `.kui--block-action [icon="Retry"]`

plugins/plugin-client-common/src/components/Views/Terminal/Block/Actions.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,34 @@ export default class Actions extends React.PureComponent<Props> {
8787
)
8888
}
8989

90+
private upwardAction() {
91+
return (
92+
this.props.hasBlockBefore &&
93+
this.props.willMoveUpward && (
94+
<Action icon="MoveUp" onClick={() => this.props.willMoveUpward()} title="Move this block up" />
95+
)
96+
)
97+
}
98+
99+
private downwardAction() {
100+
return (
101+
this.props.hasBlockAfter &&
102+
this.props.willMoveDownward && (
103+
<Action icon="MoveDown" onClick={() => this.props.willMoveDownward()} title="Move this block down" />
104+
)
105+
)
106+
}
107+
90108
public render() {
91109
return (
92110
<React.Fragment>
93-
{this.copyAction()}
94-
{this.rerunAction()}
95-
{this.screenshotAction()}
111+
<div className="kui-block-actions-others">
112+
{this.copyAction()}
113+
{this.rerunAction()}
114+
{this.screenshotAction()}
115+
</div>
116+
{this.upwardAction()}
117+
{this.downwardAction()}
96118
{this.removeAction()}
97119
</React.Fragment>
98120
)

plugins/plugin-client-common/src/components/Views/Terminal/Block/Input.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import {
3737
hasUUID,
3838
hasValue
3939
} from './BlockModel'
40-
import { BlockViewTraits } from './'
40+
import { BlockViewTraits, BlockOperationTraits } from './'
4141

4242
import Tag from '../../../spi/Tag'
4343
import ExpandableSection from '../../../spi/ExpandableSection'
@@ -46,7 +46,7 @@ const SimpleEditor = React.lazy(() => import('../../../Content/Editor/SimpleEdit
4646

4747
const strings = i18n('plugin-client-common')
4848

49-
export interface InputOptions {
49+
export interface InputOptions extends BlockOperationTraits {
5050
/** Optional: placeholder value for prompt */
5151
promptPlaceholder?: string // was: from '@kui-shell/client/config.d/style.json'
5252

@@ -80,9 +80,6 @@ export interface InputOptions {
8080
/** Optional: onFocus handler */
8181
onInputFocus?: (event: React.FocusEvent<HTMLInputElement>) => void
8282

83-
/** Remove the enclosing block */
84-
willRemove?: () => void
85-
8683
/** insert an active block before this block */
8784
willInsertBlock?: () => void
8885

plugins/plugin-client-common/src/components/Views/Terminal/Block/Output.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {
3232
Streamable
3333
} from '@kui-shell/core'
3434

35-
import { BlockViewTraits } from './'
35+
import { BlockViewTraits, BlockOperationTraits } from './'
3636

3737
import {
3838
BlockModel,
@@ -68,12 +68,10 @@ type Props = {
6868
/** Block ordinal to be displayed to user */
6969
displayedIdx?: number
7070

71-
/** Remove the enclosing block */
72-
willRemove?: () => void
73-
7471
model: ProcessingBlock | FinishedBlock
7572
onRender: () => void
76-
} & BlockViewTraits
73+
} & BlockViewTraits &
74+
BlockOperationTraits
7775

7876
interface State {
7977
alreadyListen: boolean

plugins/plugin-client-common/src/components/Views/Terminal/Block/index.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ export type BlockViewTraits = {
4242
willFocusBlock?: (evt: React.SyntheticEvent) => void
4343
}
4444

45+
export interface BlockOperationTraits {
46+
/** Remove the enclosing block */
47+
willRemove?: () => void
48+
49+
/** is there any block before the give block? */
50+
hasBlockBefore?: boolean
51+
52+
/** is there any block after the give block? */
53+
hasBlockAfter?: boolean
54+
55+
/** move a given block upward */
56+
willMoveUpward?: () => void
57+
58+
/** move a given block downward */
59+
willMoveDownward?: () => void
60+
}
61+
4562
type Props = InputOptions & {
4663
/** block ordinal index */
4764
idx: number
@@ -107,6 +124,10 @@ export default class Block extends React.PureComponent<Props, State> {
107124
model={this.props.model}
108125
isFocused={this.props.isFocused}
109126
willRemove={this.props.willRemove}
127+
hasBlockAfter={this.props.hasBlockAfter}
128+
hasBlockBefore={this.props.hasBlockBefore}
129+
willMoveUpward={this.props.willMoveUpward}
130+
willMoveDownward={this.props.willMoveDownward}
110131
onRender={this.props.onOutputRender && (() => this.props.onOutputRender(this.props.idx))}
111132
prefersTerminalPresentation={this.props.prefersTerminalPresentation}
112133
isPartOfMiniSplit={this.props.isPartOfMiniSplit}

plugins/plugin-client-common/src/components/Views/Terminal/ScrollableTerminal.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,42 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
248248
return []
249249
}
250250

251+
/** is there any block before the given block index */
252+
private hasBlockBefore(idx: number): boolean {
253+
return idx > 0
254+
}
255+
256+
/** is there any block (except the active input block) after the given block index */
257+
private hasBlockAfter(blocks: BlockModel[], idx: number): boolean {
258+
return idx < blocks.length - 2
259+
}
260+
261+
/** move the given block upward */
262+
private willMoveUpward(sbuuid: string, idx: number) {
263+
this.splice(sbuuid, curState => {
264+
return {
265+
blocks: curState.blocks
266+
.slice(0, idx - 1)
267+
.concat(curState.blocks[idx])
268+
.concat(curState.blocks[idx - 1])
269+
.concat(curState.blocks.slice(idx + 1))
270+
}
271+
})
272+
}
273+
274+
/** move the given block downward */
275+
private willMoveDownward(sbuuid: string, idx: number) {
276+
this.splice(sbuuid, curState => {
277+
return {
278+
blocks: curState.blocks
279+
.slice(0, idx)
280+
.concat(curState.blocks[idx + 1])
281+
.concat(curState.blocks[idx])
282+
.concat(curState.blocks.slice(idx + 2))
283+
}
284+
})
285+
}
286+
251287
private scrollback(
252288
capturedValue?: string,
253289
sbuuid = this.allocateUUIDForScrollback(),
@@ -890,6 +926,10 @@ export default class ScrollableTerminal extends React.PureComponent<Props, State
890926
onOutputRender={this.onOutputRender.bind(this, scrollback)}
891927
willInsertBlock={this.willInsertBlock.bind(this, scrollback.uuid, idx)}
892928
willRemove={this.willRemoveBlock.bind(this, scrollback.uuid, idx)}
929+
hasBlockAfter={this.hasBlockAfter(scrollback.blocks, idx)}
930+
hasBlockBefore={this.hasBlockBefore(idx)}
931+
willMoveUpward={this.willMoveUpward.bind(this, scrollback.uuid, idx)}
932+
willMoveDownward={this.willMoveDownward.bind(this, scrollback.uuid, idx)}
893933
willLoseFocus={() => this.doFocus(scrollback)}
894934
willFocusBlock={evt => this.doFocusBlock(evt, scrollback.uuid, idx)}
895935
isExperimental={hasCommand(_) && _.isExperimental}

plugins/plugin-client-common/src/components/spi/Icons/impl/Carbon.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import {
3333
SettingsAdjust20 as Settings,
3434
TrashCan16 as Trash,
3535
JumpLink16 as Up,
36+
ArrowUp16 as MoveUp,
37+
ArrowDown16 as MoveDown,
3638
Location16 as Location,
3739
VirtualMachine16 as Server,
3840
At16 as At,
@@ -74,6 +76,8 @@ const icons: Record<Exclude<SupportedIcon, 'Up'>, CarbonIconType> = {
7476
Grid,
7577
Info,
7678
List,
79+
MoveUp,
80+
MoveDown,
7781
Location,
7882
Network,
7983
NextPage,

plugins/plugin-client-common/src/components/spi/Icons/impl/PatternFly.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import {
3232
QuestionCircleIcon /* ToolsIcon */ as Settings,
3333
TrashAltIcon as Trash,
3434
LevelUpAltIcon as Up,
35+
ArrowUpIcon as MoveUp,
36+
ArrowDownIcon as MoveDown,
3537
MapMarkerAltIcon as Location,
3638
ServerIcon as Server,
3739
AtIcon as At,
@@ -100,6 +102,10 @@ export default function PatternFly4Icons(props: Props) {
100102
return <List {...props} />
101103
case 'Location':
102104
return <Location {...props} />
105+
case 'MoveUp':
106+
return <MoveUp {...props} />
107+
case 'MoveDown':
108+
return <MoveDown {...props} />
103109
case 'Pause':
104110
return <Pause {...props} />
105111
case 'Play':

plugins/plugin-client-common/src/components/spi/Icons/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export type SupportedIcon =
3636
| 'Info'
3737
| 'List'
3838
| 'Location'
39+
| 'MoveUp'
40+
| 'MoveDown'
3941
| 'Network'
4042
| 'NextPage'
4143
| 'Notification'

plugins/plugin-client-common/web/scss/components/Terminal/Block.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ $action-padding: 3px;
108108
}
109109
}
110110

111+
.kui-block-actions-others {
112+
display: flex;
113+
border-right: 1px solid var(--color-table-border2);
114+
}
115+
111116
.repl-input .kui--block-action:hover {
112117
background-color: var(--color-base04);
113118
}

0 commit comments

Comments
 (0)