mirror of
https://github.com/usememos/memos.git
synced 2025-02-16 03:12:13 +01:00
chore: remove resource public id (#1912)
* chore: remove resource public id * chore: update
This commit is contained in:
parent
2157651d17
commit
7e391bd53d
@ -8,10 +8,10 @@ import (
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/usememos/memos/api/v1/auth"
|
||||
"github.com/usememos/memos/common/util"
|
||||
"github.com/usememos/memos/plugin/idp"
|
||||
"github.com/usememos/memos/plugin/idp/oauth2"
|
||||
"github.com/usememos/memos/server/auth"
|
||||
"github.com/usememos/memos/store"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
@ -10,8 +10,8 @@ import (
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/usememos/memos/api/v1/auth"
|
||||
"github.com/usememos/memos/common/util"
|
||||
"github.com/usememos/memos/server/auth"
|
||||
"github.com/usememos/memos/store"
|
||||
)
|
||||
|
||||
|
@ -43,7 +43,6 @@ type Resource struct {
|
||||
ExternalLink string `json:"externalLink"`
|
||||
Type string `json:"type"`
|
||||
Size int64 `json:"size"`
|
||||
PublicID string `json:"publicId"`
|
||||
|
||||
// Related fields
|
||||
LinkedMemoAmount int `json:"linkedMemoAmount"`
|
||||
@ -54,7 +53,6 @@ type CreateResourceRequest struct {
|
||||
InternalPath string `json:"internalPath"`
|
||||
ExternalLink string `json:"externalLink"`
|
||||
Type string `json:"type"`
|
||||
PublicID string `json:"publicId"`
|
||||
DownloadToLocal bool `json:"downloadToLocal"`
|
||||
}
|
||||
|
||||
@ -62,12 +60,10 @@ type FindResourceRequest struct {
|
||||
ID *int `json:"id"`
|
||||
CreatorID *int `json:"creatorId"`
|
||||
Filename *string `json:"filename"`
|
||||
PublicID *string `json:"publicId"`
|
||||
}
|
||||
|
||||
type UpdateResourceRequest struct {
|
||||
Filename *string `json:"filename"`
|
||||
ResetPublicID *bool `json:"resetPublicId"`
|
||||
Filename *string `json:"filename"`
|
||||
}
|
||||
|
||||
const (
|
||||
@ -101,7 +97,6 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
Filename: request.Filename,
|
||||
ExternalLink: request.ExternalLink,
|
||||
Type: request.Type,
|
||||
PublicID: util.GenUUID(),
|
||||
}
|
||||
if request.ExternalLink != "" {
|
||||
// Only allow those external links scheme with http/https
|
||||
@ -195,7 +190,6 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
}
|
||||
defer sourceFile.Close()
|
||||
|
||||
create := &store.Resource{}
|
||||
systemSettingStorageServiceID, err := s.Store.GetSystemSetting(ctx, &store.FindSystemSetting{Name: SystemSettingStorageServiceIDName.String()})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find storage").SetInternal(err)
|
||||
@ -208,7 +202,7 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
}
|
||||
}
|
||||
|
||||
publicID := util.GenUUID()
|
||||
var create *store.Resource
|
||||
if storageServiceID == DatabaseStorage {
|
||||
fileBytes, err := io.ReadAll(sourceFile)
|
||||
if err != nil {
|
||||
@ -229,7 +223,7 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find local storage path setting").SetInternal(err)
|
||||
}
|
||||
localStoragePath := "assets/{publicid}"
|
||||
localStoragePath := "assets/{filename}"
|
||||
if systemSettingLocalStoragePath != nil && systemSettingLocalStoragePath.Value != "" {
|
||||
err = json.Unmarshal([]byte(systemSettingLocalStoragePath.Value), &localStoragePath)
|
||||
if err != nil {
|
||||
@ -237,10 +231,10 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
}
|
||||
}
|
||||
filePath := filepath.FromSlash(localStoragePath)
|
||||
if !strings.Contains(filePath, "{publicid}") {
|
||||
filePath = filepath.Join(filePath, "{publicid}")
|
||||
if !strings.Contains(filePath, "{filename}") {
|
||||
filePath = filepath.Join(filePath, "{filename}")
|
||||
}
|
||||
filePath = filepath.Join(s.Profile.Data, replacePathTemplate(filePath, file.Filename, publicID+filepath.Ext(file.Filename)))
|
||||
filePath = filepath.Join(s.Profile.Data, replacePathTemplate(filePath, file.Filename))
|
||||
|
||||
dir := filepath.Dir(filePath)
|
||||
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
@ -292,10 +286,10 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
}
|
||||
|
||||
filePath := s3Config.Path
|
||||
if !strings.Contains(filePath, "{publicid}") {
|
||||
filePath = path.Join(filePath, "{publicid}")
|
||||
if !strings.Contains(filePath, "{filename}") {
|
||||
filePath = path.Join(filePath, "{filename}")
|
||||
}
|
||||
filePath = replacePathTemplate(filePath, file.Filename, publicID+filepath.Ext(file.Filename))
|
||||
filePath = replacePathTemplate(filePath, file.Filename)
|
||||
_, filename := filepath.Split(filePath)
|
||||
link, err := s3Client.UploadFile(ctx, filePath, filetype, sourceFile)
|
||||
if err != nil {
|
||||
@ -313,7 +307,6 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
}
|
||||
}
|
||||
|
||||
create.PublicID = publicID
|
||||
resource, err := s.Store.CreateResource(ctx, create)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
||||
@ -389,10 +382,6 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
if request.Filename != nil && *request.Filename != "" {
|
||||
update.Filename = request.Filename
|
||||
}
|
||||
if request.ResetPublicID != nil && *request.ResetPublicID {
|
||||
publicID := util.GenUUID()
|
||||
update.PublicID = &publicID
|
||||
}
|
||||
|
||||
resource, err = s.Store.UpdateResource(ctx, update)
|
||||
if err != nil {
|
||||
@ -431,7 +420,7 @@ func (s *APIV1Service) registerResourceRoutes(g *echo.Group) {
|
||||
}
|
||||
|
||||
ext := filepath.Ext(resource.Filename)
|
||||
thumbnailPath := path.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d-%s%s", resource.ID, resource.PublicID, ext))
|
||||
thumbnailPath := path.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d%s", resource.ID, ext))
|
||||
if err := os.Remove(thumbnailPath); err != nil {
|
||||
log.Warn(fmt.Sprintf("failed to delete local thumbnail with path %s", thumbnailPath), zap.Error(err))
|
||||
}
|
||||
@ -496,7 +485,7 @@ func (s *APIV1Service) registerResourcePublicRoutes(g *echo.Group) {
|
||||
|
||||
if c.QueryParam("thumbnail") == "1" && util.HasPrefixes(resource.Type, "image/png", "image/jpeg") {
|
||||
ext := filepath.Ext(resource.Filename)
|
||||
thumbnailPath := path.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d-%s%s", resource.ID, resource.PublicID, ext))
|
||||
thumbnailPath := path.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d%s", resource.ID, ext))
|
||||
thumbnailBlob, err := getOrGenerateThumbnailImage(blob, thumbnailPath)
|
||||
if err != nil {
|
||||
log.Warn(fmt.Sprintf("failed to get or generate local thumbnail with path %s", thumbnailPath), zap.Error(err))
|
||||
@ -516,8 +505,8 @@ func (s *APIV1Service) registerResourcePublicRoutes(g *echo.Group) {
|
||||
}
|
||||
return c.Stream(http.StatusOK, resourceType, bytes.NewReader(blob))
|
||||
}
|
||||
|
||||
g.GET("/r/:resourceId", f)
|
||||
g.GET("/r/:resourceId/", f)
|
||||
g.GET("/r/:resourceId/*", f)
|
||||
}
|
||||
|
||||
@ -543,12 +532,10 @@ func (s *APIV1Service) createResourceCreateActivity(ctx context.Context, resourc
|
||||
return err
|
||||
}
|
||||
|
||||
func replacePathTemplate(path, filename, publicID string) string {
|
||||
func replacePathTemplate(path, filename string) string {
|
||||
t := time.Now()
|
||||
path = fileKeyPattern.ReplaceAllStringFunc(path, func(s string) string {
|
||||
switch s {
|
||||
case "{publicid}":
|
||||
return publicID
|
||||
case "{filename}":
|
||||
return filename
|
||||
case "{timestamp}":
|
||||
@ -624,7 +611,7 @@ func checkResourceVisibility(ctx context.Context, s *store.Store, resourceID int
|
||||
return store.Private, err
|
||||
}
|
||||
|
||||
// If resource is belongs to no memo, it'll always PRIVATE
|
||||
// If resource is belongs to no memo, it'll always PRIVATE.
|
||||
if len(memoResources) == 0 {
|
||||
return store.Private, nil
|
||||
}
|
||||
@ -640,7 +627,7 @@ func checkResourceVisibility(ctx context.Context, s *store.Store, resourceID int
|
||||
|
||||
var isProtected bool
|
||||
for _, visibility := range visibilityList {
|
||||
// If any memo is PUBLIC, resource do
|
||||
// If any memo is PUBLIC, resource should be PUBLIC too.
|
||||
if visibility == store.Public {
|
||||
return store.Public, nil
|
||||
}
|
||||
@ -650,12 +637,10 @@ func checkResourceVisibility(ctx context.Context, s *store.Store, resourceID int
|
||||
}
|
||||
}
|
||||
|
||||
// If no memo is PUBLIC, but any memo is PROTECTED, resource do
|
||||
if isProtected {
|
||||
return store.Protected, nil
|
||||
}
|
||||
|
||||
// If all memo is PRIVATE, the resource do
|
||||
return store.Private, nil
|
||||
}
|
||||
|
||||
@ -671,7 +656,6 @@ func convertResourceFromStore(resource *store.Resource) *Resource {
|
||||
ExternalLink: resource.ExternalLink,
|
||||
Type: resource.Type,
|
||||
Size: resource.Size,
|
||||
PublicID: resource.PublicID,
|
||||
LinkedMemoAmount: resource.LinkedMemoAmount,
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ func (s *APIV1Service) generateRSSFromMemoList(ctx context.Context, memoList []*
|
||||
if resource.ExternalLink != "" {
|
||||
enclosure.Url = resource.ExternalLink
|
||||
} else {
|
||||
enclosure.Url = baseURL + "/o/r/" + strconv.Itoa(resource.ID) + "/" + resource.PublicID + "/" + resource.Filename
|
||||
enclosure.Url = baseURL + "/o/r/" + strconv.Itoa(resource.ID)
|
||||
}
|
||||
enclosure.Length = strconv.Itoa(int(resource.Size))
|
||||
enclosure.Type = resource.Type
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
apiv1 "github.com/usememos/memos/api/v1"
|
||||
"github.com/usememos/memos/common/util"
|
||||
"github.com/usememos/memos/plugin/telegram"
|
||||
"github.com/usememos/memos/store"
|
||||
)
|
||||
@ -94,7 +93,6 @@ func (t *telegramHandler) MessageHandle(ctx context.Context, bot *telegram.Bot,
|
||||
Type: mime,
|
||||
Size: int64(len(blob)),
|
||||
Blob: blob,
|
||||
PublicID: util.GenUUID(),
|
||||
})
|
||||
if err != nil {
|
||||
_, err := bot.EditMessage(ctx, message.Chat.ID, reply.MessageID, fmt.Sprintf("failed to CreateResource: %s", err), nil)
|
||||
|
@ -76,9 +76,7 @@ CREATE TABLE resource (
|
||||
external_link TEXT NOT NULL DEFAULT '',
|
||||
type TEXT NOT NULL DEFAULT '',
|
||||
size INTEGER NOT NULL DEFAULT 0,
|
||||
internal_path TEXT NOT NULL DEFAULT '',
|
||||
public_id TEXT NOT NULL DEFAULT '',
|
||||
UNIQUE(id, public_id)
|
||||
internal_path TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
-- memo_resource
|
||||
|
25
store/db/migration/prod/0.14/00_drop_resource_public_id.sql
Normal file
25
store/db/migration/prod/0.14/00_drop_resource_public_id.sql
Normal file
@ -0,0 +1,25 @@
|
||||
DROP TABLE IF EXISTS resource_temp;
|
||||
|
||||
CREATE TABLE resource_temp (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
creator_id INTEGER NOT NULL,
|
||||
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
filename TEXT NOT NULL DEFAULT '',
|
||||
blob BLOB DEFAULT NULL,
|
||||
external_link TEXT NOT NULL DEFAULT '',
|
||||
type TEXT NOT NULL DEFAULT '',
|
||||
size INTEGER NOT NULL DEFAULT 0,
|
||||
internal_path TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
INSERT INTO
|
||||
resource_temp (id, creator_id, created_ts, updated_ts, filename, blob, external_link, type, size, internal_path)
|
||||
SELECT
|
||||
id, creator_id, created_ts, updated_ts, filename, blob, external_link, type, size, internal_path
|
||||
FROM
|
||||
resource;
|
||||
|
||||
DROP TABLE resource;
|
||||
|
||||
ALTER TABLE resource_temp RENAME TO resource;
|
@ -76,9 +76,7 @@ CREATE TABLE resource (
|
||||
external_link TEXT NOT NULL DEFAULT '',
|
||||
type TEXT NOT NULL DEFAULT '',
|
||||
size INTEGER NOT NULL DEFAULT 0,
|
||||
internal_path TEXT NOT NULL DEFAULT '',
|
||||
public_id TEXT NOT NULL DEFAULT '',
|
||||
UNIQUE(id, public_id)
|
||||
internal_path TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
-- memo_resource
|
||||
|
@ -22,7 +22,6 @@ type Resource struct {
|
||||
ExternalLink string
|
||||
Type string
|
||||
Size int64
|
||||
PublicID string
|
||||
LinkedMemoAmount int
|
||||
}
|
||||
|
||||
@ -32,7 +31,6 @@ type FindResource struct {
|
||||
CreatorID *int
|
||||
Filename *string
|
||||
MemoID *int
|
||||
PublicID *string
|
||||
Limit *int
|
||||
Offset *int
|
||||
}
|
||||
@ -41,7 +39,6 @@ type UpdateResource struct {
|
||||
ID int
|
||||
UpdatedTs *int64
|
||||
Filename *string
|
||||
PublicID *string
|
||||
}
|
||||
|
||||
type DeleteResource struct {
|
||||
@ -63,13 +60,12 @@ func (s *Store) CreateResource(ctx context.Context, create *Resource) (*Resource
|
||||
type,
|
||||
size,
|
||||
creator_id,
|
||||
internal_path,
|
||||
public_id
|
||||
internal_path
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING id, created_ts, updated_ts
|
||||
`,
|
||||
create.Filename, create.Blob, create.ExternalLink, create.Type, create.Size, create.CreatorID, create.InternalPath, create.PublicID,
|
||||
create.Filename, create.Blob, create.ExternalLink, create.Type, create.Size, create.CreatorID, create.InternalPath,
|
||||
).Scan(&create.ID, &create.CreatedTs, &create.UpdatedTs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -98,10 +94,6 @@ func (s *Store) ListResources(ctx context.Context, find *FindResource) ([]*Resou
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
@ -143,12 +135,9 @@ func (s *Store) UpdateResource(ctx context.Context, update *UpdateResource) (*Re
|
||||
if v := update.Filename; v != nil {
|
||||
set, args = append(set, "filename = ?"), append(args, *v)
|
||||
}
|
||||
if v := update.PublicID; v != nil {
|
||||
set, args = append(set, "public_id = ?"), append(args, *v)
|
||||
}
|
||||
|
||||
args = append(args, update.ID)
|
||||
fields := []string{"id", "filename", "external_link", "type", "size", "creator_id", "created_ts", "updated_ts", "internal_path", "public_id"}
|
||||
fields := []string{"id", "filename", "external_link", "type", "size", "creator_id", "created_ts", "updated_ts", "internal_path"}
|
||||
query := `
|
||||
UPDATE resource
|
||||
SET ` + strings.Join(set, ", ") + `
|
||||
@ -165,7 +154,6 @@ func (s *Store) UpdateResource(ctx context.Context, update *UpdateResource) (*Re
|
||||
&resource.CreatedTs,
|
||||
&resource.UpdatedTs,
|
||||
&resource.InternalPath,
|
||||
&resource.PublicID,
|
||||
}
|
||||
if err := tx.QueryRowContext(ctx, query, args...).Scan(dests...); err != nil {
|
||||
return nil, err
|
||||
@ -215,11 +203,8 @@ func listResources(ctx context.Context, tx *sql.Tx, find *FindResource) ([]*Reso
|
||||
if v := find.MemoID; v != nil {
|
||||
where, args = append(where, "resource.id in (SELECT resource_id FROM memo_resource WHERE memo_id = ?)"), append(args, *v)
|
||||
}
|
||||
if v := find.PublicID; v != nil {
|
||||
where, args = append(where, "resource.public_id = ?"), append(args, *v)
|
||||
}
|
||||
|
||||
fields := []string{"resource.id", "resource.filename", "resource.external_link", "resource.type", "resource.size", "resource.creator_id", "resource.created_ts", "resource.updated_ts", "internal_path", "public_id"}
|
||||
fields := []string{"resource.id", "resource.filename", "resource.external_link", "resource.type", "resource.size", "resource.creator_id", "resource.created_ts", "resource.updated_ts", "internal_path"}
|
||||
if find.GetBlob {
|
||||
fields = append(fields, "resource.blob")
|
||||
}
|
||||
@ -261,7 +246,6 @@ func listResources(ctx context.Context, tx *sql.Tx, find *FindResource) ([]*Reso
|
||||
&resource.CreatedTs,
|
||||
&resource.UpdatedTs,
|
||||
&resource.InternalPath,
|
||||
&resource.PublicID,
|
||||
}
|
||||
if find.GetBlob {
|
||||
dests = append(dests, &resource.Blob)
|
||||
|
@ -19,7 +19,6 @@ func TestResourceStore(t *testing.T) {
|
||||
ExternalLink: "",
|
||||
Type: "application/epub+zip",
|
||||
Size: 637607,
|
||||
PublicID: "a02748e2-9b56-46b2-8b1f-72d686d52f77",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
26
web/src/components/LearnMore.tsx
Normal file
26
web/src/components/LearnMore.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import { Tooltip } from "@mui/joy";
|
||||
import Icon from "./Icon";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
url: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
const LearnMore: React.FC<Props> = (props: Props) => {
|
||||
const { className, url, title } = props;
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={title ?? t("common.learn-more")} placement="top">
|
||||
<a className={`text-gray-500 dark:text-gray-400 hover:text-blue-600 ${className}`} href={url} target="_blank">
|
||||
<Icon.ExternalLink className="w-4 h-auto" />
|
||||
</a>
|
||||
</Tooltip>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LearnMore;
|
@ -37,21 +37,6 @@ const ResourceItemDropdown = ({ resource }: Props) => {
|
||||
toast.success(t("message.succeed-copy-resource-link"));
|
||||
};
|
||||
|
||||
const handleResetResourceLinkBtnClick = (resource: Resource) => {
|
||||
showCommonDialog({
|
||||
title: t("resource.reset-resource-link"),
|
||||
content: t("resource.reset-link-prompt"),
|
||||
style: "warning",
|
||||
dialogName: "reset-resource-link-dialog",
|
||||
onConfirm: async () => {
|
||||
await resourceStore.patchResource({
|
||||
id: resource.id,
|
||||
resetPublicId: true,
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleRenameBtnClick = (resource: Resource) => {
|
||||
showChangeResourceFilenameDialog(resource.id, resource.filename);
|
||||
};
|
||||
@ -91,12 +76,6 @@ const ResourceItemDropdown = ({ resource }: Props) => {
|
||||
>
|
||||
{t("resource.copy-link")}
|
||||
</button>
|
||||
<button
|
||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-600"
|
||||
onClick={() => handleResetResourceLinkBtnClick(resource)}
|
||||
>
|
||||
{t("resource.reset-link")}
|
||||
</button>
|
||||
<button
|
||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-600"
|
||||
onClick={() => handleRenameBtnClick(resource)}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Button, Input } from "@mui/joy";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useGlobalStore } from "@/store/module";
|
||||
import * as api from "@/helpers/api";
|
||||
import { generateDialog } from "./Dialog";
|
||||
import Icon from "./Icon";
|
||||
import HelpButton from "./kit/HelpButton";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import LearnMore from "./LearnMore";
|
||||
|
||||
interface Props extends DialogProps {
|
||||
localStoragePath?: string;
|
||||
@ -51,8 +51,8 @@ const UpdateLocalStorageDialog: React.FC<Props> = (props: Props) => {
|
||||
<div className="dialog-content-container max-w-xs">
|
||||
<p className="text-sm break-words mb-1">{t("setting.storage-section.update-local-path-description")}</p>
|
||||
<div className="flex flex-row">
|
||||
<p className="text-sm text-gray-400 mb-2 break-all">e.g. {"assets/{publicid}"}</p>
|
||||
<HelpButton hint={t("common.learn-more")} url="https://usememos.com/docs/local-storage" />
|
||||
<p className="text-sm text-gray-400 mb-2 break-all">e.g. {"assets/{filename}"}</p>
|
||||
<LearnMore url="https://usememos.com/docs/local-storage" />
|
||||
</div>
|
||||
<Input
|
||||
className="mb-2"
|
||||
|
@ -214,7 +214,7 @@ const ResourcesDashboard = () => {
|
||||
<div className="w-full flex flex-col justify-start items-start px-4 py-3 rounded-xl bg-white dark:bg-zinc-700 text-black dark:text-gray-300">
|
||||
<div className="relative w-full flex flex-row justify-between items-center">
|
||||
<p className="flex flex-row justify-start items-center select-none rounded">
|
||||
<Icon.Paperclip className="w-5 h-auto mr-1" /> {t("common.resources")}
|
||||
<Icon.Paperclip className="w-5 h-auto mr-1 ml-2" /> {t("common.resources")}
|
||||
</p>
|
||||
<ResourceSearchBar setQuery={handleSearchResourceInputChange} />
|
||||
</div>
|
||||
|
2
web/src/types/modules/resource.d.ts
vendored
2
web/src/types/modules/resource.d.ts
vendored
@ -10,7 +10,6 @@ interface Resource {
|
||||
externalLink: string;
|
||||
type: string;
|
||||
size: string;
|
||||
publicId: string;
|
||||
|
||||
linkedMemoAmount: number;
|
||||
}
|
||||
@ -25,7 +24,6 @@ interface ResourceCreate {
|
||||
interface ResourcePatch {
|
||||
id: ResourceId;
|
||||
filename?: string;
|
||||
resetPublicId?: boolean;
|
||||
}
|
||||
|
||||
interface ResourceFind {
|
||||
|
@ -3,5 +3,5 @@ export const getResourceUrl = (resource: Resource, withOrigin = true) => {
|
||||
return resource.externalLink;
|
||||
}
|
||||
|
||||
return `${withOrigin ? window.location.origin : ""}/o/r/${resource.id}/${resource.publicId}/${encodeURIComponent(resource.filename)}`;
|
||||
return `${withOrigin ? window.location.origin : ""}/o/r/${resource.id}`;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user