1.0.0 #253
| @@ -32,7 +32,8 @@ | ||||
|       "cpl-discord==2022.12.2" | ||||
|     ], | ||||
|     "DevDependencies": [ | ||||
|       "cpl-cli==2022.12.1.post3" | ||||
|       "cpl-cli==2022.12.1.post3", | ||||
|       "pygount==1.5.1" | ||||
|     ], | ||||
|     "PythonVersion": ">=3.10.4", | ||||
|     "PythonPath": {}, | ||||
|   | ||||
 Submodule kdb-bot/src/bot/config updated: eff27f4280...7986144705
									
								
							| @@ -89,7 +89,7 @@ class AutoRoleRule(TableABC): | ||||
|             INSERT INTO `AutoRoleRules` ( | ||||
|                 `AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId`, `CreatedAt`, `LastModifiedAt` | ||||
|             ) VALUES ( | ||||
|                 {self._auto_role}, | ||||
|                 {self._auto_role.id}, | ||||
|                 '{self._discord_emoji_name}', | ||||
|                 {self._discord_role_id}, | ||||
|                 '{self._created_at}', | ||||
| @@ -103,8 +103,8 @@ class AutoRoleRule(TableABC): | ||||
|         return str( | ||||
|             f""" | ||||
|             UPDATE `AutoRoleRules` | ||||
|             SET `AutoRoleId` = {self._auto_role}, | ||||
|             `DiscordEmojiName` = {self._discord_emoji_name}, | ||||
|             SET `AutoRoleId` = {self._auto_role.id}, | ||||
|             `DiscordEmojiName` = '{self._discord_emoji_name}', | ||||
|             `DiscordRoleId` = {self._discord_role_id}, | ||||
|             `LastModifiedAt` = '{self._modified_at}' | ||||
|             WHERE `AutoRoleRuleId` = {self._auto_role_rule_id}; | ||||
|   | ||||
| @@ -45,16 +45,19 @@ class AutoRoleFilter(FilterABC): | ||||
|             query = query.where(lambda x: x.id == self._id) | ||||
|  | ||||
|         if self._channel_id is not None: | ||||
|             query = query.where(lambda x: x.discord_channel_id == self._channel_id) | ||||
|  | ||||
|         if self._channel_name is not None and self._channel_id is not None: | ||||
|             query = query.where( | ||||
|                 lambda x: self._bot.get_channel(x.discord_channel_id).name == self._channel_name | ||||
|                 or self._channel_name in self._bot.get_channel(x.discord_channel_id).name | ||||
|                 lambda x: x.discord_channel_id == self._channel_id or str(self._channel_id) in str(x.discord_channel_id) | ||||
|             ) | ||||
|  | ||||
|         if self._channel_name is not None: | ||||
|             query = query.where( | ||||
|                 lambda x: x.discord_channel_name == self._channel_name or self._channel_name in x.discord_channel_name | ||||
|             ) | ||||
|  | ||||
|         if self._message_id is not None: | ||||
|             query = query.where(lambda x: x.discord_message_id == self._message_id) | ||||
|             query = query.where( | ||||
|                 lambda x: x.discord_message_id == self._message_id or str(self._message_id) in str(x.discord_message_id) | ||||
|             ) | ||||
|  | ||||
|         if self._server is not None: | ||||
|             servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) | ||||
|   | ||||
							
								
								
									
										29
									
								
								kdb-bot/src/bot_graphql/model/discord.gql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								kdb-bot/src/bot_graphql/model/discord.gql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| type Guild { | ||||
|     id: ID | ||||
|     name: String | ||||
|  | ||||
|     channels: [Channel] | ||||
|     roles: [Role] | ||||
|     emojis: [Emoji] | ||||
| } | ||||
|  | ||||
| input GuildFilter { | ||||
|     id: ID | ||||
| } | ||||
|  | ||||
| type Channel { | ||||
|     id: String | ||||
|     name: String | ||||
|     type: String | ||||
| } | ||||
|  | ||||
| type Role { | ||||
|     id: String | ||||
|     name: String | ||||
| } | ||||
|  | ||||
| type Emoji { | ||||
|     id: String | ||||
|     name: String | ||||
|     url: String | ||||
| } | ||||
| @@ -28,4 +28,6 @@ type Query { | ||||
|  | ||||
|     userCount: Int | ||||
|     users(filter: UserFilter, page: Page, sort: Sort): [User] | ||||
|  | ||||
|     guilds(filter: GuildFilter): [Guild] | ||||
| } | ||||
| @@ -35,9 +35,9 @@ class AutoRoleRuleMutation(QueryABC): | ||||
|  | ||||
|         def get_new(x: AutoRoleRule): | ||||
|             return ( | ||||
|                 x.auto_role.id == input["autoRoleId"] | ||||
|                 x.auto_role.id == int(input["autoRoleId"]) | ||||
|                 and x.emoji_name == input["emojiName"] | ||||
|                 and x.role_id == input["roleId"] | ||||
|                 and x.role_id == int(input["roleId"]) | ||||
|             ) | ||||
|  | ||||
|         return self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_rule.auto_role.id).where(get_new).last() | ||||
|   | ||||
							
								
								
									
										0
									
								
								kdb-bot/src/bot_graphql/queries/discord/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								kdb-bot/src/bot_graphql/queries/discord/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										10
									
								
								kdb-bot/src/bot_graphql/queries/discord/channel_query.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								kdb-bot/src/bot_graphql/queries/discord/channel_query.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| from bot_graphql.abc.data_query_abc import DataQueryABC | ||||
|  | ||||
|  | ||||
| class ChannelQuery(DataQueryABC): | ||||
|     def __init__(self): | ||||
|         DataQueryABC.__init__(self, "Channel") | ||||
|  | ||||
|         self.set_field("id", lambda c, *_: c.id) | ||||
|         self.set_field("name", lambda c, *_: c.name) | ||||
|         self.set_field("type", lambda c, *_: type(c)) | ||||
							
								
								
									
										10
									
								
								kdb-bot/src/bot_graphql/queries/discord/emoji_query.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								kdb-bot/src/bot_graphql/queries/discord/emoji_query.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| from bot_graphql.abc.data_query_abc import DataQueryABC | ||||
|  | ||||
|  | ||||
| class RoleQuery(DataQueryABC): | ||||
|     def __init__(self): | ||||
|         DataQueryABC.__init__(self, "Emoji") | ||||
|  | ||||
|         self.set_field("id", lambda e, *_: e.id) | ||||
|         self.set_field("name", lambda e, *_: e.name) | ||||
|         self.set_field("url", lambda e, *_: e.url) | ||||
							
								
								
									
										12
									
								
								kdb-bot/src/bot_graphql/queries/discord/guild_query.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								kdb-bot/src/bot_graphql/queries/discord/guild_query.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| from bot_graphql.abc.data_query_abc import DataQueryABC | ||||
|  | ||||
|  | ||||
| class GuildQuery(DataQueryABC): | ||||
|     def __init__(self): | ||||
|         DataQueryABC.__init__(self, "Guild") | ||||
|  | ||||
|         self.set_field("id", lambda g, *_: g.id) | ||||
|         self.set_field("name", lambda g, *_: g.name) | ||||
|         self.set_field("channels", lambda g, *_: g.channels) | ||||
|         self.set_field("roles", lambda g, *_: g.roles) | ||||
|         self.set_field("emojis", lambda g, *_: g.emojis) | ||||
							
								
								
									
										9
									
								
								kdb-bot/src/bot_graphql/queries/discord/role_query.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								kdb-bot/src/bot_graphql/queries/discord/role_query.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| from bot_graphql.abc.data_query_abc import DataQueryABC | ||||
|  | ||||
|  | ||||
| class RoleQuery(DataQueryABC): | ||||
|     def __init__(self): | ||||
|         DataQueryABC.__init__(self, "Role") | ||||
|  | ||||
|         self.set_field("id", lambda r, *_: r.id) | ||||
|         self.set_field("name", lambda r, *_: r.name) | ||||
| @@ -1,3 +1,5 @@ | ||||
| from cpl_discord.service import DiscordBotServiceABC | ||||
|  | ||||
| from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC | ||||
| from bot_data.abc.client_repository_abc import ClientRepositoryABC | ||||
| from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC | ||||
| @@ -22,44 +24,46 @@ from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceC | ||||
| class Query(QueryABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         bot: DiscordBotServiceABC, | ||||
|         auto_roles: AutoRoleRepositoryABC, | ||||
|         clients: ClientRepositoryABC, | ||||
|         known_users: KnownUserRepositoryABC, | ||||
|         levels: LevelRepositoryABC, | ||||
|         servers: ServerRepositoryABC, | ||||
|         user_joined_servers: UserJoinedServerRepositoryABC, | ||||
|         user_joined_voice_channel: UserJoinedVoiceChannelRepositoryABC, | ||||
|         user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC, | ||||
|         user_joined_game_server: UserJoinedGameServerRepositoryABC, | ||||
|         users: UserRepositoryABC, | ||||
|     ): | ||||
|         QueryABC.__init__(self, "Query") | ||||
|         self._auto_roles = auto_roles | ||||
|         self._clients = clients | ||||
|         self._known_users = known_users | ||||
|         self._levels = levels | ||||
|         self._servers = servers | ||||
|         self._user_joined_servers = user_joined_servers | ||||
|         self._user_joined_voice_channels = user_joined_voice_channel | ||||
|         self._user_joined_game_server = user_joined_game_server | ||||
|         self._users = users | ||||
|  | ||||
|         self.add_collection("autoRole", lambda *_: self._auto_roles.get_auto_roles(), AutoRoleFilter) | ||||
|         self.add_collection("autoRoleRule", lambda *_: self._auto_roles.get_auto_role_rules(), AutoRoleRuleFilter) | ||||
|         self.add_collection("client", lambda *_: self._clients.get_clients(), ClientFilter) | ||||
|         self.add_collection("knownUser", lambda *_: self._known_users.get_users()) | ||||
|         self.add_collection("level", lambda *_: self._levels.get_levels(), LevelFilter) | ||||
|         self.add_collection("server", lambda *_: self._servers.get_servers(), ServerFilter) | ||||
|         self._bot = bot | ||||
|  | ||||
|         self.add_collection("autoRole", lambda *_: auto_roles.get_auto_roles(), AutoRoleFilter) | ||||
|         self.add_collection("autoRoleRule", lambda *_: auto_roles.get_auto_role_rules(), AutoRoleRuleFilter) | ||||
|         self.add_collection("client", lambda *_: clients.get_clients(), ClientFilter) | ||||
|         self.add_collection("knownUser", lambda *_: known_users.get_users()) | ||||
|         self.add_collection("level", lambda *_: levels.get_levels(), LevelFilter) | ||||
|         self.add_collection("server", lambda *_: servers.get_servers(), ServerFilter) | ||||
|         self.add_collection( | ||||
|             "userJoinedServer", lambda *_: self._user_joined_servers.get_user_joined_servers(), UserJoinedServerFilter | ||||
|             "userJoinedServer", lambda *_: user_joined_servers.get_user_joined_servers(), UserJoinedServerFilter | ||||
|         ) | ||||
|         self.add_collection( | ||||
|             "userJoinedVoiceChannel", | ||||
|             lambda *_: self._user_joined_voice_channels.get_user_joined_voice_channels(), | ||||
|             lambda *_: user_joined_voice_channels.get_user_joined_voice_channels(), | ||||
|             UserJoinedVoiceChannelFilter, | ||||
|         ) | ||||
|         self.add_collection( | ||||
|             "userJoinedGameServer", | ||||
|             lambda *_: self._user_joined_game_server.get_user_joined_game_servers(), | ||||
|             lambda *_: user_joined_game_server.get_user_joined_game_servers(), | ||||
|             UserJoinedGameServerFilter, | ||||
|         ) | ||||
|         self.add_collection("user", lambda *_: self._users.get_users(), UserFilter) | ||||
|         self.add_collection("user", lambda *_: users.get_users(), UserFilter) | ||||
|  | ||||
|         self.set_field("guilds", self._resolve_guilds) | ||||
|  | ||||
|     def _resolve_guilds(self, *_, filter=None): | ||||
|         if filter is None or "id" not in filter: | ||||
|             return self._bot.guilds | ||||
|  | ||||
|         return self._bot.guilds.where(lambda g: g.id == int(filter["id"])) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "kdb-web", | ||||
|     "version": "1.0.dev130", | ||||
|     "version": "1.0.dev134", | ||||
|     "scripts": { | ||||
|         "ng": "ng", | ||||
|         "update-version": "ts-node-esm update-version.ts", | ||||
|   | ||||
| @@ -13,8 +13,8 @@ import { SpinnerService } from "src/app/services/spinner/spinner.service"; | ||||
| export class FooterComponent implements OnInit { | ||||
|  | ||||
|  | ||||
|   frontendVersion!: SoftwareVersion; | ||||
|   backendVersion!: SoftwareVersion; | ||||
|   frontendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0"); | ||||
|   backendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0"); | ||||
|  | ||||
|   constructor( | ||||
|     private settings: SettingsService, | ||||
|   | ||||
							
								
								
									
										36
									
								
								kdb-web/src/app/models/data/auto_role.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								kdb-web/src/app/models/data/auto_role.model.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| import { Data } from "./data.model"; | ||||
| import { Server, ServerFilter } from "./server.model"; | ||||
|  | ||||
| export interface AutoRole extends Data { | ||||
|   id?: number; | ||||
|   channelId?: string; | ||||
|   channelName?: string; | ||||
|   messageId?: string; | ||||
|   server?: Server; | ||||
|  | ||||
|   autoRoleRuleCount?: number; | ||||
|   autoRoleRules?: AutoRoleRule[]; | ||||
| } | ||||
|  | ||||
| export interface AutoRoleFilter { | ||||
|   id?: number; | ||||
|   channelId?: string; | ||||
|   channelName?: string; | ||||
|   messageId?: string; | ||||
|   server?: ServerFilter; | ||||
| } | ||||
|  | ||||
| export interface AutoRoleRule extends Data { | ||||
|   id?: number; | ||||
|   emojiName?: string; | ||||
|   roleId?: string; | ||||
|   roleName?: string; | ||||
|   autoRole?: AutoRole; | ||||
| } | ||||
|  | ||||
| export interface AutoRoleRuleFilter { | ||||
|   id?: number; | ||||
|   emojiName?: string; | ||||
|   roleId?: string; | ||||
|   autoRole?: AutoRoleFilter; | ||||
| } | ||||
							
								
								
									
										31
									
								
								kdb-web/src/app/models/data/discord.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								kdb-web/src/app/models/data/discord.model.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| export interface Guild { | ||||
|   id?: string; | ||||
|   name?: string; | ||||
|  | ||||
|   channels: [Channel] | ||||
|   roles: [Role] | ||||
|   emojis: [Emoji] | ||||
| } | ||||
|  | ||||
| export interface Channel { | ||||
|   id?: string; | ||||
|   name?: string; | ||||
|   type?: ChannelType; | ||||
| } | ||||
|  | ||||
| export enum ChannelType { | ||||
|   category = "category", | ||||
|   text = "text", | ||||
|   voice = "voice" | ||||
| } | ||||
|  | ||||
| export interface Role { | ||||
|   id?: string; | ||||
|   name?: string; | ||||
| } | ||||
|  | ||||
| export interface Emoji { | ||||
|   id?: string; | ||||
|   name?: string; | ||||
|   url?: string; | ||||
| } | ||||
| @@ -2,6 +2,7 @@ import {Data} from "./data.model"; | ||||
| import {User} from "./user.model"; | ||||
| import {Level} from "./level.model"; | ||||
| import {Client} from "./client.model"; | ||||
| import { AutoRole } from "./auto_role.model"; | ||||
|  | ||||
| export interface Server extends Data { | ||||
|   id?: number; | ||||
| @@ -9,7 +10,7 @@ export interface Server extends Data { | ||||
|   name?: string; | ||||
|   iconURL?: string; | ||||
|   autoRoleCount?: number; | ||||
|   autoRoles?: []; | ||||
|   autoRoles?: AutoRole[]; | ||||
|   clientCount?: number; | ||||
|   clients?: Client[]; | ||||
|   levelCount?: number; | ||||
|   | ||||
| @@ -14,4 +14,69 @@ export class Mutations { | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static createAutoRole = ` | ||||
|     mutation createAutoRole($serverId: ID, $channelId: String, $messageId: String) { | ||||
|       autoRole { | ||||
|         createAutoRole(input: { serverId: $serverId, channelId: $channelId, messageId: $messageId }) { | ||||
|           id | ||||
|           channelId | ||||
|           channelName | ||||
|           messageId | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static deleteAutoRole = ` | ||||
|     mutation deleteAutoRole($id: ID) { | ||||
|       autoRole { | ||||
|         deleteAutoRole(id: $id) { | ||||
|           id | ||||
|           channelId | ||||
|           channelName | ||||
|           messageId | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static createAutoRoleRule = ` | ||||
|     mutation createAutoRoleRule($autoRoleId: ID, $emojiName: String, $roleId: String) { | ||||
|       autoRoleRule { | ||||
|         createAutoRoleRule(input: { autoRoleId: $autoRoleId, emojiName: $emojiName, roleId: $roleId }) { | ||||
|           id | ||||
|           emojiName | ||||
|           roleId | ||||
|           roleName | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static updateAutoRoleRule = ` | ||||
|     mutation updateAutoRoleRule($id: ID, $emojiName: String, $roleId: String) { | ||||
|       autoRoleRule { | ||||
|         updateAutoRoleRule(input: { id: $id, emojiName: $emojiName, roleId: $roleId }) { | ||||
|           id | ||||
|           emojiName | ||||
|           roleId | ||||
|           roleName | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static deleteAutoRoleRule = ` | ||||
|     mutation deleteAutoRoleRule($id: ID) { | ||||
|       autoRoleRule { | ||||
|         deleteAutoRoleRule(id: $id) { | ||||
|           id | ||||
|           emojiName | ||||
|           roleId | ||||
|           roleName | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,29 @@ | ||||
| export class Queries { | ||||
|  | ||||
|   static guildsQuery = ` | ||||
|     query GuildsQuery($id: ID) { | ||||
|       guilds(filter: {id: $id}) { | ||||
|         id | ||||
|         name | ||||
|  | ||||
|         channels { | ||||
|           id | ||||
|           name | ||||
|           type | ||||
|         } | ||||
|         roles { | ||||
|           id | ||||
|           name | ||||
|         } | ||||
|         emojis { | ||||
|           id | ||||
|           name | ||||
|           url | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static serversQuery = ` | ||||
|     query ServerInfo($filter: ServerFilter, $page: Page, $sort: Sort) { | ||||
|       servers(filter: $filter, page: $page, sort: $sort) { | ||||
| @@ -131,4 +155,49 @@ export class Queries { | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static autoRolesQuery = ` | ||||
|     query AutoRoleQuery($serverId: ID, $filter: AutoRoleFilter, $page: Page, $sort: Sort) { | ||||
|       servers(filter: {id: $serverId}) { | ||||
|         autoRoleCount | ||||
|         autoRoles(filter: $filter, page: $page, sort: $sort) { | ||||
|           id | ||||
|           channelId | ||||
|           channelName | ||||
|           messageId | ||||
|           autoRoleRuleCount | ||||
|  | ||||
|           server { | ||||
|             id | ||||
|           } | ||||
|  | ||||
|           createdAt | ||||
|           modifiedAt | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
|  | ||||
|   static autoRoleRulesQuery = ` | ||||
|     query AutoRoleRuleQuery($serverId: ID, $autoRoleId: ID, $filter: AutoRoleRuleFilter, $page: Page, $sort: Sort) { | ||||
|       servers(filter: {id: $serverId}) { | ||||
|         autoRoles(filter: {id: $autoRoleId}) { | ||||
|           autoRoleRuleCount | ||||
|           autoRoleRules(filter: $filter, page: $page, sort: $sort) { | ||||
|             id | ||||
|             emojiName | ||||
|             roleId | ||||
|             roleName | ||||
|  | ||||
|             autoRole { | ||||
|               id | ||||
|             } | ||||
|  | ||||
|             createdAt | ||||
|             modifiedAt | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   `; | ||||
| } | ||||
|   | ||||
| @@ -1,11 +1,18 @@ | ||||
| import { Server } from "../data/server.model"; | ||||
| import { User } from "../data/user.model"; | ||||
| import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; | ||||
| import { Guild } from "../data/discord.model"; | ||||
| import { Level } from "../data/level.model"; | ||||
|  | ||||
| export interface Query { | ||||
|   serverCount: number; | ||||
|   servers: Server[]; | ||||
| } | ||||
|  | ||||
| export interface SingleDiscordQuery { | ||||
|   guilds: Guild[]; | ||||
| } | ||||
|  | ||||
| export interface UserListQuery { | ||||
|   userCount: number; | ||||
|   users: User[]; | ||||
| @@ -13,6 +20,16 @@ export interface UserListQuery { | ||||
|  | ||||
| export interface LevelListQuery { | ||||
|   levelCount: number; | ||||
|   levels: User[]; | ||||
|   levels: Level[]; | ||||
| } | ||||
|  | ||||
| export interface AutoRoleQuery { | ||||
|   autoRoleCount: number; | ||||
|   autoRoles: AutoRole[]; | ||||
| } | ||||
|  | ||||
| export interface AutoRoleRuleQuery { | ||||
|   autoRoleRuleCount: number; | ||||
|   autoRoleRules: AutoRoleRule[]; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,10 @@ | ||||
| import { User } from "../data/user.model"; | ||||
| import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; | ||||
|  | ||||
| export interface GraphQLResult { | ||||
|   data: any; | ||||
|   errors?: []; | ||||
| } | ||||
|  | ||||
| export interface QueryResult { | ||||
|   data: any; | ||||
| @@ -9,3 +15,19 @@ export interface UpdateUserMutationResult { | ||||
|     updateUser: User | ||||
|   }; | ||||
| } | ||||
|  | ||||
| export interface AutoRoleMutationResult { | ||||
|   autoRole: { | ||||
|     createAutoRole?: AutoRole | ||||
|     updateAutoRole?: AutoRole | ||||
|     deleteAutoRole?: AutoRole | ||||
|   }; | ||||
| } | ||||
|  | ||||
| export interface AutoRoleRuleMutationResult { | ||||
|   autoRoleRule: { | ||||
|     createAutoRoleRule?: AutoRoleRule | ||||
|     updateAutoRoleRule?: AutoRoleRule | ||||
|     deleteAutoRoleRule?: AutoRoleRule | ||||
|   }; | ||||
| } | ||||
|   | ||||
| @@ -5,4 +5,5 @@ export interface Variables { | ||||
|   filter?: object; | ||||
|   page?: Page; | ||||
|   sort?: Sort; | ||||
|   [x: string | number | symbol]: unknown; | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
|                     icon="pi pi-user-plus" (click)="addUser(dt)" [disabled]="isEditingNew"> | ||||
|             </button> | ||||
|             <button pButton label="{{'admin.auth_users.reset_filters' | translate}}" icon="pi pi-undo" | ||||
|                     class="icon-btn btn" (click)="resetFilters(dt)"> | ||||
|                     class="icon-btn btn" (click)="resetFilters()"> | ||||
|             </button> | ||||
|           </div> | ||||
|         </div> | ||||
|   | ||||
| @@ -1,20 +1,20 @@ | ||||
| import { Component, OnInit } from '@angular/core'; | ||||
| import { catchError, debounceTime, last } from 'rxjs/operators'; | ||||
| import { AuthRoles } from 'src/app/models/auth/auth-roles.enum'; | ||||
| import { AuthUserDTO } from 'src/app/models/auth/auth-user.dto'; | ||||
| import { AuthService } from 'src/app/services/auth/auth.service'; | ||||
| import { ConfirmationDialogService } from 'src/app/services/confirmation-dialog/confirmation-dialog.service'; | ||||
| import { SpinnerService } from 'src/app/services/spinner/spinner.service'; | ||||
| import { ToastService } from 'src/app/services/toast/toast.service'; | ||||
| import { Table } from 'primeng/table'; | ||||
| import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum'; | ||||
| import { RegisterErrorMessages } from 'src/app/models/auth/register-error-messages.enum'; | ||||
| import { ErrorDTO } from 'src/app/models/error/error-dto'; | ||||
| import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; | ||||
| import { AuthUserSelectCriterion } from 'src/app/models/selection/auth-user/auth-user-select-criterion.dto'; | ||||
| import { LazyLoadEvent } from 'primeng/api'; | ||||
| import { throwError } from 'rxjs'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { catchError, debounceTime } from "rxjs/operators"; | ||||
| import { AuthRoles } from "src/app/models/auth/auth-roles.enum"; | ||||
| import { AuthUserDTO } from "src/app/models/auth/auth-user.dto"; | ||||
| import { AuthService } from "src/app/services/auth/auth.service"; | ||||
| import { ConfirmationDialogService } from "src/app/services/confirmation-dialog/confirmation-dialog.service"; | ||||
| import { SpinnerService } from "src/app/services/spinner/spinner.service"; | ||||
| import { ToastService } from "src/app/services/toast/toast.service"; | ||||
| import { Table } from "primeng/table"; | ||||
| import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum"; | ||||
| import { RegisterErrorMessages } from "src/app/models/auth/register-error-messages.enum"; | ||||
| import { ErrorDTO } from "src/app/models/error/error-dto"; | ||||
| import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; | ||||
| import { AuthUserSelectCriterion } from "src/app/models/selection/auth-user/auth-user-select-criterion.dto"; | ||||
| import { LazyLoadEvent } from "primeng/api"; | ||||
| import { throwError } from "rxjs"; | ||||
| import { TranslateService } from "@ngx-translate/core"; | ||||
|  | ||||
|  | ||||
| @Component({ | ||||
| @@ -162,7 +162,7 @@ export class AuthUserComponent implements OnInit { | ||||
|     this.loadNextPage(); | ||||
|   } | ||||
|  | ||||
|   resetFilters(table: Table) { | ||||
|   resetFilters() { | ||||
|     this.filterForm.reset(); | ||||
|   } | ||||
|  | ||||
| @@ -309,7 +309,6 @@ export class AuthUserComponent implements OnInit { | ||||
|   addUser(table: Table) { | ||||
|     const newUser = JSON.parse(JSON.stringify(this.newUserTemplate)); | ||||
|     newUser.id = Math.max.apply(Math, this.users.map(u => { return u.id ?? 0; })) + 1; | ||||
|     console.log(newUser); | ||||
|  | ||||
|     this.users.push(newUser); | ||||
|     this.triggerUserChangeDetection(); | ||||
|   | ||||
| @@ -20,6 +20,8 @@ import { IpAddressPipe } from './pipes/ip-address.pipe'; | ||||
| import { BoolPipe } from './pipes/bool.pipe'; | ||||
| import { PanelMenuModule } from 'primeng/panelmenu'; | ||||
| import { PanelModule } from "primeng/panel"; | ||||
| import { InputNumberModule } from 'primeng/inputnumber'; | ||||
| import { ImageModule } from "primeng/image"; | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -49,6 +51,8 @@ import { PanelModule } from "primeng/panel"; | ||||
|     DynamicDialogModule, | ||||
|     PanelMenuModule, | ||||
|     PanelModule, | ||||
|     InputNumberModule, | ||||
|     ImageModule | ||||
|   ], | ||||
|   exports: [ | ||||
|     ButtonModule, | ||||
| @@ -72,6 +76,8 @@ import { PanelModule } from "primeng/panel"; | ||||
|     AuthRolePipe, | ||||
|     IpAddressPipe, | ||||
|     BoolPipe, | ||||
|     InputNumberModule, | ||||
|     ImageModule | ||||
|   ] | ||||
| }) | ||||
| export class SharedModule { } | ||||
|   | ||||
| @@ -0,0 +1,18 @@ | ||||
| import { NgModule } from "@angular/core"; | ||||
| import { RouterModule, Routes } from "@angular/router"; | ||||
| import { AutoRolesComponent } from "./components/auto-roles/auto-roles.component"; | ||||
| import { AutoRolesRulesComponent } from "./components/auto-roles-rules/auto-roles-rules.component"; | ||||
|  | ||||
| const routes: Routes = [ | ||||
|  | ||||
|   { path: "", component: AutoRolesComponent }, | ||||
|   { path: ":autoRoleId/rules", component: AutoRolesRulesComponent } | ||||
| ]; | ||||
|  | ||||
| @NgModule({ | ||||
|   imports: [RouterModule.forChild(routes)], | ||||
|   exports: [RouterModule] | ||||
| }) | ||||
| export class AutoRoleRoutingModule { | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,21 @@ | ||||
| import { NgModule } from "@angular/core"; | ||||
| import { CommonModule } from "@angular/common"; | ||||
|  | ||||
| import { AutoRoleRoutingModule } from "./auto-role-routing.module"; | ||||
| import { AutoRolesComponent } from "./components/auto-roles/auto-roles.component"; | ||||
| import { AutoRolesRulesComponent } from "./components/auto-roles-rules/auto-roles-rules.component"; | ||||
| import { SharedModule } from "../../../shared/shared.module"; | ||||
|  | ||||
|  | ||||
| @NgModule({ | ||||
|   declarations: [ | ||||
|     AutoRolesComponent, | ||||
|     AutoRolesRulesComponent | ||||
|   ], | ||||
|   imports: [ | ||||
|     CommonModule, | ||||
|     AutoRoleRoutingModule, | ||||
|     SharedModule, | ||||
|   ] | ||||
| }) | ||||
| export class AutoRoleModule { } | ||||
| @@ -0,0 +1,188 @@ | ||||
| <h1> | ||||
|   {{'view.server.auto_roles.rules.header' | translate}} | ||||
| </h1> | ||||
| <div class="content-wrapper"> | ||||
|   <div class="content"> | ||||
|     <p-table #dt [value]="rules" dataKey="id" editMode="row" [rowHover]="true" [rows]="10" | ||||
|              [rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords" | ||||
|              [lazy]="true" (onLazyLoad)="nextPage($event)"> | ||||
|  | ||||
|       <ng-template pTemplate="caption"> | ||||
|         <div class="table-caption"> | ||||
|           <div class="table-caption-text"> | ||||
|             <ng-container *ngIf="!loading">{{rules.length}} {{'view.server.auto_roles.rules.of' | translate}} | ||||
|               {{dt.totalRecords}} | ||||
|             </ng-container> | ||||
|             {{'view.server.auto_roles.rules.auto_roles' | translate}} | ||||
|           </div> | ||||
|  | ||||
|           <div class="table-caption-btn-wrapper btn-wrapper"> | ||||
|             <button pButton label="{{'admin.auth_users.add' | translate}}" class="icon-btn btn" | ||||
|                     icon="pi pi-user-plus" (click)="addAutoRoleRule(dt)" [disabled]="isEditingNew"> | ||||
|             </button> | ||||
|             <button pButton label="{{'view.server.auto_roles.rules.reset_filters' | translate}}" icon="pi pi-undo" | ||||
|                     class="icon-btn btn" (click)="resetFilters()"> | ||||
|             </button> | ||||
|           </div> | ||||
|         </div> | ||||
|       </ng-template> | ||||
|  | ||||
|       <ng-template pTemplate="header"> | ||||
|         <tr> | ||||
|           <th pSortableColumn="id"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.rules.headers.id' | translate}}</div> | ||||
|               <p-sortIcon field="id" class="table-header-icon"></p-sortIcon> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th pSortableColumn="roleName"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.rules.headers.role' | translate}}</div> | ||||
|               <p-sortIcon field="roleName" class="table-header-icon"></p-sortIcon> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.rules.headers.emoji' | translate}}</div> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'common.created_at' | translate}}</div> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'common.modified_at' | translate}}</div> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.rules.headers.actions' | translate}}</div> | ||||
|             </div> | ||||
|           </th> | ||||
|         </tr> | ||||
|  | ||||
|         <tr> | ||||
|           <th class="table-header-small"> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="text" pInputText formControlName="id" placeholder="{{'view.server.auto_roles.rules.headers.id' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|           <th> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="text" pInputText formControlName="roleId" placeholder="{{'view.server.auto_roles.rules.headers.role' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|           <th></th> | ||||
|           <th class="table-header-small-dropdown"></th> | ||||
|           <th class="table-header-small-dropdown"></th> | ||||
|           <th class="table-header-actions"></th> | ||||
|         </tr> | ||||
|       </ng-template> | ||||
|  | ||||
|       <ng-template pTemplate="body" let-autoRoleRule let-editing="editing" let-ri="rowIndex"> | ||||
|         <tr [pEditableRow]="autoRoleRule"> | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{autoRoleRule.id}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRoleRule.id}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <p-dropdown [options]="roles" optionValue="value.id" [(ngModel)]="autoRoleRule.roleId" | ||||
|                             placeholder="{{'view.server.auto_roles.rules.headers.role' | translate}}"></p-dropdown> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRoleRule.roleName}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <p-dropdown [options]="emojis" optionValue="value.name" [(ngModel)]="autoRoleRule.emojiName" | ||||
|                             placeholder="{{'view.server.auto_roles.rules.headers.emoji' | translate}}"> | ||||
|                   <ng-template pTemplate="selectedItem"> | ||||
|                     <div class="dropdown-icon-label-wrapper" *ngIf="autoRoleRule.emojiName"> | ||||
|                       <p-image [src]="getEmojiUrl(autoRoleRule.emojiName)" [alt]="autoRoleRule.emojiName" width="25"></p-image> | ||||
|                       <div>{{autoRoleRule.emojiName}}</div> | ||||
|                     </div> | ||||
|                   </ng-template> | ||||
|                   <ng-template let-emoji pTemplate="item"> | ||||
|                     <div class="dropdown-icon-label-wrapper"> | ||||
|                       <p-image [src]="emoji.value.url" [alt]="emoji.label" width="25"></p-image> | ||||
|                       <div>{{emoji.label}}</div> | ||||
|                     </div> | ||||
|                   </ng-template> | ||||
|                 </p-dropdown> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 <p-image [src]="getEmojiUrl(autoRoleRule.emojiName)" [alt]="autoRoleRule.emojiName" width="50"></p-image> | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{autoRoleRule.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRoleRule.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{autoRoleRule.modifiedAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRoleRule.modifiedAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <div class="btn-wrapper"> | ||||
|               <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil" (click)="onRowEditInit(dt, autoRoleRule, ri)"></button> | ||||
|               <button *ngIf="!editing" pButton class="btn icon-btn danger-icon-btn" icon="pi pi-trash" | ||||
|                       (click)="deleteAutoRoleRule(autoRoleRule)"></button> | ||||
|  | ||||
|               <button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn" | ||||
|                       icon="pi pi-check-circle" (click)="onRowEditSave(dt, autoRoleRule, ri)"></button> | ||||
|               <button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn" | ||||
|                       icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button> | ||||
|             </div> | ||||
|           </td> | ||||
|         </tr> | ||||
|       </ng-template> | ||||
|  | ||||
|       <ng-template pTemplate="emptymessage"> | ||||
|         <tr></tr> | ||||
|         <tr> | ||||
|           <td colspan="10">{{'view.server.auto_roles.rules.no_entries_found' | translate}}</td> | ||||
|         </tr> | ||||
|         <tr></tr> | ||||
|       </ng-template> | ||||
|  | ||||
|       <ng-template pTemplate="paginatorleft"> | ||||
|       </ng-template> | ||||
|     </p-table> | ||||
|   </div> | ||||
| </div> | ||||
| @@ -0,0 +1,23 @@ | ||||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||||
|  | ||||
| import { AutoRolesRulesComponent } from './auto-roles-rules.component'; | ||||
|  | ||||
| describe('AutoRolesRulesComponent', () => { | ||||
|   let component: AutoRolesRulesComponent; | ||||
|   let fixture: ComponentFixture<AutoRolesRulesComponent>; | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     await TestBed.configureTestingModule({ | ||||
|       declarations: [ AutoRolesRulesComponent ] | ||||
|     }) | ||||
|     .compileComponents(); | ||||
|  | ||||
|     fixture = TestBed.createComponent(AutoRolesRulesComponent); | ||||
|     component = fixture.componentInstance; | ||||
|     fixture.detectChanges(); | ||||
|   }); | ||||
|  | ||||
|   it('should create', () => { | ||||
|     expect(component).toBeTruthy(); | ||||
|   }); | ||||
| }); | ||||
| @@ -0,0 +1,290 @@ | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { DataService } from "../../../../../../services/data/data.service"; | ||||
| import { ActivatedRoute, Router } from "@angular/router"; | ||||
| import { AutoRoleRule, AutoRoleRuleFilter } from "../../../../../../models/data/auto_role.model"; | ||||
| import { Guild } from "../../../../../../models/data/discord.model"; | ||||
| import { LazyLoadEvent, MenuItem } from "primeng/api"; | ||||
| import { User } from "../../../../../../models/data/user.model"; | ||||
| import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; | ||||
| import { Page } from "../../../../../../models/graphql/filter/page.model"; | ||||
| import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; | ||||
| import { AuthService } from "../../../../../../services/auth/auth.service"; | ||||
| import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; | ||||
| import { ToastService } from "../../../../../../services/toast/toast.service"; | ||||
| import { ConfirmationDialogService } from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; | ||||
| import { TranslateService } from "@ngx-translate/core"; | ||||
| import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; | ||||
| import { AutoRoleRuleQuery, SingleDiscordQuery } from "../../../../../../models/graphql/query.model"; | ||||
| import { Queries } from "../../../../../../models/graphql/queries.model"; | ||||
| import { Server } from "../../../../../../models/data/server.model"; | ||||
| import { catchError, debounceTime } from "rxjs/operators"; | ||||
| import { Table } from "primeng/table"; | ||||
| import { AutoRoleMutationResult, AutoRoleRuleMutationResult } from "../../../../../../models/graphql/result.model"; | ||||
| import { Mutations } from "../../../../../../models/graphql/mutations.model"; | ||||
| import { throwError } from "rxjs"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: "app-auto-roles-rules", | ||||
|   templateUrl: "./auto-roles-rules.component.html", | ||||
|   styleUrls: ["./auto-roles-rules.component.scss"] | ||||
| }) | ||||
| export class AutoRolesRulesComponent implements OnInit { | ||||
|  | ||||
|   rules!: AutoRoleRule[]; | ||||
|   guild!: Guild; | ||||
|   emojis: MenuItem[] = []; | ||||
|   roles: MenuItem[] = []; | ||||
|   loading = true; | ||||
|  | ||||
|   autoRoleId!: number; | ||||
|  | ||||
|   clonedUsers: { [s: string]: User; } = {}; | ||||
|   isEditingNew: boolean = false; | ||||
|  | ||||
|   newAutoRoleTemplate: AutoRoleRule = { | ||||
|     id: 0, | ||||
|     createdAt: "", | ||||
|     modifiedAt: "" | ||||
|   }; | ||||
|  | ||||
|   filterForm!: FormGroup<{ | ||||
|     id: FormControl<number | null>, | ||||
|     emojiName: FormControl<string | null>, | ||||
|     roleId: FormControl<string | null>, | ||||
|   }>; | ||||
|  | ||||
|   filter: AutoRoleRuleFilter = {}; | ||||
|   page: Page = { | ||||
|     pageSize: undefined, | ||||
|     pageIndex: undefined | ||||
|   }; | ||||
|   sort: Sort = { | ||||
|     sortColumn: undefined, | ||||
|     sortDirection: undefined | ||||
|   }; | ||||
|  | ||||
|   totalRecords!: number; | ||||
|  | ||||
|   constructor( | ||||
|     private authService: AuthService, | ||||
|     private spinner: SpinnerService, | ||||
|     private toastService: ToastService, | ||||
|     private confirmDialog: ConfirmationDialogService, | ||||
|     private fb: FormBuilder, | ||||
|     private translate: TranslateService, | ||||
|     private data: DataService, | ||||
|     private sidebar: SidebarService, | ||||
|     private route: ActivatedRoute, | ||||
|     private router: Router | ||||
|   ) { | ||||
|   } | ||||
|  | ||||
|   public getEmojiUrl(name: string): string { | ||||
|     return this.guild?.emojis.filter(x => x.name == name)[0].url ?? ""; | ||||
|   } | ||||
|  | ||||
|   public ngOnInit(): void { | ||||
|     this.data.getServerFromRoute(this.route); | ||||
|     this.spinner.showSpinner(); | ||||
|     if (!this.route.snapshot.params["autoRoleId"]) { | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.router.navigate(["../"]); | ||||
|       return; | ||||
|     } | ||||
|     this.autoRoleId = +this.route.snapshot.params["autoRoleId"]; | ||||
|  | ||||
|     this.spinner.showSpinner(); | ||||
|     this.data.query<SingleDiscordQuery>(Queries.guildsQuery, { | ||||
|         filter: { | ||||
|           id: this.sidebar.server$.value?.discordId | ||||
|         } | ||||
|       } | ||||
|     ).subscribe(data => { | ||||
|       this.guild = data.guilds[0]; | ||||
|       this.emojis = this.guild.emojis | ||||
|         .map(x => { | ||||
|           return { label: x.name, value: x }; | ||||
|         }); | ||||
|       this.roles = this.guild.roles | ||||
|         .map(x => { | ||||
|           return { label: x.name, value: x }; | ||||
|         }); | ||||
|       this.spinner.hideSpinner(); | ||||
|     }); | ||||
|  | ||||
|     this.setFilterForm(); | ||||
|     this.loadNextPage(); | ||||
|   } | ||||
|  | ||||
|   public loadNextPage(): void { | ||||
|     this.loading = true; | ||||
|     this.data.query<AutoRoleRuleQuery>(Queries.autoRoleRulesQuery, { | ||||
|         id: this.sidebar.server$.value?.id, filter: this.filter, page: this.page, sort: this.sort | ||||
|       }, | ||||
|       (x: { servers: Server[] }) => { | ||||
|         if (!x.servers[0].autoRoles || x.servers[0].autoRoles?.length == 0) { | ||||
|           return undefined; | ||||
|         } | ||||
|         return x.servers[0].autoRoles[0]; | ||||
|       } | ||||
|     ).subscribe(data => { | ||||
|       this.totalRecords = data.autoRoleRuleCount; | ||||
|       this.rules = data.autoRoleRules; | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.loading = false; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public setFilterForm(): void { | ||||
|     this.filterForm = this.fb.group({ | ||||
|       id: new FormControl<number | null>(null), | ||||
|       emojiName: new FormControl<string | null>(null), | ||||
|       roleId: new FormControl<string | null>(null) | ||||
|     }); | ||||
|  | ||||
|     this.filterForm.valueChanges.pipe( | ||||
|       debounceTime(600) | ||||
|     ).subscribe(changes => { | ||||
|       if (changes.id) { | ||||
|         this.filter.id = changes.id; | ||||
|       } else { | ||||
|         this.filter.id = undefined; | ||||
|       } | ||||
|  | ||||
|       if (changes.emojiName) { | ||||
|         this.filter.emojiName = changes.emojiName; | ||||
|       } else { | ||||
|         this.filter.emojiName = undefined; | ||||
|       } | ||||
|  | ||||
|       if (changes.roleId) { | ||||
|         this.filter.roleId = changes.roleId; | ||||
|       } else { | ||||
|         this.filter.roleId = undefined; | ||||
|       } | ||||
|  | ||||
|       if (this.page.pageSize) | ||||
|         this.page.pageSize = 10; | ||||
|  | ||||
|       if (this.page.pageIndex) | ||||
|         this.page.pageIndex = 0; | ||||
|  | ||||
|       this.loadNextPage(); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public nextPage(event: LazyLoadEvent): void { | ||||
|     this.page.pageSize = event.rows ?? 0; | ||||
|     if (event.first != null && event.rows != null) | ||||
|       this.page.pageIndex = event.first / event.rows; | ||||
|     this.sort.sortColumn = event.sortField ?? undefined; | ||||
|     this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; | ||||
|  | ||||
|     this.loadNextPage(); | ||||
|   } | ||||
|  | ||||
|   public resetFilters(): void { | ||||
|     this.filterForm.reset(); | ||||
|   } | ||||
|  | ||||
|   public onRowEditInit(table: Table, autoRoleRule: AutoRoleRule, index: number): void { | ||||
|     this.clonedUsers[index] = { ...autoRoleRule }; | ||||
|   } | ||||
|  | ||||
|   public onRowEditSave(table: Table, newAutoRoleRule: AutoRoleRule, index: number): void { | ||||
|     if (this.isEditingNew && JSON.stringify(newAutoRoleRule) === JSON.stringify(this.newAutoRoleTemplate)) { | ||||
|       this.isEditingNew = false; | ||||
|       this.rules.splice(index, 1); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (!newAutoRoleRule.id && !this.isEditingNew || !newAutoRoleRule.emojiName && !newAutoRoleRule.roleId) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (this.isEditingNew) { | ||||
|       this.spinner.showSpinner(); | ||||
|       this.data.mutation<AutoRoleRuleMutationResult>(Mutations.createAutoRoleRule, { | ||||
|           autoRoleId: this.autoRoleId, | ||||
|           emojiName: newAutoRoleRule.emojiName, | ||||
|           roleId: newAutoRoleRule.roleId | ||||
|         } | ||||
|       ).pipe(catchError(err => { | ||||
|         this.spinner.hideSpinner(); | ||||
|         this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_failed_d")); | ||||
|         return throwError(err); | ||||
|       })).subscribe(result => { | ||||
|         this.spinner.hideSpinner(); | ||||
|         this.toastService.success(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_created"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_d", { id: result.autoRoleRule.createAutoRoleRule?.id })); | ||||
|         this.isEditingNew = false; | ||||
|         this.loadNextPage(); | ||||
|       }); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     this.spinner.showSpinner(); | ||||
|     this.data.mutation<AutoRoleMutationResult>(Mutations.updateAutoRoleRule, { | ||||
|         id: newAutoRoleRule.id, | ||||
|         emojiName: newAutoRoleRule.emojiName, | ||||
|         roleId: newAutoRoleRule.roleId | ||||
|       } | ||||
|     ).pipe(catchError(err => { | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_failed_d")); | ||||
|       return throwError(err); | ||||
|     })).subscribe(result => { | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.toastService.success(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_updated"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_d", { id: result.autoRole.createAutoRole?.id })); | ||||
|       this.loadNextPage(); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public onRowEditCancel(index: number): void { | ||||
|     if (this.isEditingNew) { | ||||
|       this.rules.splice(index, 1); | ||||
|       delete this.clonedUsers[index]; | ||||
|       this.isEditingNew = false; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     this.rules[index] = this.clonedUsers[index]; | ||||
|     delete this.clonedUsers[index]; | ||||
|   } | ||||
|  | ||||
|   public deleteAutoRoleRule(autoRoleRule: AutoRoleRule): void { | ||||
|     this.confirmDialog.confirmDialog( | ||||
|       this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_q", { id: autoRoleRule.id }), | ||||
|       () => { | ||||
|         this.spinner.showSpinner(); | ||||
|         this.data.mutation<AutoRoleMutationResult>(Mutations.deleteAutoRoleRule, { | ||||
|             id: autoRoleRule.id | ||||
|           } | ||||
|         ).pipe(catchError(err => { | ||||
|           this.spinner.hideSpinner(); | ||||
|           this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_failed_d", { id: autoRoleRule.id })); | ||||
|           return throwError(err); | ||||
|         })).subscribe(_ => { | ||||
|           this.spinner.hideSpinner(); | ||||
|           this.toastService.success(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_deleted"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_deleted_d", { id: autoRoleRule.id })); | ||||
|           this.loadNextPage(); | ||||
|         }); | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|   public addAutoRoleRule(table: Table): void { | ||||
|     const newAutoRole = JSON.parse(JSON.stringify(this.newAutoRoleTemplate)); | ||||
|     newAutoRole.id = Math.max.apply(Math, this.rules.map(u => { | ||||
|       return u.id ?? 0; | ||||
|     })) + 1; | ||||
|  | ||||
|     this.rules.push(newAutoRole); | ||||
|  | ||||
|     table.initRowEdit(newAutoRole); | ||||
|  | ||||
|     const index = this.rules.findIndex(u => u.id == newAutoRole.id); | ||||
|     this.onRowEditInit(table, newAutoRole, index); | ||||
|  | ||||
|     this.isEditingNew = true; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,221 @@ | ||||
| <h1> | ||||
|   {{'view.server.auto_roles.header' | translate}} | ||||
| </h1> | ||||
| <div class="content-wrapper"> | ||||
|   <div class="content"> | ||||
|     <p-table #dt [value]="auto_roles" dataKey="id" editMode="row" [rowHover]="true" [rows]="10" | ||||
|              [rowsPerPageOptions]="[10,25,50]" [paginator]="true" [loading]="loading" [totalRecords]="totalRecords" | ||||
|              [lazy]="true" (onLazyLoad)="nextPage($event)"> | ||||
|  | ||||
|       <ng-template pTemplate="caption"> | ||||
|         <div class="table-caption"> | ||||
|           <div class="table-caption-text"> | ||||
|             <ng-container *ngIf="!loading">{{auto_roles.length}} {{'view.server.auto_roles.of' | translate}} | ||||
|               {{dt.totalRecords}} | ||||
|             </ng-container> | ||||
|             {{'view.server.auto_roles.auto_roles' | translate}} | ||||
|           </div> | ||||
|  | ||||
|           <div class="table-caption-btn-wrapper btn-wrapper"> | ||||
|             <button pButton label="{{'admin.auth_users.add' | translate}}" class="icon-btn btn" | ||||
|                     icon="pi pi-user-plus" (click)="addAutoRole(dt)" [disabled]="isEditingNew"> | ||||
|             </button> | ||||
|             <button pButton label="{{'view.server.auto_roles.reset_filters' | translate}}" icon="pi pi-undo" | ||||
|                     class="icon-btn btn" (click)="resetFilters()"> | ||||
|             </button> | ||||
|           </div> | ||||
|         </div> | ||||
|       </ng-template> | ||||
|  | ||||
|       <ng-template pTemplate="header"> | ||||
|         <tr> | ||||
|           <th pSortableColumn="id"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.headers.id' | translate}}</div> | ||||
|               <p-sortIcon field="id" class="table-header-icon"></p-sortIcon> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th pSortableColumn="discordChannelId"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.headers.channel_id' | translate}}</div> | ||||
|               <p-sortIcon field="discordChannelId" class="table-header-icon"></p-sortIcon> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th pSortableColumn="discordChannelName"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.headers.channel_name' | translate}}</div> | ||||
|               <p-sortIcon field="discordChannelName" class="table-header-icon"></p-sortIcon> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th pSortableColumn="discordMessageId"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.headers.message_id' | translate}}</div> | ||||
|               <p-sortIcon field="discordMessageId" class="table-header-icon"></p-sortIcon> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.headers.role_count' | translate}}</div> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'common.created_at' | translate}}</div> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'common.modified_at' | translate}}</div> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.auto_roles.headers.actions' | translate}}</div> | ||||
|             </div> | ||||
|           </th> | ||||
|         </tr> | ||||
|  | ||||
|         <tr> | ||||
|           <th class="table-header-small"> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="text" pInputText formControlName="id" placeholder="{{'view.server.auto_roles.headers.id' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|           <th> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="text" pInputText formControlName="channelId" placeholder="{{'view.server.auto_roles.headers.channel_id' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|           <th> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="text" pInputText formControlName="channelName" placeholder="{{'view.server.auto_roles.headers.channel_name' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|           <th> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="text" pInputText formControlName="messageId" placeholder="{{'view.server.auto_roles.headers.message_id' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|           <th></th> | ||||
|           <th class="table-header-small-dropdown"></th> | ||||
|           <th class="table-header-small-dropdown"></th> | ||||
|           <th class="table-header-actions"></th> | ||||
|         </tr> | ||||
|       </ng-template> | ||||
|  | ||||
|       <ng-template pTemplate="body" let-autoRole let-editing="editing" let-ri="rowIndex"> | ||||
|         <tr [pEditableRow]="autoRole"> | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{autoRole.id}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRole.id}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <p-dropdown [options]="channels" optionValue="value.id" [(ngModel)]="autoRole.channelId" placeholder="{{'view.server.auto_roles.headers.channel_id' | translate}}"></p-dropdown> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRole.channelId}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{autoRole.channelName}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRole.channelName}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input pInputText class="table-edit-input" [(ngModel)]="autoRole.messageId"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRole.messageId}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{autoRole.autoRoleRuleCount}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRole.autoRoleRuleCount}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{autoRole.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRole.createdAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 {{autoRole.modifiedAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{autoRole.modifiedAt | date:'dd.MM.yy HH:mm'}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <div class="btn-wrapper"> | ||||
| <!--              <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-pencil"--> | ||||
| <!--                      (click)="onRowEditInit(dt, autoRole, ri)"></button>--> | ||||
|               <button *ngIf="!editing" pButton pInitEditableRow class="btn icon-btn" icon="pi pi-sliders-h" [routerLink]="[autoRole.id, 'rules']"></button> | ||||
|               <button *ngIf="!editing" pButton class="btn icon-btn danger-icon-btn" icon="pi pi-trash" | ||||
|                       (click)="deleteAutoRole(autoRole)"></button> | ||||
|  | ||||
|               <button *ngIf="editing" pButton pSaveEditableRow class="btn icon-btn" | ||||
|                       icon="pi pi-check-circle" (click)="onRowEditSave(dt, autoRole, ri)"></button> | ||||
|               <button *ngIf="editing" pButton pCancelEditableRow class="btn icon-btn danger-icon-btn" | ||||
|                       icon="pi pi-times-circle" (click)="onRowEditCancel(ri)"></button> | ||||
|             </div> | ||||
|           </td> | ||||
|         </tr> | ||||
|       </ng-template> | ||||
|  | ||||
|       <ng-template pTemplate="emptymessage"> | ||||
|         <tr></tr> | ||||
|         <tr> | ||||
|           <td colspan="10">{{'view.server.auto_roles.no_entries_found' | translate}}</td> | ||||
|         </tr> | ||||
|         <tr></tr> | ||||
|       </ng-template> | ||||
|  | ||||
|       <ng-template pTemplate="paginatorleft"> | ||||
|       </ng-template> | ||||
|     </p-table> | ||||
|   </div> | ||||
| </div> | ||||
| @@ -0,0 +1,23 @@ | ||||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||||
|  | ||||
| import { AutoRolesComponent } from './auto-roles.component'; | ||||
|  | ||||
| describe('AutoRolesComponent', () => { | ||||
|   let component: AutoRolesComponent; | ||||
|   let fixture: ComponentFixture<AutoRolesComponent>; | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     await TestBed.configureTestingModule({ | ||||
|       declarations: [ AutoRolesComponent ] | ||||
|     }) | ||||
|     .compileComponents(); | ||||
|  | ||||
|     fixture = TestBed.createComponent(AutoRolesComponent); | ||||
|     component = fixture.componentInstance; | ||||
|     fixture.detectChanges(); | ||||
|   }); | ||||
|  | ||||
|   it('should create', () => { | ||||
|     expect(component).toBeTruthy(); | ||||
|   }); | ||||
| }); | ||||
| @@ -0,0 +1,257 @@ | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { User } from "../../../../../../models/data/user.model"; | ||||
| import { LazyLoadEvent, MenuItem } from "primeng/api"; | ||||
| import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; | ||||
| import { Page } from "../../../../../../models/graphql/filter/page.model"; | ||||
| import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; | ||||
| import { AuthService } from "../../../../../../services/auth/auth.service"; | ||||
| import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; | ||||
| import { ToastService } from "../../../../../../services/toast/toast.service"; | ||||
| import { ConfirmationDialogService } from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; | ||||
| import { TranslateService } from "@ngx-translate/core"; | ||||
| import { DataService } from "../../../../../../services/data/data.service"; | ||||
| import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; | ||||
| import { ActivatedRoute } from "@angular/router"; | ||||
| import { AutoRoleQuery, SingleDiscordQuery } from "../../../../../../models/graphql/query.model"; | ||||
| import { Queries } from "../../../../../../models/graphql/queries.model"; | ||||
| import { catchError, debounceTime } from "rxjs/operators"; | ||||
| import { Table } from "primeng/table"; | ||||
| import { AutoRoleMutationResult } from "../../../../../../models/graphql/result.model"; | ||||
| import { Mutations } from "../../../../../../models/graphql/mutations.model"; | ||||
| import { throwError } from "rxjs"; | ||||
| import { AutoRole, AutoRoleFilter } from "../../../../../../models/data/auto_role.model"; | ||||
| import { ChannelType, Guild } from "../../../../../../models/data/discord.model"; | ||||
| import { Server } from "../../../../../../models/data/server.model"; | ||||
|  | ||||
| @Component({ | ||||
|   selector: "app-auto-roles", | ||||
|   templateUrl: "./auto-roles.component.html", | ||||
|   styleUrls: ["./auto-roles.component.scss"] | ||||
| }) | ||||
| export class AutoRolesComponent implements OnInit { | ||||
|   auto_roles!: AutoRole[]; | ||||
|   guild!: Guild; | ||||
|   channels!: MenuItem[]; | ||||
|   loading = true; | ||||
|  | ||||
|   clonedUsers: { [s: string]: User; } = {}; | ||||
|   isEditingNew: boolean = false; | ||||
|  | ||||
|   newAutoRoleTemplate: AutoRole = { | ||||
|     id: 0, | ||||
|     createdAt: "", | ||||
|     modifiedAt: "" | ||||
|   }; | ||||
|  | ||||
|   filterForm!: FormGroup<{ | ||||
|     id: FormControl<number | null>, | ||||
|     channelId: FormControl<string | null>, | ||||
|     channelName: FormControl<string | null>, | ||||
|     messageId: FormControl<string | null>, | ||||
|   }>; | ||||
|  | ||||
|   filter: AutoRoleFilter = {}; | ||||
|   page: Page = { | ||||
|     pageSize: undefined, | ||||
|     pageIndex: undefined | ||||
|   }; | ||||
|   sort: Sort = { | ||||
|     sortColumn: undefined, | ||||
|     sortDirection: undefined | ||||
|   }; | ||||
|  | ||||
|   totalRecords!: number; | ||||
|  | ||||
|   constructor( | ||||
|     private authService: AuthService, | ||||
|     private spinner: SpinnerService, | ||||
|     private toastService: ToastService, | ||||
|     private confirmDialog: ConfirmationDialogService, | ||||
|     private fb: FormBuilder, | ||||
|     private translate: TranslateService, | ||||
|     private data: DataService, | ||||
|     private sidebar: SidebarService, | ||||
|     private route: ActivatedRoute | ||||
|   ) { | ||||
|   } | ||||
|  | ||||
|   public ngOnInit(): void { | ||||
|     this.data.getServerFromRoute(this.route); | ||||
|  | ||||
|     this.spinner.showSpinner(); | ||||
|     this.data.query<SingleDiscordQuery>(Queries.guildsQuery, { | ||||
|         filter: { | ||||
|           id: this.sidebar.server$.value?.discordId | ||||
|         } | ||||
|       } | ||||
|     ).subscribe(data => { | ||||
|       this.guild = data.guilds[0]; | ||||
|       this.channels = this.guild.channels | ||||
|         .filter(x => x.type === ChannelType.text) | ||||
|         .map(x => { | ||||
|           return { label: x.name, value: x }; | ||||
|         }); | ||||
|       this.spinner.hideSpinner(); | ||||
|     }); | ||||
|  | ||||
|     this.setFilterForm(); | ||||
|     this.loadNextPage(); | ||||
|   } | ||||
|  | ||||
|   public loadNextPage(): void { | ||||
|     this.loading = true; | ||||
|     this.data.query<AutoRoleQuery>(Queries.autoRolesQuery, { | ||||
|         id: this.sidebar.server$.value?.id, filter: this.filter, page: this.page, sort: this.sort | ||||
|       }, | ||||
|       (x: { servers: Server[] }) => { | ||||
|         return x.servers[0]; | ||||
|       } | ||||
|     ).subscribe(data => { | ||||
|       this.totalRecords = data.autoRoleCount; | ||||
|       this.auto_roles = data.autoRoles; | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.loading = false; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public setFilterForm(): void { | ||||
|     this.filterForm = this.fb.group({ | ||||
|       id: new FormControl<number | null>(null), | ||||
|       channelId: new FormControl<string | null>(null), | ||||
|       channelName: new FormControl<string | null>(null), | ||||
|       messageId: new FormControl<string | null>(null) | ||||
|     }); | ||||
|  | ||||
|     this.filterForm.valueChanges.pipe( | ||||
|       debounceTime(600) | ||||
|     ).subscribe(changes => { | ||||
|       if (changes.id) { | ||||
|         this.filter.id = changes.id; | ||||
|       } else { | ||||
|         this.filter.id = undefined; | ||||
|       } | ||||
|  | ||||
|       if (changes.channelId) { | ||||
|         this.filter.channelId = changes.channelId; | ||||
|       } else { | ||||
|         this.filter.channelId = undefined; | ||||
|       } | ||||
|  | ||||
|       if (changes.channelName) { | ||||
|         this.filter.channelName = changes.channelName; | ||||
|       } else { | ||||
|         this.filter.channelName = undefined; | ||||
|       } | ||||
|  | ||||
|       if (changes.messageId) { | ||||
|         this.filter.messageId = changes.messageId; | ||||
|       } else { | ||||
|         this.filter.messageId = undefined; | ||||
|       } | ||||
|  | ||||
|       if (this.page.pageSize) | ||||
|         this.page.pageSize = 10; | ||||
|  | ||||
|       if (this.page.pageIndex) | ||||
|         this.page.pageIndex = 0; | ||||
|  | ||||
|       this.loadNextPage(); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public nextPage(event: LazyLoadEvent): void { | ||||
|     this.page.pageSize = event.rows ?? 0; | ||||
|     if (event.first != null && event.rows != null) | ||||
|       this.page.pageIndex = event.first / event.rows; | ||||
|     this.sort.sortColumn = event.sortField ?? undefined; | ||||
|     this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; | ||||
|  | ||||
|     this.loadNextPage(); | ||||
|   } | ||||
|  | ||||
|   public resetFilters(): void { | ||||
|     this.filterForm.reset(); | ||||
|   } | ||||
|  | ||||
|   public onRowEditInit(table: Table, autoRole: AutoRole, index: number): void { | ||||
|     this.clonedUsers[index] = { ...autoRole }; | ||||
|   } | ||||
|  | ||||
|   public onRowEditSave(table: Table, newAutoRole: AutoRole, index: number): void { | ||||
|     if (this.isEditingNew && JSON.stringify(newAutoRole) === JSON.stringify(this.newAutoRoleTemplate)) { | ||||
|       this.isEditingNew = false; | ||||
|       this.auto_roles.splice(index, 1); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (!newAutoRole.id || !newAutoRole.channelId && !newAutoRole.messageId) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     this.spinner.showSpinner(); | ||||
|     this.data.mutation<AutoRoleMutationResult>(Mutations.createAutoRole, { | ||||
|         serverId: this.sidebar.server$.value?.id, | ||||
|         channelId: newAutoRole.channelId, | ||||
|         messageId: newAutoRole.messageId | ||||
|       } | ||||
|     ).pipe(catchError(err => { | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.toastService.error(this.translate.instant("view.server.auto_roles.message.auto_role_create_failed"), this.translate.instant("view.server.auto_roles.message.auto_role_create_failed_d")); | ||||
|       return throwError(err); | ||||
|     })).subscribe(result => { | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.toastService.success(this.translate.instant("view.server.auto_roles.message.auto_role_created"), this.translate.instant("view.server.auto_roles.message.auto_role_create_d", { id: result.autoRole.createAutoRole?.id })); | ||||
|       this.loadNextPage(); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   public onRowEditCancel(index: number): void { | ||||
|     if (this.isEditingNew) { | ||||
|       this.auto_roles.splice(index, 1); | ||||
|       delete this.clonedUsers[index]; | ||||
|       this.isEditingNew = false; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     this.auto_roles[index] = this.clonedUsers[index]; | ||||
|     delete this.clonedUsers[index]; | ||||
|   } | ||||
|  | ||||
|   public deleteAutoRole(autoRole: AutoRole): void { | ||||
|     this.confirmDialog.confirmDialog( | ||||
|       this.translate.instant("view.server.auto_roles.message.auto_role_delete"), this.translate.instant("view.server.auto_roles.message.auto_role_delete_q", { id: autoRole.id }), | ||||
|       () => { | ||||
|         this.spinner.showSpinner(); | ||||
|         this.data.mutation<AutoRoleMutationResult>(Mutations.deleteAutoRole, { | ||||
|             id: autoRole.id | ||||
|           } | ||||
|         ).pipe(catchError(err => { | ||||
|           this.spinner.hideSpinner(); | ||||
|           this.toastService.error(this.translate.instant("view.server.auto_roles.message.auto_role_delete_failed"), this.translate.instant("view.server.auto_roles.message.auto_role_delete_failed_d", { id: autoRole.id })); | ||||
|           return throwError(err); | ||||
|         })).subscribe(_ => { | ||||
|           this.spinner.hideSpinner(); | ||||
|           this.toastService.success(this.translate.instant("view.server.auto_roles.message.auto_role_deleted"), this.translate.instant("view.server.auto_roles.message.auto_role_deleted_d", { id: autoRole.id })); | ||||
|           this.loadNextPage(); | ||||
|         }); | ||||
|       }); | ||||
|  | ||||
|  | ||||
|   } | ||||
|  | ||||
|   public addAutoRole(table: Table): void { | ||||
|     const newAutoRole = JSON.parse(JSON.stringify(this.newAutoRoleTemplate)); | ||||
|     newAutoRole.id = Math.max.apply(Math, this.auto_roles.map(u => { | ||||
|       return u.id ?? 0; | ||||
|     })) + 1; | ||||
|  | ||||
|     this.auto_roles.push(newAutoRole); | ||||
|  | ||||
|     table.initRowEdit(newAutoRole); | ||||
|  | ||||
|     const index = this.auto_roles.findIndex(u => u.id == newAutoRole.id); | ||||
|     this.onRowEditInit(table, newAutoRole, index); | ||||
|  | ||||
|     this.isEditingNew = true; | ||||
|   } | ||||
| } | ||||
| @@ -163,7 +163,8 @@ | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="number" min="0" [(ngModel)]="member.xp"> | ||||
|                 <p-inputNumber class="table-edit-input" styleClass="input-number" [(ngModel)]="member.xp" mode="decimal" [min]="0" [useGrouping]="false" [showButtons]="true" | ||||
|                                inputId="minmax-buttons"></p-inputNumber> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{member.xp}} | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { Component } from "@angular/core"; | ||||
| import { Component, OnInit } from "@angular/core"; | ||||
| import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; | ||||
| import { AuthService } from "../../../../services/auth/auth.service"; | ||||
| import { SpinnerService } from "../../../../services/spinner/spinner.service"; | ||||
| @@ -25,13 +25,13 @@ import { ActivatedRoute } from "@angular/router"; | ||||
|   templateUrl: "./members.component.html", | ||||
|   styleUrls: ["./members.component.scss"] | ||||
| }) | ||||
| export class MembersComponent { | ||||
| export class MembersComponent implements OnInit { | ||||
|   members!: User[]; | ||||
|   // levelsFilter!: MenuItem[]; | ||||
|   levels!: MenuItem[]; | ||||
|   leftServerOptions = [ | ||||
|     {label: this.translate.instant('common.bool_as_string.true'), value: false}, | ||||
|     {label: this.translate.instant('common.bool_as_string.false'), value: true}, | ||||
|     { label: this.translate.instant("common.bool_as_string.true"), value: false }, | ||||
|     { label: this.translate.instant("common.bool_as_string.false"), value: true } | ||||
|   ]; | ||||
|   loading = true; | ||||
|  | ||||
| @@ -132,7 +132,7 @@ export class MembersComponent { | ||||
|       discordId: new FormControl<number | null>(null), | ||||
|       name: [""], | ||||
|       leftServer: new FormControl<boolean | null>(null), | ||||
|       level: new FormControl<number | null>(null), | ||||
|       level: new FormControl<number | null>(null) | ||||
|     }); | ||||
|  | ||||
|     this.filterForm.valueChanges.pipe( | ||||
|   | ||||
| @@ -8,6 +8,7 @@ const routes: Routes = [ | ||||
|   { path: '', component: ServerDashboardComponent }, | ||||
|   { path: 'members', component: MembersComponent }, | ||||
|   { path: 'members/:memberId', component: ProfileComponent }, | ||||
|   { path: 'auto-roles', loadChildren: () => import('./auto-role/auto-role.module').then(m => m.AutoRoleModule)}, | ||||
| ]; | ||||
|  | ||||
| @NgModule({ | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import { Queries } from "../../models/graphql/queries.model"; | ||||
| import { Query } from "../../models/graphql/query.model"; | ||||
| import { SidebarService } from "../sidebar/sidebar.service"; | ||||
| import { SpinnerService } from "../spinner/spinner.service"; | ||||
| import { GraphQLResult } from "../../models/graphql/result.model"; | ||||
|  | ||||
| @Injectable({ | ||||
|   providedIn: "root" | ||||
| @@ -20,7 +21,7 @@ export class DataService { | ||||
|     private http: HttpClient, | ||||
|     private sidebar: SidebarService, | ||||
|     private spinner: SpinnerService, | ||||
|     private router: Router, | ||||
|     private router: Router | ||||
|   ) { | ||||
|   } | ||||
|  | ||||
| @@ -28,7 +29,7 @@ export class DataService { | ||||
|     this.spinner.showSpinner(); | ||||
|     if (!route.snapshot.params["serverId"]) { | ||||
|       this.spinner.hideSpinner(); | ||||
|       this.router.navigate(['/dashboard']); | ||||
|       this.router.navigate(["/dashboard"]); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
| @@ -46,21 +47,31 @@ export class DataService { | ||||
|  | ||||
|   public query<T>(query: string, variables?: Variables, f?: Function): Observable<T> { | ||||
|     return this.http | ||||
|       .post<{ data: T }>(`${this.appsettings.getApiURL()}/api/graphql`, { | ||||
|       .post<GraphQLResult>(`${this.appsettings.getApiURL()}/api/graphql`, { | ||||
|         query: query, | ||||
|         variables: variables | ||||
|       }) | ||||
|       .pipe(map((d) => d.data)) | ||||
|       .pipe(map(d => { | ||||
|         if (d.errors && d.errors.length > 0) { | ||||
|           throw new Error(d.errors.map((x: {message: String}) => x.message).toString()); | ||||
|         } | ||||
|         return d.data; | ||||
|       })) | ||||
|       .pipe(map((d) => f ? f(d) : d)); | ||||
|   } | ||||
|  | ||||
|   public mutation<T>(query: string, variables?: object, f?: Function): Observable<T> { | ||||
|     return this.http | ||||
|       .post<{ data: T }>(`${this.appsettings.getApiURL()}/api/graphql`, { | ||||
|       .post<GraphQLResult>(`${this.appsettings.getApiURL()}/api/graphql`, { | ||||
|         query: query, | ||||
|         variables: variables | ||||
|       }) | ||||
|       .pipe(map((d) => d.data)) | ||||
|       .pipe(map(d => { | ||||
|         if (d.errors && d.errors.length > 0) { | ||||
|           throw new Error(d.errors.toString()); | ||||
|         } | ||||
|         return d.data; | ||||
|       })) | ||||
|       .pipe(map((d) => f ? f(d) : d)); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -1,16 +1,17 @@ | ||||
| import { HttpErrorResponse } from '@angular/common/http'; | ||||
| import { ErrorHandler, Injectable, Injector } from '@angular/core'; | ||||
| import { Observable, throwError } from 'rxjs'; | ||||
| import { ErrorDTO } from 'src/app/models/error/error-dto'; | ||||
| import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum'; | ||||
| import { AuthService } from '../auth/auth.service'; | ||||
| import { ToastService } from '../toast/toast.service'; | ||||
| import { HttpErrorResponse } from "@angular/common/http"; | ||||
| import { ErrorHandler, Injectable } from "@angular/core"; | ||||
| import { Observable, throwError } from "rxjs"; | ||||
| import { ErrorDTO } from "src/app/models/error/error-dto"; | ||||
| import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum"; | ||||
| import { AuthService } from "../auth/auth.service"; | ||||
| import { ToastService } from "../toast/toast.service"; | ||||
|  | ||||
| @Injectable() | ||||
| export class ErrorHandlerService implements ErrorHandler { | ||||
|  | ||||
|   constructor( | ||||
|     private injector: Injector | ||||
|     private auth: AuthService, | ||||
|     private toast: ToastService, | ||||
|   ) { } | ||||
|  | ||||
|   handleError(error: HttpErrorResponse): Observable<never> { | ||||
| @@ -20,7 +21,7 @@ export class ErrorHandlerService implements ErrorHandler { | ||||
|       const errorDto: ErrorDTO = error.error; | ||||
|  | ||||
|       if (errorDto.errorCode === ServiceErrorCode.Unauthorized) { | ||||
|         this.injector.get(AuthService).logout(); | ||||
|         this.auth.logout(); | ||||
|         return throwError(() => error); | ||||
|       } | ||||
|  | ||||
| @@ -34,11 +35,13 @@ export class ErrorHandlerService implements ErrorHandler { | ||||
|         message = error.message; | ||||
|       } | ||||
|  | ||||
|       this.injector.get(ToastService).error(header, message); | ||||
|       this.toast.error(header, message); | ||||
|     } else { | ||||
|       console.error(error.message); | ||||
|     } | ||||
|  | ||||
|     if (error.status === 401) { | ||||
|       this.injector.get(AuthService).logout(); | ||||
|       this.auth.logout(); | ||||
|     } | ||||
|     return throwError(() => error); | ||||
|   } | ||||
|   | ||||
| @@ -22,6 +22,8 @@ export class SidebarService { | ||||
|   serverDashboard!: MenuItem; | ||||
|   serverProfile!: MenuItem; | ||||
|   serverMembers!: MenuItem; | ||||
|   serverAutoRoles!: MenuItem; | ||||
|   serverAutoRoleRules!: MenuItem; | ||||
|   serverMenu!: MenuItem; | ||||
|   adminConfig!: MenuItem; | ||||
|   adminUsers!: MenuItem; | ||||
| @@ -81,12 +83,20 @@ export class SidebarService { | ||||
|       visible: true, | ||||
|       routerLink: `server/${this.server$.value?.id}/members` | ||||
|     }; | ||||
|  | ||||
|     this.serverAutoRoles = { | ||||
|       label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.auto_roles") : "", | ||||
|       icon: "pi pi-sitemap", | ||||
|       visible: true, | ||||
|       routerLink: `server/${this.server$.value?.id}/auto-roles` | ||||
|     }; | ||||
|  | ||||
|     this.serverMenu = { | ||||
|       label: this.isSidebarOpen ? this.server$.value?.name : "", | ||||
|       icon: "pi pi-server", | ||||
|       visible: false, | ||||
|       expanded: true, | ||||
|       items: [this.serverDashboard, this.serverProfile, this.serverMembers] | ||||
|       items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles] | ||||
|     }; | ||||
|     this.adminConfig = { label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", icon: "pi pi-cog", routerLink: "/admin/settings" }; | ||||
|     this.adminUsers = { | ||||
| @@ -115,6 +125,7 @@ export class SidebarService { | ||||
|       if (this.server$.value) { | ||||
|         this.serverMenu.visible = true; | ||||
|         this.serverMembers.visible = !!user?.isModerator; | ||||
|         this.serverAutoRoles.visible = !!user?.isAdmin; | ||||
|       } else { | ||||
|         this.serverMenu.visible = false; | ||||
|       } | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; | ||||
| import { Subject } from 'rxjs'; | ||||
| import { Themes } from 'src/app/models/view/themes.enum'; | ||||
| import { AuthService } from '../auth/auth.service'; | ||||
| import { Injectable } from "@angular/core"; | ||||
| import { BehaviorSubject } from "rxjs"; | ||||
| import { Themes } from "src/app/models/view/themes.enum"; | ||||
| import { AuthService } from "../auth/auth.service"; | ||||
|  | ||||
| @Injectable({ | ||||
|   providedIn: 'root' | ||||
| @@ -15,9 +14,9 @@ export class ThemeService { | ||||
|   isSidebarOpen = false; | ||||
|   hasLangChanged = false; | ||||
|  | ||||
|   themeName$ = new Subject<string>(); | ||||
|   isSidebarOpen$ = new Subject<boolean>(); | ||||
|   sidebarWidth$ = new Subject<string>(); | ||||
|   themeName$ = new BehaviorSubject<string>(Themes.Default); | ||||
|   isSidebarOpen$ = new BehaviorSubject<boolean>(true); | ||||
|   sidebarWidth$ = new BehaviorSubject<string>('175px'); | ||||
|  | ||||
|   constructor( | ||||
|     private authService: AuthService | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|     "WebVersion": { | ||||
|         "Major": "1", | ||||
|         "Minor": "0", | ||||
|         "Micro": "dev130" | ||||
|         "Micro": "dev134" | ||||
|     }, | ||||
|     "Themes": [ | ||||
|         { | ||||
|   | ||||
| @@ -10,7 +10,8 @@ | ||||
|     "server": { | ||||
|       "dashboard": "Dashboard", | ||||
|       "profile": "Dein Profil", | ||||
|       "members": "Mitglieder" | ||||
|       "members": "Mitglieder", | ||||
|       "auto_roles": "Auto Rollen" | ||||
|     }, | ||||
|     "server_empty": "Kein Server ausgewählt", | ||||
|     "members": "Mitglieder", | ||||
| @@ -202,8 +203,8 @@ | ||||
|         "reset_filters": "Filter zurücksetzen", | ||||
|         "members": "Mitgliedern", | ||||
|         "headers": { | ||||
|           "id": "ID", | ||||
|           "discord_id": "Discord ID", | ||||
|           "id": "Id", | ||||
|           "discord_id": "Discord Id", | ||||
|           "name": "Name", | ||||
|           "xp": "XP", | ||||
|           "ontime": "Ontime", | ||||
| @@ -218,6 +219,64 @@ | ||||
|           "user_change_failed": "Benutzer änderung fehlgeschlagen", | ||||
|           "user_change_failed_d": "Benutzer {{name}} konnte nicht geändert werden!" | ||||
|         } | ||||
|       }, | ||||
|       "auto_roles": { | ||||
|         "header": "Auto Rollen", | ||||
|         "of": "von", | ||||
|         "add": "Hinzufügen", | ||||
|         "reset_filters": "Filter zurücksetzen", | ||||
|         "auto_roles": "Auto Rollen", | ||||
|         "headers": { | ||||
|           "id": "Id", | ||||
|           "channel_id": "Kanal Id", | ||||
|           "channel_name": "Kanal", | ||||
|           "message_id": "Nachricht Id", | ||||
|           "role_count": "Regeln", | ||||
|           "actions": "Aktionen" | ||||
|         }, | ||||
|         "no_entries_found": "Keine Einträge gefunden", | ||||
|         "message": { | ||||
|           "auto_role_create": "Auto Rolle erstellt", | ||||
|           "auto_role_create_d": "Auto Rolle {{id}} erfolgreich erstellt", | ||||
|           "auto_role_create_failed": "Auto Rolle Erstellung fehlgeschlagen", | ||||
|           "auto_role_create_failed_d": "Die Erstellung der Auto Rolle ist fehlgeschlagen!", | ||||
|           "auto_role_delete": "Auto Rolle löschen", | ||||
|           "auto_role_delete_q": "Sind Sie sich sicher, dass Sie die Auto Rolle {{id}} löschen möchten?", | ||||
|           "auto_role_deleted": "Auto Rolle gelöscht", | ||||
|           "auto_role_deleted_d": "Auto Rolle {{id}} erfolgreich gelöscht", | ||||
|           "auto_role_delete_failed": "Auto Rolle Löschung fehlgeschlagen", | ||||
|           "auto_role_delete_failed_d": "Die Löschung der Auto Rolle {{id}} ist fehlgeschlagen!" | ||||
|         }, | ||||
|         "rules": { | ||||
|           "header": "Auto Rollen Regeln", | ||||
|           "of": "von", | ||||
|           "add": "Hinzufügen", | ||||
|           "reset_filters": "Filter zurücksetzen", | ||||
|           "auto_roles": "Auto Rollen Regeln", | ||||
|           "headers": { | ||||
|             "id": "Id", | ||||
|             "emoji": "Emoji", | ||||
|             "role": "Rolle", | ||||
|             "actions": "Aktionen" | ||||
|           }, | ||||
|           "no_entries_found": "Keine Einträge gefunden", | ||||
|           "message": { | ||||
|             "auto_role_rule_create": "Auto Rollen Regel erstellt", | ||||
|             "auto_role_rule_create_d": "Auto Rollen Regel {{id}} erfolgreich erstellt", | ||||
|             "auto_role_rule_create_failed": "Auto Rollen Regel Erstellung fehlgeschlagen", | ||||
|             "auto_role_rule_create_failed_d": "Die Erstellung der Auto Rollen Regel ist fehlgeschlagen!", | ||||
|             "auto_role_rule_update": "Auto Rollen Regel bearbeitet", | ||||
|             "auto_role_rule_update_d": "Auto Rollen Regel {{id}} erfolgreich bearbeitet", | ||||
|             "auto_role_rule_update_failed": "Auto Rollen Regel Bearbeitung fehlgeschlagen", | ||||
|             "auto_role_rule_update_failed_d": "Die Bearbeitung der Auto Rollen Regel ist fehlgeschlagen!", | ||||
|             "auto_role_rule_delete": "Auto Rollen Regel löschen", | ||||
|             "auto_role_rule_delete_q": "Sind Sie sich sicher, dass Sie die Auto Rollen Regel {{id}} löschen möchten?", | ||||
|             "auto_role_rule_deleted": "Auto Rollen Regel gelöscht", | ||||
|             "auto_role_rule_deleted_d": "Auto Rollen Regel {{id}} erfolgreich gelöscht", | ||||
|             "auto_role_rule_delete_failed": "Auto Rollen Regel Löschung fehlgeschlagen", | ||||
|             "auto_role_rule_delete_failed_d": "Die Löschung der Auto Rollen Regel {{id}} ist fehlgeschlagen!" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "user-list": {}, | ||||
|   | ||||
| @@ -156,6 +156,12 @@ header { | ||||
|             margin: 5px 0; | ||||
|           } | ||||
|  | ||||
|           .dropdown-icon-label-wrapper { | ||||
|             display: flex; | ||||
|             flex-direction: row; | ||||
|             gap: 10px; | ||||
|           } | ||||
|  | ||||
|           .content-input-field { | ||||
|             width: 50% !important; | ||||
|             margin: 0 !important; | ||||
|   | ||||
| @@ -97,6 +97,11 @@ p-table { | ||||
|   } | ||||
| } | ||||
|  | ||||
| .p-dropdown, | ||||
| .p-inputnumber { | ||||
|   width: 100% !important; | ||||
| } | ||||
|  | ||||
| .pi-sort-alt:before { | ||||
|   content: "\e915" !important; | ||||
| } | ||||
|   | ||||
| @@ -580,4 +580,18 @@ | ||||
|     background-color: $primaryBackgroundColor !important; | ||||
|     color: $primaryHeaderColor !important; | ||||
|   } | ||||
|  | ||||
|   .input-number { | ||||
|     span { | ||||
|       .p-button { | ||||
|         background-color: $primaryHeaderColor !important; | ||||
|         border: 1px solid $primaryHeaderColor !important; | ||||
|  | ||||
|         &:hover { | ||||
|           background-color: $secondaryHeaderColor !important; | ||||
|           border: 1px solid $secondaryHeaderColor !important; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -580,4 +580,18 @@ | ||||
|     background-color: $primaryBackgroundColor !important; | ||||
|     color: $primaryHeaderColor !important; | ||||
|   } | ||||
|  | ||||
|   .input-number { | ||||
|     span { | ||||
|       .p-button { | ||||
|         background-color: $primaryHeaderColor !important; | ||||
|         border: 1px solid $primaryHeaderColor !important; | ||||
|  | ||||
|         &:hover { | ||||
|           background-color: $secondaryHeaderColor !important; | ||||
|           border: 1px solid $secondaryHeaderColor !important; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -582,4 +582,18 @@ | ||||
|     background-color: $primaryBackgroundColor !important; | ||||
|     color: $primaryHeaderColor !important; | ||||
|   } | ||||
|  | ||||
|   .input-number { | ||||
|     span { | ||||
|       .p-button { | ||||
|         background-color: $primaryHeaderColor !important; | ||||
|         border: 1px solid $primaryHeaderColor !important; | ||||
|  | ||||
|         &:hover { | ||||
|           background-color: $secondaryHeaderColor !important; | ||||
|           border: 1px solid $secondaryHeaderColor !important; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -580,4 +580,18 @@ | ||||
|     background-color: $primaryBackgroundColor !important; | ||||
|     color: $primaryHeaderColor !important; | ||||
|   } | ||||
|  | ||||
|   .input-number { | ||||
|     span { | ||||
|       .p-button { | ||||
|         background-color: $primaryHeaderColor !important; | ||||
|         border: 1px solid $primaryHeaderColor !important; | ||||
|  | ||||
|         &:hover { | ||||
|           background-color: $secondaryHeaderColor !important; | ||||
|           border: 1px solid $secondaryHeaderColor !important; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user