Добавлено меню - всё прочитано
This commit is contained in:
parent
0dc7e0c4ad
commit
f08ff88cb9
5 changed files with 112 additions and 1 deletions
|
|
@ -1,7 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as KB from './kanban-board';
|
import * as KB from './kanban-board';
|
||||||
import { IPageStore } from './store';
|
import { IPageStore, PageStoreLoadData } from './store';
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import * as TopRightMenuNs from '../misc-components/top-right-menu';
|
||||||
|
import { SetIssuesReadingTimestamp } from '../utils/unreaded-provider';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
store: IPageStore
|
store: IPageStore
|
||||||
|
|
@ -19,8 +21,17 @@ export const KanbanBoards = observer((props: Props) => {
|
||||||
const board = <KB.KanbanBoard store={boardData} key={key} />;
|
const board = <KB.KanbanBoard store={boardData} key={key} />;
|
||||||
list.push(board);
|
list.push(board);
|
||||||
}
|
}
|
||||||
|
const topRightMenuStore = TopRightMenuNs.Store.create({visible: false});
|
||||||
|
const onAllReadClick = (e: React.MouseEvent) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
SetIssuesReadingTimestamp(props.store.issueIds);
|
||||||
|
PageStoreLoadData(props.store);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<TopRightMenuNs.TopRightMenu store={topRightMenuStore}>
|
||||||
|
<button onClick={onAllReadClick}>Всё прочитано</button>
|
||||||
|
</TopRightMenuNs.TopRightMenu>
|
||||||
{list}
|
{list}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,26 @@ export const PageStore = types.model({
|
||||||
self.loaded = true;
|
self.loaded = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}).views((self) => {
|
||||||
|
return {
|
||||||
|
get issueIds(): number[] {
|
||||||
|
if (!self.data) return [];
|
||||||
|
const res = [] as number[];
|
||||||
|
for (let i = 0; i < self.data.length; i++) {
|
||||||
|
const iData = self.data[i];
|
||||||
|
for (let j = 0; j < iData.data.length; j++) {
|
||||||
|
const jData = iData.data[j];
|
||||||
|
for (let k = 0; k < jData.issues.length; k++) {
|
||||||
|
const issue = jData.issues[k];
|
||||||
|
if (res.indexOf(issue.id) < 0) {
|
||||||
|
res.push(issue.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export async function PageStoreLoadData(store: IPageStore): Promise<void> {
|
export async function PageStoreLoadData(store: IPageStore): Promise<void> {
|
||||||
|
|
|
||||||
16
frontend/src/misc-components/top-right-menu.module.css
Normal file
16
frontend/src/misc-components/top-right-menu.module.css
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
.menuButton {
|
||||||
|
position: fixed;
|
||||||
|
width: 45px;
|
||||||
|
height: 25px;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border: 1px solid #000000;
|
||||||
|
position: fixed;
|
||||||
|
top: 25px;
|
||||||
|
left: 0px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
55
frontend/src/misc-components/top-right-menu.tsx
Normal file
55
frontend/src/misc-components/top-right-menu.tsx
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import { Instance, types } from 'mobx-state-tree';
|
||||||
|
import React from 'react';
|
||||||
|
import Css from './top-right-menu.module.css';
|
||||||
|
|
||||||
|
export const Store = types.model({
|
||||||
|
visible: types.boolean
|
||||||
|
}).views((self) => {
|
||||||
|
return {
|
||||||
|
get style(): React.CSSProperties {
|
||||||
|
return {
|
||||||
|
display: self.visible ? 'block' : 'none'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}).actions((self) => {
|
||||||
|
return {
|
||||||
|
show: () => {
|
||||||
|
self.visible = true;
|
||||||
|
},
|
||||||
|
hide: () => {
|
||||||
|
self.visible = false;
|
||||||
|
},
|
||||||
|
toggle: () => {
|
||||||
|
self.visible = !self.visible;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Props = {
|
||||||
|
store: Instance<typeof Store>;
|
||||||
|
children?: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TopRightMenu = observer((props: Props): JSX.Element => {
|
||||||
|
const menuItems = [];
|
||||||
|
if (props.children.length > 1) {
|
||||||
|
for (let key = 0; key < props.children.length; key++) {
|
||||||
|
const item = props.children[key];
|
||||||
|
menuItems.push(<li key={key}>{item}</li>);
|
||||||
|
}
|
||||||
|
} else if (props.children) {
|
||||||
|
menuItems.push(<li key={0}>{props.children}</li>)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button className={Css.menuButton} onClick={(e) => {e.stopPropagation(); props.store.toggle();}}>Menu</button>
|
||||||
|
<div className={Css.menu} style={props.store.style}>
|
||||||
|
<ul>
|
||||||
|
{menuItems}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
|
@ -9,6 +9,15 @@ export function SetIssueReadingTimestamp(issueId: number): number {
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function SetIssuesReadingTimestamp(issueIds: number[]): number {
|
||||||
|
const now = (new Date()).getTime();
|
||||||
|
for (let i = 0; i < issueIds.length; i++) {
|
||||||
|
const issueId = issueIds[i];
|
||||||
|
window.localStorage.setItem(getKey(issueId), String(now));
|
||||||
|
}
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
|
||||||
function getKey(issueId: number): string {
|
function getKey(issueId: number): string {
|
||||||
return `issue_read_${issueId}`;
|
return `issue_read_${issueId}`;
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue