feat: initial daily-timer implementation

This commit is contained in:
Mikhail Kiselev
2026-02-08 05:17:37 +03:00
parent 537f72eb51
commit ef23291bdd
37 changed files with 7779 additions and 0 deletions

53
frontend/wailsjs/go/app/App.d.ts vendored Executable file
View File

@@ -0,0 +1,53 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import {models} from '../models';
export function AddParticipant(arg1:string,arg2:string,arg3:number):Promise<models.Participant>;
export function DeleteAllSessions():Promise<void>;
export function DeleteParticipant(arg1:number):Promise<void>;
export function DeleteSession(arg1:number):Promise<void>;
export function ExportCSV(arg1:string,arg2:string):Promise<string>;
export function ExportData(arg1:string,arg2:string):Promise<string>;
export function GetMeeting():Promise<models.Meeting>;
export function GetParticipants():Promise<Array<models.Participant>>;
export function GetSession(arg1:number):Promise<models.MeetingSession>;
export function GetSessions(arg1:number,arg2:number):Promise<Array<models.MeetingSession>>;
export function GetSettings():Promise<models.Settings>;
export function GetSoundsDir():Promise<string>;
export function GetStatistics(arg1:string,arg2:string):Promise<models.AggregatedStats>;
export function GetTimerState():Promise<models.TimerState>;
export function NextSpeaker():Promise<void>;
export function PauseMeeting():Promise<void>;
export function RemoveFromQueue(arg1:number):Promise<void>;
export function ReorderParticipants(arg1:Array<number>):Promise<void>;
export function ResumeMeeting():Promise<void>;
export function SkipSpeaker():Promise<void>;
export function StartMeeting(arg1:Array<number>,arg2:Record<number, boolean>):Promise<void>;
export function StopMeeting():Promise<void>;
export function UpdateMeeting(arg1:string,arg2:number):Promise<void>;
export function UpdateParticipant(arg1:number,arg2:string,arg3:string,arg4:number):Promise<void>;
export function UpdateSettings(arg1:models.Settings):Promise<void>;

103
frontend/wailsjs/go/app/App.js Executable file
View File

@@ -0,0 +1,103 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
export function AddParticipant(arg1, arg2, arg3) {
return window['go']['app']['App']['AddParticipant'](arg1, arg2, arg3);
}
export function DeleteAllSessions() {
return window['go']['app']['App']['DeleteAllSessions']();
}
export function DeleteParticipant(arg1) {
return window['go']['app']['App']['DeleteParticipant'](arg1);
}
export function DeleteSession(arg1) {
return window['go']['app']['App']['DeleteSession'](arg1);
}
export function ExportCSV(arg1, arg2) {
return window['go']['app']['App']['ExportCSV'](arg1, arg2);
}
export function ExportData(arg1, arg2) {
return window['go']['app']['App']['ExportData'](arg1, arg2);
}
export function GetMeeting() {
return window['go']['app']['App']['GetMeeting']();
}
export function GetParticipants() {
return window['go']['app']['App']['GetParticipants']();
}
export function GetSession(arg1) {
return window['go']['app']['App']['GetSession'](arg1);
}
export function GetSessions(arg1, arg2) {
return window['go']['app']['App']['GetSessions'](arg1, arg2);
}
export function GetSettings() {
return window['go']['app']['App']['GetSettings']();
}
export function GetSoundsDir() {
return window['go']['app']['App']['GetSoundsDir']();
}
export function GetStatistics(arg1, arg2) {
return window['go']['app']['App']['GetStatistics'](arg1, arg2);
}
export function GetTimerState() {
return window['go']['app']['App']['GetTimerState']();
}
export function NextSpeaker() {
return window['go']['app']['App']['NextSpeaker']();
}
export function PauseMeeting() {
return window['go']['app']['App']['PauseMeeting']();
}
export function RemoveFromQueue(arg1) {
return window['go']['app']['App']['RemoveFromQueue'](arg1);
}
export function ReorderParticipants(arg1) {
return window['go']['app']['App']['ReorderParticipants'](arg1);
}
export function ResumeMeeting() {
return window['go']['app']['App']['ResumeMeeting']();
}
export function SkipSpeaker() {
return window['go']['app']['App']['SkipSpeaker']();
}
export function StartMeeting(arg1, arg2) {
return window['go']['app']['App']['StartMeeting'](arg1, arg2);
}
export function StopMeeting() {
return window['go']['app']['App']['StopMeeting']();
}
export function UpdateMeeting(arg1, arg2) {
return window['go']['app']['App']['UpdateMeeting'](arg1, arg2);
}
export function UpdateParticipant(arg1, arg2, arg3, arg4) {
return window['go']['app']['App']['UpdateParticipant'](arg1, arg2, arg3, arg4);
}
export function UpdateSettings(arg1) {
return window['go']['app']['App']['UpdateSettings'](arg1);
}

434
frontend/wailsjs/go/models.ts Executable file
View File

@@ -0,0 +1,434 @@
export namespace models {
export class ParticipantBreakdown {
participantId: number;
name: string;
sessionsAttended: number;
totalSpeakingTime: number;
averageSpeakingTime: number;
overtimeCount: number;
skipCount: number;
attendanceRate: number;
static createFrom(source: any = {}) {
return new ParticipantBreakdown(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.participantId = source["participantId"];
this.name = source["name"];
this.sessionsAttended = source["sessionsAttended"];
this.totalSpeakingTime = source["totalSpeakingTime"];
this.averageSpeakingTime = source["averageSpeakingTime"];
this.overtimeCount = source["overtimeCount"];
this.skipCount = source["skipCount"];
this.attendanceRate = source["attendanceRate"];
}
}
export class AggregatedStats {
totalSessions: number;
totalMeetingTime: number;
averageMeetingTime: number;
overtimeSessions: number;
overtimePercentage: number;
averageAttendance: number;
participantBreakdown: ParticipantBreakdown[];
static createFrom(source: any = {}) {
return new AggregatedStats(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.totalSessions = source["totalSessions"];
this.totalMeetingTime = source["totalMeetingTime"];
this.averageMeetingTime = source["averageMeetingTime"];
this.overtimeSessions = source["overtimeSessions"];
this.overtimePercentage = source["overtimePercentage"];
this.averageAttendance = source["averageAttendance"];
this.participantBreakdown = this.convertValues(source["participantBreakdown"], ParticipantBreakdown);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class SessionAttendance {
id: number;
sessionId: number;
participantId: number;
participant?: Participant;
present: boolean;
joinedLate: boolean;
static createFrom(source: any = {}) {
return new SessionAttendance(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.sessionId = source["sessionId"];
this.participantId = source["participantId"];
this.participant = this.convertValues(source["participant"], Participant);
this.present = source["present"];
this.joinedLate = source["joinedLate"];
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class Participant {
id: number;
name: string;
email?: string;
timeLimit: number;
order: number;
active: boolean;
// Go type: time
createdAt: any;
// Go type: time
updatedAt: any;
static createFrom(source: any = {}) {
return new Participant(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.name = source["name"];
this.email = source["email"];
this.timeLimit = source["timeLimit"];
this.order = source["order"];
this.active = source["active"];
this.createdAt = this.convertValues(source["createdAt"], null);
this.updatedAt = this.convertValues(source["updatedAt"], null);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class ParticipantLog {
id: number;
sessionId: number;
participantId: number;
participant?: Participant;
// Go type: time
startedAt: any;
// Go type: time
endedAt?: any;
duration: number;
skipped: boolean;
overtime: boolean;
order: number;
static createFrom(source: any = {}) {
return new ParticipantLog(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.sessionId = source["sessionId"];
this.participantId = source["participantId"];
this.participant = this.convertValues(source["participant"], Participant);
this.startedAt = this.convertValues(source["startedAt"], null);
this.endedAt = this.convertValues(source["endedAt"], null);
this.duration = source["duration"];
this.skipped = source["skipped"];
this.overtime = source["overtime"];
this.order = source["order"];
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class MeetingSession {
id: number;
meetingId: number;
// Go type: time
startedAt: any;
// Go type: time
endedAt?: any;
totalDuration: number;
completed: boolean;
participantLogs?: ParticipantLog[];
attendance?: SessionAttendance[];
static createFrom(source: any = {}) {
return new MeetingSession(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.meetingId = source["meetingId"];
this.startedAt = this.convertValues(source["startedAt"], null);
this.endedAt = this.convertValues(source["endedAt"], null);
this.totalDuration = source["totalDuration"];
this.completed = source["completed"];
this.participantLogs = this.convertValues(source["participantLogs"], ParticipantLog);
this.attendance = this.convertValues(source["attendance"], SessionAttendance);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class Meeting {
id: number;
name: string;
timeLimit: number;
sessions?: MeetingSession[];
// Go type: time
createdAt: any;
// Go type: time
updatedAt: any;
static createFrom(source: any = {}) {
return new Meeting(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.name = source["name"];
this.timeLimit = source["timeLimit"];
this.sessions = this.convertValues(source["sessions"], MeetingSession);
this.createdAt = this.convertValues(source["createdAt"], null);
this.updatedAt = this.convertValues(source["updatedAt"], null);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
export class QueuedSpeaker {
id: number;
name: string;
timeLimit: number;
order: number;
static createFrom(source: any = {}) {
return new QueuedSpeaker(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.name = source["name"];
this.timeLimit = source["timeLimit"];
this.order = source["order"];
}
}
export class Settings {
id: number;
defaultParticipantTime: number;
defaultMeetingTime: number;
soundEnabled: boolean;
soundWarning: string;
soundTimeUp: string;
soundMeetingEnd: string;
warningThreshold: number;
theme: string;
windowWidth: number;
windowFullHeight: boolean;
static createFrom(source: any = {}) {
return new Settings(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.defaultParticipantTime = source["defaultParticipantTime"];
this.defaultMeetingTime = source["defaultMeetingTime"];
this.soundEnabled = source["soundEnabled"];
this.soundWarning = source["soundWarning"];
this.soundTimeUp = source["soundTimeUp"];
this.soundMeetingEnd = source["soundMeetingEnd"];
this.warningThreshold = source["warningThreshold"];
this.theme = source["theme"];
this.windowWidth = source["windowWidth"];
this.windowFullHeight = source["windowFullHeight"];
}
}
export class SpeakerInfo {
id: number;
name: string;
timeLimit: number;
order: number;
status: string;
static createFrom(source: any = {}) {
return new SpeakerInfo(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.id = source["id"];
this.name = source["name"];
this.timeLimit = source["timeLimit"];
this.order = source["order"];
this.status = source["status"];
}
}
export class TimerState {
running: boolean;
paused: boolean;
currentSpeakerId: number;
currentSpeaker: string;
speakerElapsed: number;
speakerLimit: number;
meetingElapsed: number;
meetingLimit: number;
speakerOvertime: boolean;
meetingOvertime: boolean;
warning: boolean;
warningSeconds: number;
totalSpeakersTime: number;
speakingOrder: number;
totalSpeakers: number;
remainingQueue: QueuedSpeaker[];
allSpeakers: SpeakerInfo[];
static createFrom(source: any = {}) {
return new TimerState(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.running = source["running"];
this.paused = source["paused"];
this.currentSpeakerId = source["currentSpeakerId"];
this.currentSpeaker = source["currentSpeaker"];
this.speakerElapsed = source["speakerElapsed"];
this.speakerLimit = source["speakerLimit"];
this.meetingElapsed = source["meetingElapsed"];
this.meetingLimit = source["meetingLimit"];
this.speakerOvertime = source["speakerOvertime"];
this.meetingOvertime = source["meetingOvertime"];
this.warning = source["warning"];
this.warningSeconds = source["warningSeconds"];
this.totalSpeakersTime = source["totalSpeakersTime"];
this.speakingOrder = source["speakingOrder"];
this.totalSpeakers = source["totalSpeakers"];
this.remainingQueue = this.convertValues(source["remainingQueue"], QueuedSpeaker);
this.allSpeakers = this.convertValues(source["allSpeakers"], SpeakerInfo);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice && a.map) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
}