From 4b57d7f102612540e202df893d2855a3457e8e4b Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 15 Aug 2023 20:29:44 +0200 Subject: [PATCH 1/8] Added feature flags config to technician settings #334 --- kdb-bot/src/bot/main.py | 2 +- .../src/bot/startup_migration_extension.py | 2 + .../config_feature_flags_migration.py | 33 ++++++++++++ .../bot_data/migration/config_migration.py | 2 + kdb-bot/src/bot_data/model/server_config.py | 11 ++++ .../bot_data/model/server_config_history.py | 6 +++ .../src/bot_data/model/technician_config.py | 21 ++++++-- .../server_config_repository_service.py | 11 ++-- .../bot_data/service/server_config_seeder.py | 1 + .../technician_config_repository_service.py | 5 +- .../service/technician_config_seeder.py | 1 + .../src/bot_graphql/model/featureFlags.gql | 9 ++++ .../bot_graphql/model/technicianConfig.gql | 3 ++ .../mutations/technician_config_mutation.py | 5 ++ .../technician_config_history_query.py | 4 ++ .../queries/technician_config_query.py | 4 ++ .../app/models/config/feature-flags.model.ts | 4 ++ .../models/config/technician-config.model.ts | 2 + .../src/app/models/graphql/mutations.model.ts | 7 ++- .../src/app/models/graphql/queries.model.ts | 4 ++ .../settings/settings.component.html | 3 ++ .../components/settings/settings.component.ts | 2 + .../config-list/config-list.component.html | 4 +- .../feature-flag-list.component.html | 54 +++++++++++++++++++ .../feature-flag-list.component.scss | 0 .../feature-flag-list.component.spec.ts | 23 ++++++++ .../feature-flag-list.component.ts | 28 ++++++++++ .../src/app/modules/shared/shared.module.ts | 6 +++ kdb-web/src/assets/i18n/de.json | 1 + .../styles/themes/sh-edraft-dark-theme.scss | 11 +++- 30 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 kdb-bot/src/bot_data/migration/config_feature_flags_migration.py create mode 100644 kdb-bot/src/bot_graphql/model/featureFlags.gql create mode 100644 kdb-web/src/app/models/config/feature-flags.model.ts create mode 100644 kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.html create mode 100644 kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.scss create mode 100644 kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.spec.ts create mode 100644 kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.ts diff --git a/kdb-bot/src/bot/main.py b/kdb-bot/src/bot/main.py index 48b66eed..c004dd7d 100644 --- a/kdb-bot/src/bot/main.py +++ b/kdb-bot/src/bot/main.py @@ -31,10 +31,10 @@ class Program: .use_extension(StartupDiscordExtension) .use_extension(StartupModuleExtension) .use_extension(StartupMigrationExtension) + .use_extension(DatabaseExtension) .use_extension(ConfigExtension) .use_extension(InitBotExtension) .use_extension(BootLogExtension) - .use_extension(DatabaseExtension) .use_extension(AppApiExtension) .use_extension(CoreExtension) .use_startup(Startup) diff --git a/kdb-bot/src/bot/startup_migration_extension.py b/kdb-bot/src/bot/startup_migration_extension.py index 796b8257..89c5ae7d 100644 --- a/kdb-bot/src/bot/startup_migration_extension.py +++ b/kdb-bot/src/bot/startup_migration_extension.py @@ -9,6 +9,7 @@ from bot_data.migration.api_key_migration import ApiKeyMigration from bot_data.migration.api_migration import ApiMigration from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration from bot_data.migration.auto_role_migration import AutoRoleMigration +from bot_data.migration.config_feature_flags_migration import ConfigFeatureFlagsMigration from bot_data.migration.config_migration import ConfigMigration from bot_data.migration.db_history_migration import DBHistoryMigration from bot_data.migration.initial_migration import InitialMigration @@ -46,3 +47,4 @@ class StartupMigrationExtension(StartupExtensionABC): services.add_transient(MigrationABC, DBHistoryMigration) # 06.03.2023 #246 - 1.0.0 services.add_transient(MigrationABC, AchievementsMigration) # 14.06.2023 #268 - 1.1.0 services.add_transient(MigrationABC, ConfigMigration) # 19.07.2023 #127 - 1.1.0 + services.add_transient(MigrationABC, ConfigFeatureFlagsMigration) # 15.08.2023 #334 - 1.1.0 diff --git a/kdb-bot/src/bot_data/migration/config_feature_flags_migration.py b/kdb-bot/src/bot_data/migration/config_feature_flags_migration.py new file mode 100644 index 00000000..18a583e6 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/config_feature_flags_migration.py @@ -0,0 +1,33 @@ +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class ConfigFeatureFlagsMigration(MigrationABC): + name = "1.1.0_ConfigFeatureFlagsMigration" + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def upgrade(self): + self._logger.debug(__name__, "Running upgrade") + + self._cursor.execute( + str( + """ALTER TABLE CFG_Technician ADD FeatureFlags JSON NULL DEFAULT JSON_OBJECT() AFTER CacheMaxMessages;""" + ) + ) + + self._cursor.execute( + str( + """ALTER TABLE CFG_Server ADD FeatureFlags JSON NULL DEFAULT JSON_OBJECT() AFTER LoginMessageChannelId;""" + ) + ) + + def downgrade(self): + self._logger.debug(__name__, "Running downgrade") + self._cursor.execute("ALTER TABLE CFG_Technician DROP COLUMN FeatureFlags;") + self._cursor.execute("ALTER TABLE CFG_Server DROP COLUMN FeatureFlags;") diff --git a/kdb-bot/src/bot_data/migration/config_migration.py b/kdb-bot/src/bot_data/migration/config_migration.py index 0370cbb4..556b396f 100644 --- a/kdb-bot/src/bot_data/migration/config_migration.py +++ b/kdb-bot/src/bot_data/migration/config_migration.py @@ -143,6 +143,8 @@ class ConfigMigration(MigrationABC): def downgrade(self): self._logger.debug(__name__, "Running downgrade") + self._server_downgrade() + self._technician_downgrade() def _server_downgrade(self): self._cursor.execute("DROP TABLE `CFG_Server`;") diff --git a/kdb-bot/src/bot_data/model/server_config.py b/kdb-bot/src/bot_data/model/server_config.py index ba1db9f6..493a6cf5 100644 --- a/kdb-bot/src/bot_data/model/server_config.py +++ b/kdb-bot/src/bot_data/model/server_config.py @@ -4,6 +4,7 @@ from cpl_core.configuration import ConfigurationModelABC from cpl_core.database import TableABC from cpl_query.extension import List +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_data.model.server import Server from bot_data.model.server_team_role_ids_config import ServerTeamRoleIdsConfig @@ -24,6 +25,7 @@ class ServerConfig(TableABC, ConfigurationModelABC): help_voice_channel_id: int, team_channel_id: int, login_message_channel_id: int, + feature_flags: dict[FeatureFlagsEnum], server: Server, afk_channel_ids: List[int], team_role_ids: List[ServerTeamRoleIdsConfig], @@ -45,6 +47,7 @@ class ServerConfig(TableABC, ConfigurationModelABC): self._help_voice_channel_id = help_voice_channel_id self._team_channel_id = team_channel_id self._login_message_channel_id = login_message_channel_id + self._feature_flags = feature_flags self._server = server self._afk_channel_ids = afk_channel_ids self._team_role_ids = team_role_ids @@ -161,6 +164,14 @@ class ServerConfig(TableABC, ConfigurationModelABC): def login_message_channel_id(self, value: int): self._login_message_channel_id = value + @property + def feature_flags(self) -> dict[FeatureFlagsEnum]: + return self._feature_flags + + @feature_flags.setter + def feature_flags(self, value: dict[FeatureFlagsEnum]): + self._feature_flags = value + @property def afk_channel_ids(self) -> List[int]: return self._afk_channel_ids diff --git a/kdb-bot/src/bot_data/model/server_config_history.py b/kdb-bot/src/bot_data/model/server_config_history.py index d96e8473..a816e069 100644 --- a/kdb-bot/src/bot_data/model/server_config_history.py +++ b/kdb-bot/src/bot_data/model/server_config_history.py @@ -17,6 +17,7 @@ class ServerConfigHistory(HistoryTableABC): help_voice_channel_id: int, team_channel_id: int, login_message_channel_id: int, + feature_flags: dict[str], server_id: int, deleted: bool, date_from: str, @@ -39,6 +40,7 @@ class ServerConfigHistory(HistoryTableABC): self._help_voice_channel_id = help_voice_channel_id self._team_channel_id = team_channel_id self._login_message_channel_id = login_message_channel_id + self._feature_flags = feature_flags self._server_id = server_id self._deleted = deleted @@ -97,6 +99,10 @@ class ServerConfigHistory(HistoryTableABC): def login_message_channel_id(self) -> int: return self._login_message_channel_id + @property + def feature_flags(self) -> dict[str]: + return self._feature_flags + @property def server_id(self) -> int: return self._server_id diff --git a/kdb-bot/src/bot_data/model/technician_config.py b/kdb-bot/src/bot_data/model/technician_config.py index db43a82c..1390f4b8 100644 --- a/kdb-bot/src/bot_data/model/technician_config.py +++ b/kdb-bot/src/bot_data/model/technician_config.py @@ -1,9 +1,12 @@ +import json from datetime import datetime from cpl_core.configuration import ConfigurationModelABC from cpl_core.database import TableABC from cpl_query.extension import List +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum + class TechnicianConfig(TableABC, ConfigurationModelABC): def __init__( @@ -12,6 +15,7 @@ class TechnicianConfig(TableABC, ConfigurationModelABC): wait_for_restart: int, wait_for_shutdown: int, cache_max_messages: int, + feature_flags: dict[FeatureFlagsEnum], technician_ids: List[int], ping_urls: List[str], created_at: datetime = None, @@ -23,6 +27,7 @@ class TechnicianConfig(TableABC, ConfigurationModelABC): self._wait_for_restart = wait_for_restart self._wait_for_shutdown = wait_for_shutdown self._cache_max_messages = cache_max_messages + self._feature_flags = feature_flags self._technician_ids = technician_ids self._ping_urls = ping_urls @@ -66,6 +71,14 @@ class TechnicianConfig(TableABC, ConfigurationModelABC): def cache_max_messages(self, value: int): self._cache_max_messages = value + @property + def feature_flags(self) -> dict[FeatureFlagsEnum]: + return self._feature_flags + + @feature_flags.setter + def feature_flags(self, value: dict[FeatureFlagsEnum]): + self._feature_flags = value + @property def technician_ids(self) -> List[int]: return self._technician_ids @@ -104,12 +117,13 @@ class TechnicianConfig(TableABC, ConfigurationModelABC): return str( f""" INSERT INTO `CFG_Technician` ( - `HelpCommandReferenceUrl`, `WaitForRestart`, `WaitForShutdown`, `CacheMaxMessages` + `HelpCommandReferenceUrl`, `WaitForRestart`, `WaitForShutdown`, `CacheMaxMessages`, `FeatureFlags` ) VALUES ( '{self._help_command_reference_url}', {self._wait_for_restart}, {self._wait_for_shutdown}, - {self._cache_max_messages} + {self._cache_max_messages}, + '{json.dumps(self._feature_flags)}' ); """ ) @@ -122,7 +136,8 @@ class TechnicianConfig(TableABC, ConfigurationModelABC): SET `HelpCommandReferenceUrl` = '{self._help_command_reference_url}', `WaitForRestart` = {self._wait_for_restart}, `WaitForShutdown` = {self._wait_for_shutdown}, - `CacheMaxMessages` = {self._cache_max_messages} + `CacheMaxMessages` = {self._cache_max_messages}, + `FeatureFlags` = '{json.dumps(self._feature_flags)}' WHERE `Id` = {self._id}; """ ) diff --git a/kdb-bot/src/bot_data/service/server_config_repository_service.py b/kdb-bot/src/bot_data/service/server_config_repository_service.py index 09c1bff5..2f4879f9 100644 --- a/kdb-bot/src/bot_data/service/server_config_repository_service.py +++ b/kdb-bot/src/bot_data/service/server_config_repository_service.py @@ -1,3 +1,5 @@ +import json + from cpl_core.database.context import DatabaseContextABC from cpl_query.extension import List @@ -62,11 +64,12 @@ class ServerConfigRepositoryService(ServerConfigRepositoryABC): result[11], result[12], result[13], - self._servers.get_server_by_id(result[14]), - self._get_afk_channel_ids(result[14]), - self._get_team_role_ids(result[14]), - result[15], + json.loads(result[14]), + self._servers.get_server_by_id(result[15]), + self._get_afk_channel_ids(result[15]), + self._get_team_role_ids(result[15]), result[16], + result[17], id=result[0], ) diff --git a/kdb-bot/src/bot_data/service/server_config_seeder.py b/kdb-bot/src/bot_data/service/server_config_seeder.py index c80f3997..926c09b4 100644 --- a/kdb-bot/src/bot_data/service/server_config_seeder.py +++ b/kdb-bot/src/bot_data/service/server_config_seeder.py @@ -48,6 +48,7 @@ class ServerConfigSeeder(DataSeederABC): guild.system_channel.id, guild.system_channel.id, guild.system_channel.id, + {}, server, [], [], diff --git a/kdb-bot/src/bot_data/service/technician_config_repository_service.py b/kdb-bot/src/bot_data/service/technician_config_repository_service.py index 3e1354cb..fe32eded 100644 --- a/kdb-bot/src/bot_data/service/technician_config_repository_service.py +++ b/kdb-bot/src/bot_data/service/technician_config_repository_service.py @@ -1,3 +1,5 @@ +import json + from cpl_core.database.context import DatabaseContextABC from cpl_query.extension import List @@ -41,10 +43,11 @@ class TechnicianConfigRepositoryService(TechnicianConfigRepositoryABC): result[2], result[3], result[4], + json.loads(result[5]), self._get_technician_ids(), self._get_technician_ping_urls(), - result[5], result[6], + result[7], id=result[0], ) diff --git a/kdb-bot/src/bot_data/service/technician_config_seeder.py b/kdb-bot/src/bot_data/service/technician_config_seeder.py index ce2be05d..209b3e02 100644 --- a/kdb-bot/src/bot_data/service/technician_config_seeder.py +++ b/kdb-bot/src/bot_data/service/technician_config_seeder.py @@ -32,6 +32,7 @@ class TechnicianConfigSeeder(DataSeederABC): 8, 8, 1000000, + {}, List(int, [240160344557879316]), List(str, ["www.google.com", "www.sh-edraft.de", "www.keksdose-gaming.de"]), ) diff --git a/kdb-bot/src/bot_graphql/model/featureFlags.gql b/kdb-bot/src/bot_graphql/model/featureFlags.gql new file mode 100644 index 00000000..1eed1031 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/featureFlags.gql @@ -0,0 +1,9 @@ +type FeatureFlag { + key: String + value: Boolean +} + +input FeatureFlagInput { + key: String + value: Boolean +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/technicianConfig.gql b/kdb-bot/src/bot_graphql/model/technicianConfig.gql index dc35704a..0983c25b 100644 --- a/kdb-bot/src/bot_graphql/model/technicianConfig.gql +++ b/kdb-bot/src/bot_graphql/model/technicianConfig.gql @@ -4,6 +4,7 @@ type TechnicianConfig implements TableWithHistoryQuery { waitForRestart: Int waitForShutdown: Int cacheMaxMessages: Int + featureFlags: [FeatureFlag] pingURLs: [String] technicianIds: [String] @@ -21,6 +22,7 @@ type TechnicianConfigHistory implements HistoryTableQuery { waitForRestart: Int waitForShutdown: Int cacheMaxMessages: Int + featureFlags: [FeatureFlag] deleted: Boolean dateFrom: String @@ -55,6 +57,7 @@ input TechnicianConfigInput { waitForRestart: Int waitForShutdown: Int cacheMaxMessages: Int + featureFlags: [FeatureFlagInput] pingURLs: [String] technicianIds: [String] } \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py index da3b7651..1ac2e475 100644 --- a/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/technician_config_mutation.py @@ -49,6 +49,11 @@ class TechnicianConfigMutation(QueryABC): technician_config.cache_max_messages = ( input["cacheMaxMessages"] if "cacheMaxMessages" in input else technician_config.cache_max_messages ) + technician_config.feature_flags = ( + dict(zip([x["key"] for x in input["featureFlags"]], [x["value"] for x in input["featureFlags"]])) + if "featureFlags" in input + else technician_config.feature_flags + ) technician_config.ping_urls = ( List(str, input["pingURLs"]) if "pingURLs" in input else technician_config.ping_urls ) diff --git a/kdb-bot/src/bot_graphql/queries/technician_config_history_query.py b/kdb-bot/src/bot_graphql/queries/technician_config_history_query.py index 8d945fe0..ccdfc6df 100644 --- a/kdb-bot/src/bot_graphql/queries/technician_config_history_query.py +++ b/kdb-bot/src/bot_graphql/queries/technician_config_history_query.py @@ -9,3 +9,7 @@ class TechnicianConfigHistoryQuery(HistoryQueryABC): self.set_field("waitForRestart", lambda config, *_: config.wait_for_restart) self.set_field("waitForShutdown", lambda config, *_: config.wait_for_shutdown) self.set_field("cacheMaxMessages", lambda config, *_: config.cache_max_messages) + self.set_field( + "featureFlags", + lambda config, *_: [{"key": x, "value": config.feature_flags[x]} for x in config.feature_flags], + ) diff --git a/kdb-bot/src/bot_graphql/queries/technician_config_query.py b/kdb-bot/src/bot_graphql/queries/technician_config_query.py index 3cda423f..e97707df 100644 --- a/kdb-bot/src/bot_graphql/queries/technician_config_query.py +++ b/kdb-bot/src/bot_graphql/queries/technician_config_query.py @@ -16,6 +16,10 @@ class TechnicianConfigQuery(DataQueryWithHistoryABC): self.set_field("waitForRestart", lambda config, *_: config.wait_for_restart) self.set_field("waitForShutdown", lambda config, *_: config.wait_for_shutdown) self.set_field("cacheMaxMessages", lambda config, *_: config.cache_max_messages) + self.set_field( + "featureFlags", + lambda config, *_: [{"key": x, "value": config.feature_flags[x]} for x in config.feature_flags], + ) self.set_field("pingURLs", lambda config, *_: config.ping_urls) self.set_field("technicianIds", lambda config, *_: config.technician_ids) diff --git a/kdb-web/src/app/models/config/feature-flags.model.ts b/kdb-web/src/app/models/config/feature-flags.model.ts new file mode 100644 index 00000000..010843a3 --- /dev/null +++ b/kdb-web/src/app/models/config/feature-flags.model.ts @@ -0,0 +1,4 @@ +export interface FeatureFlag { + key: string; + value: boolean; +} diff --git a/kdb-web/src/app/models/config/technician-config.model.ts b/kdb-web/src/app/models/config/technician-config.model.ts index 6e1430f0..e70ae752 100644 --- a/kdb-web/src/app/models/config/technician-config.model.ts +++ b/kdb-web/src/app/models/config/technician-config.model.ts @@ -1,4 +1,5 @@ import { DataWithHistory } from "../data/data.model"; +import { FeatureFlag } from "./feature-flags.model"; export interface TechnicianConfig extends DataWithHistory { id?: number; @@ -6,6 +7,7 @@ export interface TechnicianConfig extends DataWithHistory { waitForRestart?: number; waitForShutdown?: number; cacheMaxMessages?: number; + featureFlags: FeatureFlag[]; pingURLs: string[]; technicianIds: string[]; } diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts index 7905eff4..42f0ad2b 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -167,7 +167,7 @@ export class Mutations { `; static updateTechnicianConfig = ` - mutation updateTechnicianConfig($id: ID, $helpCommandReferenceUrl: String, $waitForRestart: Int, $waitForShutdown: Int, $cacheMaxMessages: Int, $pingURLs: [String], $technicianIds: [String]) { + mutation updateTechnicianConfig($id: ID, $helpCommandReferenceUrl: String, $waitForRestart: Int, $waitForShutdown: Int, $cacheMaxMessages: Int, $featureFlags: [FeatureFlagInput], $pingURLs: [String], $technicianIds: [String]) { technicianConfig { updateTechnicianConfig(input: { id: $id, @@ -175,6 +175,7 @@ export class Mutations { waitForRestart: $waitForRestart, waitForShutdown: $waitForShutdown, cacheMaxMessages: $cacheMaxMessages, + featureFlags: $featureFlags, pingURLs: $pingURLs, technicianIds: $technicianIds }) { @@ -183,6 +184,10 @@ export class Mutations { waitForRestart waitForShutdown cacheMaxMessages + featureFlags { + key + value + } pingURLs technicianIds } diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 4f6856b4..51042ef6 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -353,6 +353,10 @@ export class Queries { waitForRestart waitForShutdown cacheMaxMessages + featureFlags { + key + value + } pingURLs technicianIds diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html index b7e68a1b..8eb4a65d 100644 --- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html +++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html @@ -164,6 +164,9 @@ + +
+
diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts index c4b691a7..d543c7ad 100644 --- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts +++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts @@ -49,6 +49,7 @@ export class SettingsComponent implements OnInit { waitForRestart: 0, waitForShutdown: 0, cacheMaxMessages: 0, + featureFlags: [], pingURLs: [], technicianIds: [] }; @@ -150,6 +151,7 @@ export class SettingsComponent implements OnInit { waitForRestart: this.config.waitForRestart, waitForShutdown: this.config.waitForShutdown, cacheMaxMessages: this.config.cacheMaxMessages, + featureFlags: this.config.featureFlags, pingURLs: this.config.pingURLs, technicianIds: this.config.technicianIds } diff --git a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html index 4e3ea7d2..ee893a09 100644 --- a/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html +++ b/kdb-web/src/app/modules/shared/components/config-list/config-list.component.html @@ -15,8 +15,8 @@
- - + + diff --git a/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.html b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.html new file mode 100644 index 00000000..88197a1b --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.html @@ -0,0 +1,54 @@ +
+
+
+ {{'common.feature_flags' | translate}}: +
+
+ + +
+
+ +
+
+
+ + + + + + + + + {{value.value.key}} + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+
+
+
+
diff --git a/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.scss b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.spec.ts b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.spec.ts new file mode 100644 index 00000000..4151e4d6 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FeatureFlagListComponent } from './feature-flag-list.component'; + +describe('FeatureFlagListComponent', () => { + let component: FeatureFlagListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ FeatureFlagListComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(FeatureFlagListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.ts b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.ts new file mode 100644 index 00000000..4781de70 --- /dev/null +++ b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.ts @@ -0,0 +1,28 @@ +import { Component } from "@angular/core"; +import { ConfigListComponent } from "../config-list/config-list.component"; +import { Table } from "primeng/table"; + +@Component({ + selector: "app-feature-flag-list", + templateUrl: "./feature-flag-list.component.html", + styleUrls: ["./feature-flag-list.component.scss"] +}) +export class FeatureFlagListComponent extends ConfigListComponent { + options: boolean[] = [true, false]; + + constructor() { + super(); + } + + override addNew(table: Table) { + const id = Math.max.apply(Math, this.internal_data.map(value => { + return value.id ?? 0; + })) + 1; + const newItem = { id: id, value: {key: "", value: false} }; + this.internal_data.push(newItem); + + table.initRowEdit(newItem); + const index = this.internal_data.findIndex(l => l.id == newItem.id); + this.editInit(newItem, index); + } +} diff --git a/kdb-web/src/app/modules/shared/shared.module.ts b/kdb-web/src/app/modules/shared/shared.module.ts index ae7d2ebd..9cea8e7f 100644 --- a/kdb-web/src/app/modules/shared/shared.module.ts +++ b/kdb-web/src/app/modules/shared/shared.module.ts @@ -30,6 +30,8 @@ import { MultiSelectModule } from "primeng/multiselect"; import { HideableColumnComponent } from './components/hideable-column/hideable-column.component'; import { HideableHeaderComponent } from './components/hideable-header/hideable-header.component'; import { MultiSelectColumnsComponent } from './base/multi-select-columns/multi-select-columns.component'; +import { FeatureFlagListComponent } from './components/feature-flag-list/feature-flag-list.component'; +import { InputSwitchModule } from "primeng/inputswitch"; @NgModule({ @@ -42,6 +44,7 @@ import { MultiSelectColumnsComponent } from './base/multi-select-columns/multi-s HideableColumnComponent, HideableHeaderComponent, MultiSelectColumnsComponent, + FeatureFlagListComponent, ], imports: [ CommonModule, @@ -68,6 +71,7 @@ import { MultiSelectColumnsComponent } from './base/multi-select-columns/multi-s SidebarModule, DataViewModule, MultiSelectModule, + InputSwitchModule, ], exports: [ ButtonModule, @@ -102,6 +106,8 @@ import { MultiSelectColumnsComponent } from './base/multi-select-columns/multi-s HideableColumnComponent, HideableHeaderComponent, MultiSelectColumnsComponent, + FeatureFlagListComponent, + InputSwitchModule, ] }) export class SharedModule { diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index e624840c..5c940e5a 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -122,6 +122,7 @@ } }, "common": { + "feature_flags": "Funktionen", "404": "404 - Der Eintrag konnte nicht gefunden werden", "actions": "Aktionen", "active": "Aktiv", diff --git a/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss b/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss index a14d03eb..117949d4 100644 --- a/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss +++ b/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss @@ -587,7 +587,7 @@ .p-datatable .p-sortable-column.p-highlight, .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon, - .p-datatable .p-sortable-column:not(.p-highlight):hover{ + .p-datatable .p-sortable-column:not(.p-highlight):hover { color: $primaryHeaderColor !important; background-color: transparent !important; } @@ -672,4 +672,13 @@ } } } + + .p-inputswitch.p-inputswitch-checked .p-inputswitch-slider { + background: $primaryHeaderColor !important; + } + + .p-inputswitch.p-focus .p-inputswitch-slider { + box-shadow: none !important; + } + } From 8a0d939147ef2e30eec07a1d539d9ead2dc9e550 Mon Sep 17 00:00:00 2001 From: Sven Heidemann Date: Tue, 15 Aug 2023 20:50:11 +0200 Subject: [PATCH 2/8] Added feature flags to server config #334 --- kdb-bot/src/bot_data/model/server_config.py | 4 +++ kdb-bot/src/bot_graphql/model/query.gql | 1 + .../src/bot_graphql/model/serverConfig.gql | 3 ++ .../mutations/server_config_mutation.py | 5 +++ .../queries/server_config_query.py | 4 +++ kdb-bot/src/bot_graphql/query.py | 2 ++ .../app/models/config/server-config.model.ts | 2 ++ .../src/app/models/graphql/mutations.model.ts | 36 +++++++++++-------- .../src/app/models/graphql/queries.model.ts | 4 +++ kdb-web/src/app/models/graphql/query.model.ts | 5 +++ .../settings/settings.component.html | 2 -- .../feature-flag-list.component.html | 3 +- .../feature-flag-list.component.ts | 22 +++++++++--- .../components/config/config.component.html | 1 + .../components/config/config.component.ts | 5 +-- 15 files changed, 74 insertions(+), 25 deletions(-) diff --git a/kdb-bot/src/bot_data/model/server_config.py b/kdb-bot/src/bot_data/model/server_config.py index 493a6cf5..64c666d1 100644 --- a/kdb-bot/src/bot_data/model/server_config.py +++ b/kdb-bot/src/bot_data/model/server_config.py @@ -1,3 +1,4 @@ +import json from datetime import datetime from cpl_core.configuration import ConfigurationModelABC @@ -236,6 +237,7 @@ class ServerConfig(TableABC, ConfigurationModelABC): `HelpVoiceChannelId`, `TeamChannelId`, `LoginMessageChannelId`, + `FeatureFlags`, `ServerId` ) VALUES ( {self._message_delete_timer}, @@ -251,6 +253,7 @@ class ServerConfig(TableABC, ConfigurationModelABC): {self._help_voice_channel_id}, {self._team_channel_id}, {self._login_message_channel_id}, + '{json.dumps(self._feature_flags)}', {self._server.id} ); """ @@ -274,6 +277,7 @@ class ServerConfig(TableABC, ConfigurationModelABC): `HelpVoiceChannelId` = {self._help_voice_channel_id}, `TeamChannelId` = {self._team_channel_id}, `LoginMessageChannelId` = {self._login_message_channel_id}, + `FeatureFlags` = '{json.dumps(self._feature_flags)}', `ServerId` = {self._server.id} WHERE `Id` = {self._id}; """ diff --git a/kdb-bot/src/bot_graphql/model/query.gql b/kdb-bot/src/bot_graphql/model/query.gql index abb3048a..8c8a9de1 100644 --- a/kdb-bot/src/bot_graphql/model/query.gql +++ b/kdb-bot/src/bot_graphql/model/query.gql @@ -40,4 +40,5 @@ type Query { technicianConfig: TechnicianConfig guilds(filter: GuildFilter): [Guild] + possibleFeatureFlags: [String] } \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/serverConfig.gql b/kdb-bot/src/bot_graphql/model/serverConfig.gql index b16fa139..0f327ae2 100644 --- a/kdb-bot/src/bot_graphql/model/serverConfig.gql +++ b/kdb-bot/src/bot_graphql/model/serverConfig.gql @@ -13,6 +13,7 @@ type ServerConfig implements TableWithHistoryQuery { helpVoiceChannelId: String teamChannelId: String loginMessageChannelId: String + featureFlags: [FeatureFlag] afkChannelIds: [String] moderatorRoleIds: [String] @@ -41,6 +42,7 @@ type ServerConfigHistory implements HistoryTableQuery { helpVoiceChannelId: String teamChannelId: String loginMessageChannelId: String + featureFlags: [FeatureFlag] serverId: ID @@ -87,6 +89,7 @@ input ServerConfigInput { helpVoiceChannelId: String teamChannelId: String loginMessageChannelId: String + featureFlags: [FeatureFlagInput] afkChannelIds: [String] moderatorRoleIds: [String] diff --git a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py index 2480be82..df8996e2 100644 --- a/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/server_config_mutation.py @@ -82,6 +82,11 @@ class ServerConfigMutation(QueryABC): if "loginMessageChannelId" in input else server_config.login_message_channel_id ) + server_config.feature_flags = ( + dict(zip([x["key"] for x in input["featureFlags"]], [x["value"] for x in input["featureFlags"]])) + if "featureFlags" in input + else server_config.feature_flags + ) server_config.afk_channel_ids = ( List(int).extend([int(x) for x in input["afkChannelIds"]]) if "afkChannelIds" in input diff --git a/kdb-bot/src/bot_graphql/queries/server_config_query.py b/kdb-bot/src/bot_graphql/queries/server_config_query.py index 8672c4d2..189a86ee 100644 --- a/kdb-bot/src/bot_graphql/queries/server_config_query.py +++ b/kdb-bot/src/bot_graphql/queries/server_config_query.py @@ -23,6 +23,10 @@ class ServerConfigQuery(DataQueryWithHistoryABC): self.set_field("helpVoiceChannelId", lambda config, *_: config.help_voice_channel_id) self.set_field("teamChannelId", lambda config, *_: config.team_channel_id) self.set_field("loginMessageChannelId", lambda config, *_: config.login_message_channel_id) + self.set_field( + "featureFlags", + lambda config, *_: [{"key": x, "value": config.feature_flags[x]} for x in config.feature_flags], + ) self.set_field("afkChannelIds", lambda config, *_: config.afk_channel_ids) self.set_field( "moderatorRoleIds", diff --git a/kdb-bot/src/bot_graphql/query.py b/kdb-bot/src/bot_graphql/query.py index 030d7bdd..7ec97aee 100644 --- a/kdb-bot/src/bot_graphql/query.py +++ b/kdb-bot/src/bot_graphql/query.py @@ -1,5 +1,6 @@ from cpl_discord.service import DiscordBotServiceABC +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_data.abc.achievement_repository_abc import AchievementRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC @@ -75,6 +76,7 @@ class Query(QueryABC): self.set_field("guilds", self._resolve_guilds) self.set_field("achievementAttributes", lambda x, *_: achievement_service.get_attributes()) self.set_field("achievementOperators", lambda x, *_: achievement_service.get_operators()) + self.set_field("possibleFeatureFlags", lambda x, *_: [e.value for e in FeatureFlagsEnum]) def _resolve_guilds(self, *_, filter=None): if filter is None or "id" not in filter: diff --git a/kdb-web/src/app/models/config/server-config.model.ts b/kdb-web/src/app/models/config/server-config.model.ts index b55c4136..c2b1d1c8 100644 --- a/kdb-web/src/app/models/config/server-config.model.ts +++ b/kdb-web/src/app/models/config/server-config.model.ts @@ -1,4 +1,5 @@ import { DataWithHistory } from "../data/data.model"; +import { FeatureFlag } from "./feature-flags.model"; export interface ServerConfig extends DataWithHistory { id?: number; @@ -15,6 +16,7 @@ export interface ServerConfig extends DataWithHistory { helpVoiceChannelId?: string; teamChannelId?: string; loginMessageChannelId?: string; + featureFlags: FeatureFlag[]; afkChannelIds: string[]; moderatorRoleIds: string[]; adminRoleIds: string[]; diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts index 42f0ad2b..20263626 100644 --- a/kdb-web/src/app/models/graphql/mutations.model.ts +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -211,6 +211,7 @@ export class Mutations { $helpVoiceChannelId: String, $teamChannelId: String, $loginMessageChannelId: String, + $featureFlags: [FeatureFlagInput], $afkChannelIds: [String], $moderatorRoleIds: [String], $adminRoleIds: [String] @@ -218,21 +219,22 @@ export class Mutations { serverConfig { updateServerConfig(input: { id: $id, - messageDeleteTimer: $messageDeleteTimer - notificationChatId: $notificationChatId - maxVoiceStateHours: $maxVoiceStateHours - xpPerMessage: $xpPerMessage - xpPerReaction: $xpPerReaction - maxMessageXpPerHour: $maxMessageXpPerHour - xpPerOntimeHour: $xpPerOntimeHour - xpPerEventParticipation: $xpPerEventParticipation - xpPerAchievement: $xpPerAchievement - afkCommandChannelId: $afkCommandChannelId - helpVoiceChannelId: $helpVoiceChannelId - teamChannelId: $teamChannelId - loginMessageChannelId: $loginMessageChannelId - afkChannelIds: $afkChannelIds - moderatorRoleIds: $moderatorRoleIds + messageDeleteTimer: $messageDeleteTimer, + notificationChatId: $notificationChatId, + maxVoiceStateHours: $maxVoiceStateHours, + xpPerMessage: $xpPerMessage, + xpPerReaction: $xpPerReaction, + maxMessageXpPerHour: $maxMessageXpPerHour, + xpPerOntimeHour: $xpPerOntimeHour, + xpPerEventParticipation: $xpPerEventParticipation, + xpPerAchievement: $xpPerAchievement, + afkCommandChannelId: $afkCommandChannelId, + helpVoiceChannelId: $helpVoiceChannelId, + teamChannelId: $teamChannelId, + loginMessageChannelId: $loginMessageChannelId, + featureFlags: $featureFlags, + afkChannelIds: $afkChannelIds, + moderatorRoleIds: $moderatorRoleIds, adminRoleIds: $adminRoleIds }) { id @@ -249,6 +251,10 @@ export class Mutations { helpVoiceChannelId teamChannelId loginMessageChannelId + featureFlags { + key + value + } afkChannelIds moderatorRoleIds adminRoleIds diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 51042ef6..7e7e212f 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -385,6 +385,10 @@ export class Queries { helpVoiceChannelId teamChannelId loginMessageChannelId + featureFlags { + key + value + } afkChannelIds moderatorRoleIds adminRoleIds diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts index 42eeb69d..12b5ddaa 100644 --- a/kdb-web/src/app/models/graphql/query.model.ts +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -59,3 +59,8 @@ export interface AutoRoleRuleQuery { autoRoleRules: AutoRoleRule[]; } + +export interface PossibleFeatureFlagsQuery { + possibleFeatureFlags: string[]; +} + diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html index 8eb4a65d..7887819d 100644 --- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html +++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html @@ -163,9 +163,7 @@
- -
+
diff --git a/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.ts b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.ts index 4781de70..141ed1a4 100644 --- a/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.ts +++ b/kdb-web/src/app/modules/shared/components/feature-flag-list/feature-flag-list.component.ts @@ -1,24 +1,36 @@ -import { Component } from "@angular/core"; +import { Component, OnInit } from "@angular/core"; import { ConfigListComponent } from "../config-list/config-list.component"; import { Table } from "primeng/table"; +import { PossibleFeatureFlagsQuery } from "../../../../models/graphql/query.model"; +import { DataService } from "../../../../services/data/data.service"; @Component({ selector: "app-feature-flag-list", templateUrl: "./feature-flag-list.component.html", styleUrls: ["./feature-flag-list.component.scss"] }) -export class FeatureFlagListComponent extends ConfigListComponent { - options: boolean[] = [true, false]; +export class FeatureFlagListComponent extends ConfigListComponent implements OnInit { + featureFlags: string[] = []; - constructor() { + + constructor( + private dataService: DataService + ) { super(); } + ngOnInit() { + this.dataService.query("{possibleFeatureFlags}" + ).subscribe(data => { + this.featureFlags = data.possibleFeatureFlags; + }); + } + override addNew(table: Table) { const id = Math.max.apply(Math, this.internal_data.map(value => { return value.id ?? 0; })) + 1; - const newItem = { id: id, value: {key: "", value: false} }; + const newItem = { id: id, value: { key: "", value: false } }; this.internal_data.push(newItem); table.initRowEdit(newItem); diff --git a/kdb-web/src/app/modules/view/server/config/components/config/config.component.html b/kdb-web/src/app/modules/view/server/config/components/config/config.component.html index 9f7701c1..7f0fadb0 100644 --- a/kdb-web/src/app/modules/view/server/config/components/config/config.component.html +++ b/kdb-web/src/app/modules/view/server/config/components/config/config.component.html @@ -113,6 +113,7 @@ +