staging #447
| @@ -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}'"}, | ||||
|   | ||||
							
								
								
									
										8
									
								
								bot/src/bot_data/model/scheduled_event_interval_enum.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								bot/src/bot_data/model/scheduled_event_interval_enum.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| from enum import Enum | ||||
|  | ||||
|  | ||||
| class ScheduledEventIntervalEnum(Enum): | ||||
|     daily = "daily" | ||||
|     weekly = "weekly" | ||||
|     monthly = "monthly" | ||||
|     yearly = "yearly" | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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]), | ||||
|         ) | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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, | ||||
|         ) | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
							
								
								
									
										110
									
								
								web/package.json
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								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" | ||||
|     } | ||||
| } | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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" | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -1,44 +1,92 @@ | ||||
| <div class="edit-dialog"> | ||||
|   <p-dialog [header]="header" [(visible)]="visible" [modal]="true" | ||||
|   <p-dialog [contentStyle]="{'overflow':'visible'}" [header]="header" [(visible)]="visible" [modal]="true" | ||||
|             [draggable]="false" [resizable]="false" | ||||
|             [style]="{ width: '50vw' }"> | ||||
|             [style]="{ width: '500px', height: '575px' }"> | ||||
|     <form [formGroup]="inputForm"> | ||||
|       <p-tabView [(activeIndex)]="activeIndex"> | ||||
|         <p-tabPanel header="{{'view.server.scheduled_events.edit_dialog.location.tab_name' | translate}}"> | ||||
|           <div *ngFor="let enum of EventType | keyvalue" class="field-checkbox"> | ||||
|             <p-radioButton [inputId]="enum.key" [value]="enum.value" formControlName="entityType"></p-radioButton> | ||||
|             <label [for]="enum.key" | ||||
|                    class="ml-2">{{'view.server.scheduled_events.edit_dialog.location.' + enum.key | translate}}</label> | ||||
|           <div class="form"> | ||||
|             <div style="display: flex; flex-direction: column; gap: 5px;"> | ||||
|               {{'view.server.scheduled_events.edit_dialog.location.interval' | translate}}: | ||||
|               <p-dropdown [options]="interval" | ||||
|                           formControlName="interval" | ||||
|                           placeholder="{{'view.server.scheduled_events.edit_dialog.location.interval' | translate}}"></p-dropdown> | ||||
|             </div> | ||||
|  | ||||
|             <div class="type"> | ||||
|               <div *ngFor="let enum of EventType | keyvalue" class="field-checkbox"> | ||||
|                 <p-radioButton [inputId]="enum.key" [value]="enum.value" formControlName="entityType"></p-radioButton> | ||||
|                 <label [for]="enum.key" | ||||
|                        class="ml-2">{{'view.server.scheduled_events.edit_dialog.location.' + enum.key | translate}}</label> | ||||
|               </div> | ||||
|             </div> | ||||
|  | ||||
|             <div class="input"> | ||||
|               <p-dropdown *ngIf="inputForm.controls.entityType.value == 1" | ||||
|                           [options]="stageChannels" | ||||
|                           optionLabel="name" | ||||
|                           optionValue="id" | ||||
|                           formControlName="channelId" | ||||
|                           placeholder="{{'view.server.scheduled_events.edit_dialog.location.stage_input' | translate}}"></p-dropdown> | ||||
|               <p-dropdown *ngIf="inputForm.controls.entityType.value == 2" | ||||
|                           [options]="voiceChannels" | ||||
|                           optionLabel="name" | ||||
|                           optionValue="id" | ||||
|                           formControlName="channelId" | ||||
|                           placeholder="{{'view.server.scheduled_events.edit_dialog.location.voice_input' | translate}}"></p-dropdown> | ||||
|               <input *ngIf="inputForm.controls.entityType.value == 3" pInputText class="table-edit-input" | ||||
|                      formControlName="location" | ||||
|                      placeholder="{{'view.server.scheduled_events.edit_dialog.location.somewhere_else' | translate}}"> | ||||
|             </div> | ||||
|           </div> | ||||
|         </p-tabPanel> | ||||
|         <p-tabPanel header="{{'view.server.scheduled_events.edit_dialog.event_info.tab_name' | translate}}"> | ||||
|           <p> | ||||
|             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. | ||||
|           </p> | ||||
|           <div class="form"> | ||||
|             <div style="display: flex; flex-direction: column; gap: 5px;"> | ||||
|               {{'view.server.scheduled_events.edit_dialog.event_info.event_topic' | translate}}: | ||||
|               <input pInputText class="table-edit-input" | ||||
|                      formControlName="name" | ||||
|                      placeholder="{{'view.server.scheduled_events.edit_dialog.event_info.event_topic_input' | translate}}"> | ||||
|             </div> | ||||
|  | ||||
|             <div style="display: flex; flex-direction: column; gap: 5px;"> | ||||
|               {{'view.server.scheduled_events.edit_dialog.event_info.start_date_time' | translate}}: | ||||
|               <p-calendar formControlName="startTime" dateFormat="dd.mm.yy" [showIcon]="true" | ||||
|                           [showTime]="true" [stepMinute]="15"></p-calendar> | ||||
|             </div> | ||||
|  | ||||
|             <div style="display: flex; flex-direction: column; gap: 5px;"> | ||||
|               {{'view.server.scheduled_events.edit_dialog.event_info.end_date_time' | translate}}: | ||||
|               <p-calendar formControlName="endTime" dateFormat="dd.mm.yy" [showIcon]="true" | ||||
|                           [showTime]="true" [stepMinute]="15"></p-calendar> | ||||
|             </div> | ||||
|  | ||||
|             <div style="display: flex; flex-direction: column; gap: 5px;"> | ||||
|               {{'view.server.scheduled_events.edit_dialog.event_info.description' | translate}}: | ||||
|               <textarea rows="5" cols="30" pInputTextarea [autoResize]="true" | ||||
|                         class="table-edit-input" | ||||
|                         formControlName="description" | ||||
|                         placeholder="{{'view.server.scheduled_events.edit_dialog.event_info.description_input' | translate}}"></textarea> | ||||
|             </div> | ||||
|           </div> | ||||
|         </p-tabPanel> | ||||
|       </p-tabView> | ||||
|       <ng-template pTemplate="footer"> | ||||
|         <div style="display: flex;"> | ||||
|           <div class="btn-wrapper" style="flex: 1;"> | ||||
|             <button pButton label="{{'common.back' | translate}}" class="text-btn" | ||||
|                     (click)="back()" [disabled]="activeIndex == 0"></button> | ||||
|           </div> | ||||
|           <div class="btn-wrapper"> | ||||
|             <button pButton label="{{'common.abort' | translate}}" class="btn danger-btn" | ||||
|                     (click)="visible = false"></button> | ||||
|             <button *ngIf="activeIndex < 1" pButton label="{{'common.continue' | translate}}" class="btn" | ||||
|                     (click)="next()"></button> | ||||
|             <button *ngIf="activeIndex == 1" pButton label="{{'common.save' | translate}}" class="btn" | ||||
|                     (click)="saveEvent()" [disabled]="!inputForm.valid"></button> | ||||
|           </div> | ||||
|         </div> | ||||
|       </ng-template> | ||||
|     </form> | ||||
|     <ng-template pTemplate="footer"> | ||||
|       <div style="display: flex;"> | ||||
|         <div class="btn-wrapper" style="flex: 1;"> | ||||
|           <button pButton label="{{'common.back' | translate}}" class="text-btn" | ||||
|                   (click)="back()" [disabled]="activeIndex == 0"></button> | ||||
|         </div> | ||||
|         <div class="btn-wrapper"> | ||||
|           <button pButton label="{{'common.abort' | translate}}" class="btn danger-btn" | ||||
|                   (click)="visible = false"></button> | ||||
|           <button *ngIf="activeIndex < 1" pButton label="{{'common.continue' | translate}}" class="btn" | ||||
|                   (click)="next()" [disabled]="!inputForm"></button> | ||||
|           <button *ngIf="activeIndex == 1" pButton label="{{'common.save' | translate}}" class="btn" | ||||
|                   (click)="saveEvent()" [disabled]="!inputForm.valid"></button> | ||||
|         </div> | ||||
|       </div> | ||||
|     </ng-template> | ||||
|   </p-dialog> | ||||
| </div> | ||||
|   | ||||
| @@ -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<ScheduledEvent>(); | ||||
|  | ||||
| @@ -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<number | undefined>(this.event?.id), | ||||
|     interval: new FormControl<string | undefined>(this.event?.interval, [Validators.required]), | ||||
|     entityType: new FormControl<number | undefined>(this.event?.entityType, [Validators.required]), | ||||
|     channelId: new FormControl<string | undefined>(this.event?.channelId, this.event?.entityType == EventType.voice || this.event?.entityType == EventType.stageInstance ? [Validators.required] : []), | ||||
|     location: new FormControl<string | undefined>(this.event?.location, this.event?.entityType == EventType.external ? [Validators.required] : []), | ||||
|     name: new FormControl<string | undefined>(this.event?.name, [Validators.required]), | ||||
|     startTime: new FormControl<string | undefined>(this.event?.startTime, [Validators.required]), | ||||
|     endTime: new FormControl<string | undefined>(this.event?.endTime), | ||||
|     description: new FormControl<string | undefined>(this.event?.description) | ||||
|   }); | ||||
|   public inputForm!: FormGroup<{ | ||||
|     entityType: FormControl<number | undefined | null>; | ||||
|     name: FormControl<string | undefined | null>; | ||||
|     description: FormControl<string | undefined | null>; | ||||
|     interval: FormControl<ScheduledEventInterval | undefined | null>; | ||||
|     location: FormControl<string | undefined | null>; | ||||
|     startTime: FormControl<Date | undefined | null>; | ||||
|     id: FormControl<number | undefined | null>; | ||||
|     endTime: FormControl<Date | undefined | null>; | ||||
|     channelId: FormControl<string | undefined | null> | ||||
|   }>; | ||||
|   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<SingleDiscordQuery>(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<number | undefined>(this.event?.id), | ||||
|       interval: new FormControl<ScheduledEventInterval | undefined>(this.event?.interval, [Validators.required]), | ||||
|       entityType: new FormControl<number | undefined>(this.event?.entityType, [Validators.required]), | ||||
|       channelId: new FormControl<string | undefined>(this.event?.channelId, this.event?.entityType == EventType.voice || this.event?.entityType == EventType.stageInstance ? [Validators.required] : []), | ||||
|       location: new FormControl<string | undefined>(this.event?.location, this.event?.entityType == EventType.external ? [Validators.required] : []), | ||||
|       name: new FormControl<string | undefined>(this.event?.name, [Validators.required]), | ||||
|       startTime: new FormControl<Date | undefined>(this.event?.startTime ? new Date(this.event.startTime) : this.now, [Validators.required]), | ||||
|       endTime: new FormControl<Date | undefined>(this.event?.endTime ? new Date(this.event.endTime) : undefined), | ||||
|       description: new FormControl<string | undefined>(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() { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| <app-edit-scheduled-event-dialog [event]="editableScheduledEvent" (save)="onRowEditSave($event)"></app-edit-scheduled-event-dialog> | ||||
| <app-edit-scheduled-event-dialog [event]="editableScheduledEvent" | ||||
|                                  (save)="onRowEditSave($event)"></app-edit-scheduled-event-dialog> | ||||
|  | ||||
| <h1> | ||||
|   {{'view.server.scheduled_events.header' | translate}} | ||||
| @@ -123,7 +124,7 @@ | ||||
|             </form> | ||||
|           </th> | ||||
|  | ||||
|           <th class="table-header-small"></th> | ||||
|           <th hideable-th="interval" [parent]="this"></th> | ||||
|  | ||||
|           <th hideable-th="name" [parent]="this"> | ||||
|             <form [formGroup]="filterForm"> | ||||
| @@ -132,12 +133,24 @@ | ||||
|             </form> | ||||
|           </th> | ||||
|  | ||||
|           <th class="table-header-small"></th> | ||||
|           <th class="table-header-small"></th> | ||||
|           <th class="table-header-small"></th> | ||||
|           <th class="table-header-small"></th> | ||||
|           <th class="table-header-small"></th> | ||||
|           <th class="table-header-small"></th> | ||||
|           <th hideable-th="description" [parent]="this"> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="text" pInputText formControlName="description" | ||||
|                      placeholder="{{'common.description' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|  | ||||
|           <th hideable-th="channel_id" [parent]="this"> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="number" pInputText formControlName="channelId" | ||||
|                      placeholder="{{'common.channel_id' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|  | ||||
|           <th hideable-th="start_time" [parent]="this"></th> | ||||
|           <th hideable-th="end_time" [parent]="this"></th> | ||||
|           <th hideable-th="type" [parent]="this"></th> | ||||
|           <th hideable-th="location" [parent]="this"></th> | ||||
|           <th class="table-header-small-dropdown"></th> | ||||
|           <th class="table-header-small-dropdown"></th> | ||||
|           <th class="table-header-actions"></th> | ||||
| @@ -148,133 +161,56 @@ | ||||
|         <tr [pEditableRow]="scheduledEvent"> | ||||
|           <td hideable-td="id" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.id' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{scheduledEvent.id}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.id}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.id}} | ||||
|           </td> | ||||
|  | ||||
|           <td hideable-td="interval" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.interval' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="scheduledEvent.interval"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.interval}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.interval}} | ||||
|           </td> | ||||
|  | ||||
|           <td hideable-td="name" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.name' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="scheduledEvent.name"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.name}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.name}} | ||||
|           </td> | ||||
|  | ||||
|           <td hideable-td="description" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.description' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="scheduledEvent.description"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.description}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.description}} | ||||
|           </td> | ||||
|  | ||||
|           <td hideable-td="channel_id" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.channel_id' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="scheduledEvent.channel_id"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.channel_id}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.channelId}} | ||||
|           </td> | ||||
|  | ||||
|           <td hideable-td="start_time" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.start_time' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="scheduledEvent.start_time"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.start_time}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.startTime}} | ||||
|           </td> | ||||
|  | ||||
|           <td hideable-td="end_time" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.end_time' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="scheduledEvent.end_time"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.end_time}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.endTime}} | ||||
|           </td> | ||||
|  | ||||
|           <td hideable-td="type" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.type' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="scheduledEvent.type"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.type}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.entityType}} | ||||
|           </td> | ||||
|  | ||||
|           <td hideable-td="location" [parent]="this"> | ||||
|             <span class="p-column-title">{{'common.location' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="scheduledEvent.location"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.location}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.location}} | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <span class="p-column-title">{{'common.created_at' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{scheduledEvent.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|           </td> | ||||
|           <td> | ||||
|             <span class="p-column-title">{{'common.modified_at' | translate}}:</span> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{scheduledEvent.modifiedAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{scheduledEvent.modifiedAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|             {{scheduledEvent.modifiedAt | date:'dd.MM.yy HH:mm'}} | ||||
|           </td> | ||||
|           <td> | ||||
|             <div class="btn-wrapper"> | ||||
|   | ||||
| @@ -118,7 +118,7 @@ export class ScheduledEventsComponent extends ComponentWithTable implements OnIn | ||||
|       startTime: new FormControl<string | null>(null), | ||||
|       endTime: new FormControl<string | null>(null), | ||||
|       entityType: new FormControl<EventType | null>(null), | ||||
|       location: new FormControl<string | null>(null), | ||||
|       location: new FormControl<string | null>(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<ScheduledEventMutationResult>(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<ScheduledEventMutationResult>(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)); | ||||
|     // | ||||
|   | ||||
| @@ -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 { | ||||
| } | ||||
|   | ||||
| @@ -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` | ||||
|     }; | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|   "WebVersion": { | ||||
|     "Major": "1", | ||||
|     "Minor": "2", | ||||
|     "Micro": "2" | ||||
|   } | ||||
| } | ||||
|     "WebVersion": { | ||||
|         "Major": "1", | ||||
|         "Minor": "2", | ||||
|         "Micro": "dev410" | ||||
|     } | ||||
| } | ||||
| @@ -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; | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -113,3 +113,4 @@ p-table { | ||||
| .pi-sort-amount-down:before { | ||||
|   content: "\e913" !important; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user