diff --git a/backend/cmd/db/main.go b/backend/cmd/db/main.go
index 2b99883d2..bbdf8f7b8 100644
--- a/backend/cmd/db/main.go
+++ b/backend/cmd/db/main.go
@@ -30,7 +30,8 @@ func main() {
cfg := db.New()
// Init database
- pg := cache.NewPGCache(postgres.NewConn(cfg.Postgres, cfg.BatchQueueLimit, cfg.BatchSizeLimit, metrics), cfg.ProjectExpirationTimeoutMs)
+ pg := cache.NewPGCache(
+ postgres.NewConn(cfg.Postgres, cfg.BatchQueueLimit, cfg.BatchSizeLimit, metrics), cfg.ProjectExpirationTimeoutMs)
defer pg.Close()
// HandlersFabric returns the list of message handlers we want to be applied to each incoming message.
diff --git a/backend/internal/config/configurator/configurator.go b/backend/internal/config/configurator/configurator.go
index 5335d4a91..1b459335d 100644
--- a/backend/internal/config/configurator/configurator.go
+++ b/backend/internal/config/configurator/configurator.go
@@ -30,7 +30,13 @@ func readFile(path string) (map[string]string, error) {
res := make(map[string]string)
lines := strings.Split(string(data), "\n")
for _, line := range lines {
+ if len(line) == 0 {
+ continue
+ }
env := strings.Split(line, "=")
+ if len(env) < 2 {
+ continue
+ }
res[env[0]] = env[1]
}
return res, nil
diff --git a/backend/pkg/db/cache/cache.go b/backend/pkg/db/cache/cache.go
new file mode 100644
index 000000000..9075ae73f
--- /dev/null
+++ b/backend/pkg/db/cache/cache.go
@@ -0,0 +1,73 @@
+package cache
+
+import (
+ "log"
+ "openreplay/backend/pkg/db/postgres"
+ "openreplay/backend/pkg/db/types"
+ "sync"
+ "time"
+)
+
+type SessionMeta struct {
+ *types.Session
+ lastUse time.Time
+}
+
+type ProjectMeta struct {
+ *types.Project
+ expirationTime time.Time
+}
+
+type Cache interface {
+ SetSession(sess *types.Session)
+ HasSession(sessID uint64) bool
+ GetSession(sessionID uint64) (*types.Session, error)
+ GetProject(projectID uint32) (*types.Project, error)
+ GetProjectByKey(projectKey string) (*types.Project, error)
+}
+
+type cacheImpl struct {
+ conn *postgres.Conn
+ mutex sync.RWMutex
+ sessions map[uint64]*SessionMeta
+ projects map[uint32]*ProjectMeta
+ projectsByKeys sync.Map
+ projectExpirationTimeout time.Duration
+}
+
+func NewCache(conn *postgres.Conn, projectExpirationTimeoutMs int64) Cache {
+ newCache := &cacheImpl{
+ conn: conn,
+ sessions: make(map[uint64]*SessionMeta),
+ projects: make(map[uint32]*ProjectMeta),
+ projectExpirationTimeout: time.Duration(1000 * projectExpirationTimeoutMs),
+ }
+ go newCache.cleaner()
+ return newCache
+}
+
+func (c *cacheImpl) cleaner() {
+ cleanTick := time.Tick(time.Minute * 5)
+ for {
+ select {
+ case <-cleanTick:
+ c.clearCache()
+ }
+ }
+}
+
+func (c *cacheImpl) clearCache() {
+ c.mutex.Lock()
+ defer c.mutex.Unlock()
+
+ now := time.Now()
+ cacheSize := len(c.sessions)
+ deleted := 0
+ for id, sess := range c.sessions {
+ if now.Sub(sess.lastUse).Minutes() > 3 {
+ deleted++
+ delete(c.sessions, id)
+ }
+ }
+ log.Printf("cache cleaner: deleted %d/%d sessions", deleted, cacheSize)
+}
diff --git a/backend/pkg/db/cache/messages-common.go b/backend/pkg/db/cache/messages-common.go
index a4df19cc3..46fc64790 100644
--- a/backend/pkg/db/cache/messages-common.go
+++ b/backend/pkg/db/cache/messages-common.go
@@ -19,7 +19,6 @@ func (c *PGCache) HandleSessionEnd(sessionID uint64) error {
if err := c.Conn.HandleSessionEnd(sessionID); err != nil {
log.Printf("can't handle session end: %s", err)
}
- c.DeleteSession(sessionID)
return nil
}
diff --git a/backend/pkg/db/cache/messages-ios.go b/backend/pkg/db/cache/messages-ios.go
index e0463c431..e65051f33 100644
--- a/backend/pkg/db/cache/messages-ios.go
+++ b/backend/pkg/db/cache/messages-ios.go
@@ -1,16 +1,16 @@
package cache
import (
- "errors"
+ "fmt"
. "openreplay/backend/pkg/db/types"
. "openreplay/backend/pkg/messages"
)
func (c *PGCache) InsertIOSSessionStart(sessionID uint64, s *IOSSessionStart) error {
- if c.sessions[sessionID] != nil {
- return errors.New("This session already in cache!")
+ if c.cache.HasSession(sessionID) {
+ return fmt.Errorf("session %d already in cache", sessionID)
}
- c.sessions[sessionID] = &Session{
+ newSess := &Session{
SessionID: sessionID,
Platform: "ios",
Timestamp: s.Timestamp,
@@ -24,8 +24,10 @@ func (c *PGCache) InsertIOSSessionStart(sessionID uint64, s *IOSSessionStart) er
UserCountry: s.UserCountry,
UserDeviceType: s.UserDeviceType,
}
- if err := c.Conn.InsertSessionStart(sessionID, c.sessions[sessionID]); err != nil {
- c.sessions[sessionID] = nil
+ c.cache.SetSession(newSess)
+ if err := c.Conn.InsertSessionStart(sessionID, newSess); err != nil {
+ // don't know why?
+ c.cache.SetSession(nil)
return err
}
return nil
diff --git a/backend/pkg/db/cache/messages-web.go b/backend/pkg/db/cache/messages-web.go
index 50b531d0a..de97ef42a 100644
--- a/backend/pkg/db/cache/messages-web.go
+++ b/backend/pkg/db/cache/messages-web.go
@@ -1,7 +1,7 @@
package cache
import (
- "errors"
+ "fmt"
. "openreplay/backend/pkg/db/types"
. "openreplay/backend/pkg/messages"
)
@@ -31,10 +31,10 @@ func (c *PGCache) InsertWebSessionStart(sessionID uint64, s *SessionStart) error
}
func (c *PGCache) HandleWebSessionStart(sessionID uint64, s *SessionStart) error {
- if c.sessions[sessionID] != nil {
- return errors.New("This session already in cache!")
+ if c.cache.HasSession(sessionID) {
+ return fmt.Errorf("session %d already in cache", sessionID)
}
- c.sessions[sessionID] = &Session{
+ newSess := &Session{
SessionID: sessionID,
Platform: "web",
Timestamp: s.Timestamp,
@@ -55,8 +55,10 @@ func (c *PGCache) HandleWebSessionStart(sessionID uint64, s *SessionStart) error
UserDeviceHeapSize: s.UserDeviceHeapSize,
UserID: &s.UserID,
}
- if err := c.Conn.HandleSessionStart(sessionID, c.sessions[sessionID]); err != nil {
- c.sessions[sessionID] = nil
+ c.cache.SetSession(newSess)
+ if err := c.Conn.HandleSessionStart(sessionID, newSess); err != nil {
+ // don't know why?
+ c.cache.SetSession(nil)
return err
}
return nil
diff --git a/backend/pkg/db/cache/pg-cache.go b/backend/pkg/db/cache/pg-cache.go
index bb87f9f4c..75e468d35 100644
--- a/backend/pkg/db/cache/pg-cache.go
+++ b/backend/pkg/db/cache/pg-cache.go
@@ -1,31 +1,20 @@
package cache
import (
- "sync"
- "time"
-
"openreplay/backend/pkg/db/postgres"
- . "openreplay/backend/pkg/db/types"
)
-type ProjectMeta struct {
- *Project
- expirationTime time.Time
-}
-
type PGCache struct {
*postgres.Conn
- sessions map[uint64]*Session
- projects map[uint32]*ProjectMeta
- projectsByKeys sync.Map // map[string]*ProjectMeta
- projectExpirationTimeout time.Duration
+ cache Cache
}
-func NewPGCache(pgConn *postgres.Conn, projectExpirationTimeoutMs int64) *PGCache {
+func NewPGCache(conn *postgres.Conn, projectExpirationTimeoutMs int64) *PGCache {
+ // Create in-memory cache layer for sessions and projects
+ c := NewCache(conn, projectExpirationTimeoutMs)
+ // Return PG wrapper with integrated cache layer
return &PGCache{
- Conn: pgConn,
- sessions: make(map[uint64]*Session),
- projects: make(map[uint32]*ProjectMeta),
- projectExpirationTimeout: time.Duration(1000 * projectExpirationTimeoutMs),
+ Conn: conn,
+ cache: c,
}
}
diff --git a/backend/pkg/db/cache/project.go b/backend/pkg/db/cache/project.go
index 35d952302..60b868501 100644
--- a/backend/pkg/db/cache/project.go
+++ b/backend/pkg/db/cache/project.go
@@ -5,7 +5,7 @@ import (
"time"
)
-func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) {
+func (c *cacheImpl) GetProjectByKey(projectKey string) (*Project, error) {
pmInterface, found := c.projectsByKeys.Load(projectKey)
if found {
if pm, ok := pmInterface.(*ProjectMeta); ok {
@@ -15,7 +15,7 @@ func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) {
}
}
- p, err := c.Conn.GetProjectByKey(projectKey)
+ p, err := c.conn.GetProjectByKey(projectKey)
if err != nil {
return nil, err
}
@@ -24,12 +24,12 @@ func (c *PGCache) GetProjectByKey(projectKey string) (*Project, error) {
return p, nil
}
-func (c *PGCache) GetProject(projectID uint32) (*Project, error) {
+func (c *cacheImpl) GetProject(projectID uint32) (*Project, error) {
if c.projects[projectID] != nil &&
time.Now().Before(c.projects[projectID].expirationTime) {
return c.projects[projectID].Project, nil
}
- p, err := c.Conn.GetProject(projectID)
+ p, err := c.conn.GetProject(projectID)
if err != nil {
return nil, err
}
diff --git a/backend/pkg/db/cache/session.go b/backend/pkg/db/cache/session.go
index 89b8f89f8..f03f1e955 100644
--- a/backend/pkg/db/cache/session.go
+++ b/backend/pkg/db/cache/session.go
@@ -4,28 +4,48 @@ import (
"errors"
"github.com/jackc/pgx/v4"
. "openreplay/backend/pkg/db/types"
+ "time"
)
var NilSessionInCacheError = errors.New("nil session in error")
-func (c *PGCache) GetSession(sessionID uint64) (*Session, error) {
- if s, inCache := c.sessions[sessionID]; inCache {
- if s == nil {
- return s, NilSessionInCacheError
- }
- return s, nil
+func (c *cacheImpl) SetSession(sess *Session) {
+ c.mutex.Lock()
+ defer c.mutex.Unlock()
+
+ if meta, ok := c.sessions[sess.SessionID]; ok {
+ meta.Session = sess
+ meta.lastUse = time.Now()
+ } else {
+ c.sessions[sess.SessionID] = &SessionMeta{sess, time.Now()}
}
- s, err := c.Conn.GetSession(sessionID)
+}
+
+func (c *cacheImpl) HasSession(sessID uint64) bool {
+ c.mutex.RLock()
+ defer c.mutex.RUnlock()
+
+ sess, ok := c.sessions[sessID]
+ return ok && sess.Session != nil
+}
+
+func (c *cacheImpl) GetSession(sessionID uint64) (*Session, error) {
+ c.mutex.Lock()
+ defer c.mutex.Unlock()
+
+ if s, inCache := c.sessions[sessionID]; inCache {
+ if s.Session == nil {
+ return nil, NilSessionInCacheError
+ }
+ return s.Session, nil
+ }
+ s, err := c.conn.GetSession(sessionID)
if err == pgx.ErrNoRows {
- c.sessions[sessionID] = nil
+ c.sessions[sessionID] = &SessionMeta{nil, time.Now()}
}
if err != nil {
return nil, err
}
- c.sessions[sessionID] = s
+ c.sessions[sessionID] = &SessionMeta{s, time.Now()}
return s, nil
}
-
-func (c *PGCache) DeleteSession(sessionID uint64) {
- delete(c.sessions, sessionID)
-}
diff --git a/backend/pkg/db/types/error-event.go b/backend/pkg/db/types/error-event.go
index 51569346f..826cbba9e 100644
--- a/backend/pkg/db/types/error-event.go
+++ b/backend/pkg/db/types/error-event.go
@@ -3,6 +3,7 @@ package types
import (
"encoding/hex"
"encoding/json"
+ "fmt"
"hash/fnv"
"log"
"strconv"
@@ -27,6 +28,9 @@ func unquote(s string) string {
return s
}
func parseTags(tagsJSON string) (tags map[string]*string, err error) {
+ if len(tagsJSON) == 0 {
+ return nil, fmt.Errorf("empty tags")
+ }
if tagsJSON[0] == '[' {
var tagsArr []json.RawMessage
if err = json.Unmarshal([]byte(tagsJSON), &tagsArr); err != nil {
diff --git a/backend/pkg/db/types/session.go b/backend/pkg/db/types/session.go
index 53fef410c..202eb9966 100644
--- a/backend/pkg/db/types/session.go
+++ b/backend/pkg/db/types/session.go
@@ -20,7 +20,7 @@ type Session struct {
IssueTypes []string
IssueScore int
- UserID *string // pointer??
+ UserID *string
UserAnonymousID *string
Metadata1 *string
Metadata2 *string
diff --git a/frontend/app/components/Client/CustomFields/CustomFields.js b/frontend/app/components/Client/CustomFields/CustomFields.js
index 0964ff7b8..5f2645fc8 100644
--- a/frontend/app/components/Client/CustomFields/CustomFields.js
+++ b/frontend/app/components/Client/CustomFields/CustomFields.js
@@ -71,7 +71,7 @@ function CustomFields(props) {
-
+
diff --git a/frontend/app/components/Client/Sites/AddProjectButton/AddUserButton.tsx b/frontend/app/components/Client/Sites/AddProjectButton/AddProjectButton.tsx
similarity index 96%
rename from frontend/app/components/Client/Sites/AddProjectButton/AddUserButton.tsx
rename to frontend/app/components/Client/Sites/AddProjectButton/AddProjectButton.tsx
index 5934dfe52..1d0721495 100644
--- a/frontend/app/components/Client/Sites/AddProjectButton/AddUserButton.tsx
+++ b/frontend/app/components/Client/Sites/AddProjectButton/AddProjectButton.tsx
@@ -22,7 +22,7 @@ function AddProjectButton({ isAdmin = false, init = () => {} }: any) {
};
return (
-
+
);
}
diff --git a/frontend/app/components/Client/Sites/AddProjectButton/index.ts b/frontend/app/components/Client/Sites/AddProjectButton/index.ts
index 66beb9cf8..631dd2a10 100644
--- a/frontend/app/components/Client/Sites/AddProjectButton/index.ts
+++ b/frontend/app/components/Client/Sites/AddProjectButton/index.ts
@@ -1 +1 @@
-export { default } from './AddUserButton';
\ No newline at end of file
+export { default } from './AddProjectButton';
\ No newline at end of file
diff --git a/frontend/app/components/Client/Users/components/AddUserButton/AddUserButton.tsx b/frontend/app/components/Client/Users/components/AddUserButton/AddUserButton.tsx
index df2777e83..19f77b420 100644
--- a/frontend/app/components/Client/Users/components/AddUserButton/AddUserButton.tsx
+++ b/frontend/app/components/Client/Users/components/AddUserButton/AddUserButton.tsx
@@ -14,16 +14,7 @@ function AddUserButton({ isAdmin = false, onClick }: any ) {
-
- {/* */}
+
);
}
diff --git a/frontend/app/components/Client/Webhooks/Webhooks.js b/frontend/app/components/Client/Webhooks/Webhooks.js
index 4235cd28b..e005a893a 100644
--- a/frontend/app/components/Client/Webhooks/Webhooks.js
+++ b/frontend/app/components/Client/Webhooks/Webhooks.js
@@ -46,7 +46,7 @@ function Webhooks(props) {
{'Webhooks'}
{/*
diff --git a/frontend/app/components/Dashboard/components/Alerts/AlertsView.tsx b/frontend/app/components/Dashboard/components/Alerts/AlertsView.tsx
index 277f13ab8..07b77961a 100644
--- a/frontend/app/components/Dashboard/components/Alerts/AlertsView.tsx
+++ b/frontend/app/components/Dashboard/components/Alerts/AlertsView.tsx
@@ -21,7 +21,7 @@ function AlertsView({ siteId, init }: IAlertsView) {
-
Create
+
Create Alert
diff --git a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx
index 11634632f..5341c3487 100644
--- a/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx
+++ b/frontend/app/components/Dashboard/components/DashboardList/DashboardsView.tsx
@@ -27,7 +27,7 @@ function DashboardsView({ history, siteId }: { history: any, siteId: string }) {
-
Create
+
Create Dashboard
diff --git a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx
index d5402fd2c..dd87b2fef 100644
--- a/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx
+++ b/frontend/app/components/Dashboard/components/MetricsView/MetricsView.tsx
@@ -22,7 +22,7 @@ function MetricsView({ siteId }: Props) {
-
Create
+
Create Metric
diff --git a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx
index 813c394e3..a09e48777 100644
--- a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx
+++ b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx
@@ -5,10 +5,10 @@ import { Tooltip } from 'react-tippy';
interface Props {
filter: any;
+ isFirst: boolean
}
function FunnelBar(props: Props) {
- const { filter } = props;
- // const completedPercentage = calculatePercentage(filter.sessionsCount, filter.dropDueToIssues);
+ const { filter, isFirst = false } = props;
return (
@@ -16,7 +16,6 @@ function FunnelBar(props: Props) {
-
- {/* {filter.completedPercentage}% */}
-
+
- {filter.dropDueToIssues > 0 && (
+ {/* {filter.dropDueToIssues > 0 && (
- )}
+ )} */}
-
-
- {filter.sessionsCount}
-
- ({filter.completedPercentage}%) Completed
-
- {/* Completed */}
-
-
-
- {filter.droppedCount}
- ({filter.droppedPercentage}%) Dropped
-
+ {/* @ts-ignore */}
+
+
+
+ {filter.sessionsCount}
+
+ ({filter.completedPercentage}%) Completed
+
+
+
+ {/* @ts-ignore */}
+
+
+
+ {filter.droppedCount}
+ ({filter.droppedPercentage}%) Dropped
+
+
);
diff --git a/frontend/app/components/Funnels/FunnelWidget/FunnelWidget.tsx b/frontend/app/components/Funnels/FunnelWidget/FunnelWidget.tsx
index 70e0d1b60..80e498a2f 100644
--- a/frontend/app/components/Funnels/FunnelWidget/FunnelWidget.tsx
+++ b/frontend/app/components/Funnels/FunnelWidget/FunnelWidget.tsx
@@ -98,7 +98,7 @@ function Stage({ stage, index, isWidget }: any) {
return useObserver(() => stage ? (
-
+
{!isWidget && (
)}
diff --git a/frontend/app/components/Header/UserMenu/UserMenu.tsx b/frontend/app/components/Header/UserMenu/UserMenu.tsx
index 3e74f63e9..c54d582b0 100644
--- a/frontend/app/components/Header/UserMenu/UserMenu.tsx
+++ b/frontend/app/components/Header/UserMenu/UserMenu.tsx
@@ -26,7 +26,7 @@ function UserMenu(props: RouteComponentProps
) {
style={{ width: '250px' }}
className={cn(className, 'absolute right-0 top-0 bg-white border mt-14')}
>
-
+
{getInitials(account.name)}
@@ -41,13 +41,6 @@ function UserMenu(props: RouteComponentProps
) {
-
-
- {'Account'}
-
- {component}
- ,
- document.querySelector('#modal-root')
- )
- ) : (
- <>>
- );
+ const history = useHistory();
+
+ useEffect(() => {
+ return history.listen((location) => {
+ if (history.action === 'POP') {
+ document.querySelector('body').style.overflow = 'visible';
+ }
+ });
+ });
+ return component ? (
+ ReactDOM.createPortal(
+
+ {component}
+ ,
+ document.querySelector('#modal-root')
+ )
+ ) : (
+ <>>
+ );
}
diff --git a/frontend/app/components/Session_/EventsBlock/NoteEvent.tsx b/frontend/app/components/Session_/EventsBlock/NoteEvent.tsx
index 622d13831..08e5631a9 100644
--- a/frontend/app/components/Session_/EventsBlock/NoteEvent.tsx
+++ b/frontend/app/components/Session_/EventsBlock/NoteEvent.tsx
@@ -45,7 +45,7 @@ function NoteEvent(props: Props) {
copy(
`${window.location.origin}/${window.location.pathname.split('/')[1]}${session(
props.note.sessionId
- )}${props.note.timestamp > 0 ? '?jumpto=' + props.note.timestamp : ''}`
+ )}${props.note.timestamp > 0 ? `?jumpto=${props.note.timestamp}¬e=${props.note.noteId}` : `?note=${props.note.noteId}`}`
);
toast.success('Note URL copied to clipboard');
};
@@ -114,11 +114,9 @@ function NoteEvent(props: Props) {
// @ts-ignore
background: tagProps[props.note.tag],
userSelect: 'none',
- width: 50,
- textAlign: 'center',
- fontSize: 11,
+ padding: '1px 6px',
}}
- className="rounded-full px-2 py-1 text-white text-sm"
+ className="rounded-full text-white text-xs select-none w-fit"
>
{props.note.tag}
diff --git a/frontend/app/components/Session_/Player/Controls/Controls.js b/frontend/app/components/Session_/Player/Controls/Controls.js
index 0a9b57fb3..3d5f096dc 100644
--- a/frontend/app/components/Session_/Player/Controls/Controls.js
+++ b/frontend/app/components/Session_/Player/Controls/Controls.js
@@ -78,6 +78,7 @@ function getStorageName(type) {
fullscreenDisabled: state.messagesLoading,
// logCount: state.logList.length,
logRedCount: state.logRedCount,
+ showExceptions: state.exceptionsList.length > 0,
resourceRedCount: state.resourceRedCount,
fetchRedCount: state.fetchRedCount,
showStack: state.stackList.length > 0,
@@ -143,6 +144,7 @@ export default class Controls extends React.Component {
// nextProps.inspectorMode !== this.props.inspectorMode ||
// nextProps.logCount !== this.props.logCount ||
nextProps.logRedCount !== this.props.logRedCount ||
+ nextProps.showExceptions !== this.props.showExceptions ||
nextProps.resourceRedCount !== this.props.resourceRedCount ||
nextProps.fetchRedCount !== this.props.fetchRedCount ||
nextProps.showStack !== this.props.showStack ||
@@ -262,6 +264,7 @@ export default class Controls extends React.Component {
speed,
disabled,
logRedCount,
+ showExceptions,
resourceRedCount,
showStack,
stackRedCount,
@@ -345,7 +348,7 @@ export default class Controls extends React.Component {
label="CONSOLE"
noIcon
labelClassName="!text-base font-semibold"
- hasErrors={logRedCount > 0}
+ hasErrors={logRedCount > 0 || showExceptions}
containerClassName="mx-2"
/>
{!live && (
diff --git a/frontend/app/components/shared/SessionListContainer/components/Notes/NoteItem.tsx b/frontend/app/components/shared/SessionListContainer/components/Notes/NoteItem.tsx
index 33108c0fe..d445e926c 100644
--- a/frontend/app/components/shared/SessionListContainer/components/Notes/NoteItem.tsx
+++ b/frontend/app/components/shared/SessionListContainer/components/Notes/NoteItem.tsx
@@ -24,7 +24,7 @@ function NoteItem(props: Props) {
copy(
`${window.location.origin}/${window.location.pathname.split('/')[1]}${session(
props.note.sessionId
- )}${props.note.timestamp > 0 ? '?jumpto=' + props.note.timestamp : ''}`
+ )}${props.note.timestamp > 0 ? `?jumpto=${props.note.timestamp}¬e=${props.note.noteId}` : `?note=${props.note.noteId}`}`
);
toast.success('Note URL copied to clipboard');
};
@@ -35,7 +35,7 @@ function NoteItem(props: Props) {
});
};
const menuItems = [
- { icon: 'link-45deg', text: 'Copy URL', onClick: onCopy },
+ { icon: 'link-45deg', text: 'Copy Note URL', onClick: onCopy },
{ icon: 'trash', text: 'Delete', onClick: onDelete },
];
@@ -49,20 +49,17 @@ function NoteItem(props: Props) {
session(props.note.sessionId) +
(props.note.timestamp > 0
? `?jumpto=${props.note.timestamp}¬e=${props.note.noteId}`
- : '')
+ : `?note=${props.note.noteId}`)
}
>
-
{safeStrMessage}
+
{safeStrMessage}
{props.note.tag ? (