insert bookmark

This commit is contained in:
sawka 2023-02-20 21:39:29 -08:00
parent 37ffcd03c8
commit 3845429fd2
6 changed files with 178 additions and 10 deletions

View File

@ -1,3 +1,6 @@
DROP TABLE bookmark;
DROP TABLE bookmark_order;
DROP TABLE bookmark_cmd;
ALTER TABLE line DROP COLUMN bookmarked;
ALTER TABLE line DROP COLUMN pinned;

View File

@ -16,6 +16,11 @@ CREATE TABLE bookmark_order (
CREATE TABLE bookmark_cmd (
bookmarkid varchar(36) NOT NULL,
sessionid varchar(36) NOT NULL,
cmdid varchar(36) NOT NULL,
PRIMARY KEY (bookmarkid, cmdid)
PRIMARY KEY (bookmarkid, sessionid, cmdid)
);
ALTER TABLE line ADD COLUMN bookmarked boolean NOT NULL DEFAULT 0;
ALTER TABLE line ADD COLUMN pinned boolean NOT NULL DEFAULT 0;

View File

@ -97,7 +97,7 @@ CREATE TABLE line (
ephemeral boolean NOT NULL,
contentheight int NOT NULL,
star int NOT NULL,
archived boolean NOT NULL, renderer varchar(50) NOT NULL DEFAULT '',
archived boolean NOT NULL, renderer varchar(50) NOT NULL DEFAULT '', bookmarked boolean NOT NULL DEFAULT 0, pinned boolean NOT NULL DEFAULT 0,
PRIMARY KEY (sessionid, windowid, lineid)
);
CREATE TABLE remote (
@ -181,6 +181,7 @@ CREATE TABLE bookmark_order (
);
CREATE TABLE bookmark_cmd (
bookmarkid varchar(36) NOT NULL,
sessionid varchar(36) NOT NULL,
cmdid varchar(36) NOT NULL,
PRIMARY KEY (bookmarkid, cmdid)
PRIMARY KEY (bookmarkid, sessionid, cmdid)
);

View File

@ -157,6 +157,8 @@ func init() {
registerCmdFn("line", LineCommand)
registerCmdFn("line:show", LineShowCommand)
registerCmdFn("line:star", LineStarCommand)
registerCmdFn("line:bookmark", LineBookmarkCommand)
registerCmdFn("line:pin", LinePinCommand)
registerCmdFn("line:archive", LineArchiveCommand)
registerCmdFn("line:purge", LinePurgeCommand)
registerCmdFn("line:setheight", LineSetHeightCommand)
@ -1900,6 +1902,58 @@ func LineSetHeightCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
return nil, nil
}
func LineBookmarkCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window)
if err != nil {
return nil, err
}
if len(pk.Args) == 0 {
return nil, fmt.Errorf("/line:bookmark requires an argument (line number or id)")
}
lineArg := pk.Args[0]
lineId, err := sstore.FindLineIdByArg(ctx, ids.SessionId, ids.WindowId, lineArg)
if err != nil {
return nil, fmt.Errorf("error looking up lineid: %v", err)
}
if lineId == "" {
return nil, fmt.Errorf("line %q not found", lineArg)
}
lineObj, cmdObj, err := sstore.GetLineCmdByLineId(ctx, ids.SessionId, ids.WindowId, lineId)
if err != nil {
return nil, fmt.Errorf("/line:bookmark error getting line: %v", err)
}
if cmdObj == nil {
return nil, fmt.Errorf("cannot bookmark non-cmd line")
}
ck := base.MakeCommandKey(lineObj.SessionId, cmdObj.CmdId)
bm := &sstore.BookmarkType{
BookmarkId: uuid.New().String(),
CreatedTs: time.Now().UnixMilli(),
CmdStr: cmdObj.CmdStr,
Alias: "",
Tags: nil,
Description: "",
CmdIds: []base.CommandKey{ck},
}
err = sstore.InsertBookmark(ctx, bm)
if err != nil {
return nil, fmt.Errorf("cannot insert bookmark: %v", err)
}
newLineObj, err := sstore.GetLineById(ctx, ids.SessionId, ids.WindowId, lineId)
if err != nil {
return nil, fmt.Errorf("/line:bookmark error getting line: %v", err)
}
if newLineObj == nil {
// no line (which is strange given we checked for it above). just return a nop.
return nil, nil
}
return sstore.ModelUpdate{Line: newLineObj}, nil
}
func LinePinCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
return nil, nil
}
func LineStarCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window)
if err != nil {
@ -1930,7 +1984,7 @@ func LineStarCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
if err != nil {
return nil, fmt.Errorf("/line:star error updating star value: %v", err)
}
lineObj, err := sstore.GetLineById(ctx, lineId)
lineObj, err := sstore.GetLineById(ctx, ids.SessionId, ids.WindowId, lineId)
if err != nil {
return nil, fmt.Errorf("/line:star error getting line: %v", err)
}
@ -1965,7 +2019,7 @@ func LineArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
if err != nil {
return nil, fmt.Errorf("/line:archive error updating hidden status: %v", err)
}
lineObj, err := sstore.GetLineById(ctx, lineId)
lineObj, err := sstore.GetLineById(ctx, ids.SessionId, ids.WindowId, lineId)
if err != nil {
return nil, fmt.Errorf("/line:archive error getting line: %v", err)
}

View File

@ -719,8 +719,8 @@ func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
query = `SELECT nextlinenum FROM window WHERE sessionid = ? AND windowid = ?`
nextLineNum := tx.GetInt(query, line.SessionId, line.WindowId)
line.LineNum = int64(nextLineNum)
query = `INSERT INTO line ( sessionid, windowid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, cmdid, renderer, ephemeral, contentheight, star, archived)
VALUES (:sessionid,:windowid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:cmdid,:renderer,:ephemeral,:contentheight,:star,:archived)`
query = `INSERT INTO line ( sessionid, windowid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, cmdid, renderer, ephemeral, contentheight, star, archived, bookmarked, pinned)
VALUES (:sessionid,:windowid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:cmdid,:renderer,:ephemeral,:contentheight,:star,:archived,:bookmarked,:pinned)`
tx.NamedExec(query, line)
query = `UPDATE window SET nextlinenum = ? WHERE sessionid = ? AND windowid = ?`
tx.Exec(query, nextLineNum+1, line.SessionId, line.WindowId)
@ -899,6 +899,8 @@ func cleanSessionCmds(ctx context.Context, sessionId string) error {
removedCmds = tx.SelectStrings(query, sessionId, sessionId)
query = `DELETE FROM cmd WHERE sessionid = ? AND cmdid NOT IN (SELECT cmdid FROM line WHERE sessionid = ?)`
tx.Exec(query, sessionId, sessionId)
query = `DELETE FROM bookmark_cmd WHERE sessionid = ? AND cmdid NOT IN (SELECT cmdid FROM cmd WHERE sessionid = ?)`
tx.Exec(query, sessionId, sessionId)
return nil
})
if txErr != nil {
@ -1391,6 +1393,8 @@ func DeleteSession(ctx context.Context, sessionId string) (UpdatePacket, error)
tx.Exec(query, sessionId)
query = `DELETE FROM cmd WHERE sessionid = ?`
tx.Exec(query, sessionId)
query = `DELETE FROM bookmark_cmd WHERE sessionid = ?`
tx.Exec(query, sessionId)
newActiveSessionId, _ = fixActiveSessionId(tx.Context())
return nil
})
@ -1825,12 +1829,12 @@ func UpdateLineHeight(ctx context.Context, lineId string, heightVal int) error {
}
// can return nil, nil if line is not found
func GetLineById(ctx context.Context, lineId string) (*LineType, error) {
func GetLineById(ctx context.Context, sessionId string, windowId string, lineId string) (*LineType, error) {
var rtn *LineType
txErr := WithTx(ctx, func(tx *TxWrap) error {
var line LineType
query := `SELECT * FROM line WHERE lineid = ?`
found := tx.Get(&line, query, lineId)
query := `SELECT * FROM line WHERE sessionid = ? AND windowid = ? AND lineid = ?`
found := tx.Get(&line, query, sessionId, windowId, lineId)
if found {
rtn = &line
}
@ -2033,3 +2037,67 @@ func GetDBVersion(ctx context.Context) (int, error) {
})
return version, txErr
}
func InsertBookmark(ctx context.Context, bm *BookmarkType) error {
if bm == nil || bm.BookmarkId == "" {
return fmt.Errorf("invalid empty bookmark id")
}
txErr := WithTx(ctx, func(tx *TxWrap) error {
query := `SELECT bookmarkid FROM bookmark WHERE bookmarkid = ?`
if tx.Exists(query, bm.BookmarkId) {
return fmt.Errorf("bookmarkid already exists")
}
query = `INSERT INTO bookmark ( bookmarkid, createdts, cmdstr, alias, tags, description)
VALUES (:bookmarkid,:createdts,:cmdstr,:alias,:tags,:description)`
tx.NamedExec(query, bm.ToMap())
for _, tag := range append(bm.Tags, "") {
query = `SELECT COALESCE(max(orderidx), 0) FROM bookmark_order WHERE tag = ?`
maxOrder := tx.GetInt(query, tag)
query = `INSERT INTO bookmark_order (tag, bookmarkid, orderidx) VALUES (?, ?, ?)`
tx.Exec(query, tag, bm.BookmarkId, maxOrder+1)
}
query = `INSERT INTO bookmark_cmd (bookmarkid, sessionid, cmdid) VALUES (?, ?, ?)`
for _, ck := range bm.CmdIds {
tx.Exec(query, bm.BookmarkId, ck.GetSessionId(), ck.GetCmdId())
}
query = `UPDATE line SET bookmarked = 1 WHERE sessionid = ? AND cmdid = ?`
for _, ck := range bm.CmdIds {
tx.Exec(query, ck.GetSessionId(), ck.GetCmdId())
}
return nil
})
return txErr
}
func fixupBookmarkOrder(tx *TxWrap) {
query := `
WITH new_order AS (
SELECT tag, bookmarkid, row_number() OVER (PARTITION BY tag ORDER BY orderidx) AS newidx FROM bookmark_order
)
UPDATE bookmark_order
SET orderidx = new_order.newidx
FROM new_order
WHERE bookmark_order.tag = new_order.tag AND bookmark_order.bookmarkid = new_order.bookmarkid
`
tx.Exec(query)
}
func DeleteBookmark(ctx context.Context, bookmarkId string) error {
txErr := WithTx(ctx, func(tx *TxWrap) error {
query := `SELECT bookmarkid FROM bookmark WHERE bookmarkid = ?`
if !tx.Exists(query, bookmarkId) {
return fmt.Errorf("bookmark not found")
}
query = `DELETE FROM bookmark WHERE bookmarkid = ?`
tx.Exec(query, bookmarkId)
query = `DELETE FROM bookmark_order WHERE bookmarkid = ?`
tx.Exec(query, bookmarkId)
query = `UPDATE line SET bookmarked = 0 WHERE bookmarked AND cmdid <> '' AND (sessionid||cmdid) IN (SELECT sessionid||cmdid FROM bookmark_cmd WHERE bookmarkid = ?) `
tx.Exec(query, bookmarkId)
query = `DELETE FROM bookmark_cmd WHERE bookmarkid = ?`
tx.Exec(query, bookmarkId)
fixupBookmarkOrder(tx)
return nil
})
return txErr
}

View File

@ -650,10 +650,47 @@ type LineType struct {
Ephemeral bool `json:"ephemeral,omitempty"`
ContentHeight int64 `json:"contentheight,omitempty"`
Star bool `json:"star,omitempty"`
Bookmarked bool `json:"bookmarked,omitempty"`
Pinned bool `json:"pinned,omitempty"`
Archived bool `json:"archived,omitempty"`
Remove bool `json:"remove,omitempty"`
}
type BookmarkType struct {
BookmarkId string `json:"bookmarkid"`
CreatedTs int64 `json:"createdts"`
CmdStr string `json:"cmdstr"`
Alias string `json:"alias,omitempty"`
Tags []string `json:"tags"`
Description string `json:"description"`
CmdIds []base.CommandKey `json:"cmdids"`
}
func (bm *BookmarkType) ToMap() map[string]interface{} {
rtn := make(map[string]interface{})
rtn["bookmarkid"] = bm.BookmarkId
rtn["createdts"] = bm.CreatedTs
rtn["cmdstr"] = bm.CmdStr
rtn["alias"] = bm.Alias
rtn["description"] = bm.Description
rtn["tags"] = quickJsonArr(bm.Tags)
return rtn
}
func BookmarkFromMap(m map[string]interface{}) *BookmarkType {
if len(m) == 0 {
return nil
}
var bm BookmarkType
quickSetStr(&bm.BookmarkId, m, "bookmarkid")
quickSetInt64(&bm.CreatedTs, m, "createdts")
quickSetStr(&bm.Alias, m, "alias")
quickSetStr(&bm.CmdStr, m, "cmdstr")
quickSetStr(&bm.Description, m, "description")
quickSetJsonArr(&bm.Tags, m, "tags")
return &bm
}
type ResolveItem struct {
Name string
Num int