Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions backend/api/management/commands/dev_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ def handle(self, *args, **options):
User.objects.all().delete()

print('Creating Users')
user1 = User.objects.create_superuser(username='devuser', password='password')
user2 = User.objects.create_superuser(username='devuser2', password='password')
user1 = User.objects.create_superuser(username='devuser', password='password', first_name='Dev User 1')
user2 = User.objects.create_superuser(username='devuser2', password='password', first_name='Dev User 2')

print('Creating Characters')
char1 = models.Character.objects.create(
models.Character.objects.create(
avatar_url='https://placehold.co/96/2E53A5/F3F3EC.png?text=1',
lodestone_id='1',
name='Character 1',
Expand Down Expand Up @@ -68,16 +68,16 @@ def handle(self, *args, **options):
has_weapon=True,
)
raid_gear = models.Gear.objects.get(
item_level=tier.max_item_level-5,
item_level=tier.max_item_level - 5,
name=tier.raid_gear_name,
has_weapon=False,
)
tome_gear = models.Gear.objects.get(
item_level=tier.max_item_level-5,
item_level=tier.max_item_level - 5,
name=tier.tome_gear_name,
)
crafted_gear = models.Gear.objects.get(
item_level=tier.max_item_level-25,
item_level=tier.max_item_level - 25,
has_weapon=True,
has_armour=True,
has_accessories=True,
Expand Down
92 changes: 71 additions & 21 deletions backend/api/tests/test_lodestone_gear_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,82 @@ def tearDown(self):
def test_import(self):
"""
Test Plan;
- Import Eira and ensure her gear matches what I currently had equipped
- Create Gear entries for some ARR items
- Import Niseras and ensure her gear matches what I currently had equipped
"""
url = reverse('api:lodestone_gear_import', kwargs={'character_id': '22909725', 'expected_job': 'GNB'})
ironworks = Gear.objects.create(
name='Augmented Ironworks',
item_level=130,
has_armour=True,
has_accessories=True,
has_weapon=True,
).pk
koga = Gear.objects.create(
name='Koga',
item_level=90,
has_armour=True,
has_accessories=False,
has_weapon=False,
).pk
azeyma = Gear.objects.create(
name="Azeyma's",
item_level=560,
has_armour=False,
has_accessories=True,
has_weapon=False,
).pk
brass = Gear.objects.create(
name='Aetherial Brass',
item_level=16,
has_armour=False,
has_accessories=True,
has_weapon=False,
).pk
dawn = Gear.objects.create(
name='Dawn',
item_level=18,
has_armour=False,
has_accessories=True,
has_weapon=False,
).pk
new = Gear.objects.create(
name='Brand New',
item_level=30,
has_armour=False,
has_accessories=True,
has_weapon=False,
).pk
weathered = Gear.objects.create(
name='Weathered',
item_level=5,
has_armour=False,
has_accessories=True,
has_weapon=False,
).pk

url = reverse('api:lodestone_gear_import', kwargs={'character_id': '42935425', 'expected_job': 'NIN'})
user = self._get_user()
self.client.force_authenticate(user)
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK, response.json())

# Build an expected data packet
expected = {
'job_id': 'GNB',
'mainhand': Gear.objects.get(name='Archeo Kingdom').pk,
'offhand': Gear.objects.get(name='Archeo Kingdom').pk,
'head': Gear.objects.get(name='Dark Horse Champion', has_armour=True).pk,
'body': Gear.objects.get(name='Augmented Quetzalli', has_armour=True).pk,
'hands': Gear.objects.get(name='Quetzalli', has_armour=True).pk,
'legs': Gear.objects.get(name='Dark Horse Champion', has_armour=True).pk,
'feet': Gear.objects.get(name='Augmented Quetzalli', has_armour=True).pk,
'earrings': Gear.objects.get(name='Dark Horse Champion', has_accessories=True).pk,
'necklace': Gear.objects.get(name='Dark Horse Champion', has_accessories=True).pk,
'bracelet': Gear.objects.get(name='Augmented Quetzalli', has_accessories=True).pk,
'right_ring': Gear.objects.get(name='Augmented Quetzalli', has_accessories=True).pk,
'left_ring': Gear.objects.get(name='Dark Horse Champion', has_accessories=True).pk,
'min_il': 710,
'max_il': 730,
'job_id': 'NIN',
'mainhand': ironworks,
'offhand': ironworks,
'head': koga,
'body': ironworks,
'hands': koga,
'legs': ironworks,
'feet': koga,
'earrings': azeyma,
'necklace': brass,
'bracelet': dawn,
'right_ring': new,
'left_ring': weathered,
'min_il': 5,
'max_il': 560,
}
self.maxDiff = None
self.assertDictEqual(response.json(), expected)
Expand Down Expand Up @@ -130,10 +181,9 @@ def test_import_400_and_404(self):
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

# Job ID doesn't match gear
url = reverse('api:lodestone_gear_import', kwargs={'character_id': '22909725', 'expected_job': 'SAM'})
url = reverse('api:lodestone_gear_import', kwargs={'character_id': '22909725', 'expected_job': 'MNK'})
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_406_NOT_ACCEPTABLE)
self.assertEqual(
response.json()['message'],
'Couldn\'t import Gear from Lodestone. Gear was expected to be for "SAM", but "GNB" was found.',
self.assertTrue(
'Couldn\'t import Gear from Lodestone. Gear was expected to be for "MNK"' in response.json()['message'],
)
4 changes: 2 additions & 2 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ cryptography==43.0.3
daphne==3.0.2
defusedxml==0.7.1
Deprecated==1.2.13
Django==4.2.16
Django==4.2.17
django-allauth==0.47.0
django-auto-prefetch==1.9.0
djangorestframework==3.15.2
Expand All @@ -37,7 +37,7 @@ incremental==24.7.2
inflection==0.5.1
itypes==1.2.0
jellyfish==0.9.0
Jinja2==3.1.4
Jinja2==3.1.5
jsonschema==4.17.3
kombu==5.2.3
MarkupSafe==2.1.1
Expand Down
13 changes: 7 additions & 6 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"match-sorter": "^6.3.1",
"microtip": "^0.2.2",
"multi-range-slider-vue": "^1.1.4",
"nanoid": "^3.3.8",
"nouislider": "^15.7.0",
"vue": "^2.6.11",
"vue-class-component": "^7.2.3",
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/loot/greed_character_entry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ export default class GreedCharacterEntry extends Vue {
@Prop()
userHasPermission!: boolean

save(list: GreedItem): void {
save(list: GreedItem | null): void {
// A main level function to determine how we save. The modal type can no longer make the determination for us
// Some items cannot be saved with an update, even if they are displayed using the raid modal
if (this.item.indexOf('tome') !== -1 || this.item === 'mount') {
if (this.item.indexOf('tome') !== -1 || this.item === 'mount' || list == null) {
// We cannot run an update but we do want to save them
this.saveWithoutUpdate()
}
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/loot/greed_raid_modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
</div>
</div>
</a>
<div class="divider">OR</div>
<button class="button is-info is-fullwidth" @click="() => { select(null) }">Give Item to Character</button>
</div>
</div>
</template>
Expand All @@ -45,9 +47,9 @@ export default class GreedRaidModal extends Vue {
entry!: GreedGear

@Prop()
save!: (list: GreedItem) => void
save!: (list: GreedItem | null) => void

select(list: GreedItem): void {
select(list: GreedItem | null): void {
this.save(list)
this.$emit('close')
}
Expand Down
15 changes: 9 additions & 6 deletions frontend/src/components/modals/changelog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
</div>
</div>
<div class="card-content content">
<h2 class="has-text-primary subtitle">{{ version }} - Happy New Year!!</h2>
<div class="divider"><i class="material-icons icon">expand_more</i> Bugfixes <i class="material-icons icon">expand_more</i></div>
<p>Worked out some edgecase issues with the Loot Solver. If you run into any weirdness with your Team's Loot Solver, please let me know!</p>

<div class="divider"><i class="material-icons icon">expand_more</i> Developer QoL <i class="material-icons icon">expand_more</i></div>
<p>Ever wanted to try running SavageAim locally and messing around with it? Well the README in the GitHub repo just got a whole lot more helpful, and there's now even a command to setup your local database automatically!</p>
<h2 class="has-text-primary subtitle">{{ version }}</h2>
<div class="divider"><i class="material-icons icon">expand_more</i> Loot Solver Greed Improvements <i class="material-icons icon">expand_more</i></div>
<p>
Made it so that when people have Greed BIS Lists, you can still generically assign items to them without updating one of their BIS Lists if the item is not relevant.
<ul>
<li>For example, currently, if a WHM weapon drops from a fourth fight, and the person who gets it has Greed BIS Lists, but none for WHM, the only way to track the item was to track it manually via the form in the History section.</li>
<li>Now there is a generic "Give Item to Character" button even if they have Greed lists, to give them an item that a Character obtained without it being relevant to their Greed lists.</li>
</ul>
</p>
</div>
</div>
</template>
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/modals/per_fight_member_select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@
</div>
</div>

<!-- If the member has no bis list just give a big button -->
<button v-if="entry.greed_lists.length === 0" class="button is-info is-fullwidth" @click="() => { chooseGreed(entry, null) }">Select This Character</button>
<!-- Generic "give item to this character" button -->
<div class="divider" v-if="entry.greed_lists.length > 0">OR</div>
<button class="button is-info is-fullwidth" @click="() => { chooseGreed(entry, null) }">Give Item to Character</button>
</div>
</a>
</template>
Expand Down
Loading