#268_achievements #325
| @@ -27,6 +27,10 @@ class AchievementRepositoryABC(ABC): | ||||
|     def get_achievements_by_user_id(self, user_id: int) -> List[Achievement]: | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]: | ||||
|         pass | ||||
|  | ||||
|     @abstractmethod | ||||
|     def add_achievement(self, achievement: Achievement): | ||||
|         pass | ||||
|   | ||||
| @@ -21,6 +21,7 @@ class AchievementsMigration(MigrationABC): | ||||
|                     CREATE TABLE IF NOT EXISTS `Achievements` ( | ||||
|                         `Id` BIGINT NOT NULL AUTO_INCREMENT, | ||||
|                         `Name` VARCHAR(255) NOT NULL, | ||||
|                         `Description` VARCHAR(255) NOT NULL, | ||||
|                         `Attribute` VARCHAR(255) NOT NULL, | ||||
|                         `Operator` VARCHAR(255) NOT NULL, | ||||
|                         `Value` VARCHAR(255) NOT NULL, | ||||
| @@ -41,6 +42,7 @@ class AchievementsMigration(MigrationABC): | ||||
|                     ( | ||||
|                         `Id`    BIGINT(20)  NOT NULL, | ||||
|                         `Name` VARCHAR(255) NOT NULL, | ||||
|                         `Description` VARCHAR(255) NOT NULL, | ||||
|                         `Attribute` VARCHAR(255) NOT NULL, | ||||
|                         `Operator` VARCHAR(255) NOT NULL, | ||||
|                         `Value` VARCHAR(255) NOT NULL, | ||||
| @@ -77,41 +79,45 @@ class AchievementsMigration(MigrationABC): | ||||
|         self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD MessageCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) | ||||
|         self._cursor.execute(str(f"""ALTER TABLE UsersHistory ADD ReactionCount BIGINT NOT NULL DEFAULT 0 AFTER XP;""")) | ||||
|  | ||||
|         self._cursor.execute(str(f"""DROP TRIGGER IF EXISTS `TR_AchievementsUpdate`;""")) | ||||
|         self._cursor.execute( | ||||
|             str( | ||||
|                 f""" | ||||
|                     DROP TRIGGER IF EXISTS `TR_AchievementsUpdate`; | ||||
|  | ||||
|                     CREATE TRIGGER `TR_AchievementsUpdate` | ||||
|                         AFTER UPDATE | ||||
|                         ON `Achievements` | ||||
|                         FOR EACH ROW | ||||
|                     BEGIN | ||||
|                         INSERT INTO `AchievementsHistory` ( | ||||
|                             `Id`, `Name`, `Attribute`, `Operator`, `Value`, `ServerId`, `DateFrom`, `DateTo` | ||||
|                             `Id`, `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`, `DateFrom`, `DateTo` | ||||
|                         ) | ||||
|                         VALUES ( | ||||
|                             OLD.Id, OLD.Name, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) | ||||
|                             OLD.Id, OLD.Name, OLD.Description, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) | ||||
|                         ); | ||||
|                     END; | ||||
|                      | ||||
|                     DROP TRIGGER IF EXISTS `TR_AchievementsDelete`; | ||||
|                      | ||||
|                 """ | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|         self._cursor.execute(str(f"""DROP TRIGGER IF EXISTS `TR_AchievementsDelete`;""")) | ||||
|  | ||||
|         self._cursor.execute( | ||||
|             str( | ||||
|                 f""" | ||||
|                     CREATE TRIGGER `TR_AchievementsDelete` | ||||
|                         AFTER DELETE | ||||
|                         ON `Achievements` | ||||
|                         FOR EACH ROW | ||||
|                     BEGIN | ||||
|                         INSERT INTO `AchievementsHistory` ( | ||||
|                             `Id`, `Name`, `Attribute`, `Operator`, `Value`, `ServerId`, `Deleted`, `DateFrom`, `DateTo` | ||||
|                             `Id`, `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId`, `Deleted`, `DateFrom`, `DateTo` | ||||
|                         ) | ||||
|                         VALUES ( | ||||
|                             OLD.Id, OLD.Name, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) | ||||
|                             OLD.Id, OLD.Name, OLD.Description, OLD.Attribute, OLD.Operator, OLD.Value, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) | ||||
|                         ); | ||||
|                     END; | ||||
|                 """ | ||||
|             ), | ||||
|             multi=True, | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|     def downgrade(self): | ||||
|   | ||||
| @@ -11,6 +11,7 @@ class Achievement(TableABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         name: str, | ||||
|         description: str, | ||||
|         attribute: str, | ||||
|         operator: str, | ||||
|         value: str, | ||||
| @@ -21,6 +22,7 @@ class Achievement(TableABC): | ||||
|     ): | ||||
|         self._id = id | ||||
|         self._name = name | ||||
|         self._description = description | ||||
|         self._attribute = attribute | ||||
|  | ||||
|         if self._is_operator_valid(operator): | ||||
| @@ -53,6 +55,14 @@ class Achievement(TableABC): | ||||
|     def name(self, value: str): | ||||
|         self._name = value | ||||
|  | ||||
|     @property | ||||
|     def description(self) -> str: | ||||
|         return self._description | ||||
|  | ||||
|     @description.setter | ||||
|     def description(self, value: str): | ||||
|         self._description = value | ||||
|  | ||||
|     @property | ||||
|     def attribute(self) -> str: | ||||
|         return self._attribute | ||||
| @@ -103,9 +113,10 @@ class Achievement(TableABC): | ||||
|         return str( | ||||
|             f""" | ||||
|             INSERT INTO `Achievements` ( | ||||
|                 `Name`, `Attribute`, `Operator`, `Value`, `ServerId` | ||||
|                 `Name`, `Description`, `Attribute`, `Operator`, `Value`, `ServerId` | ||||
|             ) VALUES ( | ||||
|                 '{self._name}', | ||||
|                 '{self._description}', | ||||
|                 '{self._attribute}', | ||||
|                 '{self._operator}', | ||||
|                 '{self._value}', | ||||
| @@ -120,6 +131,7 @@ class Achievement(TableABC): | ||||
|             f""" | ||||
|                     UPDATE `Achievements` | ||||
|                     SET `Name` = '{self._name}', | ||||
|                     `Description` = '{self._description}', | ||||
|                     `Attribute` = '{self._attribute}', | ||||
|                     `Operator` = '{self._operator}', | ||||
|                     `Value` = '{self._value}' | ||||
|   | ||||
| @@ -5,6 +5,7 @@ class AchievementHistory(HistoryTableABC): | ||||
|     def __init__( | ||||
|         self, | ||||
|         name: str, | ||||
|         description: str, | ||||
|         attribute: str, | ||||
|         operator: str, | ||||
|         value: str, | ||||
| @@ -18,6 +19,7 @@ class AchievementHistory(HistoryTableABC): | ||||
|  | ||||
|         self._id = id | ||||
|         self._name = name | ||||
|         self._description = description | ||||
|         self._attribute = attribute | ||||
|         self._operator = operator | ||||
|         self._value = value | ||||
| @@ -35,6 +37,10 @@ class AchievementHistory(HistoryTableABC): | ||||
|     def name(self) -> str: | ||||
|         return self._name | ||||
|  | ||||
|     @property | ||||
|     def description(self) -> str: | ||||
|         return self._description | ||||
|  | ||||
|     @property | ||||
|     def attribute(self) -> str: | ||||
|         return self._attribute | ||||
|   | ||||
| @@ -62,6 +62,15 @@ class UserGotAchievement(TableABC): | ||||
|             """ | ||||
|         ) | ||||
|  | ||||
|     @staticmethod | ||||
|     def get_select_by_achievement_id_string(id: int) -> str: | ||||
|         return str( | ||||
|             f""" | ||||
|                 SELECT * FROM `UserGotAchievements` | ||||
|                 WHERE `AchievementId` = {id}; | ||||
|             """ | ||||
|         ) | ||||
|  | ||||
|     @property | ||||
|     def insert_string(self) -> str: | ||||
|         return str( | ||||
|   | ||||
| @@ -31,9 +31,10 @@ class AchievementRepositoryService(AchievementRepositoryABC): | ||||
|             result[2], | ||||
|             result[3], | ||||
|             result[4], | ||||
|             self._servers.get_server_by_id(result[5]), | ||||
|             result[6], | ||||
|             result[5], | ||||
|             self._servers.get_server_by_id(result[6]), | ||||
|             result[7], | ||||
|             result[8], | ||||
|             id=result[0], | ||||
|         ) | ||||
|  | ||||
| @@ -89,6 +90,18 @@ class AchievementRepositoryService(AchievementRepositoryABC): | ||||
|  | ||||
|         return achievements | ||||
|  | ||||
|     def get_user_got_achievements_by_achievement_id(self, achievement_id: int) -> List[Achievement]: | ||||
|         achievements_joins = List(UserGotAchievement) | ||||
|         self._logger.trace( | ||||
|             __name__, f"Send SQL command: {UserGotAchievement.get_select_by_achievement_id_string(achievement_id)}" | ||||
|         ) | ||||
|         results = self._context.select(UserGotAchievement.get_select_by_achievement_id_string(achievement_id)) | ||||
|         for result in results: | ||||
|             self._logger.trace(__name__, f"Got UserGotAchievement with id {result[0]}") | ||||
|             achievements_joins.append(self._join_from_result(result)) | ||||
|  | ||||
|         return achievements_joins | ||||
|  | ||||
|     def add_achievement(self, achievement: Achievement): | ||||
|         self._logger.trace(__name__, f"Send SQL command: {achievement.insert_string}") | ||||
|         self._context.cursor.execute(achievement.insert_string) | ||||
|   | ||||
| @@ -10,6 +10,7 @@ class AchievementFilter(FilterABC): | ||||
|  | ||||
|         self._id = None | ||||
|         self._name = None | ||||
|         self._description = None | ||||
|         self._attribute = None | ||||
|         self._operator = None | ||||
|         self._value = None | ||||
| @@ -22,6 +23,9 @@ class AchievementFilter(FilterABC): | ||||
|         if "name" in values: | ||||
|             self._name = values["name"] | ||||
|  | ||||
|         if "description" in values: | ||||
|             self._description = values["description"] | ||||
|  | ||||
|         if "attribute" in values: | ||||
|             self._attribute = values["attribute"] | ||||
|  | ||||
| @@ -42,10 +46,13 @@ class AchievementFilter(FilterABC): | ||||
|             query = query.where(lambda x: x.id == self._id) | ||||
|  | ||||
|         if self._name is not None: | ||||
|             query = query.where(lambda x: x.name == self._name) | ||||
|             query = query.where(lambda x: x.name == self._name or self._name in x.name) | ||||
|  | ||||
|         if self._description is not None: | ||||
|             query = query.where(lambda x: x.description == self._description or self._description in x.description) | ||||
|  | ||||
|         if self._attribute is not None: | ||||
|             query = query.where(lambda x: x.attribute == self._attribute) | ||||
|             query = query.where(lambda x: x.attribute == self._attribute or self._attribute in x.attribute) | ||||
|  | ||||
|         if self._operator is not None: | ||||
|             query = query.where(lambda x: x.operator == self._operator) | ||||
|   | ||||
| @@ -9,6 +9,7 @@ type AchievementAttribute { | ||||
| type Achievement implements TableWithHistoryQuery { | ||||
|     id: ID | ||||
|     name: String | ||||
|     description: String | ||||
|     attribute: String | ||||
|     operator: String | ||||
|     value: String | ||||
| @@ -24,6 +25,7 @@ type Achievement implements TableWithHistoryQuery { | ||||
| type AchievementHistory implements HistoryTableQuery { | ||||
|     id: ID | ||||
|     name: String | ||||
|     description: String | ||||
|     attribute: String | ||||
|     operator: String | ||||
|     value: String | ||||
| @@ -38,6 +40,7 @@ type AchievementHistory implements HistoryTableQuery { | ||||
| input AchievementFilter { | ||||
|     id: ID | ||||
|     name: String | ||||
|     description: String | ||||
|     attribute: String | ||||
|     operator: String | ||||
|     value: String | ||||
| @@ -53,6 +56,7 @@ type AchievementMutation { | ||||
| input AchievementInput { | ||||
|     id: ID | ||||
|     name: String | ||||
|     description: String | ||||
|     attribute: String | ||||
|     operator: String | ||||
|     value: String | ||||
|   | ||||
| @@ -36,6 +36,7 @@ class AchievementMutation(QueryABC): | ||||
|  | ||||
|         achievement = Achievement( | ||||
|             input["name"], | ||||
|             input["description"], | ||||
|             input["attribute"], | ||||
|             input["operator"], | ||||
|             input["value"], | ||||
| @@ -47,6 +48,7 @@ class AchievementMutation(QueryABC): | ||||
|         def get_new_achievement(a: Achievement): | ||||
|             return ( | ||||
|                 a.name == achievement.name | ||||
|                 and a.description == achievement.description | ||||
|                 and a.attribute == achievement.attribute | ||||
|                 and a.operator == achievement.operator | ||||
|                 and a.value == achievement.value | ||||
| @@ -60,6 +62,7 @@ class AchievementMutation(QueryABC): | ||||
|         self._can_user_mutate_data(achievement.server, UserRoleEnum.moderator) | ||||
|  | ||||
|         achievement.name = input["name"] if "name" in input else achievement.name | ||||
|         achievement.description = input["description"] if "description" in input else achievement.description | ||||
|         achievement.attribute = input["attribute"] if "attribute" in input else achievement.attribute | ||||
|         achievement.operator = input["operator"] if "operator" in input else achievement.operator | ||||
|         achievement.value = input["value"] if "value" in input else achievement.value | ||||
| @@ -74,6 +77,10 @@ class AchievementMutation(QueryABC): | ||||
|         achievement = self._achievements.get_achievement_by_id(id) | ||||
|         self._can_user_mutate_data(achievement.server, UserRoleEnum.admin) | ||||
|  | ||||
|         joins = self._achievements.get_user_got_achievements_by_achievement_id(id) | ||||
|         for join in joins: | ||||
|             self._achievements.delete_user_got_achievement(join) | ||||
|  | ||||
|         self._achievements.delete_achievement(achievement) | ||||
|         self._db.save_changes() | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ class AchievementHistoryQuery(HistoryQueryABC): | ||||
|  | ||||
|         self.set_field("id", lambda x, *_: x.id) | ||||
|         self.set_field("name", lambda x, *_: x.name) | ||||
|         self.set_field("description", lambda x, *_: x.description) | ||||
|         self.set_field("attribute", lambda x, *_: x.attribute) | ||||
|         self.set_field("operator", lambda x, *_: x.operator) | ||||
|         self.set_field("value", lambda x, *_: x.value) | ||||
|   | ||||
| @@ -13,6 +13,7 @@ class AchievementQuery(DataQueryWithHistoryABC): | ||||
|  | ||||
|         self.set_field("id", lambda x, *_: x.id) | ||||
|         self.set_field("name", lambda x, *_: x.name) | ||||
|         self.set_field("description", lambda x, *_: x.description) | ||||
|         self.set_field("attribute", lambda x, *_: x.attribute) | ||||
|         self.set_field("operator", lambda x, *_: x.operator) | ||||
|         self.set_field("value", lambda x, *_: x.value) | ||||
|   | ||||
| @@ -9,6 +9,7 @@ export interface AchievementAttribute { | ||||
| export interface Achievement extends DataWithHistory { | ||||
|   id?: number; | ||||
|   name?: string; | ||||
|   description?: string; | ||||
|   attribute?: string | AchievementAttribute; | ||||
|   operator?: string; | ||||
|   value?: string; | ||||
| @@ -20,6 +21,7 @@ export interface Achievement extends DataWithHistory { | ||||
| export interface AchievementFilter { | ||||
|   id?: number; | ||||
|   name?: string; | ||||
|   description?: string; | ||||
|   attribute?: string; | ||||
|   operator?: string; | ||||
|   value?: string; | ||||
|   | ||||
| @@ -123,11 +123,12 @@ export class Mutations { | ||||
|   `; | ||||
|  | ||||
|   static createAchievement = ` | ||||
|     mutation createAchievement($name: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { | ||||
|     mutation createAchievement($name: String, $description: String, $attribute: String, $operator: String, $value: String, $serverId: ID) { | ||||
|       achievement { | ||||
|         createAchievement(input: { name: $name, attribute: $attribute, operator: $operator, value: $value, serverId: $serverId}) { | ||||
|         createAchievement(input: { name: $name, description: $description, attribute: $attribute, operator: $operator, value: $value, serverId: $serverId}) { | ||||
|           id | ||||
|           name | ||||
|           description | ||||
|           attribute | ||||
|           operator | ||||
|           value | ||||
| @@ -140,11 +141,12 @@ export class Mutations { | ||||
|   `; | ||||
|  | ||||
|   static updateAchievement = ` | ||||
|     mutation updateAchievement($id: ID, $name: String, $attribute: String, $operator: String, $value: String) { | ||||
|     mutation updateAchievement($id: ID, $name: String, $description: String, $attribute: String, $operator: String, $value: String) { | ||||
|       achievement { | ||||
|         updateAchievement(input: { id: $id, name: $name, attribute: $attribute, operator: $operator, value: $value}) { | ||||
|         updateAchievement(input: { id: $id, name: $name, description: $description, attribute: $attribute, operator: $operator, value: $value}) { | ||||
|           id | ||||
|           name | ||||
|           description | ||||
|           attribute | ||||
|           operator | ||||
|           value | ||||
|   | ||||
| @@ -117,6 +117,7 @@ export class Queries { | ||||
|         achievements(filter: $filter, page: $page, sort: $sort) { | ||||
|           id | ||||
|           name | ||||
|           description | ||||
|           attribute | ||||
|           operator | ||||
|           value | ||||
| @@ -141,6 +142,7 @@ export class Queries { | ||||
|           history { | ||||
|             id | ||||
|             name | ||||
|             description | ||||
|             attribute | ||||
|             operator | ||||
|             value | ||||
|   | ||||
| @@ -43,6 +43,13 @@ | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th pSortableColumn="description"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.achievements.headers.description' | translate}}</div> | ||||
|               <p-sortIcon field="name" class="table-header-icon"></p-sortIcon> | ||||
|             </div> | ||||
|           </th> | ||||
|  | ||||
|           <th pSortableColumn="attribute"> | ||||
|             <div class="table-header-label"> | ||||
|               <div class="table-header-text">{{'view.server.achievements.headers.attribute' | translate}}</div> | ||||
| @@ -96,6 +103,12 @@ | ||||
|                      placeholder="{{'view.server.achievements.headers.name' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|           <th> | ||||
|             <form [formGroup]="filterForm"> | ||||
|               <input type="text" pInputText formControlName="name" | ||||
|                      placeholder="{{'view.server.achievements.headers.description' | translate}}"> | ||||
|             </form> | ||||
|           </th> | ||||
|           <th></th> | ||||
|           <th></th> | ||||
|           <th></th> | ||||
| @@ -129,6 +142,17 @@ | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|                 <input class="table-edit-input" pInputText type="text" [(ngModel)]="achievement.description"> | ||||
|               </ng-template> | ||||
|               <ng-template pTemplate="output"> | ||||
|                 {{achievement.description}} | ||||
|               </ng-template> | ||||
|             </p-cellEditor> | ||||
|           </td> | ||||
|  | ||||
|           <td> | ||||
|             <p-cellEditor> | ||||
|               <ng-template pTemplate="input"> | ||||
|   | ||||
| @@ -227,6 +227,7 @@ export class AchievementComponent implements OnInit, OnDestroy { | ||||
|       this.spinner.showSpinner(); | ||||
|       this.data.mutation<AchievementMutationResult>(Mutations.createAchievement, { | ||||
|           name: newAchievement.name, | ||||
|           description: newAchievement.description, | ||||
|           attribute: newAchievement.attribute, | ||||
|           operator: newAchievement.operator, | ||||
|           value: newAchievement.value + "", | ||||
| @@ -250,6 +251,7 @@ export class AchievementComponent implements OnInit, OnDestroy { | ||||
|     this.data.mutation<AchievementMutationResult>(Mutations.updateAchievement, { | ||||
|         id: newAchievement.id, | ||||
|         name: newAchievement.name, | ||||
|         description: newAchievement.description, | ||||
|         attribute: newAchievement.attribute, | ||||
|         operator: newAchievement.operator, | ||||
|         value: newAchievement.value + "" | ||||
|   | ||||
| @@ -326,6 +326,7 @@ | ||||
|         "headers": { | ||||
|           "attribute": "Attribut", | ||||
|           "name": "Name", | ||||
|           "description": "Beschreibung", | ||||
|           "operator": "Operator", | ||||
|           "value": "Wert" | ||||
|         }, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user