Skip to content

Commit

Permalink
Merge pull request #251 from logisky/jh/fix
Browse files Browse the repository at this point in the history
fix: sheet actions and cell input
  • Loading branch information
ImJeremyHe authored Dec 31, 2024
2 parents 9a6df84 + 0ca5c9c commit c6f74da
Show file tree
Hide file tree
Showing 18 changed files with 228 additions and 104 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
21 changes: 20 additions & 1 deletion crates/controller/src/api/test.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::edit_action::{EditPayload, PayloadsAction, SheetRename, WorkbookUpdateType};

use super::Workbook;

#[test]
fn new_workbook() {
let wb = Workbook::default();
let mut wb = Workbook::default();
let ws = wb.get_sheet_by_idx(0).unwrap();

ws.get_cell_position(100, 100).unwrap();
Expand Down Expand Up @@ -30,4 +32,21 @@ fn new_workbook() {
.into_iter()
.fold(0., |p, c| return p + c.width);
assert!(v > 100.);

let result = wb.handle_action(crate::EditAction::Payloads(PayloadsAction {
payloads: vec![EditPayload::SheetRename(SheetRename {
old_name: Some("Sheet1".to_string()),
new_name: "abcd".to_string(),
idx: None,
})],
undoable: true,
}));

match result.status {
crate::edit_action::StatusCode::Ok(workbook_update_type) => {
println!("{:?}", workbook_update_type);
assert!(matches!(workbook_update_type, WorkbookUpdateType::Sheet));
}
crate::edit_action::StatusCode::Err(e) => panic!("{:?}", e),
}
}
33 changes: 31 additions & 2 deletions crates/controller/src/controller/executor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::{HashMap, HashSet};

use logisheets_base::{Addr, CellId, CubeId, RangeId, SheetId};
use logisheets_base::{errors::BasicError, Addr, CellId, CubeId, RangeId, SheetId};

use crate::{
async_func_manager::AsyncFuncManager,
Expand All @@ -11,7 +11,7 @@ use crate::{
},
container::ContainerExecutor,
cube_manager::executors::CubeExecutor,
edit_action::{EditPayload, PayloadsAction},
edit_action::{EditPayload, PayloadsAction, SheetRename},
formula_manager::{FormulaExecutor, Vertex},
navigator::{NavExecutor, Navigator},
range_manager::RangeExecutor,
Expand Down Expand Up @@ -58,6 +58,35 @@ impl<'a> Executor<'a> {

fn execute_payload(self, payload: EditPayload) -> Result<Self, Error> {
let mut result = self;

if let EditPayload::SheetRename(rename) = payload {
let manager = &mut result.status.sheet_id_manager;
let SheetRename {
old_name,
idx,
new_name,
} = rename;
if let Some(old_name) = old_name {
manager.rename(&old_name, new_name);
} else {
if let Some(idx) = idx {
let id = result
.status
.sheet_pos_manager
.get_sheet_id(idx)
.ok_or(Error::Basic(BasicError::SheetIdxExceed(idx)))?;
let old_name = manager
.get_string(&id)
.ok_or(Error::Basic(BasicError::SheetIdNotFound(id)))?;
manager.rename(&old_name, new_name);
} else {
return Err(Error::PayloadError("".to_string()));
}
}
result.sheet_updated = true;
return Ok(result);
}

let (sheet_pos_manager, sheet_updated) = result.execute_sheet_pos(&payload)?;
result.status.sheet_pos_manager = sheet_pos_manager;

Expand Down
6 changes: 6 additions & 0 deletions crates/controller/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub enum Error {
Parse(#[from] ParseError),
#[error("unavailable sheet idx: {0}")]
UnavailableSheetIdx(usize),
#[error("invalid payload: {0}")]
PayloadError(String),
}

// A cleaner way for users to know about the error and a more convenient
Expand Down Expand Up @@ -61,6 +63,10 @@ impl From<Error> for ErrorMessage {
let msg = e.to_string();
ErrorMessage { msg, ty: 5 }
}
Error::PayloadError(e) => {
let msg = e;
ErrorMessage { msg, ty: 6 }
}
}
}
}
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
"react-modal": "^3.16.3",
"react-scripts": "5.0.0",
"react-select": "^5.4.0",
"react-toastify": "^11.0.2",
"react-transition-group": "^4.4.2",
"react-use-websocket": "^2.9.1",
"rxjs": "^7.5.2",
"rxjs": "^7.8.1",
"source-map-loader": "^3.0.1",
"ssf": "^0.11.2",
"style-loader": "^3.3.1",
Expand Down Expand Up @@ -98,7 +98,6 @@
"jest": "^27.5.1",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
"react-toastify": "^9.0.5",
"reflect-metadata": "^0.1.13",
"sass": "^1.83.0",
"sass-loader": "^16.0.4",
Expand Down
7 changes: 5 additions & 2 deletions src/components/canvas/store/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export class Render {
box.position = toCanvasPosition(
position,
this.store.anchorX,
this.store.anchorY
this.store.anchorY,
'cell'
)
this._fill(box, style)
this._border(box, position, style)
Expand Down Expand Up @@ -264,11 +265,13 @@ export class Render {
// }

private _text(box: Box, info: StandardCell) {
const t = info.getFormattedText()
if (!t) return
const textAttr = new TextAttr()
if (info.style) {
textAttr.alignment = info.style.alignment
textAttr.setFont(info.style.getFont())
}
this._painterService.text(info.getFormattedText(), textAttr, box)
this._painterService.text(t, textAttr, box)
}
}
12 changes: 0 additions & 12 deletions src/components/root/socket-status.ts

This file was deleted.

5 changes: 0 additions & 5 deletions src/components/root/waiting.tsx

This file was deleted.

76 changes: 62 additions & 14 deletions src/components/sheets-tab/contextmenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,107 @@ import Modal from 'react-modal'
import {DataService} from '@/core/data2'
import {useInjection} from '@/core/ioc/provider'
import {TYPES} from '@/core/ioc/types'
import {useToast} from '@/ui/notification/useToast'
import styles from './sheets-tab.module.scss'

export interface ContextMenuProps {
readonly index: number
readonly sheetnames: readonly string[]
readonly isOpen: boolean
readonly setIsOpen: (isOpen: boolean) => void
readonly left: number
readonly top: number
}

export const ContextMenuComponent = (props: ContextMenuProps) => {
const {index, sheetnames, isOpen, setIsOpen} = props
const {index, sheetnames: sheetNames, setIsOpen, top, left, isOpen} = props
const [renameIsOpen, setRenameIsOpen] = useState(false)
const oldName = sheetnames[index]
const [sheetName, setSheetName] = useState(oldName)
const oldName = sheetNames[index] || ''
const [newName, setNewName] = useState(oldName)
const DATA_SERVICE = useInjection<DataService>(TYPES.Data)
const toast = useToast()

const openRename = () => {
setRenameIsOpen(true)
setIsOpen(false)
}

const rename = () => {
if (sheetName === oldName) return
if (!newName) return
if (newName === oldName) return
const sheetRename = new SheetRenameBuilder()
.oldName(oldName)
.newName(sheetName)
.newName(newName)
.build()
DATA_SERVICE.handleTransaction(new Transaction([sheetRename], true))
}

const deleteSheet = () => {
if (sheetNames.length === 1) {
toast.toast.error(
'Deletion failed: A spreadsheet must have at least one sheet.'
)
return
}
const payload = new DeleteSheetBuilder().sheetIdx(index).build()
DATA_SERVICE.handleTransaction(new Transaction([payload], true))
}

return (
<div>
<>
<Modal
isOpen={isOpen}
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
onRequestClose={() => setIsOpen(false)}
ariaHideApp={false}
style={{
content: {
width: 'max-content',
height: 'max-content',
left: left,
top: top - 140,
},
}}
>
<div onClick={openRename}>重命名</div>
<div onClick={deleteSheet}>删除</div>
<div className={styles['context-menu']} tabIndex={-1}>
<div
className={styles['context-menu-item']}
onClick={openRename}
>
✏️ Rename
</div>
<div className={styles['context-menu-divider']} />
<div
className={styles['context-menu-item']}
onClick={deleteSheet}
>
🗑️ Delete
</div>
</div>
</Modal>
<Modal
isOpen={renameIsOpen}
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
onAfterClose={rename}
onRequestClose={() => setRenameIsOpen(false)}
ariaHideApp={false}
>
<input
value={sheetName}
onChange={(e) => setSheetName(e.target.value)}
/>
<button onClick={() => setRenameIsOpen(true)}>关闭</button>
<div className={styles['rename-modal']} tabIndex={-1}>
<input
className={styles['rename-input']}
value={newName}
onChange={(e) => setNewName(e.target.value)}
/>
<button
className={styles['rename-close-button']}
onClick={() => setRenameIsOpen(false)}
>
Close
</button>
</div>
</Modal>
</div>
</>
)
}
9 changes: 8 additions & 1 deletion src/components/sheets-tab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const SheetsTabComponent: FC<SheetTabProps> = ({
}
const [sheets, setSheets] = useState([] as string[])
const [isOpen, setIsOpen] = useState(false)
const [modalPosition, setModalPosition] = useState({top: 0, left: 0})

useEffect(() => {
getSheets().then((v) => {
Expand Down Expand Up @@ -82,6 +83,10 @@ export const SheetsTabComponent: FC<SheetTabProps> = ({
e.stopPropagation()
activeSheet$(i)
setIsOpen(true)
setModalPosition({
top: e.clientY,
left: e.clientX,
})
}}
>
{sheet}
Expand All @@ -101,7 +106,7 @@ export const SheetsTabComponent: FC<SheetTabProps> = ({
DATA_SERVICE.handleTransaction(
new Transaction([payload], true)
).then((v) => {
if (isErrorMessage(v)) return
if (v) return
activeSheet$(newIdx)
})
} else if (action === 'remove') {
Expand All @@ -113,6 +118,8 @@ export const SheetsTabComponent: FC<SheetTabProps> = ({
activeKey={sheets[activeSheet]}
/>
<ContextMenuComponent
left={modalPosition.left}
top={modalPosition.top}
isOpen={isOpen}
setIsOpen={setIsOpen}
index={activeSheet}
Expand Down
23 changes: 0 additions & 23 deletions src/components/sheets-tab/rename.tsx

This file was deleted.

Loading

0 comments on commit c6f74da

Please sign in to comment.