diff --git a/bot/src/bot_data/model/scheduled_event.py b/bot/src/bot_data/model/scheduled_event.py index fa05c946..3f8fbee3 100644 --- a/bot/src/bot_data/model/scheduled_event.py +++ b/bot/src/bot_data/model/scheduled_event.py @@ -4,13 +4,14 @@ from typing import Optional import discord from cpl_core.database import TableABC +from bot_data.model.scheduled_event_interval_enum import ScheduledEventIntervalEnum from bot_data.model.server import Server class ScheduledEvent(TableABC): def __init__( self, - interval: str, + interval: ScheduledEventIntervalEnum, name: str, description: str, channel_id: int, @@ -43,11 +44,11 @@ class ScheduledEvent(TableABC): return self._id @property - def interval(self) -> str: + def interval(self) -> ScheduledEventIntervalEnum: return self._interval @interval.setter - def interval(self, value: str): + def interval(self, value: ScheduledEventIntervalEnum): self._interval = value @property @@ -145,11 +146,11 @@ class ScheduledEvent(TableABC): return str( f""" INSERT INTO `ScheduledEvents` ( - `Interval`, `Name`, `Description`, `ChannelId`, `StartTime`, `EndTime`, `EntityType`, `Location`, `ServerId`, + `Interval`, `Name`, `Description`, `ChannelId`, `StartTime`, `EndTime`, `EntityType`, `Location`, `ServerId` ) VALUES ( - '{self._interval}', + '{self._interval.value}', '{self._name}', - '{self._description}', + {"NULL" if self._description is None else f"'{self._description}'"}, {"NULL" if self._channel_id is None else f"'{self._channel_id}'"}, '{self._start_time}', {"NULL" if self._end_time is None else f"'{self._end_time}'"}, @@ -165,7 +166,7 @@ class ScheduledEvent(TableABC): return str( f""" UPDATE `ScheduledEvents` - SET `Interval` = '{self._interval}', + SET `Interval` = '{self._interval.value}', `Name` = '{self._name}', `Description` = '{self._start_time}', `ChannelId` = {"NULL" if self._channel_id is None else f"'{self._channel_id}'"}, diff --git a/bot/src/bot_data/model/scheduled_event_interval_enum.py b/bot/src/bot_data/model/scheduled_event_interval_enum.py new file mode 100644 index 00000000..7f13c589 --- /dev/null +++ b/bot/src/bot_data/model/scheduled_event_interval_enum.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class ScheduledEventIntervalEnum(Enum): + daily = "daily" + weekly = "weekly" + monthly = "monthly" + yearly = "yearly" diff --git a/bot/src/bot_data/scripts/1.2.2/1_ScheduledEvents_up.sql b/bot/src/bot_data/scripts/1.2.2/1_ScheduledEvents_up.sql index 2768651e..843c21fc 100644 --- a/bot/src/bot_data/scripts/1.2.2/1_ScheduledEvents_up.sql +++ b/bot/src/bot_data/scripts/1.2.2/1_ScheduledEvents_up.sql @@ -1,9 +1,9 @@ CREATE TABLE IF NOT EXISTS `ScheduledEvents` ( `Id` BIGINT NOT NULL AUTO_INCREMENT, - `Interval` VARCHAR(255) NOT NULL, + `Interval` ENUM ('daily', 'weekly', 'monthly', 'yearly') NOT NULL, `Name` VARCHAR(255) NOT NULL, - `Description` VARCHAR(255) NOT NULL, + `Description` VARCHAR(255) NULL, `ChannelId` BIGINT NULL, `StartTime` DATETIME(6) NOT NULL, `EndTime` DATETIME(6) NULL, @@ -19,9 +19,9 @@ CREATE TABLE IF NOT EXISTS `ScheduledEvents` CREATE TABLE IF NOT EXISTS `ScheduledEventsHistory` ( `Id` BIGINT(20) NOT NULL, - `Interval` VARCHAR(255) NOT NULL, + `Interval` ENUM ('daily', 'weekly', 'monthly', 'yearly') NOT NULL, `Name` VARCHAR(255) NOT NULL, - `Description` VARCHAR(255) NOT NULL, + `Description` VARCHAR(255) NULL, `ChannelId` BIGINT NULL, `StartTime` DATETIME(6) NOT NULL, `EndTime` DATETIME(6) NULL, diff --git a/bot/src/bot_data/service/scheduled_event_repository_service.py b/bot/src/bot_data/service/scheduled_event_repository_service.py index 7d5e67ba..01d4fc6c 100644 --- a/bot/src/bot_data/service/scheduled_event_repository_service.py +++ b/bot/src/bot_data/service/scheduled_event_repository_service.py @@ -7,6 +7,7 @@ from bot_core.logging.database_logger import DatabaseLogger from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.scheduled_event_repository_abc import ScheduledEventRepositoryABC from bot_data.model.scheduled_event import ScheduledEvent +from bot_data.model.scheduled_event_interval_enum import ScheduledEventIntervalEnum class ScheduledEventRepositoryService(ScheduledEventRepositoryABC): @@ -32,17 +33,17 @@ class ScheduledEventRepositoryService(ScheduledEventRepositoryABC): def _scheduled_event_from_result(self, sql_result: tuple) -> ScheduledEvent: return ScheduledEvent( - self._get_value_from_result(sql_result[0]), # interval - self._get_value_from_result(sql_result[1]), # name - self._get_value_from_result(sql_result[2]), # description - int(self._get_value_from_result(sql_result[3])), # channel_id - self._get_value_from_result(sql_result[4]), # start_time - self._get_value_from_result(sql_result[5]), # end_time - self._get_value_from_result(sql_result[6]), # entity_type - self._get_value_from_result(sql_result[7]), # location - self._servers.get_server_by_id((sql_result[8])), # server - self._get_value_from_result(sql_result[9]), # created_at - self._get_value_from_result(sql_result[10]), # modified_at + self._get_value_from_result(ScheduledEventIntervalEnum(sql_result[1])), # interval + self._get_value_from_result(sql_result[2]), # name + self._get_value_from_result(sql_result[3]), # description + int(self._get_value_from_result(sql_result[4])), # channel_id + self._get_value_from_result(sql_result[5]), # start_time + self._get_value_from_result(sql_result[6]), # end_time + self._get_value_from_result(sql_result[7]), # entity_type + self._get_value_from_result(sql_result[8]), # location + self._servers.get_server_by_id((sql_result[9])), # server + self._get_value_from_result(sql_result[10]), # created_at + self._get_value_from_result(sql_result[11]), # modified_at id=self._get_value_from_result(sql_result[0]), ) diff --git a/bot/src/bot_graphql/abc/filter_abc.py b/bot/src/bot_graphql/abc/filter_abc.py index 7c1fa477..3067b075 100644 --- a/bot/src/bot_graphql/abc/filter_abc.py +++ b/bot/src/bot_graphql/abc/filter_abc.py @@ -63,7 +63,9 @@ class FilterABC(ABC): self.__setattr__(f"_{attr}", attr_type(values[attr])) @staticmethod - def _filter_by_attributes(attrs: list[Callable], values: List[T]) -> List[R]: + def _filter_by_attributes(attrs: list[dict], values: List[T]) -> List[R]: for attr in attrs: - values = values.where(attr) + if attr["attr"] is None: + continue + values = values.where(attr["func"]) return values diff --git a/bot/src/bot_graphql/filter/scheduled_event_filter.py b/bot/src/bot_graphql/filter/scheduled_event_filter.py index d1937c25..e98be02b 100644 --- a/bot/src/bot_graphql/filter/scheduled_event_filter.py +++ b/bot/src/bot_graphql/filter/scheduled_event_filter.py @@ -51,15 +51,15 @@ class ScheduledEventFilter(FilterABC): query = self._filter_by_attributes( [ - lambda x: x.id == self._id, - lambda x: x.interval == self._interval, - lambda x: x.name == self._name, - lambda x: x.description == self._description, - lambda x: x.channel_id == self._channel_id, - lambda x: x.start_time == self._start_time, - lambda x: x.end_time == self._end_time, - lambda x: x.entity_type == self._entity_type, - lambda x: x.location == self._location, + {"attr": self._id, "func": lambda x: x.id == self._id}, + {"attr": self._interval, "func": lambda x: x.interval == self._interval}, + {"attr": self._name, "func": lambda x: x.name == self._name}, + {"attr": self._description, "func": lambda x: x.description == self._description}, + {"attr": self._channel_id, "func": lambda x: x.channel_id == self._channel_id}, + {"attr": self._start_time, "func": lambda x: x.start_time == self._start_time}, + {"attr": self._end_time, "func": lambda x: x.end_time == self._end_time}, + {"attr": self._entity_type, "func": lambda x: x.entity_type == self._entity_type}, + {"attr": self._location, "func": lambda x: x.location == self._location}, ], query, ) diff --git a/bot/src/bot_graphql/mutation.py b/bot/src/bot_graphql/mutation.py index 39e38cc5..86b269d0 100644 --- a/bot/src/bot_graphql/mutation.py +++ b/bot/src/bot_graphql/mutation.py @@ -4,6 +4,7 @@ from bot_graphql.mutations.achievement_mutation import AchievementMutation from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation from bot_graphql.mutations.level_mutation import LevelMutation +from bot_graphql.mutations.scheduled_event_mutation import ScheduledEventMutation from bot_graphql.mutations.server_config_mutation import ServerConfigMutation from bot_graphql.mutations.short_role_name_mutation import ShortRoleNameMutation from bot_graphql.mutations.technician_config_mutation import TechnicianConfigMutation @@ -23,6 +24,7 @@ class Mutation(MutationType): achievement_mutation: AchievementMutation, user_joined_game_server: UserJoinedGameServerMutation, technician_config: TechnicianConfigMutation, + scheduled_event: ScheduledEventMutation, server_config: ServerConfigMutation, short_role_name_mutation: ShortRoleNameMutation, ): @@ -36,4 +38,5 @@ class Mutation(MutationType): self.set_field("userJoinedGameServer", lambda *_: user_joined_game_server) self.set_field("shortRoleName", lambda *_: short_role_name_mutation) self.set_field("technicianConfig", lambda *_: technician_config) + self.set_field("scheduledEvent", lambda *_: scheduled_event) self.set_field("serverConfig", lambda *_: server_config) diff --git a/bot/src/bot_graphql/mutations/scheduled_event_mutation.py b/bot/src/bot_graphql/mutations/scheduled_event_mutation.py index c138b082..81353c62 100644 --- a/bot/src/bot_graphql/mutations/scheduled_event_mutation.py +++ b/bot/src/bot_graphql/mutations/scheduled_event_mutation.py @@ -1,9 +1,12 @@ +from datetime import datetime + from cpl_core.database.context import DatabaseContextABC from cpl_discord.service import DiscordBotServiceABC from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.scheduled_event_repository_abc import ScheduledEventRepositoryABC from bot_data.model.scheduled_event import ScheduledEvent +from bot_data.model.scheduled_event_interval_enum import ScheduledEventIntervalEnum from bot_data.model.user_role_enum import UserRoleEnum from bot_graphql.abc.query_abc import QueryABC from modules.permission.service.permission_service import PermissionService @@ -35,14 +38,14 @@ class ScheduledEventMutation(QueryABC): self._can_user_mutate_data(server, UserRoleEnum.moderator) scheduled_event = ScheduledEvent( - input["interval"], + ScheduledEventIntervalEnum(input["interval"]), input["name"], - input["description"], - input["channel_id"], - input["start_time"], - input["end_time"], - input["entity_type"], - input["location"], + input["description"] if "description" in input else None, + input["channelId"] if "channelId" in input else None, + datetime.strptime(input["startTime"], "%Y-%m-%dT%H:%M:%S.%fZ"), + datetime.strptime(input["endTime"], "%Y-%m-%dT%H:%M:%S.%fZ") if "endTime" in input else None, + input["entityType"], + input["location"] if "location" in input else None, server, ) @@ -70,10 +73,10 @@ class ScheduledEventMutation(QueryABC): scheduled_event.interval = input["interval"] if "interval" in input else scheduled_event.interval scheduled_event.name = input["name"] if "name" in input else scheduled_event.name scheduled_event.description = input["description"] if "description" in input else scheduled_event.description - scheduled_event.channel_id = input["channel_id"] if "channel_id" in input else scheduled_event.channel_id - scheduled_event.start_time = input["start_time"] if "start_time" in input else scheduled_event.start_time - scheduled_event.end_time = input["end_time"] if "end_time" in input else scheduled_event.end_time - scheduled_event.entity_type = input["entity_type"] if "entity_type" in input else scheduled_event.entity_type + scheduled_event.channel_id = input["channelId"] if "channelId" in input else scheduled_event.channel_id + scheduled_event.start_time = input["startTime"] if "startTime" in input else scheduled_event.start_time + scheduled_event.end_time = input["endTime"] if "endTime" in input else scheduled_event.end_time + scheduled_event.entity_type = input["entityType"] if "entityType" in input else scheduled_event.entity_type scheduled_event.location = input["location"] if "location" in input else scheduled_event.location self._scheduled_events.update_scheduled_event(scheduled_event) diff --git a/web/package.json b/web/package.json index 3255abc5..281eca54 100644 --- a/web/package.json +++ b/web/package.json @@ -1,56 +1,56 @@ { - "name": "web", - "version": "1.2.2", - "scripts": { - "ng": "ng", - "update-version": "ts-node update-version.ts", - "prestart": "npm run update-version", - "start": "ng serve", - "prebuild": "npm run update-version", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "gv": "echo $npm_package_version", - "predocker-build": "npm run update-version", - "docker-build": "export VERSION=$npm_package_version; ng build; docker build -t sh-edraft.de/sdb-web:$VERSION .", - "docker-build-dev": "export VERSION=$npm_package_version; ng build --configuration development; docker build -t sh-edraft.de/sdb-web:$VERSION .", - "docker-build-stage": "export VERSION=$npm_package_version; ng build --configuration staging; docker build -t sh-edraft.de/sdb-web:$VERSION ." - }, - "private": true, - "dependencies": { - "@angular/animations": "^15.1.4", - "@angular/common": "^15.1.4", - "@angular/compiler": "^15.1.4", - "@angular/core": "^15.1.4", - "@angular/forms": "^15.1.4", - "@angular/platform-browser": "^15.1.4", - "@angular/platform-browser-dynamic": "^15.1.4", - "@angular/router": "^15.1.4", - "@auth0/angular-jwt": "^5.1.0", - "@microsoft/signalr": "^6.0.9", - "@ngx-translate/core": "^14.0.0", - "@ngx-translate/http-loader": "^7.0.0", - "@types/socket.io-client": "^3.0.0", - "moment": "^2.29.4", - "primeicons": "^6.0.1", - "primeng": "^15.2.0", - "rxjs": "~7.5.0", - "socket.io-client": "^4.5.3", - "zone.js": "~0.11.4" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^15.1.5", - "@angular/cli": "~15.1.5", - "@angular/compiler-cli": "^15.1.4", - "@types/jasmine": "~4.0.0", - "@types/node": "^18.11.9", - "jasmine-core": "~4.1.0", - "karma": "~6.3.0", - "karma-chrome-launcher": "~3.1.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.0.0", - "karma-jasmine-html-reporter": "~1.7.0", - "tslib": "^2.4.1", - "typescript": "~4.9.5" - } -} + "name": "web", + "version": "1.2.dev410", + "scripts": { + "ng": "ng", + "update-version": "ts-node update-version.ts", + "prestart": "npm run update-version", + "start": "ng serve", + "prebuild": "npm run update-version", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test", + "gv": "echo $npm_package_version", + "predocker-build": "npm run update-version", + "docker-build": "export VERSION=$npm_package_version; ng build; docker build -t sh-edraft.de/sdb-web:$VERSION .", + "docker-build-dev": "export VERSION=$npm_package_version; ng build --configuration development; docker build -t sh-edraft.de/sdb-web:$VERSION .", + "docker-build-stage": "export VERSION=$npm_package_version; ng build --configuration staging; docker build -t sh-edraft.de/sdb-web:$VERSION ." + }, + "private": true, + "dependencies": { + "@angular/animations": "^15.1.4", + "@angular/common": "^15.1.4", + "@angular/compiler": "^15.1.4", + "@angular/core": "^15.1.4", + "@angular/forms": "^15.1.4", + "@angular/platform-browser": "^15.1.4", + "@angular/platform-browser-dynamic": "^15.1.4", + "@angular/router": "^15.1.4", + "@auth0/angular-jwt": "^5.1.0", + "@microsoft/signalr": "^6.0.9", + "@ngx-translate/core": "^14.0.0", + "@ngx-translate/http-loader": "^7.0.0", + "@types/socket.io-client": "^3.0.0", + "moment": "^2.29.4", + "primeicons": "^6.0.1", + "primeng": "^15.2.0", + "rxjs": "~7.5.0", + "socket.io-client": "^4.5.3", + "zone.js": "~0.11.4" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^15.1.5", + "@angular/cli": "~15.1.5", + "@angular/compiler-cli": "^15.1.4", + "@types/jasmine": "~4.0.0", + "@types/node": "^18.11.9", + "jasmine-core": "~4.1.0", + "karma": "~6.3.0", + "karma-chrome-launcher": "~3.1.0", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.0.0", + "karma-jasmine-html-reporter": "~1.7.0", + "tslib": "^2.4.1", + "typescript": "~4.9.5" + } +} \ No newline at end of file diff --git a/web/src/app/models/data/discord.model.ts b/web/src/app/models/data/discord.model.ts index 6e640052..a77de21e 100644 --- a/web/src/app/models/data/discord.model.ts +++ b/web/src/app/models/data/discord.model.ts @@ -1,4 +1,4 @@ -export interface Discord { +export interface Discord { guilds?: Guild[]; users?: DiscordUser[]; } @@ -21,7 +21,8 @@ export interface Channel { export enum ChannelType { category = "CategoryChannel", text = "TextChannel", - voice = "VoiceChannel" + voice = "VoiceChannel", + stage = "StageChannel" } export interface Role { diff --git a/web/src/app/models/data/scheduled_events.model.ts b/web/src/app/models/data/scheduled_events.model.ts index c3e8beea..972c10bb 100644 --- a/web/src/app/models/data/scheduled_events.model.ts +++ b/web/src/app/models/data/scheduled_events.model.ts @@ -9,12 +9,12 @@ export enum EventType { export interface ScheduledEvent extends DataWithHistory { id?: number; - interval?: string; + interval?: ScheduledEventInterval; name?: string; description?: string; channelId?: string; - startTime?: string; - endTime?: string; + startTime?: Date; + endTime?: Date; entityType?: EventType; location?: string; server?: Server; @@ -32,3 +32,10 @@ export interface ScheduledEventFilter { location?: string; server?: ServerFilter; } + +export enum ScheduledEventInterval { + daily = "daily", + weekly = "weekly", + monthly = "monthly", + yearly = "yearly" +} diff --git a/web/src/app/models/graphql/mutations.model.ts b/web/src/app/models/graphql/mutations.model.ts index 27fd48c1..95843b64 100644 --- a/web/src/app/models/graphql/mutations.model.ts +++ b/web/src/app/models/graphql/mutations.model.ts @@ -185,14 +185,16 @@ export class Mutations { endTime: $endTime, entityType: $entityType, location: $location, - serverId: $serverId} - ) { - id + serverId: $serverId + }) { + interval name description - attribute - operator - value + channelId + startTime + endTime + entityType + location server { id } @@ -215,12 +217,17 @@ export class Mutations { location: $location, serverId: $serverId} ) { - id + interval name description - attribute - operator - value + channelId + startTime + endTime + entityType + location + server { + id + } } } } @@ -397,7 +404,6 @@ export class Mutations { `; - static createUserWarning = ` mutation createUserWarning($name: String, $description: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { userWarning { diff --git a/web/src/app/modules/shared/shared.module.ts b/web/src/app/modules/shared/shared.module.ts index 2a7bfc45..af9e8ea8 100644 --- a/web/src/app/modules/shared/shared.module.ts +++ b/web/src/app/modules/shared/shared.module.ts @@ -1,4 +1,4 @@ -import { CommonModule } from "@angular/common"; +import { CommonModule, DatePipe } from "@angular/common"; import { HttpClientModule } from "@angular/common/http"; import { NgModule } from "@angular/core"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; @@ -38,6 +38,8 @@ import { FileUploadModule } from "primeng/fileupload"; import { SelectButtonModule } from "primeng/selectbutton"; import { TabViewModule } from "primeng/tabview"; import { RadioButtonModule } from "primeng/radiobutton"; +import { InputTextareaModule } from "primeng/inputtextarea"; +import { InputMaskModule } from "primeng/inputmask"; const PrimeNGModules = [ @@ -69,7 +71,9 @@ const PrimeNGModules = [ FileUploadModule, SelectButtonModule, TabViewModule, - RadioButtonModule + RadioButtonModule, + InputTextareaModule, + InputMaskModule ]; @NgModule({ @@ -102,6 +106,9 @@ const PrimeNGModules = [ MultiSelectColumnsComponent, FeatureFlagListComponent, DataImportAndExportComponent + ], + providers: [ + DatePipe ] }) export class SharedModule { diff --git a/web/src/app/modules/view/server/scheduled-events/components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component.html b/web/src/app/modules/view/server/scheduled-events/components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component.html index 938281d5..62289884 100644 --- a/web/src/app/modules/view/server/scheduled-events/components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component.html +++ b/web/src/app/modules/view/server/scheduled-events/components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component.html @@ -1,44 +1,92 @@
- + [style]="{ width: '500px', height: '575px' }">
-
- - +
+
+ {{'view.server.scheduled_events.edit_dialog.location.interval' | translate}}: + +
+ +
+
+ + +
+
+ +
+ + + +
-

- Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem - aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. - Nemo - enim - ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos - qui - ratione voluptatem sequi nesciunt. Consectetur, adipisci velit, sed quia non numquam eius modi. -

+
+
+ {{'view.server.scheduled_events.edit_dialog.event_info.event_topic' | translate}}: + +
+ +
+ {{'view.server.scheduled_events.edit_dialog.event_info.start_date_time' | translate}}: + +
+ +
+ {{'view.server.scheduled_events.edit_dialog.event_info.end_date_time' | translate}}: + +
+ +
+ {{'view.server.scheduled_events.edit_dialog.event_info.description' | translate}}: + +
+
- -
-
- -
-
- - - -
-
-
+ +
+
+ +
+
+ + + +
+
+
diff --git a/web/src/app/modules/view/server/scheduled-events/components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component.ts b/web/src/app/modules/view/server/scheduled-events/components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component.ts index ca5ff6d6..f74fb1cd 100644 --- a/web/src/app/modules/view/server/scheduled-events/components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component.ts +++ b/web/src/app/modules/view/server/scheduled-events/components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component.ts @@ -1,14 +1,26 @@ -import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { EventType, ScheduledEvent } from "../../../../../../models/data/scheduled_events.model"; +import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core"; +import { + EventType, + ScheduledEvent, + ScheduledEventInterval +} from "../../../../../../models/data/scheduled_events.model"; import { TranslateService } from "@ngx-translate/core"; -import { FormBuilder, FormControl, Validators } from "@angular/forms"; +import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms"; +import { SingleDiscordQuery } from "../../../../../../models/graphql/query.model"; +import { Queries } from "../../../../../../models/graphql/queries.model"; +import { Channel, ChannelType, Guild } from "../../../../../../models/data/discord.model"; +import { DataService } from "../../../../../../services/data/data.service"; +import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; +import { ActivatedRoute } from "@angular/router"; +import { Server } from "../../../../../../models/data/server.model"; +import { DatePipe } from "@angular/common"; @Component({ selector: "app-edit-scheduled-event-dialog", templateUrl: "./edit-scheduled-event-dialog.component.html", styleUrls: ["./edit-scheduled-event-dialog.component.scss"] }) -export class EditScheduledEventDialogComponent { +export class EditScheduledEventDialogComponent implements OnInit { @Input() event?: ScheduledEvent; @Output() save = new EventEmitter(); @@ -19,8 +31,9 @@ export class EditScheduledEventDialogComponent { set visible(val: boolean) { if (!val) { this.event = undefined; + this.inputForm.reset(); + this.activeIndex = 0; } - this.visible = val; } get header() { @@ -32,26 +45,118 @@ export class EditScheduledEventDialogComponent { } public activeIndex: number = 0; - public inputForm = this.fb.group({ - id: new FormControl(this.event?.id), - interval: new FormControl(this.event?.interval, [Validators.required]), - entityType: new FormControl(this.event?.entityType, [Validators.required]), - channelId: new FormControl(this.event?.channelId, this.event?.entityType == EventType.voice || this.event?.entityType == EventType.stageInstance ? [Validators.required] : []), - location: new FormControl(this.event?.location, this.event?.entityType == EventType.external ? [Validators.required] : []), - name: new FormControl(this.event?.name, [Validators.required]), - startTime: new FormControl(this.event?.startTime, [Validators.required]), - endTime: new FormControl(this.event?.endTime), - description: new FormControl(this.event?.description) - }); + public inputForm!: FormGroup<{ + entityType: FormControl; + name: FormControl; + description: FormControl; + interval: FormControl; + location: FormControl; + startTime: FormControl; + id: FormControl; + endTime: FormControl; + channelId: FormControl + }>; + server: Server = {}; + public voiceChannels: Channel[] = []; + public stageChannels: Channel[] = []; + public guild: Guild = { channels: [], emojis: [], roles: [] }; + public times: string[] = []; + public now = new Date(); + public interval = Object.keys(ScheduledEventInterval).map(k => ( + { + label: this.translate.instant(`view.server.scheduled_events.edit_dialog.location.intervals.${k}`), + value: k + } + )); constructor( private translate: TranslateService, - private fb: FormBuilder + private fb: FormBuilder, + private data: DataService, + private spinner: SpinnerService, + private route: ActivatedRoute, + private datePipe: DatePipe ) { + for (let i = 0; i < 25; i++) { + let time = ""; + if (i < 10) { + time = `0${i}`; + } else { + time = `${i}`; + } + this.times.push(`${time}:00`); + this.times.push(`${time}:15`); + this.times.push(`${time}:30`); + this.times.push(`${time}:45`); + } + this.setInputForm(); + } + + public ngOnInit() { + this.data.getServerFromRoute(this.route).then(server => { + this.server = server; + this.spinner.showSpinner(); + + this.data.query(Queries.guildsQuery, { + id: server?.discordId + } + ).subscribe(data => { + if (data.discord.guilds) { + this.guild = data.discord.guilds[0]; + } + + this.voiceChannels = this.guild.channels.filter(x => x.type === ChannelType.voice); + this.stageChannels = this.guild.channels.filter(x => x.type === ChannelType.stage); + this.setInputForm(); + this.spinner.hideSpinner(); + }); + }); + } + + public setInputForm() { + if (this.now.getMinutes() % 15 != 0) { + if (this.now.getMinutes() < 15) { + this.now.setMinutes(15); + } else if (this.now.getMinutes() < 30) { + this.now.setMinutes(30); + } else if (this.now.getMinutes() < 45) { + this.now.setMinutes(45); + } else if (this.now.getMinutes() > 45) { + this.now.setMinutes(0); + this.now.setHours(this.now.getHours() + 1); + } + } + this.now.setSeconds(0); + + this.inputForm = this.fb.group({ + id: new FormControl(this.event?.id), + interval: new FormControl(this.event?.interval, [Validators.required]), + entityType: new FormControl(this.event?.entityType, [Validators.required]), + channelId: new FormControl(this.event?.channelId, this.event?.entityType == EventType.voice || this.event?.entityType == EventType.stageInstance ? [Validators.required] : []), + location: new FormControl(this.event?.location, this.event?.entityType == EventType.external ? [Validators.required] : []), + name: new FormControl(this.event?.name, [Validators.required]), + startTime: new FormControl(this.event?.startTime ? new Date(this.event.startTime) : this.now, [Validators.required]), + endTime: new FormControl(this.event?.endTime ? new Date(this.event.endTime) : undefined), + description: new FormControl(this.event?.description) + }); } public saveEvent() { + this.event = { + id: this.inputForm.controls.id.value ?? undefined, + interval: this.inputForm.controls.interval.value ?? undefined, + name: this.inputForm.controls.name.value ?? undefined, + description: this.inputForm.controls.description.value ?? undefined, + channelId: this.inputForm.controls.channelId.value ?? undefined, + startTime: this.inputForm.controls.startTime.value ?? undefined, + endTime: this.inputForm.controls.endTime.value ?? undefined, + entityType: this.inputForm.controls.entityType.value ?? undefined, + location: this.inputForm.controls.location.value ?? undefined, + server: this.server + }; + this.save.emit(this.event); + this.event = undefined; } public next() { diff --git a/web/src/app/modules/view/server/scheduled-events/components/scheduled-events/scheduled-events.component.html b/web/src/app/modules/view/server/scheduled-events/components/scheduled-events/scheduled-events.component.html index 1296b1bd..4e2491b4 100644 --- a/web/src/app/modules/view/server/scheduled-events/components/scheduled-events/scheduled-events.component.html +++ b/web/src/app/modules/view/server/scheduled-events/components/scheduled-events/scheduled-events.component.html @@ -1,4 +1,5 @@ - +

{{'view.server.scheduled_events.header' | translate}} @@ -123,7 +124,7 @@ - +
@@ -132,12 +133,24 @@
- - - - - - + +
+ +
+ + + +
+ +
+ + + + + + @@ -148,133 +161,56 @@ {{'common.id' | translate}}: - - - {{scheduledEvent.id}} - - - {{scheduledEvent.id}} - - + {{scheduledEvent.id}} {{'common.interval' | translate}}: - - - - - - {{scheduledEvent.interval}} - - + {{scheduledEvent.interval}} {{'common.name' | translate}}: - - - - - - {{scheduledEvent.name}} - - + {{scheduledEvent.name}} {{'common.description' | translate}}: - - - - - - {{scheduledEvent.description}} - - + {{scheduledEvent.description}} {{'common.channel_id' | translate}}: - - - - - - {{scheduledEvent.channel_id}} - - + {{scheduledEvent.channelId}} {{'common.start_time' | translate}}: - - - - - - {{scheduledEvent.start_time}} - - + {{scheduledEvent.startTime}} {{'common.end_time' | translate}}: - - - - - - {{scheduledEvent.end_time}} - - + {{scheduledEvent.endTime}} {{'common.type' | translate}}: - - - - - - {{scheduledEvent.type}} - - + {{scheduledEvent.entityType}} {{'common.location' | translate}}: - - - - - - {{scheduledEvent.location}} - - + {{scheduledEvent.location}} {{'common.created_at' | translate}}: - - - {{scheduledEvent.createdAt | date:'dd.MM.yy HH:mm'}} - - - {{scheduledEvent.createdAt | date:'dd.MM.yy HH:mm'}} - - + {{scheduledEvent.createdAt | date:'dd.MM.yy HH:mm'}} {{'common.modified_at' | translate}}: - - - {{scheduledEvent.modifiedAt | date:'dd.MM.yy HH:mm'}} - - - {{scheduledEvent.modifiedAt | date:'dd.MM.yy HH:mm'}} - - + {{scheduledEvent.modifiedAt | date:'dd.MM.yy HH:mm'}}
diff --git a/web/src/app/modules/view/server/scheduled-events/components/scheduled-events/scheduled-events.component.ts b/web/src/app/modules/view/server/scheduled-events/components/scheduled-events/scheduled-events.component.ts index da0e8972..a7534dc1 100644 --- a/web/src/app/modules/view/server/scheduled-events/components/scheduled-events/scheduled-events.component.ts +++ b/web/src/app/modules/view/server/scheduled-events/components/scheduled-events/scheduled-events.component.ts @@ -118,7 +118,7 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn startTime: new FormControl(null), endTime: new FormControl(null), entityType: new FormControl(null), - location: new FormControl(null), + location: new FormControl(null) }); this.filterForm.valueChanges.pipe( @@ -221,7 +221,15 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn if (this.isEditingNew) { this.spinner.showSpinner(); this.data.mutation(Mutations.createScheduledEvent, { + id: newScheduledEvent.id, + interval: newScheduledEvent.interval, name: newScheduledEvent.name, + description: newScheduledEvent.description, + channelId: newScheduledEvent.channelId, + startTime: newScheduledEvent.startTime, + endTime: newScheduledEvent.endTime, + entityType: newScheduledEvent.entityType, + location: newScheduledEvent.location, serverId: this.server.id } ).pipe(catchError(err => { @@ -240,7 +248,15 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn this.spinner.showSpinner(); this.data.mutation(Mutations.updateScheduledEvent, { id: newScheduledEvent.id, + interval: newScheduledEvent.interval, name: newScheduledEvent.name, + description: newScheduledEvent.description, + channelId: newScheduledEvent.channelId, + startTime: newScheduledEvent.startTime, + endTime: newScheduledEvent.endTime, + entityType: newScheduledEvent.entityType, + location: newScheduledEvent.location, + serverId: this.server.id } ).pipe(catchError(err => { this.spinner.hideSpinner(); @@ -250,6 +266,7 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn this.toastService.success(this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_update"), this.translate.instant("view.server.ScheduledEvents.message.scheduled_event_update_d", { name: newScheduledEvent.name })); this.loadNextPage(); }); + this.editableScheduledEvent = undefined; } public deleteScheduledEvent(ScheduledEvent: ScheduledEvent): void { @@ -272,6 +289,7 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn } public addScheduledEvent(table: Table): void { + this.isEditingNew = true; this.editableScheduledEvent = JSON.parse(JSON.stringify(this.newScheduledEventTemplate)); // const newScheduledEvent = JSON.parse(JSON.stringify(this.newScheduledEventTemplate)); // diff --git a/web/src/app/modules/view/server/scheduled-events/scheduled-events.module.ts b/web/src/app/modules/view/server/scheduled-events/scheduled-events.module.ts index 752b6ce7..2ba42372 100644 --- a/web/src/app/modules/view/server/scheduled-events/scheduled-events.module.ts +++ b/web/src/app/modules/view/server/scheduled-events/scheduled-events.module.ts @@ -1,10 +1,12 @@ -import { NgModule } from '@angular/core'; -import { CommonModule } from '@angular/common'; +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; -import { ScheduledEventsRoutingModule } from './scheduled-events-routing.module'; +import { ScheduledEventsRoutingModule } from "./scheduled-events-routing.module"; import { ScheduledEventsComponent } from "./components/scheduled-events/scheduled-events.component"; import { SharedModule } from "../../../shared/shared.module"; -import { EditScheduledEventDialogComponent } from './components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component'; +import { + EditScheduledEventDialogComponent +} from "./components/edit-scheduled-event-dialog/edit-scheduled-event-dialog.component"; @NgModule({ @@ -16,6 +18,8 @@ import { EditScheduledEventDialogComponent } from './components/edit-scheduled-e CommonModule, SharedModule, ScheduledEventsRoutingModule - ] + ], + exports: [] }) -export class ScheduledEventsModule { } +export class ScheduledEventsModule { +} diff --git a/web/src/app/services/sidebar/sidebar.service.ts b/web/src/app/services/sidebar/sidebar.service.ts index 285b3a8f..14c55841 100644 --- a/web/src/app/services/sidebar/sidebar.service.ts +++ b/web/src/app/services/sidebar/sidebar.service.ts @@ -4,7 +4,7 @@ import { BehaviorSubject, forkJoin, Observable } from "rxjs"; import { AuthRoles } from "../../models/auth/auth-roles.enum"; import { AuthService } from "../auth/auth.service"; import { TranslateService } from "@ngx-translate/core"; -import { NavigationEnd, Router } from "@angular/router"; +import { Router } from "@angular/router"; import { ThemeService } from "../theme/theme.service"; import { Server } from "../../models/data/server.model"; import { UserDTO } from "../../models/auth/auth-user.dto"; @@ -113,7 +113,7 @@ export class SidebarService { this.serverScheduledEvents = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.scheduled_events") : "", - icon: "pi pi-calender", + icon: "pi pi-calendar", visible: true, routerLink: `server/${this.server?.id}/scheduled-events` }; diff --git a/web/src/assets/i18n/de.json b/web/src/assets/i18n/de.json index 845e8a17..7d70ae2d 100644 --- a/web/src/assets/i18n/de.json +++ b/web/src/assets/i18n/de.json @@ -335,6 +335,7 @@ "config": "Konfiguration", "dashboard": "Dashboard", "members": "Mitglieder", + "scheduled_events": "Geplante Events", "server": { "achievements": "Errungenschaften", "auto_roles": "Auto Rollen", @@ -343,6 +344,7 @@ "levels": "Level", "members": "Mitglieder", "profile": "Dein Profil", + "scheduled_events": "Geplante Events", "short_role_names": "Rollen Kürzel" }, "server_empty": "Kein Server ausgewählt", @@ -551,16 +553,24 @@ "add_header": "Event hinzufügen", "edit_header": "Event bearbeiten", "event_info": { + "description": "Beschreibung", "description_input": "Erzähl den Leuten ein wenig mehr über dein Event. Markdown, neue Zeilen und Links werden unterstützt.", "event_topic": "Thema", "event_topic_input": "Worum geht es bei deinem Event?", "header": "Worum geht es bei deinem Event?", - "start_date": "Startdatum", - "start_time": "Startzeit", + "start_date_time": "Startzeitpunkt", + "end_date_time": "Endzeitpunkt", "tab_name": "Eventinformationen" }, "location": { "header": "Wo ist dein Event?", + "interval": "Interval", + "intervals": { + "daily": "Täglich", + "weekly": "Wöchentlich", + "monthly": "Monatlich", + "yearly": "Jährlich" + }, "somewhere_else": "Irgendwo anders", "somewhere_else_input": "Ort eingeben", "stage": "Stage-Kanal", diff --git a/web/src/assets/i18n/en.json b/web/src/assets/i18n/en.json index 86a3cd2a..ebaa4b27 100644 --- a/web/src/assets/i18n/en.json +++ b/web/src/assets/i18n/en.json @@ -338,6 +338,7 @@ "levels": "Level", "members": "Members", "profile": "Your profile", + "scheduled_events": "Scheduled events", "short_role_names": "Short role names" }, "server_empty": "No server selected", diff --git a/web/src/assets/version.json b/web/src/assets/version.json index 0e2d8ac7..9e53173b 100644 --- a/web/src/assets/version.json +++ b/web/src/assets/version.json @@ -1,7 +1,7 @@ { - "WebVersion": { - "Major": "1", - "Minor": "2", - "Micro": "2" - } -} + "WebVersion": { + "Major": "1", + "Minor": "2", + "Micro": "dev410" + } +} \ No newline at end of file diff --git a/web/src/styles.scss b/web/src/styles.scss index 3878c311..8800861f 100644 --- a/web/src/styles.scss +++ b/web/src/styles.scss @@ -689,8 +689,42 @@ p-inputNumber { } } } + } + .form { + display: flex; + flex-direction: column; + gap: 20px; + textarea { + min-height: 101px !important; + + &:focus { + box-shadow: none !important; + } + } + + .type { + display: flex; + flex-direction: column; + gap: 10px; + + .field-checkbox { + display: flex; + gap: 15px; + } + } + + input, + .p-dropdown { + width: 100%; + } + } +} + +p-calendar { + .p-calendar { + width: 100% !important; } } diff --git a/web/src/styles/primeng-fixes.scss b/web/src/styles/primeng-fixes.scss index cf514b43..cbf7dea3 100644 --- a/web/src/styles/primeng-fixes.scss +++ b/web/src/styles/primeng-fixes.scss @@ -113,3 +113,4 @@ p-table { .pi-sort-amount-down:before { content: "\e913" !important; } + diff --git a/web/src/styles/themes/sh-edraft-dark-theme.scss b/web/src/styles/themes/sh-edraft-dark-theme.scss index f7b2f949..9d9bf6f5 100644 --- a/web/src/styles/themes/sh-edraft-dark-theme.scss +++ b/web/src/styles/themes/sh-edraft-dark-theme.scss @@ -705,6 +705,8 @@ } .p-datepicker { + color: $primaryTextColor !important; + .p-datepicker-header { color: $primaryHeaderColor !important; background-color: $primaryBackgroundColor !important; @@ -764,6 +766,19 @@ } .edit-dialog { + textarea { + background-color: $secondaryBackgroundColor; + color: $primaryTextColor; + + &:hover { + border-color: $primaryHeaderColor; + } + + &:focus { + border-color: $primaryHeaderColor; + } + } + .p-dialog-content { .p-tabview { .p-tabview-nav li .p-tabview-nav-link:not(.p-disabled):focus { @@ -784,4 +799,19 @@ } } } + + .p-radiobutton { + .p-radiobutton-box.p-highlight { + border-color: $primaryHeaderColor !important; + background: $primaryHeaderColor !important; + } + + .p-radiobutton-box:not(.p-disabled):not(.p-highlight):hover { + border-color: $primaryHeaderColor !important; + } + + .p-radiobutton-box:not(.p-disabled).p-focus { + box-shadow: none !important; + } + } }