mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: update memo resource name definition
This commit is contained in:
@ -61,7 +61,8 @@ message Resource {
|
||||
|
||||
int64 size = 7;
|
||||
|
||||
optional int32 memo_id = 8;
|
||||
// Format: memos/{id}
|
||||
optional string memo = 8;
|
||||
}
|
||||
|
||||
message CreateResourceRequest {
|
||||
@ -71,7 +72,8 @@ message CreateResourceRequest {
|
||||
|
||||
string type = 3;
|
||||
|
||||
optional int32 memo_id = 4;
|
||||
// Format: memos/{id}
|
||||
optional string memo = 4;
|
||||
}
|
||||
|
||||
message CreateResourceResponse {
|
||||
|
@ -1332,7 +1332,7 @@ Used internally for obfuscating the page token.
|
||||
| filename | [string](#string) | | |
|
||||
| external_link | [string](#string) | | |
|
||||
| type | [string](#string) | | |
|
||||
| memo_id | [int32](#int32) | optional | |
|
||||
| memo | [string](#string) | optional | Format: memos/{id} |
|
||||
|
||||
|
||||
|
||||
@ -1449,7 +1449,7 @@ Used internally for obfuscating the page token.
|
||||
| external_link | [string](#string) | | |
|
||||
| type | [string](#string) | | |
|
||||
| size | [int64](#int64) | | |
|
||||
| memo_id | [int32](#int32) | optional | |
|
||||
| memo | [string](#string) | optional | Format: memos/{id} |
|
||||
|
||||
|
||||
|
||||
|
@ -39,7 +39,8 @@ type Resource struct {
|
||||
ExternalLink string `protobuf:"bytes,5,opt,name=external_link,json=externalLink,proto3" json:"external_link,omitempty"`
|
||||
Type string `protobuf:"bytes,6,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Size int64 `protobuf:"varint,7,opt,name=size,proto3" json:"size,omitempty"`
|
||||
MemoId *int32 `protobuf:"varint,8,opt,name=memo_id,json=memoId,proto3,oneof" json:"memo_id,omitempty"`
|
||||
// Format: memos/{id}
|
||||
Memo *string `protobuf:"bytes,8,opt,name=memo,proto3,oneof" json:"memo,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Resource) Reset() {
|
||||
@ -123,11 +124,11 @@ func (x *Resource) GetSize() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Resource) GetMemoId() int32 {
|
||||
if x != nil && x.MemoId != nil {
|
||||
return *x.MemoId
|
||||
func (x *Resource) GetMemo() string {
|
||||
if x != nil && x.Memo != nil {
|
||||
return *x.Memo
|
||||
}
|
||||
return 0
|
||||
return ""
|
||||
}
|
||||
|
||||
type CreateResourceRequest struct {
|
||||
@ -138,7 +139,8 @@ type CreateResourceRequest struct {
|
||||
Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"`
|
||||
ExternalLink string `protobuf:"bytes,2,opt,name=external_link,json=externalLink,proto3" json:"external_link,omitempty"`
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
MemoId *int32 `protobuf:"varint,4,opt,name=memo_id,json=memoId,proto3,oneof" json:"memo_id,omitempty"`
|
||||
// Format: memos/{id}
|
||||
Memo *string `protobuf:"bytes,4,opt,name=memo,proto3,oneof" json:"memo,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CreateResourceRequest) Reset() {
|
||||
@ -194,11 +196,11 @@ func (x *CreateResourceRequest) GetType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CreateResourceRequest) GetMemoId() int32 {
|
||||
if x != nil && x.MemoId != nil {
|
||||
return *x.MemoId
|
||||
func (x *CreateResourceRequest) GetMemo() string {
|
||||
if x != nil && x.Memo != nil {
|
||||
return *x.Memo
|
||||
}
|
||||
return 0
|
||||
return ""
|
||||
}
|
||||
|
||||
type CreateResourceResponse struct {
|
||||
@ -721,7 +723,7 @@ var file_api_v2_resource_service_proto_rawDesc = []byte{
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x80, 0x02, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf8, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x72,
|
||||
@ -735,19 +737,18 @@ var file_api_v2_resource_service_proto_rawDesc = []byte{
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65,
|
||||
0x12, 0x1c, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28,
|
||||
0x05, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a,
|
||||
0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x69, 0x64, 0x22, 0x96, 0x01, 0x0a, 0x15, 0x43,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x12, 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6c, 0x69, 0x6e,
|
||||
0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61,
|
||||
0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x07, 0x6d, 0x65, 0x6d,
|
||||
0x6f, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x65,
|
||||
0x6d, 0x6f, 0x49, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x6d, 0x65, 0x6d, 0x6f,
|
||||
0x5f, 0x69, 0x64, 0x22, 0x4c, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
|
||||
0x12, 0x17, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
||||
0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6d, 0x65,
|
||||
0x6d, 0x6f, 0x22, 0x8e, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08,
|
||||
0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
|
||||
0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
|
||||
0x65, 0x12, 0x17, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x00, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6d,
|
||||
0x65, 0x6d, 0x6f, 0x22, 0x4c, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a,
|
||||
0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52,
|
||||
|
@ -346,11 +346,11 @@ paths:
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
- name: memoId
|
||||
- name: memo
|
||||
description: 'Format: memos/{id}'
|
||||
in: query
|
||||
required: false
|
||||
type: integer
|
||||
format: int32
|
||||
type: string
|
||||
tags:
|
||||
- ResourceService
|
||||
/api/v2/resources:search:
|
||||
@ -1476,9 +1476,9 @@ paths:
|
||||
size:
|
||||
type: string
|
||||
format: int64
|
||||
memoId:
|
||||
type: integer
|
||||
format: int32
|
||||
memo:
|
||||
type: string
|
||||
title: 'Format: memos/{id}'
|
||||
tags:
|
||||
- ResourceService
|
||||
/api/v2/{setting.name}:
|
||||
@ -2183,9 +2183,9 @@ definitions:
|
||||
size:
|
||||
type: string
|
||||
format: int64
|
||||
memoId:
|
||||
type: integer
|
||||
format: int32
|
||||
memo:
|
||||
type: string
|
||||
title: 'Format: memos/{id}'
|
||||
v2SearchMemosResponse:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -41,8 +41,12 @@ func (s *APIV2Service) CreateResource(ctx context.Context, request *apiv2pb.Crea
|
||||
ExternalLink: request.ExternalLink,
|
||||
Type: request.Type,
|
||||
}
|
||||
if request.MemoId != nil {
|
||||
create.MemoID = request.MemoId
|
||||
if request.Memo != nil {
|
||||
memoID, err := ExtractMemoIDFromName(*request.Memo)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid memo id: %v", err)
|
||||
}
|
||||
create.MemoID = &memoID
|
||||
}
|
||||
resource, err := s.Store.CreateResource(ctx, create)
|
||||
if err != nil {
|
||||
@ -139,8 +143,15 @@ func (s *APIV2Service) UpdateResource(ctx context.Context, request *apiv2pb.Upda
|
||||
for _, field := range request.UpdateMask.Paths {
|
||||
if field == "filename" {
|
||||
update.Filename = &request.Resource.Filename
|
||||
} else if field == "memo_id" {
|
||||
update.MemoID = request.Resource.MemoId
|
||||
} else if field == "memo" {
|
||||
if request.Resource.Memo == nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "memo is required")
|
||||
}
|
||||
memoID, err := ExtractMemoIDFromName(*request.Resource.Memo)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid memo id: %v", err)
|
||||
}
|
||||
update.MemoID = &memoID
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,17 +193,7 @@ func (s *APIV2Service) DeleteResource(ctx context.Context, request *apiv2pb.Dele
|
||||
}
|
||||
|
||||
func (s *APIV2Service) convertResourceFromStore(ctx context.Context, resource *store.Resource) *apiv2pb.Resource {
|
||||
var memoID *int32
|
||||
if resource.MemoID != nil {
|
||||
memo, _ := s.Store.GetMemo(ctx, &store.FindMemo{
|
||||
ID: resource.MemoID,
|
||||
})
|
||||
if memo != nil {
|
||||
memoID = &memo.ID
|
||||
}
|
||||
}
|
||||
|
||||
return &apiv2pb.Resource{
|
||||
resourceMessage := &apiv2pb.Resource{
|
||||
Name: fmt.Sprintf("%s%d", ResourceNamePrefix, resource.ID),
|
||||
Uid: resource.UID,
|
||||
CreateTime: timestamppb.New(time.Unix(resource.CreatedTs, 0)),
|
||||
@ -200,8 +201,18 @@ func (s *APIV2Service) convertResourceFromStore(ctx context.Context, resource *s
|
||||
ExternalLink: resource.ExternalLink,
|
||||
Type: resource.Type,
|
||||
Size: resource.Size,
|
||||
MemoId: memoID,
|
||||
}
|
||||
if resource.MemoID != nil {
|
||||
memo, _ := s.Store.GetMemo(ctx, &store.FindMemo{
|
||||
ID: resource.MemoID,
|
||||
})
|
||||
if memo != nil {
|
||||
memoName := fmt.Sprintf("%s%d", MemoNamePrefix, memo.ID)
|
||||
resourceMessage.Memo = &memoName
|
||||
}
|
||||
}
|
||||
|
||||
return resourceMessage
|
||||
}
|
||||
|
||||
// SearchResourcesFilterCELAttributes are the CEL attributes for SearchResourcesFilter.
|
||||
|
@ -8,7 +8,7 @@ import { TAB_SPACE_WIDTH } from "@/helpers/consts";
|
||||
import { isValidUrl } from "@/helpers/utils";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
import { useGlobalStore, useResourceStore, useTagStore } from "@/store/module";
|
||||
import { extractMemoIdFromName, useMemoStore, useUserStore } from "@/store/v1";
|
||||
import { useMemoStore, useUserStore } from "@/store/v1";
|
||||
import { MemoRelation, MemoRelation_Type } from "@/types/proto/api/v2/memo_relation_service";
|
||||
import { Memo, Visibility } from "@/types/proto/api/v2/memo_service";
|
||||
import { Resource } from "@/types/proto/api/v2/resource_service";
|
||||
@ -233,9 +233,9 @@ const MemoEditor = (props: Props) => {
|
||||
await resourceStore.updateResource({
|
||||
resource: Resource.fromPartial({
|
||||
name: resource.name,
|
||||
memoId: extractMemoIdFromName(memoName),
|
||||
memo: memoName,
|
||||
}),
|
||||
updateMask: ["memo_id"],
|
||||
updateMask: ["memo"],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +1,3 @@
|
||||
export const isNullorUndefined = (value: any) => {
|
||||
return value === null || value === undefined;
|
||||
};
|
||||
|
||||
export const getElementBounding = (element: HTMLElement, relativeEl?: HTMLElement) => {
|
||||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
|
||||
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft;
|
||||
|
||||
relativeEl = relativeEl || document.body;
|
||||
|
||||
const elementRect = element.getBoundingClientRect();
|
||||
const relativeElRect = relativeEl.getBoundingClientRect();
|
||||
const relativeElPosition = window.getComputedStyle(relativeEl).getPropertyValue("position");
|
||||
|
||||
const bounding = {
|
||||
width: elementRect.width,
|
||||
height: elementRect.height,
|
||||
};
|
||||
|
||||
if ((relativeEl.tagName !== "BODY" && relativeElPosition === "relative") || relativeElPosition === "sticky") {
|
||||
return Object.assign(bounding, {
|
||||
top: elementRect.top - relativeElRect.top,
|
||||
left: elementRect.left - relativeElRect.left,
|
||||
});
|
||||
}
|
||||
|
||||
const isElementFixed = (element: HTMLElement): boolean => {
|
||||
const parentNode = element.parentNode;
|
||||
|
||||
if (!parentNode || parentNode.nodeName === "HTML") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const position = window.getComputedStyle(element).getPropertyValue("position");
|
||||
if (position === "fixed" || position === "static") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isElementFixed(parentNode as HTMLElement);
|
||||
};
|
||||
|
||||
if (isElementFixed(element)) {
|
||||
return Object.assign(bounding, {
|
||||
top: elementRect.top,
|
||||
left: elementRect.left,
|
||||
});
|
||||
}
|
||||
|
||||
return Object.assign(bounding, {
|
||||
top: elementRect.top + scrollTop,
|
||||
left: elementRect.left + scrollLeft,
|
||||
});
|
||||
};
|
||||
|
||||
export function absolutifyLink(rel: string): string {
|
||||
const anchor = document.createElement("a");
|
||||
anchor.setAttribute("href", rel);
|
||||
@ -75,15 +21,6 @@ export function convertFileToBase64(file: File): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
export const formatBytes = (bytes: number) => {
|
||||
if (bytes <= 0) return "0 Bytes";
|
||||
const k = 1024,
|
||||
dm = 2,
|
||||
sizes = ["Bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"],
|
||||
i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
|
||||
};
|
||||
|
||||
export const isValidUrl = (url: string): boolean => {
|
||||
try {
|
||||
new URL(url);
|
||||
|
@ -10,7 +10,7 @@ import ResourceIcon from "@/components/ResourceIcon";
|
||||
import { resourceServiceClient } from "@/grpcweb";
|
||||
import useLoading from "@/hooks/useLoading";
|
||||
import i18n from "@/i18n";
|
||||
import { MemoNamePrefix, extractMemoIdFromName, useMemoStore } from "@/store/v1";
|
||||
import { extractMemoIdFromName, useMemoStore } from "@/store/v1";
|
||||
import { Resource } from "@/types/proto/api/v2/resource_service";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
|
||||
@ -49,16 +49,14 @@ const Resources = () => {
|
||||
const memoStore = useMemoStore();
|
||||
const [resources, setResources] = useState<Resource[]>([]);
|
||||
const filteredResources = resources.filter((resource) => includes(resource.filename, state.searchQuery));
|
||||
const groupedResources = groupResourcesByDate(filteredResources.filter((resource) => resource.memoId));
|
||||
const unusedResources = filteredResources.filter((resource) => !resource.memoId);
|
||||
const groupedResources = groupResourcesByDate(filteredResources.filter((resource) => resource.memo));
|
||||
const unusedResources = filteredResources.filter((resource) => !resource.memo);
|
||||
|
||||
useEffect(() => {
|
||||
resourceServiceClient.listResources({}).then(({ resources }) => {
|
||||
setResources(resources);
|
||||
loadingState.setFinish();
|
||||
Promise.all(
|
||||
resources.map((resource: any) => (resource.memoId ? memoStore.getOrFetchMemoByName(`${MemoNamePrefix}${resource.memoId}`) : null)),
|
||||
);
|
||||
Promise.all(resources.map((resource) => (resource.memo ? memoStore.getOrFetchMemoByName(resource.memo) : null)));
|
||||
});
|
||||
}, []);
|
||||
|
||||
@ -72,7 +70,7 @@ const Resources = () => {
|
||||
for (const resource of unusedResources) {
|
||||
await resourceServiceClient.deleteResource({ name: resource.name });
|
||||
}
|
||||
setResources(resources.filter((resource) => resource.memoId));
|
||||
setResources(resources.filter((resource) => resource.memo));
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -121,7 +119,7 @@ const Resources = () => {
|
||||
</div>
|
||||
<div className="w-full max-w-[calc(100%-4rem)] sm:max-w-[calc(100%-6rem)] flex flex-row justify-start items-start gap-4 flex-wrap">
|
||||
{resources.map((resource) => {
|
||||
const relatedMemo = resource.memoId ? memoStore.getMemoByName(`${MemoNamePrefix}${resource.memoId}`) : null;
|
||||
const relatedMemo = resource.memo ? memoStore.getMemoByName(resource.memo) : null;
|
||||
return (
|
||||
<div key={resource.name} className="w-24 sm:w-32 h-auto flex flex-col justify-start items-start">
|
||||
<div className="w-24 h-24 flex justify-center items-center sm:w-32 sm:h-32 border dark:border-zinc-900 overflow-clip rounded-xl cursor-pointer hover:shadow hover:opacity-80">
|
||||
|
Reference in New Issue
Block a user