Skip to content

Commit 8a25220

Browse files
Hieu Lam - TMAmarcoagkhangonodkhangntthitrinh
authored
feature-8683: Add Options for Badges in Wizard (#8926)
* feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8638 Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8638: add badge * feature-8683: Add Options for Badges in Wizard * feature-8683 * feature-8683 * feature-8683 * feature-8683: Add Options for Badges in Wizard * feature-8638 * feature-8638 * feature-8683: Add Options for Badges in Wizard * feature-8638: Add Options for Badges in Wizard * feature-8638: Add Options for Badges in Wizard * feature-8638: Add Options for Badges in Wizard * feature-8638 fix css * feature-8683: Add Options for Badges in Wizard edit UI * feature-8683: Add Options for Badges in Wizard update upload background image * feature-8683: Add Options for Badges in Wizard update upload background image * feature-8683 avoid using style inline * feature-8683 avoid using style inline * feature-8683: Merge code of Khang * feature-8683: Merge code of Khang * feature-8683 avoid using style inline * feature-8683 avoid using style inline * feature-8683 disable input when choose QR * feature-8683: Add Options for Badges in Wizard create UI for QR in badge * feature-8683: Add Options for Badges in Wizard badge: choose field to be generate as QR code * feature-8683: Add Options for Badges in Wizard qr code implement * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard implement save badge to server * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard implement save badge to server * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard load saved badge * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard remove unused package * feature-8683: Add Options for Badges in Wizard * feature-8683 remove unused package * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard add some common font for badge field * feature-8683: Add Options for Badges in Wizard add some common font for badge field * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard add some common font name for badge field * feature-8683: Add Options for Badges in Wizard fix badge size * feature-8683: Fix font-weight, add rows * feature-8683: Add Options for Badges in Wizard fix UI issue * feature-8683: Add Options for Badges in Wizard fix UI issue * feature-8683: Add Options for Badges in Wizard * feature-8683 update qr fields save as identifier instead of name * feature-8683: Add Options for Badges in Wizard update warning when include field to qr * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8683:Add Options for Badges in Wizard * feature-8683:Add Options for Badges in Wizard * feature-8683:Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard * feature-8683:feature-8683: Add Options for Badges in Wizard * feature-8683: Add Options for Badges in Wizard --------- Co-authored-by: Marco A. Gutierrez <[email protected]> Co-authored-by: Khang On - TMA <[email protected]> Co-authored-by: khangon <[email protected]> Co-authored-by: ntthitrinh <[email protected]> Co-authored-by: cweitat <[email protected]>
1 parent fdc2076 commit 8a25220

39 files changed

+1970
-38
lines changed

app/components/forms/wizard/attendee-step.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ export default Component.extend(FormMixin, EventWizardMixin, {
5757
this.excludeTickets.pushObject(ticket);
5858
}
5959
});
60-
6160
Object.keys(_forms).forEach(_id => {
6261
const selectedTicket = _forms[_id].ticketsDetails;
6362
forms.pushObject({
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import Component from '@ember/component';
2+
import { orderBy, union } from 'lodash-es';
3+
import { computed } from '@ember/object';
4+
import { inject as service } from '@ember/service';
5+
import FormMixin from 'open-event-frontend/mixins/form';
6+
import { booleanTextType } from 'open-event-frontend/utils/dictionary/boolean_text_type';
7+
import { fieldFontName } from 'open-event-frontend/utils/dictionary/badge-field';
8+
9+
export default Component.extend(FormMixin, {
10+
router : service(),
11+
autoScrollToErrors : false,
12+
isExpanded : true,
13+
booleanTextType : orderBy(booleanTextType, 'position'),
14+
15+
getCustomFields: computed('includeCustomField', function() {
16+
const validForms = this.includeCustomField.map(item => item.name);
17+
if (this.data.custom_field) {
18+
validForms.push(this.data.custom_field);
19+
}
20+
return union(validForms);
21+
}),
22+
23+
getQrFields: computed('qrFields', function() {
24+
return union(this.qrFields, 'name');
25+
}),
26+
27+
getWarningFields: computed('data.custom_field', 'selectedTickets', function() {
28+
const warningFields = [];
29+
if (this.data.custom_field !== 'QR') {
30+
this.selectedTickets.forEach(ticket => {
31+
const listCFields = this.customForms.filter(form => (ticket.formID === form.formID) && form.isIncluded || form.isFixed).map(form => form.name);
32+
if (this.data.custom_field && !listCFields.includes(this.data.custom_field)) {
33+
warningFields.pushObject(
34+
{
35+
field : this.data.custom_field,
36+
ticket : ticket.name
37+
}
38+
);
39+
}
40+
});
41+
}
42+
return warningFields;
43+
}),
44+
45+
getWarningQRFields: computed('data.qr_custom_field.@each', 'selectedTickets', function() {
46+
if (this.data.qr_custom_field) {
47+
const warningFields = [];
48+
this.selectedTickets.forEach(ticket => {
49+
const listCFields = union(this.customForms.filter(form => (ticket.formID === form.formID) && form.isIncluded || form.isFixed), 'fieldIdentifier');
50+
this.data.qr_custom_field.forEach(field => {
51+
const warningField = listCFields.map(item => item.fieldIdentifier).includes(field);
52+
if (!warningField) {
53+
warningFields.pushObject(
54+
{
55+
field : this.customForms.find(item => item.fieldIdentifier === field).name,
56+
ticket : ticket.name
57+
}
58+
);
59+
}
60+
});
61+
});
62+
return warningFields;
63+
}
64+
}),
65+
66+
get fieldFont() {
67+
return orderBy(fieldFontName, 'name');
68+
},
69+
70+
actions: {
71+
toggleSetting() {
72+
if (!this.isExpanded) {
73+
this.set('isExpanded', true);
74+
} else {
75+
this.set('isExpanded', false);
76+
}
77+
},
78+
removeForm() {
79+
if (this.removeBadgeField) {
80+
this.set('data.is_deleted', true);
81+
this.removeBadgeField(this.data);
82+
}
83+
},
84+
toggleTextAlignments(item) {
85+
this.set('data.text_alignment', item);
86+
},
87+
onChangeCustomField(code) {
88+
if (this.onChange) {
89+
this.onChange(this.data.custom_field, code);
90+
this.set('data.custom_field', code);
91+
if (code === 'QR') {
92+
this.set('data.field_identifier', 'QR');
93+
} else {
94+
const cfield = this.includeCustomField.filter(item => item.name === code)[0];
95+
if (cfield) {
96+
this.set('data.field_identifier', cfield.fieldIdentifier);
97+
}
98+
}
99+
}
100+
},
101+
onChangeTextTransform(value) {
102+
this.set('data.text_type', value);
103+
},
104+
onChangeFontName(value) {
105+
this.set('data.font_name', value);
106+
}
107+
}
108+
});
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import Component from '@ember/component';
2+
import { computed, observer } from '@ember/object';
3+
import FormMixin from 'open-event-frontend/mixins/form';
4+
import EventWizardMixin from 'open-event-frontend/mixins/event-wizard';
5+
import { sortBy, union } from 'lodash-es';
6+
import { badgeSize } from 'open-event-frontend/utils/dictionary/badge-field';
7+
import { htmlSafe } from '@ember/template';
8+
import { badgeCustomFields } from 'open-event-frontend/utils/dictionary/badge-custom-fields';
9+
// import QRCode from 'qrcode';
10+
11+
export default Component.extend(FormMixin, EventWizardMixin, {
12+
currentSelected : [],
13+
ignoreCustomField : [],
14+
isExpandedBadge : true,
15+
init() {
16+
this._super(...arguments);
17+
this.removeBadgeField = this.removeBadgeField.bind(this);
18+
this.currentSelected = this.selectedTicket;
19+
this.badgeForms = this.data;
20+
this.ignoreCustomField = [];
21+
},
22+
23+
ticketsEnable: computed('tickets', 'selectedTicket.@each', function() {
24+
return union(this.tickets || [], this.selectedTicket || []);
25+
}),
26+
27+
fixedFields: computed('data.customForms.@each', function() {
28+
return this.data.customForms?.filter(field => field.isFixed);
29+
}),
30+
31+
badgeFields: computed('[email protected]_deleted', function() {
32+
return this.data.badgeFields?.filter(field => !field.is_deleted);
33+
}),
34+
35+
includeCustomField: computed('ignoreCustomField.@each', 'selectedTicket.@each', '[email protected]_deleted', 'data.badgeFields.@each', function() {
36+
return this.customFormsValid.filter(item => !this.ignoreCustomField.includes(item.name) && !this.data.badgeFields.map(field => !field.is_deleted && field.custom_field).includes(item.name));
37+
}),
38+
39+
customFormsValid: computed('selectedTicket.@each', 'data.badgeFields.@each', function() {
40+
const formIds = this.selectedTicket.map(item => item.formID);
41+
const validForms = this.customForms.filter(form => (formIds.includes(form.formID) && form.isIncluded) || form.isFixed);
42+
validForms.push({ 'name': 'QR', 'field_identifier': 'qr' });
43+
return union(sortBy(validForms));
44+
}),
45+
46+
qrFields: computed('selectedTicket.@each', 'data.badgeFields.@each', function() {
47+
// return sortBy(this.data.badgeFields.filter(field => !field.is_deleted && field.custom_field !== 'QR').map(field => field.custom_field));
48+
const formIds = this.selectedTicket.map(item => item.formID);
49+
const validForms = this.customForms.filter(form => (formIds.includes(form.formID) && form.isIncluded) || form.isFixed);
50+
return union(sortBy(validForms));
51+
}),
52+
53+
ticketNames: computed('selectedTicket.@each', function() {
54+
let ticketNames = '';
55+
this.selectedTicket.forEach(ticket => {
56+
if (ticketNames) {
57+
ticketNames += ', ' + ticket.name;
58+
} else {
59+
ticketNames = ticket.name;
60+
}
61+
});
62+
return ticketNames.trim();
63+
}),
64+
65+
selectChanges: observer('selectedTicket.@each', function() {
66+
const ticketsDetails = this.selectedTicket;
67+
const { currentSelected } = this;
68+
69+
const added = currentSelected.length < ticketsDetails.length;
70+
let changed = [];
71+
if (added) {
72+
changed = ticketsDetails.filter(item => !currentSelected.includes(item));
73+
} else {
74+
changed = currentSelected.filter(item => !ticketsDetails.includes(item));
75+
}
76+
this.currentSelected = ticketsDetails;
77+
this.get('onFormUpdateTicket')({
78+
added,
79+
changed,
80+
formID: this.id
81+
});
82+
}),
83+
84+
editableFields: computed('data.customForms.@each', function() {
85+
const filteredFields = this.customForms?.filter(field => !field.isFixed);
86+
const fields = sortBy(filteredFields, ['isComplex', 'name']);
87+
return sortBy(fields, ['position']);
88+
}),
89+
90+
revertChanges: observer('event.isBadgesEnabled', function() {
91+
if (!this.event.isBadgesEnabled) {
92+
this.editableFields.forEach(field => field.set('isRequired', false));
93+
}
94+
}),
95+
96+
showEditColumn: computed('editableFields.@each', function() {
97+
return this.editableFields?.some(field => field.isComplex);
98+
}),
99+
100+
disableAddBadgeField: computed('[email protected]_deleted', function() {
101+
return this.badgeForms.badgeFields?.filter(field => !field.is_deleted).length - 1 === this.customForms?.filter(field => field.isIncluded).length;
102+
}),
103+
104+
removeBadgeField(badgeField) {
105+
this.ignoreCustomField.removeObject(badgeField.custom_field);
106+
},
107+
108+
onSelectedCustomField(old_code, new_code) {
109+
if (old_code) {
110+
this.ignoreCustomField.removeObject(old_code);
111+
}
112+
if (new_code) {
113+
this.ignoreCustomField.pushObject(new_code);
114+
}
115+
},
116+
117+
getsampleData: computed('sampleData', function() {
118+
return {
119+
name : 'Barack Obama',
120+
organisation : 'US',
121+
position : 'President'
122+
};
123+
}),
124+
125+
getBadgeSize: computed('badgeForms.badgeSize', 'badgeForms.badgeOrientation', function() {
126+
let height = 4;
127+
let lineHeight = 3;
128+
const selectedSize = badgeSize.filter(badge => badge.name === this.badgeForms.badgeSize)[0];
129+
if (selectedSize) {
130+
[height, lineHeight] = [selectedSize.height, selectedSize.lineHeight];
131+
}
132+
if (this.badgeForms.badgeOrientation === 'Landscape') {
133+
[height, lineHeight] = [lineHeight, height];
134+
}
135+
136+
return {
137+
height,
138+
lineHeight };
139+
}),
140+
141+
getBadgeImgOrColor: computed('badgeForms.badgeColor', 'badgeForms.badgeImageURL', function() {
142+
let style = '';
143+
if (this.badgeForms.badgeColor) {
144+
style += `background-color: ${this.badgeForms.badgeColor}`;
145+
}
146+
if (this.badgeForms.badgeImageURL) {
147+
style += `background-image: url(${this.badgeForms.badgeImageURL}); background-size: cover;`;
148+
}
149+
return htmlSafe(style);
150+
}),
151+
152+
// generateQRCode(element) {
153+
// const text = 'Hello world'; // get the text to encode from the component argument or use a default value
154+
// const test = document.getElementById('badge_qr');
155+
// QRCode.toCanvas(test, text, function(error) { // use the qrcode method to create a canvas element with the QR code
156+
// if (error) {
157+
// console.error(error); // handle any errors
158+
// } else {
159+
// console.log('QR code generated!'); // log success
160+
// }
161+
// });
162+
// },
163+
164+
actions: {
165+
removeField(field) {
166+
field.deleteRecord();
167+
},
168+
addBadgeField() {
169+
this.badgeForms.badgeFields.pushObject(this.store.createRecord('badge-field-form', {
170+
badge_id : this.data.badgeID,
171+
is_deleted : false,
172+
badgeCustomFields
173+
}));
174+
},
175+
mutateBadgeSize(value) {
176+
badgeSize.forEach(badge => {
177+
if (badge.name === value) {(this.badgeForms.badgeSize = badge.name)}
178+
});
179+
},
180+
onChildChangeCustomField(old_code, new_code) {
181+
this.onSelectedCustomField(old_code, new_code);
182+
},
183+
toggleBadge() {
184+
if (!this.isExpandedBadge) {
185+
this.set('isExpandedBadge', true);
186+
} else {
187+
this.set('isExpandedBadge', false);
188+
}
189+
},
190+
mutatetickets(ticket) {
191+
this.selectedTicket.pushObject(ticket);
192+
}
193+
}
194+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{{#if this.data.selectedImage}}
2+
{{#if (and this.requiresDivider this.device.isMobile)}}
3+
<div class="ui hidden divider"></div>
4+
{{/if}}
5+
{{#if this.isHeaderImage}}
6+
<div class="ui" style="width:100%;height: auto;overflow: hidden;">
7+
{{#if this.uploadingImage}}
8+
<div class="ui active dimmer">
9+
<div class="ui text loader">{{t 'Image Uploading'}}</div>
10+
</div>
11+
{{/if}}
12+
{{#if this.allowReCrop}}
13+
<button type="button" class="ui center aligned icon button" {{action 'reCrop' }}>
14+
<i class="crop icon"></i>
15+
{{t 'Re-crop'}}
16+
</button>
17+
{{/if}}
18+
<button type="button" class="ui center aligned icon button" {{action 'removeSelection' }}>
19+
<i class="trash icon"></i>
20+
{{if this.needsConfirmation 'Delete' 'Confirm Delete'}}
21+
</button>
22+
</div>
23+
{{else}}
24+
<div class="ui">
25+
{{#if this.uploadingImage}}
26+
<div class="ui active dimmer">
27+
<div class="ui text loader">{{t 'Image Uploading'}}</div>
28+
</div>
29+
{{/if}}
30+
{{#if this.allowReCrop}}
31+
<button type="button" class="ui center aligned icon button" {{action 'reCrop' }}>
32+
<i class="crop icon"></i>
33+
{{t 'Re-crop'}}
34+
</button>
35+
{{/if}}
36+
<button type="button" class="ui center aligned icon button" {{action 'removeSelection' }}>
37+
<i class="trash icon"></i>
38+
{{if this.needsConfirmation 'Delete' 'Confirm Delete'}}
39+
</button>
40+
</div>
41+
{{/if}}
42+
<div class="ui center aligned text mb-8" style="margin-top:-5px">
43+
<span>{{this.imageText}}</span>
44+
</div>
45+
{{else}}
46+
<Input @type="file" @id={{this.inputIdGenerated}} class="styled input" @accept="image/*" @name={{or @name 'image_upload'
47+
}} @change={{action "fileSelected" }} />
48+
<label for="{{this.inputIdGenerated}}">
49+
<div class="ui center aligned icon button">
50+
<i aria-disabled={{true}}>{{t 'Choose File'}}</i>
51+
</div>
52+
</label>
53+
{{/if}}
54+
{{#if this.needsCropper}}
55+
<Modals::CropperModal @isOpen={{this.cropperModalIsShown}} @imgData={{this.imgData}}
56+
@onImageCrop={{action "imageCropped" }} @aspectRatio={{this.aspectRatio}} @cropPanel={{@cropPanel}}/>
57+
{{/if}}

0 commit comments

Comments
 (0)