chore: add time filter to timeline

pull/2782/head
Steven 1 year ago
parent 7de3de5610
commit d426f89cf0

@ -105,11 +105,27 @@ func (s *APIV2Service) ListMemos(ctx context.Context, request *apiv2pb.ListMemos
if filter.OrderByPinned {
memoFind.OrderByPinned = filter.OrderByPinned
}
if filter.CreatedTsBefore != nil {
memoFind.CreatedTsBefore = filter.CreatedTsBefore
if filter.DisplayTimeAfter != nil {
displayWithUpdatedTs, err := s.getMemoDisplayWithUpdatedTsSettingValue(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get memo display with updated ts setting value")
}
if displayWithUpdatedTs {
memoFind.UpdatedTsAfter = filter.DisplayTimeAfter
} else {
memoFind.CreatedTsAfter = filter.DisplayTimeAfter
}
}
if filter.DisplayTimeBefore != nil {
displayWithUpdatedTs, err := s.getMemoDisplayWithUpdatedTsSettingValue(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get memo display with updated ts setting value")
}
if displayWithUpdatedTs {
memoFind.UpdatedTsBefore = filter.DisplayTimeBefore
} else {
memoFind.CreatedTsBefore = filter.DisplayTimeBefore
}
if filter.CreatedTsAfter != nil {
memoFind.CreatedTsAfter = filter.CreatedTsAfter
}
if filter.Creator != nil {
username, err := ExtractUsernameFromName(*filter.Creator)
@ -463,11 +479,27 @@ func (s *APIV2Service) GetUserMemosStats(ctx context.Context, request *apiv2pb.G
if filter.OrderByPinned {
memoFind.OrderByPinned = filter.OrderByPinned
}
if filter.CreatedTsBefore != nil {
memoFind.CreatedTsBefore = filter.CreatedTsBefore
if filter.DisplayTimeAfter != nil {
displayWithUpdatedTs, err := s.getMemoDisplayWithUpdatedTsSettingValue(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get memo display with updated ts setting value")
}
if displayWithUpdatedTs {
memoFind.UpdatedTsAfter = filter.DisplayTimeAfter
} else {
memoFind.CreatedTsAfter = filter.DisplayTimeAfter
}
}
if filter.DisplayTimeBefore != nil {
displayWithUpdatedTs, err := s.getMemoDisplayWithUpdatedTsSettingValue(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get memo display with updated ts setting value")
}
if displayWithUpdatedTs {
memoFind.UpdatedTsBefore = filter.DisplayTimeBefore
} else {
memoFind.CreatedTsBefore = filter.DisplayTimeBefore
}
if filter.CreatedTsAfter != nil {
memoFind.CreatedTsAfter = filter.CreatedTsAfter
}
if filter.RowStatus != nil {
memoFind.RowStatus = filter.RowStatus
@ -590,8 +622,8 @@ var ListMemosFilterCELAttributes = []cel.EnvOption{
cel.Variable("content_search", cel.ListType(cel.StringType)),
cel.Variable("visibilities", cel.ListType(cel.StringType)),
cel.Variable("order_by_pinned", cel.BoolType),
cel.Variable("created_ts_before", cel.IntType),
cel.Variable("created_ts_after", cel.IntType),
cel.Variable("display_time_before", cel.IntType),
cel.Variable("display_time_after", cel.IntType),
cel.Variable("creator", cel.StringType),
cel.Variable("row_status", cel.StringType),
}
@ -600,8 +632,8 @@ type ListMemosFilter struct {
ContentSearch []string
Visibilities []store.Visibility
OrderByPinned bool
CreatedTsBefore *int64
CreatedTsAfter *int64
DisplayTimeBefore *int64
DisplayTimeAfter *int64
Creator *string
RowStatus *store.RowStatus
}
@ -646,12 +678,12 @@ func findField(callExpr *expr.Expr_Call, filter *ListMemosFilter) {
} else if idExpr.Name == "order_by_pinned" {
value := callExpr.Args[1].GetConstExpr().GetBoolValue()
filter.OrderByPinned = value
} else if idExpr.Name == "created_ts_before" {
createdTsBefore := callExpr.Args[1].GetConstExpr().GetInt64Value()
filter.CreatedTsBefore = &createdTsBefore
} else if idExpr.Name == "created_ts_after" {
createdTsAfter := callExpr.Args[1].GetConstExpr().GetInt64Value()
filter.CreatedTsAfter = &createdTsAfter
} else if idExpr.Name == "display_time_before" {
displayTimeBefore := callExpr.Args[1].GetConstExpr().GetInt64Value()
filter.DisplayTimeBefore = &displayTimeBefore
} else if idExpr.Name == "display_time_after" {
displayTimeAfter := callExpr.Args[1].GetConstExpr().GetInt64Value()
filter.DisplayTimeAfter = &displayTimeAfter
} else if idExpr.Name == "creator" {
creator := callExpr.Args[1].GetConstExpr().GetStringValue()
filter.Creator = &creator

@ -55,6 +55,12 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo
if v := find.CreatedTsAfter; v != nil {
where, args = append(where, "UNIX_TIMESTAMP(`memo`.`created_ts`) > ?"), append(args, *v)
}
if v := find.UpdatedTsBefore; v != nil {
where, args = append(where, "UNIX_TIMESTAMP(`memo`.`updated_ts`) < ?"), append(args, *v)
}
if v := find.UpdatedTsAfter; v != nil {
where, args = append(where, "UNIX_TIMESTAMP(`memo`.`updated_ts`) > ?"), append(args, *v)
}
if v := find.ContentSearch; len(v) != 0 {
for _, s := range v {
where, args = append(where, "`memo`.`content` LIKE ?"), append(args, "%"+s+"%")

@ -46,6 +46,12 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo
if v := find.CreatedTsAfter; v != nil {
where, args = append(where, "memo.created_ts > "+placeholder(len(args)+1)), append(args, *v)
}
if v := find.UpdatedTsBefore; v != nil {
where, args = append(where, "memo.updated_ts < "+placeholder(len(args)+1)), append(args, *v)
}
if v := find.UpdatedTsAfter; v != nil {
where, args = append(where, "memo.updated_ts > "+placeholder(len(args)+1)), append(args, *v)
}
if v := find.ContentSearch; len(v) != 0 {
for _, s := range v {
where, args = append(where, "memo.content LIKE "+placeholder(len(args)+1)), append(args, fmt.Sprintf("%%%s%%", s))

@ -45,6 +45,12 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo
if v := find.CreatedTsAfter; v != nil {
where, args = append(where, "memo.created_ts > ?"), append(args, *v)
}
if v := find.UpdatedTsBefore; v != nil {
where, args = append(where, "memo.updated_ts < ?"), append(args, *v)
}
if v := find.UpdatedTsAfter; v != nil {
where, args = append(where, "memo.updated_ts > ?"), append(args, *v)
}
if v := find.ContentSearch; len(v) != 0 {
for _, s := range v {
where, args = append(where, "memo.content LIKE ?"), append(args, fmt.Sprintf("%%%s%%", s))

@ -54,6 +54,8 @@ type FindMemo struct {
CreatorID *int32
CreatedTsAfter *int64
CreatedTsBefore *int64
UpdatedTsAfter *int64
UpdatedTsBefore *int64
// Domain specific fields
ContentSearch []string

@ -6,6 +6,7 @@ interface Props {
// Format: 2021-1
month: string;
data: Record<string, number>;
onClick?: (date: string) => void;
}
const getBgColor = (count: number, maxCount: number) => {
@ -26,7 +27,7 @@ const getBgColor = (count: number, maxCount: number) => {
};
const ActivityCalendar = (props: Props) => {
const { month: monthStr, data } = props;
const { month: monthStr, data, onClick } = props;
const year = new Date(monthStr).getFullYear();
const month = new Date(monthStr).getMonth() + 1;
const dayInMonth = new Date(year, month, 0).getDate();
@ -60,6 +61,7 @@ const ActivityCalendar = (props: Props) => {
getBgColor(count, maxCount),
isToday && "border-gray-600 dark:!border-gray-400"
)}
onClick={() => count && onClick && onClick(date)}
></div>
</Tooltip>
) : (

@ -10,7 +10,7 @@ import MemoFilter from "@/components/MemoFilter";
import MemoView from "@/components/MemoView";
import MobileHeader from "@/components/MobileHeader";
import { memoServiceClient } from "@/grpcweb";
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
import { DAILY_TIMESTAMP, DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
import { getNormalizedTimeString, getTimeStampByDate } from "@/helpers/datetime";
import useCurrentUser from "@/hooks/useCurrentUser";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
@ -52,6 +52,7 @@ const Timeline = () => {
const memoList = useMemoList();
const filterStore = useFilterStore();
const [activityStats, setActivityStats] = useState<Record<string, number>>({});
const [selectedDay, setSelectedDay] = useState<string | undefined>();
const [isRequesting, setIsRequesting] = useState(true);
const [isComplete, setIsComplete] = useState(false);
const { tag: tagQuery, text: textQuery } = filterStore.state;
@ -61,7 +62,7 @@ const Timeline = () => {
useEffect(() => {
memoList.reset();
fetchMemos();
}, [tagQuery, textQuery]);
}, [selectedDay, tagQuery, textQuery]);
useEffect(() => {
(async () => {
@ -97,6 +98,12 @@ const Timeline = () => {
if (contentSearch.length > 0) {
filters.push(`content_search == [${contentSearch.join(", ")}]`);
}
if (selectedDay) {
const selectedDateStamp = getTimeStampByDate(selectedDay) + new Date().getTimezoneOffset() * 60 * 1000;
filters.push(
...[`display_time_after == ${selectedDateStamp / 1000}`, `display_time_before == ${(selectedDateStamp + DAILY_TIMESTAMP) / 1000}`]
);
}
setIsRequesting(true);
const data = await memoStore.fetchMemos({
filter: filters.join(" && "),
@ -143,7 +150,7 @@ const Timeline = () => {
<span className="opacity-60">{new Date(group.month).getFullYear()}</span>
<span className="text-xs opacity-40">Total: {sum(Object.values(group.data))}</span>
</div>
<ActivityCalendar month={group.month} data={group.data} />
<ActivityCalendar month={group.month} data={group.data} onClick={(date) => setSelectedDay(date)} />
</div>
<div className={classNames("flex flex-col justify-start items-start", md ? "w-[calc(100%-8rem)]" : "w-full")}>

Loading…
Cancel
Save