feat: hashtags same interface across all dto objects
This commit is contained in:
parent
b938e9fb78
commit
9e6b30d35f
@ -35,6 +35,11 @@ export interface SettingsConfig {
|
||||
skipCssImageSizeMB: number;
|
||||
expertMode: boolean;
|
||||
history: SettingsHistoryConfig;
|
||||
interface: SettingsInterfaceConfig;
|
||||
}
|
||||
|
||||
interface SettingsInterfaceConfig {
|
||||
optionsLeftSidebarOpen: boolean;
|
||||
}
|
||||
|
||||
interface EnvironmentConfig {
|
||||
@ -64,6 +69,9 @@ export const environmentConfig: EnvironmentConfig = {
|
||||
pinDraw: true,
|
||||
pageComment: true,
|
||||
pageNote: true
|
||||
},
|
||||
interface: {
|
||||
optionsLeftSidebarOpen: false
|
||||
}
|
||||
},
|
||||
objListLimit: parseInt(process.env.OBJ_LIST_LIMIT || '100000')
|
||||
|
@ -14,8 +14,13 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export interface ObjHashtagable {
|
||||
hashtags?: ObjHashtagList;
|
||||
}
|
||||
|
||||
export interface ObjHashtagList {
|
||||
hashtags: ObjHashtag[];
|
||||
data: ObjHashtag[];
|
||||
hash: string;
|
||||
}
|
||||
|
||||
|
@ -15,11 +15,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { ObjUrlDto } from './obj.dto';
|
||||
import { ObjHashtagable } from './obj-hashtag.dto';
|
||||
export interface ObjPageNoteDto extends ObjNoteDto {
|
||||
url: ObjUrlDto;
|
||||
}
|
||||
|
||||
export interface ObjNoteDto {
|
||||
export interface ObjNoteDto extends ObjHashtagable {
|
||||
hash: string;
|
||||
prev?: string;
|
||||
data: ObjNoteDataDto;
|
||||
@ -29,5 +30,4 @@ export interface ObjNoteDataDto {
|
||||
title: string;
|
||||
description: string;
|
||||
words: string[];
|
||||
hashtags?: string[];
|
||||
}
|
||||
|
@ -16,8 +16,9 @@
|
||||
*/
|
||||
import { ObjCommentListDto } from './obj-comment.dto';
|
||||
import { PageSnapshotDto } from './page-snapshot.dto';
|
||||
import { ObjHashtagable } from './obj-hashtag.dto';
|
||||
|
||||
export interface ObjPageDto {
|
||||
export interface ObjPageDto extends ObjHashtagable {
|
||||
snapshot: PageSnapshotDto;
|
||||
comments: ObjCommentListDto;
|
||||
}
|
||||
|
@ -15,8 +15,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { ObjUrlDto } from './obj.dto';
|
||||
import { ObjHashtagable } from './obj-hashtag.dto';
|
||||
|
||||
export interface ObjPdfDto {
|
||||
export interface ObjPdfDto extends ObjHashtagable {
|
||||
hash: string;
|
||||
data: ObjPdfDataDto;
|
||||
}
|
||||
@ -25,6 +26,5 @@ export interface ObjPdfDataDto {
|
||||
screenshot: string;
|
||||
rawUrl: string;
|
||||
url: ObjUrlDto;
|
||||
hashtags?: string[];
|
||||
hash: string;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ export interface PageSnapshotInfoDto {
|
||||
url: ObjUrlDto;
|
||||
title: string;
|
||||
words: string[];
|
||||
hashtags?: string[];
|
||||
}
|
||||
|
||||
export interface PageSnapshotDataDto {
|
||||
|
@ -55,17 +55,14 @@ export class OptionsConvertObjectsCommand implements ICommand<Promise<void>> {
|
||||
}
|
||||
|
||||
private async convertPdf(obj: ObjDto<ObjPdfDto>) {
|
||||
delete obj.data.data['hashtags'];
|
||||
await BrowserStorage.set<ObjDto>(`${ObjectStoreKeys.OBJECT_ID}:${obj.id}`, obj);
|
||||
}
|
||||
|
||||
private async convertPageNote(obj: ObjDto<ObjPageNoteDto>) {
|
||||
delete obj.data.data['hashtags'];
|
||||
await BrowserStorage.set<ObjDto>(`${ObjectStoreKeys.OBJECT_ID}:${obj.id}`, obj);
|
||||
}
|
||||
|
||||
private async convertSnapshot(obj: ObjDto<ObjPageDto>) {
|
||||
delete obj.data.snapshot.info['hashtags'];
|
||||
await BrowserStorage.set<ObjDto>(`${ObjectStoreKeys.OBJECT_ID}:${obj.id}`, obj);
|
||||
//
|
||||
}
|
||||
|
42
src/options-ui/components/board/board-item.mediator.ts
Normal file
42
src/options-ui/components/board/board-item.mediator.ts
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 { ObjHashtag, ObjHashtagable } from '../../../common/model/obj/obj-hashtag.dto';
|
||||
import { ObjDto } from '../../../common/model/obj/obj.dto';
|
||||
import { BrowserStorage } from '@pinmenote/browser-api';
|
||||
import { BoardStore } from '../../store/board.store';
|
||||
import { ObjectStoreKeys } from '../../../common/keys/object.store.keys';
|
||||
import { fnSha256Object } from '../../../common/fn/fn-hash';
|
||||
|
||||
export class BoardItemMediator {
|
||||
static removeObject = async (obj: ObjDto, refreshCallback: () => void) => {
|
||||
if (await BoardStore.removeObj(obj)) {
|
||||
refreshCallback();
|
||||
}
|
||||
};
|
||||
|
||||
static saveTags = async (
|
||||
dto: ObjDto<ObjHashtagable>,
|
||||
newTags: ObjHashtag[],
|
||||
setNewTags: (newTags: ObjHashtag[]) => void
|
||||
) => {
|
||||
if (!dto.data.hashtags) dto.data.hashtags = { data: [], hash: '' };
|
||||
dto.data.hashtags.hash = fnSha256Object(newTags);
|
||||
dto.data.hashtags.data = newTags;
|
||||
await BrowserStorage.set<ObjDto<any>>(`${ObjectStoreKeys.OBJECT_ID}:${dto.id}`, dto);
|
||||
setNewTags(newTags);
|
||||
};
|
||||
}
|
@ -26,14 +26,15 @@ import TagIcon from '@mui/icons-material/Tag';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import dayjs from 'dayjs';
|
||||
import { SettingsStore } from '../../../store/settings.store';
|
||||
import { ObjHashtag, ObjHashtagList } from '../../../../common/model/obj/obj-hashtag.dto';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
createdAt: number;
|
||||
words: string[];
|
||||
tags: string[];
|
||||
tags: ObjHashtag[];
|
||||
url?: string;
|
||||
saveTags: (newTags: string[]) => void;
|
||||
saveTags: (newTags: ObjHashtag[]) => void;
|
||||
}
|
||||
|
||||
export const BoardItemFooter: FunctionComponent<Props> = (props) => {
|
||||
|
@ -23,6 +23,8 @@ import { ObjDto } from '../../../../common/model/obj/obj.dto';
|
||||
import { ObjPageNoteDto } from '../../../../common/model/obj/obj-note.dto';
|
||||
import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
||||
import { marked } from 'marked';
|
||||
import { fnSha256Object } from '../../../../common/fn/fn-hash';
|
||||
import { ObjHashtag } from '../../../../common/model/obj/obj-hashtag.dto';
|
||||
|
||||
interface Props {
|
||||
dto: ObjDto<ObjPageNoteDto>;
|
||||
@ -31,7 +33,7 @@ interface Props {
|
||||
|
||||
export const PageNoteElement: FunctionComponent<Props> = (props) => {
|
||||
const [edit, setEdit] = useState<boolean>(false);
|
||||
const [hashtags, setHashtags] = useState<string[]>(props.dto.data.data.hashtags || []);
|
||||
const [hashtags, setHashtags] = useState<ObjHashtag[]>(props.dto.data.hashtags?.data || []);
|
||||
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
@ -50,8 +52,10 @@ export const PageNoteElement: FunctionComponent<Props> = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleTagSave = (newTags: string[]) => {
|
||||
props.dto.data.data.hashtags = newTags;
|
||||
const handleTagSave = (newTags: ObjHashtag[]) => {
|
||||
if (!props.dto.data.hashtags) props.dto.data.hashtags = { data: [], hash: '' };
|
||||
props.dto.data.hashtags.hash = fnSha256Object(newTags);
|
||||
props.dto.data.hashtags.data = newTags;
|
||||
setHashtags(newTags);
|
||||
fnConsoleLog('PageSnapshotElement->handleTagSave->newTags', newTags);
|
||||
};
|
||||
@ -66,7 +70,7 @@ export const PageNoteElement: FunctionComponent<Props> = (props) => {
|
||||
<BoardItemFooter
|
||||
title="page note"
|
||||
saveTags={handleTagSave}
|
||||
tags={props.dto.data.data.hashtags || []}
|
||||
tags={hashtags}
|
||||
createdAt={props.dto.createdAt}
|
||||
words={props.dto.data.data.words}
|
||||
url={props.dto.data.url?.href}
|
||||
|
@ -18,10 +18,10 @@ import React, { FunctionComponent, useState } from 'react';
|
||||
import { BoardItem } from '../board/board-item';
|
||||
import { BoardItemFooter } from '../board/board-item-footer';
|
||||
import { BoardItemTitle } from '../board/board-item-title';
|
||||
import { BoardStore } from '../../../store/board.store';
|
||||
import { ObjDto } from '../../../../common/model/obj/obj.dto';
|
||||
import { ObjPageDto } from '../../../../common/model/obj/obj-page.dto';
|
||||
import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
||||
import { ObjHashtag } from '../../../../common/model/obj/obj-hashtag.dto';
|
||||
import { BoardItemMediator } from '../board-item.mediator';
|
||||
|
||||
interface Props {
|
||||
dto: ObjDto<ObjPageDto>;
|
||||
@ -30,7 +30,7 @@ interface Props {
|
||||
|
||||
export const PageSnapshotElement: FunctionComponent<Props> = (props) => {
|
||||
const [edit, setEdit] = useState<boolean>(false);
|
||||
const [hashtags, setHashtags] = useState<string[]>(props.dto.data.snapshot.info.hashtags || []);
|
||||
const [hashtags, setHashtags] = useState<ObjHashtag[]>(props.dto.data.hashtags?.data || []);
|
||||
|
||||
const handleEdit = () => {
|
||||
setEdit(true);
|
||||
@ -40,25 +40,13 @@ export const PageSnapshotElement: FunctionComponent<Props> = (props) => {
|
||||
window.location.hash = `obj/${props.dto.id}`;
|
||||
};
|
||||
|
||||
const handleRemove = async () => {
|
||||
if (await BoardStore.removeObj(props.dto)) {
|
||||
props.refreshBoardCallback();
|
||||
}
|
||||
};
|
||||
|
||||
const handleTagSave = (newTags: string[]) => {
|
||||
props.dto.data.snapshot.info.hashtags = newTags;
|
||||
setHashtags(newTags);
|
||||
fnConsoleLog('PageSnapshotElement->handleTagSave->newTags', newTags);
|
||||
};
|
||||
|
||||
return (
|
||||
<BoardItem>
|
||||
<BoardItemTitle
|
||||
title={props.dto.data.snapshot.info.title}
|
||||
editCallback={handleEdit}
|
||||
htmlCallback={handleHtml}
|
||||
removeCallback={handleRemove}
|
||||
removeCallback={() => BoardItemMediator.removeObject(props.dto, props.refreshBoardCallback)}
|
||||
/>
|
||||
<img
|
||||
style={{ height: '100%', width: '100%', objectFit: 'contain', maxHeight: 220 }}
|
||||
@ -66,7 +54,7 @@ export const PageSnapshotElement: FunctionComponent<Props> = (props) => {
|
||||
/>
|
||||
<div style={{ display: 'flex', flexGrow: 1 }}></div>
|
||||
<BoardItemFooter
|
||||
saveTags={handleTagSave}
|
||||
saveTags={(newTags) => BoardItemMediator.saveTags(props.dto, newTags, setHashtags)}
|
||||
title="page snapshot"
|
||||
createdAt={props.dto.createdAt}
|
||||
tags={hashtags}
|
||||
|
@ -18,10 +18,10 @@ import React, { FunctionComponent, useState } from 'react';
|
||||
import { BoardItem } from '../board/board-item';
|
||||
import { BoardItemFooter } from '../board/board-item-footer';
|
||||
import { BoardItemTitle } from '../board/board-item-title';
|
||||
import { BoardStore } from '../../../store/board.store';
|
||||
import { ObjDto } from '../../../../common/model/obj/obj.dto';
|
||||
import { ObjPdfDto } from '../../../../common/model/obj/obj-pdf.dto';
|
||||
import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
||||
import { ObjHashtag } from '../../../../common/model/obj/obj-hashtag.dto';
|
||||
import { BoardItemMediator } from '../board-item.mediator';
|
||||
|
||||
interface Props {
|
||||
dto: ObjDto<ObjPdfDto>;
|
||||
@ -30,7 +30,7 @@ interface Props {
|
||||
|
||||
export const PdfElement: FunctionComponent<Props> = (props) => {
|
||||
const [edit, setEdit] = useState<boolean>(false);
|
||||
const [hashtags, setHashtags] = useState<string[]>(props.dto.data.data.hashtags || []);
|
||||
const [hashtags, setHashtags] = useState<ObjHashtag[]>(props.dto.data.hashtags?.data || []);
|
||||
|
||||
const a = props.dto.data.data.url.pathname.split('/');
|
||||
const title = a[a.length - 1];
|
||||
@ -43,28 +43,21 @@ export const PdfElement: FunctionComponent<Props> = (props) => {
|
||||
window.location.hash = `pdf/${props.dto.id}`;
|
||||
};
|
||||
|
||||
const handleRemove = async () => {
|
||||
if (await BoardStore.removeObj(props.dto)) {
|
||||
props.refreshBoardCallback();
|
||||
}
|
||||
};
|
||||
|
||||
const handleTagSave = (newTags: string[]) => {
|
||||
props.dto.data.data.hashtags = newTags;
|
||||
setHashtags(newTags);
|
||||
fnConsoleLog('PageSnapshotElement->handleTagSave->newTags', newTags);
|
||||
};
|
||||
|
||||
return (
|
||||
<BoardItem>
|
||||
<BoardItemTitle title={title} htmlCallback={handleHtml} editCallback={handleEdit} removeCallback={handleRemove} />
|
||||
<BoardItemTitle
|
||||
title={title}
|
||||
htmlCallback={handleHtml}
|
||||
editCallback={handleEdit}
|
||||
removeCallback={() => BoardItemMediator.removeObject(props.dto, props.refreshBoardCallback)}
|
||||
/>
|
||||
<img
|
||||
style={{ height: '100%', width: '100%', objectFit: 'contain', maxHeight: 220 }}
|
||||
src={props.dto.data.data.screenshot}
|
||||
/>
|
||||
<div style={{ display: 'flex', flexGrow: 1 }}></div>
|
||||
<BoardItemFooter
|
||||
saveTags={handleTagSave}
|
||||
saveTags={(newTags) => BoardItemMediator.saveTags(props.dto, newTags, setHashtags)}
|
||||
title="page snapshot"
|
||||
createdAt={props.dto.createdAt}
|
||||
tags={hashtags}
|
||||
|
@ -19,17 +19,17 @@ import Autocomplete from '@mui/material/Autocomplete';
|
||||
import Button from '@mui/material/Button';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import { ObjHashtag } from '../../../common/model/obj/obj-hashtag.dto';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import { fnConsoleLog } from '../../../common/fn/fn-console';
|
||||
|
||||
interface Props {
|
||||
tags: string[];
|
||||
saveCallback: (newTags: string[]) => void;
|
||||
tags: ObjHashtag[];
|
||||
saveCallback: (newTags: ObjHashtag[]) => void;
|
||||
}
|
||||
|
||||
export const TagEditor: FunctionComponent<Props> = (props) => {
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const [currentValue, setCurrentValue] = useState<string[]>([...props.tags.concat()]);
|
||||
const [currentValue, setCurrentValue] = useState<string[]>([...props.tags.map((t) => t.value)]);
|
||||
const [tagsChanged, setTagsChanged] = useState<boolean>(false);
|
||||
const [tagOptions, setTagOptions] = useState<string[] | undefined>(undefined);
|
||||
const loading = open && tagOptions === undefined;
|
||||
@ -39,12 +39,16 @@ export const TagEditor: FunctionComponent<Props> = (props) => {
|
||||
}, []);
|
||||
|
||||
const handleSave = () => {
|
||||
props.saveCallback(currentValue);
|
||||
props.saveCallback(
|
||||
currentValue.map((t) => {
|
||||
return { value: t };
|
||||
})
|
||||
);
|
||||
setTagsChanged(false);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setCurrentValue([...props.tags.concat()]);
|
||||
setCurrentValue([...props.tags.map((t) => t.value)]);
|
||||
setTagsChanged(false);
|
||||
};
|
||||
|
||||
@ -62,10 +66,8 @@ export const TagEditor: FunctionComponent<Props> = (props) => {
|
||||
open={open}
|
||||
onOpen={() => setOpen(true)}
|
||||
onChange={(event: any, newValue: string[]) => {
|
||||
const missing = newValue.filter((item) => props.tags.indexOf(item) < 0);
|
||||
fnConsoleLog('TagEditor->diff', props.tags, newValue, missing);
|
||||
missing.length > 0 ? setTagsChanged(true) : setTagsChanged(false);
|
||||
|
||||
const propTags = props.tags.map((t) => t.value).sort();
|
||||
propTags.toString() === newValue.sort().toString() ? setTagsChanged(false) : setTagsChanged(true);
|
||||
setCurrentValue(newValue);
|
||||
}}
|
||||
onClose={() => setOpen(false)}
|
||||
|
Loading…
Reference in New Issue
Block a user