@dcrackel/hematournamentui 1.0.712 → 1.0.713
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +7 -7
- package/.storybook/main.js +3 -1
- package/README.md +30 -0
- package/package.json +96 -96
- package/prettier.config.js +16 -16
- package/src/main.js +1 -1
- package/src/mocks/getDEBouts-TableOf128.js +37 -37
- package/src/mocks/getDEBouts-TableOf64.js +35 -35
- package/src/stories/Atoms/Input/BaseInput.test.js +97 -97
- package/src/stories/Atoms/Input/BaseInput.vue +149 -149
- package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.stories.js +23 -23
- package/src/stories/Molecules/Indicators/MissingHemaRatingsId/MissingHemaRatingsId.vue +35 -35
- package/src/stories/Molecules/Indicators/RegistrationStatus/RegistrationStatus.vue +30 -30
- package/src/stories/Molecules/Menus/HoverActions/HoverActions.test.js +138 -0
- package/src/stories/Molecules/Menus/HoverActions/HoverActions.vue +212 -0
- package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.stories.js +6 -0
- package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.test.js +18 -18
- package/src/stories/Molecules/Modals/DirectorModal/DirectorModal.vue +1 -1
- package/src/stories/Organisms/Cards/BoutCard/BoutCard.vue +5 -1
- package/src/stories/Organisms/Cards/BoutCard/Variants/BoutCardActive/BoutCardActive.vue +19 -10
- package/src/stories/Organisms/Cards/BoutCard/Variants/BoutCardInactive/BoutCardInactive.vue +11 -7
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.stories.js +33 -33
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.test.js +45 -45
- package/src/stories/Organisms/Cards/BracketDirectorAssignmentCard/BracketDirectorAssignmentCard.vue +103 -103
- package/src/stories/Organisms/Cards/Director/DirectorCard.test.js +82 -0
- package/src/stories/Organisms/Cards/Director/DirectorCard.vue +32 -51
- package/src/stories/Organisms/Cards/EditBout/EditBout.test.js +51 -51
- package/src/stories/Organisms/Cards/EventCard/EventCard.test.js +106 -106
- package/src/stories/Organisms/Cards/FencerCard/FencerCard.vue +298 -298
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.stories.js +77 -60
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.test.js +144 -143
- package/src/stories/Organisms/Cards/TableauBoutCard/TableauBoutCard.vue +289 -256
- package/src/stories/Organisms/Cards/TableauFencerCard/TableauFencerCard.stories.js +69 -69
- package/src/stories/Organisms/Cards/TableauFencerCard/TableauFencerCard.vue +80 -80
- package/src/stories/Organisms/Cards/WaitlistFencerCard/WaitlistFencerCard.vue +153 -153
- package/src/stories/Organisms/ComplexInputs/DropDown/DropDownMenu.vue +4 -0
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.stories.js +31 -31
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.test.js +109 -109
- package/src/stories/Organisms/ComplexInputs/ImageCropper/ImageCropper.vue +192 -192
- package/src/stories/Organisms/Containers/Tableau/Tableau.stories.js +1 -0
- package/src/stories/Organisms/Containers/Tableau/Tableau.test.js +247 -204
- package/src/stories/Organisms/Containers/Tableau/Tableau.vue +89 -15
- package/src/stories/Organisms/Containers/Tableau/components/BracketDirectorAssignmentPanel.test.js +29 -29
- package/src/stories/Organisms/Containers/Tableau/components/BracketDirectorAssignmentPanel.vue +46 -46
- package/src/stories/Organisms/Containers/Tableau/components/TableauSvgOverlay.test.js +21 -21
- package/src/stories/Organisms/Containers/Tableau/components/TableauSvgOverlay.vue +39 -39
- package/src/stories/Organisms/Containers/Tableau/layout/TableauLayoutEngine.js +145 -145
- package/src/stories/Organisms/Containers/Tableau/layout/TableauLayoutEngine.test.js +64 -64
- package/src/stories/Organisms/Containers/Tableau/plannedAssignments.js +36 -57
- package/src/stories/Organisms/Containers/Tableau/plannedAssignments.test.js +101 -65
- package/src/stories/Organisms/Containers/TableauColumn/TableauColumn.vue +14 -1
- package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.stories.js +52 -52
- package/src/stories/Organisms/Wizards/EditEventWizard/BasicEventInfo/BasicEventInfo.vue +10 -3
- package/src/stories/Organisms/Wizards/EditEventWizard/DirectElimination/DirectElimination.vue +226 -226
- package/src/stories/Organisms/Wizards/EditEventWizard/DirectEliminationPromotion/DirectEliminationPromotion.vue +204 -204
- package/src/stories/Organisms/Wizards/EditEventWizard/EditEventWizard.stories.js +137 -137
- package/src/stories/Organisms/Wizards/EditEventWizard/EventCustomization/EventCustomization.vue +172 -172
- package/src/stories/Organisms/Wizards/EditEventWizard/PoolConfiguration/PoolConfiguration.vue +216 -216
- package/src/stories/Organisms/Wizards/EditEventWizard/PriceFields.test.js +79 -79
- package/src/stories/Organisms/Wizards/EditEventWizard/RuleSerialization.test.js +29 -29
- package/src/stories/Organisms/Wizards/EditEventWizard/WeaponSelection.test.js +138 -0
- package/src/stories/Templates/EventManagement/Bracket/Bracket.stories.js +123 -12
- package/src/stories/Templates/EventManagement/Bracket/Bracket.test.js +178 -166
- package/src/stories/Templates/EventManagement/Bracket/Bracket.vue +35 -7
- package/src/stories/Templates/EventManagement/Bracket/BracketDirectorAssignment.test.js +242 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketMobile.test.js +131 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketPlannedSuggestions.js +42 -39
- package/src/stories/Templates/EventManagement/Bracket/BracketStories.test.js +80 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryAssignments.js +93 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryAssignments.test.js +152 -0
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryHarness.js +39 -39
- package/src/stories/Templates/EventManagement/Bracket/BracketStoryHarness.test.js +79 -79
- package/src/stories/Templates/EventManagement/EditEventInfo/EditEventInfo.stories.js +93 -93
- package/src/stories/Templates/EventManagement/EditEventInfo/EditEventInfo.vue +91 -91
- package/src/stories/Templates/EventManagement/PoolLive/PoolLive.test.js +121 -121
- package/src/stories/Templates/Menus/EditEventsTopMenu/EditEventsTopMenu.stories.js +9 -2
- package/src/stories/Templates/Menus/EditEventsTopMenu/EditEventsTopMenu.vue +5 -4
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.stories.js +81 -81
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.test.js +39 -39
- package/src/stories/Templates/PersonManagement/Admin/Administration/Administration.vue +101 -101
- package/src/stories/Templates/PersonManagement/Admin/FencerAdmin/FencerAdmin.stories.js +71 -71
- package/src/stories/Templates/PersonManagement/Admin/FencerAdmin/FencerAdmin.vue +86 -86
- package/src/stories/Templates/PersonManagement/Admin/MergeAccounts/MergeAccounts.stories.js +86 -86
- package/src/stories/Templates/PersonManagement/Admin/MergeAccounts/MergeAccounts.vue +247 -247
- package/src/stories/Templates/PersonManagement/Basic/BasicEdit.vue +170 -170
- package/src/stories/Templates/PersonManagement/PersonManagement.stories.js +156 -156
- package/src/stories/Templates/PersonManagement/PersonManagement.test.js +329 -329
- package/src/stories/Templates/PersonManagement/PersonManagement.vue +329 -329
- package/src/stories/Templates/PersonManagement/PersonManagementDraft.js +42 -42
- package/src/stories/Templates/TournamentManagement/TournamentManagement.stories.js +84 -84
- package/src/stories/Templates/TournamentManagement/TournamentManagement.test.js +114 -114
- package/src/stories/Templates/TournamentManagement/TournamentManagement.vue +363 -363
- package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.stories.js +116 -116
- package/src/stories/Templates/TournamentManagement/TournamentPageOne/TournamentPageOne.vue +307 -307
- package/src/stories/Util/Validations/PersonManagementValidations.js +45 -45
- package/src/stories/Util/Validations/PriceValidation.js +6 -6
- package/src/stories/Util/boutDirectorAssignment.js +46 -0
- package/src/stories/Util/registrationStatus.js +11 -11
- package/src/stories/Util/tabs.js +19 -47
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import BasicEventInfo from './BasicEventInfo/BasicEventInfo.vue';
|
|
4
|
+
import EditEventWizard from './EditEventWizard.vue';
|
|
5
|
+
import DropDownMenu from '../../ComplexInputs/DropDown/DropDownMenu.vue';
|
|
6
|
+
|
|
7
|
+
const wrappers = [];
|
|
8
|
+
const weapons = [
|
|
9
|
+
{ text: 'Sword & Buckler', link: 8 },
|
|
10
|
+
{ text: 'MG Longsword', link: 17 },
|
|
11
|
+
{ text: 'Longsword', link: 1 }
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
afterEach(() => wrappers.splice(0).forEach(wrapper => wrapper.unmount()));
|
|
15
|
+
|
|
16
|
+
function mountBasic(eventConfig, options = weapons) {
|
|
17
|
+
const wrapper = mount(BasicEventInfo, {
|
|
18
|
+
props: {
|
|
19
|
+
eventConfig,
|
|
20
|
+
weapons: options,
|
|
21
|
+
validation: { EventName: { invalid: false } },
|
|
22
|
+
steps: [],
|
|
23
|
+
currentStep: 0
|
|
24
|
+
},
|
|
25
|
+
global: { stubs: { DatePicker: true, StepIndicator: true } }
|
|
26
|
+
});
|
|
27
|
+
wrappers.push(wrapper);
|
|
28
|
+
return wrapper;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function selectedText(wrapper) {
|
|
32
|
+
return wrapper.findComponent(DropDownMenu).find('input').element.value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe('event weapon selection', () => {
|
|
36
|
+
it.each([1, '1', 8, '8', 17, '17'])('shows the actual saved weapon for ID %s without emitting a change', WeaponId => {
|
|
37
|
+
const wrapper = mountBasic({ WeaponId });
|
|
38
|
+
expect(selectedText(wrapper)).toBe(weapons.find(option => String(option.link) === String(WeaponId)).text);
|
|
39
|
+
expect(wrapper.emitted('update')).toBeUndefined();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('accepts raw weapon records as well as dropdown options', () => {
|
|
43
|
+
const wrapper = mountBasic(
|
|
44
|
+
{ WeaponId: '8' },
|
|
45
|
+
weapons.map(option => ({ Id: option.link, Name: option.text }))
|
|
46
|
+
);
|
|
47
|
+
expect(selectedText(wrapper)).toBe('Sword & Buckler');
|
|
48
|
+
expect(wrapper.findComponent(DropDownMenu).props('items')).toEqual(
|
|
49
|
+
weapons.map(option => ({ ...option, Id: option.link, Name: option.text }))
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it.each([undefined, 99])('does not pretend an unavailable weapon %s is Longsword', WeaponId => {
|
|
54
|
+
const wrapper = mountBasic({ WeaponId });
|
|
55
|
+
expect(selectedText(wrapper)).toBe('Select a weapon');
|
|
56
|
+
expect(wrapper.emitted('update')).toBeUndefined();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('reconciles a parent weapon change and restores that selection after closing the menu', async () => {
|
|
60
|
+
const wrapper = mountBasic({ WeaponId: 8 });
|
|
61
|
+
await wrapper.setProps({ eventConfig: { WeaponId: 1 } });
|
|
62
|
+
expect(selectedText(wrapper)).toBe('Longsword');
|
|
63
|
+
const dropdown = wrapper.findComponent(DropDownMenu);
|
|
64
|
+
dropdown.vm.clearInput();
|
|
65
|
+
dropdown.vm.restorePreviousValue();
|
|
66
|
+
await wrapper.vm.$nextTick();
|
|
67
|
+
expect(selectedText(wrapper)).toBe('Longsword');
|
|
68
|
+
expect(wrapper.emitted('update')).toBeUndefined();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('shows the saved selection when the weapon options arrive later', async () => {
|
|
72
|
+
const wrapper = mountBasic({ WeaponId: 8 }, []);
|
|
73
|
+
await wrapper.setProps({ weapons });
|
|
74
|
+
expect(selectedText(wrapper)).toBe('Sword & Buckler');
|
|
75
|
+
expect(wrapper.emitted('update')).toBeUndefined();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('emits the chosen option ID only after an explicit selection', async () => {
|
|
79
|
+
const wrapper = mountBasic({ WeaponId: 8 });
|
|
80
|
+
const dropdown = wrapper.findComponent(DropDownMenu);
|
|
81
|
+
dropdown.vm.handleDropDown();
|
|
82
|
+
await wrapper.vm.$nextTick();
|
|
83
|
+
await dropdown
|
|
84
|
+
.findAll('a')
|
|
85
|
+
.find(option => option.text() === 'Longsword')
|
|
86
|
+
.trigger('click');
|
|
87
|
+
expect(wrapper.emitted('update')).toEqual([[{ WeaponId: 1 }]]);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('preserves the saved weapon when another field is edited and saves a deliberate weapon change', async () => {
|
|
91
|
+
const event = { EventId: 12, EventName: 'Example Event', EventPrice: 25, WeaponId: '8', rules: [] };
|
|
92
|
+
const wrapper = mount(EditEventWizard, {
|
|
93
|
+
props: { event, weapons, editMode: true },
|
|
94
|
+
global: { stubs: { DatePicker: true, StepIndicator: true } }
|
|
95
|
+
});
|
|
96
|
+
wrappers.push(wrapper);
|
|
97
|
+
await wrapper.vm.$nextTick();
|
|
98
|
+
expect(selectedText(wrapper)).toBe('Sword & Buckler');
|
|
99
|
+
wrapper.vm.handleValueChange({ EventName: 'Renamed Event' });
|
|
100
|
+
wrapper.vm.handleUpdate();
|
|
101
|
+
expect(wrapper.emitted('save:step')[0][0].event.WeaponId).toBe('8');
|
|
102
|
+
|
|
103
|
+
wrapper.findComponent(DropDownMenu).vm.handleClick(weapons.find(option => option.link === 17));
|
|
104
|
+
await wrapper.vm.$nextTick();
|
|
105
|
+
wrapper.vm.handleUpdate();
|
|
106
|
+
expect(wrapper.emitted('save:step')[1][0].event.WeaponId).toBe(17);
|
|
107
|
+
expect(event.WeaponId).toBe('8');
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it.each([false, true])(
|
|
112
|
+
'actual dropdown choices retain catalog IDs through submit with edit mode %s',
|
|
113
|
+
async editMode => {
|
|
114
|
+
const event = { EventId: 230, EventName: 'MG Longsword', EventPrice: 45, WeaponId: 17, rules: [] };
|
|
115
|
+
const wrapper = mount(EditEventWizard, {
|
|
116
|
+
props: { event, weapons, editMode },
|
|
117
|
+
global: { stubs: { DatePicker: true, StepIndicator: true } }
|
|
118
|
+
});
|
|
119
|
+
wrappers.push(wrapper);
|
|
120
|
+
await wrapper.vm.$nextTick();
|
|
121
|
+
expect(selectedText(wrapper)).toBe('MG Longsword');
|
|
122
|
+
for (const option of weapons) {
|
|
123
|
+
const dropdown = wrapper.findComponent(DropDownMenu);
|
|
124
|
+
dropdown.vm.handleDropDown();
|
|
125
|
+
await wrapper.vm.$nextTick();
|
|
126
|
+
await dropdown
|
|
127
|
+
.findAll('a')
|
|
128
|
+
.find(item => item.text() === option.text)
|
|
129
|
+
.trigger('click');
|
|
130
|
+
expect(selectedText(wrapper)).toBe(option.text);
|
|
131
|
+
wrapper.vm.handleSubmit();
|
|
132
|
+
const eventName = editMode ? 'save:step' : 'update:submit';
|
|
133
|
+
const submitted = wrapper.emitted(eventName).at(-1)[0];
|
|
134
|
+
expect((editMode ? submitted.event : submitted).WeaponId).toBe(option.link);
|
|
135
|
+
}
|
|
136
|
+
expect(event.WeaponId).toBe(17);
|
|
137
|
+
}
|
|
138
|
+
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ref, watch } from 'vue';
|
|
1
|
+
import { computed, nextTick, ref, watch } from 'vue';
|
|
2
2
|
import Bracket from './Bracket.vue';
|
|
3
|
+
import { distributeStoryAssignments } from './BracketStoryAssignments.js';
|
|
3
4
|
import {
|
|
4
5
|
activateStoryBout,
|
|
5
6
|
canStoryDirectorDirectBout,
|
|
@@ -8,11 +9,7 @@ import {
|
|
|
8
9
|
getStoryDirectorId,
|
|
9
10
|
replaceStoryBout
|
|
10
11
|
} from './BracketStoryHarness.js';
|
|
11
|
-
import {
|
|
12
|
-
plannedBoutAssignments,
|
|
13
|
-
plannedDirectingStations,
|
|
14
|
-
plannedSuggestionViewerId
|
|
15
|
-
} from './BracketPlannedSuggestions.js';
|
|
12
|
+
import { plannedDirectingStations, plannedSuggestionViewerId } from './BracketPlannedSuggestions.js';
|
|
16
13
|
//import getDEWithBouts from '../../../../mocks/getDEWithBouts.js';
|
|
17
14
|
import getDEWithBouts6Fencers from '../../../../mocks/getDeBouts-6fencers.js';
|
|
18
15
|
import getDEWithBouts12Fencers from '../../../../mocks/getDeBouts-12fencers.js';
|
|
@@ -30,11 +27,54 @@ const renderInteractiveBracket = args => ({
|
|
|
30
27
|
setup() {
|
|
31
28
|
const storyBouts = ref(cloneStoryBouts(args.bouts));
|
|
32
29
|
const storyStations = ref(cloneStations(args.plannedDirectingStations));
|
|
30
|
+
const storyAssignments = ref([]);
|
|
31
|
+
const canAddDirector = computed(() =>
|
|
32
|
+
plannedDirectingStations.some(
|
|
33
|
+
station => !storyStations.value.some(item => String(item.RingId) === String(station.RingId))
|
|
34
|
+
)
|
|
35
|
+
);
|
|
36
|
+
const redistributeAssignments = () => {
|
|
37
|
+
storyAssignments.value = distributeStoryAssignments({
|
|
38
|
+
bouts: storyBouts.value,
|
|
39
|
+
stations: storyStations.value,
|
|
40
|
+
previousAssignments: storyAssignments.value
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
const applyProvidedAssignments = assignments => {
|
|
44
|
+
redistributeAssignments();
|
|
45
|
+
const providedIds = new Set(assignments.map(assignment => String(assignment.DEBoutId)));
|
|
46
|
+
storyAssignments.value = [
|
|
47
|
+
...storyAssignments.value.filter(assignment => !providedIds.has(String(assignment.DEBoutId))),
|
|
48
|
+
...assignments.map(assignment => ({ ...assignment }))
|
|
49
|
+
];
|
|
50
|
+
};
|
|
51
|
+
const assignmentBout = ref(null);
|
|
52
|
+
const directorPicker = ref(null);
|
|
53
|
+
const assignmentDialog = ref(null);
|
|
54
|
+
|
|
55
|
+
watch(() => args.plannedBoutAssignments, applyProvidedAssignments, { deep: true, immediate: true });
|
|
56
|
+
|
|
57
|
+
const requestBoutDirector = async bout => {
|
|
58
|
+
assignmentBout.value = bout;
|
|
59
|
+
await nextTick();
|
|
60
|
+
assignmentDialog.value?.showModal();
|
|
61
|
+
directorPicker.value?.focus();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const assignPlannedDirector = ringId => {
|
|
65
|
+
const bout = assignmentBout.value;
|
|
66
|
+
const station = storyStations.value.find(item => String(item.RingId) === String(ringId));
|
|
67
|
+
if (!bout || !station) return;
|
|
68
|
+
const remaining = storyAssignments.value.filter(item => String(item.DEBoutId) !== String(bout.DEBoutId));
|
|
69
|
+
storyAssignments.value = [...remaining, { DEBoutId: bout.DEBoutId, RingId: station.RingId }];
|
|
70
|
+
assignmentBout.value = null;
|
|
71
|
+
};
|
|
33
72
|
|
|
34
73
|
watch(
|
|
35
74
|
() => args.bouts,
|
|
36
75
|
bouts => {
|
|
37
76
|
storyBouts.value = cloneStoryBouts(bouts);
|
|
77
|
+
redistributeAssignments();
|
|
38
78
|
},
|
|
39
79
|
{ deep: true }
|
|
40
80
|
);
|
|
@@ -43,6 +83,7 @@ const renderInteractiveBracket = args => ({
|
|
|
43
83
|
() => args.plannedDirectingStations,
|
|
44
84
|
stations => {
|
|
45
85
|
storyStations.value = cloneStations(stations);
|
|
86
|
+
redistributeAssignments();
|
|
46
87
|
},
|
|
47
88
|
{ deep: true }
|
|
48
89
|
);
|
|
@@ -59,6 +100,7 @@ const renderInteractiveBracket = args => ({
|
|
|
59
100
|
const nextStation = plannedDirectingStations.find(station => !assignedRingIds.has(String(station.RingId)));
|
|
60
101
|
if (!nextStation) return;
|
|
61
102
|
storyStations.value = [...storyStations.value, ...cloneStations([nextStation])];
|
|
103
|
+
redistributeAssignments();
|
|
62
104
|
};
|
|
63
105
|
|
|
64
106
|
const handleDirectingBout = bout => {
|
|
@@ -75,6 +117,13 @@ const renderInteractiveBracket = args => ({
|
|
|
75
117
|
args,
|
|
76
118
|
storyBouts,
|
|
77
119
|
storyStations,
|
|
120
|
+
storyAssignments,
|
|
121
|
+
canAddDirector,
|
|
122
|
+
assignmentBout,
|
|
123
|
+
directorPicker,
|
|
124
|
+
assignmentDialog,
|
|
125
|
+
requestBoutDirector,
|
|
126
|
+
assignPlannedDirector,
|
|
78
127
|
handleAddPlannedDirector,
|
|
79
128
|
handleCloseDirectingBout,
|
|
80
129
|
handleDirectingBout,
|
|
@@ -82,6 +131,19 @@ const renderInteractiveBracket = args => ({
|
|
|
82
131
|
};
|
|
83
132
|
},
|
|
84
133
|
template: `
|
|
134
|
+
<div>
|
|
135
|
+
<dialog v-if="assignmentBout" ref="assignmentDialog" aria-label="Assign director" class="fixed inset-0 m-auto rounded border border-dropdownSelect bg-white p-4 shadow-lg backdrop:bg-black/20" @cancel="assignmentBout = null">
|
|
136
|
+
<label class="text-sm text-primaryHighlight">
|
|
137
|
+
Assign director to bout {{ assignmentBout.DEBoutId }}
|
|
138
|
+
<select ref="directorPicker" class="ml-2 rounded border border-dropdownSelect p-2" @change="assignPlannedDirector($event.target.value)">
|
|
139
|
+
<option value="">Choose director</option>
|
|
140
|
+
<option v-for="station in storyStations" :key="station.RingId" :value="station.RingId">
|
|
141
|
+
{{ station.Director?.DisplayName || 'Director TBD' }} / {{ station.RingName }}
|
|
142
|
+
</option>
|
|
143
|
+
</select>
|
|
144
|
+
</label>
|
|
145
|
+
<button type="button" class="ml-4 text-sm underline" @click="assignmentBout = null">Cancel</button>
|
|
146
|
+
</dialog>
|
|
85
147
|
<Bracket
|
|
86
148
|
v-bind="args"
|
|
87
149
|
:connectedToServer="args.connectedToServer"
|
|
@@ -89,6 +151,9 @@ const renderInteractiveBracket = args => ({
|
|
|
89
151
|
:hostingClubColors="args.hostingClubColors"
|
|
90
152
|
:bouts="storyBouts"
|
|
91
153
|
:plannedDirectingStations="storyStations"
|
|
154
|
+
:plannedBoutAssignments="storyAssignments"
|
|
155
|
+
:showAddPlannedDirectorCard="args.showAddPlannedDirectorCard && canAddDirector"
|
|
156
|
+
@request:bout-director="requestBoutDirector"
|
|
92
157
|
@close:directing-bout="handleCloseDirectingBout"
|
|
93
158
|
@request:add-planned-director="handleAddPlannedDirector"
|
|
94
159
|
@update:directing-bout="handleDirectingBout"
|
|
@@ -96,6 +161,7 @@ const renderInteractiveBracket = args => ({
|
|
|
96
161
|
@update:bout="persistStoryBout"
|
|
97
162
|
@submit:bout="persistStoryBout"
|
|
98
163
|
/>
|
|
164
|
+
</div>
|
|
99
165
|
`
|
|
100
166
|
});
|
|
101
167
|
|
|
@@ -110,13 +176,18 @@ export default {
|
|
|
110
176
|
hostingClubColors: getDEWithBouts.hostingClubColors,
|
|
111
177
|
connectedToServer: true,
|
|
112
178
|
role: 'admin',
|
|
113
|
-
plannedDirectingStations:
|
|
179
|
+
plannedDirectingStations: plannedDirectingStations.slice(0, 2),
|
|
114
180
|
plannedBoutAssignments: [],
|
|
115
|
-
viewerPersonId:
|
|
116
|
-
showPlannedDirectorAssignments:
|
|
117
|
-
showAddPlannedDirectorCard: true
|
|
181
|
+
viewerPersonId: plannedSuggestionViewerId,
|
|
182
|
+
showPlannedDirectorAssignments: true,
|
|
183
|
+
showAddPlannedDirectorCard: true,
|
|
184
|
+
showBoutDirectorAssignment: true
|
|
118
185
|
},
|
|
119
186
|
argTypes: {
|
|
187
|
+
showBoutDirectorAssignment: {
|
|
188
|
+
control: 'boolean',
|
|
189
|
+
description: 'Include Assign director in the pairing hover menu. The parent supplies staff selection and saving.'
|
|
190
|
+
},
|
|
120
191
|
bouts: {
|
|
121
192
|
control: 'object'
|
|
122
193
|
},
|
|
@@ -220,10 +291,38 @@ export const PlannedDirectorSuggestions = {
|
|
|
220
291
|
status: 'de',
|
|
221
292
|
role: 'Admin',
|
|
222
293
|
plannedDirectingStations: plannedDirectingStations.slice(0, 2),
|
|
223
|
-
plannedBoutAssignments,
|
|
224
294
|
viewerPersonId: plannedSuggestionViewerId,
|
|
225
295
|
showPlannedDirectorAssignments: true,
|
|
226
|
-
showAddPlannedDirectorCard: true
|
|
296
|
+
showAddPlannedDirectorCard: true,
|
|
297
|
+
showBoutDirectorAssignment: true
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
export const ThreeDirectors = {
|
|
302
|
+
args: { ...PlannedDirectorSuggestions.args, plannedDirectingStations: plannedDirectingStations.slice(0, 3) }
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
export const FourDirectors = {
|
|
306
|
+
args: { ...PlannedDirectorSuggestions.args, plannedDirectingStations: plannedDirectingStations.slice(0, 4) }
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
export const FiveDirectors = {
|
|
310
|
+
args: { ...PlannedDirectorSuggestions.args, plannedDirectingStations: plannedDirectingStations.slice(0, 5) }
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
export const SixDirectors = {
|
|
314
|
+
args: { ...PlannedDirectorSuggestions.args, plannedDirectingStations }
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
export const HoverBoutActions = {
|
|
318
|
+
args: { ...PlannedDirectorSuggestions.args },
|
|
319
|
+
parameters: {
|
|
320
|
+
docs: {
|
|
321
|
+
description: {
|
|
322
|
+
story:
|
|
323
|
+
'Hover over a pairing for Open bout and Assign director. Clicking the pairing still opens it directly. The picker in this story simulates the consuming app; the story simulates balanced section coverage through the semifinals, while production assignment and persistence remain app-owned.'
|
|
324
|
+
}
|
|
325
|
+
}
|
|
227
326
|
}
|
|
228
327
|
};
|
|
229
328
|
|
|
@@ -246,3 +345,15 @@ export const noBoutsYet = {
|
|
|
246
345
|
status: 'live'
|
|
247
346
|
}
|
|
248
347
|
};
|
|
348
|
+
|
|
349
|
+
export const PhoneDirector = {
|
|
350
|
+
args: { ...PlannedDirectorSuggestions.args, role: 'Director' },
|
|
351
|
+
parameters: {
|
|
352
|
+
docs: {
|
|
353
|
+
description: {
|
|
354
|
+
story:
|
|
355
|
+
'Use a viewport narrower than 768px to see the phone directing view: a bout list, ring suggestions, connection status, and collapsed completed bouts. Organising controls stay on desktop, even when assignment options are enabled. Returning to desktop restores the selected List View or Tableau.'
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
};
|