Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 676ff961ed | |||
| b40b58f866 |
@@ -79,15 +79,15 @@ export type MainLedgerResponseTypeEnum = typeof MainLedgerResponseTypeEnum[keyof
|
|||||||
|
|
||||||
export interface RuleBookResponse {
|
export interface RuleBookResponse {
|
||||||
'characterId': number;
|
'characterId': number;
|
||||||
'ruleSets': { [key: string]: RuleSetResponse; };
|
'rules': { [key: string]: RuleResponse; };
|
||||||
}
|
}
|
||||||
export interface RuleResponse {
|
export interface RuleClauseResponse {
|
||||||
'rate': RuleResponseRateEnum;
|
'rate': RuleClauseResponseRateEnum;
|
||||||
'fromLedgerId'?: string;
|
'fromLedgerId'?: string;
|
||||||
'toLedgerId'?: string;
|
'toLedgerId'?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RuleResponseRateEnum = {
|
export const RuleClauseResponseRateEnum = {
|
||||||
None: 'NONE',
|
None: 'NONE',
|
||||||
Value: 'VALUE',
|
Value: 'VALUE',
|
||||||
JitaBuy: 'JITA_BUY',
|
JitaBuy: 'JITA_BUY',
|
||||||
@@ -95,13 +95,13 @@ export const RuleResponseRateEnum = {
|
|||||||
EveEstimate: 'EVE_ESTIMATE',
|
EveEstimate: 'EVE_ESTIMATE',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type RuleResponseRateEnum = typeof RuleResponseRateEnum[keyof typeof RuleResponseRateEnum];
|
export type RuleClauseResponseRateEnum = typeof RuleClauseResponseRateEnum[keyof typeof RuleClauseResponseRateEnum];
|
||||||
|
|
||||||
export interface RuleSetResponse {
|
export interface RuleResponse {
|
||||||
'rules': Array<RuleResponse>;
|
'rules': Array<RuleClauseResponse>;
|
||||||
}
|
}
|
||||||
export interface SetCharacterRuleBookRequest {
|
export interface SetCharacterRuleBookRequest {
|
||||||
'ruleSets': { [key: string]: RuleSetResponse; };
|
'rules': { [key: string]: RuleResponse; };
|
||||||
}
|
}
|
||||||
export interface UpdateCombinedLedgerRequest {
|
export interface UpdateCombinedLedgerRequest {
|
||||||
'name': string;
|
'name': string;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {Character, CharacterLabel, useCharactersStore} from "@/characters";
|
|||||||
import {useRoute} from "vue-router";
|
import {useRoute} from "vue-router";
|
||||||
import {ref, watch, watchEffect} from "vue";
|
import {ref, watch, watchEffect} from "vue";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {activityTypes, findByCharacterId, RuleBook, RuleSetInput, setCharacterRuleBook} from "@/rules";
|
import {activityTypes, findByCharacterId, RuleBook, RuleInput, setCharacterRuleBook} from "@/rules";
|
||||||
|
|
||||||
const {findById: findCharacterById} = useCharactersStore();
|
const {findById: findCharacterById} = useCharactersStore();
|
||||||
const character = ref<Character>();
|
const character = ref<Character>();
|
||||||
@@ -50,7 +50,7 @@ watch(useRoute(), async route => {
|
|||||||
<div v-if="ruleBook" class="flex-col">
|
<div v-if="ruleBook" class="flex-col">
|
||||||
<div class="flex-col grow border-b-1" v-for="activityType in activityTypes" :key="activityType.key">
|
<div class="flex-col grow border-b-1" v-for="activityType in activityTypes" :key="activityType.key">
|
||||||
<span>{{ activityType.name }}</span>
|
<span>{{ activityType.name }}</span>
|
||||||
<RuleSetInput v-model="ruleBook.ruleSets[activityType.key]" />
|
<RuleInput v-model="ruleBook.rules[activityType.key]" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import {RuleClauseResponse} from "@/generated/mammon";
|
||||||
|
import {computed} from "vue";
|
||||||
|
import {isMain, Ledger, LedgerSelect, systemLedger, useLedgersStore} from "@/ledger";
|
||||||
|
import {ratesTypes} from "@/rules/rules.ts";
|
||||||
|
|
||||||
|
const rule = defineModel<RuleClauseResponse>();
|
||||||
|
|
||||||
|
const ledgersStore = useLedgersStore();
|
||||||
|
const {findById} = ledgersStore;
|
||||||
|
const ledgers = computed<Ledger[]>(() => [systemLedger, ...ledgersStore.ledgers.filter(isMain)]);
|
||||||
|
|
||||||
|
const ledgerComputed = (key: 'fromLedgerId' | 'toLedgerId') => computed<Ledger>({
|
||||||
|
get: () => rule.value && rule.value[key] ? findById(rule.value[key]) ?? systemLedger : systemLedger,
|
||||||
|
set: value => {
|
||||||
|
if (value) {
|
||||||
|
rule.value = {...rule.value, [key]: value.ledgerId.length ? value.ledgerId : undefined}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const fromLedger = ledgerComputed('fromLedgerId')
|
||||||
|
const toLedger = ledgerComputed('toLedgerId')
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
From:
|
||||||
|
<LedgerSelect class="me-2 grow" v-model="fromLedger" :ledgers="ledgers" />
|
||||||
|
To:
|
||||||
|
<LedgerSelect class="me-2 grow" v-model="toLedger" :ledgers="ledgers" />
|
||||||
|
At:
|
||||||
|
<select class="me-2 grow" v-model="rule.rate">
|
||||||
|
<option v-for="rateType in ratesTypes" :key="rateType.key" :value="rateType.key">{{ rateType.name }}</option>
|
||||||
|
</select>
|
||||||
|
</template>
|
||||||
+55
-27
@@ -1,37 +1,65 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
import {RuleResponse} from "@/generated/mammon";
|
import {RuleClauseResponse, RuleClauseResponseRateEnum, RuleResponse} from "@/generated/mammon";
|
||||||
import {computed} from "vue";
|
import RuleClauseInput from "@/rules/RuleClauseInput.vue";
|
||||||
import {isMain, Ledger, LedgerSelect, systemLedger, useLedgersStore} from "@/ledger";
|
import {computed, useTemplateRef} from "vue";
|
||||||
import {ratesTypes} from "@/rules/rules.ts";
|
import {Bars4Icon, PlusIcon, TrashIcon} from '@heroicons/vue/24/outline';
|
||||||
|
import {useSortable} from "@vueuse/integrations/useSortable";
|
||||||
|
|
||||||
const rule = defineModel<RuleResponse>();
|
const rule = defineModel<RuleResponse>();
|
||||||
|
const rules = computed<RuleClauseResponse[]>({
|
||||||
const ledgersStore = useLedgersStore();
|
get: () => rule.value && rule.value.rules ? rule.value.rules : [],
|
||||||
const {findById} = ledgersStore;
|
set: value => rule.value = {rules: value}
|
||||||
const ledgers = computed<Ledger[]>(() => [systemLedger, ...ledgersStore.ledgers.filter(isMain)]);
|
|
||||||
|
|
||||||
const ledgerComputed = (key: 'fromLedgerId' | 'toLedgerId') => computed<Ledger>({
|
|
||||||
get: () => rule.value && rule.value[key] ? findById(rule.value[key]) ?? systemLedger : systemLedger,
|
|
||||||
set: value => {
|
|
||||||
if (value) {
|
|
||||||
rule.value = {...rule.value, [key]: value.ledgerId.length ? value.ledgerId : undefined}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const fromLedger = ledgerComputed('fromLedgerId')
|
const addRule = () => {
|
||||||
const toLedger = ledgerComputed('toLedgerId')
|
rules.value = [...rules.value, {rate: RuleClauseResponseRateEnum.None}]
|
||||||
|
}
|
||||||
|
|
||||||
|
const setRule = (index: number, rule?: RuleClauseResponse) => {
|
||||||
|
if (!rule) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rules.value = rules.value.with(index, rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeRule = (index: number) => {
|
||||||
|
rules.value = rules.value.toSpliced(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortableContainer = useTemplateRef('sortable-container')
|
||||||
|
useSortable(sortableContainer, rules, { handle: '.sortable-handle'});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
From:
|
<div class="flex-col">
|
||||||
<LedgerSelect class="me-2 grow" v-model="fromLedger" :ledgers="ledgers" />
|
<div ref="sortable-container" class="flex-col">
|
||||||
To:
|
<div class="flex items-end gap-2 mt-2" v-for="(rule, index) in rules" :key="index">
|
||||||
<LedgerSelect class="me-2 grow" v-model="toLedger" :ledgers="ledgers" />
|
<span class="sortable-handle flex">
|
||||||
At:
|
<Bars4Icon class="w-6"/>
|
||||||
<select class="me-2 grow" v-model="rule.rate">
|
</span>
|
||||||
<option v-for="rateType in ratesTypes" :key="rateType.key" :value="rateType.key">{{ rateType.name }}</option>
|
<RuleClauseInput :modelValue="rule" @update:modelValue="v => setRule(index, v)" />
|
||||||
</select>
|
<button class="btn-icon" @click="removeRule(index)"><TrashIcon /></button>
|
||||||
</template>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end mb-2 mt-2">
|
||||||
|
<button class="btn-icon" @click="addRule"><PlusIcon /></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.sortable-handle {
|
||||||
|
@apply cursor-grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-chosen {
|
||||||
|
@apply cursor-grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-chosen .sortable-handle {
|
||||||
|
@apply cursor-grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
|
|
||||||
import {RuleResponse, RuleResponseRateEnum, RuleSetResponse} from "@/generated/mammon";
|
|
||||||
import RuleInput from "@/rules/RuleInput.vue";
|
|
||||||
import {computed, useTemplateRef} from "vue";
|
|
||||||
import {Bars4Icon, PlusIcon, TrashIcon} from '@heroicons/vue/24/outline';
|
|
||||||
import {useSortable} from "@vueuse/integrations/useSortable";
|
|
||||||
|
|
||||||
const ruleSet = defineModel<RuleSetResponse>();
|
|
||||||
const rules = computed<RuleResponse[]>({
|
|
||||||
get: () => ruleSet.value && ruleSet.value.rules ? ruleSet.value.rules : [],
|
|
||||||
set: value => ruleSet.value = {rules: value}
|
|
||||||
})
|
|
||||||
|
|
||||||
const addRule = () => {
|
|
||||||
rules.value = [...rules.value, {rate: RuleResponseRateEnum.None}]
|
|
||||||
}
|
|
||||||
|
|
||||||
const setRule = (index: number, rule?: RuleResponse) => {
|
|
||||||
if (!rule) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rules.value = rules.value.with(index, rule)
|
|
||||||
}
|
|
||||||
|
|
||||||
const removeRule = (index: number) => {
|
|
||||||
rules.value = rules.value.toSpliced(index, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortableContainer = useTemplateRef('sortable-container')
|
|
||||||
useSortable(sortableContainer, rules, { handle: '.sortable-handle'});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex-col">
|
|
||||||
<div ref="sortable-container" class="flex-col">
|
|
||||||
<div class="flex items-end gap-2 mt-2" v-for="(rule, index) in rules" :key="index">
|
|
||||||
<span class="sortable-handle flex">
|
|
||||||
<Bars4Icon class="w-6"/>
|
|
||||||
</span>
|
|
||||||
<RuleInput :modelValue="rule" @update:modelValue="v => setRule(index, v)" />
|
|
||||||
<button class="btn-icon" @click="removeRule(index)"><TrashIcon /></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex justify-end mb-2 mt-2">
|
|
||||||
<button class="btn-icon" @click="addRule"><PlusIcon /></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
.sortable-handle {
|
|
||||||
@apply cursor-grab;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sortable-chosen {
|
|
||||||
@apply cursor-grabbing;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sortable-chosen .sortable-handle {
|
|
||||||
@apply cursor-grabbing;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
export * from "./rules";
|
export * from "./rules";
|
||||||
|
|
||||||
export {default as RuleSetInput} from './RuleSetInput.vue';
|
export {default as RuleInput} from './RuleInput.vue';
|
||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
import {ruleBookControllerApi} from "@/mammon";
|
import {ruleBookControllerApi} from "@/mammon";
|
||||||
import {RuleBookResponse, RuleResponseRateEnum, RuleSetResponse} from "@/generated/mammon";
|
import {RuleBookResponse, RuleClauseResponseRateEnum, RuleResponse} from "@/generated/mammon";
|
||||||
|
|
||||||
export const activityTypes = {
|
export const activityTypes = {
|
||||||
itemBought: {key: "ITEM_BOUGHT", name: "Item Bought"},
|
itemBought: {key: "ITEM_BOUGHT", name: "Item Bought"},
|
||||||
@@ -10,7 +10,7 @@ export const activityTypes = {
|
|||||||
|
|
||||||
export type Activity = { key: ActivityType, name: string }
|
export type Activity = { key: ActivityType, name: string }
|
||||||
export type ActivityType = typeof activityTypes[keyof typeof activityTypes]['key'];
|
export type ActivityType = typeof activityTypes[keyof typeof activityTypes]['key'];
|
||||||
export type RuleBook = RuleBookResponse & { ruleSets: { [key: ActivityType]: RuleSetResponse; } }
|
export type RuleBook = RuleBookResponse & { rules: { [key: ActivityType]: RuleResponse; } }
|
||||||
|
|
||||||
export const ratesTypes = {
|
export const ratesTypes = {
|
||||||
None: {key: "NONE", name: "0 ISK"},
|
None: {key: "NONE", name: "0 ISK"},
|
||||||
@@ -20,11 +20,11 @@ export const ratesTypes = {
|
|||||||
EveEstimate: {key: "EVE_ESTIMATE", name: "Eve Estimate"},
|
EveEstimate: {key: "EVE_ESTIMATE", name: "Eve Estimate"},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type Rate = { key: RuleResponseRateEnum, name: string }
|
export type Rate = { key: RuleClauseResponseRateEnum, name: string }
|
||||||
|
|
||||||
export const findByCharacterId = (characterId: number): Promise<RuleBook> => ruleBookControllerApi.findByCharacterId(characterId)
|
export const findByCharacterId = (characterId: number): Promise<RuleBook> => ruleBookControllerApi.findByCharacterId(characterId)
|
||||||
.then(response => response.data)
|
.then(response => response.data)
|
||||||
.catch(() => ({characterId, ruleSets: {}}));
|
.catch(() => ({characterId, rules: {}}));
|
||||||
|
|
||||||
export const setCharacterRuleBook = (characterId: number, ruleBook: RuleBook): Promise<RuleBook> => ruleBookControllerApi.setCharacterRuleBook(characterId, ruleBook)
|
export const setCharacterRuleBook = (characterId: number, ruleBook: RuleBook): Promise<RuleBook> => ruleBookControllerApi.setCharacterRuleBook(characterId, ruleBook)
|
||||||
.then(response => response.data);
|
.then(response => response.data);
|
||||||
Reference in New Issue
Block a user