mirror of
https://github.com/usememos/memos.git
synced 2025-03-19 20:20:06 +01:00
chore: fix calendar timestamps
This commit is contained in:
parent
bdc257d837
commit
139090fb8f
@ -357,42 +357,6 @@ paths:
|
|||||||
$ref: '#/definitions/v1CreateMemoRequest'
|
$ref: '#/definitions/v1CreateMemoRequest'
|
||||||
tags:
|
tags:
|
||||||
- MemoService
|
- MemoService
|
||||||
/api/v1/memos/stats:
|
|
||||||
get:
|
|
||||||
summary: GetUserMemosStats gets stats of memos for a user.
|
|
||||||
operationId: MemoService_GetUserMemosStats
|
|
||||||
responses:
|
|
||||||
"200":
|
|
||||||
description: A successful response.
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/v1GetUserMemosStatsResponse'
|
|
||||||
default:
|
|
||||||
description: An unexpected error response.
|
|
||||||
schema:
|
|
||||||
$ref: '#/definitions/googlerpcStatus'
|
|
||||||
parameters:
|
|
||||||
- name: name
|
|
||||||
description: |-
|
|
||||||
name is the name of the user to get stats for.
|
|
||||||
Format: users/{id}
|
|
||||||
in: query
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
- name: timezone
|
|
||||||
description: |-
|
|
||||||
timezone location
|
|
||||||
Format: uses tz identifier
|
|
||||||
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
|
||||||
in: query
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
- name: filter
|
|
||||||
description: Same as ListMemosRequest.filter
|
|
||||||
in: query
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
tags:
|
|
||||||
- MemoService
|
|
||||||
/api/v1/memos:by-uid/{uid}:
|
/api/v1/memos:by-uid/{uid}:
|
||||||
get:
|
get:
|
||||||
summary: GetMemoByUid gets a memo by uid
|
summary: GetMemoByUid gets a memo by uid
|
||||||
@ -2417,17 +2381,6 @@ definitions:
|
|||||||
content:
|
content:
|
||||||
type: string
|
type: string
|
||||||
format: byte
|
format: byte
|
||||||
v1GetUserMemosStatsResponse:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
stats:
|
|
||||||
type: object
|
|
||||||
additionalProperties:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
description: |-
|
|
||||||
stats is the stats of memo creating/updating activities.
|
|
||||||
key is the year-month-day string. e.g. "2020-01-01".
|
|
||||||
v1HTMLElementNode:
|
v1HTMLElementNode:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -2555,11 +2508,11 @@ definitions:
|
|||||||
v1ListMemoPropertiesResponse:
|
v1ListMemoPropertiesResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
properties:
|
entities:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
$ref: '#/definitions/v1MemoProperty'
|
$ref: '#/definitions/v1MemoPropertyEntity'
|
||||||
v1ListMemoReactionsResponse:
|
v1ListMemoReactionsResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@ -2744,6 +2697,21 @@ definitions:
|
|||||||
type: boolean
|
type: boolean
|
||||||
hasIncompleteTasks:
|
hasIncompleteTasks:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
v1MemoPropertyEntity:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
title: |-
|
||||||
|
The name of the memo property.
|
||||||
|
Format: memos/{id}/properties/{property_id}
|
||||||
|
property:
|
||||||
|
$ref: '#/definitions/v1MemoProperty'
|
||||||
|
readOnly: true
|
||||||
|
displayTime:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
readOnly: true
|
||||||
v1MemoRelation:
|
v1MemoRelation:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -123,11 +123,6 @@ service MemoService {
|
|||||||
option (google.api.http) = {get: "/api/v1/{name=memos/*}/comments"};
|
option (google.api.http) = {get: "/api/v1/{name=memos/*}/comments"};
|
||||||
option (google.api.method_signature) = "name";
|
option (google.api.method_signature) = "name";
|
||||||
}
|
}
|
||||||
// GetUserMemosStats gets stats of memos for a user.
|
|
||||||
rpc GetUserMemosStats(GetUserMemosStatsRequest) returns (GetUserMemosStatsResponse) {
|
|
||||||
option (google.api.http) = {get: "/api/v1/memos/stats"};
|
|
||||||
option (google.api.method_signature) = "username";
|
|
||||||
}
|
|
||||||
// ListMemoReactions lists reactions for a memo.
|
// ListMemoReactions lists reactions for a memo.
|
||||||
rpc ListMemoReactions(ListMemoReactionsRequest) returns (ListMemoReactionsResponse) {
|
rpc ListMemoReactions(ListMemoReactionsRequest) returns (ListMemoReactionsResponse) {
|
||||||
option (google.api.http) = {get: "/api/v1/{name=memos/*}/reactions"};
|
option (google.api.http) = {get: "/api/v1/{name=memos/*}/reactions"};
|
||||||
@ -281,7 +276,17 @@ message ListMemoPropertiesRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ListMemoPropertiesResponse {
|
message ListMemoPropertiesResponse {
|
||||||
repeated MemoProperty properties = 1;
|
repeated MemoPropertyEntity entities = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MemoPropertyEntity {
|
||||||
|
// The name of the memo property.
|
||||||
|
// Format: memos/{id}/properties/{property_id}
|
||||||
|
string name = 1;
|
||||||
|
|
||||||
|
MemoProperty property = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||||
|
|
||||||
|
google.protobuf.Timestamp display_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||||
}
|
}
|
||||||
|
|
||||||
message RebuildMemoPropertyRequest {
|
message RebuildMemoPropertyRequest {
|
||||||
@ -377,26 +382,6 @@ message ListMemoCommentsResponse {
|
|||||||
repeated Memo memos = 1;
|
repeated Memo memos = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetUserMemosStatsRequest {
|
|
||||||
// name is the name of the user to get stats for.
|
|
||||||
// Format: users/{id}
|
|
||||||
string name = 1;
|
|
||||||
|
|
||||||
// timezone location
|
|
||||||
// Format: uses tz identifier
|
|
||||||
// https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
|
||||||
string timezone = 2;
|
|
||||||
|
|
||||||
// Same as ListMemosRequest.filter
|
|
||||||
string filter = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GetUserMemosStatsResponse {
|
|
||||||
// stats is the stats of memo creating/updating activities.
|
|
||||||
// key is the year-month-day string. e.g. "2020-01-01".
|
|
||||||
map<string, int32> stats = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ListMemoReactionsRequest {
|
message ListMemoReactionsRequest {
|
||||||
// The name of the memo.
|
// The name of the memo.
|
||||||
// Format: memos/{id}
|
// Format: memos/{id}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1043,42 +1043,6 @@ func local_request_MemoService_ListMemoComments_0(ctx context.Context, marshaler
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
filter_MemoService_GetUserMemosStats_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
|
||||||
)
|
|
||||||
|
|
||||||
func request_MemoService_GetUserMemosStats_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
|
||||||
var protoReq GetUserMemosStatsRequest
|
|
||||||
var metadata runtime.ServerMetadata
|
|
||||||
|
|
||||||
if err := req.ParseForm(); err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
|
||||||
}
|
|
||||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_MemoService_GetUserMemosStats_0); err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := client.GetUserMemosStats(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
|
||||||
return msg, metadata, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func local_request_MemoService_GetUserMemosStats_0(ctx context.Context, marshaler runtime.Marshaler, server MemoServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
|
||||||
var protoReq GetUserMemosStatsRequest
|
|
||||||
var metadata runtime.ServerMetadata
|
|
||||||
|
|
||||||
if err := req.ParseForm(); err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
|
||||||
}
|
|
||||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_MemoService_GetUserMemosStats_0); err != nil {
|
|
||||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
msg, err := server.GetUserMemosStats(ctx, &protoReq)
|
|
||||||
return msg, metadata, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func request_MemoService_ListMemoReactions_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
func request_MemoService_ListMemoReactions_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||||
var protoReq ListMemoReactionsRequest
|
var protoReq ListMemoReactionsRequest
|
||||||
var metadata runtime.ServerMetadata
|
var metadata runtime.ServerMetadata
|
||||||
@ -1699,31 +1663,6 @@ func RegisterMemoServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.Handle("GET", pattern_MemoService_GetUserMemosStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
|
||||||
defer cancel()
|
|
||||||
var stream runtime.ServerTransportStream
|
|
||||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
|
||||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
|
||||||
var err error
|
|
||||||
var annotatedContext context.Context
|
|
||||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.MemoService/GetUserMemosStats", runtime.WithHTTPPathPattern("/api/v1/memos/stats"))
|
|
||||||
if err != nil {
|
|
||||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, md, err := local_request_MemoService_GetUserMemosStats_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
|
||||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
|
||||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
|
||||||
if err != nil {
|
|
||||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_MemoService_GetUserMemosStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
mux.Handle("GET", pattern_MemoService_ListMemoReactions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
mux.Handle("GET", pattern_MemoService_ListMemoReactions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -2236,28 +2175,6 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
mux.Handle("GET", pattern_MemoService_GetUserMemosStats_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
|
||||||
defer cancel()
|
|
||||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
|
||||||
var err error
|
|
||||||
var annotatedContext context.Context
|
|
||||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.MemoService/GetUserMemosStats", runtime.WithHTTPPathPattern("/api/v1/memos/stats"))
|
|
||||||
if err != nil {
|
|
||||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, md, err := request_MemoService_GetUserMemosStats_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
|
||||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
|
||||||
if err != nil {
|
|
||||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
forward_MemoService_GetUserMemosStats_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
mux.Handle("GET", pattern_MemoService_ListMemoReactions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
mux.Handle("GET", pattern_MemoService_ListMemoReactions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||||
ctx, cancel := context.WithCancel(req.Context())
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -2364,8 +2281,6 @@ var (
|
|||||||
|
|
||||||
pattern_MemoService_ListMemoComments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "memos", "name", "comments"}, ""))
|
pattern_MemoService_ListMemoComments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "memos", "name", "comments"}, ""))
|
||||||
|
|
||||||
pattern_MemoService_GetUserMemosStats_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "memos", "stats"}, ""))
|
|
||||||
|
|
||||||
pattern_MemoService_ListMemoReactions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "memos", "name", "reactions"}, ""))
|
pattern_MemoService_ListMemoReactions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "memos", "name", "reactions"}, ""))
|
||||||
|
|
||||||
pattern_MemoService_UpsertMemoReaction_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "memos", "name", "reactions"}, ""))
|
pattern_MemoService_UpsertMemoReaction_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "memos", "name", "reactions"}, ""))
|
||||||
@ -2410,8 +2325,6 @@ var (
|
|||||||
|
|
||||||
forward_MemoService_ListMemoComments_0 = runtime.ForwardResponseMessage
|
forward_MemoService_ListMemoComments_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
forward_MemoService_GetUserMemosStats_0 = runtime.ForwardResponseMessage
|
|
||||||
|
|
||||||
forward_MemoService_ListMemoReactions_0 = runtime.ForwardResponseMessage
|
forward_MemoService_ListMemoReactions_0 = runtime.ForwardResponseMessage
|
||||||
|
|
||||||
forward_MemoService_UpsertMemoReaction_0 = runtime.ForwardResponseMessage
|
forward_MemoService_UpsertMemoReaction_0 = runtime.ForwardResponseMessage
|
||||||
|
@ -38,7 +38,6 @@ const (
|
|||||||
MemoService_ListMemoRelations_FullMethodName = "/memos.api.v1.MemoService/ListMemoRelations"
|
MemoService_ListMemoRelations_FullMethodName = "/memos.api.v1.MemoService/ListMemoRelations"
|
||||||
MemoService_CreateMemoComment_FullMethodName = "/memos.api.v1.MemoService/CreateMemoComment"
|
MemoService_CreateMemoComment_FullMethodName = "/memos.api.v1.MemoService/CreateMemoComment"
|
||||||
MemoService_ListMemoComments_FullMethodName = "/memos.api.v1.MemoService/ListMemoComments"
|
MemoService_ListMemoComments_FullMethodName = "/memos.api.v1.MemoService/ListMemoComments"
|
||||||
MemoService_GetUserMemosStats_FullMethodName = "/memos.api.v1.MemoService/GetUserMemosStats"
|
|
||||||
MemoService_ListMemoReactions_FullMethodName = "/memos.api.v1.MemoService/ListMemoReactions"
|
MemoService_ListMemoReactions_FullMethodName = "/memos.api.v1.MemoService/ListMemoReactions"
|
||||||
MemoService_UpsertMemoReaction_FullMethodName = "/memos.api.v1.MemoService/UpsertMemoReaction"
|
MemoService_UpsertMemoReaction_FullMethodName = "/memos.api.v1.MemoService/UpsertMemoReaction"
|
||||||
MemoService_DeleteMemoReaction_FullMethodName = "/memos.api.v1.MemoService/DeleteMemoReaction"
|
MemoService_DeleteMemoReaction_FullMethodName = "/memos.api.v1.MemoService/DeleteMemoReaction"
|
||||||
@ -84,8 +83,6 @@ type MemoServiceClient interface {
|
|||||||
CreateMemoComment(ctx context.Context, in *CreateMemoCommentRequest, opts ...grpc.CallOption) (*Memo, error)
|
CreateMemoComment(ctx context.Context, in *CreateMemoCommentRequest, opts ...grpc.CallOption) (*Memo, error)
|
||||||
// ListMemoComments lists comments for a memo.
|
// ListMemoComments lists comments for a memo.
|
||||||
ListMemoComments(ctx context.Context, in *ListMemoCommentsRequest, opts ...grpc.CallOption) (*ListMemoCommentsResponse, error)
|
ListMemoComments(ctx context.Context, in *ListMemoCommentsRequest, opts ...grpc.CallOption) (*ListMemoCommentsResponse, error)
|
||||||
// GetUserMemosStats gets stats of memos for a user.
|
|
||||||
GetUserMemosStats(ctx context.Context, in *GetUserMemosStatsRequest, opts ...grpc.CallOption) (*GetUserMemosStatsResponse, error)
|
|
||||||
// ListMemoReactions lists reactions for a memo.
|
// ListMemoReactions lists reactions for a memo.
|
||||||
ListMemoReactions(ctx context.Context, in *ListMemoReactionsRequest, opts ...grpc.CallOption) (*ListMemoReactionsResponse, error)
|
ListMemoReactions(ctx context.Context, in *ListMemoReactionsRequest, opts ...grpc.CallOption) (*ListMemoReactionsResponse, error)
|
||||||
// UpsertMemoReaction upserts a reaction for a memo.
|
// UpsertMemoReaction upserts a reaction for a memo.
|
||||||
@ -282,16 +279,6 @@ func (c *memoServiceClient) ListMemoComments(ctx context.Context, in *ListMemoCo
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *memoServiceClient) GetUserMemosStats(ctx context.Context, in *GetUserMemosStatsRequest, opts ...grpc.CallOption) (*GetUserMemosStatsResponse, error) {
|
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
|
||||||
out := new(GetUserMemosStatsResponse)
|
|
||||||
err := c.cc.Invoke(ctx, MemoService_GetUserMemosStats_FullMethodName, in, out, cOpts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *memoServiceClient) ListMemoReactions(ctx context.Context, in *ListMemoReactionsRequest, opts ...grpc.CallOption) (*ListMemoReactionsResponse, error) {
|
func (c *memoServiceClient) ListMemoReactions(ctx context.Context, in *ListMemoReactionsRequest, opts ...grpc.CallOption) (*ListMemoReactionsResponse, error) {
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(ListMemoReactionsResponse)
|
out := new(ListMemoReactionsResponse)
|
||||||
@ -362,8 +349,6 @@ type MemoServiceServer interface {
|
|||||||
CreateMemoComment(context.Context, *CreateMemoCommentRequest) (*Memo, error)
|
CreateMemoComment(context.Context, *CreateMemoCommentRequest) (*Memo, error)
|
||||||
// ListMemoComments lists comments for a memo.
|
// ListMemoComments lists comments for a memo.
|
||||||
ListMemoComments(context.Context, *ListMemoCommentsRequest) (*ListMemoCommentsResponse, error)
|
ListMemoComments(context.Context, *ListMemoCommentsRequest) (*ListMemoCommentsResponse, error)
|
||||||
// GetUserMemosStats gets stats of memos for a user.
|
|
||||||
GetUserMemosStats(context.Context, *GetUserMemosStatsRequest) (*GetUserMemosStatsResponse, error)
|
|
||||||
// ListMemoReactions lists reactions for a memo.
|
// ListMemoReactions lists reactions for a memo.
|
||||||
ListMemoReactions(context.Context, *ListMemoReactionsRequest) (*ListMemoReactionsResponse, error)
|
ListMemoReactions(context.Context, *ListMemoReactionsRequest) (*ListMemoReactionsResponse, error)
|
||||||
// UpsertMemoReaction upserts a reaction for a memo.
|
// UpsertMemoReaction upserts a reaction for a memo.
|
||||||
@ -431,9 +416,6 @@ func (UnimplementedMemoServiceServer) CreateMemoComment(context.Context, *Create
|
|||||||
func (UnimplementedMemoServiceServer) ListMemoComments(context.Context, *ListMemoCommentsRequest) (*ListMemoCommentsResponse, error) {
|
func (UnimplementedMemoServiceServer) ListMemoComments(context.Context, *ListMemoCommentsRequest) (*ListMemoCommentsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ListMemoComments not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ListMemoComments not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedMemoServiceServer) GetUserMemosStats(context.Context, *GetUserMemosStatsRequest) (*GetUserMemosStatsResponse, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetUserMemosStats not implemented")
|
|
||||||
}
|
|
||||||
func (UnimplementedMemoServiceServer) ListMemoReactions(context.Context, *ListMemoReactionsRequest) (*ListMemoReactionsResponse, error) {
|
func (UnimplementedMemoServiceServer) ListMemoReactions(context.Context, *ListMemoReactionsRequest) (*ListMemoReactionsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ListMemoReactions not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ListMemoReactions not implemented")
|
||||||
}
|
}
|
||||||
@ -780,24 +762,6 @@ func _MemoService_ListMemoComments_Handler(srv interface{}, ctx context.Context,
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _MemoService_GetUserMemosStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(GetUserMemosStatsRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(MemoServiceServer).GetUserMemosStats(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: MemoService_GetUserMemosStats_FullMethodName,
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(MemoServiceServer).GetUserMemosStats(ctx, req.(*GetUserMemosStatsRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _MemoService_ListMemoReactions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _MemoService_ListMemoReactions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(ListMemoReactionsRequest)
|
in := new(ListMemoReactionsRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@ -931,10 +895,6 @@ var MemoService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "ListMemoComments",
|
MethodName: "ListMemoComments",
|
||||||
Handler: _MemoService_ListMemoComments_Handler,
|
Handler: _MemoService_ListMemoComments_Handler,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MethodName: "GetUserMemosStats",
|
|
||||||
Handler: _MemoService_GetUserMemosStats_Handler,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
MethodName: "ListMemoReactions",
|
MethodName: "ListMemoReactions",
|
||||||
Handler: _MemoService_ListMemoReactions_Handler,
|
Handler: _MemoService_ListMemoReactions_Handler,
|
||||||
|
@ -491,61 +491,6 @@ func (s *APIV1Service) ListMemoComments(ctx context.Context, request *v1pb.ListM
|
|||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *APIV1Service) GetUserMemosStats(ctx context.Context, request *v1pb.GetUserMemosStatsRequest) (*v1pb.GetUserMemosStatsResponse, error) {
|
|
||||||
userID, err := ExtractUserIDFromName(request.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "invalid user name")
|
|
||||||
}
|
|
||||||
user, err := s.Store.GetUser(ctx, &store.FindUser{
|
|
||||||
ID: &userID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get user")
|
|
||||||
}
|
|
||||||
if user == nil {
|
|
||||||
return nil, status.Errorf(codes.NotFound, "user not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
normalRowStatus := store.Normal
|
|
||||||
memoFind := &store.FindMemo{
|
|
||||||
CreatorID: &user.ID,
|
|
||||||
RowStatus: &normalRowStatus,
|
|
||||||
ExcludeComments: true,
|
|
||||||
ExcludeContent: true,
|
|
||||||
}
|
|
||||||
if err := s.buildMemoFindWithFilter(ctx, memoFind, request.Filter); err != nil {
|
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "failed to build find memos with filter")
|
|
||||||
}
|
|
||||||
|
|
||||||
memos, err := s.Store.ListMemos(ctx, memoFind)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to list memos: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
location, err := time.LoadLocation(request.Timezone)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "invalid timezone location")
|
|
||||||
}
|
|
||||||
|
|
||||||
workspaceMemoRelatedSetting, err := s.Store.GetWorkspaceMemoRelatedSetting(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Internal, "failed to get workspace memo related setting")
|
|
||||||
}
|
|
||||||
stats := make(map[string]int32)
|
|
||||||
for _, memo := range memos {
|
|
||||||
displayTs := memo.CreatedTs
|
|
||||||
if workspaceMemoRelatedSetting.DisplayWithUpdateTime {
|
|
||||||
displayTs = memo.UpdatedTs
|
|
||||||
}
|
|
||||||
stats[time.Unix(displayTs, 0).In(location).Format("2006-01-02")]++
|
|
||||||
}
|
|
||||||
|
|
||||||
response := &v1pb.GetUserMemosStatsResponse{
|
|
||||||
Stats: stats,
|
|
||||||
}
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *APIV1Service) ExportMemos(ctx context.Context, request *v1pb.ExportMemosRequest) (*v1pb.ExportMemosResponse, error) {
|
func (s *APIV1Service) ExportMemos(ctx context.Context, request *v1pb.ExportMemosRequest) (*v1pb.ExportMemosResponse, error) {
|
||||||
normalRowStatus := store.Normal
|
normalRowStatus := store.Normal
|
||||||
memoFind := &store.FindMemo{
|
memoFind := &store.FindMemo{
|
||||||
@ -614,14 +559,28 @@ func (s *APIV1Service) ListMemoProperties(ctx context.Context, request *v1pb.Lis
|
|||||||
return nil, status.Errorf(codes.Internal, "failed to list memos")
|
return nil, status.Errorf(codes.Internal, "failed to list memos")
|
||||||
}
|
}
|
||||||
|
|
||||||
properties := []*v1pb.MemoProperty{}
|
workspaceMemoRelatedSetting, err := s.Store.GetWorkspaceMemoRelatedSetting(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to get workspace memo related setting")
|
||||||
|
}
|
||||||
|
|
||||||
|
entities := []*v1pb.MemoPropertyEntity{}
|
||||||
for _, memo := range memos {
|
for _, memo := range memos {
|
||||||
if memo.Payload.Property != nil {
|
displayTs := memo.CreatedTs
|
||||||
properties = append(properties, convertMemoPropertyFromStore(memo.Payload.Property))
|
if workspaceMemoRelatedSetting.DisplayWithUpdateTime {
|
||||||
|
displayTs = memo.UpdatedTs
|
||||||
}
|
}
|
||||||
|
entity := &v1pb.MemoPropertyEntity{
|
||||||
|
Name: fmt.Sprintf("%s%d", MemoNamePrefix, memo.ID),
|
||||||
|
DisplayTime: timestamppb.New(time.Unix(displayTs, 0)),
|
||||||
|
}
|
||||||
|
if memo.Payload.Property != nil {
|
||||||
|
entity.Property = convertMemoPropertyFromStore(memo.Payload.Property)
|
||||||
|
}
|
||||||
|
entities = append(entities, entity)
|
||||||
}
|
}
|
||||||
return &v1pb.ListMemoPropertiesResponse{
|
return &v1pb.ListMemoPropertiesResponse{
|
||||||
Properties: properties,
|
Entities: entities,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Tooltip } from "@mui/joy";
|
import { Tooltip } from "@mui/joy";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { getNormalizedDateString, getDateWithOffset } from "@/helpers/datetime";
|
import dayjs from "dayjs";
|
||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -29,8 +29,8 @@ const getCellAdditionalStyles = (count: number, maxCount: number) => {
|
|||||||
const ActivityCalendar = (props: Props) => {
|
const ActivityCalendar = (props: Props) => {
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
const { month: monthStr, data, onClick } = props;
|
const { month: monthStr, data, onClick } = props;
|
||||||
const year = new Date(monthStr).getFullYear();
|
const year = dayjs(monthStr).toDate().getFullYear();
|
||||||
const month = new Date(monthStr).getMonth() + 1;
|
const month = dayjs(monthStr).toDate().getMonth() + 1;
|
||||||
const dayInMonth = new Date(year, month, 0).getDate();
|
const dayInMonth = new Date(year, month, 0).getDate();
|
||||||
const firstDay = new Date(year, month - 1, 1).getDay();
|
const firstDay = new Date(year, month - 1, 1).getDay();
|
||||||
const lastDay = new Date(year, month - 1, dayInMonth).getDay();
|
const lastDay = new Date(year, month - 1, dayInMonth).getDay();
|
||||||
@ -49,14 +49,19 @@ const ActivityCalendar = (props: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={clsx("w-full h-auto shrink-0 grid grid-cols-7 grid-flow-row gap-1")}>
|
<div className={clsx("w-full h-auto shrink-0 grid grid-cols-7 grid-flow-row gap-1")}>
|
||||||
|
<div className={clsx("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>Su</div>
|
||||||
|
<div className={clsx("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>Mo</div>
|
||||||
|
<div className={clsx("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>Tu</div>
|
||||||
|
<div className={clsx("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>We</div>
|
||||||
|
<div className={clsx("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>Th</div>
|
||||||
|
<div className={clsx("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>Fr</div>
|
||||||
|
<div className={clsx("w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60")}>Sa</div>
|
||||||
{days.map((day, index) => {
|
{days.map((day, index) => {
|
||||||
const date = getNormalizedDateString(
|
const date = dayjs(`${year}-${month}-${day}`).format("YYYY-MM-DD");
|
||||||
getDateWithOffset(`${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`),
|
|
||||||
);
|
|
||||||
const count = data[date] || 0;
|
const count = data[date] || 0;
|
||||||
const isToday = new Date().toDateString() === new Date(date).toDateString();
|
const isToday = dayjs().format("YYYY-MM-DD") === date;
|
||||||
const tooltipText = count ? t("memo.count-memos-in-date", { count: count, date: date }) : date;
|
const tooltipText = count ? t("memo.count-memos-in-date", { count: count, date: date }) : date;
|
||||||
const isSelected = new Date(props.selectedDate).toDateString() === new Date(date).toDateString();
|
const isSelected = dayjs(props.selectedDate).format("YYYY-MM-DD") === date;
|
||||||
return day ? (
|
return day ? (
|
||||||
count > 0 ? (
|
count > 0 ? (
|
||||||
<Tooltip className="shrink-0" key={`${date}-${index}`} title={tooltipText} placement="top" arrow>
|
<Tooltip className="shrink-0" key={`${date}-${index}`} title={tooltipText} placement="top" arrow>
|
||||||
@ -68,7 +73,7 @@ const ActivityCalendar = (props: Props) => {
|
|||||||
isSelected && "font-bold border-zinc-400 dark:border-zinc-300",
|
isSelected && "font-bold border-zinc-400 dark:border-zinc-300",
|
||||||
!isToday && !isSelected && "border-transparent",
|
!isToday && !isSelected && "border-transparent",
|
||||||
)}
|
)}
|
||||||
onClick={() => count && onClick && onClick(new Date(date).toDateString())}
|
onClick={() => count && onClick && onClick(date)}
|
||||||
>
|
>
|
||||||
{day}
|
{day}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Divider, Tooltip } from "@mui/joy";
|
import { Divider, Tooltip } from "@mui/joy";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
import { chain } from "lodash-es";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { memoServiceClient } from "@/grpcweb";
|
import { memoServiceClient } from "@/grpcweb";
|
||||||
@ -33,43 +34,36 @@ const UserStatisticsView = () => {
|
|||||||
const days = Math.ceil((Date.now() - currentUser.createTime!.getTime()) / 86400000);
|
const days = Math.ceil((Date.now() - currentUser.createTime!.getTime()) / 86400000);
|
||||||
|
|
||||||
useAsyncEffect(async () => {
|
useAsyncEffect(async () => {
|
||||||
const { properties } = await memoServiceClient.listMemoProperties({
|
const { entities } = await memoServiceClient.listMemoProperties({
|
||||||
name: `memos/-`,
|
name: `memos/-`,
|
||||||
});
|
});
|
||||||
const memoStats: UserMemoStats = { link: 0, taskList: 0, code: 0, incompleteTasks: 0 };
|
const memoStats: UserMemoStats = { link: 0, taskList: 0, code: 0, incompleteTasks: 0 };
|
||||||
properties.forEach((property) => {
|
entities.forEach((entity) => {
|
||||||
if (property.hasLink) {
|
const { property } = entity;
|
||||||
|
if (property?.hasLink) {
|
||||||
memoStats.link += 1;
|
memoStats.link += 1;
|
||||||
}
|
}
|
||||||
if (property.hasTaskList) {
|
if (property?.hasTaskList) {
|
||||||
memoStats.taskList += 1;
|
memoStats.taskList += 1;
|
||||||
}
|
}
|
||||||
if (property.hasCode) {
|
if (property?.hasCode) {
|
||||||
memoStats.code += 1;
|
memoStats.code += 1;
|
||||||
}
|
}
|
||||||
if (property.hasIncompleteTasks) {
|
if (property?.hasIncompleteTasks) {
|
||||||
memoStats.incompleteTasks += 1;
|
memoStats.incompleteTasks += 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const displayTimes = entities.map((entity) => entity.displayTime).filter(Boolean) as Date[];
|
||||||
|
const monthStrGroup = chain(displayTimes)
|
||||||
|
.map((date) => dayjs(date).format("YYYY-MM-DD"))
|
||||||
|
.countBy()
|
||||||
|
.value();
|
||||||
setMemoStats(memoStats);
|
setMemoStats(memoStats);
|
||||||
setMemoAmount(properties.length);
|
setMemoAmount(entities.length);
|
||||||
|
setActivityStats(monthStrGroup);
|
||||||
const filters = [`row_status == "NORMAL"`];
|
|
||||||
const { stats } = await memoServiceClient.getUserMemosStats({
|
|
||||||
name: currentUser.name,
|
|
||||||
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
||||||
filter: filters.join(" && "),
|
|
||||||
});
|
|
||||||
setActivityStats(
|
|
||||||
Object.fromEntries(
|
|
||||||
Object.entries(stats).filter(([date]) => {
|
|
||||||
return dayjs(date).format("YYYY-MM") === monthString;
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}, [memoStore.stateId]);
|
}, [memoStore.stateId]);
|
||||||
|
|
||||||
const handleRebuildMemoTags = async () => {
|
const rebuildMemoTags = async () => {
|
||||||
await memoServiceClient.rebuildMemoProperty({
|
await memoServiceClient.rebuildMemoProperty({
|
||||||
name: "memos/-",
|
name: "memos/-",
|
||||||
});
|
});
|
||||||
@ -77,12 +71,17 @@ const UserStatisticsView = () => {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onCalendarClick = (date: string) => {
|
||||||
|
memoFilterStore.removeFilter((f) => f.factor === "displayTime");
|
||||||
|
memoFilterStore.addFilter({ factor: "displayTime", value: date });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="group w-full border mt-2 py-2 px-3 rounded-lg space-y-0.5 text-gray-500 dark:text-gray-400 bg-zinc-50 dark:bg-zinc-900 dark:border-zinc-800">
|
<div className="group w-full border mt-2 py-2 px-3 rounded-lg space-y-0.5 text-gray-500 dark:text-gray-400 bg-zinc-50 dark:bg-zinc-900 dark:border-zinc-800">
|
||||||
<div className="w-full mb-2 flex flex-row justify-between items-center">
|
<div className="w-full mb-1 flex flex-row justify-between items-center">
|
||||||
<div className="relative text-base font-medium leading-6 flex flex-row items-center dark:text-gray-400">
|
<div className="relative text-base font-medium leading-6 flex flex-row items-center dark:text-gray-400">
|
||||||
<Icon.CalendarDays className="w-5 h-auto mr-1 opacity-60" strokeWidth={1.5} />
|
<Icon.CalendarDays className="w-5 h-auto mr-1 opacity-60" strokeWidth={1.5} />
|
||||||
<span>{new Date(monthString).toLocaleString(i18n.language, { year: "numeric", month: "long" })}</span>
|
<span>{dayjs(monthString).toDate().toLocaleString(i18n.language, { year: "numeric", month: "long" })}</span>
|
||||||
<input
|
<input
|
||||||
className="inset-0 absolute z-1 opacity-0"
|
className="inset-0 absolute z-1 opacity-0"
|
||||||
type="month"
|
type="month"
|
||||||
@ -97,7 +96,7 @@ const UserStatisticsView = () => {
|
|||||||
<Icon.MoreVertical className="w-4 h-auto shrink-0 opacity-60" />
|
<Icon.MoreVertical className="w-4 h-auto shrink-0 opacity-60" />
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent>
|
||||||
<button className="w-auto flex flex-row justify-between items-center gap-2 hover:opacity-80" onClick={handleRebuildMemoTags}>
|
<button className="w-auto flex flex-row justify-between items-center gap-2 hover:opacity-80" onClick={rebuildMemoTags}>
|
||||||
<Icon.RefreshCcw className="text-gray-400 w-4 h-auto cursor-pointer opacity-60" />
|
<Icon.RefreshCcw className="text-gray-400 w-4 h-auto cursor-pointer opacity-60" />
|
||||||
<span className="text-sm shrink-0 text-gray-500 dark:text-gray-400">Refresh</span>
|
<span className="text-sm shrink-0 text-gray-500 dark:text-gray-400">Refresh</span>
|
||||||
</button>
|
</button>
|
||||||
@ -106,10 +105,10 @@ const UserStatisticsView = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<ActivityCalendar month={monthString} selectedDate={selectedDate.toDateString()} data={activityStats} />
|
<ActivityCalendar month={monthString} selectedDate={selectedDate.toDateString()} data={activityStats} onClick={onCalendarClick} />
|
||||||
{memoAmount > 0 && (
|
{memoAmount > 0 && (
|
||||||
<p className="mt-1 w-full text-xs italic opacity-80">
|
<p className="mt-1 w-full text-xs italic opacity-80">
|
||||||
<span>{memoAmount}</span> memos in <span>{days}</span> days
|
<span>{memoAmount}</span> memos in <span>{days}</span> {days > 1 ? "days" : "day"}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,26 +4,6 @@ export function getTimeStampByDate(t: Date | number | string | any): number {
|
|||||||
return new Date(t).getTime();
|
return new Date(t).getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a time string to provided time.
|
|
||||||
*
|
|
||||||
* If no date is provided, the current date is used.
|
|
||||||
*
|
|
||||||
* Output is always ``HH:MM`` (24-hour format)
|
|
||||||
*/
|
|
||||||
export function getTimeString(t?: Date | number | string): string {
|
|
||||||
const tsFromDate = getTimeStampByDate(t ? t : Date.now());
|
|
||||||
const d = new Date(tsFromDate);
|
|
||||||
|
|
||||||
const hours = d.getHours();
|
|
||||||
const mins = d.getMinutes();
|
|
||||||
|
|
||||||
const hoursStr = hours < 10 ? "0" + hours : hours;
|
|
||||||
const minsStr = mins < 10 ? "0" + mins : mins;
|
|
||||||
|
|
||||||
return `${hoursStr}:${minsStr}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a localized date and time string to provided time.
|
* Get a localized date and time string to provided time.
|
||||||
*
|
*
|
||||||
@ -49,51 +29,3 @@ export function getDateTimeString(t?: Date | number | string | any, locale = i18
|
|||||||
return tsFromDate.toLocaleString();
|
return tsFromDate.toLocaleString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This returns the normalized date string of the provided date.
|
|
||||||
* Format is always `YYYY-MM-DDT00:00`.
|
|
||||||
*
|
|
||||||
* If no date is provided, the current date is used.
|
|
||||||
*/
|
|
||||||
export function getNormalizedTimeString(t?: Date | number | string): string {
|
|
||||||
const date = new Date(t ? t : Date.now());
|
|
||||||
|
|
||||||
const yyyy = date.getFullYear();
|
|
||||||
const M = date.getMonth() + 1;
|
|
||||||
const d = date.getDate();
|
|
||||||
const h = date.getHours();
|
|
||||||
const m = date.getMinutes();
|
|
||||||
|
|
||||||
const MM = M < 10 ? "0" + M : M;
|
|
||||||
const dd = d < 10 ? "0" + d : d;
|
|
||||||
const hh = h < 10 ? "0" + h : h;
|
|
||||||
const mm = m < 10 ? "0" + m : m;
|
|
||||||
|
|
||||||
return `${yyyy}-${MM}-${dd}T${hh}:${mm}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getNormalizedDateString(t?: Date | number | string): string {
|
|
||||||
const date = new Date(t ? t : Date.now());
|
|
||||||
|
|
||||||
const yyyy = date.getFullYear();
|
|
||||||
const M = date.getMonth() + 1;
|
|
||||||
const d = date.getDate();
|
|
||||||
|
|
||||||
const MM = M < 10 ? "0" + M : M;
|
|
||||||
const dd = d < 10 ? "0" + d : d;
|
|
||||||
|
|
||||||
return `${yyyy}-${MM}-${dd}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a new Date object by adjusting the provided date, timestamp, or date string
|
|
||||||
* based on the current timezone offset.
|
|
||||||
*
|
|
||||||
* @param t - The input date, timestamp, or date string (optional). If not provided,
|
|
||||||
* the current date and time will be used.
|
|
||||||
* @returns A new Date object adjusted by the current timezone offset.
|
|
||||||
*/
|
|
||||||
export function getDateWithOffset(t?: Date | number | string): Date {
|
|
||||||
return new Date(getTimeStampByDate(t) + new Date().getTimezoneOffset() * 60 * 1000);
|
|
||||||
}
|
|
||||||
|
@ -9,11 +9,13 @@ import useCurrentUser from "@/hooks/useCurrentUser";
|
|||||||
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
|
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
|
||||||
import Loading from "@/pages/Loading";
|
import Loading from "@/pages/Loading";
|
||||||
import { Routes } from "@/router";
|
import { Routes } from "@/router";
|
||||||
|
import { useMemoFilterStore } from "@/store/v1";
|
||||||
|
|
||||||
const RootLayout = () => {
|
const RootLayout = () => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { sm } = useResponsiveWidth();
|
const { sm } = useResponsiveWidth();
|
||||||
const currentUser = useCurrentUser();
|
const currentUser = useCurrentUser();
|
||||||
|
const memoFilterStore = useMemoFilterStore();
|
||||||
const [collapsed, setCollapsed] = useLocalStorage<boolean>("navigation-collapsed", false);
|
const [collapsed, setCollapsed] = useLocalStorage<boolean>("navigation-collapsed", false);
|
||||||
const [initialized, setInitialized] = useState(false);
|
const [initialized, setInitialized] = useState(false);
|
||||||
|
|
||||||
@ -27,6 +29,11 @@ const RootLayout = () => {
|
|||||||
setInitialized(true);
|
setInitialized(true);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// When the route changes, remove all filters.
|
||||||
|
memoFilterStore.removeFilter(() => true);
|
||||||
|
}, [location.pathname]);
|
||||||
|
|
||||||
return !initialized ? (
|
return !initialized ? (
|
||||||
<Loading />
|
<Loading />
|
||||||
) : (
|
) : (
|
||||||
|
@ -51,6 +51,10 @@ const Home = () => {
|
|||||||
filters.push(`has_task_list == true`);
|
filters.push(`has_task_list == true`);
|
||||||
} else if (filter.factor === "property.hasCode") {
|
} else if (filter.factor === "property.hasCode") {
|
||||||
filters.push(`has_code == true`);
|
filters.push(`has_code == true`);
|
||||||
|
} else if (filter.factor === "displayTime") {
|
||||||
|
const timestampAfter = getTimeStampByDate(new Date(filter.value)) / 1000;
|
||||||
|
filters.push(`display_time_after == ${timestampAfter}`);
|
||||||
|
filters.push(`display_time_before == ${timestampAfter + 60 * 60 * 24}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (contentSearch.length > 0) {
|
if (contentSearch.length > 0) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user