From 56216419a398fea0f92a4295b3e84885e1633ae7 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 12:47:23 +0100 Subject: [PATCH 01/47] Multi-BIS Add names, remove unique-together --- backend/api/migrations/0019_multi_bis.py | 22 ++++++++++++++++++++++ backend/api/models/bis_list.py | 2 +- backend/api/serializers/bis_list.py | 22 ++++++++++++---------- 3 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 backend/api/migrations/0019_multi_bis.py diff --git a/backend/api/migrations/0019_multi_bis.py b/backend/api/migrations/0019_multi_bis.py new file mode 100644 index 00000000..47865fe2 --- /dev/null +++ b/backend/api/migrations/0019_multi_bis.py @@ -0,0 +1,22 @@ +# Generated by Django 3.2.13 on 2022-05-13 11:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0018_character_alias'), + ] + + operations = [ + migrations.AddField( + model_name='bislist', + name='name', + field=models.CharField(default='', max_length=64), + ), + migrations.AlterUniqueTogether( + name='bislist', + unique_together=set(), + ), + ] diff --git a/backend/api/models/bis_list.py b/backend/api/models/bis_list.py index 87b39bf4..e9288d79 100644 --- a/backend/api/models/bis_list.py +++ b/backend/api/models/bis_list.py @@ -38,10 +38,10 @@ class BISList(models.Model): current_right_ring = models.ForeignKey('Gear', on_delete=models.CASCADE, related_name='current_right_ring_set') external_link = models.URLField(null=True) job = models.ForeignKey('Job', on_delete=models.CASCADE) + name = models.CharField(max_length=64, default='') owner = models.ForeignKey('Character', on_delete=models.CASCADE, related_name='bis_lists') class Meta: - unique_together = ['job', 'owner'] ordering = ['-job__role', 'job__ordering'] def accessory_augments_required(self, gear_name: str) -> int: diff --git a/backend/api/serializers/bis_list.py b/backend/api/serializers/bis_list.py index 455310c1..1b2de4a1 100644 --- a/backend/api/serializers/bis_list.py +++ b/backend/api/serializers/bis_list.py @@ -64,11 +64,21 @@ class BISListSerializer(serializers.ModelSerializer): current_right_ring = GearSerializer() item_level = serializers.IntegerField() job = JobSerializer() + display_name = serializers.SerializerMethodField() class Meta: exclude = ['owner'] model = BISList + def get_display_name(self, obj: BISList) -> str: + """ + Same as Character, use the list name if one exists otherwise use the job name + """ + if obj.name != '': + return obj.name + else: + return obj.job.display_name + class BISListModifySerializer(serializers.ModelSerializer): offhand_is_mainhand = True @@ -99,6 +109,7 @@ class BISListModifySerializer(serializers.ModelSerializer): current_offhand_id = serializers.IntegerField() current_right_ring_id = serializers.IntegerField(validators=[_validate_gear_type('accessories')]) external_link = serializers.URLField(required=False, allow_null=True, allow_blank=True) + name = serializers.CharField(max_length=64, allow_blank=True) class Meta: model = BISList @@ -129,6 +140,7 @@ class Meta: 'current_offhand_id', 'current_right_ring_id', 'external_link', + 'name', ) def validate_job_id(self, job_id: str) -> str: @@ -141,16 +153,6 @@ def validate_job_id(self, job_id: str) -> str: except Job.DoesNotExist: raise serializers.ValidationError('Please select a valid Job.') - # Ensure that this is the only BISList for the Job - test = BISList.objects.filter(job_id=job_id) - if self.instance is not None: - test = test.filter(owner=self.instance.owner).exclude(pk=self.instance.pk) - else: - test = test.filter(owner=self.context['owner']) - - if test.exists(): - raise serializers.ValidationError('Currently SavageAim only supports one BISList per job.') - # Check the flag if job_id == 'PLD': self.offhand_is_mainhand = False From b6eda74de734cbb695e883706abbc84871c4a19e Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 12:57:54 +0100 Subject: [PATCH 02/47] Name field added to bis list form --- frontend/src/components/bis_list_form.vue | 28 +++++++++++++++++++++ frontend/src/dataclasses/bis_list_modify.ts | 5 ++++ frontend/src/interfaces/bis_list.ts | 2 ++ frontend/src/interfaces/responses.ts | 1 + frontend/src/views/edit_bis.vue | 7 +++--- frontend/src/views/new_bis.vue | 3 ++- 6 files changed, 42 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/bis_list_form.vue b/frontend/src/components/bis_list_form.vue index 3eba70b3..bc1f068f 100644 --- a/frontend/src/components/bis_list_form.vue +++ b/frontend/src/components/bis_list_form.vue @@ -10,6 +10,20 @@
+
+
+ +
+
+
+
+ +
+

{{ errors.name[0] }}

+
+
+
+
@@ -219,6 +233,20 @@
+
+
+ +
+
+
+
+ +
+

{{ errors.name[0] }}

+
+
+
+
diff --git a/frontend/src/dataclasses/bis_list_modify.ts b/frontend/src/dataclasses/bis_list_modify.ts index f98b6211..3889efd2 100644 --- a/frontend/src/dataclasses/bis_list_modify.ts +++ b/frontend/src/dataclasses/bis_list_modify.ts @@ -31,6 +31,8 @@ export default class BISListModify { public current_offhand_id = -1 public current_right_ring_id = -1 public external_link: string | null = null + public name = '' + public display_name = '' static buildEditVersion(responseList: BISList): BISListModify { // Create an instance of this dataclass from an object with the BISList interface @@ -65,6 +67,9 @@ export default class BISListModify { newList.current_right_ring_id = responseList.current_right_ring.id newList.external_link = responseList.external_link + newList.name = responseList.name + newList.display_name = responseList.display_name + return newList } } diff --git a/frontend/src/interfaces/bis_list.ts b/frontend/src/interfaces/bis_list.ts index f55c4306..b96c4757 100644 --- a/frontend/src/interfaces/bis_list.ts +++ b/frontend/src/interfaces/bis_list.ts @@ -27,8 +27,10 @@ export default interface BISList { current_necklace: Gear current_offhand: Gear current_right_ring: Gear + display_name: string external_link: string | null id: number item_level: number job: Job + name: string } diff --git a/frontend/src/interfaces/responses.ts b/frontend/src/interfaces/responses.ts index 6092dde7..c6efc34d 100644 --- a/frontend/src/interfaces/responses.ts +++ b/frontend/src/interfaces/responses.ts @@ -28,6 +28,7 @@ export interface BISListErrors { current_offhand_id?: string[], current_right_ring_id?: string[], external_link?: string[], + name?: string[], } export interface BISListDeleteReadResponse { diff --git a/frontend/src/views/edit_bis.vue b/frontend/src/views/edit_bis.vue index 40b0f6bd..d242e364 100644 --- a/frontend/src/views/edit_bis.vue +++ b/frontend/src/views/edit_bis.vue @@ -6,7 +6,8 @@
@@ -41,7 +42,7 @@ export default class EditBIS extends NewBIS { // Flag indicating if we're ready to display the page get loaded(): boolean { if (this.charLoaded && this.listLoaded) { - document.title = `Edit ${this.bisList.job_id} - ${this.character.name} - Savage Aim` + document.title = `Edit ${this.bisList.display_name} - ${this.character.name} - Savage Aim` return true } return false @@ -60,7 +61,7 @@ export default class EditBIS extends NewBIS { // Parse the list into an array of character interfaces and store them in the character data list const data = await response.json() as BISList this.bisList = BISListModify.buildEditVersion(data) - this.breadcrumb = this.bisList.job_id + this.breadcrumb = this.bisList.display_name this.listLoaded = true } else { diff --git a/frontend/src/views/new_bis.vue b/frontend/src/views/new_bis.vue index 5c1ac9a8..b0488529 100644 --- a/frontend/src/views/new_bis.vue +++ b/frontend/src/views/new_bis.vue @@ -7,7 +7,8 @@ From b33b89e5f0486e936634fefb257a709639d74304 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 13:13:07 +0100 Subject: [PATCH 03/47] Updated BISList ordering to include name descending order --- backend/api/migrations/0019_multi_bis.py | 6 +++++- backend/api/models/bis_list.py | 4 +--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/api/migrations/0019_multi_bis.py b/backend/api/migrations/0019_multi_bis.py index 47865fe2..78eb2bbc 100644 --- a/backend/api/migrations/0019_multi_bis.py +++ b/backend/api/migrations/0019_multi_bis.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.13 on 2022-05-13 11:31 +# Generated by Django 3.2.13 on 2022-05-13 12:12 from django.db import migrations, models @@ -10,6 +10,10 @@ class Migration(migrations.Migration): ] operations = [ + migrations.AlterModelOptions( + name='bislist', + options={'ordering': ['-job__role', 'job__ordering', 'name']}, + ), migrations.AddField( model_name='bislist', name='name', diff --git a/backend/api/models/bis_list.py b/backend/api/models/bis_list.py index e9288d79..41d7c151 100644 --- a/backend/api/models/bis_list.py +++ b/backend/api/models/bis_list.py @@ -2,8 +2,6 @@ The main class of the system; Links together characters, jobs and gear into a single list - -Currently is one gear list per character per job for ease, may change later """ from typing import List from django.db import models @@ -42,7 +40,7 @@ class BISList(models.Model): owner = models.ForeignKey('Character', on_delete=models.CASCADE, related_name='bis_lists') class Meta: - ordering = ['-job__role', 'job__ordering'] + ordering = ['-job__role', 'job__ordering', 'name'] def accessory_augments_required(self, gear_name: str) -> int: """ From 0a38b52a78c8509bc7caf9404f5b8e210b473140 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 13:17:23 +0100 Subject: [PATCH 04/47] Update tests to reflect new state of bis functionality --- backend/api/tests/test_bis_list.py | 92 ++++-------------------------- 1 file changed, 10 insertions(+), 82 deletions(-) diff --git a/backend/api/tests/test_bis_list.py b/backend/api/tests/test_bis_list.py index ba185dc1..b6506e0b 100644 --- a/backend/api/tests/test_bis_list.py +++ b/backend/api/tests/test_bis_list.py @@ -73,6 +73,7 @@ def test_create(self): 'current_right_ring_id': self.gear_id_map['Moonward'], 'current_left_ring_id': self.gear_id_map['Moonward'], 'external_link': '', + 'name': 'Hello :)', } response = self.client.post(url, data) @@ -101,7 +102,7 @@ def test_create_400(self): - Gear pk doesn't exist - Gear category is incorrect - Job ID doesn't exist - - Job already has a BIS List + - Name too long - Data missing - External link isn't a url """ @@ -113,7 +114,7 @@ def test_create_400(self): content = response.json() for field in content: self.assertEqual(content[field], ['This field is required.']) - self.assertEqual(len(content), 25) + self.assertEqual(len(content), 26) # All gear errors will be run at once since there's only one actual function to test data = { @@ -124,6 +125,7 @@ def test_create_400(self): 'bis_earrings_id': self.gear_id_map['Divine Light'], 'current_mainhand_id': self.gear_id_map['The Last'], 'external_link': 'abcde', + 'name': 'abcde' * 100, } response = self.client.post(url, data) @@ -138,45 +140,7 @@ def test_create_400(self): self.assertEqual(content['bis_earrings_id'], [invalid_gear]) self.assertEqual(content['current_mainhand_id'], [invalid_gear]) self.assertEqual(content['external_link'], ['Enter a valid URL.']) - - # Create a BIS List for a job, then send a request to make one for the same job - bis_gear = Gear.objects.first() - curr_gear = Gear.objects.last() - BISList.objects.create( - bis_body=bis_gear, - bis_bracelet=bis_gear, - bis_earrings=bis_gear, - bis_feet=bis_gear, - bis_hands=bis_gear, - bis_head=bis_gear, - bis_left_ring=bis_gear, - bis_legs=bis_gear, - bis_mainhand=bis_gear, - bis_necklace=bis_gear, - bis_offhand=bis_gear, - bis_right_ring=bis_gear, - current_body=curr_gear, - current_bracelet=curr_gear, - current_earrings=curr_gear, - current_feet=curr_gear, - current_hands=curr_gear, - current_head=curr_gear, - current_left_ring=curr_gear, - current_legs=curr_gear, - current_mainhand=curr_gear, - current_necklace=curr_gear, - current_offhand=curr_gear, - current_right_ring=curr_gear, - job_id='DRG', - owner=self.char, - ) - - data = {'job_id': 'DRG'} - response = self.client.post(url, data) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.content) - # Since we checked all the "this field is required" errors above, just check the ones we send now - content = response.json() - self.assertEqual(content['job_id'], ['Currently SavageAim only supports one BISList per job.']) + self.assertEqual(content['name'], ['Ensure this field has no more than 64 characters.']) def test_404(self): """ @@ -315,6 +279,7 @@ def test_update(self): 'current_right_ring_id': self.gear_id_map['Moonward'], 'current_left_ring_id': self.gear_id_map['Moonward'], 'external_link': None, + 'name': 'Update c:', } response = self.client.put(url, data) @@ -332,7 +297,7 @@ def test_update_400(self): - Gear pk doesn't exist - Gear category is incorrect - Job ID doesn't exist - - Job already has a BIS List + - Name is too long - Data missing """ url = reverse('api:bis_resource', kwargs={'character_id': self.char.pk, 'pk': self.bis.pk}) @@ -343,7 +308,7 @@ def test_update_400(self): content = response.json() for field in content: self.assertEqual(content[field], ['This field is required.']) - self.assertEqual(len(content), 25) + self.assertEqual(len(content), 26) # All gear errors will be run at once since there's only one actual function to test data = { @@ -353,6 +318,7 @@ def test_update_400(self): 'bis_head_id': self.gear_id_map['Eternal Dark'], 'bis_earrings_id': self.gear_id_map['Divine Light'], 'current_mainhand_id': self.gear_id_map['The Last'], + 'name': 'abcde' * 64, } response = self.client.put(url, data) @@ -366,45 +332,7 @@ def test_update_400(self): self.assertEqual(content['bis_head_id'], [invalid_gear]) self.assertEqual(content['bis_earrings_id'], [invalid_gear]) self.assertEqual(content['current_mainhand_id'], [invalid_gear]) - - # Create a BIS List for a job, then send a request to make one for the same job - bis_gear = Gear.objects.first() - curr_gear = Gear.objects.last() - BISList.objects.create( - bis_body=bis_gear, - bis_bracelet=bis_gear, - bis_earrings=bis_gear, - bis_feet=bis_gear, - bis_hands=bis_gear, - bis_head=bis_gear, - bis_left_ring=bis_gear, - bis_legs=bis_gear, - bis_mainhand=bis_gear, - bis_necklace=bis_gear, - bis_offhand=bis_gear, - bis_right_ring=bis_gear, - current_body=curr_gear, - current_bracelet=curr_gear, - current_earrings=curr_gear, - current_feet=curr_gear, - current_hands=curr_gear, - current_head=curr_gear, - current_left_ring=curr_gear, - current_legs=curr_gear, - current_mainhand=curr_gear, - current_necklace=curr_gear, - current_offhand=curr_gear, - current_right_ring=curr_gear, - job_id='RPR', - owner=self.char, - ) - - data = {'job_id': 'RPR'} - response = self.client.put(url, data) - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.content) - # Since we checked all the "this field is required" errors above, just check the ones we send now - content = response.json() - self.assertEqual(content['job_id'], ['Currently SavageAim only supports one BISList per job.']) + self.assertEqual(content['name'], ['Ensure this field has no more than 64 characters.']) def test_404(self): """ From 3021611d11c5fd7907fb4c0ff99c72dcd1601508 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 13:56:02 +0100 Subject: [PATCH 05/47] Using BIS List display name instead of job id / display name --- frontend/src/components/modals/confirmations/delete_bis.vue | 2 +- frontend/src/components/team_member_form.vue | 2 +- frontend/src/views/character.vue | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/modals/confirmations/delete_bis.vue b/frontend/src/components/modals/confirmations/delete_bis.vue index 9db44cb0..a7925c2e 100644 --- a/frontend/src/components/modals/confirmations/delete_bis.vue +++ b/frontend/src/components/modals/confirmations/delete_bis.vue @@ -129,7 +129,7 @@ export default class DeleteBIS extends Vue { if (response.ok) { // Attempt to parse the json, get the id, and then redirect this.$emit('close') - this.$notify({ text: `${this.bis.job.id} BIS deleted successfully!`, type: 'is-success' }) + this.$notify({ text: `${this.bis.display_name} deleted successfully!`, type: 'is-success' }) } else { this.$notify({ text: `Unexpected response ${response.status} when attempting to delete BIS List.`, type: 'is-danger' }) diff --git a/frontend/src/components/team_member_form.vue b/frontend/src/components/team_member_form.vue index 0aa4d805..fc342d17 100644 --- a/frontend/src/components/team_member_form.vue +++ b/frontend/src/components/team_member_form.vue @@ -30,7 +30,7 @@
diff --git a/frontend/src/views/character.vue b/frontend/src/views/character.vue index 2b570d7f..6e51e3d8 100644 --- a/frontend/src/views/character.vue +++ b/frontend/src/views/character.vue @@ -71,7 +71,7 @@
- {{ bis.job.display_name }} + {{ bis.display_name }}
From f76cda6683ad3a9b0460bf24e0380badbaa0e619 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 16:27:37 +0100 Subject: [PATCH 06/47] Updated serializer error messages for bis list --- backend/api/serializers/bis_list.py | 5 +++-- backend/api/tests/test_bis_list.py | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/backend/api/serializers/bis_list.py b/backend/api/serializers/bis_list.py index 1b2de4a1..febd6c83 100644 --- a/backend/api/serializers/bis_list.py +++ b/backend/api/serializers/bis_list.py @@ -26,11 +26,11 @@ def _inner(value: int) -> int: try: obj = Gear.objects.get(pk=value) except Gear.DoesNotExist: - raise serializers.ValidationError('Please ensure your value corresponds with a valid type of Gear.') + raise serializers.ValidationError('Please select a valid type of Gear.') # Ensure valid Gear for the slot if not getattr(obj, f'has_{gear_type}', False): - raise serializers.ValidationError('The chosen category of Gear does not have an item for this slot.') + raise serializers.ValidationError('The chosen type of Gear is invalid for this equipment slot.') return value return _inner @@ -142,6 +142,7 @@ class Meta: 'external_link', 'name', ) + extra_kwargs = {'bis_head_id': {'error_messages': {'invalid': 'Please select a valid type of Gear.'}}} def validate_job_id(self, job_id: str) -> str: """ diff --git a/backend/api/tests/test_bis_list.py b/backend/api/tests/test_bis_list.py index b6506e0b..739df8cf 100644 --- a/backend/api/tests/test_bis_list.py +++ b/backend/api/tests/test_bis_list.py @@ -132,10 +132,10 @@ def test_create_400(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.content) # Since we checked all the "this field is required" errors above, just check the ones we send now content = response.json() - invalid_gear = 'The chosen category of Gear does not have an item for this slot.' + invalid_gear = 'The chosen type of Gear is invalid for this equipment slot.' self.assertEqual(content['job_id'], ['Please select a valid Job.']) self.assertEqual(content['bis_mainhand_id'], ['A valid integer is required.']) - self.assertEqual(content['bis_body_id'], ['Please ensure your value corresponds with a valid type of Gear.']) + self.assertEqual(content['bis_body_id'], ['Please select a valid type of Gear.']) self.assertEqual(content['bis_head_id'], [invalid_gear]) self.assertEqual(content['bis_earrings_id'], [invalid_gear]) self.assertEqual(content['current_mainhand_id'], [invalid_gear]) @@ -325,10 +325,10 @@ def test_update_400(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST, response.content) # Since we checked all the "this field is required" errors above, just check the ones we send now content = response.json() - invalid_gear = 'The chosen category of Gear does not have an item for this slot.' + invalid_gear = 'The chosen type of Gear is invalid for this equipment slot.' self.assertEqual(content['job_id'], ['Please select a valid Job.']) self.assertEqual(content['bis_mainhand_id'], ['A valid integer is required.']) - self.assertEqual(content['bis_body_id'], ['Please ensure your value corresponds with a valid type of Gear.']) + self.assertEqual(content['bis_body_id'], ['Please select a valid type of Gear.']) self.assertEqual(content['bis_head_id'], [invalid_gear]) self.assertEqual(content['bis_earrings_id'], [invalid_gear]) self.assertEqual(content['current_mainhand_id'], [invalid_gear]) From 6231ec201379c6b175e5912826cc5317a1bd1df4 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 16:32:02 +0100 Subject: [PATCH 07/47] Spread out bis form into multiple components Planning for something BIG --- frontend/src/components/bis_list/actions.vue | 101 ++++ frontend/src/components/bis_list/bis.vue | 69 +++ frontend/src/components/bis_list/current.vue | 32 ++ .../src/components/bis_list/desktop_form.vue | 118 ++++ frontend/src/components/bis_list/details.vue | 109 ++++ frontend/src/components/bis_list/filters.vue | 77 +++ frontend/src/components/bis_list/form.vue | 107 ++++ .../src/components/bis_list/mobile_form.vue | 209 +++++++ frontend/src/components/bis_list_form.vue | 528 ------------------ frontend/src/components/modals/add_bis.vue | 32 +- frontend/src/components/modals/changelog.vue | 16 + frontend/src/views/edit_bis.vue | 36 +- frontend/src/views/new_bis.vue | 40 +- 13 files changed, 856 insertions(+), 618 deletions(-) create mode 100644 frontend/src/components/bis_list/actions.vue create mode 100644 frontend/src/components/bis_list/bis.vue create mode 100644 frontend/src/components/bis_list/current.vue create mode 100644 frontend/src/components/bis_list/desktop_form.vue create mode 100644 frontend/src/components/bis_list/details.vue create mode 100644 frontend/src/components/bis_list/filters.vue create mode 100644 frontend/src/components/bis_list/form.vue create mode 100644 frontend/src/components/bis_list/mobile_form.vue delete mode 100644 frontend/src/components/bis_list_form.vue diff --git a/frontend/src/components/bis_list/actions.vue b/frontend/src/components/bis_list/actions.vue new file mode 100644 index 00000000..be2e22ab --- /dev/null +++ b/frontend/src/components/bis_list/actions.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/frontend/src/components/bis_list/bis.vue b/frontend/src/components/bis_list/bis.vue new file mode 100644 index 00000000..cf0ff91e --- /dev/null +++ b/frontend/src/components/bis_list/bis.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/frontend/src/components/bis_list/current.vue b/frontend/src/components/bis_list/current.vue new file mode 100644 index 00000000..d8393513 --- /dev/null +++ b/frontend/src/components/bis_list/current.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/frontend/src/components/bis_list/desktop_form.vue b/frontend/src/components/bis_list/desktop_form.vue new file mode 100644 index 00000000..b8c5af5c --- /dev/null +++ b/frontend/src/components/bis_list/desktop_form.vue @@ -0,0 +1,118 @@ + + + + + diff --git a/frontend/src/components/bis_list/details.vue b/frontend/src/components/bis_list/details.vue new file mode 100644 index 00000000..0af8ca30 --- /dev/null +++ b/frontend/src/components/bis_list/details.vue @@ -0,0 +1,109 @@ + + + diff --git a/frontend/src/components/bis_list/filters.vue b/frontend/src/components/bis_list/filters.vue new file mode 100644 index 00000000..30ca5a3c --- /dev/null +++ b/frontend/src/components/bis_list/filters.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/frontend/src/components/bis_list/form.vue b/frontend/src/components/bis_list/form.vue new file mode 100644 index 00000000..51a63f76 --- /dev/null +++ b/frontend/src/components/bis_list/form.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/frontend/src/components/bis_list/mobile_form.vue b/frontend/src/components/bis_list/mobile_form.vue new file mode 100644 index 00000000..c1c4ff99 --- /dev/null +++ b/frontend/src/components/bis_list/mobile_form.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/frontend/src/components/bis_list_form.vue b/frontend/src/components/bis_list_form.vue deleted file mode 100644 index bc1f068f..00000000 --- a/frontend/src/components/bis_list_form.vue +++ /dev/null @@ -1,528 +0,0 @@ - - - - - diff --git a/frontend/src/components/modals/add_bis.vue b/frontend/src/components/modals/add_bis.vue index ac0a581b..228021ad 100644 --- a/frontend/src/components/modals/add_bis.vue +++ b/frontend/src/components/modals/add_bis.vue @@ -11,15 +11,14 @@
- - +
diff --git a/frontend/src/components/modals/changelog.vue b/frontend/src/components/modals/changelog.vue index 2491a01f..4ccdeefe 100644 --- a/frontend/src/components/modals/changelog.vue +++ b/frontend/src/components/modals/changelog.vue @@ -19,6 +19,22 @@
  • Ultimate of the Heavens; Item Level 605 Weapons
  • + +
    expand_more Multiple BIS Lists per Job expand_more
    +

    The limit of one BIS List per Job has finally been removed! You can now have as many BIS Lists as you want per Job, allowing you to keep historical lists as you advance the tiers, or manage two current lists per Job for the current Tier, the options are endless!

    +

    You can also give each list a name, to help differentiate different BIS Lists of the same Job. The name will default to the name of the Job.

    +

    + As part of this update, the following functionality has been changed; + +

    + +
    expand_more Minor Changes expand_more
    +

    Minor changes to the breadcrumbs in the BIS Create / Edit pages.

    diff --git a/frontend/src/views/edit_bis.vue b/frontend/src/views/edit_bis.vue index d242e364..178e7fe5 100644 --- a/frontend/src/views/edit_bis.vue +++ b/frontend/src/views/edit_bis.vue @@ -11,15 +11,14 @@
  • {{ breadcrumb }}
  • - - +
    diff --git a/frontend/src/views/new_bis.vue b/frontend/src/views/new_bis.vue index b0488529..9440cec7 100644 --- a/frontend/src/views/new_bis.vue +++ b/frontend/src/views/new_bis.vue @@ -11,17 +11,15 @@
  • New
  • - - +
    From 3d37e0b574d0bbe8fd5d9172700b3a930e12ec2f Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 18:02:45 +0100 Subject: [PATCH 08/47] Ensuring the add bis popup still works with new form design --- frontend/src/components/bis_list/actions.vue | 22 ++++++++++++++----- frontend/src/components/bis_list/form.vue | 11 +++++----- .../src/components/bis_list/mobile_form.vue | 6 ++++- frontend/src/components/modals/add_bis.vue | 3 ++- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/bis_list/actions.vue b/frontend/src/components/bis_list/actions.vue index be2e22ab..4f19bb29 100644 --- a/frontend/src/components/bis_list/actions.vue +++ b/frontend/src/components/bis_list/actions.vue @@ -3,14 +3,18 @@
    - - + - - +
    @@ -33,6 +37,10 @@ export default class Actions extends Vue { @Prop() method!: string + // Hide actions that spawn popups when this flag is true + @Prop({ default: false }) + simple!: boolean + @Prop() url!: string @@ -72,7 +80,11 @@ export default class Actions extends Vue { }) if (response.ok) { - if (this.create) { + if (this.simple) { + this.$notify({ text: 'BIS List Created successfully!', type: 'is-success' }) + this.$emit('close') + } + else if (this.create) { // Redirect back to the new bis list page const json = await response.json() as CreateResponse this.$router.push(`./${json.id}/`, () => { diff --git a/frontend/src/components/bis_list/form.vue b/frontend/src/components/bis_list/form.vue index 51a63f76..b93c2eda 100644 --- a/frontend/src/components/bis_list/form.vue +++ b/frontend/src/components/bis_list/form.vue @@ -13,7 +13,8 @@ v-on:update-max-il="updateMaxIl" v-on:error-code="emitErrorCode" v-on:errors="handleErrors" - v-on:save="emitSave" + v-on:save="$emit('save')" + v-on:close="$emit('close')" v-if="renderDesktop" /> @@ -26,12 +27,14 @@ :maxIl="maxIl" :method="method" :url="url" + :simpleActions="!renderDesktop" v-on:job-change="jobChange" v-on:update-min-il="updateMinIl" v-on:update-max-il="updateMaxIl" v-on:error-code="emitErrorCode" v-on:errors="handleErrors" - v-on:save="emitSave" + v-on:save="$emit('save')" + v-on:close="$emit('close')" :class="[renderDesktop ? 'is-hidden-desktop' : '']" />
    @@ -90,10 +93,6 @@ export default class BISListForm extends Vue { this.$emit('error-code', errorCode) } - emitSave(): void { - this.$emit('save') - } - handleErrors(errors: BISListErrors): void { this.errors = errors } diff --git a/frontend/src/components/bis_list/mobile_form.vue b/frontend/src/components/bis_list/mobile_form.vue index c1c4ff99..a806d5de 100644 --- a/frontend/src/components/bis_list/mobile_form.vue +++ b/frontend/src/components/bis_list/mobile_form.vue @@ -62,7 +62,7 @@
    - + @@ -114,6 +114,10 @@ export default class BISListMobileForm extends Vue { @Prop() minIl!: number + // Hide actions that spawn a popup, when used in the add bis section + @Prop() + simpleActions!: boolean + @Prop() url!: string diff --git a/frontend/src/components/modals/add_bis.vue b/frontend/src/components/modals/add_bis.vue index 228021ad..64684f50 100644 --- a/frontend/src/components/modals/add_bis.vue +++ b/frontend/src/components/modals/add_bis.vue @@ -11,7 +11,7 @@
    - +
    @@ -42,6 +42,7 @@ export default class AddBIS extends Vue { } handleError(errorCode: number): void { + if (errorCode === 400) return this.$notify({ text: `Something went wrong; HTTP ${errorCode}. Try adding a new BIS from the standard page instead.`, type: 'is-danger' }) } } From 9e5eb11d986991cfa1de64cf4b6ee661ada091bf Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 18:05:57 +0100 Subject: [PATCH 09/47] Making filters take up less vertical space --- frontend/src/components/bis_list/filters.vue | 5 ++--- frontend/src/components/bis_list/form.vue | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/bis_list/filters.vue b/frontend/src/components/bis_list/filters.vue index 30ca5a3c..29b4688a 100644 --- a/frontend/src/components/bis_list/filters.vue +++ b/frontend/src/components/bis_list/filters.vue @@ -1,9 +1,8 @@ From 6673ffeeb4c0060ad8768c9f4c0a226a9b3d23b5 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 19:30:46 +0100 Subject: [PATCH 12/47] Beginning work on the etro import view --- backend/requirements.txt | 2 ++ frontend/src/components/bis_list/details.vue | 2 +- frontend/src/components/modals/changelog.vue | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index 01e46777..75b3010d 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -41,3 +41,5 @@ urllib3==1.26.7 vine==5.0.0 wcwidth==0.2.5 wrapt==1.13.3 +coreapi +jellyfish diff --git a/frontend/src/components/bis_list/details.vue b/frontend/src/components/bis_list/details.vue index 0af8ca30..88224ad7 100644 --- a/frontend/src/components/bis_list/details.vue +++ b/frontend/src/components/bis_list/details.vue @@ -46,7 +46,7 @@

    {{ errors.external_link[0] }}

    -

    This is just a link to any page you deem would be handy to have attached to the list!

    +

    Etro links can now be imported automatically!

    diff --git a/frontend/src/components/modals/changelog.vue b/frontend/src/components/modals/changelog.vue index 4df82e62..aee4ff10 100644 --- a/frontend/src/components/modals/changelog.vue +++ b/frontend/src/components/modals/changelog.vue @@ -30,7 +30,12 @@
  • When creating / editing a BIS List you also have the option to pull Current Gear from another List of the same Job.
  • -

    It is also now possible to import BIS Gear from Etro Gearsets by filling in the Extra URL of a BIS List.

    +

    + It is also now possible to import BIS Gear from Etro Gearsets by filling in the Extra URL of a BIS List. +

      +
    • Imports may not be perfect as to avoid maintaining a map for different names in the website, it compares names of Gear between Savage Aim and Etro and chooses the closest name.
    • +
    +

    expand_more Minor Changes expand_more

    Minor changes to the breadcrumbs in the BIS Create / Edit pages.

    From bd27333369d7b88d90ad632f569df1cc9a62e5a2 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 21:32:01 +0100 Subject: [PATCH 13/47] Creating a view to import from etro --- backend/api/views/__init__.py | 3 ++ backend/api/views/etro.py | 88 +++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 backend/api/views/etro.py diff --git a/backend/api/views/__init__.py b/backend/api/views/__init__.py index 4275de4d..3cdfdddb 100644 --- a/backend/api/views/__init__.py +++ b/backend/api/views/__init__.py @@ -1,5 +1,6 @@ from .bis_list import BISListCollection, BISListDelete, BISListResource from .character import CharacterCollection, CharacterDelete, CharacterResource, CharacterVerification +from .etro import EtroImport from .gear import GearCollection, ItemLevels from .job import JobCollection from .loot import LootCollection, LootWithBIS @@ -19,6 +20,8 @@ 'CharacterResource', 'CharacterVerification', + 'EtroImport', + 'GearCollection', 'ItemLevels', diff --git a/backend/api/views/etro.py b/backend/api/views/etro.py new file mode 100644 index 00000000..60563408 --- /dev/null +++ b/backend/api/views/etro.py @@ -0,0 +1,88 @@ +""" +Given an etro id, convert it into a format that uses Savage Aim ids +""" +# stdlib +from typing import Dict, Set, Tuple +# lib +import coreapi +import jellyfish +from rest_framework.views import APIView +from rest_framework.request import Request +from rest_framework.response import Response +# local +from api.models import Gear, Job + + +# Map names of slots from etro to savage aim +SLOT_MAP = { + 'weapon': 'mainhand', + 'offHand': 'offhand', + 'head': 'head', + 'body': 'body', + 'hands': 'hands', + 'legs': 'legs', + 'feet': 'feet', + 'ears': 'earrings', + 'neck': 'necklace', + 'wrists': 'bracelet', + 'fingerL': 'left_ring', + 'fingerR': 'right_ring', +} + + +class EtroImport(APIView): + """ + Import an etro gearset using coreapi and levenshtein distance + """ + + @staticmethod + def _get_gear_id(gear_selection: Dict[str, str], item_name: str) -> str: + """ + Find the id of the gear piece that matches the name closest + """ + diff = float('inf') + gear_id = None + for details in gear_selection: + curr_diff = jellyfish.levenshtein_distance(details['name'], item_name) + if curr_diff < diff: + diff = curr_diff + gear_id = details['id'] + return gear_id + + def get(self, request: Request, id: str) -> Response: + """ + Return a list of Characters belonging to a certain User + """ + # Instantiate a Client instance for CoreAPI + client = coreapi.Client() + schema = client.get("https://etro.gg/api/docs/") + + # First things first, attempt to read the gearset + try: + response = client.action(schema, ['gearsets', 'read'], params={'id': id}) + except coreapi.exceptions.ErrorMessage as e: + return Response({'message': e.error.title}, status=400) + + job_id = response['jobAbbrev'] + + # Loop through each slot of the etro gearset, fetch the name and item level and store it in a dict + gear_details: Dict[str, str] = {} + item_levels: Set[int] = set() + + for etro_slot, sa_slot in SLOT_MAP.items(): + item_response = client.action(schema, ['equipment', 'read'], params={'id': response[etro_slot]}) + gear_details[sa_slot] = item_response['name'] + item_levels.add(item_response['itemLevel']) + + # Get the names of all the gear with the specified Item Levels + gear_names = Gear.objects.filter(item_level__in=item_levels).values('name', 'id') + + # Loop through the slots one final time, and get the gear id for that slot + response = { + slot: _get_gear_id(gear_names, item_name) + for slot, item_name in gear_details.items() + } + # Add the Job ID + response['job_id'] = job_id + + return Response(response) From 478bb163e2b367c73e526f13119fe5659c27f9ab Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 21:46:27 +0100 Subject: [PATCH 14/47] Hooked up etro import view, fixed it --- backend/api/urls.py | 3 +++ backend/api/views/etro.py | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/api/urls.py b/backend/api/urls.py index 8d96ac0b..46003ef0 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -17,6 +17,9 @@ path('gear/', views.GearCollection.as_view(), name='gear_collection'), path('gear/item_levels/', views.ItemLevels.as_view(), name='item_levels'), + # Imports + path('import/etro//', views.EtroImport.as_view(), name='etro_import'), + # Job path('job/', views.JobCollection.as_view(), name='job_collection'), diff --git a/backend/api/views/etro.py b/backend/api/views/etro.py index 60563408..49686014 100644 --- a/backend/api/views/etro.py +++ b/backend/api/views/etro.py @@ -62,7 +62,6 @@ def get(self, request: Request, id: str) -> Response: response = client.action(schema, ['gearsets', 'read'], params={'id': id}) except coreapi.exceptions.ErrorMessage as e: return Response({'message': e.error.title}, status=400) - job_id = response['jobAbbrev'] # Loop through each slot of the etro gearset, fetch the name and item level and store it in a dict @@ -70,7 +69,10 @@ def get(self, request: Request, id: str) -> Response: item_levels: Set[int] = set() for etro_slot, sa_slot in SLOT_MAP.items(): - item_response = client.action(schema, ['equipment', 'read'], params={'id': response[etro_slot]}) + gear_id = response[etro_slot] + if gear_id is None: + continue + item_response = client.action(schema, ['equipment', 'read'], params={'id': gear_id}) gear_details[sa_slot] = item_response['name'] item_levels.add(item_response['itemLevel']) @@ -79,7 +81,7 @@ def get(self, request: Request, id: str) -> Response: # Loop through the slots one final time, and get the gear id for that slot response = { - slot: _get_gear_id(gear_names, item_name) + slot: self._get_gear_id(gear_names, item_name) for slot, item_name in gear_details.items() } # Add the Job ID From 595fcd104cef0740a86ab93880ff2bce6a98fa60 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 22:05:34 +0100 Subject: [PATCH 15/47] Add handling for offhand to keep ui easy --- backend/api/views/etro.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/api/views/etro.py b/backend/api/views/etro.py index 49686014..015162e8 100644 --- a/backend/api/views/etro.py +++ b/backend/api/views/etro.py @@ -86,5 +86,8 @@ def get(self, request: Request, id: str) -> Response: } # Add the Job ID response['job_id'] = job_id + # Check for offhand + if job_id != 'PLD': + response['offhand'] = response['mainhand'] return Response(response) From 1b4bf520c0caae4a6041f4a56b760d304a93e8b0 Mon Sep 17 00:00:00 2001 From: freyamade Date: Fri, 13 May 2022 23:10:59 +0100 Subject: [PATCH 16/47] adding display name to etro import this is so we can have the job icon update too --- backend/api/views/etro.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/api/views/etro.py b/backend/api/views/etro.py index 015162e8..d95e6c86 100644 --- a/backend/api/views/etro.py +++ b/backend/api/views/etro.py @@ -84,8 +84,9 @@ def get(self, request: Request, id: str) -> Response: slot: self._get_gear_id(gear_names, item_name) for slot, item_name in gear_details.items() } - # Add the Job ID + # Add the Job ID and display name response['job_id'] = job_id + response['job_name'] = Job.objects.get(pk=job_id).display_name # Check for offhand if job_id != 'PLD': response['offhand'] = response['mainhand'] From 600ee2d5d013b737b718a55220f874e3faaba847 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 00:35:20 +0100 Subject: [PATCH 17/47] rename images to use job id instead of display name --- .../public/job_icons/{astrologian.png => AST.png} | Bin .../public/job_icons/{blackmage.png => BLM.png} | Bin frontend/public/job_icons/{bard.png => BRD.png} | Bin frontend/public/job_icons/{dancer.png => DNC.png} | Bin frontend/public/job_icons/{dragoon.png => DRG.png} | Bin .../public/job_icons/{darkknight.png => DRK.png} | Bin .../public/job_icons/{gunbreaker.png => GNB.png} | Bin .../public/job_icons/{machinist.png => MCH.png} | Bin frontend/public/job_icons/{monk.png => MNK.png} | Bin frontend/public/job_icons/{ninja.png => NIN.png} | Bin frontend/public/job_icons/{paladin.png => PLD.png} | Bin frontend/public/job_icons/{redmage.png => RDM.png} | Bin frontend/public/job_icons/{reaper.png => RPR.png} | Bin frontend/public/job_icons/{samurai.png => SAM.png} | Bin frontend/public/job_icons/{scholar.png => SCH.png} | Bin frontend/public/job_icons/{sage.png => SGE.png} | Bin frontend/public/job_icons/{summoner.png => SMN.png} | Bin frontend/public/job_icons/{warrior.png => WAR.png} | Bin .../public/job_icons/{whitemage.png => WHM.png} | Bin 19 files changed, 0 insertions(+), 0 deletions(-) rename frontend/public/job_icons/{astrologian.png => AST.png} (100%) rename frontend/public/job_icons/{blackmage.png => BLM.png} (100%) rename frontend/public/job_icons/{bard.png => BRD.png} (100%) rename frontend/public/job_icons/{dancer.png => DNC.png} (100%) rename frontend/public/job_icons/{dragoon.png => DRG.png} (100%) rename frontend/public/job_icons/{darkknight.png => DRK.png} (100%) rename frontend/public/job_icons/{gunbreaker.png => GNB.png} (100%) rename frontend/public/job_icons/{machinist.png => MCH.png} (100%) rename frontend/public/job_icons/{monk.png => MNK.png} (100%) rename frontend/public/job_icons/{ninja.png => NIN.png} (100%) rename frontend/public/job_icons/{paladin.png => PLD.png} (100%) rename frontend/public/job_icons/{redmage.png => RDM.png} (100%) rename frontend/public/job_icons/{reaper.png => RPR.png} (100%) rename frontend/public/job_icons/{samurai.png => SAM.png} (100%) rename frontend/public/job_icons/{scholar.png => SCH.png} (100%) rename frontend/public/job_icons/{sage.png => SGE.png} (100%) rename frontend/public/job_icons/{summoner.png => SMN.png} (100%) rename frontend/public/job_icons/{warrior.png => WAR.png} (100%) rename frontend/public/job_icons/{whitemage.png => WHM.png} (100%) diff --git a/frontend/public/job_icons/astrologian.png b/frontend/public/job_icons/AST.png similarity index 100% rename from frontend/public/job_icons/astrologian.png rename to frontend/public/job_icons/AST.png diff --git a/frontend/public/job_icons/blackmage.png b/frontend/public/job_icons/BLM.png similarity index 100% rename from frontend/public/job_icons/blackmage.png rename to frontend/public/job_icons/BLM.png diff --git a/frontend/public/job_icons/bard.png b/frontend/public/job_icons/BRD.png similarity index 100% rename from frontend/public/job_icons/bard.png rename to frontend/public/job_icons/BRD.png diff --git a/frontend/public/job_icons/dancer.png b/frontend/public/job_icons/DNC.png similarity index 100% rename from frontend/public/job_icons/dancer.png rename to frontend/public/job_icons/DNC.png diff --git a/frontend/public/job_icons/dragoon.png b/frontend/public/job_icons/DRG.png similarity index 100% rename from frontend/public/job_icons/dragoon.png rename to frontend/public/job_icons/DRG.png diff --git a/frontend/public/job_icons/darkknight.png b/frontend/public/job_icons/DRK.png similarity index 100% rename from frontend/public/job_icons/darkknight.png rename to frontend/public/job_icons/DRK.png diff --git a/frontend/public/job_icons/gunbreaker.png b/frontend/public/job_icons/GNB.png similarity index 100% rename from frontend/public/job_icons/gunbreaker.png rename to frontend/public/job_icons/GNB.png diff --git a/frontend/public/job_icons/machinist.png b/frontend/public/job_icons/MCH.png similarity index 100% rename from frontend/public/job_icons/machinist.png rename to frontend/public/job_icons/MCH.png diff --git a/frontend/public/job_icons/monk.png b/frontend/public/job_icons/MNK.png similarity index 100% rename from frontend/public/job_icons/monk.png rename to frontend/public/job_icons/MNK.png diff --git a/frontend/public/job_icons/ninja.png b/frontend/public/job_icons/NIN.png similarity index 100% rename from frontend/public/job_icons/ninja.png rename to frontend/public/job_icons/NIN.png diff --git a/frontend/public/job_icons/paladin.png b/frontend/public/job_icons/PLD.png similarity index 100% rename from frontend/public/job_icons/paladin.png rename to frontend/public/job_icons/PLD.png diff --git a/frontend/public/job_icons/redmage.png b/frontend/public/job_icons/RDM.png similarity index 100% rename from frontend/public/job_icons/redmage.png rename to frontend/public/job_icons/RDM.png diff --git a/frontend/public/job_icons/reaper.png b/frontend/public/job_icons/RPR.png similarity index 100% rename from frontend/public/job_icons/reaper.png rename to frontend/public/job_icons/RPR.png diff --git a/frontend/public/job_icons/samurai.png b/frontend/public/job_icons/SAM.png similarity index 100% rename from frontend/public/job_icons/samurai.png rename to frontend/public/job_icons/SAM.png diff --git a/frontend/public/job_icons/scholar.png b/frontend/public/job_icons/SCH.png similarity index 100% rename from frontend/public/job_icons/scholar.png rename to frontend/public/job_icons/SCH.png diff --git a/frontend/public/job_icons/sage.png b/frontend/public/job_icons/SGE.png similarity index 100% rename from frontend/public/job_icons/sage.png rename to frontend/public/job_icons/SGE.png diff --git a/frontend/public/job_icons/summoner.png b/frontend/public/job_icons/SMN.png similarity index 100% rename from frontend/public/job_icons/summoner.png rename to frontend/public/job_icons/SMN.png diff --git a/frontend/public/job_icons/warrior.png b/frontend/public/job_icons/WAR.png similarity index 100% rename from frontend/public/job_icons/warrior.png rename to frontend/public/job_icons/WAR.png diff --git a/frontend/public/job_icons/whitemage.png b/frontend/public/job_icons/WHM.png similarity index 100% rename from frontend/public/job_icons/whitemage.png rename to frontend/public/job_icons/WHM.png From 3cc70e0e979468a7d0ef7c4fb490781f7b81ecc9 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 00:40:21 +0100 Subject: [PATCH 18/47] changing strings to use id for job image --- backend/api/views/loot.py | 20 +++++++++---------- .../modals/confirmations/delete_bis.vue | 2 +- .../modals/confirmations/kick_from_team.vue | 2 +- .../modals/confirmations/leave_team.vue | 2 +- frontend/src/components/team_bio.vue | 2 +- frontend/src/components/team_member_card.vue | 2 +- frontend/src/components/team_member_form.vue | 2 +- frontend/src/dataclasses/bis_list_modify.ts | 19 +++++++++++++++++- frontend/src/views/character.vue | 2 +- 9 files changed, 35 insertions(+), 18 deletions(-) diff --git a/backend/api/views/loot.py b/backend/api/views/loot.py index 4a0b2962..9df0036f 100644 --- a/backend/api/views/loot.py +++ b/backend/api/views/loot.py @@ -65,7 +65,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: 'character_name': tm.character.display_name, 'current_gear_name': current_gear.name, 'current_gear_il': current_gear.item_level, - 'job_icon_name': tm.bis_list.job.name, + 'job_icon_name': tm.bis_list.job.id, 'job_role': tm.bis_list.job.role, }) @@ -90,7 +90,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: 'bis_list_id': greed_list.id, 'current_gear_name': current_gear.name, 'current_gear_il': current_gear.item_level, - 'job_icon_name': greed_list.job.name, + 'job_icon_name': greed_list.job.id, 'job_role': greed_list.job.role, }) gear[slot]['greed'].append(data) @@ -109,7 +109,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: # 'character_name': tm.character.display_name, # 'current_gear_name': current_gear.name, # 'current_gear_il': current_gear.item_level, - # 'job_icon_name': tm.bis_list.job.name, + # 'job_icon_name': tm.bis_list.job.id, # 'job_role': tm.bis_list.job.role, # }) @@ -135,7 +135,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: # 'bis_list_id': greed_list.id, # 'current_gear_name': current_gear.name, # 'current_gear_il': current_gear.item_level, - # 'job_icon_name': greed_list.job.name, + # 'job_icon_name': greed_list.job.id, # 'job_role': greed_list.job.role, # }) # gear[slot]['greed'].append(data) @@ -159,7 +159,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: 'character_name': tm.character.display_name, 'current_gear_name': current_gear.name, 'current_gear_il': current_gear.item_level, - 'job_icon_name': tm.bis_list.job.name, + 'job_icon_name': tm.bis_list.job.id, 'job_role': tm.bis_list.job.role, }) @@ -191,7 +191,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: 'bis_list_id': greed_list.id, 'current_gear_name': current_gear.name, 'current_gear_il': current_gear.item_level, - 'job_icon_name': greed_list.job.name, + 'job_icon_name': greed_list.job.id, 'job_role': greed_list.job.role, }) gear[slot]['greed'].append(data) @@ -207,7 +207,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: gear[slot]['need'].append({ 'member_id': tm.id, 'character_name': tm.character.display_name, - 'job_icon_name': tm.bis_list.job.name, + 'job_icon_name': tm.bis_list.job.id, 'job_role': tm.bis_list.job.role, 'requires': needs, }) @@ -224,7 +224,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: for greed_list in greed_lists: data['greed_lists'].append({ 'bis_list_id': greed_list.id, - 'job_icon_name': greed_list.job.name, + 'job_icon_name': greed_list.job.id, 'job_role': greed_list.job.role, 'requires': greed_list.accessory_augments_required(obj.tier.tome_gear_name), }) @@ -240,7 +240,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: gear[slot]['need'].append({ 'member_id': tm.id, 'character_name': tm.character.display_name, - 'job_icon_name': tm.bis_list.job.name, + 'job_icon_name': tm.bis_list.job.id, 'job_role': tm.bis_list.job.role, 'requires': needs, }) @@ -257,7 +257,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: for greed_list in greed_lists: data['greed_lists'].append({ 'bis_list_id': greed_list.id, - 'job_icon_name': greed_list.job.name, + 'job_icon_name': greed_list.job.id, 'job_role': greed_list.job.role, 'requires': greed_list.armour_augments_required(obj.tier.tome_gear_name), }) diff --git a/frontend/src/components/modals/confirmations/delete_bis.vue b/frontend/src/components/modals/confirmations/delete_bis.vue index e2ae8ada..dcfd70cc 100644 --- a/frontend/src/components/modals/confirmations/delete_bis.vue +++ b/frontend/src/components/modals/confirmations/delete_bis.vue @@ -31,7 +31,7 @@
    - +
    diff --git a/frontend/src/components/modals/confirmations/kick_from_team.vue b/frontend/src/components/modals/confirmations/kick_from_team.vue index 05d3d89e..473f74f7 100644 --- a/frontend/src/components/modals/confirmations/kick_from_team.vue +++ b/frontend/src/components/modals/confirmations/kick_from_team.vue @@ -30,7 +30,7 @@
    - +
    diff --git a/frontend/src/components/modals/confirmations/leave_team.vue b/frontend/src/components/modals/confirmations/leave_team.vue index d71e4b59..a60abaef 100644 --- a/frontend/src/components/modals/confirmations/leave_team.vue +++ b/frontend/src/components/modals/confirmations/leave_team.vue @@ -31,7 +31,7 @@
    - +
    diff --git a/frontend/src/components/team_bio.vue b/frontend/src/components/team_bio.vue index da85c2c3..d772a065 100644 --- a/frontend/src/components/team_bio.vue +++ b/frontend/src/components/team_bio.vue @@ -16,7 +16,7 @@
    -
    +
    diff --git a/frontend/src/components/team_member_card.vue b/frontend/src/components/team_member_card.vue index 3d50c1af..85e3f9f7 100644 --- a/frontend/src/components/team_member_card.vue +++ b/frontend/src/components/team_member_card.vue @@ -19,7 +19,7 @@ - + diff --git a/frontend/src/components/team_member_form.vue b/frontend/src/components/team_member_form.vue index fc342d17..461dccc8 100644 --- a/frontend/src/components/team_member_form.vue +++ b/frontend/src/components/team_member_form.vue @@ -88,7 +88,7 @@ export default class TeamMemberForm extends SavageAimMixin { get bisIcon(): string { const list = this.bisLists.find((bl: BISList) => bl.id === parseInt(this.bisListId, 10)) if (list != null) { - return list.job.name + return list.job.id } return '' } diff --git a/frontend/src/dataclasses/bis_list_modify.ts b/frontend/src/dataclasses/bis_list_modify.ts index 3889efd2..b792d4f4 100644 --- a/frontend/src/dataclasses/bis_list_modify.ts +++ b/frontend/src/dataclasses/bis_list_modify.ts @@ -1,10 +1,11 @@ // Slight variation on bis_list that is used for sending create / update requests // Done as a class instead of an interface to allow for functions and such import BISList from '@/interfaces/bis_list' +import { ImportResponse } from '@/interfaces/imports' export default class BISListModify { public id = -1 - public job_id = 'na' + public job_id = 'PLD' public bis_body_id = -1 public bis_bracelet_id = -1 @@ -72,4 +73,20 @@ export default class BISListModify { return newList } + + importBIS(data: ImportResponse): void { + this.job_id = data.job_id + this.bis_mainhand_id = data.mainhand + this.bis_offhand_id = data.offhand + this.bis_head_id = data.head + this.bis_body_id = data.body + this.bis_hands_id = data.hands + this.bis_legs_id = data.legs + this.bis_feet_id = data.feet + this.bis_earrings_id = data.earrings + this.bis_necklace_id = data.necklace + this.bis_bracelet_id = data.bracelet + this.bis_left_ring_id = data.left_ring + this.bis_right_ring_id = data.right_ring + } } diff --git a/frontend/src/views/character.vue b/frontend/src/views/character.vue index 6e51e3d8..c8b36b5b 100644 --- a/frontend/src/views/character.vue +++ b/frontend/src/views/character.vue @@ -83,7 +83,7 @@ - + From 00a23941498ff0fe2c747b1f5c8eaaf0182363ca Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 00:49:31 +0100 Subject: [PATCH 19/47] using job id as image name means I don't need convoluted icon code --- frontend/src/components/bis_list/details.vue | 22 +++----------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/bis_list/details.vue b/frontend/src/components/bis_list/details.vue index 88224ad7..bbead154 100644 --- a/frontend/src/components/bis_list/details.vue +++ b/frontend/src/components/bis_list/details.vue @@ -22,13 +22,12 @@
    -
    - Paladin Job Icon +

    {{ errors.job_id[0] }}

    @@ -84,26 +83,11 @@ export default class Details extends Vue { return this.$refs.jobPicker as HTMLSelectElement } - changeJobIcon(): void { + changeJob(): void { const selectedJob = (this.jobPicker.options[this.jobPicker.selectedIndex]).dataset.target as string // Handle the flag for the offhand this.$emit('job-change', selectedJob) - - this.setIcon(selectedJob) - } - - // On mount, run the changeJob icon function to update for edit pages - mounted(): void { - this.changeJobIcon() - } - - // Update icons on desktop and mobile view - setIcon(job: string): void { - const src = `${this.baseImgUrl}${job}.png` - const alt = `${job} job icon` - this.jobIcon.src = src - this.jobIcon.alt = alt } } From 8276fa4701d39f0c45261f2d2637330e5d44f995 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 01:23:30 +0100 Subject: [PATCH 20/47] Etro import is fully functioning as far as I can tell --- backend/api/views/etro.py | 25 ++++++--- frontend/src/components/bis_list/actions.vue | 55 ++++++++++++++----- .../src/components/bis_list/desktop_form.vue | 6 +- frontend/src/components/bis_list/form.vue | 25 ++++++--- .../src/components/bis_list/mobile_form.vue | 6 +- frontend/src/interfaces/imports.ts | 23 ++++++++ 6 files changed, 100 insertions(+), 40 deletions(-) create mode 100644 frontend/src/interfaces/imports.ts diff --git a/backend/api/views/etro.py b/backend/api/views/etro.py index d95e6c86..b69bbbb0 100644 --- a/backend/api/views/etro.py +++ b/backend/api/views/etro.py @@ -10,7 +10,7 @@ from rest_framework.request import Request from rest_framework.response import Response # local -from api.models import Gear, Job +from api.models import Gear # Map names of slots from etro to savage aim @@ -28,6 +28,8 @@ 'fingerL': 'left_ring', 'fingerR': 'right_ring', } +ARMOUR_SLOTS = {'head', 'body', 'hands', 'legs', 'feet'} +ACCESSORY_SLOTS = {'earrings', 'necklace', 'bracelet', 'left_ring', 'right_ring'} class EtroImport(APIView): @@ -79,16 +81,25 @@ def get(self, request: Request, id: str) -> Response: # Get the names of all the gear with the specified Item Levels gear_names = Gear.objects.filter(item_level__in=item_levels).values('name', 'id') - # Loop through the slots one final time, and get the gear id for that slot response = { - slot: self._get_gear_id(gear_names, item_name) - for slot, item_name in gear_details.items() + 'job_id': job_id, } - # Add the Job ID and display name - response['job_id'] = job_id - response['job_name'] = Job.objects.get(pk=job_id).display_name + + # Loop through the slots one final time, and get the gear id for that slot + for slot, item_name in gear_details.items(): + if slot in ARMOUR_SLOTS: + response[slot] = self._get_gear_id(gear_names.filter(has_armour=True), item_name) + elif slot in ACCESSORY_SLOTS: + response[slot] = self._get_gear_id(gear_names.filter(has_accessories=True), item_name) + else: + response[slot] = self._get_gear_id(gear_names.filter(has_weapon=True), item_name) + # Check for offhand if job_id != 'PLD': response['offhand'] = response['mainhand'] + # Also add item level status + response['min_il'] = min(*item_levels) + response['max_il'] = max(*item_levels) + return Response(response) diff --git a/frontend/src/components/bis_list/actions.vue b/frontend/src/components/bis_list/actions.vue index 4f19bb29..6f771203 100644 --- a/frontend/src/components/bis_list/actions.vue +++ b/frontend/src/components/bis_list/actions.vue @@ -3,18 +3,15 @@
    - - - - + - @@ -28,12 +25,15 @@ import { } from 'vue-property-decorator' import BISListModify from '@/dataclasses/bis_list_modify' import { CreateResponse, BISListErrors } from '@/interfaces/responses' +import { ImportResponse, ImportError } from '@/interfaces/imports' @Component export default class Actions extends Vue { @Prop() bisList!: BISListModify + importLoading = false + @Prop() method!: string @@ -60,11 +60,6 @@ export default class Actions extends Vue { return this.importPattern.exec(this.bisList.external_link || '') !== null } - @Watch('bisList.job_id', { deep: true }) - syncable(): boolean { - return this.bisList.job_id !== 'na' - } - // Save the data into a new bis list async save(): Promise { this.$emit('errors', {}) @@ -106,6 +101,36 @@ export default class Actions extends Vue { this.$notify({ text: `Error ${e} when attempting to create BIS List.`, type: 'is-danger' }) } } + + async etroImport(): Promise { + const url = this.etroImportUrl + if (url === null) return + this.importLoading = true + try { + const response = await fetch(url) + if (response.ok) { + // Handle the import + const data = await response.json() as ImportResponse + this.$emit('import-bis-data', data) + } + else { + const error = await response.json() as ImportError + this.$notify({ text: `Error while importing Etro gearset; ${error.message}`, type: 'is-danger' }) + } + } + catch (e) { + this.$notify({ text: `Error ${e} when attempting to import Etro data.`, type: 'is-danger' }) + } + finally { + this.importLoading = false + } + } + + get etroImportUrl(): string | null { + const match = this.importPattern.exec(this.bisList.external_link || '') + if (match === null) return null + return `/backend/api/import/etro/${match[1]}/` + } } diff --git a/frontend/src/components/bis_list/desktop_form.vue b/frontend/src/components/bis_list/desktop_form.vue index b8c5af5c..5ded61ea 100644 --- a/frontend/src/components/bis_list/desktop_form.vue +++ b/frontend/src/components/bis_list/desktop_form.vue @@ -8,7 +8,7 @@
    -
    +
    @@ -100,10 +100,6 @@ export default class BISListDesktopForm extends Vue { @Prop() url!: string - jobChange(selectedJob: string): void { - this.$emit('job-change', selectedJob) - } - updateMin(minIl: number): void { this.$emit('update-min-il', minIl) } diff --git a/frontend/src/components/bis_list/form.vue b/frontend/src/components/bis_list/form.vue index 78ac544c..8dd40a0e 100644 --- a/frontend/src/components/bis_list/form.vue +++ b/frontend/src/components/bis_list/form.vue @@ -8,13 +8,13 @@ :maxIl="maxIl" :method="method" :url="url" - v-on:job-change="jobChange" v-on:update-min-il="updateMinIl" v-on:update-max-il="updateMaxIl" v-on:error-code="emitErrorCode" v-on:errors="handleErrors" v-on:save="$emit('save')" v-on:close="$emit('close')" + v-on:import-bis-data="importBISData" v-if="renderDesktop" /> @@ -28,13 +28,13 @@ :method="method" :url="url" :simpleActions="!renderDesktop" - v-on:job-change="jobChange" v-on:update-min-il="updateMinIl" v-on:update-max-il="updateMaxIl" v-on:error-code="emitErrorCode" v-on:errors="handleErrors" v-on:save="$emit('save')" v-on:close="$emit('close')" + v-on:import-bis-data="importBISData" :class="[renderDesktop ? 'is-hidden-desktop' : '']" /> @@ -45,6 +45,7 @@ import { Component, Prop, Vue } from 'vue-property-decorator' import BISListDesktopForm from '@/components/bis_list/desktop_form.vue' import BISListMobileForm from '@/components/bis_list/mobile_form.vue' import BISListModify from '@/dataclasses/bis_list_modify' +import { ImportResponse } from '@/interfaces/imports' import { BISListErrors } from '@/interfaces/responses' @Component({ @@ -75,12 +76,6 @@ export default class BISListForm extends Vue { minIl = 580 - // Handle the events that change values - jobChange(selectedJob: string): void { - this.displayOffhand = selectedJob === 'paladin' - this.$forceUpdate() - } - updateMinIl(minIl: number): void { this.minIl = minIl } @@ -96,6 +91,20 @@ export default class BISListForm extends Vue { handleErrors(errors: BISListErrors): void { this.errors = errors } + + importBISData(data: ImportResponse): void { + if (data.min_il < this.minIl) this.minIl = data.min_il + if (data.max_il > this.maxIl) this.maxIl = data.max_il + Vue.nextTick(() => { + this.bisList.importBIS(data) + this.displayOffhand = data.job_id === 'PLD' + this.$forceUpdate() + }) + } + + mounted(): void { + this.displayOffhand = this.bisList.job_id === 'PLD' + } } diff --git a/frontend/src/components/bis_list/mobile_form.vue b/frontend/src/components/bis_list/mobile_form.vue index a806d5de..10520550 100644 --- a/frontend/src/components/bis_list/mobile_form.vue +++ b/frontend/src/components/bis_list/mobile_form.vue @@ -38,7 +38,7 @@
    -
    +
    @@ -121,10 +121,6 @@ export default class BISListMobileForm extends Vue { @Prop() url!: string - jobChange(selectedJob: string): void { - this.$emit('job-change', selectedJob) - } - updateMin(minIl: number): void { this.$emit('update-min-il', minIl) } diff --git a/frontend/src/interfaces/imports.ts b/frontend/src/interfaces/imports.ts new file mode 100644 index 00000000..3bae611e --- /dev/null +++ b/frontend/src/interfaces/imports.ts @@ -0,0 +1,23 @@ +export interface ImportError { + message: string +} + +export interface ImportResponse { + job_id: string + job_name: string + mainhand: number + offhand: number + head: number + body: number + hands: number + legs: number + feet: number + earrings: number + necklace: number + bracelet: number + left_ring: number + right_ring: number + + min_il: number + max_il: number +} From b9da29cee1e8854fa7aeefaa3f65529e8b5e080b Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 01:27:17 +0100 Subject: [PATCH 21/47] fixing actions --- backend/api/tests/test_loot.py | 100 ++++++++++++++++----------------- backend/api/views/etro.py | 2 +- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/backend/api/tests/test_loot.py b/backend/api/tests/test_loot.py index 8f4e22cb..45a74daf 100644 --- a/backend/api/tests/test_loot.py +++ b/backend/api/tests/test_loot.py @@ -234,7 +234,7 @@ def setUp(self): 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, { @@ -242,7 +242,7 @@ def setUp(self): 'character_name': self.team_lead.alias, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'sage', + 'job_icon_name': 'SGE', 'job_role': 'heal', }, ], @@ -255,14 +255,14 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'whitemage', + 'job_icon_name': 'WHM', 'job_role': 'heal', }, { 'bis_list_id': self.mt_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'dancer', + 'job_icon_name': 'DNC', 'job_role': 'dps', }, ], @@ -275,14 +275,14 @@ def setUp(self): 'bis_list_id': self.tl_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, { 'bis_list_id': self.tl_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'reaper', + 'job_icon_name': 'RPR', 'job_role': 'dps', }, ], @@ -296,7 +296,7 @@ def setUp(self): # 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', # 'current_gear_name': self.crafted.name, # 'current_gear_il': self.crafted.item_level, - # 'job_icon_name': 'paladin', + # 'job_icon_name': 'PLD', # 'job_role': 'tank', # }, # ], @@ -314,7 +314,7 @@ def setUp(self): # 'bis_list_id': self.tl_alt_bis.id, # 'current_gear_name': self.crafted.name, # 'current_gear_il': self.crafted.item_level, - # 'job_icon_name': 'paladin', + # 'job_icon_name': 'PLD', # 'job_role': 'tank', # }, # ], @@ -328,7 +328,7 @@ def setUp(self): 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, ], @@ -341,7 +341,7 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'dancer', + 'job_icon_name': 'DNC', 'job_role': 'dps', }, ], @@ -354,14 +354,14 @@ def setUp(self): 'bis_list_id': self.tl_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, { 'bis_list_id': self.tl_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'reaper', + 'job_icon_name': 'RPR', 'job_role': 'dps', }, ], @@ -375,7 +375,7 @@ def setUp(self): 'character_name': self.team_lead.alias, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'sage', + 'job_icon_name': 'SGE', 'job_role': 'heal', }, ], @@ -388,7 +388,7 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'whitemage', + 'job_icon_name': 'WHM', 'job_role': 'heal', }, ], @@ -407,7 +407,7 @@ def setUp(self): 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, ], @@ -420,7 +420,7 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'dancer', + 'job_icon_name': 'DNC', 'job_role': 'dps', }, ], @@ -433,14 +433,14 @@ def setUp(self): 'bis_list_id': self.tl_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, { 'bis_list_id': self.tl_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'reaper', + 'job_icon_name': 'RPR', 'job_role': 'dps', }, ], @@ -454,7 +454,7 @@ def setUp(self): 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, ], @@ -467,7 +467,7 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'dancer', + 'job_icon_name': 'DNC', 'job_role': 'dps', }, ], @@ -480,14 +480,14 @@ def setUp(self): 'bis_list_id': self.tl_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, { 'bis_list_id': self.tl_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'reaper', + 'job_icon_name': 'RPR', 'job_role': 'dps', }, ], @@ -501,7 +501,7 @@ def setUp(self): 'character_name': self.team_lead.alias, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'sage', + 'job_icon_name': 'SGE', 'job_role': 'heal', }, ], @@ -514,7 +514,7 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'whitemage', + 'job_icon_name': 'WHM', 'job_role': 'heal', }, ], @@ -533,7 +533,7 @@ def setUp(self): 'character_name': self.team_lead.alias, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'sage', + 'job_icon_name': 'SGE', 'job_role': 'heal', }, ], @@ -546,7 +546,7 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'whitemage', + 'job_icon_name': 'WHM', 'job_role': 'heal', }, ], @@ -565,7 +565,7 @@ def setUp(self): 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, ], @@ -578,7 +578,7 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'dancer', + 'job_icon_name': 'DNC', 'job_role': 'dps', }, ], @@ -591,14 +591,14 @@ def setUp(self): 'bis_list_id': self.tl_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, { 'bis_list_id': self.tl_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'reaper', + 'job_icon_name': 'RPR', 'job_role': 'dps', }, ], @@ -612,7 +612,7 @@ def setUp(self): 'character_name': self.team_lead.alias, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'sage', + 'job_icon_name': 'SGE', 'job_role': 'heal', }, ], @@ -625,7 +625,7 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'whitemage', + 'job_icon_name': 'WHM', 'job_role': 'heal', }, ], @@ -644,7 +644,7 @@ def setUp(self): 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, { @@ -652,7 +652,7 @@ def setUp(self): 'character_name': self.team_lead.alias, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'sage', + 'job_icon_name': 'SGE', 'job_role': 'heal', }, ], @@ -665,14 +665,14 @@ def setUp(self): 'bis_list_id': self.mt_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'whitemage', + 'job_icon_name': 'WHM', 'job_role': 'heal', }, { 'bis_list_id': self.mt_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'dancer', + 'job_icon_name': 'DNC', 'job_role': 'dps', }, ], @@ -685,14 +685,14 @@ def setUp(self): 'bis_list_id': self.tl_alt_bis.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', }, { 'bis_list_id': self.tl_alt_bis2.id, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, - 'job_icon_name': 'reaper', + 'job_icon_name': 'RPR', 'job_role': 'dps', }, ], @@ -704,14 +704,14 @@ def setUp(self): { 'member_id': self.mt_tm.pk, 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', 'requires': 3, }, { 'member_id': self.tl_tm.pk, 'character_name': self.team_lead.alias, - 'job_icon_name': 'sage', + 'job_icon_name': 'SGE', 'job_role': 'heal', 'requires': 2, }, @@ -723,13 +723,13 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, - 'job_icon_name': 'whitemage', + 'job_icon_name': 'WHM', 'job_role': 'heal', 'requires': 2, }, { 'bis_list_id': self.mt_alt_bis2.id, - 'job_icon_name': 'dancer', + 'job_icon_name': 'DNC', 'job_role': 'dps', 'requires': 3, }, @@ -741,13 +741,13 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', 'requires': 3, }, { 'bis_list_id': self.tl_alt_bis2.id, - 'job_icon_name': 'reaper', + 'job_icon_name': 'RPR', 'job_role': 'dps', 'requires': 3, }, @@ -760,14 +760,14 @@ def setUp(self): { 'member_id': self.mt_tm.pk, 'character_name': f'{self.main_tank.name} @ {self.main_tank.world}', - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', 'requires': 2, }, { 'member_id': self.tl_tm.pk, 'character_name': self.team_lead.alias, - 'job_icon_name': 'sage', + 'job_icon_name': 'SGE', 'job_role': 'heal', 'requires': 3, }, @@ -779,13 +779,13 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, - 'job_icon_name': 'whitemage', + 'job_icon_name': 'WHM', 'job_role': 'heal', 'requires': 3, }, { 'bis_list_id': self.mt_alt_bis2.id, - 'job_icon_name': 'dancer', + 'job_icon_name': 'DNC', 'job_role': 'dps', 'requires': 2, }, @@ -797,13 +797,13 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, - 'job_icon_name': 'paladin', + 'job_icon_name': 'PLD', 'job_role': 'tank', 'requires': 2, }, { 'bis_list_id': self.tl_alt_bis2.id, - 'job_icon_name': 'reaper', + 'job_icon_name': 'RPR', 'job_role': 'dps', 'requires': 2, }, diff --git a/backend/api/views/etro.py b/backend/api/views/etro.py index b69bbbb0..0df48184 100644 --- a/backend/api/views/etro.py +++ b/backend/api/views/etro.py @@ -2,7 +2,7 @@ Given an etro id, convert it into a format that uses Savage Aim ids """ # stdlib -from typing import Dict, Set, Tuple +from typing import Dict, Set # lib import coreapi import jellyfish From 1c42908ae5960d437ae54b21bcacafd38614b71b Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 01:38:05 +0100 Subject: [PATCH 22/47] passed character details down to the actions component this is so we can check if there are other bis lists of the same job --- frontend/src/components/bis_list/actions.vue | 4 ++++ frontend/src/components/bis_list/desktop_form.vue | 6 +++++- frontend/src/components/bis_list/form.vue | 6 ++++++ frontend/src/components/bis_list/mobile_form.vue | 6 +++++- frontend/src/views/edit_bis.vue | 5 ++--- frontend/src/views/new_bis.vue | 2 +- 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/bis_list/actions.vue b/frontend/src/components/bis_list/actions.vue index 6f771203..370021ac 100644 --- a/frontend/src/components/bis_list/actions.vue +++ b/frontend/src/components/bis_list/actions.vue @@ -24,6 +24,7 @@ import { Watch, } from 'vue-property-decorator' import BISListModify from '@/dataclasses/bis_list_modify' +import { CharacterDetails } from '@/interfaces/character' import { CreateResponse, BISListErrors } from '@/interfaces/responses' import { ImportResponse, ImportError } from '@/interfaces/imports' @@ -32,6 +33,9 @@ export default class Actions extends Vue { @Prop() bisList!: BISListModify + @Prop() + character!: CharacterDetails + importLoading = false @Prop() diff --git a/frontend/src/components/bis_list/desktop_form.vue b/frontend/src/components/bis_list/desktop_form.vue index 5ded61ea..bf08087f 100644 --- a/frontend/src/components/bis_list/desktop_form.vue +++ b/frontend/src/components/bis_list/desktop_form.vue @@ -30,7 +30,7 @@ - + @@ -66,6 +66,7 @@ import Current from '@/components/bis_list/current.vue' import Details from '@/components/bis_list/details.vue' import Filters from '@/components/bis_list/filters.vue' import BISListModify from '@/dataclasses/bis_list_modify' +import { CharacterDetails } from '@/interfaces/character' import { BISListErrors } from '@/interfaces/responses' @Component({ @@ -81,6 +82,9 @@ export default class BISListDesktopForm extends Vue { @Prop() bisList!: BISListModify + @Prop() + character!: CharacterDetails + @Prop() displayOffhand!: boolean diff --git a/frontend/src/components/bis_list/form.vue b/frontend/src/components/bis_list/form.vue index 8dd40a0e..eda4c85b 100644 --- a/frontend/src/components/bis_list/form.vue +++ b/frontend/src/components/bis_list/form.vue @@ -2,6 +2,7 @@
    - + @@ -76,6 +76,7 @@ import Current from '@/components/bis_list/current.vue' import Details from '@/components/bis_list/details.vue' import Filters from '@/components/bis_list/filters.vue' import BISListModify from '@/dataclasses/bis_list_modify' +import { CharacterDetails } from '@/interfaces/character' import { BISListErrors } from '@/interfaces/responses' @Component({ @@ -98,6 +99,9 @@ export default class BISListMobileForm extends Vue { @Prop() bisList!: BISListModify + @Prop() + character!: CharacterDetails + @Prop() displayOffhand!: boolean diff --git a/frontend/src/views/edit_bis.vue b/frontend/src/views/edit_bis.vue index 178e7fe5..ff700867 100644 --- a/frontend/src/views/edit_bis.vue +++ b/frontend/src/views/edit_bis.vue @@ -11,7 +11,7 @@
  • {{ breadcrumb }}
  • - + @@ -21,7 +21,6 @@ import { Component } from 'vue-property-decorator' import BISListForm from '@/components/bis_list/form.vue' import BISListModify from '@/dataclasses/bis_list_modify' import BISList from '@/interfaces/bis_list' -import { BISListErrors } from '@/interfaces/responses' import NewBIS from './new_bis.vue' @Component({ @@ -86,7 +85,7 @@ export default class EditBIS extends NewBIS { this.breadcrumb = this.bisList.display_name } - async postSave() { + async postSave(): Promise { await this.getList() this.updateBreadcrumb() } diff --git a/frontend/src/views/new_bis.vue b/frontend/src/views/new_bis.vue index 9440cec7..392abdc3 100644 --- a/frontend/src/views/new_bis.vue +++ b/frontend/src/views/new_bis.vue @@ -11,7 +11,7 @@
  • New
  • - + From 2fcc24cdc1b1490436107ef58e2e595bc1e74415 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 01:45:16 +0100 Subject: [PATCH 23/47] re-setting up syncable checks now that we have bislist data --- frontend/src/components/bis_list/actions.vue | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/bis_list/actions.vue b/frontend/src/components/bis_list/actions.vue index 370021ac..b8e327b9 100644 --- a/frontend/src/components/bis_list/actions.vue +++ b/frontend/src/components/bis_list/actions.vue @@ -3,7 +3,10 @@
    - + - +
    @@ -24,6 +30,7 @@ import { Watch, } from 'vue-property-decorator' import BISListModify from '@/dataclasses/bis_list_modify' +import BISList from '@/interfaces/bis_list' import { CharacterDetails } from '@/interfaces/character' import { CreateResponse, BISListErrors } from '@/interfaces/responses' import { ImportResponse, ImportError } from '@/interfaces/imports' @@ -64,6 +71,11 @@ export default class Actions extends Vue { return this.importPattern.exec(this.bisList.external_link || '') !== null } + @Watch('bisList.job_id', { deep: true }) + syncable(): boolean { + return this.character.bis_lists.some((list: BISList) => list.id !== this.bisList.id && list.job.id === this.bisList.job_id) + } + // Save the data into a new bis list async save(): Promise { this.$emit('errors', {}) From 6d531bfcd8ded85163620cd04b3cad7819fbbef6 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 02:50:10 +0100 Subject: [PATCH 24/47] in the process of loading current gear --- frontend/src/components/bis_list/actions.vue | 77 +++++++++++-------- .../components/modals/load_current_gear.vue | 59 ++++++++++++++ 2 files changed, 104 insertions(+), 32 deletions(-) create mode 100644 frontend/src/components/modals/load_current_gear.vue diff --git a/frontend/src/components/bis_list/actions.vue b/frontend/src/components/bis_list/actions.vue index b8e327b9..c1ed06a3 100644 --- a/frontend/src/components/bis_list/actions.vue +++ b/frontend/src/components/bis_list/actions.vue @@ -15,7 +15,7 @@ @@ -29,6 +29,7 @@ import { Vue, Watch, } from 'vue-property-decorator' +import LoadCurrentGear from '@/components/modals/load_current_gear.vue' import BISListModify from '@/dataclasses/bis_list_modify' import BISList from '@/interfaces/bis_list' import { CharacterDetails } from '@/interfaces/character' @@ -61,11 +62,21 @@ export default class Actions extends Vue { return this.method === 'POST' } + get etroImportUrl(): string | null { + const match = this.importPattern.exec(this.bisList.external_link || '') + if (match === null) return null + return `/backend/api/import/etro/${match[1]}/` + } + get saveText(): string { if (this.create) return 'Create' return 'Save' } + get syncableLists(): BISList[] { + return this.character.bis_lists.filter((list: BISList) => list.id !== this.bisList.id && list.job.id === this.bisList.job_id) + } + @Watch('bisList.external_link', { deep: true }) importable(): boolean { return this.importPattern.exec(this.bisList.external_link || '') !== null @@ -73,7 +84,39 @@ export default class Actions extends Vue { @Watch('bisList.job_id', { deep: true }) syncable(): boolean { - return this.character.bis_lists.some((list: BISList) => list.id !== this.bisList.id && list.job.id === this.bisList.job_id) + return this.syncableLists.length > 0 + } + + loadCurrent(): void { + this.$modal.show(LoadCurrentGear, { bisLists: this.syncableLists, loadBIS: this.loadGearFromBIS }) + } + + loadGearFromBIS(list: BISList): void { + console.log(list) + } + + async etroImport(): Promise { + const url = this.etroImportUrl + if (url === null) return + this.importLoading = true + try { + const response = await fetch(url) + if (response.ok) { + // Handle the import + const data = await response.json() as ImportResponse + this.$emit('import-bis-data', data) + } + else { + const error = await response.json() as ImportError + this.$notify({ text: `Error while importing Etro gearset; ${error.message}`, type: 'is-danger' }) + } + } + catch (e) { + this.$notify({ text: `Error ${e} when attempting to import Etro data.`, type: 'is-danger' }) + } + finally { + this.importLoading = false + } } // Save the data into a new bis list @@ -117,36 +160,6 @@ export default class Actions extends Vue { this.$notify({ text: `Error ${e} when attempting to create BIS List.`, type: 'is-danger' }) } } - - async etroImport(): Promise { - const url = this.etroImportUrl - if (url === null) return - this.importLoading = true - try { - const response = await fetch(url) - if (response.ok) { - // Handle the import - const data = await response.json() as ImportResponse - this.$emit('import-bis-data', data) - } - else { - const error = await response.json() as ImportError - this.$notify({ text: `Error while importing Etro gearset; ${error.message}`, type: 'is-danger' }) - } - } - catch (e) { - this.$notify({ text: `Error ${e} when attempting to import Etro data.`, type: 'is-danger' }) - } - finally { - this.importLoading = false - } - } - - get etroImportUrl(): string | null { - const match = this.importPattern.exec(this.bisList.external_link || '') - if (match === null) return null - return `/backend/api/import/etro/${match[1]}/` - } } diff --git a/frontend/src/components/modals/load_current_gear.vue b/frontend/src/components/modals/load_current_gear.vue new file mode 100644 index 00000000..b8e33cf7 --- /dev/null +++ b/frontend/src/components/modals/load_current_gear.vue @@ -0,0 +1,59 @@ + + + From 34c42e92ac020e5b311c8a210d4918974afff717 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 03:06:35 +0100 Subject: [PATCH 25/47] Load current data from alternative bis list --- frontend/src/components/bis_list/actions.vue | 2 +- frontend/src/components/bis_list/form.vue | 36 ++++++++++++++++++++ frontend/src/dataclasses/bis_list_modify.ts | 15 ++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/bis_list/actions.vue b/frontend/src/components/bis_list/actions.vue index c1ed06a3..11abd805 100644 --- a/frontend/src/components/bis_list/actions.vue +++ b/frontend/src/components/bis_list/actions.vue @@ -92,7 +92,7 @@ export default class Actions extends Vue { } loadGearFromBIS(list: BISList): void { - console.log(list) + this.$emit('import-current-data', list) } async etroImport(): Promise { diff --git a/frontend/src/components/bis_list/form.vue b/frontend/src/components/bis_list/form.vue index eda4c85b..78c3a25a 100644 --- a/frontend/src/components/bis_list/form.vue +++ b/frontend/src/components/bis_list/form.vue @@ -16,6 +16,7 @@ v-on:save="$emit('save')" v-on:close="$emit('close')" v-on:import-bis-data="importBISData" + v-on:import-current-data="importCurrentData" v-if="renderDesktop" /> @@ -37,6 +38,7 @@ v-on:save="$emit('save')" v-on:close="$emit('close')" v-on:import-bis-data="importBISData" + v-on:import-current-data="importCurrentData" :class="[renderDesktop ? 'is-hidden-desktop' : '']" /> @@ -47,7 +49,9 @@ import { Component, Prop, Vue } from 'vue-property-decorator' import BISListDesktopForm from '@/components/bis_list/desktop_form.vue' import BISListMobileForm from '@/components/bis_list/mobile_form.vue' import BISListModify from '@/dataclasses/bis_list_modify' +import BISList from '@/interfaces/bis_list' import { CharacterDetails } from '@/interfaces/character' +import Gear from '@/interfaces/gear' import { ImportResponse } from '@/interfaces/imports' import { BISListErrors } from '@/interfaces/responses' @@ -105,12 +109,44 @@ export default class BISListForm extends Vue { this.bisList.importBIS(data) this.displayOffhand = data.job_id === 'PLD' this.$forceUpdate() + this.$notify({ text: 'Successfully imported BIS Gear!', type: 'is-success' }) + }) + } + + importCurrentData(data: BISList): void { + // Calculate min and max item levels + const { minIl, maxIl } = this.calculateCurrentILRange(data) + if (minIl < this.minIl) this.minIl = minIl + if (maxIl > this.maxIl) this.maxIl = maxIl + Vue.nextTick(() => { + this.bisList.importCurrent(data) + this.$forceUpdate() + this.$notify({ text: 'Successfully imported Current Gear!', type: 'is-success' }) }) } mounted(): void { this.displayOffhand = this.bisList.job_id === 'PLD' } + + calculateCurrentILRange(data: BISList): { minIl: number, maxIl: number } { + const itemLevels = [ + data.current_mainhand.item_level, + data.current_offhand.item_level, + data.current_head.item_level, + data.current_body.item_level, + data.current_hands.item_level, + data.current_legs.item_level, + data.current_feet.item_level, + data.current_earrings.item_level, + data.current_necklace.item_level, + data.current_bracelet.item_level, + data.current_left_ring.item_level, + data.current_right_ring.item_level, + ] + + return { minIl: Math.min(...itemLevels), maxIl: Math.max(...itemLevels) } + } } diff --git a/frontend/src/dataclasses/bis_list_modify.ts b/frontend/src/dataclasses/bis_list_modify.ts index b792d4f4..1d01f375 100644 --- a/frontend/src/dataclasses/bis_list_modify.ts +++ b/frontend/src/dataclasses/bis_list_modify.ts @@ -89,4 +89,19 @@ export default class BISListModify { this.bis_left_ring_id = data.left_ring this.bis_right_ring_id = data.right_ring } + + importCurrent(data: BISList): void { + this.current_body_id = data.current_body.id + this.current_bracelet_id = data.current_bracelet.id + this.current_earrings_id = data.current_earrings.id + this.current_feet_id = data.current_feet.id + this.current_hands_id = data.current_hands.id + this.current_head_id = data.current_head.id + this.current_left_ring_id = data.current_left_ring.id + this.current_legs_id = data.current_legs.id + this.current_mainhand_id = data.current_mainhand.id + this.current_necklace_id = data.current_necklace.id + this.current_offhand_id = data.current_offhand.id + this.current_right_ring_id = data.current_right_ring.id + } } From d98b6e42773a36a59a8155db0bdd4a7cfd3d9155 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 03:20:27 +0100 Subject: [PATCH 26/47] Added tooltip on job icons for team bio displays --- frontend/src/components/modals/changelog.vue | 1 + frontend/src/components/team_bio.vue | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/modals/changelog.vue b/frontend/src/components/modals/changelog.vue index aee4ff10..4dc5c620 100644 --- a/frontend/src/components/modals/changelog.vue +++ b/frontend/src/components/modals/changelog.vue @@ -40,6 +40,7 @@
    expand_more Minor Changes expand_more

    Minor changes to the breadcrumbs in the BIS Create / Edit pages.

    The Greed section of the Loot Manager page now uses popups for Characters with more than one BIS List.

    +

    Job icons on Team boxes now have a tooltip with the name / alias of the associated Character.

    diff --git a/frontend/src/components/team_bio.vue b/frontend/src/components/team_bio.vue index d772a065..d2b0513c 100644 --- a/frontend/src/components/team_bio.vue +++ b/frontend/src/components/team_bio.vue @@ -16,7 +16,11 @@
    -
    +
    + + + +
    From 6ae3b7d8c1c9d8f951a9ee294cea68fdf2c96401 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 03:26:44 +0100 Subject: [PATCH 27/47] improving layout of the join a team page --- frontend/src/components/modals/changelog.vue | 1 + frontend/src/views/team/join.vue | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/modals/changelog.vue b/frontend/src/components/modals/changelog.vue index 4dc5c620..31d60774 100644 --- a/frontend/src/components/modals/changelog.vue +++ b/frontend/src/components/modals/changelog.vue @@ -41,6 +41,7 @@

    Minor changes to the breadcrumbs in the BIS Create / Edit pages.

    The Greed section of the Loot Manager page now uses popups for Characters with more than one BIS List.

    Job icons on Team boxes now have a tooltip with the name / alias of the associated Character.

    +

    Minor layout improvements in the Join a Team page.

    diff --git a/frontend/src/views/team/join.vue b/frontend/src/views/team/join.vue index 4b8ea6ce..7fea0bbd 100644 --- a/frontend/src/views/team/join.vue +++ b/frontend/src/views/team/join.vue @@ -14,13 +14,20 @@
    -
    - +
    +
    +
    You have been invited to join;
    +
    +
    +
    + +
    +
    -
    Select your Character and BIS List to join!
    +
    Select your Character and BIS List
    From 23b2edcf2c0cfbfb4384e7cd10c1aff1edfbb148 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 03:27:01 +0100 Subject: [PATCH 28/47] linting vue --- frontend/src/components/bis_list/form.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/components/bis_list/form.vue b/frontend/src/components/bis_list/form.vue index 78c3a25a..744c55c4 100644 --- a/frontend/src/components/bis_list/form.vue +++ b/frontend/src/components/bis_list/form.vue @@ -51,7 +51,6 @@ import BISListMobileForm from '@/components/bis_list/mobile_form.vue' import BISListModify from '@/dataclasses/bis_list_modify' import BISList from '@/interfaces/bis_list' import { CharacterDetails } from '@/interfaces/character' -import Gear from '@/interfaces/gear' import { ImportResponse } from '@/interfaces/imports' import { BISListErrors } from '@/interfaces/responses' From 456c02f3a93d304da09e01a29ed2353c84dad825 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 04:05:13 +0100 Subject: [PATCH 29/47] Separated the history table into its own component file --- backend/api/serializers/loot.py | 2 +- backend/api/tests/test_loot.py | 4 +- frontend/src/components/loot/history.vue | 319 +++++++++++++++++++ frontend/src/components/modals/changelog.vue | 1 + frontend/src/views/team/loot.vue | 266 +--------------- 5 files changed, 337 insertions(+), 255 deletions(-) create mode 100644 frontend/src/components/loot/history.vue diff --git a/backend/api/serializers/loot.py b/backend/api/serializers/loot.py index 26582814..a0602c1f 100644 --- a/backend/api/serializers/loot.py +++ b/backend/api/serializers/loot.py @@ -92,7 +92,7 @@ def validate_obtained(self, obtained): Ensure we're not recording loot for the future """ if obtained > datetime.today().date(): - raise serializers.ValidationError('Cannot record loot for a date in the future.') + raise serializers.ValidationError('Cannot record Loot for a date in the future.') return obtained diff --git a/backend/api/tests/test_loot.py b/backend/api/tests/test_loot.py index 45a74daf..0d673232 100644 --- a/backend/api/tests/test_loot.py +++ b/backend/api/tests/test_loot.py @@ -1054,7 +1054,7 @@ def test_create_400(self): Greed not bool: 'Must be a valid boolean.' Obtained not sent: 'This field is required.' Obtained not valid date: 'Date has wrong format. Use one of these formats instead: YYYY-MM-DD.' - Obtained in the future: 'Cannot record loot for a date in the future.' + Obtained in the future: 'Cannot record Loot for a date in the future.' """ url = reverse('api:loot_collection', kwargs={'team_id': self.team.pk}) user = self._get_user() @@ -1089,7 +1089,7 @@ def test_create_400(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) content = response.json() self.assertEqual(content['member_id'], ['Please select a Character that is a member of the Team.']) - self.assertEqual(content['obtained'], ['Cannot record loot for a date in the future.']) + self.assertEqual(content['obtained'], ['Cannot record Loot for a date in the future.']) def test_create_with_bis(self): """ diff --git a/frontend/src/components/loot/history.vue b/frontend/src/components/loot/history.vue new file mode 100644 index 00000000..b9679174 --- /dev/null +++ b/frontend/src/components/loot/history.vue @@ -0,0 +1,319 @@ + + + + + diff --git a/frontend/src/components/modals/changelog.vue b/frontend/src/components/modals/changelog.vue index 31d60774..5211fc64 100644 --- a/frontend/src/components/modals/changelog.vue +++ b/frontend/src/components/modals/changelog.vue @@ -40,6 +40,7 @@
    expand_more Minor Changes expand_more

    Minor changes to the breadcrumbs in the BIS Create / Edit pages.

    The Greed section of the Loot Manager page now uses popups for Characters with more than one BIS List.

    +

    The forms in the Loot History section of the Loot Manager page have been moved to the top of their related sections to prevent large amounts of unnecessary scrolling as History tables fill up.

    Job icons on Team boxes now have a tooltip with the name / alias of the associated Character.

    Minor layout improvements in the Join a Team page.

    diff --git a/frontend/src/views/team/loot.vue b/frontend/src/views/team/loot.vue index b3fa5d94..1e48cf45 100644 --- a/frontend/src/views/team/loot.vue +++ b/frontend/src/views/team/loot.vue @@ -94,191 +94,14 @@
    -
    -
    - -
    - Loot History -
    -
    - expand_more -
    -
    - -
    -
    +
    @@ -289,7 +112,7 @@ import dayjs from 'dayjs' import { Component } from 'vue-property-decorator' import GreedRaidItemBox from '@/components/loot/greed_raid_item_box.vue' import GreedTomeItemBox from '@/components/loot/greed_tome_item_box.vue' -import DeleteLoot from '@/components/modals/confirmations/delete_loot.vue' +import History from '@/components/loot/history.vue' import ItemDropdown from '@/components/item_dropdown.vue' import NeedRaidItemBox from '@/components/loot/need_raid_item_box.vue' import NeedTomeItemBox from '@/components/loot/need_tome_item_box.vue' @@ -315,6 +138,7 @@ import SavageAimMixin from '@/mixins/savage_aim_mixin' components: { GreedRaidItemBox, GreedTomeItemBox, + History, ItemDropdown, NeedRaidItemBox, NeedTomeItemBox, @@ -324,16 +148,6 @@ import SavageAimMixin from '@/mixins/savage_aim_mixin' export default class TeamLoot extends SavageAimMixin { bisLootErrors: LootBISCreateErrors = {} - createData = { - item: 'na', - member: -1, - obtained: '', - } - - createLootErrors: LootCreateErrors = {} - - historyShown = false - displayItem = 'na' loaded = false @@ -358,18 +172,6 @@ export default class TeamLoot extends SavageAimMixin { document.title = `Loot Tracker - ${this.team.name} - Savage Aim` } - deleteEntries(items: Loot[]): void { - // Prompt deletion first before sending an api request (we'll use a modal instead of javascript alerts) - this.$modal.show(DeleteLoot, { team: this.team, items }, { }, { closed: () => { this.fetchData(true) } }) - } - - deleteMultipleEntries(): void { - const checkboxes = this.$refs.lootDeleteCheckbox as HTMLInputElement[] - const ids = checkboxes.filter((check: HTMLInputElement) => check.checked).map((check: HTMLInputElement) => parseInt(check.dataset.id!, 10)) as number[] - const items = this.loot.history.filter((entry: Loot) => ids.includes(entry.id)) - this.deleteEntries(items) - } - async fetchData(reload: boolean): Promise { // Load the loot data from the API try { @@ -448,9 +250,9 @@ export default class TeamLoot extends SavageAimMixin { this.fetchData(true) } - async sendLoot(data: LootPacket): Promise { + async sendLoot(data: LootPacket): Promise { // Send a request to create loot entry without affecting bis lists - if (this.requesting) return + if (this.requesting) return null this.requesting = true const body = JSON.stringify(data) try { @@ -466,11 +268,10 @@ export default class TeamLoot extends SavageAimMixin { if (response.ok) { await this.fetchData(true) this.$notify({ text: 'Loot updated!', type: 'is-success' }) - this.createData = { obtained: '', member: -1, item: 'na' } } else { super.handleError(response.status) - this.createLootErrors = (await response.json() as LootCreateErrors) + return await response.json() as LootCreateErrors } } catch (e) { @@ -479,6 +280,7 @@ export default class TeamLoot extends SavageAimMixin { finally { this.requesting = false } + return null } async sendLootWithBis(data: LootWithBISPacket): Promise { @@ -514,36 +316,6 @@ export default class TeamLoot extends SavageAimMixin { this.requesting = false } } - - // Hide / Show the History body - toggleHistory(): void { - const icon = this.$refs.historyIcon as Element - const history = this.$refs.history as Element - if (this.historyShown) { - this.historyShown = false - icon.innerHTML = 'expand_more' - } - else { - this.historyShown = true - icon.innerHTML = 'expand_less' - } - history.classList.toggle('is-hidden') - } - - trackExtraLoot(greed: boolean): void { - this.createLootErrors = {} - if (this.createData.obtained === '') { - this.createLootErrors.obtained = ['Please enter a date.'] - return - } - const data = { - member_id: this.createData.member, - obtained: this.createData.obtained, - item: this.createData.item, - greed, - } - this.sendLoot(data) - } } @@ -577,17 +349,7 @@ export default class TeamLoot extends SavageAimMixin { margin-left: 1.25rem; } -.mobile-history li:not(:last-child) { - margin-bottom: 0.75rem; - padding-bottom: 0.75rem; - border-bottom: 2px solid #17181c; -} - .greed-box { position: relative; } - -.delete-cell { - width: 0; -} From 37548a8165d047d85701056a3b2afcc4d6abb805 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 04:12:29 +0100 Subject: [PATCH 30/47] Improving changelog layout and messages --- frontend/src/components/modals/changelog.vue | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/modals/changelog.vue b/frontend/src/components/modals/changelog.vue index 5211fc64..54c52fc0 100644 --- a/frontend/src/components/modals/changelog.vue +++ b/frontend/src/components/modals/changelog.vue @@ -12,15 +12,7 @@

    {{ version }}

    -
    expand_more FFXIV 6.1.1 expand_more
    -

    - Added the following Gear for the release of 6.1.1; -

      -
    • Ultimate of the Heavens; Item Level 605 Weapons
    • -
    -

    - -
    expand_more Massive BIS Lists Updates expand_more
    +
    expand_more BIS Lists Expansion Update expand_more

    The limit of one BIS List per Job has finally been removed! You can now have as many BIS Lists as you want per Job, allowing you to keep historical lists as you advance the tiers, or manage two current lists per Job for the current Tier, the options are endless!

    You can also give each list a name, to help differentiate different BIS Lists of the same Job. The name will default to the name of the Job.

    @@ -36,13 +28,21 @@

  • Imports may not be perfect as to avoid maintaining a map for different names in the website, it compares names of Gear between Savage Aim and Etro and chooses the closest name.
  • +

    To help prevent over-population of pages, the Greed section of the Loot Manager page now uses popups to assign loot to a Greed BIS List instead of displaying all of the Lists for each Character directly on the page itself.

    expand_more Minor Changes expand_more
    -

    Minor changes to the breadcrumbs in the BIS Create / Edit pages.

    -

    The Greed section of the Loot Manager page now uses popups for Characters with more than one BIS List.

    -

    The forms in the Loot History section of the Loot Manager page have been moved to the top of their related sections to prevent large amounts of unnecessary scrolling as History tables fill up.

    +

    Minor changes to the display of breadcrumbs in the BIS Create / Edit pages.

    Job icons on Team boxes now have a tooltip with the name / alias of the associated Character.

    -

    Minor layout improvements in the Join a Team page.

    +

    Minor design improvements in the Join a Team page.

    +

    The forms in the Loot History section of the Loot Manager page have been moved to the top of their related sections to prevent large amounts of unnecessary scrolling as History tables fill up.

    + +
    expand_more Database Additions expand_more
    +

    + Added the following Gear for the release of 6.11; +

      +
    • Ultimate of the Heavens; Item Level 605 Weapons
    • +
    +

    From 93d547d97c9607bbdc0e01b85ddc79dea4291141 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 14:20:18 +0100 Subject: [PATCH 31/47] Fixed offhand issue Using v-on:listeners to just bubble everything up to the top form --- .../src/components/bis_list/desktop_form.vue | 12 ++---------- frontend/src/components/bis_list/details.vue | 5 +++-- frontend/src/components/bis_list/form.vue | 17 ++++++++++++----- .../src/components/bis_list/mobile_form.vue | 12 ++---------- 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/frontend/src/components/bis_list/desktop_form.vue b/frontend/src/components/bis_list/desktop_form.vue index bf08087f..28843de4 100644 --- a/frontend/src/components/bis_list/desktop_form.vue +++ b/frontend/src/components/bis_list/desktop_form.vue @@ -8,7 +8,7 @@ -
    +
    @@ -19,7 +19,7 @@ - + @@ -103,14 +103,6 @@ export default class BISListDesktopForm extends Vue { @Prop() url!: string - - updateMin(minIl: number): void { - this.$emit('update-min-il', minIl) - } - - updateMax(maxIl: number): void { - this.$emit('update-max-il', maxIl) - } } diff --git a/frontend/src/components/bis_list/details.vue b/frontend/src/components/bis_list/details.vue index bbead154..8e07ac21 100644 --- a/frontend/src/components/bis_list/details.vue +++ b/frontend/src/components/bis_list/details.vue @@ -23,7 +23,7 @@
    @@ -84,9 +84,10 @@ export default class Details extends Vue { } changeJob(): void { - const selectedJob = (this.jobPicker.options[this.jobPicker.selectedIndex]).dataset.target as string + const selectedJob = (this.jobPicker.options[this.jobPicker.selectedIndex]).value as string // Handle the flag for the offhand + console.log('change-job', selectedJob) this.$emit('job-change', selectedJob) } } diff --git a/frontend/src/components/bis_list/form.vue b/frontend/src/components/bis_list/form.vue index 744c55c4..db022526 100644 --- a/frontend/src/components/bis_list/form.vue +++ b/frontend/src/components/bis_list/form.vue @@ -9,8 +9,9 @@ :maxIl="maxIl" :method="method" :url="url" - v-on:update-min-il="updateMinIl" - v-on:update-max-il="updateMaxIl" + v-on:job-change="jobChange" + v-on:update-min="updateMinIl" + v-on:update-max="updateMaxIl" v-on:error-code="emitErrorCode" v-on:errors="handleErrors" v-on:save="$emit('save')" @@ -31,8 +32,9 @@ :method="method" :url="url" :simpleActions="!renderDesktop" - v-on:update-min-il="updateMinIl" - v-on:update-max-il="updateMaxIl" + v-on:job-change="jobChange" + v-on:update-min="updateMinIl" + v-on:update-max="updateMaxIl" v-on:error-code="emitErrorCode" v-on:errors="handleErrors" v-on:save="$emit('save')" @@ -85,6 +87,11 @@ export default class BISListForm extends Vue { minIl = 580 + jobChange(selectedJob: string): void { + console.log('displayOffhand', selectedJob === 'PLD') + this.displayOffhand = selectedJob === 'PLD' + } + updateMinIl(minIl: number): void { this.minIl = minIl } @@ -106,7 +113,7 @@ export default class BISListForm extends Vue { if (data.max_il > this.maxIl) this.maxIl = data.max_il Vue.nextTick(() => { this.bisList.importBIS(data) - this.displayOffhand = data.job_id === 'PLD' + this.jobChange(data.job_id) this.$forceUpdate() this.$notify({ text: 'Successfully imported BIS Gear!', type: 'is-success' }) }) diff --git a/frontend/src/components/bis_list/mobile_form.vue b/frontend/src/components/bis_list/mobile_form.vue index 6fcd1187..2787166b 100644 --- a/frontend/src/components/bis_list/mobile_form.vue +++ b/frontend/src/components/bis_list/mobile_form.vue @@ -32,13 +32,13 @@
    - +
    -
    +
    @@ -125,14 +125,6 @@ export default class BISListMobileForm extends Vue { @Prop() url!: string - updateMin(minIl: number): void { - this.$emit('update-min-il', minIl) - } - - updateMax(maxIl: number): void { - this.$emit('update-max-il', maxIl) - } - // Method toggle for the tabs showBIS(): void { this.showNone() From 60ba4d1f371525b402d5887ea83b5a9e115dcfb9 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 14:43:17 +0100 Subject: [PATCH 32/47] Tests for the etro import view --- backend/api/tests/test_etro.py | 61 ++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 backend/api/tests/test_etro.py diff --git a/backend/api/tests/test_etro.py b/backend/api/tests/test_etro.py new file mode 100644 index 00000000..42020560 --- /dev/null +++ b/backend/api/tests/test_etro.py @@ -0,0 +1,61 @@ +from io import StringIO +from django.core.management import call_command +from django.urls import reverse +from rest_framework import status +from api.models import Gear +from .test_base import SavageAimTestCase + + +class EtroImport(SavageAimTestCase): + """ + Test the Etro Import view to ensure it works as we expect + + Currently using https://etro.gg/gearset/48e6d8c0-afd8-4857-a320-70528884ac86 for testing + """ + + def setUp(self): + """ + Call the Gear seed command to prepopulate the DB + """ + call_command('gear_seed', stdout=StringIO()) + + def test_import(self): + """ + List Gears from the API, ensure same order as in DB in general + """ + url = reverse('api:etro_import', kwargs={'id': '48e6d8c0-afd8-4857-a320-70528884ac86'}) + user = self._get_user() + self.client.force_authenticate(user) + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + # Build an expected data packet + expected = { + 'job_id': 'DNC', + 'mainhand': Gear.objects.get(name='Ultimate of the Heavens').pk, + 'offhand': Gear.objects.get(name='Ultimate of the Heavens').pk, + 'head': Gear.objects.get(name='Asphodelos', has_armour=True).pk, + 'body': Gear.objects.get(name='Asphodelos', has_armour=True).pk, + 'hands': Gear.objects.get(name='Asphodelos', has_armour=True).pk, + 'earrings': Gear.objects.get(name='Asphodelos', has_armour=True).pk, + 'left_ring': Gear.objects.get(name='Asphodelos', has_armour=True).pk, + 'legs': Gear.objects.get(name='Augmented Radiant Host').pk, + 'feet': Gear.objects.get(name='Augmented Radiant Host').pk, + 'necklace': Gear.objects.get(name='Augmented Radiant Host').pk, + 'bracelet': Gear.objects.get(name='Augmented Radiant Host').pk, + 'right_ring': Gear.objects.get(name='Augmented Radiant Host').pk, + 'min_il': 600, + 'max_il': 605, + } + self.assertDictEqual(response.json(), expected) + + def test_import_400(self): + """ + Send a request with an invalid ID, check we get a proper error + """ + url = reverse('api:etro_import', kwargs={'id': 'abcde'}) + user = self._get_user() + self.client.force_authenticate(user) + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(response.json()['message'], '404 Not Found') From 72da844e13818a0cbe6fdfae1995ac7c94d2dcde Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 15:39:34 +0100 Subject: [PATCH 33/47] add bis list name to the greed sections --- backend/api/models/bis_list.py | 10 +++++++++ backend/api/serializers/bis_list.py | 11 +--------- backend/api/tests/test_loot.py | 33 +++++++++++++++++++++++++++++ backend/api/views/loot.py | 5 +++++ frontend/src/interfaces/loot.ts | 1 + 5 files changed, 50 insertions(+), 10 deletions(-) diff --git a/backend/api/models/bis_list.py b/backend/api/models/bis_list.py index 41d7c151..43fb49cf 100644 --- a/backend/api/models/bis_list.py +++ b/backend/api/models/bis_list.py @@ -100,6 +100,16 @@ def item_level(self): self.current_right_ring.item_level, ]) / 12 + @property + def display_name(self) -> str: + """ + Same as Character, use the list name if one exists otherwise use the job name + """ + if self.name != '': + return self.name + else: + return self.job.display_name + @staticmethod def needs_accessory_augments(gear_name: str) -> models.QuerySet: """ diff --git a/backend/api/serializers/bis_list.py b/backend/api/serializers/bis_list.py index febd6c83..d3f98eea 100644 --- a/backend/api/serializers/bis_list.py +++ b/backend/api/serializers/bis_list.py @@ -64,21 +64,12 @@ class BISListSerializer(serializers.ModelSerializer): current_right_ring = GearSerializer() item_level = serializers.IntegerField() job = JobSerializer() - display_name = serializers.SerializerMethodField() + display_name = serializers.CharField() class Meta: exclude = ['owner'] model = BISList - def get_display_name(self, obj: BISList) -> str: - """ - Same as Character, use the list name if one exists otherwise use the job name - """ - if obj.name != '': - return obj.name - else: - return obj.job.display_name - class BISListModifySerializer(serializers.ModelSerializer): offhand_is_mainhand = True diff --git a/backend/api/tests/test_loot.py b/backend/api/tests/test_loot.py index 0d673232..ef601384 100644 --- a/backend/api/tests/test_loot.py +++ b/backend/api/tests/test_loot.py @@ -253,6 +253,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, + 'bis_list_name': self.mt_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'WHM', @@ -260,6 +261,7 @@ def setUp(self): }, { 'bis_list_id': self.mt_alt_bis2.id, + 'bis_list_name': self.mt_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'DNC', @@ -273,6 +275,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, + 'bis_list_name': self.tl_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'PLD', @@ -280,6 +283,7 @@ def setUp(self): }, { 'bis_list_id': self.tl_alt_bis2.id, + 'bis_list_name': self.tl_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'RPR', @@ -312,6 +316,7 @@ def setUp(self): # 'greed_lists': [ # { # 'bis_list_id': self.tl_alt_bis.id, + # 'bis_list_name': self.tl_alt_bis.display_name, # 'current_gear_name': self.crafted.name, # 'current_gear_il': self.crafted.item_level, # 'job_icon_name': 'PLD', @@ -339,6 +344,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis2.id, + 'bis_list_name': self.mt_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'DNC', @@ -352,6 +358,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, + 'bis_list_name': self.tl_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'PLD', @@ -359,6 +366,7 @@ def setUp(self): }, { 'bis_list_id': self.tl_alt_bis2.id, + 'bis_list_name': self.tl_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'RPR', @@ -386,6 +394,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, + 'bis_list_name': self.mt_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'WHM', @@ -418,6 +427,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis2.id, + 'bis_list_name': self.mt_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'DNC', @@ -431,6 +441,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, + 'bis_list_name': self.tl_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'PLD', @@ -438,6 +449,7 @@ def setUp(self): }, { 'bis_list_id': self.tl_alt_bis2.id, + 'bis_list_name': self.tl_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'RPR', @@ -465,6 +477,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis2.id, + 'bis_list_name': self.mt_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'DNC', @@ -478,6 +491,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, + 'bis_list_name': self.tl_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'PLD', @@ -485,6 +499,7 @@ def setUp(self): }, { 'bis_list_id': self.tl_alt_bis2.id, + 'bis_list_name': self.tl_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'RPR', @@ -512,6 +527,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, + 'bis_list_name': self.mt_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'WHM', @@ -544,6 +560,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, + 'bis_list_name': self.mt_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'WHM', @@ -576,6 +593,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis2.id, + 'bis_list_name': self.mt_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'DNC', @@ -589,6 +607,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, + 'bis_list_name': self.tl_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'PLD', @@ -596,6 +615,7 @@ def setUp(self): }, { 'bis_list_id': self.tl_alt_bis2.id, + 'bis_list_name': self.tl_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'RPR', @@ -623,6 +643,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, + 'bis_list_name': self.mt_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'WHM', @@ -663,6 +684,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, + 'bis_list_name': self.mt_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'WHM', @@ -670,6 +692,7 @@ def setUp(self): }, { 'bis_list_id': self.mt_alt_bis2.id, + 'bis_list_name': self.mt_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'DNC', @@ -683,6 +706,7 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, + 'bis_list_name': self.tl_alt_bis.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'PLD', @@ -690,6 +714,7 @@ def setUp(self): }, { 'bis_list_id': self.tl_alt_bis2.id, + 'bis_list_name': self.tl_alt_bis2.display_name, 'current_gear_name': self.crafted.name, 'current_gear_il': self.crafted.item_level, 'job_icon_name': 'RPR', @@ -723,12 +748,14 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, + 'bis_list_name': self.mt_alt_bis.display_name, 'job_icon_name': 'WHM', 'job_role': 'heal', 'requires': 2, }, { 'bis_list_id': self.mt_alt_bis2.id, + 'bis_list_name': self.mt_alt_bis2.display_name, 'job_icon_name': 'DNC', 'job_role': 'dps', 'requires': 3, @@ -741,12 +768,14 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, + 'bis_list_name': self.tl_alt_bis.display_name, 'job_icon_name': 'PLD', 'job_role': 'tank', 'requires': 3, }, { 'bis_list_id': self.tl_alt_bis2.id, + 'bis_list_name': self.tl_alt_bis2.display_name, 'job_icon_name': 'RPR', 'job_role': 'dps', 'requires': 3, @@ -779,12 +808,14 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.mt_alt_bis.id, + 'bis_list_name': self.mt_alt_bis.display_name, 'job_icon_name': 'WHM', 'job_role': 'heal', 'requires': 3, }, { 'bis_list_id': self.mt_alt_bis2.id, + 'bis_list_name': self.mt_alt_bis2.display_name, 'job_icon_name': 'DNC', 'job_role': 'dps', 'requires': 2, @@ -797,12 +828,14 @@ def setUp(self): 'greed_lists': [ { 'bis_list_id': self.tl_alt_bis.id, + 'bis_list_name': self.tl_alt_bis.display_name, 'job_icon_name': 'PLD', 'job_role': 'tank', 'requires': 2, }, { 'bis_list_id': self.tl_alt_bis2.id, + 'bis_list_name': self.tl_alt_bis2.display_name, 'job_icon_name': 'RPR', 'job_role': 'dps', 'requires': 2, diff --git a/backend/api/views/loot.py b/backend/api/views/loot.py index 9df0036f..3c3b7c93 100644 --- a/backend/api/views/loot.py +++ b/backend/api/views/loot.py @@ -87,6 +87,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: for greed_list in greed_lists: current_gear = getattr(greed_list, f'current_{slot}') data['greed_lists'].append({ + 'bis_list_name': greed_list.display_name, 'bis_list_id': greed_list.id, 'current_gear_name': current_gear.name, 'current_gear_il': current_gear.item_level, @@ -132,6 +133,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: # for greed_list in greed_lists: # current_gear = getattr(greed_list, 'current_offhand') # data['greed_lists'].append({ + # 'bis_list_name': greed_list.display_name, # 'bis_list_id': greed_list.id, # 'current_gear_name': current_gear.name, # 'current_gear_il': current_gear.item_level, @@ -188,6 +190,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: current_gear = greed_list.current_left_ring data['greed_lists'].append({ + 'bis_list_name': greed_list.display_name, 'bis_list_id': greed_list.id, 'current_gear_name': current_gear.name, 'current_gear_il': current_gear.item_level, @@ -223,6 +226,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: } for greed_list in greed_lists: data['greed_lists'].append({ + 'bis_list_name': greed_list.display_name, 'bis_list_id': greed_list.id, 'job_icon_name': greed_list.job.id, 'job_role': greed_list.job.role, @@ -256,6 +260,7 @@ def _get_gear_data(self, obj: Team) -> Dict[str, List[Dict[str, str]]]: } for greed_list in greed_lists: data['greed_lists'].append({ + 'bis_list_name': greed_list.display_name, 'bis_list_id': greed_list.id, 'job_icon_name': greed_list.job.id, 'job_role': greed_list.job.role, diff --git a/frontend/src/interfaces/loot.ts b/frontend/src/interfaces/loot.ts index 528aad50..ef032b5f 100644 --- a/frontend/src/interfaces/loot.ts +++ b/frontend/src/interfaces/loot.ts @@ -2,6 +2,7 @@ import Team from './team' export interface GreedItem { bis_list_id: number + bis_list_name: string current_gear_name: string current_gear_il: number job_icon_name: string From 39ce03fa5248517627ab67f3ef5dbe661bfa5223 Mon Sep 17 00:00:00 2001 From: freyamade Date: Sat, 14 May 2022 16:18:57 +0100 Subject: [PATCH 34/47] Moving greed to use modals to keep the UI a little neater --- frontend/src/components/bis_list/details.vue | 1 - frontend/src/components/bis_list/form.vue | 1 - .../components/loot/greed_character_entry.vue | 75 +++++++++++++++++++ .../components/loot/greed_raid_item_box.vue | 69 ----------------- .../src/components/loot/greed_raid_modal.vue | 58 ++++++++++++++ .../components/loot/greed_tome_item_box.vue | 72 ------------------ .../src/components/loot/greed_tome_modal.vue | 59 +++++++++++++++ frontend/src/views/team/loot.vue | 17 +---- 8 files changed, 196 insertions(+), 156 deletions(-) create mode 100644 frontend/src/components/loot/greed_character_entry.vue delete mode 100644 frontend/src/components/loot/greed_raid_item_box.vue create mode 100644 frontend/src/components/loot/greed_raid_modal.vue delete mode 100644 frontend/src/components/loot/greed_tome_item_box.vue create mode 100644 frontend/src/components/loot/greed_tome_modal.vue diff --git a/frontend/src/components/bis_list/details.vue b/frontend/src/components/bis_list/details.vue index 8e07ac21..f17ab2e9 100644 --- a/frontend/src/components/bis_list/details.vue +++ b/frontend/src/components/bis_list/details.vue @@ -87,7 +87,6 @@ export default class Details extends Vue { const selectedJob = (this.jobPicker.options[this.jobPicker.selectedIndex]).value as string // Handle the flag for the offhand - console.log('change-job', selectedJob) this.$emit('job-change', selectedJob) } } diff --git a/frontend/src/components/bis_list/form.vue b/frontend/src/components/bis_list/form.vue index db022526..190cfc57 100644 --- a/frontend/src/components/bis_list/form.vue +++ b/frontend/src/components/bis_list/form.vue @@ -88,7 +88,6 @@ export default class BISListForm extends Vue { minIl = 580 jobChange(selectedJob: string): void { - console.log('displayOffhand', selectedJob === 'PLD') this.displayOffhand = selectedJob === 'PLD' } diff --git a/frontend/src/components/loot/greed_character_entry.vue b/frontend/src/components/loot/greed_character_entry.vue new file mode 100644 index 00000000..d915717f --- /dev/null +++ b/frontend/src/components/loot/greed_character_entry.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/frontend/src/components/loot/greed_raid_item_box.vue b/frontend/src/components/loot/greed_raid_item_box.vue deleted file mode 100644 index 120a8f8c..00000000 --- a/frontend/src/components/loot/greed_raid_item_box.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - - - diff --git a/frontend/src/components/loot/greed_raid_modal.vue b/frontend/src/components/loot/greed_raid_modal.vue new file mode 100644 index 00000000..5e54ae1a --- /dev/null +++ b/frontend/src/components/loot/greed_raid_modal.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/frontend/src/components/loot/greed_tome_item_box.vue b/frontend/src/components/loot/greed_tome_item_box.vue deleted file mode 100644 index 07a5af41..00000000 --- a/frontend/src/components/loot/greed_tome_item_box.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - - - diff --git a/frontend/src/components/loot/greed_tome_modal.vue b/frontend/src/components/loot/greed_tome_modal.vue new file mode 100644 index 00000000..dbd8ad57 --- /dev/null +++ b/frontend/src/components/loot/greed_tome_modal.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/frontend/src/views/team/loot.vue b/frontend/src/views/team/loot.vue index 1e48cf45..83e62bdd 100644 --- a/frontend/src/views/team/loot.vue +++ b/frontend/src/views/team/loot.vue @@ -84,11 +84,8 @@

    Below are the people that need the chosen item for any other BIS they have, grouped by character.

    Clicking the button beside anyone will add a Loot entry, and update their BIS List accordingly (where possible).

    - -