227 lines
7.4 KiB
Bash
Executable file
227 lines
7.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Seed a realistic demo dataset for Opsdash with multiple calendars and mixed events.
|
|
#
|
|
# Usage:
|
|
# BASE=http://localhost:8088 USER=admin PASS=admin ./tools/seed_opsdash_demo.sh
|
|
#
|
|
set -euo pipefail
|
|
|
|
BASE_URL=${BASE:-http://localhost:8088}
|
|
USER=${USER:-admin}
|
|
PASS=${PASS:-admin}
|
|
WEEKS=${WEEKS:-4} # number of consecutive weeks starting from current week
|
|
|
|
DAV_BASE="$BASE_URL/remote.php/dav/calendars/$USER"
|
|
|
|
declare -A CALENDARS=(
|
|
["opsdash-work"]="Opsdash · Deep Work"
|
|
["opsdash-meetings"]="Opsdash · Meetings"
|
|
["opsdash-personal"]="Opsdash · Personal"
|
|
["opsdash-recovery"]="Opsdash · Recovery"
|
|
["opsdash-sport"]="Opsdash · Sport"
|
|
["opsdash-learning"]="Opsdash · Learning"
|
|
)
|
|
|
|
declare -A CALENDAR_COLORS=(
|
|
["opsdash-work"]="#2563EB"
|
|
["opsdash-meetings"]="#7C3AED"
|
|
["opsdash-personal"]="#F97316"
|
|
["opsdash-recovery"]="#0EA5E9"
|
|
["opsdash-sport"]="#10B981"
|
|
["opsdash-learning"]="#D97706"
|
|
)
|
|
|
|
EVENT_DATA=$(cat <<'EOF'
|
|
opsdash-work|Mon|09:00|150|API implementation block
|
|
opsdash-work|Mon|14:00|120|Release hardening sprint
|
|
opsdash-meetings|Mon|11:30|60|Product standup
|
|
opsdash-meetings|Mon|16:30|45|Customer feedback sync
|
|
opsdash-personal|Mon|18:30|90|Family dinner
|
|
opsdash-sport|Mon|20:30|60|Strength training
|
|
|
|
opsdash-work|Tue|08:30|180|Architecture decision workshop
|
|
opsdash-meetings|Tue|12:00|60|Partner call: migration plan
|
|
opsdash-work|Tue|15:00|120|Code review + refactor
|
|
opsdash-learning|Tue|19:30|75|Technical writing meetup
|
|
|
|
opsdash-work|Wed|09:00|180|Deep work sprint
|
|
opsdash-meetings|Wed|13:00|90|Cross-team planning
|
|
opsdash-recovery|Wed|17:30|60|Reset walk
|
|
opsdash-personal|Wed|19:00|120|Dinner with friends
|
|
|
|
opsdash-work|Thu|08:30|150|Feature polish loop
|
|
opsdash-meetings|Thu|11:00|45|Mentoring 1:1
|
|
opsdash-work|Thu|14:00|150|Integration + regression checks
|
|
opsdash-recovery|Thu|18:30|60|Mobility session
|
|
|
|
opsdash-work|Fri|09:00|120|Weekly wrap-up docs
|
|
opsdash-meetings|Fri|11:30|60|Sprint demo + retrospective
|
|
opsdash-personal|Fri|16:30|90|Family time
|
|
opsdash-sport|Fri|19:00|75|Swim interval training
|
|
|
|
opsdash-personal|Sat|10:00|180|Hike and nature break
|
|
opsdash-sport|Sat|16:30|90|Trail run
|
|
opsdash-recovery|Sat|19:30|60|Stretch + foam roll
|
|
|
|
opsdash-personal|Sun|09:30|150|Brunch and weekly planning
|
|
opsdash-learning|Sun|14:00|120|Course: observability fundamentals
|
|
opsdash-recovery|Sun|18:00|90|Quiet evening reset
|
|
EOF
|
|
)
|
|
|
|
log(){ printf '[seed_opsdash_demo] %s\n' "$*"; }
|
|
|
|
print_story_map(){
|
|
cat <<EOF
|
|
|
|
[seed_opsdash_demo] Screenshot/onboarding story map
|
|
[seed_opsdash_demo] Work:
|
|
[seed_opsdash_demo] - Opsdash · Deep Work
|
|
[seed_opsdash_demo] - Opsdash · Meetings
|
|
[seed_opsdash_demo] Hobby / Personal:
|
|
[seed_opsdash_demo] - Opsdash · Personal
|
|
[seed_opsdash_demo] - Opsdash · Learning
|
|
[seed_opsdash_demo] Sport / Recovery:
|
|
[seed_opsdash_demo] - Opsdash · Sport
|
|
[seed_opsdash_demo] - Opsdash · Recovery
|
|
[seed_opsdash_demo]
|
|
[seed_opsdash_demo] Calendar contents
|
|
[seed_opsdash_demo] Opsdash · Deep Work -> long focus blocks, implementation, polish work
|
|
[seed_opsdash_demo] Opsdash · Meetings -> standups, syncs, retros, customer calls
|
|
[seed_opsdash_demo] Opsdash · Personal -> dinners, weekend planning, family time
|
|
[seed_opsdash_demo] Opsdash · Learning -> courses, writing, meetups
|
|
[seed_opsdash_demo] Opsdash · Sport -> strength, swim, trail run
|
|
[seed_opsdash_demo] Opsdash · Recovery -> reset walks, mobility, quiet evening recovery
|
|
[seed_opsdash_demo]
|
|
[seed_opsdash_demo] Recommended onboarding mapping
|
|
[seed_opsdash_demo] Work -> Deep Work + Meetings
|
|
[seed_opsdash_demo] Hobby -> Personal + Learning
|
|
[seed_opsdash_demo] Sport -> Sport + Recovery
|
|
[seed_opsdash_demo]
|
|
[seed_opsdash_demo] Recommended screenshot presets
|
|
[seed_opsdash_demo] Single-goal light -> Work only
|
|
[seed_opsdash_demo] Calendar goals dark -> Work + Hobby + Sport
|
|
[seed_opsdash_demo] Category goals light -> Work + Hobby + Sport with the mapping above
|
|
[seed_opsdash_demo] Onboarding dark -> same seeded set, before completing setup
|
|
EOF
|
|
}
|
|
|
|
utc_ts(){
|
|
local s="$1"
|
|
if [[ "$s" =~ ^([0-9]{4})-([0-9]{2})-([0-9]{2})[[:space:]]+(.*)$ ]]; then
|
|
s="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}-${BASH_REMATCH[3]} ${BASH_REMATCH[4]}"
|
|
fi
|
|
date -u -d "$s" +%Y%m%dT%H%M%SZ
|
|
}
|
|
|
|
ensure_calendar(){
|
|
local slug="$1"
|
|
local name="$2"
|
|
local color="$3"
|
|
local url="$DAV_BASE/$slug/"
|
|
local body='<?xml version="1.0" encoding="utf-8"?>
|
|
<c:mkcalendar xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">
|
|
<d:set>
|
|
<d:prop>
|
|
<d:displayname>'"$name"'</d:displayname>
|
|
<c:calendar-description>Seeded by seed_opsdash_demo.sh</c:calendar-description>
|
|
</d:prop>
|
|
</d:set>
|
|
</c:mkcalendar>'
|
|
curl -fsS -u "$USER:$PASS" -X MKCALENDAR \
|
|
-H 'Content-Type: application/xml; charset=utf-8' \
|
|
--data-binary "$body" \
|
|
"$url" >/dev/null || true
|
|
|
|
local patch='<?xml version="1.0" encoding="utf-8"?>
|
|
<d:propertyupdate xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:a="http://apple.com/ns/ical/">
|
|
<d:set>
|
|
<d:prop>
|
|
<d:displayname>'"$name"'</d:displayname>
|
|
<c:calendar-description>Seeded by seed_opsdash_demo.sh</c:calendar-description>
|
|
<a:calendar-color>'"$color"'</a:calendar-color>
|
|
</d:prop>
|
|
</d:set>
|
|
</d:propertyupdate>'
|
|
curl -fsS -u "$USER:$PASS" -X PROPPATCH \
|
|
-H 'Content-Type: application/xml; charset=utf-8' \
|
|
--data-binary "$patch" \
|
|
"$url" >/dev/null || true
|
|
}
|
|
|
|
make_event_ics(){
|
|
local date_iso="$1"; shift
|
|
local start="$1"; shift
|
|
local end="$1"; shift
|
|
local uid="$1"; shift
|
|
local summary="$1"; shift
|
|
cat <<ICS
|
|
BEGIN:VCALENDAR
|
|
VERSION:2.0
|
|
PRODID:-//opsdash//seed-demo//EN
|
|
BEGIN:VEVENT
|
|
UID:$uid@opsdash-seed
|
|
DTSTAMP:$(date -u +%Y%m%dT%H%M%SZ)
|
|
DTSTART:$(utc_ts "$date_iso $start:00")
|
|
DTEND:$(utc_ts "$date_iso $end:00")
|
|
SUMMARY:$summary
|
|
STATUS:CONFIRMED
|
|
END:VEVENT
|
|
END:VCALENDAR
|
|
ICS
|
|
}
|
|
|
|
put_event(){
|
|
local slug="$1"; shift
|
|
local name="$1"; shift
|
|
local ics="$1"; shift
|
|
curl -fsS -u "$USER:$PASS" -X PUT \
|
|
-H 'Content-Type: text/calendar; charset=utf-8' \
|
|
--data-binary "$ics" \
|
|
"$DAV_BASE/$slug/$name.ics" >/dev/null
|
|
}
|
|
|
|
dow_offset(){
|
|
case "$1" in
|
|
Mon) echo 0 ;;
|
|
Tue) echo 1 ;;
|
|
Wed) echo 2 ;;
|
|
Thu) echo 3 ;;
|
|
Fri) echo 4 ;;
|
|
Sat) echo 5 ;;
|
|
Sun) echo 6 ;;
|
|
*) log "Unknown day $1" >&2; exit 1 ;;
|
|
esac
|
|
}
|
|
|
|
for slug in "${!CALENDARS[@]}"; do
|
|
ensure_calendar "$slug" "${CALENDARS[$slug]}" "${CALENDAR_COLORS[$slug]}"
|
|
done
|
|
|
|
readarray -t EVENTS <<<"$EVENT_DATA"
|
|
|
|
log "Seeding $WEEKS week(s) starting from current week"
|
|
|
|
for week in $(seq 0 $((WEEKS-1))); do
|
|
week_start=$(date -d "monday this week +$week week" +%Y-%m-%d)
|
|
for entry in "${EVENTS[@]}"; do
|
|
[[ -z "$entry" ]] && continue
|
|
IFS='|' read -r slug dow start duration summary <<<"$entry"
|
|
[[ -z "$slug" ]] && continue
|
|
offset=$(dow_offset "$dow")
|
|
date_iso=$(date -d "$week_start +$offset day" +%Y-%m-%d)
|
|
start_ts=$(date -d "$date_iso $start:00" +%s)
|
|
end_ts=$(( start_ts + duration*60 ))
|
|
end=$(date -d "@$end_ts" +%H:%M)
|
|
uid="seed-${week}-${slug}-${dow}-${start}"
|
|
ics=$(make_event_ics "$date_iso" "$start" "$end" "$uid" "$summary")
|
|
put_event "$slug" "$uid" "$ics"
|
|
done
|
|
done
|
|
|
|
log "Done."
|
|
print_story_map
|
|
log "Calendar UI: $BASE_URL/index.php/apps/calendar/"
|
|
log "Dashboard API week: $BASE_URL/index.php/apps/opsdash/config_dashboard/load?range=week&offset=0"
|
|
log "Dashboard API month: $BASE_URL/index.php/apps/opsdash/config_dashboard/load?range=month&offset=0"
|