Bookmarks: Store URLs instead of ids (#91121)

This commit is contained in:
Joao Silva
2024-07-31 13:56:39 +01:00
committed by GitHub
parent 562380079f
commit 85d0e17dc4
17 changed files with 37 additions and 40 deletions

View File

@ -53,7 +53,7 @@ Content-Type: application/json
`PUT /api/user/preferences` `PUT /api/user/preferences`
**Example Request**: **Example Request**:
```http ```http
PUT /api/user/preferences HTTP/1.1 PUT /api/user/preferences HTTP/1.1
Accept: application/json Accept: application/json
@ -142,7 +142,7 @@ Content-Type: application/json
Update one or more preferences without modifying the others. Update one or more preferences without modifying the others.
`PATCH /api/org/preferences` `PATCH /api/org/preferences`
**Example Request**: **Example Request**:
```http ```http

View File

@ -49,7 +49,7 @@ lineage: schemas: [{
} @cuetsy(kind="interface") } @cuetsy(kind="interface")
#NavbarPreference: { #NavbarPreference: {
bookmarkIds: [...string] bookmarkUrls: [...string]
} @cuetsy(kind="interface") } @cuetsy(kind="interface")
} }
}] }]

View File

@ -22,11 +22,11 @@ export interface CookiePreferences {
} }
export interface NavbarPreference { export interface NavbarPreference {
bookmarkIds: Array<string>; bookmarkUrls: Array<string>;
} }
export const defaultNavbarPreference: Partial<NavbarPreference> = { export const defaultNavbarPreference: Partial<NavbarPreference> = {
bookmarkIds: [], bookmarkUrls: [],
}; };
/** /**

View File

@ -18,7 +18,7 @@ type CookiePreferences struct {
// NavbarPreference defines model for NavbarPreference. // NavbarPreference defines model for NavbarPreference.
type NavbarPreference struct { type NavbarPreference struct {
BookmarkIds []string `json:"bookmarkIds"` BookmarkUrls []string `json:"bookmarkUrls"`
} }
// QueryHistoryPreference defines model for QueryHistoryPreference. // QueryHistoryPreference defines model for QueryHistoryPreference.

View File

@ -338,11 +338,11 @@ func (s *ServiceImpl) buildStarredItemsNavLinks(c *contextmodel.ReqContext) ([]*
func (s *ServiceImpl) buildBookmarksNavLinks(prefs *pref.Preference, treeRoot *navtree.NavTreeRoot) []*navtree.NavLink { func (s *ServiceImpl) buildBookmarksNavLinks(prefs *pref.Preference, treeRoot *navtree.NavTreeRoot) []*navtree.NavLink {
bookmarksChildNavs := []*navtree.NavLink{} bookmarksChildNavs := []*navtree.NavLink{}
bookmarkIds := prefs.JSONData.Navbar.BookmarkIds bookmarkUrls := prefs.JSONData.Navbar.BookmarkUrls
if len(bookmarkIds) > 0 { if len(bookmarkUrls) > 0 {
for _, id := range bookmarkIds { for _, url := range bookmarkUrls {
item := treeRoot.FindById(id) item := treeRoot.FindByURL(url)
if item != nil { if item != nil {
bookmarksChildNavs = append(bookmarksChildNavs, &navtree.NavLink{ bookmarksChildNavs = append(bookmarksChildNavs, &navtree.NavLink{
Id: item.Id, Id: item.Id,

View File

@ -98,7 +98,7 @@ type QueryHistoryPreference struct {
} }
type NavbarPreference struct { type NavbarPreference struct {
BookmarkIds []string `json:"bookmarkIds"` BookmarkUrls []string `json:"bookmarkUrls"`
} }
func (j *PreferenceJSONData) FromDB(data []byte) error { func (j *PreferenceJSONData) FromDB(data []byte) error {

View File

@ -97,11 +97,11 @@ func GetPreferencesFor(ctx context.Context,
dto.Language = &preference.JSONData.Language dto.Language = &preference.JSONData.Language
} }
if preference.JSONData.Navbar.BookmarkIds != nil { if preference.JSONData.Navbar.BookmarkUrls != nil {
dto.Navbar = &preferences.NavbarPreference{ dto.Navbar = &preferences.NavbarPreference{
BookmarkIds: []string{}, BookmarkUrls: []string{},
} }
dto.Navbar.BookmarkIds = preference.JSONData.Navbar.BookmarkIds dto.Navbar.BookmarkUrls = preference.JSONData.Navbar.BookmarkUrls
} }
if preference.JSONData.QueryHistory.HomeTab != "" { if preference.JSONData.QueryHistory.HomeTab != "" {

View File

@ -71,8 +71,8 @@ func (s *Service) GetWithDefaults(ctx context.Context, query *pref.GetPreference
res.JSONData.QueryHistory.HomeTab = p.JSONData.QueryHistory.HomeTab res.JSONData.QueryHistory.HomeTab = p.JSONData.QueryHistory.HomeTab
} }
if p.JSONData.Navbar.BookmarkIds != nil { if p.JSONData.Navbar.BookmarkUrls != nil {
res.JSONData.Navbar.BookmarkIds = p.JSONData.Navbar.BookmarkIds res.JSONData.Navbar.BookmarkUrls = p.JSONData.Navbar.BookmarkUrls
} }
if p.JSONData.CookiePreferences != nil { if p.JSONData.CookiePreferences != nil {
@ -174,11 +174,11 @@ func (s *Service) Patch(ctx context.Context, cmd *pref.PatchPreferenceCommand) e
preference.JSONData.Language = *cmd.Language preference.JSONData.Language = *cmd.Language
} }
if cmd.Navbar != nil && cmd.Navbar.BookmarkIds != nil { if cmd.Navbar != nil && cmd.Navbar.BookmarkUrls != nil {
if preference.JSONData == nil { if preference.JSONData == nil {
preference.JSONData = &pref.PreferenceJSONData{} preference.JSONData = &pref.PreferenceJSONData{}
} }
preference.JSONData.Navbar.BookmarkIds = cmd.Navbar.BookmarkIds preference.JSONData.Navbar.BookmarkUrls = cmd.Navbar.BookmarkUrls
} }
if cmd.QueryHistory != nil { if cmd.QueryHistory != nil {

View File

@ -17112,7 +17112,7 @@
"type": "object", "type": "object",
"title": "NavbarPreference defines model for NavbarPreference.", "title": "NavbarPreference defines model for NavbarPreference.",
"properties": { "properties": {
"bookmarkIds": { "bookmarkUrls": {
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"

View File

@ -54,29 +54,28 @@ export const MegaMenu = memo(
}; };
const isPinned = useCallback( const isPinned = useCallback(
(id?: string) => { (url?: string) => {
if (!id || !pinnedItems?.length) { if (!url || !pinnedItems?.length) {
return false; return false;
} }
return pinnedItems?.includes(id); return pinnedItems?.includes(url);
}, },
[pinnedItems] [pinnedItems]
); );
const onPinItem = (item: NavModelItem) => { const onPinItem = (item: NavModelItem) => {
const id = item.id; const url = item.url;
if (id && config.featureToggles.pinNavItems) { if (url && config.featureToggles.pinNavItems) {
const navItem = navTree.find((item) => item.id === id); const isSaved = isPinned(url);
const isSaved = isPinned(id); const newItems = isSaved ? pinnedItems.filter((i) => url !== i) : [...pinnedItems, url];
const newItems = isSaved ? pinnedItems.filter((i) => id !== i) : [...pinnedItems, id];
const interactionName = isSaved ? 'grafana_nav_item_unpinned' : 'grafana_nav_item_pinned'; const interactionName = isSaved ? 'grafana_nav_item_unpinned' : 'grafana_nav_item_pinned';
reportInteraction(interactionName, { reportInteraction(interactionName, {
path: navItem?.url ?? id, path: url,
}); });
patchPreferences({ patchPreferences({
patchPrefsCmd: { patchPrefsCmd: {
navbar: { navbar: {
bookmarkIds: newItems, bookmarkUrls: newItems,
}, },
}, },
}).then((data) => { }).then((data) => {

View File

@ -104,9 +104,8 @@ export function MegaMenuItem({ link, activeItem, level = 0, onClick, onPin, isPi
}} }}
target={link.target} target={link.target}
url={link.url} url={link.url}
id={link.id}
onPin={() => onPin(link)} onPin={() => onPin(link)}
isPinned={isPinned(link.id)} isPinned={isPinned(link.url)}
> >
<div <div
className={cx(styles.labelWrapper, { className={cx(styles.labelWrapper, {

View File

@ -13,12 +13,11 @@ export interface Props {
onClick?: () => void; onClick?: () => void;
target?: HTMLAnchorElement['target']; target?: HTMLAnchorElement['target'];
url: string; url: string;
id?: string;
onPin: (id?: string) => void; onPin: (id?: string) => void;
isPinned?: boolean; isPinned?: boolean;
} }
export function MegaMenuItemText({ children, isActive, onClick, target, url, id, onPin, isPinned }: Props) { export function MegaMenuItemText({ children, isActive, onClick, target, url, onPin, isPinned }: Props) {
const theme = useTheme2(); const theme = useTheme2();
const styles = getStyles(theme, isActive); const styles = getStyles(theme, isActive);
const LinkComponent = !target && url.startsWith('/') ? Link : 'a'; const LinkComponent = !target && url.startsWith('/') ? Link : 'a';
@ -51,12 +50,12 @@ export function MegaMenuItemText({ children, isActive, onClick, target, url, id,
> >
{linkContent} {linkContent}
</LinkComponent> </LinkComponent>
{config.featureToggles.pinNavItems && id && id !== 'bookmarks' && ( {config.featureToggles.pinNavItems && url && url !== '/bookmarks' && (
<IconButton <IconButton
name="bookmark" name="bookmark"
className={'pin-icon'} className={'pin-icon'}
iconType={isPinned ? 'solid' : 'default'} iconType={isPinned ? 'solid' : 'default'}
onClick={() => onPin(id)} onClick={() => onPin(url)}
aria-label={ aria-label={
isPinned isPinned
? t('navigation.item.remove-bookmark', 'Remove from Bookmarks') ? t('navigation.item.remove-bookmark', 'Remove from Bookmarks')

View File

@ -5,7 +5,7 @@ import { useGetUserPreferencesQuery } from 'app/features/preferences/api';
export const usePinnedItems = () => { export const usePinnedItems = () => {
const preferences = useGetUserPreferencesQuery(); const preferences = useGetUserPreferencesQuery();
const pinnedItems = useMemo(() => preferences.data?.navbar?.bookmarkIds || [], [preferences]); const pinnedItems = useMemo(() => preferences.data?.navbar?.bookmarkUrls || [], [preferences]);
if (config.featureToggles.pinNavItems) { if (config.featureToggles.pinNavItems) {
return pinnedItems; return pinnedItems;

View File

@ -73,7 +73,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
weekStart: '', weekStart: '',
language: '', language: '',
queryHistory: { homeTab: '' }, queryHistory: { homeTab: '' },
navbar: { bookmarkIds: [] }, navbar: { bookmarkUrls: [] },
}; };
this.themeOptions = getBuiltInThemes(config.featureToggles.extraThemes).map((theme) => ({ this.themeOptions = getBuiltInThemes(config.featureToggles.extraThemes).map((theme) => ({

View File

@ -71,7 +71,7 @@ const navTreeSlice = createSlice({
}; };
bookmarks.children.push(newBookmark); bookmarks.children.push(newBookmark);
} else { } else {
bookmarks.children = bookmarks.children?.filter((i) => i.id !== item.id) ?? []; bookmarks.children = bookmarks.children?.filter((i) => i.url !== item.url) ?? [];
} }
} }
}, },

View File

@ -38,7 +38,7 @@ export type CookiePreferencesDefinesModelForCookiePreferences = {
}; };
}; };
export type NavbarPreferenceDefinesModelForNavbarPreference = { export type NavbarPreferenceDefinesModelForNavbarPreference = {
bookmarkIds?: string[]; bookmarkUrls?: string[];
}; };
export type QueryHistoryPreferenceDefinesModelForQueryHistoryPreference = { export type QueryHistoryPreferenceDefinesModelForQueryHistoryPreference = {
/** HomeTab one of: '' | 'query' | 'starred'; */ /** HomeTab one of: '' | 'query' | 'starred'; */

View File

@ -7188,7 +7188,7 @@
}, },
"NavbarPreference": { "NavbarPreference": {
"properties": { "properties": {
"bookmarkIds": { "bookmarkUrls": {
"items": { "items": {
"type": "string" "type": "string"
}, },