diff --git a/examples/hero/heromodels/heromodels_calendar_event.vsh b/examples/hero/heromodels/heromodels_calendar_event.vsh new file mode 100644 index 00000000..0a41919d --- /dev/null +++ b/examples/hero/heromodels/heromodels_calendar_event.vsh @@ -0,0 +1,41 @@ +#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.herolib.core.redisclient +import freeflowuniverse.herolib.hero.heromodels + +mut mydb := heromodels.new()! +mydb.calendar_event.db.redis.flushdb()! + +mut o := mydb.calendar_event.new( + name: 'Team Meeting' + description: 'Weekly team meeting' + title: 'Team Meeting' + start_time: '2023-01-01 10:00:00' + end_time: '2023-01-01 11:00:00' + location: 'Conference Room A' + attendees: [u32(1), u32(2), u32(3)] + fs_items: [u32(10), u32(20)] + calendar_id: u32(1) + status: .published + is_all_day: false + is_recurring: false + recurrence: [] + reminder_mins: [15, 30] + color: '#00FF00' + timezone: 'Europe/Brussels' +)! + +// Add tags if needed +o.tags = mydb.calendar_event.db.tags_get(['work', 'meeting', 'team'])! + +// Add comments if needed +// o.comments = mydb.calendar_event.db.comments_get([CommentArg{comment: 'This is a comment'}])! + +oid := mydb.calendar_event.set(o)! +mut o2 := mydb.calendar_event.get(oid)! + +println('Calendar Event ID: ${oid}') +println('Calendar Event object: ${o2}') + +mut objects := mydb.calendar_event.list()! +println('All calendar events: ${objects}') diff --git a/examples/hero/heromodels/heromodels_calendar_event_simple.vsh b/examples/hero/heromodels/heromodels_calendar_event_simple.vsh new file mode 100644 index 00000000..e34dc15b --- /dev/null +++ b/examples/hero/heromodels/heromodels_calendar_event_simple.vsh @@ -0,0 +1,38 @@ +#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.herolib.core.redisclient +import freeflowuniverse.herolib.hero.heromodels + +mut mydb := heromodels.new()! +// mydb.calendar_event.db.redis.flushdb()! + +mut o := mydb.calendar_event.new( + name: 'Team Meeting' + description: 'Weekly team meeting' + title: 'Team Meeting' + start_time: '2023-01-01 10:00:00' + end_time: '2023-01-01 11:00:00' + location: 'Conference Room A' + attendees: [u32(1), u32(2), u32(3)] + fs_items: [u32(10), u32(20)] + calendar_id: u32(1) + status: .published + is_all_day: false + is_recurring: false + recurrence: [] + reminder_mins: [15, 30] + color: '#00FF00' + timezone: 'Europe/Brussels' +)! + +// Add tags if needed +o.tags = mydb.calendar_event.db.tags_get(['work', 'meeting', 'team'])! + +// Add comments if needed +// o.comments = mydb.calendar_event.db.comments_get([CommentArg{comment: 'This is a comment'}])! + +oid := mydb.calendar_event.set(o)! +mut o2 := mydb.calendar_event.get(oid)! + +println('Calendar Event ID: ${oid}') +println('Calendar Event object: ${o2}') diff --git a/examples/hero/heromodels/heromodels_calendar_event_with_recurrence.vsh b/examples/hero/heromodels/heromodels_calendar_event_with_recurrence.vsh new file mode 100644 index 00000000..c6b52759 --- /dev/null +++ b/examples/hero/heromodels/heromodels_calendar_event_with_recurrence.vsh @@ -0,0 +1,51 @@ +#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run + +import freeflowuniverse.herolib.core.redisclient +import freeflowuniverse.herolib.hero.heromodels + +mut mydb := heromodels.new()! +mydb.calendar_event.db.redis.flushdb()! + +// Create a recurrence rule +mut rule := heromodels.RecurrenceRule{ + frequency: .weekly + interval: 1 + until: 1672570800 + 30 * 24 * 60 * 60 // 30 days from start + count: 0 + by_weekday: [1, 3, 5] // Monday, Wednesday, Friday + by_monthday: [] +} + +mut o := mydb.calendar_event.new( + name: 'Team Meeting' + description: 'Weekly team meeting' + title: 'Team Meeting' + start_time: '2023-01-01 10:00:00' + end_time: '2023-01-01 11:00:00' + location: 'Conference Room A' + attendees: [u32(1), u32(2), u32(3)] + fs_items: [u32(10), u32(20)] + calendar_id: u32(1) + status: .published + is_all_day: false + is_recurring: true + recurrence: [rule] + reminder_mins: [15, 30] + color: '#00FF00' + timezone: 'Europe/Brussels' +)! + +// Add tags if needed +o.tags = mydb.calendar_event.db.tags_get(['work', 'meeting', 'team'])! + +// Add comments if needed +// o.comments = mydb.calendar_event.db.comments_get([CommentArg{comment: 'This is a comment'}])! + +oid := mydb.calendar_event.set(o)! +mut o2 := mydb.calendar_event.get(oid)! + +println('Calendar Event ID: ${oid}') +println('Calendar Event object: ${o2}') + +mut objects := mydb.calendar_event.list()! +println('All calendar events: ${objects}') diff --git a/lib/hero/heromodels/calendar_event.v b/lib/hero/heromodels/calendar_event.v index db3205f1..2670db8d 100644 --- a/lib/hero/heromodels/calendar_event.v +++ b/lib/hero/heromodels/calendar_event.v @@ -1,15 +1,14 @@ + module heromodels -import crypto.blake3 -import json -import freeflowuniverse.herolib.data.ourtime import freeflowuniverse.herolib.data.encoder -import freeflowuniverse.herolib.core.redisclient +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db // CalendarEvent represents a single event in a calendar @[heap] pub struct CalendarEvent { - Base + db.Base pub mut: title string start_time i64 // Unix timestamp @@ -72,45 +71,110 @@ pub enum RecurrenceFreq { yearly } -@[params] -pub struct CalendarEventArgs { - BaseArgs +pub struct DBCalendarEvent { pub mut: - title string - start_time string // use ourtime module to go from string to epoch - end_time string // use ourtime module to go from string to epoch - location string - attendees []u32 // IDs of user groups - fs_items []u32 // IDs of linked files or dirs - calendar_id u32 // Associated calendar - status EventStatus - is_all_day bool - is_recurring bool - recurrence []RecurrenceRule - reminder_mins []int // Minutes before event for reminders - color string // Hex color code - timezone string + db &db.DB @[skip; str: skip] } -pub fn calendar_event_new(args CalendarEventArgs) !CalendarEvent { - // Convert tags to u32 ID - tags_id := tags2id(args.tags)! +pub fn (self CalendarEvent) type_name() string { + return 'calendar_event' +} - return CalendarEvent{ - // Base fields - id: args.id or { 0 } - name: args.name - description: args.description - created_at: ourtime.now().unix() - updated_at: ourtime.now().unix() - securitypolicy: args.securitypolicy or { 0 } - tags: tags_id - comments: comments2ids(args.comments)! +pub fn (self CalendarEvent) dump(mut e &encoder.Encoder) ! { + e.add_string(self.title) + e.add_i64(self.start_time) + e.add_i64(self.end_time) + e.add_string(self.location) + e.add_list_u32(self.attendees) + e.add_list_u32(self.fs_items) + e.add_u32(self.calendar_id) + e.add_u8(u8(self.status)) + e.add_bool(self.is_all_day) + e.add_bool(self.is_recurring) - // CalendarEvent specific fields + // Encode recurrence array + e.add_u16(u16(self.recurrence.len)) + for rule in self.recurrence { + e.add_u8(u8(rule.frequency)) + e.add_int(rule.interval) + e.add_i64(rule.until) + e.add_int(rule.count) + e.add_list_int(rule.by_weekday) + e.add_list_int(rule.by_monthday) + } + + e.add_list_int(self.reminder_mins) + e.add_string(self.color) + e.add_string(self.timezone) +} + +fn (mut self DBCalendarEvent) load(mut o CalendarEvent, mut e &encoder.Decoder) ! { + o.title = e.get_string()! + o.start_time = e.get_i64()! + o.end_time = e.get_i64()! + o.location = e.get_string()! + o.attendees = e.get_list_u32()! + o.fs_items = e.get_list_u32()! + o.calendar_id = e.get_u32()! + o.status = unsafe { EventStatus(e.get_u8()!) } + o.is_all_day = e.get_bool()! + o.is_recurring = e.get_bool()! + + // Decode recurrence array + recurrence_len := e.get_u16()! + mut recurrence := []RecurrenceRule{} + for _ in 0 .. recurrence_len { + frequency := unsafe { RecurrenceFreq(e.get_u8()!) } + interval := e.get_int()! + until := e.get_i64()! + count := e.get_int()! + by_weekday := e.get_list_int()! + by_monthday := e.get_list_int()! + + recurrence << RecurrenceRule{ + frequency: frequency + interval: interval + until: until + count: count + by_weekday: by_weekday + by_monthday: by_monthday + } + } + o.recurrence = recurrence + + o.reminder_mins = e.get_list_int()! + o.color = e.get_string()! + o.timezone = e.get_string()! +} + +@[params] +pub struct CalendarEventArg { +pub mut: + name string + description string + title string + start_time string // use ourtime module to go from string to epoch + end_time string // use ourtime module to go from string to epoch + location string + attendees []u32 // IDs of user groups + fs_items []u32 // IDs of linked files or dirs + calendar_id u32 // Associated calendar + status EventStatus + is_all_day bool + is_recurring bool + recurrence []RecurrenceRule + reminder_mins []int // Minutes before event for reminders + color string // Hex color code + timezone string + securitypolicy u32 + tags []string + comments []db.CommentArg +} + +// get new calendar event, not from the DB +pub fn (mut self DBCalendarEvent) new(args CalendarEventArg) !CalendarEvent { + mut o := CalendarEvent{ title: args.title - start_time: ourtime.new(args.start_time)!.unix() - end_time: ourtime.new(args.end_time)!.unix() location: args.location attendees: args.attendees fs_items: args.fs_items @@ -123,139 +187,45 @@ pub fn calendar_event_new(args CalendarEventArgs) !CalendarEvent { color: args.color timezone: args.timezone } + + // Set base fields + o.name = args.name + o.description = args.description + o.securitypolicy = args.securitypolicy + o.tags = self.db.tags_get(args.tags)! + o.comments = self.db.comments_get(args.comments)! + o.updated_at = ourtime.now().unix() + + // Convert string times to Unix timestamps + mut start_time_obj := ourtime.new(args.start_time)! + o.start_time = start_time_obj.unix() + + mut end_time_obj := ourtime.new(args.end_time)! + o.end_time = end_time_obj.unix() + + return o } -pub fn (mut e CalendarEvent) dump() ![]u8 { - // Create a new encoder - mut enc := encoder.new() - - // Add version byte - enc.add_u8(1) - - // Encode Base fields - enc.add_u32(e.id) - enc.add_string(e.name) - enc.add_string(e.description) - enc.add_i64(e.created_at) - enc.add_i64(e.updated_at) - enc.add_u32(e.securitypolicy) - enc.add_u32(e.tags) - enc.add_list_u32(e.comments) - - // Encode CalendarEvent specific fields - enc.add_string(e.title) - enc.add_string(e.description) - enc.add_i64(e.start_time) - enc.add_i64(e.end_time) - enc.add_string(e.location) - enc.add_list_u32(e.attendees) - enc.add_list_u32(e.fs_items) - enc.add_u32(e.calendar_id) - enc.add_u8(u8(e.status)) - enc.add_bool(e.is_all_day) - enc.add_bool(e.is_recurring) - - // Encode recurrence array - enc.add_u16(u16(e.recurrence.len)) - for rule in e.recurrence { - enc.add_u8(u8(rule.frequency)) - enc.add_int(rule.interval) - enc.add_i64(rule.until) - enc.add_int(rule.count) - enc.add_list_int(rule.by_weekday) - enc.add_list_int(rule.by_monthday) - } - - enc.add_list_int(e.reminder_mins) - enc.add_string(e.color) - enc.add_string(e.timezone) - - return enc.data +pub fn (mut self DBCalendarEvent) set(o CalendarEvent) !u32 { + // Use db set function which now returns the ID + return self.db.set[CalendarEvent](o)! } -pub fn (ce CalendarEvent) load(data []u8) !CalendarEvent { - // Create a new decoder - mut dec := encoder.decoder_new(data) - - // Read version byte - version := dec.get_u8()! - if version != 1 { - return error('wrong version in calendar event load') - } - - // Decode Base fields - id := dec.get_u32()! - name := dec.get_string()! - description := dec.get_string()! - created_at := dec.get_i64()! - updated_at := dec.get_i64()! - securitypolicy := dec.get_u32()! - tags := dec.get_u32()! - comments := dec.get_list_u32()! - - // Decode CalendarEvent specific fields - title := dec.get_string()! - description2 := dec.get_string()! // Second description field - start_time := dec.get_i64()! - end_time := dec.get_i64()! - location := dec.get_string()! - attendees := dec.get_list_u32()! - fs_items := dec.get_list_u32()! - calendar_id := dec.get_u32()! - status := unsafe { EventStatus(dec.get_u8()!) } - is_all_day := dec.get_bool()! - is_recurring := dec.get_bool()! - - // Decode recurrence array - recurrence_len := dec.get_u16()! - mut recurrence := []RecurrenceRule{} - for _ in 0 .. recurrence_len { - frequency := unsafe { RecurrenceFreq(dec.get_u8()!) } - interval := dec.get_int()! - until := dec.get_i64()! - count := dec.get_int()! - by_weekday := dec.get_list_int()! - by_monthday := dec.get_list_int()! - - recurrence << RecurrenceRule{ - frequency: frequency - interval: interval - until: until - count: count - by_weekday: by_weekday - by_monthday: by_monthday - } - } - - reminder_mins := dec.get_list_int()! - color := dec.get_string()! - timezone := dec.get_string()! - - return CalendarEvent{ - // Base fields - id: id - name: name - description: description - created_at: created_at - updated_at: updated_at - securitypolicy: securitypolicy - tags: tags - comments: comments - - // CalendarEvent specific fields - title: title - start_time: start_time - end_time: end_time - location: location - attendees: attendees - fs_items: fs_items - calendar_id: calendar_id - status: status - is_all_day: is_all_day - is_recurring: is_recurring - recurrence: recurrence - reminder_mins: reminder_mins - color: color - timezone: timezone - } +pub fn (mut self DBCalendarEvent) delete(id u32) ! { + self.db.delete[CalendarEvent](id)! +} + +pub fn (mut self DBCalendarEvent) exist(id u32) !bool { + return self.db.exists[CalendarEvent](id)! +} + +pub fn (mut self DBCalendarEvent) get(id u32) !CalendarEvent { + mut o, data := self.db.get_data[CalendarEvent](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBCalendarEvent) list() ![]CalendarEvent { + return self.db.list[CalendarEvent]()!.map(self.get(it)!) } diff --git a/lib/hero/heromodels/factory.v b/lib/hero/heromodels/factory.v index 8d47ed3b..0ab5d926 100644 --- a/lib/hero/heromodels/factory.v +++ b/lib/hero/heromodels/factory.v @@ -4,8 +4,9 @@ import freeflowuniverse.herolib.hero.db pub struct ModelsFactory { pub mut: - comments DBComments - calendar DBCalendar + comments DBComments + calendar DBCalendar + calendar_event DBCalendarEvent } pub fn new() !ModelsFactory { @@ -17,5 +18,8 @@ pub fn new() !ModelsFactory { calendar: DBCalendar{ db: &mydb } + calendar_event: DBCalendarEvent{ + db: &mydb + } } }