-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented: Clean up UI for BOPIS inventory lookup (#470) #509
base: main
Are you sure you want to change the base?
Conversation
…e and operational hours.
alphabetical sorting, distance based sorting, atp based toggle, improved search function.
…on texts in locales/ files and code improvements.
src/store/modules/util/actions.ts
Outdated
async fetchCurrentFacilityLatLon({ commit }, facilityId) { | ||
const payload = { | ||
inputFields: { | ||
facilityId: facilityId |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
facilityId: facilityId | |
facilityId |
src/store/modules/util/actions.ts
Outdated
} | ||
}, | ||
|
||
async fetchStoreLookupByLatLon({ commit }, point) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
async fetchStoreLookupByLatLon({ commit }, point) { | |
async fetchStoresInformation({ commit }, point) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also update the service name, state and mutation name accordingly.
src/store/modules/util/actions.ts
Outdated
throw resp.data | ||
} | ||
} catch (err) { | ||
console.error("Failed to fetch stores by lat/lon information", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
console.error("Failed to fetch stores by lat/lon information", err) | |
logger.error("Failed to fetch stores information by lat/lon", err) |
if (this.hideEmptyStores) { | ||
filteredInventory = filteredInventory.filter((store: any) => store.stock > 0); | ||
} | ||
this.atpMappedStoresInventory = filteredInventory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.atpMappedStoresInventory = filteredInventory; | |
this.storesWithInventory = filteredInventory; |
<ion-note v-if="hasWeekCalendar(inventory)" :color="inventory.isOpen ? '' : 'danger'"> | ||
{{ inventory.hoursDisplay }} | ||
</ion-note> | ||
<p v-if="typeof inventory.dist === 'number'">{{ Math.round(inventory.dist) }} miles</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we have added typeof
check here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My logic behind adding this typeof check here is to filter out rendering of invalid stores,
while exploring the api (storeLookup) i found out certain stores had a string value "Infinity" in this dist field
This check omits the non number results from being rendered.
do i need to include these stores too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this stores should be included without displaying any distance and should be displayed at last.
</ion-item> | ||
</ion-list> | ||
<ion-accordion-group v-if="atpMappedStoresInventory.length"> | ||
<ion-accordion v-for="inventory in atpMappedStoresInventory" :key="inventory.storeCode" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<ion-accordion v-for="inventory in atpMappedStoresInventory" :key="inventory.storeCode" | |
<ion-accordion v-for="store in storesWithInventory" :key="inventory.storeCode" |
</ion-item> | ||
</ion-list> | ||
<ion-accordion-group v-if="atpMappedStoresInventory.length"> | ||
<ion-accordion v-for="inventory in atpMappedStoresInventory" :key="inventory.storeCode" | ||
:value="String(inventory.storeCode)" :toggle-icon="hasWeekCalendar(inventory) ? chevronDownOutline : false" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we do not need this String
conversion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right, it can be safely removed.
</ion-note> | ||
<p v-if="typeof inventory.dist === 'number'">{{ Math.round(inventory.dist) }} miles</p> | ||
</ion-label> | ||
<ion-button fill="clear" slot="end"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not need an ion-button
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, replacing button with a div.
</ion-item> | ||
</ion-list> | ||
<ion-accordion-group v-if="storesWithInventory.length"> | ||
<ion-accordion v-for="store in storesWithInventory" :key="store.storeCode" :value="store.storeCode" | ||
:toggle-icon="hasWeekCalendar(store) ? chevronDownOutline : false" :readonly="!hasWeekCalendar(store)"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't use false
as a value for toggle icon, please update this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also instead of handling accordion for displaying stores without calendar we can directly use ion-item, because using accordion will reserve some space for toggle-icon that will result in an empty space at the end.
<ion-list> | ||
<ion-item> | ||
<ion-label>{{ translate("Hide facilities without stock") }}</ion-label> | ||
<ion-toggle @click="toggleHideEmptyStock" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some specific components, ionic always require a label, so check the ion-toggle doc for defining label and update the UI accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i assume we are referring to this warning from console-
When i added an "aria-label" to the ion-toggle component it suppressed the warning but the ui got spoilt.
to overcome this, when i explored docs, i found another way of using ion-toggle component with inline label-placement property, that allows label to be directly passed inside of ion-toggle
This solved issue
docs referances-
Migrating from Legacy Toggle Syntax
const openTime = DateTime.fromFormat(store[openKey], 'HH:mm:ss'); | ||
const closeTime = DateTime.fromFormat(store[closeKey], 'HH:mm:ss'); | ||
|
||
const openDisplay = openTime.toFormat('ha').toLowerCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Display store timing with hours and minutes.
const isOpen = now >= openTime && now <= closeTime; | ||
|
||
return { | ||
display: isOpen ? `Open: ${openDisplay} - ${closeDisplay}` : 'Closed', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to translate Open and Closed static labels
mounted() { | ||
computed: { | ||
...mapGetters({ | ||
FacilityInformation: 'util/getCurrentFacilityInformation', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FacilityInformation: 'util/getCurrentFacilityInformation', | |
currentFacilityLatLon: 'util/getCurrentFacilityInformation', |
src/store/modules/util/getters.ts
Outdated
return state.currentFacilityInformation ? state.currentFacilityInformation : {} | ||
}, | ||
getStoresInformation: (state) => { | ||
return state.storesInformation ? state.storesInformation : {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return state.storesInformation ? state.storesInformation : {} | |
return state.storesInformation ? state.storesInformation : [] |
FacilityInformation: 'util/getCurrentFacilityInformation', | ||
storesInformation: 'util/getStoresInformation' | ||
}), | ||
currentFacilityCoords() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is not required, we can directly use the getter wherever required.
await this.store.dispatch("util/fetchCurrentFacilityInformation", this.currentFacilityId); | ||
if (this.currentFacilityCoords?.latitude && this.currentFacilityCoords?.longitude) { | ||
await this.store.dispatch("util/fetchStoresInformation", { | ||
latitude: this.currentFacilityCoords.latitude, | ||
longitude: this.currentFacilityCoords.longitude | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not fetch facility latLng and stores information on every mounted hook call, as this information is not changed frequently.
We should only call this apis if the state does not have data for these store states, and clear this data whenever facility changes from settings page.
src/store/modules/util/mutations.ts
Outdated
[types.UTIL_CURRENT_FACILITY_INFORMATION_UPDATED] (state, payload) { | ||
state.currentFacilityInformation = payload | ||
}, | ||
[types.UTIL_STORES_INFORMATION_UPDATED] (state, payload) { | ||
state.storesInformation = payload | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear the state on logout.
src/store/modules/util/index.ts
Outdated
@@ -15,7 +15,9 @@ const utilModule: Module<UtilState, RootState> = { | |||
partyNames: {}, | |||
cancelReasons: [], | |||
facilities: {}, | |||
enumerations: {} | |||
enumerations: {}, | |||
currentFacilityInformation: {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can rename it to facilitiesLatLng and store multiple facility latLng in the format:
facilitiesLatLng: {
facilityId: { latitude: value, longitude: value }
}
So when fetching the facility latLng from action we can first check in the state that if the latLng information is available, and only make api call if the information is not available in state.
Making this change will require all the related getter and mutation changes as well.
…toggle label warning fix, internationalization of static texts and calendar and store open time minutes display added.
…CurrentFacilityLatLon and related state changes, cleared state on logout and facility change.
// Create a copy of otherStoresInventory on mount | ||
this.storesInventory = this.otherStoresInventory.slice(); | ||
|
||
try { | ||
console.log(this.storesInventory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unwanted console log statement.
src/store/modules/util/getters.ts
Outdated
getCurrentFacilityLatLon: (state) => { | ||
return state.facilitiesLatLng ? state.facilitiesLatLng : {} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getCurrentFacilityLatLon: (state) => { | |
return state.facilitiesLatLng ? state.facilitiesLatLng : {} | |
}, | |
getFacilityLatLon: (state) => (facilityId: string) => { | |
return state.facilitiesLatLng[facilityId] ? state.facilitiesLatLng[facilityId] : {} | |
}, |
@@ -7,3 +7,5 @@ export const UTIL_PARTY_NAMES_UPDATED = SN_UTIL + '/PARTY_NAMES_UPDATED' | |||
export const UTIL_CANCEL_REASONS_UPDATED = SN_UTIL + '/CANCEL_REASONS_UPDATED' | |||
export const UTIL_FACILITIES_UPDATED = SN_UTIL + '/FACILITIES_UPDATED' | |||
export const UTIL_ENUMERATIONS_UPDATED = SN_UTIL + '/ENUMERATIONS_UPDATED' | |||
export const UTIL_CURRENT_FACILITY_LAT_LON_UPDATED = SN_UTIL + '/CURRENT_FACILITY_LAT_LON_UPDATED' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export const UTIL_CURRENT_FACILITY_LAT_LON_UPDATED = SN_UTIL + '/CURRENT_FACILITY_LAT_LON_UPDATED' | |
export const UTIL_FACILITY_LAT_LON_UPDATED = SN_UTIL + '/FACILITY_LAT_LON_UPDATED' |
src/store/modules/util/actions.ts
Outdated
) | ||
|
||
if (validCoords) { | ||
commit(types.UTIL_CURRENT_FACILITY_LAT_LON_UPDATED, validCoords) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
commit(types.UTIL_CURRENT_FACILITY_LAT_LON_UPDATED, validCoords) | |
commit(types.UTIL_CURRENT_FACILITY_LAT_LON_UPDATED, { facilityId, validCoords }) |
src/store/modules/util/mutations.ts
Outdated
@@ -27,5 +27,11 @@ const mutations: MutationTree <UtilState> = { | |||
[types.UTIL_ENUMERATIONS_UPDATED] (state, payload) { | |||
state.enumerations = payload | |||
}, | |||
[types.UTIL_CURRENT_FACILITY_LAT_LON_UPDATED] (state, payload) { | |||
state.facilitiesLatLng = payload |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
state.facilitiesLatLng = payload | |
state.facilitiesLatLng[payload.facilityId] = payload.validCoords |
mounted() { | ||
computed: { | ||
...mapGetters({ | ||
FacilityInformation: 'util/getCurrentFacilityLatLon', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FacilityInformation: 'util/getCurrentFacilityLatLon', | |
facilityLatLon: 'util/getCurrentFacilityLatLon', |
src/views/ProductDetail.vue
Outdated
@@ -314,7 +314,7 @@ export default defineComponent({ | |||
async getOtherStoresInventoryDetails() { | |||
const otherStoresInventoryModal = await modalController.create({ | |||
component: OtherStoresInventoryModal, | |||
componentProps: { otherStoresInventory: this.otherStoresInventoryDetails } | |||
componentProps: { otherStoresInventory: this.otherStoresInventoryDetails, currentFacilityId: this.currentFacility?.facilityId } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is still not handled.
… the facilityId in component itself.
Related Issues
#470
Short Description and Why It's Useful
Screenshots of Visual Changes before/after (If There Are Any)
Implemented Mockup-
![image](https://private-user-images.githubusercontent.com/44861896/410893584-a2757014-255a-4ee0-b67f-0e79b4f606b6.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2OTE5NDEsIm5iZiI6MTczOTY5MTY0MSwicGF0aCI6Ii80NDg2MTg5Ni80MTA4OTM1ODQtYTI3NTcwMTQtMjU1YS00ZWUwLWI2N2YtMGU3OWI0ZjYwNmI2LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDA3NDA0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWM0NTRmYjMwYTU5MDVkZjcwMjZkNTMwM2M5Yjg3YmM3MGNkNzBhYzM4ODcwZDY3MTJhYzViYzc2MmFiMWIzMjgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.4EKiu0pDbusMhL4u7HItGVFlSirKnq-H9SYqKiAO4YY)
Accordion dropdown shows calendar-
![image](https://private-user-images.githubusercontent.com/44861896/410893795-8d39ca97-4816-46bc-b27f-f37f5040f45f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2OTE5NDEsIm5iZiI6MTczOTY5MTY0MSwicGF0aCI6Ii80NDg2MTg5Ni80MTA4OTM3OTUtOGQzOWNhOTctNDgxNi00NmJjLWIyN2YtZjM3ZjUwNDBmNDVmLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDA3NDA0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTg4MzcwNGYxYTI1NWQ3ZGQ5NjkxMDgzNjgwYmM4ZDgyYTQ0Yjc3YWU1YTE5N2U5ZTc0MmNiYTJjOWE5NDYwMTMmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.pGvCnEYCnnQatGeogTpxSc8a44yrrOlPxWIVN-LAXQ4)
Hide facilities without stock, alphabetically sorted-
![image](https://private-user-images.githubusercontent.com/44861896/410893894-6f0da21f-db5e-4a59-9557-b6666b0ae348.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2OTE5NDEsIm5iZiI6MTczOTY5MTY0MSwicGF0aCI6Ii80NDg2MTg5Ni80MTA4OTM4OTQtNmYwZGEyMWYtZGI1ZS00YTU5LTk1NTctYjY2NjZiMGFlMzQ4LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDA3NDA0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTVlNzRhMjI5NThmNDkzZDFmYWEzZGVjNmQ4ZmFjNTlmMjM5YmFmMjU5NTNlNDJmOWM4MzdlOWQyZGJmZDM3Y2EmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.ENVAvD9fr2AocJxRlarzJbelqHkn2g-yH8qdkZl4WI8)
Hide facilities without stock, sorted by distance-
![image](https://private-user-images.githubusercontent.com/44861896/410894001-664dd126-524d-4f34-9711-41980e070cb1.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2OTE5NDEsIm5iZiI6MTczOTY5MTY0MSwicGF0aCI6Ii80NDg2MTg5Ni80MTA4OTQwMDEtNjY0ZGQxMjYtNTI0ZC00ZjM0LTk3MTEtNDE5ODBlMDcwY2IxLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDA3NDA0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTFjNDNiYTNkYmZhNTQ5NDhkNDFiYTZlMGE0MWM0ZmNkMGE0ZGE0MWQxMDE0Y2VmMTBlYTVlNTRiMmYxN2QxZGYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.pkJZXGCxq1iUUHj5u1w7d4DWVn2DGSg0LKLtZGlbOxc)
Sorting by distance only-
![image](https://private-user-images.githubusercontent.com/44861896/410894090-2f30a9e6-0d82-4366-94dd-d3cd189f68a4.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2OTE5NDEsIm5iZiI6MTczOTY5MTY0MSwicGF0aCI6Ii80NDg2MTg5Ni80MTA4OTQwOTAtMmYzMGE5ZTYtMGQ4Mi00MzY2LTk0ZGQtZDNjZDE4OWY2OGE0LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDA3NDA0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTA1Mzk3ZDM3OTIwN2M4NzM0ZmI5YTIzMWY1ZDQxYTI0OWE1YzllMTgyOTgwNjNlOTFlYzMxYjc1OGQ0NjJhYTUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.mlieSkjxcHVLI5oNbqvl2iNhQBB3ZAnXpJTivEcjxCY)
Searchbar testing-
![image](https://private-user-images.githubusercontent.com/44861896/410894192-135df22c-f0fc-4c11-8802-d4df23395a87.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk2OTE5NDEsIm5iZiI6MTczOTY5MTY0MSwicGF0aCI6Ii80NDg2MTg5Ni80MTA4OTQxOTItMTM1ZGYyMmMtZjBmYy00YzExLTg4MDItZDRkZjIzMzk1YTg3LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAyMTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMjE2VDA3NDA0MVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTM4Y2E0NzliZmVkMmMxYTE1MmYwN2ZmNWVjMTIxMjZkNDhmY2MyZDg0ZDE2ZmMzYTI5Y2NmOGJjNDAxMmUxZWImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.Tn_zjbyrMYZgnmnZXBhQj02bkFD2DbWc1CBVFnwSTDQ)
Contribution and Currently Important Rules Acceptance