auto saving

This commit is contained in:
Gabriele Cannata 2023-08-15 15:14:13 +02:00
parent 243e2b1cd3
commit f519f3a3b1
4 changed files with 161 additions and 115 deletions

View file

@ -1,46 +1,53 @@
import SheetjsPlugin from "src/main";
import { App, PluginSettingTab, Setting } from "obsidian";
export class SheetjsSettingsTab extends PluginSettingTab {
plugin: SheetjsPlugin;
plugin: SheetjsPlugin;
constructor(app: App, plugin: SheetjsPlugin) {
super(app, plugin);
this.plugin = plugin;
}
constructor(app: App, plugin: SheetjsPlugin) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const {containerEl} = this;
display(): void {
const { containerEl } = this;
containerEl.empty();
containerEl.empty();
containerEl.createEl('h2', {text: 'Sheetjs Settings'});
containerEl.createEl("h2", { text: "Sheetjs Settings" });
this.createToggle(containerEl, "Add Ribbon Icon",
"Adds an icon to the ribbon to launch scan",
"addRibbonIcon"
this.createToggle(
containerEl,
"Enable Saving To File",
"Enabling saving to external files (.xlsx, .xls, ,.csv)",
"enableSaveToFile"
);
this.createToggle(containerEl, "Show Sheetjs Sidebar",
"Opens Sheetjs sidebar at startup",
"showAtStartUp"
);
this.createToggle(
containerEl,
"Auto Save",
"Saves automatically",
"autoSave"
);
}
}
private createToggle(containerEl: HTMLElement, name: string, desc: string, prop: string) {
new Setting(containerEl)
.setName(name)
.setDesc(desc)
.addToggle(bool => bool
.setValue((this.plugin.settings as any)[prop] as boolean)
.onChange(async (value) => {
(this.plugin.settings as any)[prop] = value;
await this.plugin.saveSettings();
this.display();
})
);
}
private createToggle(
containerEl: HTMLElement,
name: string,
desc: string,
prop: string
) {
new Setting(containerEl)
.setName(name)
.setDesc(desc)
.addToggle((bool) =>
bool
.setValue((this.plugin.settings as any)[prop] as boolean)
.onChange(async (value) => {
(this.plugin.settings as any)[prop] = value;
await this.plugin.saveSettings();
this.display();
})
);
}
}

View file

@ -1,11 +1,13 @@
export interface SheetsSettings {
addRibbonIcon: boolean;
enableSaveToFile: boolean
enableSaveToFile: boolean;
autoSave: boolean;
}
export const DEFAULT_SETTINGS: SheetsSettings = {
addRibbonIcon: false,
enableSaveToFile: true
enableSaveToFile: false,
autoSave: true
}

View file

@ -18,8 +18,14 @@ import * as XLSX from "xlsx";
import * as ExcelJS from "exceljs";
import { stox } from "../utils/xlsxpread";
import { toSpreadsheet } from "src/utils/excelConverter";
import { createSpreadSheet, prepareDataForSaving, saveToFile } from "./spreadSheetWrapper";
import Spreadsheet from "x-data-spreadsheet";
import {
createSpreadSheet,
prepareDataForSaving,
saveDataIntoBlock,
saveToFile,
} from "./spreadSheetWrapper";
const DEFAULT_OPTIONS = {
height: 540,
@ -36,7 +42,6 @@ const MINHEIGHT = 400;
const saveIcon =
"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNTc3MTc3MDkyOTg4IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjI2NzgiIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PC9zdHlsZT48L2RlZnM+PHBhdGggZD0iTTIxMy4zMzMzMzMgMTI4aDU5Ny4zMzMzMzRhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzMgODUuMzMzMzMzdjU5Ny4zMzMzMzRhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMS04NS4zMzMzMzMgODUuMzMzMzMzSDIxMy4zMzMzMzNhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMS04NS4zMzMzMzMtODUuMzMzMzMzVjIxMy4zMzMzMzNhODUuMzMzMzMzIDg1LjMzMzMzMyAwIDAgMSA4NS4zMzMzMzMtODUuMzMzMzMzeiBtMzY2LjkzMzMzNCAxMjhoMzQuMTMzMzMzYTI1LjYgMjUuNiAwIDAgMSAyNS42IDI1LjZ2MTE5LjQ2NjY2N2EyNS42IDI1LjYgMCAwIDEtMjUuNiAyNS42aC0zNC4xMzMzMzNhMjUuNiAyNS42IDAgMCAxLTI1LjYtMjUuNlYyODEuNmEyNS42IDI1LjYgMCAwIDEgMjUuNi0yNS42ek0yMTMuMzMzMzMzIDIxMy4zMzMzMzN2NTk3LjMzMzMzNGg1OTcuMzMzMzM0VjIxMy4zMzMzMzNIMjEzLjMzMzMzM3ogbTEyOCAwdjI1NmgzNDEuMzMzMzM0VjIxMy4zMzMzMzNoODUuMzMzMzMzdjI5OC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMS00Mi42NjY2NjcgNDIuNjY2NjY3SDI5OC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMS00Mi42NjY2NjctNDIuNjY2NjY3VjIxMy4zMzMzMzNoODUuMzMzMzMzek0yNTYgMjEzLjMzMzMzM2g4NS4zMzMzMzMtODUuMzMzMzMzeiBtNDI2LjY2NjY2NyAwaDg1LjMzMzMzMy04NS4zMzMzMzN6IG0wIDU5Ny4zMzMzMzR2LTEyOEgzNDEuMzMzMzMzdjEyOEgyNTZ2LTE3MC42NjY2NjdhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA0Mi42NjY2NjctNDIuNjY2NjY3aDQyNi42NjY2NjZhNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA0Mi42NjY2NjcgNDIuNjY2NjY3djE3MC42NjY2NjdoLTg1LjMzMzMzM3ogbTg1LjMzMzMzMyAwaC04NS4zMzMzMzMgODUuMzMzMzMzek0zNDEuMzMzMzMzIDgxMC42NjY2NjdIMjU2aDg1LjMzMzMzM3oiIHAtaWQ9IjI2NzkiIGZpbGw9IiMyYzJjMmMiPjwvcGF0aD48L3N2Zz4=";
export function processCodeBlock(
source: string,
el: HTMLElement,
@ -59,7 +64,7 @@ export function processCodeBlock(
if ((ctx as any).spreadsheet) return;
const options = { ...DEFAULT_OPTIONS, ...parseYaml(source) };
options.height = Math.max(options.height, MINHEIGHT);
const {
@ -133,9 +138,9 @@ export function processCodeBlock(
icon: saveIcon,
shortcut: "Ctrl+S",
onClick: (s: any, d: any) => {
if(!filename) saveDataIntoBlock(s, d, ctx);
if (!filename) saveDataIntoBlock(s, d, ctx);
else {
saveToFile((ctx as any).spreadsheet, filename)
saveToFile((ctx as any).spreadsheet, filename);
}
},
},
@ -143,34 +148,37 @@ export function processCodeBlock(
};
}
if (filename !== undefined) {
(async () => {
let data = undefined
try {
const fileContent = await app.vault.adapter.readBinary(filename);
data = await parseFileContent(filename, fileContent);
} catch (e) {
console.warn(e)
}
// setTimeout(() => {
if (filename !== undefined) {
(async () => {
let data = undefined;
try {
const fileContent = await app.vault.adapter.readBinary(
filename
);
data = await parseFileContent(filename, fileContent);
} catch (e) {
console.warn(e);
}
(ctx as any).spreadsheet = createSpreadSheet(
container,
spreadsheet_options,
{ ...options, data: data },
ctx
);
// .loadData();
})();
} else {
(ctx as any).spreadsheet = createSpreadSheet(
container,
spreadsheet_options,
{ ...options, data: data },
{ ...options },
ctx
);
// .loadData();
})();
} else {
(ctx as any).spreadsheet = createSpreadSheet(
container,
spreadsheet_options,
{ ...options },
ctx
);
}
}
// }, 0);
// (ctx as any).spreadsheet = s;
@ -182,10 +190,9 @@ export function processCodeBlock(
// https://github.com/wolf-table/table
}
async function parseFileContent(filename:string, fileContent:ArrayBuffer){
async function parseFileContent(filename: string, fileContent: ArrayBuffer) {
const ext = filename.slice(filename.lastIndexOf(".")).toLowerCase();
if(ext === ".xlsx" || ext === ".csv") {
if (ext === ".xlsx" || ext === ".csv") {
const workbook = new ExcelJS.Workbook();
const excelWorkbook = await workbook.xlsx.load(fileContent);
const data2 = toSpreadsheet(excelWorkbook);
@ -199,38 +206,4 @@ async function parseFileContent(filename:string, fileContent:ArrayBuffer){
const data = stox(xlsx);
return data;
}
}
function saveDataIntoBlock(
data: any,
sheet: any,
ctx: MarkdownPostProcessorContext
) {
const s = (ctx as any).spreadsheet as Spreadsheet;
const dts = prepareDataForSaving( s );
const view = app.workspace.getActiveViewOfType(MarkdownView);
if (!view) return;
if (view.getMode() === "source") {
const sec = ctx.getSectionInfo((ctx as any).el as HTMLElement);
if (sec) {
const obj = { data: dts };
const yaml = stringifyYaml(obj) + "\n";
view?.editor.replaceRange(
yaml,
{ line: sec?.lineStart + 1, ch: 0 },
{ line: sec?.lineEnd, ch: 0 },
"*"
);
console.info("Data saved on code block");
}
} else {
// preview
new Notice("Sheet not saved while in reading mode");
}
}

View file

@ -1,12 +1,13 @@
// import { Spreadsheet } from 'x-data-spreadsheet';
/* eslint-disable @typescript-eslint/no-explicit-any */
import { MarkdownPostProcessorContext, debounce } from "obsidian";
import { MarkdownPostProcessorContext, MarkdownView, Notice, debounce, stringifyYaml } from "obsidian";
import * as XLSX from "xlsx";
import { xtos } from "../utils/xlsxpread";
import { toExcelJS } from "src/utils/excelConverter";
import { SheetData, SpreadsheetData } from "x-data-spreadsheet";
// HACK
import Spreadsheet from "x-data-spreadsheet";
import { getSheetjsSettings } from "src/main";
// import * as Spreadsheet from "x-data-spreadsheet";
// const { Spreadsheet } = require("x-data-spreadsheet");
@ -74,26 +75,89 @@ export function createSpreadSheet(
)
// .loadData(options.data || {});
const settings = getSheetjsSettings()
prepareDataForLoading(spreadSheet, options.data as SpreadsheetData)
spreadSheet.change(
debounce((_data) => {
// save data
// console.log(data)
if (options.filename) {
saveToFile(spreadSheet, options.filename);
} else {
// at the moment we avoid since this would cause re-rendering
// saveDataIntoBlock(null,null,ctx)
}
let focused = true;
// XLSX.writeFile(xtos(s.getData(data)) as any, filename);
}, 1000)
);
if(settings.autoSave) {
spreadSheet.change(
debounce((_data) => {
// save data
// console.log(data)
if (options.filename && settings.enableSaveToFile) {
saveToFile(spreadSheet, options.filename);
} else {
// at the moment we avoid since this would cause re-rendering
// saveDataIntoBlock(null,null,ctx)
}
// XLSX.writeFile(xtos(s.getData(data)) as any, filename);
}, 1000)
);
if(!options.filename && settings.autoSave){
const ae = container.closest("[tabindex]");
console.log('ae',ae);
ae?.addEventListener('blur', debounce((e)=>{
// console.log(`focus changed `,e);
const tmp = document.activeElement;
saveDataIntoBlock(null,null,ctx);
// let el = tmp;
// let f = false;
// while(el?.parentElement) {
// if(el === container) {
// f = true;
// break;
// }
// el = el.parentElement;
// }
// if(focused && !f){
// // lost focus
// console.log(`lost focus`);
// }
// focused = f;
}))
}
}
return spreadSheet;
}
export function saveDataIntoBlock(
data: any,
sheet: any,
ctx: MarkdownPostProcessorContext
) {
const s = (ctx as any).spreadsheet as Spreadsheet;
const dts = prepareDataForSaving( s );
const view = app.workspace.getActiveViewOfType(MarkdownView);
if (!view) return;
if (view.getMode() === "source") {
const sec = ctx.getSectionInfo((ctx as any).el as HTMLElement);
if (sec) {
const obj = { data: dts };
const yaml = stringifyYaml(obj) + "\n";
view?.editor.replaceRange(
yaml,
{ line: sec?.lineStart + 1, ch: 0 },
{ line: sec?.lineEnd, ch: 0 },
"*"
);
console.info("Data saved on code block");
}
} else {
// preview
new Notice("Sheet not saved while in reading mode");
}
}
export async function saveToFile(spreadSheet: Spreadsheet, filename: string) {
const spreadsheetData = spreadSheet.getData() as any[];