feat(ui): add notes store
This commit is contained in:
parent
d1a325c413
commit
266a0bef7e
7 changed files with 209 additions and 88 deletions
|
|
@ -2,17 +2,16 @@ import React from 'react';
|
|||
import SessionList from './components/SessionList';
|
||||
import SessionHeader from './components/SessionHeader';
|
||||
import NotesList from './components/Notes/NoteList';
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
function SessionListContainer() {
|
||||
function SessionListContainer({ activeTab }: { activeTab: string }) {
|
||||
return (
|
||||
<div className="widget-wrapper">
|
||||
<SessionHeader />
|
||||
<div className="border-b" />
|
||||
{/* <SessionList /> */}
|
||||
<NotesList />
|
||||
|
||||
{activeTab !== 'notes' ? <SessionList /> : <NotesList />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionListContainer;
|
||||
export default connect(state => ({ activeTab: state.getIn(['search', 'activeTab', 'type'])}))(SessionListContainer);
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ enum Tags {
|
|||
|
||||
interface Props {
|
||||
author: string
|
||||
date: string
|
||||
tag: Tags
|
||||
timestamp: number
|
||||
tags: string[]
|
||||
isPrivate: boolean
|
||||
description: string
|
||||
sessionId: string
|
||||
|
|
@ -25,10 +25,10 @@ function NoteItem(props: Props) {
|
|||
<div className="flex flex-col">
|
||||
<div>{props.description}</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div>{props.tag}</div>
|
||||
<div>{props.tags}</div>
|
||||
<div className='text-disabled-text flex items-center'>
|
||||
<span className="text-figmaColors-text-primary mr-1">By </span>
|
||||
{props.author}, {props.date}
|
||||
{props.author}, {props.timestamp}
|
||||
{props.isPrivate ? null : (
|
||||
<>
|
||||
<Icon name="user-friends" className="ml-4 mr-1" color="gray-dark" /> Team
|
||||
|
|
|
|||
|
|
@ -2,37 +2,20 @@ import React from 'react';
|
|||
import { NoContent, Pagination, Icon } from 'UI';
|
||||
import { sliceListPerPage } from 'App/utils';
|
||||
import NoteItem from './NoteItem';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
||||
//{ siteId }: { siteId: string }
|
||||
function NotesList() {
|
||||
const list = [
|
||||
{
|
||||
author: 'nikita@openreplay.com',
|
||||
date: 'Today, 12.00PM',
|
||||
tag: 1,
|
||||
isPrivate: true,
|
||||
description: 'Testing private note stuff bla bla bla',
|
||||
sessionId: '123123123',
|
||||
id: 2,
|
||||
},
|
||||
{
|
||||
author: 'sasha@openreplay.com',
|
||||
date: 'Tomorrow, 12.00PM',
|
||||
tag: 0,
|
||||
isPrivate: false,
|
||||
description: 'Not Testing team note stuff bla bla bla',
|
||||
sessionId: '123123123',
|
||||
id: 1,
|
||||
},
|
||||
];
|
||||
const { notesStore } = useStore()
|
||||
|
||||
const store = {
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
// @ts-ignore
|
||||
updateKey: (a, b) => 1,
|
||||
};
|
||||
React.useEffect(() => {
|
||||
if (!notesStore.notes.length) {
|
||||
notesStore.fetchNotes()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const list = notesStore.notes
|
||||
console.log(list)
|
||||
return (
|
||||
<NoContent
|
||||
show={list.length === 0}
|
||||
|
|
@ -44,15 +27,15 @@ function NotesList() {
|
|||
}
|
||||
>
|
||||
<div className="mt-3 border-b rounded bg-white">
|
||||
{sliceListPerPage(list, store.page - 1, store.pageSize).map((note) => (
|
||||
<React.Fragment key={note.id}>
|
||||
{sliceListPerPage(list, notesStore.page - 1, notesStore.pageSize).map(note => (
|
||||
<React.Fragment key={note.noteId}>
|
||||
<NoteItem
|
||||
author={note.author}
|
||||
tag={note.tag}
|
||||
date={note.date}
|
||||
isPrivate={note.isPrivate}
|
||||
description={note.description}
|
||||
sessionId={note.sessionId}
|
||||
tags={note.tags}
|
||||
timestamp={note.timestamp}
|
||||
isPrivate={note.isPublic}
|
||||
description={note.message}
|
||||
sessionId={'123123'} // note.sessionId
|
||||
/>
|
||||
</React.Fragment>
|
||||
))}
|
||||
|
|
@ -60,14 +43,14 @@ function NotesList() {
|
|||
|
||||
<div className="w-full flex items-center justify-between pt-4 px-6">
|
||||
<div className="text-disabled-text">
|
||||
Showing <span className="font-semibold">{Math.min(list.length, store.pageSize)}</span> out
|
||||
Showing <span className="font-semibold">{Math.min(list.length, notesStore.pageSize)}</span> out
|
||||
of <span className="font-semibold">{list.length}</span> notes
|
||||
</div>
|
||||
<Pagination
|
||||
page={store.page}
|
||||
totalPages={Math.ceil(list.length / store.pageSize)}
|
||||
onPageChange={(page) => store.updateKey('page', page)}
|
||||
limit={store.pageSize}
|
||||
page={notesStore.page}
|
||||
totalPages={Math.ceil(list.length / notesStore.pageSize)}
|
||||
onPageChange={(page) => notesStore.changePage(page)}
|
||||
limit={notesStore.pageSize}
|
||||
debounceRequest={100}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -75,4 +58,4 @@ function NotesList() {
|
|||
);
|
||||
}
|
||||
|
||||
export default NotesList;
|
||||
export default observer(NotesList);
|
||||
|
|
|
|||
|
|
@ -5,56 +5,67 @@ import UserStore from './userStore';
|
|||
import RoleStore from './roleStore';
|
||||
import APIClient from 'App/api_client';
|
||||
import FunnelStore from './funnelStore';
|
||||
import { dashboardService, metricService, sessionService, userService, auditService, funnelService, errorService } from 'App/services';
|
||||
import {
|
||||
dashboardService,
|
||||
metricService,
|
||||
sessionService,
|
||||
userService,
|
||||
auditService,
|
||||
funnelService,
|
||||
errorService,
|
||||
notesService,
|
||||
} from 'App/services';
|
||||
import SettingsStore from './settingsStore';
|
||||
import AuditStore from './auditStore';
|
||||
import NotificationStore from './notificationStore';
|
||||
import ErrorStore from './errorStore';
|
||||
import SessionStore from './sessionStore';
|
||||
import NotesStore from './notesStore';
|
||||
|
||||
export class RootStore {
|
||||
dashboardStore: DashboardStore;
|
||||
metricStore: MetricStore;
|
||||
funnelStore: FunnelStore;
|
||||
settingsStore: SettingsStore;
|
||||
userStore: UserStore;
|
||||
roleStore: RoleStore;
|
||||
auditStore: AuditStore;
|
||||
errorStore: ErrorStore;
|
||||
notificationStore: NotificationStore
|
||||
sessionStore: SessionStore;
|
||||
dashboardStore: DashboardStore;
|
||||
metricStore: MetricStore;
|
||||
funnelStore: FunnelStore;
|
||||
settingsStore: SettingsStore;
|
||||
userStore: UserStore;
|
||||
roleStore: RoleStore;
|
||||
auditStore: AuditStore;
|
||||
errorStore: ErrorStore;
|
||||
notificationStore: NotificationStore;
|
||||
sessionStore: SessionStore;
|
||||
notesStore: NotesStore;
|
||||
|
||||
constructor() {
|
||||
this.dashboardStore = new DashboardStore();
|
||||
this.metricStore = new MetricStore();
|
||||
this.funnelStore = new FunnelStore();
|
||||
this.settingsStore = new SettingsStore();
|
||||
this.userStore = new UserStore();
|
||||
this.roleStore = new RoleStore();
|
||||
this.auditStore = new AuditStore();
|
||||
this.errorStore = new ErrorStore();
|
||||
this.notificationStore = new NotificationStore();
|
||||
this.sessionStore = new SessionStore();
|
||||
}
|
||||
constructor() {
|
||||
this.dashboardStore = new DashboardStore();
|
||||
this.metricStore = new MetricStore();
|
||||
this.funnelStore = new FunnelStore();
|
||||
this.settingsStore = new SettingsStore();
|
||||
this.userStore = new UserStore();
|
||||
this.roleStore = new RoleStore();
|
||||
this.auditStore = new AuditStore();
|
||||
this.errorStore = new ErrorStore();
|
||||
this.notificationStore = new NotificationStore();
|
||||
this.sessionStore = new SessionStore();
|
||||
this.notesStore = new NotesStore();
|
||||
}
|
||||
|
||||
initClient() {
|
||||
const client = new APIClient();
|
||||
dashboardService.initClient(client)
|
||||
metricService.initClient(client)
|
||||
funnelService.initClient(client)
|
||||
sessionService.initClient(client)
|
||||
userService.initClient(client)
|
||||
auditService.initClient(client)
|
||||
errorService.initClient(client)
|
||||
}
|
||||
initClient() {
|
||||
const client = new APIClient();
|
||||
dashboardService.initClient(client);
|
||||
metricService.initClient(client);
|
||||
funnelService.initClient(client);
|
||||
sessionService.initClient(client);
|
||||
userService.initClient(client);
|
||||
auditService.initClient(client);
|
||||
errorService.initClient(client);
|
||||
notesService.initClient(client)
|
||||
}
|
||||
}
|
||||
|
||||
const StoreContext = React.createContext<RootStore>({} as RootStore);
|
||||
|
||||
export const StoreProvider = ({ children, store }: any) => {
|
||||
return (
|
||||
<StoreContext.Provider value={store}>{children}</StoreContext.Provider>
|
||||
);
|
||||
return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
|
||||
};
|
||||
|
||||
export const useStore = () => React.useContext(StoreContext);
|
||||
|
|
|
|||
72
frontend/app/mstore/notesStore.ts
Normal file
72
frontend/app/mstore/notesStore.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import { makeAutoObservable } from "mobx"
|
||||
import { notesService } from "App/services"
|
||||
import { Note } from 'App/services/NotesService'
|
||||
|
||||
interface SessionNotes {
|
||||
[sessionId: string]: Note[]
|
||||
}
|
||||
|
||||
export default class NotesStore {
|
||||
notes: Note[] = []
|
||||
sessionNotes: SessionNotes
|
||||
loading: boolean
|
||||
page = 1
|
||||
pageSize = 15
|
||||
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
|
||||
async fetchNotes() {
|
||||
this.loading = true
|
||||
try {
|
||||
const notes = await notesService.getNotes()
|
||||
this.notes = notes;
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
async fetchSessionNotes(sessionId: string) {
|
||||
this.loading = true
|
||||
try {
|
||||
const notes = await notesService.getNotesBySessionId(sessionId)
|
||||
this.sessionNotes[sessionId] = notes
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
async addNote(sessionId: string, note: Note) {
|
||||
this.loading = true
|
||||
try {
|
||||
const addedNote = await notesService.addNote(sessionId, note)
|
||||
return addedNote
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
async deleteNote(noteId: string) {
|
||||
this.loading = true
|
||||
try {
|
||||
const deleted = await notesService.deleteNote(noteId)
|
||||
return deleted
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
changePage(page: number) {
|
||||
this.page = page
|
||||
}
|
||||
}
|
||||
54
frontend/app/services/NotesService.ts
Normal file
54
frontend/app/services/NotesService.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
|
||||
import APIClient from 'App/api_client';
|
||||
|
||||
export interface Note {
|
||||
message: string
|
||||
tags: string[]
|
||||
isPublic: boolean
|
||||
timestamp: number
|
||||
noteId?: string
|
||||
author?: string
|
||||
}
|
||||
|
||||
export default class NotesService {
|
||||
private client: APIClient;
|
||||
|
||||
constructor(client?: APIClient) {
|
||||
this.client = client ? client : new APIClient();
|
||||
}
|
||||
|
||||
initClient(client?: APIClient) {
|
||||
this.client = client || new APIClient();
|
||||
}
|
||||
|
||||
getNotes(): Promise<Note[]> {
|
||||
return this.client.get('/notes').then(r => {
|
||||
if (r.ok) {
|
||||
return r.json()
|
||||
} else {
|
||||
throw new Error('Error getting notes: ' + r.status)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getNotesBySessionId(sessionID: string): Promise<Note[]> {
|
||||
return this.client.get(`/sessions/${sessionID}/notes`)
|
||||
.then(r => r.json())
|
||||
}
|
||||
|
||||
addNote(sessionID: string, note: Note): Promise<Note> {
|
||||
return this.client.post(`/sessions/${sessionID}/notes`, note)
|
||||
.then(r => r.json())
|
||||
}
|
||||
|
||||
updateNote(noteID: string, note: Note): Promise<Note> {
|
||||
return this.client.post(`/notes/${noteID}`, note)
|
||||
.then(r => r.json())
|
||||
}
|
||||
|
||||
deleteNote(noteID: string) {
|
||||
return this.client.delete(`/notes/${noteID}`)
|
||||
.then(r => r.json())
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
import DashboardService, { IDashboardService } from "./DashboardService";
|
||||
import MetricService, { IMetricService } from "./MetricService";
|
||||
import FunnelService, { IFunnelService } from "./FunnelService";
|
||||
import DashboardService from "./DashboardService";
|
||||
import MetricService from "./MetricService";
|
||||
import FunnelService from "./FunnelService";
|
||||
import SessionSerivce from "./SessionService";
|
||||
import UserService from "./UserService";
|
||||
import AuditService from './AuditService';
|
||||
import ErrorService from "./ErrorService";
|
||||
import NotesService from "./NotesService";
|
||||
|
||||
export const dashboardService = new DashboardService();
|
||||
export const metricService = new MetricService();
|
||||
|
|
@ -13,3 +14,4 @@ export const userService = new UserService();
|
|||
export const funnelService = new FunnelService();
|
||||
export const auditService = new AuditService();
|
||||
export const errorService = new ErrorService();
|
||||
export const notesService = new NotesService();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue