FIX: users :)
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1069,7 +1069,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm"
|
name = "wasm"
|
||||||
version = "0.5.0"
|
version = "0.5.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ironcalc_base",
|
"ironcalc_base",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -405,6 +405,7 @@ impl Model {
|
|||||||
},
|
},
|
||||||
tables: HashMap::new(),
|
tables: HashMap::new(),
|
||||||
views,
|
views,
|
||||||
|
users: Vec::new(),
|
||||||
};
|
};
|
||||||
let parsed_formulas = Vec::new();
|
let parsed_formulas = Vec::new();
|
||||||
let worksheets = &workbook.worksheets;
|
let worksheets = &workbook.worksheets;
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ pub struct WorkbookView {
|
|||||||
pub window_height: i64,
|
pub window_height: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WebUser {
|
||||||
|
pub id: String,
|
||||||
|
pub sheet: u32,
|
||||||
|
pub row: i32,
|
||||||
|
pub column: i32,
|
||||||
|
}
|
||||||
|
|
||||||
/// An internal representation of an IronCalc Workbook
|
/// An internal representation of an IronCalc Workbook
|
||||||
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct Workbook {
|
pub struct Workbook {
|
||||||
@@ -51,6 +59,7 @@ pub struct Workbook {
|
|||||||
pub metadata: Metadata,
|
pub metadata: Metadata,
|
||||||
pub tables: HashMap<String, Table>,
|
pub tables: HashMap<String, Table>,
|
||||||
pub views: HashMap<u32, WorkbookView>,
|
pub views: HashMap<u32, WorkbookView>,
|
||||||
|
pub users: Vec<WebUser>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A defined name. The `sheet_id` is the sheet index in case the name is local
|
/// A defined name. The `sheet_id` is the sheet index in case the name is local
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::{
|
|||||||
model::Model,
|
model::Model,
|
||||||
types::{
|
types::{
|
||||||
Alignment, BorderItem, CellType, Col, HorizontalAlignment, SheetProperties, SheetState,
|
Alignment, BorderItem, CellType, Col, HorizontalAlignment, SheetProperties, SheetState,
|
||||||
Style, VerticalAlignment,
|
Style, VerticalAlignment, WebUser,
|
||||||
},
|
},
|
||||||
utils::is_valid_hex_color,
|
utils::is_valid_hex_color,
|
||||||
};
|
};
|
||||||
@@ -293,6 +293,11 @@ impl UserModel {
|
|||||||
self.model.workbook.name = name.to_string();
|
self.model.workbook.name = name.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set users
|
||||||
|
pub fn set_users(&mut self, users: &[WebUser]) {
|
||||||
|
self.model.workbook.users = users.to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
/// Undoes last change if any, places the change in the redo list and evaluates the model if needed
|
/// Undoes last change if any, places the change in the redo list and evaluates the model if needed
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wasm"
|
name = "wasm"
|
||||||
version = "0.5.0"
|
version = "0.5.3"
|
||||||
authors = ["Nicolas Hatcher <nicolas@theuniverse.today>"]
|
authors = ["Nicolas Hatcher <nicolas@theuniverse.today>"]
|
||||||
description = "IronCalc Web bindings"
|
description = "IronCalc Web bindings"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
|
|||||||
@@ -201,6 +201,36 @@ defined_name_list_types = r"""
|
|||||||
getDefinedNameList(): DefinedName[];
|
getDefinedNameList(): DefinedName[];
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
set_users = r"""
|
||||||
|
/**
|
||||||
|
* @param {any} users
|
||||||
|
*/
|
||||||
|
setUsers(users: any): void;
|
||||||
|
"""
|
||||||
|
|
||||||
|
set_users_types = r"""
|
||||||
|
/**
|
||||||
|
* @param {WebUser[]} users
|
||||||
|
*/
|
||||||
|
setUsers(users: WebUser[]): void;
|
||||||
|
"""
|
||||||
|
|
||||||
|
get_users = r"""
|
||||||
|
/**
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
|
getUsers(): any;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
get_users_types = r"""
|
||||||
|
/**
|
||||||
|
* @returns {WebUser[]}
|
||||||
|
*/
|
||||||
|
getUsers(): WebUser[];
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
def fix_types(text):
|
def fix_types(text):
|
||||||
text = text.replace(get_tokens_str, get_tokens_str_types)
|
text = text.replace(get_tokens_str, get_tokens_str_types)
|
||||||
text = text.replace(update_style_str, update_style_str_types)
|
text = text.replace(update_style_str, update_style_str_types)
|
||||||
@@ -215,6 +245,8 @@ def fix_types(text):
|
|||||||
text = text.replace(clipboard, clipboard_types)
|
text = text.replace(clipboard, clipboard_types)
|
||||||
text = text.replace(paste_from_clipboard, paste_from_clipboard_types)
|
text = text.replace(paste_from_clipboard, paste_from_clipboard_types)
|
||||||
text = text.replace(defined_name_list, defined_name_list_types)
|
text = text.replace(defined_name_list, defined_name_list_types)
|
||||||
|
text = text.replace(set_users, set_users_types)
|
||||||
|
text = text.replace(get_users, get_users_types)
|
||||||
with open("types.ts") as f:
|
with open("types.ts") as f:
|
||||||
types_str = f.read()
|
types_str = f.read()
|
||||||
header_types = "{}\n\n{}".format(header, types_str)
|
header_types = "{}\n\n{}".format(header, types_str)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use wasm_bindgen::{
|
|||||||
|
|
||||||
use ironcalc_base::{
|
use ironcalc_base::{
|
||||||
expressions::{lexer::util::get_tokens as tokenizer, types::Area, utils::number_to_column},
|
expressions::{lexer::util::get_tokens as tokenizer, types::Area, utils::number_to_column},
|
||||||
types::{CellType, Style},
|
types::{CellType, Style, WebUser},
|
||||||
BorderArea, ClipboardData, UserModel as BaseModel,
|
BorderArea, ClipboardData, UserModel as BaseModel,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -672,4 +672,18 @@ impl Model {
|
|||||||
.delete_defined_name(name, scope)
|
.delete_defined_name(name, scope)
|
||||||
.map_err(|e| to_js_error(e.to_string()))
|
.map_err(|e| to_js_error(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = "setUsers")]
|
||||||
|
pub fn set_users(&mut self, users: JsValue) -> Result<(), JsError> {
|
||||||
|
let users: Vec<WebUser> =
|
||||||
|
serde_wasm_bindgen::from_value(users).map_err(|e| to_js_error(e.to_string()))?;
|
||||||
|
self.model.set_users(&users);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = "getUsers")]
|
||||||
|
pub fn get_users(&self) -> Result<JsValue, JsError> {
|
||||||
|
let users = self.model.get_model().workbook.users.clone();
|
||||||
|
serde_wasm_bindgen::to_value(&users).map_err(|e| to_js_error(e.to_string()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,4 +233,11 @@ export interface DefinedName {
|
|||||||
name: string;
|
name: string;
|
||||||
scope?: number;
|
scope?: number;
|
||||||
formula: string;
|
formula: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WebUser {
|
||||||
|
id: string;
|
||||||
|
sheet: number;
|
||||||
|
row: number;
|
||||||
|
column: number;
|
||||||
}
|
}
|
||||||
17
webapp/IronCalc/package-lock.json
generated
17
webapp/IronCalc/package-lock.json
generated
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@ironcalc/workbook",
|
"name": "@ironcalc/workbook",
|
||||||
"version": "0.5.1",
|
"version": "0.5.4",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@ironcalc/workbook",
|
"name": "@ironcalc/workbook",
|
||||||
"version": "0.5.1",
|
"version": "0.5.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@ironcalc/wasm": "0.5.0",
|
"@ironcalc/wasm": "0.5.3",
|
||||||
"@mui/material": "^6.4",
|
"@mui/material": "^6.4",
|
||||||
"@mui/system": "^6.4",
|
"@mui/system": "^6.4",
|
||||||
"i18next": "^23.11.1",
|
"i18next": "^23.11.1",
|
||||||
@@ -43,11 +43,6 @@
|
|||||||
"react-dom": "^18.0.0 || ^19.0.0"
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../../bindings/wasm/pkg": {
|
|
||||||
"name": "@ironcalc/wasm",
|
|
||||||
"version": "0.5.0",
|
|
||||||
"license": "MIT/Apache-2.0"
|
|
||||||
},
|
|
||||||
"node_modules/@adobe/css-tools": {
|
"node_modules/@adobe/css-tools": {
|
||||||
"version": "4.4.2",
|
"version": "4.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.2.tgz",
|
||||||
@@ -1060,8 +1055,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ironcalc/wasm": {
|
"node_modules/@ironcalc/wasm": {
|
||||||
"resolved": "../../bindings/wasm/pkg",
|
"version": "0.5.3",
|
||||||
"link": true
|
"resolved": "https://registry.npmjs.org/@ironcalc/wasm/-/wasm-0.5.3.tgz",
|
||||||
|
"integrity": "sha512-ryQKR5ISkSQnnsxBYDnrAUN+GDiAQUx0MzkVpJr7VQXiymOSMZbHfpv5geum1eSJV4gw1ft69syuNolIhVZ4Hg==",
|
||||||
|
"license": "MIT/Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@isaacs/cliui": {
|
"node_modules/@isaacs/cliui": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ironcalc/workbook",
|
"name": "@ironcalc/workbook",
|
||||||
"version": "0.5.1",
|
"version": "0.5.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/ironcalc.js",
|
"main": "./dist/ironcalc.js",
|
||||||
"module": "./dist/ironcalc.js",
|
"module": "./dist/ironcalc.js",
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.0",
|
"@emotion/styled": "^11.14.0",
|
||||||
"@ironcalc/wasm": "0.5.0",
|
"@ironcalc/wasm": "0.5.3",
|
||||||
"@mui/material": "^6.4",
|
"@mui/material": "^6.4",
|
||||||
"@mui/system": "^6.4",
|
"@mui/system": "^6.4",
|
||||||
"i18next": "^23.11.1",
|
"i18next": "^23.11.1",
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ interface IronCalcProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function IronCalc(properties: IronCalcProperties) {
|
function IronCalc(properties: IronCalcProperties) {
|
||||||
|
properties.model.setUsers([
|
||||||
|
{ id: "john@doe.com", sheet: 0, row: 5, column: 6 },
|
||||||
|
{ id: "micheal@doe.com", sheet: 0, row: 1, column: 6 },
|
||||||
|
]);
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<Workbook model={properties.model} workbookState={new WorkbookState()} />
|
<Workbook model={properties.model} workbookState={new WorkbookState()} />
|
||||||
|
|||||||
@@ -19,6 +19,13 @@ import {
|
|||||||
outlineColor,
|
outlineColor,
|
||||||
} from "./constants";
|
} from "./constants";
|
||||||
|
|
||||||
|
export interface UserSelection {
|
||||||
|
userId: string;
|
||||||
|
color: string;
|
||||||
|
selection: [number, number, number, number, number]; // [sheet, rowStart, columnStart, rowEnd, columnEnd]
|
||||||
|
div: HTMLDivElement;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CanvasSettings {
|
export interface CanvasSettings {
|
||||||
model: Model;
|
model: Model;
|
||||||
width: number;
|
width: number;
|
||||||
@@ -1244,6 +1251,34 @@ export default class WorksheetCanvas {
|
|||||||
editor.style.height = `${height - 1}px`;
|
editor.style.height = `${height - 1}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private drawUsersSelection(): void {
|
||||||
|
const users = this.model.getUsers();
|
||||||
|
for (const handle of document.querySelectorAll(
|
||||||
|
".user-selection-ironcalc",
|
||||||
|
))
|
||||||
|
handle.remove();
|
||||||
|
const colors = [];
|
||||||
|
users.forEach((user, index) => {
|
||||||
|
const { sheet, row, column } = user;
|
||||||
|
if (sheet !== this.model.getSelectedSheet()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [x, y] = this.getCoordinatesByCell(row, column);
|
||||||
|
const width = this.getColumnWidth(sheet, column);
|
||||||
|
const height = this.getRowHeight(sheet, row);
|
||||||
|
const div = document.createElement("div");
|
||||||
|
const color = getColor(index + 1);
|
||||||
|
div.className = "user-selection-ironcalc";
|
||||||
|
div.style.left = `${x}px`;
|
||||||
|
div.style.top = `${y}px`;
|
||||||
|
div.style.width = `${width}px`;
|
||||||
|
div.style.height = `${height}px`;
|
||||||
|
div.style.border = `1px solid ${color}`;
|
||||||
|
div.style.position = "absolute";
|
||||||
|
this.canvas.parentElement?.appendChild(div);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private drawCellOutline(): void {
|
private drawCellOutline(): void {
|
||||||
const { cellOutline, areaOutline, cellOutlineHandle } = this;
|
const { cellOutline, areaOutline, cellOutlineHandle } = this;
|
||||||
if (this.workbookState.getEditingCell()) {
|
if (this.workbookState.getEditingCell()) {
|
||||||
@@ -1595,6 +1630,7 @@ export default class WorksheetCanvas {
|
|||||||
context.stroke();
|
context.stroke();
|
||||||
|
|
||||||
this.drawCellOutline();
|
this.drawCellOutline();
|
||||||
|
this.drawUsersSelection();
|
||||||
this.drawCellEditor();
|
this.drawCellEditor();
|
||||||
this.drawExtendToArea();
|
this.drawExtendToArea();
|
||||||
this.drawActiveRanges(topLeftCell, bottomRightCell);
|
this.drawActiveRanges(topLeftCell, bottomRightCell);
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ fn load_xlsx_from_reader<R: Read + std::io::Seek>(
|
|||||||
metadata,
|
metadata,
|
||||||
tables,
|
tables,
|
||||||
views,
|
views,
|
||||||
|
users: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user