feat: sync pdf and note

This commit is contained in:
Michal Szczepanski 2023-09-20 03:57:47 +02:00
parent f10d617689
commit 6e1ea32255
36 changed files with 186 additions and 204 deletions

@ -22,7 +22,6 @@ import { ObjPageDto } from '../../../model/obj/obj-page.dto';
import { ObjPageNoteDto } from '../../../model/obj/obj-note.dto'; import { ObjPageNoteDto } from '../../../model/obj/obj-note.dto';
import { ObjPdfDto } from '../../../model/obj/obj-pdf.dto'; import { ObjPdfDto } from '../../../model/obj/obj-pdf.dto';
import { ObjPinDto } from '../../../model/obj/obj-pin.dto'; import { ObjPinDto } from '../../../model/obj/obj-pin.dto';
import { ObjTaskDto } from '../../../model/obj/obj-task.dto';
import { fnConsoleLog } from '../../../fn/fn-console'; import { fnConsoleLog } from '../../../fn/fn-console';
export class ObjGetOriginCommand implements ICommand<Promise<ObjDto<ObjPageDataDto>[]>> { export class ObjGetOriginCommand implements ICommand<Promise<ObjDto<ObjPageDataDto>[]>> {
@ -45,10 +44,8 @@ export class ObjGetOriginCommand implements ICommand<Promise<ObjDto<ObjPageDataD
if ((obj.data as ObjPinDto).data.url.href === this.data.href) continue; if ((obj.data as ObjPinDto).data.url.href === this.data.href) continue;
} else if (obj.type === ObjTypeDto.PageNote) { } else if (obj.type === ObjTypeDto.PageNote) {
if ((obj.data as ObjPageNoteDto).url.href === this.data.href) continue; if ((obj.data as ObjPageNoteDto).url.href === this.data.href) continue;
} else if (obj.type === ObjTypeDto.PageTask) {
if ((obj.data as ObjTaskDto).url?.href === this.data.href) continue;
} else if (obj.type === ObjTypeDto.Pdf) { } else if (obj.type === ObjTypeDto.Pdf) {
if ((obj.data as ObjPdfDto).rawUrl === this.data.href) continue; if ((obj.data as ObjPdfDto).data.rawUrl === this.data.href) continue;
} }
out.push(obj); out.push(obj);
// TODO pagination - now show last 10 // TODO pagination - now show last 10

@ -45,7 +45,7 @@ export class PageNoteAddCommand implements ICommand<Promise<void>> {
}; };
await SwTaskStore.addTask(SwTaskType.WORDS_ADD_INDEX, { await SwTaskStore.addTask(SwTaskType.WORDS_ADD_INDEX, {
words: this.note.words, words: this.note.data.words,
objectId: id objectId: id
}); });

@ -47,7 +47,7 @@ export class PageNoteRemoveCommand implements ICommand<void> {
await LinkHrefStore.noteDel(data.url, this.obj.id); await LinkHrefStore.noteDel(data.url, this.obj.id);
await SwTaskStore.addTask(SwTaskType.WORDS_REMOVE_INDEX, { await SwTaskStore.addTask(SwTaskType.WORDS_REMOVE_INDEX, {
words: data.words, words: data.data.words,
objectId: this.obj.id objectId: this.obj.id
}); });

@ -17,14 +17,14 @@
import { BrowserStorage } from '@pinmenote/browser-api'; import { BrowserStorage } from '@pinmenote/browser-api';
import { ICommand } from '../../model/shared/common.dto'; import { ICommand } from '../../model/shared/common.dto';
import { ObjDto } from '../../model/obj/obj.dto'; import { ObjDto } from '../../model/obj/obj.dto';
import { ObjPageNoteDto } from '../../model/obj/obj-note.dto'; import { ObjNoteDataDto, ObjPageNoteDto } from '../../model/obj/obj-note.dto';
import { ObjUpdateIndexAddCommand } from '../obj/index/obj-update-index-add.command'; import { ObjUpdateIndexAddCommand } from '../obj/index/obj-update-index-add.command';
import { ObjectStoreKeys } from '../../keys/object.store.keys'; import { ObjectStoreKeys } from '../../keys/object.store.keys';
import { SwTaskStore } from '../../store/sw-task.store'; import { SwTaskStore } from '../../store/sw-task.store';
import { SwTaskType } from '../../model/sw-task.model'; import { SwTaskType } from '../../model/sw-task.model';
import { WordFactory } from '../../text/word.factory'; import { WordFactory } from '../../text/word.factory';
import { fnConsoleLog } from '../../fn/fn-console'; import { fnConsoleLog } from '../../fn/fn-console';
import { fnSha256 } from '../../fn/fn-hash'; import { fnSha256Object } from '../../fn/fn-hash';
export class PageNoteUpdateCommand implements ICommand<void> { export class PageNoteUpdateCommand implements ICommand<void> {
constructor(private obj: ObjDto<ObjPageNoteDto>, private title: string, private description: string) {} constructor(private obj: ObjDto<ObjPageNoteDto>, private title: string, private description: string) {}
@ -37,24 +37,28 @@ export class PageNoteUpdateCommand implements ICommand<void> {
await BrowserStorage.set<ObjPageNoteDto>(`${ObjectStoreKeys.NOTE_HASH}:${this.obj.data.hash}`, this.obj.data); await BrowserStorage.set<ObjPageNoteDto>(`${ObjectStoreKeys.NOTE_HASH}:${this.obj.data.hash}`, this.obj.data);
this.obj.data.prev = this.obj.data.hash; this.obj.data.prev = this.obj.data.hash;
this.obj.data.hash = fnSha256(this.title + this.description + (this.obj.data.url?.href || '') + dt.toString());
this.obj.data.title = this.title; const words = new Set<string>([...WordFactory.toWordList(this.title), ...WordFactory.toWordList(this.description)]);
this.obj.data.description = this.description;
const newData: ObjNoteDataDto = {
title: this.title,
description: this.description,
words: Array.from(words),
hashtags: this.obj.data.data.hashtags
};
this.obj.data.hash = fnSha256Object({ ...newData, url: this.obj.data.url, dt });
this.obj.data.data = newData;
this.obj.updatedAt = dt; this.obj.updatedAt = dt;
// Remove words from index // Remove words from index
await SwTaskStore.addTask(SwTaskType.WORDS_REMOVE_INDEX, { await SwTaskStore.addTask(SwTaskType.WORDS_REMOVE_INDEX, {
words: this.obj.data.words, words: this.obj.data.data.words,
objectId: this.obj.id objectId: this.obj.id
}); });
// Update words
const words = new Set<string>([...WordFactory.toWordList(this.title), ...WordFactory.toWordList(this.description)]);
this.obj.data.words = Array.from(words);
await SwTaskStore.addTask(SwTaskType.WORDS_ADD_INDEX, { await SwTaskStore.addTask(SwTaskType.WORDS_ADD_INDEX, {
words: this.obj.data.words, words: Array.from(words),
objectId: this.obj.id objectId: this.obj.id
}); });

@ -22,11 +22,11 @@ import { ICommand } from '../../model/shared/common.dto';
import { LinkHrefStore } from '../../store/link-href.store'; import { LinkHrefStore } from '../../store/link-href.store';
import { ObjAddIdCommand } from '../obj/id/obj-add-id.command'; import { ObjAddIdCommand } from '../obj/id/obj-add-id.command';
import { ObjNextIdCommand } from '../obj/id/obj-next-id.command'; import { ObjNextIdCommand } from '../obj/id/obj-next-id.command';
import { ObjPdfDto } from '../../model/obj/obj-pdf.dto'; import { ObjPdfDataDto, ObjPdfDto } from '../../model/obj/obj-pdf.dto';
import { ObjectStoreKeys } from '../../keys/object.store.keys'; import { ObjectStoreKeys } from '../../keys/object.store.keys';
import { ScreenshotFactory } from '../../factory/screenshot.factory'; import { ScreenshotFactory } from '../../factory/screenshot.factory';
import { UrlFactory } from '../../factory/url.factory'; import { UrlFactory } from '../../factory/url.factory';
import { fnSha256 } from '../../fn/fn-hash'; import { fnSha256, fnSha256Object } from '../../fn/fn-hash';
import { ImageResizeFactory } from '../../factory/image-resize.factory'; import { ImageResizeFactory } from '../../factory/image-resize.factory';
export class PdfAddCommand implements ICommand<Promise<void>> { export class PdfAddCommand implements ICommand<Promise<void>> {
@ -46,13 +46,17 @@ export class PdfAddCommand implements ICommand<Promise<void>> {
const url = UrlFactory.newUrl(); const url = UrlFactory.newUrl();
const data: ObjPdfDto = { const pdfData: Omit<ObjPdfDataDto, 'hash'> = {
hash,
screenshot, screenshot,
rawUrl: this.value.url, rawUrl: this.value.url,
url, url,
hashtags: [] hashtags: []
}; };
const pdfDataHash = fnSha256Object(pdfData);
const data: ObjPdfDto = {
hash,
data: { ...pdfData, hash: pdfDataHash }
};
const dto: ObjDto<ObjPdfDto> = { const dto: ObjDto<ObjPdfDto> = {
id, id,

@ -27,7 +27,7 @@ export class PdfRemoveCommand implements ICommand<Promise<void>> {
await BrowserStorage.remove(`${ObjectStoreKeys.PDF_DATA}:${this.dto.hash}`); await BrowserStorage.remove(`${ObjectStoreKeys.PDF_DATA}:${this.dto.hash}`);
await BrowserStorage.remove(`${ObjectStoreKeys.OBJECT_ID}:${this.id}`); await BrowserStorage.remove(`${ObjectStoreKeys.OBJECT_ID}:${this.id}`);
await LinkHrefStore.del(this.dto.url, this.id); await LinkHrefStore.del(this.dto.data.url, this.id);
await new ObjRemoveIdCommand(this.id, ObjectStoreKeys.OBJECT_LIST).execute(); await new ObjRemoveIdCommand(this.id, ObjectStoreKeys.OBJECT_LIST).execute();
} }

@ -77,15 +77,13 @@ export class DownloadImageButton {
}; };
private downloadScreenshot = async (screenshot: string): Promise<void> => { private downloadScreenshot = async (screenshot: string): Promise<void> => {
let url = ''; const url = window.URL.createObjectURL(fnB64toBlob(screenshot));
let filename = ''; let filename = '';
switch (this.model.doc.settings.screenshotFormat) { switch (this.model.doc.settings.screenshotFormat) {
case 'jpeg': case 'jpeg':
url = window.URL.createObjectURL(fnB64toBlob(screenshot, 'image/jpeg'));
filename = `${fnUid()}.jpg`; filename = `${fnUid()}.jpg`;
break; break;
default: default:
url = window.URL.createObjectURL(fnB64toBlob(screenshot, 'image/png'));
filename = `${fnUid()}.png`; filename = `${fnUid()}.png`;
} }
const data = { url, filename }; const data = { url, filename };

@ -14,8 +14,13 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
export const fnB64toBlob = (b64Data: string, contentType = '', sliceSize = 512): Blob => { export const fnB64toBlob = (b64Data: string, sliceSize = 512): Blob => {
const byteCharacters = window.atob(b64Data.split(',')[1]); const a = b64Data.split(',');
const contentType = a[0].substring(5).split(';')[0];
let data = a[1];
if (data.endsWith('%3D')) data = data.replaceAll('%3D', '=');
// console.log('fnB64toBlob', 'contentType', contentType, 'data', data);
const byteCharacters = atob(data);
const byteArrays = []; const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {

@ -22,6 +22,10 @@ export interface ObjPageNoteDto extends ObjNoteDto {
export interface ObjNoteDto { export interface ObjNoteDto {
hash: string; hash: string;
prev?: string; prev?: string;
data: ObjNoteDataDto;
}
export interface ObjNoteDataDto {
title: string; title: string;
description: string; description: string;
words: string[]; words: string[];

@ -18,8 +18,13 @@ import { ObjUrlDto } from './obj.dto';
export interface ObjPdfDto { export interface ObjPdfDto {
hash: string; hash: string;
data: ObjPdfDataDto;
}
export interface ObjPdfDataDto {
screenshot: string; screenshot: string;
rawUrl: string; rawUrl: string;
url: ObjUrlDto; url: ObjUrlDto;
hashtags: string[]; hashtags: string[];
hash: string;
} }

@ -1,25 +0,0 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2023 Michal Szczepanski.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ObjUrlDto } from './obj.dto';
export interface ObjTaskDto {
title: string;
description: string;
url?: ObjUrlDto;
words: string[];
hashtags: string[];
}

@ -28,7 +28,6 @@ import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjPageNoteDto } from '../../../common/model/obj/obj-note.dto'; import { ObjPageNoteDto } from '../../../common/model/obj/obj-note.dto';
import { ObjViewComponent } from '../obj/obj-view.component'; import { ObjViewComponent } from '../obj/obj-view.component';
import { PopupFunctionsComponent } from '../popup-functions/popup-functions.component'; import { PopupFunctionsComponent } from '../popup-functions/popup-functions.component';
import { TaskComponent } from '../task/task.component';
export const MainViewComponent: FunctionComponent = () => { export const MainViewComponent: FunctionComponent = () => {
const [previousView, setPreviousView] = useState<MainViewEnum>(MainViewEnum.PAGE_OBJECTS); const [previousView, setPreviousView] = useState<MainViewEnum>(MainViewEnum.PAGE_OBJECTS);
@ -57,8 +56,6 @@ export const MainViewComponent: FunctionComponent = () => {
return <DecryptComponent />; return <DecryptComponent />;
case MainViewEnum.CALENDAR: case MainViewEnum.CALENDAR:
return <CalendarComponent />; return <CalendarComponent />;
case MainViewEnum.TASK:
return <TaskComponent />;
case MainViewEnum.BUG_REPORT: case MainViewEnum.BUG_REPORT:
return <BugReportComponent cancelCallback={() => setCurrentView(MainViewEnum.PAGE_OBJECTS)} />; return <BugReportComponent cancelCallback={() => setCurrentView(MainViewEnum.PAGE_OBJECTS)} />;
case MainViewEnum.NOTE: case MainViewEnum.NOTE:

@ -18,14 +18,14 @@ import { COLOR_DEFAULT_BORDER, DEFAULT_BORDER_RADIUS } from '../../../../common/
import React, { FunctionComponent, useEffect, useRef, useState } from 'react'; import React, { FunctionComponent, useEffect, useRef, useState } from 'react';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import { EditorView } from 'prosemirror-view'; import { EditorView } from 'prosemirror-view';
import { ObjPageNoteDto } from '../../../../common/model/obj/obj-note.dto'; import { ObjNoteDataDto } from '../../../../common/model/obj/obj-note.dto';
import { PageNoteAddCommand } from '../../../../common/command/page-note/page-note-add.command'; import { PageNoteAddCommand } from '../../../../common/command/page-note/page-note-add.command';
import { PopupActiveTabStore } from '../../../store/popup-active-tab.store'; import { PopupActiveTabStore } from '../../../store/popup-active-tab.store';
import { StyledInput } from '../../../../common/components/react/styled.input'; import { StyledInput } from '../../../../common/components/react/styled.input';
import { WordFactory } from '../../../../common/text/word.factory'; import { WordFactory } from '../../../../common/text/word.factory';
import { createTextEditorState } from '../../../../common/components/text-editor/text.editor.state'; import { createTextEditorState } from '../../../../common/components/text-editor/text.editor.state';
import { defaultMarkdownSerializer } from 'prosemirror-markdown'; import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { fnSha256 } from '../../../../common/fn/fn-hash'; import { fnSha256Object } from '../../../../common/fn/fn-hash';
interface Props { interface Props {
addCallback: () => void; addCallback: () => void;
@ -76,16 +76,21 @@ export const NoteAddComponent: FunctionComponent<Props> = (props) => {
const description = LocalModel.description; const description = LocalModel.description;
const words = new Set<string>([...WordFactory.toWordList(title), ...WordFactory.toWordList(description)]); const words = new Set<string>([...WordFactory.toWordList(title), ...WordFactory.toWordList(description)]);
const dt = Date.now(); const dt = Date.now();
const hash = fnSha256(title + description + (url?.href || '') + dt.toString()); const data: ObjNoteDataDto = {
const note: ObjPageNoteDto = {
hash,
title, title,
description, description,
url,
words: Array.from(words), words: Array.from(words),
hashtags: [] hashtags: []
}; };
await new PageNoteAddCommand(note, dt).execute(); const hash = fnSha256Object({ ...data, url, dt });
await new PageNoteAddCommand(
{
hash,
url,
data
},
dt
).execute();
props.addCallback(); props.addCallback();
}; };

@ -43,7 +43,7 @@ class LocalModel {
} }
export const NoteEditComponent: FunctionComponent<Props> = (props) => { export const NoteEditComponent: FunctionComponent<Props> = (props) => {
const [title, setTitle] = useState<string>(props.editNote.data.title); const [title, setTitle] = useState<string>(props.editNote.data.data.title);
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
@ -56,7 +56,7 @@ export const NoteEditComponent: FunctionComponent<Props> = (props) => {
}, []); }, []);
const create = (el: HTMLDivElement): void => { const create = (el: HTMLDivElement): void => {
let state = createTextEditorState(props.editNote.data.description); let state = createTextEditorState(props.editNote.data.data.description);
LocalModel.editorView = new EditorView(el, { LocalModel.editorView = new EditorView(el, {
state, state,
handleKeyDown: (view: EditorView, event: KeyboardEvent) => { handleKeyDown: (view: EditorView, event: KeyboardEvent) => {

@ -43,7 +43,7 @@ export const NoteElementComponent: FunctionComponent<Props> = ({ obj, editCallba
); );
const expandComponent = isExpanded ? <NoteListExpandComponent note={obj} /> : ''; const expandComponent = isExpanded ? <NoteListExpandComponent note={obj} /> : '';
const title = obj.data.title.length > 50 ? `${obj.data.title.substring(0, 50)}...` : obj.data.title; const title = obj.data.data.title.length > 50 ? `${obj.data.data.title.substring(0, 50)}...` : obj.data.data.title;
return ( return (
<div <div
style={{ style={{

@ -50,7 +50,7 @@ export const NoteListElementComponent: FunctionComponent<Props> = (props) => {
); );
const expandComponent = isExpanded ? <NoteListExpandComponent note={props.obj} /> : ''; const expandComponent = isExpanded ? <NoteListExpandComponent note={props.obj} /> : '';
const value = props.obj.data.title; const value = props.obj.data.data.title;
const title = value.length > 30 ? `${value.substring(0, 30)}...` : value; const title = value.length > 30 ? `${value.substring(0, 30)}...` : value;
return ( return (

@ -27,7 +27,8 @@ export const NoteListExpandComponent: FunctionComponent<PinExpandProps> = ({ not
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
if (!ref.current) return; if (!ref.current) return;
ref.current.innerHTML = marked(note.data.description); const { data } = note.data;
ref.current.innerHTML = marked(data.description);
}); });
return ( return (

@ -37,8 +37,8 @@ export const PdfListElementComponent: FunctionComponent<Props> = (props) => {
const [isExpanded, setIsExpanded] = useState(false); const [isExpanded, setIsExpanded] = useState(false);
const handleNavigate = async (data: ObjDto<ObjPdfDto>): Promise<void> => { const handleNavigate = async (data: ObjDto<ObjPdfDto>): Promise<void> => {
if (PopupActiveTabStore.url?.href !== data.data.url.href) { if (PopupActiveTabStore.url?.href !== data.data.data.url.href) {
await BrowserApi.setActiveTabUrl(data.data.url.href); await BrowserApi.setActiveTabUrl(data.data.data.url.href);
window.close(); window.close();
} }
}; };
@ -58,7 +58,7 @@ export const PdfListElementComponent: FunctionComponent<Props> = (props) => {
); );
const expandComponent = isExpanded ? <PdfListExpandComponent obj={props.obj}></PdfListExpandComponent> : ''; const expandComponent = isExpanded ? <PdfListExpandComponent obj={props.obj}></PdfListExpandComponent> : '';
const a = props.obj.data.url.pathname.split('/'); const a = props.obj.data.data.url.pathname.split('/');
let title = a[a.length - 1]; let title = a[a.length - 1];
title = title.length > 30 ? `${title.substring(0, 30)}...` : title; title = title.length > 30 ? `${title.substring(0, 30)}...` : title;

@ -1,5 +0,0 @@
import React, { FunctionComponent } from 'react';
export const TaskAddComponent: FunctionComponent = () => {
return <div>Task add</div>;
};

@ -1,15 +0,0 @@
import React, { FunctionComponent } from 'react';
import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjTaskDto } from '../../../common/model/obj/obj-task.dto';
interface Props {
editCallback: (obj: ObjDto<ObjTaskDto>) => void;
}
export const TaskListComponent: FunctionComponent<Props> = () => {
return (
<div>
<h2>List</h2>
</div>
);
};

@ -1,57 +0,0 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2023 Michal Szczepanski.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { FunctionComponent, useState } from 'react';
import AddIcon from '@mui/icons-material/Add';
import IconButton from '@mui/material/IconButton';
import { TaskListComponent } from './task-list.component';
import { fnConsoleLog } from '../../../common/fn/fn-console';
enum CurrentView {
TASK_LIST = 'TASK_LIST',
TASK_ADD = 'TASK_ADD',
TASK_EDIT = 'TASK_EDIT'
}
export const TaskComponent: FunctionComponent = () => {
const [state, setState] = useState<CurrentView>(CurrentView.TASK_LIST);
const getComponent = (state: CurrentView) => {
switch (state) {
case CurrentView.TASK_LIST:
return (
<TaskListComponent
editCallback={() => {
fnConsoleLog('editCallback');
}}
/>
);
case CurrentView.TASK_ADD:
return 'TODO';
}
};
const component = getComponent(state);
return (
<div>
<div style={{ display: 'flex', flexDirection: 'row' }}>
<h2>Task</h2>
<IconButton onClick={() => setState(CurrentView.TASK_ADD)}>
<AddIcon />
</IconButton>
</div>
{component}
</div>
);
};

@ -17,8 +17,8 @@
import { ObjDto, ObjTypeDto } from '../../../common/model/obj/obj.dto'; import { ObjDto, ObjTypeDto } from '../../../common/model/obj/obj.dto';
import React, { FunctionComponent, useEffect, useRef, useState } from 'react'; import React, { FunctionComponent, useEffect, useRef, useState } from 'react';
import { BoardStore } from '../../store/board.store'; import { BoardStore } from '../../store/board.store';
import { ObjNoteDto } from '../../../common/model/obj/obj-note.dto';
import { ObjPageDto } from '../../../common/model/obj/obj-page.dto'; import { ObjPageDto } from '../../../common/model/obj/obj-page.dto';
import { ObjPageNoteDto } from '../../../common/model/obj/obj-note.dto';
import { ObjPdfDto } from '../../../common/model/obj/obj-pdf.dto'; import { ObjPdfDto } from '../../../common/model/obj/obj-pdf.dto';
import { PageNoteElement } from './page-note/page-note.element'; import { PageNoteElement } from './page-note/page-note.element';
import { PageSnapshotElement } from './page-snapshot/page-snapshot.element'; import { PageSnapshotElement } from './page-snapshot/page-snapshot.element';
@ -84,7 +84,11 @@ export const BoardComponent: FunctionComponent = () => {
} }
case ObjTypeDto.PageNote: { case ObjTypeDto.PageNote: {
boardElements.push( boardElements.push(
<PageNoteElement key={obj.id} dto={obj as ObjDto<ObjNoteDto>} refreshBoardCallback={refreshBoardCallback} /> <PageNoteElement
key={obj.id}
dto={obj as ObjDto<ObjPageNoteDto>}
refreshBoardCallback={refreshBoardCallback}
/>
); );
break; break;
} }

@ -31,13 +31,13 @@ interface Props {
export const PageNoteElement: FunctionComponent<Props> = (props) => { export const PageNoteElement: FunctionComponent<Props> = (props) => {
const [edit, setEdit] = useState<boolean>(false); const [edit, setEdit] = useState<boolean>(false);
const [hashtags, setHashtags] = useState<string[]>(props.dto.data.hashtags); const [hashtags, setHashtags] = useState<string[]>(props.dto.data.data.hashtags);
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
if (!ref.current) return; if (!ref.current) return;
ref.current.innerHTML = marked(props.dto.data.description); ref.current.innerHTML = marked(props.dto.data.data.description);
}, []); }, []);
const handleEdit = () => { const handleEdit = () => {
@ -51,14 +51,14 @@ export const PageNoteElement: FunctionComponent<Props> = (props) => {
}; };
const handleTagSave = (newTags: string[]) => { const handleTagSave = (newTags: string[]) => {
props.dto.data.hashtags = newTags; props.dto.data.data.hashtags = newTags;
setHashtags(newTags); setHashtags(newTags);
fnConsoleLog('PageSnapshotElement->handleTagSave->newTags', newTags); fnConsoleLog('PageSnapshotElement->handleTagSave->newTags', newTags);
}; };
return ( return (
<BoardItem> <BoardItem>
<BoardItemTitle title={props.dto.data.title} editCallback={handleEdit} removeCallback={handleRemove} /> <BoardItemTitle title={props.dto.data.data.title} editCallback={handleEdit} removeCallback={handleRemove} />
<div> <div>
<div ref={ref}></div> <div ref={ref}></div>
</div> </div>
@ -66,9 +66,9 @@ export const PageNoteElement: FunctionComponent<Props> = (props) => {
<BoardItemFooter <BoardItemFooter
title="page note" title="page note"
saveTags={handleTagSave} saveTags={handleTagSave}
tags={props.dto.data.hashtags} tags={props.dto.data.data.hashtags}
createdAt={props.dto.createdAt} createdAt={props.dto.createdAt}
words={props.dto.data.words} words={props.dto.data.data.words}
url={props.dto.data.url?.href} url={props.dto.data.url?.href}
/> />
</BoardItem> </BoardItem>

@ -30,9 +30,9 @@ interface Props {
export const PdfElement: FunctionComponent<Props> = (props) => { export const PdfElement: FunctionComponent<Props> = (props) => {
const [edit, setEdit] = useState<boolean>(false); const [edit, setEdit] = useState<boolean>(false);
const [hashtags, setHashtags] = useState<string[]>(props.dto.data.hashtags || []); const [hashtags, setHashtags] = useState<string[]>(props.dto.data.data.hashtags || []);
const a = props.dto.data.url.pathname.split('/'); const a = props.dto.data.data.url.pathname.split('/');
const title = a[a.length - 1]; const title = a[a.length - 1];
const handleEdit = () => { const handleEdit = () => {
@ -50,7 +50,7 @@ export const PdfElement: FunctionComponent<Props> = (props) => {
}; };
const handleTagSave = (newTags: string[]) => { const handleTagSave = (newTags: string[]) => {
props.dto.data.hashtags = newTags; props.dto.data.data.hashtags = newTags;
setHashtags(newTags); setHashtags(newTags);
fnConsoleLog('PageSnapshotElement->handleTagSave->newTags', newTags); fnConsoleLog('PageSnapshotElement->handleTagSave->newTags', newTags);
}; };
@ -60,7 +60,7 @@ export const PdfElement: FunctionComponent<Props> = (props) => {
<BoardItemTitle title={title} htmlCallback={handleHtml} editCallback={handleEdit} removeCallback={handleRemove} /> <BoardItemTitle title={title} htmlCallback={handleHtml} editCallback={handleEdit} removeCallback={handleRemove} />
<img <img
style={{ height: '100%', width: '100%', objectFit: 'contain', maxHeight: 220 }} style={{ height: '100%', width: '100%', objectFit: 'contain', maxHeight: 220 }}
src={props.dto.data.screenshot} src={props.dto.data.data.screenshot}
/> />
<div style={{ display: 'flex', flexGrow: 1 }}></div> <div style={{ display: 'flex', flexGrow: 1 }}></div>
<BoardItemFooter <BoardItemFooter
@ -69,7 +69,7 @@ export const PdfElement: FunctionComponent<Props> = (props) => {
createdAt={props.dto.createdAt} createdAt={props.dto.createdAt}
tags={hashtags} tags={hashtags}
words={[]} words={[]}
url={props.dto.data.rawUrl} url={props.dto.data.data.rawUrl}
/> />
</BoardItem> </BoardItem>
); );

@ -63,7 +63,7 @@ export const PdfPreviewComponent: FunctionComponent<Props> = (props) => {
if (!pdfRef.current || !titleRef.current) return; if (!pdfRef.current || !titleRef.current) return;
const obj = await new ObjGetCommand<ObjPdfDto>(id).execute(); const obj = await new ObjGetCommand<ObjPdfDto>(id).execute();
const data = await BrowserStorage.get<string | undefined>(`${ObjectStoreKeys.PDF_DATA}:${obj.data.hash}`); const data = await BrowserStorage.get<string | undefined>(`${ObjectStoreKeys.PDF_DATA}:${obj.data.hash}`);
const a = obj.data.url.pathname.split('/'); const a = obj.data.data.url.pathname.split('/');
titleRef.current.innerText = `${a[a.length - 1]}`; titleRef.current.innerText = `${a[a.length - 1]}`;
@ -95,7 +95,7 @@ export const PdfPreviewComponent: FunctionComponent<Props> = (props) => {
} }
}, 250); }, 250);
} }
} catch (e) { } catch (e: any) {
fnConsoleLog('render->ERROR', e); fnConsoleLog('render->ERROR', e);
// eslint-disable-next-line // eslint-disable-next-line
pdfRef.current.innerHTML = `<h1>ERROR RENDERING PDF</h1><br /><p>${e.toString()}</p>`; pdfRef.current.innerHTML = `<h1>ERROR RENDERING PDF</h1><br /><p>${e.toString()}</p>`;

@ -17,9 +17,11 @@
export interface BeginTxResponse { export interface BeginTxResponse {
tx: string; tx: string;
locked: boolean; locked: boolean;
lockedBy?: string;
lockExpire: number; lockExpire: number;
lockedBy?: string;
lockReason?: string; lockReason?: string;
refreshToken: boolean;
resetStorage: boolean;
} }
enum HashOperation { enum HashOperation {

@ -29,37 +29,21 @@ export interface FileDataDto {
} }
export class ApiSegmentAddCommand extends ApiCallBase implements ICommand<Promise<boolean>> { export class ApiSegmentAddCommand extends ApiCallBase implements ICommand<Promise<boolean>> {
constructor(private tx: BeginTxResponse, private file: string, private data: FileDataDto) { constructor(private tx: BeginTxResponse, private file: string | Blob, private data: FileDataDto) {
super(); super();
} }
async execute(): Promise<boolean> { async execute(): Promise<boolean> {
await this.initTokenData(); await this.initTokenData();
if (!this.storeUrl) return false; if (!this.storeUrl) return false;
if (await this.hasSegment()) return this.addRef(); if (await this.hasSegment()) return true;
return await this.addSegment(); return await this.addSegment();
} }
async addRef(): Promise<boolean> {
if (!this.data.parent) return true;
const authHeaders = this.getAuthHeaders(false);
const resp = await FetchService.fetch<BeginTxResponse>(
`${this.storeUrl!}/api/v1/segment/ref/${this.tx.tx}/${this.data.hash}/${this.data.parent}`,
{
type: 'TEXT',
headers: {
...authHeaders
}
},
this.refreshParams()
);
fnConsoleLog('ApiSegmentAddCommand->addRef', resp);
return true;
}
async hasSegment(): Promise<boolean> { async hasSegment(): Promise<boolean> {
const authHeaders = this.getAuthHeaders(); const authHeaders = this.getAuthHeaders();
const params = this.data.parent ? `?parent=${this.data.parent}` : '';
const resp = await FetchService.fetch<BeginTxResponse>( const resp = await FetchService.fetch<BeginTxResponse>(
`${this.storeUrl!}/api/v1/segment/${this.data.hash}/has`, `${this.storeUrl!}/api/v1/segment/has/${this.tx.tx}/${this.data.hash}${params}`,
{ {
type: 'TEXT', type: 'TEXT',
headers: { headers: {
@ -73,7 +57,8 @@ export class ApiSegmentAddCommand extends ApiCallBase implements ICommand<Promis
async addSegment(): Promise<boolean> { async addSegment(): Promise<boolean> {
const formData = new FormData(); const formData = new FormData();
const fileData = new Blob([this.file], { type: 'application/json' }); let fileData = this.file;
if (!(this.file instanceof Blob)) fileData = new Blob([this.file], { type: 'application/json' });
formData.append('file', fileData); formData.append('file', fileData);
if (this.data.parent) formData.append('parent', this.data.parent); if (this.data.parent) formData.append('parent', this.data.parent);
formData.append('key', this.data.key); formData.append('key', this.data.key);

@ -26,7 +26,6 @@ export class SyncObjectCommand implements ICommand<Promise<void>> {
constructor(private obj: ObjDto, private hash: string, private tx: BeginTxResponse) {} constructor(private obj: ObjDto, private hash: string, private tx: BeginTxResponse) {}
async execute(): Promise<void> { async execute(): Promise<void> {
fnConsoleLog('SyncObjectCommand', this.tx);
if (this.obj.server?.id) return; if (this.obj.server?.id) return;
const resp: ObjAddResponse | ServerErrorDto = await new ApiObjAddCommand(this.obj, this.hash, this.tx).execute(); const resp: ObjAddResponse | ServerErrorDto = await new ApiObjAddCommand(this.obj, this.hash, this.tx).execute();
if ('serverId' in resp) { if ('serverId' in resp) {
@ -34,6 +33,7 @@ export class SyncObjectCommand implements ICommand<Promise<void>> {
} else if ('code' in resp && resp.code === ApiErrorCode.SYNC_DUPLICATED_HASH) { } else if ('code' in resp && resp.code === ApiErrorCode.SYNC_DUPLICATED_HASH) {
return await this.setByHash(); return await this.setByHash();
} }
fnConsoleLog('SyncObjectCommand', 'tx', this.tx, 'resp', resp);
throw new Error('PROBLEM !!!!!!!!!!!!!!!'); throw new Error('PROBLEM !!!!!!!!!!!!!!!');
} }

@ -14,20 +14,43 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { BrowserStorage } from '@pinmenote/browser-api';
import { ICommand } from '../../../../common/model/shared/common.dto'; import { ICommand } from '../../../../common/model/shared/common.dto';
import { ObjDto } from '../../../../common/model/obj/obj.dto'; import { ObjDto } from '../../../../common/model/obj/obj.dto';
import { ObjPageNoteDto } from '../../../../common/model/obj/obj-note.dto'; import { ObjPageNoteDto } from '../../../../common/model/obj/obj-note.dto';
import { SyncObjectCommand } from './sync-object.command'; import { SyncObjectCommand } from './sync-object.command';
import { SyncObjectStatus } from '../sync.model'; import { SyncHashType, SyncObjectStatus } from '../sync.model';
import { fnConsoleLog } from '../../../../common/fn/fn-console'; import { fnConsoleLog } from '../../../../common/fn/fn-console';
import { BeginTxResponse } from '../../api/store/api-store.model'; import { BeginTxResponse } from '../../api/store/api-store.model';
import { ObjectStoreKeys } from '../../../../common/keys/object.store.keys';
import { ApiSegmentAddCommand } from '../../api/store/segment/api-segment-add.command';
const TEMP_KEY = 'foo';
export class SyncPageNoteCommand implements ICommand<Promise<SyncObjectStatus>> { export class SyncPageNoteCommand implements ICommand<Promise<SyncObjectStatus>> {
constructor(private obj: ObjDto<ObjPageNoteDto>, private tx: BeginTxResponse) {} constructor(private obj: ObjDto<ObjPageNoteDto>, private tx: BeginTxResponse) {}
async execute(): Promise<SyncObjectStatus> { async execute(): Promise<SyncObjectStatus> {
fnConsoleLog('SyncPageNoteCommand');
const data = this.obj.data; const data = this.obj.data;
await new SyncObjectCommand(this.obj, data.hash, this.tx).execute(); await new SyncObjectCommand(this.obj, data.hash, this.tx).execute();
return SyncObjectStatus.SERVER_ERROR;
await this.syncNote(data);
return SyncObjectStatus.OK;
}
private async syncNote(data: ObjPageNoteDto): Promise<void> {
const content = JSON.stringify(data);
await new ApiSegmentAddCommand(this.tx, content, {
hash: data.hash,
parent: data.hash,
type: SyncHashType.ObjPdfDataDto,
key: TEMP_KEY
}).execute();
if (data.prev) {
const prevData = await BrowserStorage.get<ObjPageNoteDto>(`${ObjectStoreKeys.NOTE_HASH}:${data.prev}`);
fnConsoleLog('SyncPageNoteCommand->prev', data.prev, 'data', prevData);
await this.syncNote(prevData);
}
} }
} }

@ -16,18 +16,50 @@
*/ */
import { ICommand } from '../../../../common/model/shared/common.dto'; import { ICommand } from '../../../../common/model/shared/common.dto';
import { ObjDto } from '../../../../common/model/obj/obj.dto'; import { ObjDto } from '../../../../common/model/obj/obj.dto';
import { ObjPdfDto } from '../../../../common/model/obj/obj-pdf.dto'; import { ObjPdfDataDto, ObjPdfDto } from '../../../../common/model/obj/obj-pdf.dto';
import { SyncObjectCommand } from './sync-object.command'; import { SyncObjectCommand } from './sync-object.command';
import { SyncObjectStatus } from '../sync.model'; import { SyncHashType, SyncObjectStatus } from '../sync.model';
import { fnConsoleLog } from '../../../../common/fn/fn-console'; import { fnConsoleLog } from '../../../../common/fn/fn-console';
import { BeginTxResponse } from '../../api/store/api-store.model'; import { BeginTxResponse } from '../../api/store/api-store.model';
import { ObjectStoreKeys } from '../../../../common/keys/object.store.keys';
import { BrowserStorage } from '@pinmenote/browser-api';
import { fnB64toBlob } from '../../../../common/fn/fn-b64-to-blob';
import { ApiSegmentAddCommand } from '../../api/store/segment/api-segment-add.command';
const TEMP_KEY = 'foo';
export class SyncPdfCommand implements ICommand<Promise<SyncObjectStatus>> { export class SyncPdfCommand implements ICommand<Promise<SyncObjectStatus>> {
constructor(private obj: ObjDto<ObjPdfDto>, private tx: BeginTxResponse) {} constructor(private obj: ObjDto<ObjPdfDto>, private tx: BeginTxResponse) {}
async execute(): Promise<SyncObjectStatus> { async execute(): Promise<SyncObjectStatus> {
fnConsoleLog('SyncPdfCommand');
const data = this.obj.data; const data = this.obj.data;
await new SyncObjectCommand(this.obj, data.hash, this.tx).execute(); await new SyncObjectCommand(this.obj, data.hash, this.tx).execute();
return SyncObjectStatus.SERVER_ERROR;
await this.syncPdf(data.hash);
await this.syncData(data.data, data.hash);
return SyncObjectStatus.OK;
}
private async syncData(data: ObjPdfDataDto, parent: string): Promise<void> {
const content = JSON.stringify(data);
await new ApiSegmentAddCommand(this.tx, content, {
hash: data.hash,
parent,
type: SyncHashType.ObjPdfDataDto,
key: TEMP_KEY
}).execute();
}
private async syncPdf(parent: string): Promise<void> {
const pdfData = await BrowserStorage.get<string | undefined>(`${ObjectStoreKeys.PDF_DATA}:${parent}`);
if (!pdfData) return;
const pdfBlob = fnB64toBlob(pdfData);
fnConsoleLog('SyncPdfCommand->syncPdf->blob', pdfBlob);
await new ApiSegmentAddCommand(this.tx, pdfBlob, {
hash: parent,
parent,
type: SyncHashType.ObjPdf,
key: TEMP_KEY
}).execute();
} }
} }

@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { SegmentPage, SegmentType } from '@pinmenote/page-compute'; import { SegmentPage, SegmentType, SegmentImg } from '@pinmenote/page-compute';
import { ICommand } from '../../../../common/model/shared/common.dto'; import { ICommand } from '../../../../common/model/shared/common.dto';
import { ObjDto } from '../../../../common/model/obj/obj.dto'; import { ObjDto } from '../../../../common/model/obj/obj.dto';
import { ObjPageDto } from '../../../../common/model/obj/obj-page.dto'; import { ObjPageDto } from '../../../../common/model/obj/obj-page.dto';
@ -25,6 +25,7 @@ import { fnConsoleLog } from '../../../../common/fn/fn-console';
import { BeginTxResponse } from '../../api/store/api-store.model'; import { BeginTxResponse } from '../../api/store/api-store.model';
import { PageSnapshotDto } from '../../../../common/model/obj/page-snapshot.dto'; import { PageSnapshotDto } from '../../../../common/model/obj/page-snapshot.dto';
import { ApiSegmentAddCommand } from '../../api/store/segment/api-segment-add.command'; import { ApiSegmentAddCommand } from '../../api/store/segment/api-segment-add.command';
import { fnB64toBlob } from '../../../../common/fn/fn-b64-to-blob';
const TEMP_KEY = 'foo'; const TEMP_KEY = 'foo';
@ -42,7 +43,7 @@ export class SyncSnapshotCommand implements ICommand<Promise<SyncObjectStatus>>
await this.syncSnapshot(snapshot, snapshot.hash); await this.syncSnapshot(snapshot, snapshot.hash);
// TODO await this.syncComments(page.comments, snapshot.hash); // TODO await this.syncComments(page.comments, snapshot.hash);
if (!snapshot.segment) { if (!snapshot.segment) {
fnConsoleLog('SyncSnapshotCommand->OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO', snapshot.segment, this.obj); fnConsoleLog('SyncSnapshotCommand->!!!!!!!!!!!!1SEGMENT->EMPTY', snapshot.segment, this.obj);
return SyncObjectStatus.OK; return SyncObjectStatus.OK;
} }
await this.syncSegment(snapshot.segment, snapshot.hash); await this.syncSegment(snapshot.segment, snapshot.hash);
@ -73,14 +74,25 @@ export class SyncSnapshotCommand implements ICommand<Promise<SyncObjectStatus>>
private async syncSegment(hash: string, parent: string) { private async syncSegment(hash: string, parent: string) {
const segment = await new PageSegmentGetCommand(hash).execute(); const segment = await new PageSegmentGetCommand(hash).execute();
if (!segment) return; if (!segment) return;
let content: string | Blob | undefined;
if (segment.type === (3 as SegmentType)) return;
if (segment.type == SegmentType.IMG) {
const src = (segment.content as SegmentImg).src;
if (src.startsWith('data:image/svg') || src === 'data:') {
content = src;
} else {
content = fnB64toBlob(src);
}
} else {
content = JSON.stringify(segment.content);
}
const isSynchronized = await new ApiSegmentAddCommand(this.tx, JSON.stringify(segment), { await new ApiSegmentAddCommand(this.tx, content, {
hash, hash,
parent, parent,
type: this.convertSegmentTypeSyncHashType(segment.type), type: this.convertSegmentTypeSyncHashType(segment.type),
key: TEMP_KEY key: TEMP_KEY
}).execute(); }).execute();
if (isSynchronized) return;
switch (segment.type) { switch (segment.type) {
case SegmentType.SNAPSHOT: { case SegmentType.SNAPSHOT: {
@ -93,12 +105,11 @@ export class SyncSnapshotCommand implements ICommand<Promise<SyncObjectStatus>>
} }
break; break;
} }
case 3 as SegmentType: // FIXME - remove later - SHADOW - obsolete - no longer exists
case SegmentType.CSS: case SegmentType.CSS:
case SegmentType.IMG: { case SegmentType.IMG: {
break; break;
} }
case 3 as SegmentType: // FIXME - remove later - SHADOW - obsolete - no longer exists
return;
case SegmentType.IFRAME: { case SegmentType.IFRAME: {
const content = segment.content as SegmentPage; const content = segment.content as SegmentPage;
for (const css of content.css) { for (const css of content.css) {
@ -126,6 +137,7 @@ export class SyncSnapshotCommand implements ICommand<Promise<SyncObjectStatus>>
case SegmentType.SNAPSHOT: case SegmentType.SNAPSHOT:
return SyncHashType.Snapshot; return SyncHashType.Snapshot;
default: default:
fnConsoleLog('convertSegmentTypeSyncHashType', type);
throw new Error('PROBLEM !!!!!!!!!!!!!!!!!!!!'); throw new Error('PROBLEM !!!!!!!!!!!!!!!!!!!!');
} }
} }

@ -85,6 +85,9 @@ export class SyncResetProgressCommand implements ICommand<Promise<void>> {
}); });
await this.setList(yearMonth, newList); await this.setList(yearMonth, newList);
} }
// clear tx
await BrowserStorage.remove(ObjectStoreKeys.SYNC_TX);
fnConsoleLog('SyncResetProgressCommand->complete in ', Date.now() - a); fnConsoleLog('SyncResetProgressCommand->complete in ', Date.now() - a);
} }

@ -79,7 +79,7 @@ export class SyncIndexCommand implements ICommand<Promise<SyncObjectStatus>> {
break; break;
} }
default: { default: {
fnConsoleLog('SyncObjectCommand->PROBLEM', obj.type, 'index', this.index); fnConsoleLog('SyncObjectCommand->PROBLEM', obj, 'index', this.index);
break; break;
} }
} }

@ -29,7 +29,7 @@ export class SyncMonthCommand implements ICommand<Promise<SyncIndex>> {
const indexListKey = `${ObjectStoreKeys.UPDATED_DT}:${this.yearMonth}`; const indexListKey = `${ObjectStoreKeys.UPDATED_DT}:${this.yearMonth}`;
const indexList = await SyncTxHelper.getList(indexListKey); const indexList = await SyncTxHelper.getList(indexListKey);
fnConsoleLog('SyncMonthCommand->syncList', indexList); fnConsoleLog('SyncMonthCommand->syncList', this.yearMonth, 'size', indexList.length);
if (indexList.length === 0) if (indexList.length === 0)
return { dt: this.progress.timestamp, id: this.progress.id, status: SyncObjectStatus.EMPTY_LIST }; return { dt: this.progress.timestamp, id: this.progress.id, status: SyncObjectStatus.EMPTY_LIST };
@ -64,8 +64,8 @@ export class SyncMonthCommand implements ICommand<Promise<SyncIndex>> {
} }
if ([SyncObjectStatus.INDEX_NOT_EXISTS, SyncObjectStatus.OBJECT_NOT_EXISTS].includes(status)) { if ([SyncObjectStatus.INDEX_NOT_EXISTS, SyncObjectStatus.OBJECT_NOT_EXISTS].includes(status)) {
fnConsoleLog('syncIndex->PROBLEM !!!!!!!!!!!!!!!!!!!!!!!!', status, 'index', index); fnConsoleLog('syncIndex->PROBLEM !!!!!!!!!!!!!!!!!!!!!!!!', status, 'index', index);
await SyncTxHelper.commit(); // await SyncTxHelper.commit();
throw new Error(`Status ERROR ${status}`); // throw new Error(`Status ERROR ${status}`);
} }
} }

@ -61,7 +61,7 @@ export class SyncServerCommand implements ICommand<Promise<void>> {
} }
dt.setMonth(dt.getMonth() + 1); dt.setMonth(dt.getMonth() + 1);
fnConsoleLog('sync dt', dt, 'lastDay', lastDay, 'syncResult', syncResult); // fnConsoleLog('sync dt', dt, 'lastDay', lastDay, 'syncResult', syncResult);
// reset id so we start next month from 0 // reset id so we start next month from 0
await new SyncSetProgressCommand({ await new SyncSetProgressCommand({

@ -36,5 +36,8 @@ export enum SyncHashType {
IFrame = '3', IFrame = '3',
Img = '4', Img = '4',
Css = '5', Css = '5',
Snapshot = '6' Snapshot = '6',
ObjPdfDataDto = '7',
ObjPdf = '8',
ObjPageNoteDto = '9'
} }