Skip to content

Commit

Permalink
Support weekly limit(#306)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheepzh committed Aug 12, 2024
1 parent b5f6f95 commit 7930f5b
Show file tree
Hide file tree
Showing 60 changed files with 674 additions and 393 deletions.
2 changes: 1 addition & 1 deletion src/app/components/About/Description.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import { ElCard, ElDescriptions, ElDescriptionsItem, ElDivider, ElSpace, ElText
import { defineComponent, StyleValue } from "vue"
import InstallationLink from "./InstallationLink"
import packageInfo, { AUTHOR_EMAIL } from "@src/package"
import { locale } from "@i18n"
import "./description.sass"
import metaService from "@service/meta-service"
import DescLink from "./DescLink"
import { locale } from "@i18n"

const INSTALLATION_STYLE: StyleValue = {
display: "flex",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
EffectScatterSeriesOption
} from "echarts"
import { formatTime, getAllDatesBetween, getWeeksAgo, parseTime } from "@util/time"
import { locale } from "@i18n"
import { EffectScatterChart } from "echarts/charts"
import { SVGRenderer } from "echarts/renderers"
import { use } from "echarts/core"
Expand All @@ -23,6 +22,7 @@ import { groupBy, rotate } from "@util/array"
import { t } from "@app/locale"
import { getRegularTextColor, getSecondaryTextColor } from "@util/style"
import { periodFormatter } from "@app/util/time"
import { locale } from "@i18n"

type EcOption = ComposeOption<
| EffectScatterSeriesOption
Expand Down
8 changes: 4 additions & 4 deletions src/app/components/Dashboard/components/Calendar/Wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ use([
])

import { EchartsWrapper } from "@hooks"
import { formatPeriodCommon, getAllDatesBetween, MILL_PER_HOUR } from "@util/time"
import { locale } from "@i18n"
import { formatPeriodCommon, getAllDatesBetween, MILL_PER_HOUR, MILL_PER_MINUTE } from "@util/time"
import { groupBy, rotate, sum } from "@util/array"
import { t } from "@app/locale"
import { getPrimaryTextColor } from "@util/style"
Expand All @@ -31,6 +30,7 @@ import { getAppPageUrl } from "@util/constant/url"
import { REPORT_ROUTE } from "@app/router/constants"
import { createTabAfterCurrent } from "@api/chrome/tab"
import { getStepColors } from "@app/util/echarts"
import { locale } from "@i18n"

type _Value = [
x: number,
Expand Down Expand Up @@ -109,8 +109,8 @@ type Piece = {
color?: string
}

const minOf = (min: number) => min * 60 * 1000
const hourOf = (hour: number) => hour * 60 * 60 * 1000
const minOf = (min: number) => min * MILL_PER_MINUTE
const hourOf = (hour: number) => hour * MILL_PER_HOUR

const ALL_PIECES: Piece[] = [
{ min: 1, max: minOf(10), label: "<10m" },
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/DataManage/ClearPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { defineComponent } from "vue"
import { t } from "@app/locale"
import { alertProps } from "../common"
import ClearFilter from "./ClearFilter"
import { MILL_PER_DAY } from "@util/time"
import { MILL_PER_DAY, MILL_PER_SECOND } from "@util/time"
import statService, { StatQueryParam } from "@service/stat-service"

type FilterOption = {
Expand Down Expand Up @@ -54,7 +54,7 @@ function assertQueryParam(range: Vector<2>, mustInteger?: boolean): boolean {
}

const str2Num = (str: string, defaultVal?: number) => (str && str !== '') ? parseInt(str) : defaultVal
const seconds2Milliseconds = (a: number) => a * 1000
const seconds2Milliseconds = (a: number) => a * MILL_PER_SECOND

function checkParam(option: FilterOption): StatQueryParam | undefined {
const { focus = [null, null], time = [null, null] } = option || {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { fillExist } from "@service/components/import-processor"
import { AUTHOR_EMAIL } from "@src/package"
import { extractHostname, isBrowserUrl } from "@util/pattern"
import { formatTime } from "@util/time"
import { formatTimeYMD, MILL_PER_SECOND } from "@util/time"

export type OtherExtension =
| "webtime_tracker"
Expand Down Expand Up @@ -52,7 +52,7 @@ async function parseWebActivityTimeTracker(file: File): Promise<timer.imported.R
const [year, month, day] = date.split('/')
!year || !month || !day && throwError()
const realDate = `${year}${month.length == 2 ? month : '0' + month}${day.length == 2 ? day : '0' + day}`
return { host, date: realDate, focus: parseInt(seconds) * 1000 }
return { host, date: realDate, focus: parseInt(seconds) * MILL_PER_SECOND }
})
return rows
}
Expand Down Expand Up @@ -89,7 +89,7 @@ async function parseWebtimeTracker(file: File): Promise<timer.imported.Row[]> {
.map(([host, date, seconds]) => ({
host,
date,
focus: seconds * 1000
focus: seconds * MILL_PER_SECOND
} as timer.imported.Row))
return rows
} else if (isCsvFile(file)) {
Expand All @@ -103,7 +103,7 @@ async function parseWebtimeTracker(file: File): Promise<timer.imported.Row[]> {
for (let i = 1; i < colHeaders?.length; i++) {
const seconds = Number.parseInt(cells[i])
const date = cvtWebtimeTrackerDate(colHeaders[i])
seconds && date && rows.push({ host, date, focus: seconds * 1000 })
seconds && date && rows.push({ host, date, focus: seconds * MILL_PER_SECOND })
}
})
return rows
Expand All @@ -120,7 +120,7 @@ function parseHistoryTrendsUnlimitedLine(line: string, data: { [dateAndHost: str
// Backup data
let date: string;
try {
date = formatTime(parseFloat(tsMaybe.substring(1)), "{y}{m}{d}")
date = formatTimeYMD(parseFloat(tsMaybe.substring(1)))
} catch {
console.error("Invalid line: " + line)
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const baseLegendTitle = (): TitleComponentOption => ({
})

function generateOption(bizOption: BizOption): EcOption {
let { rows, dateRange } = bizOption || {}
let { rows = [], dateRange } = bizOption || {}
const [averageLen, _, exclusiveDate] = computeAverageLen(dateRange)
if (exclusiveDate) {
rows = rows.filter(r => r.date !== exclusiveDate)
Expand Down
6 changes: 2 additions & 4 deletions src/app/components/Habit/components/Site/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
import type { TitleComponentOption } from "echarts/components"

import { getRegularTextColor } from "@util/style"
import { generateSiteLabel } from "@util/site"
import { periodFormatter } from "@app/util/time"
import { formatTime, getDayLength, isSameDay } from "@util/time"
import { formatTimeYMD, getDayLength, isSameDay } from "@util/time"

export const generateTitleOption = (text: string): TitleComponentOption => {
const secondaryTextColor = getRegularTextColor()
Expand Down Expand Up @@ -42,7 +40,7 @@ export const computeAverageLen = (dateRange: [Date, Date] = [null, null]): [numb
const dateDiff = getDayLength(start, end)
const endIsTody = isSameDay(end, new Date())
if (endIsTody) {
return [dateDiff - 1, true, formatTime(end, "{y}{m}{d}")]
return [dateDiff - 1, true, formatTimeYMD(end)]
} else {
return [dateDiff, false, null]
}
Expand Down
14 changes: 8 additions & 6 deletions src/app/components/Limit/LimitModify/Sop/Step3/TimeInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ function computeLimitInfo2Second(hour: number, minute: number, second: number):
const _default = defineComponent({
props: {
modelValue: Number,
hourMax: Number
},
emits: {
change: (_val: number) => true
Expand All @@ -83,12 +84,13 @@ const _default = defineComponent({
const limitTime = computed(() => computeLimitInfo2Second(hour.value, minute.value, second.value))
watch(limitTime, () => ctx.emit('change', limitTime.value))

return () => <div class="limit-time-input">
<UnitInput modelValue={hour.value} onChange={setHour} unit="H" max={23} />
<UnitInput modelValue={minute.value} onChange={setMinute} unit="M" max={59} />
<UnitInput modelValue={second.value} onChange={setSecond} unit="S" max={59} />
</div>

return () => (
<div class="limit-time-input">
<UnitInput modelValue={hour.value} onChange={setHour} unit="H" max={props.hourMax ?? 23} />
<UnitInput modelValue={minute.value} onChange={setMinute} unit="M" max={59} />
<UnitInput modelValue={second.value} onChange={setSecond} unit="S" max={59} />
</div>
)
}
})

Expand Down
27 changes: 24 additions & 3 deletions src/app/components/Limit/LimitModify/Sop/Step3/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,38 @@ import { useShadow } from "@hooks"
import { StepFromInstance } from "../common"
import "./style.sass"

type Value = Pick<timer.limit.Item, 'time' | 'visitTime' | 'weekly' | 'periods'>

const MAX_HOUR_WEEKLY = 7 * 24 - 1

const _default = defineComponent({
props: {
time: Number,
visitTime: Number,
weekly: Number,
periods: Array as PropType<timer.limit.Period[]>,
},
emits: {
change: (_time: number, _visitTime: number, _periods: Vector<2>[]) => true,
change: (_val: Value) => true,
},
setup(props, ctx) {
const [time, setTime] = useShadow(() => props.time)
const [weekly, setWeekly] = useShadow(() => props.weekly)
const [visitTime, setVisitTime] = useShadow(() => props.visitTime)
const [periods, setPeriods] = useShadow(() => props.periods, [])

watch([time, visitTime, periods], () => ctx.emit("change", time.value, visitTime.value, periods.value))
watch([time, visitTime, periods, weekly], () => {
const val: Value = {
time: time.value,
visitTime: visitTime.value,
weekly: weekly.value,
periods: periods.value,
}
ctx.emit("change", val)
})

const validate = () => {
if (!time.value && !visitTime.value && !periods.value?.length) {
if (!time.value && !visitTime.value && !periods.value?.length && !weekly.value) {
ElMessage.error(t(msg => msg.limit.message.noRule))
return false
}
Expand All @@ -44,6 +58,13 @@ const _default = defineComponent({
<ElFormItem label={t(msg => msg.limit.item.time)}>
<TimeInput modelValue={time.value} onChange={setTime} />
</ElFormItem>
<ElFormItem label={t(msg => msg.limit.item.weekly)}>
<TimeInput
modelValue={weekly.value}
onChange={setWeekly}
hourMax={MAX_HOUR_WEEKLY}
/>
</ElFormItem>
<ElFormItem label={t(msg => msg.limit.item.visitTime)}>
<TimeInput modelValue={visitTime.value} onChange={setVisitTime} />
</ElFormItem>
Expand Down
5 changes: 4 additions & 1 deletion src/app/components/Limit/LimitModify/Sop/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type SopInstance = {
const createInitial = (): Required<Omit<timer.limit.Rule, 'id' | 'allowDelay'>> => ({
name: null,
time: 3600,
weekly: null,
cond: [],
visitTime: null,
periods: null,
Expand Down Expand Up @@ -102,12 +103,14 @@ const _default = defineComponent({
v-show={step.value === 2}
ref={stepInstances[2]}
time={data.time}
weekly={data.weekly}
visitTime={data.visitTime}
periods={data.periods}
onChange={(time, visitTime, periods) => {
onChange={({ time, visitTime, periods, weekly }) => {
data.time = time
data.visitTime = visitTime
data.periods = periods
data.weekly = weekly
}}
/>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/Limit/LimitModify/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ const _default = defineComponent({
let modifyingItem: timer.limit.Rule = undefined

const handleSave = async (rule: timer.limit.Rule) => {
const { cond, enabled, name, time, visitTime, periods, weekdays } = rule
const { cond, enabled, name, time, weekly, visitTime, periods, weekdays } = rule
const toSave: timer.limit.Rule = {
...modifyingItem || {},
cond, enabled, name, time, visitTime, weekdays,
cond, enabled, name, time, weekly, visitTime, weekdays,
// Object to array
periods: periods?.map(i => [i?.[0], i?.[1]]),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { Delete, Edit } from "@element-plus/icons-vue"
import { ElButton, ElMessageBox, ElTableColumn } from "element-plus"
import { defineComponent } from "vue"
import { t } from "@app/locale"
import optionService from "@service/option-service"
import { locale } from "@i18n"
import optionService from "@service/option-service"
import { ElTableRowScope } from "@src/element-ui/table"
import { judgeVerificationRequired, processVerification } from "@app/util/limit"

Expand All @@ -34,8 +34,7 @@ async function handleDelete(row: timer.limit.Item, callback: () => void) {
async function handleModify(row: timer.limit.Item, callback: () => void) {
let promise: Promise<void> = undefined
if (await judgeVerificationRequired(row)) {
const option =
(await optionService.getAllOption()) as timer.option.DailyLimitOption
const option = (await optionService.getAllOption()) as timer.option.DailyLimitOption
promise = processVerification(option)
promise ? promise.then(callback).catch(() => { }) : callback()
} else {
Expand Down
Loading

0 comments on commit 7930f5b

Please sign in to comment.