Skip to content
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

Feature/custom ringtone [WTEL-4348] #706

Merged
merged 16 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from 10 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
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ VITE_CRM_URL = '/crm'
VITE_OMNI_WIDGET_URL = '/omni-widget'
VITE_FLOW_DIAGRAM_URL = '/flow'
VITE_START_PAGE_URL = '/'
VITE_RINGTONES_URL = '/ringtones'
5 changes: 5 additions & 0 deletions src/app/locale/en/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export default {
webPhone: 'WebPhone',
useWebPhone: 'Use WebPhone',
useStun: 'Use STUN',
ringtones: {
title: 'Change ringtone',
ringtone: 'Ringtone',
customRingtone: 'Use the custom ringtone',
},
},

validation: {
Expand Down
5 changes: 5 additions & 0 deletions src/app/locale/ru/ru.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export default {
webPhone: 'Web-телефон',
useWebPhone: 'Использовать Web-телефон',
useStun: 'Использовать STUN',
ringtones: {
title: 'Поменять рингтон',
ringtone: 'Рингтон',
customRingtone: 'Использовать кастомный рингтон',
},
},

validation: {
Expand Down
5 changes: 5 additions & 0 deletions src/app/locale/ua/ua.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ export default {
webPhone: 'Web-телефон',
useWebPhone: 'Використовувати Web-телефон',
useStun: 'Використовувати STUN',
ringtones: {
title: 'Змінити рінгтон',
ringtone: 'Рінгтон',
customRingtone: 'Використовувати кастомний рінгтон',
},
},

validation: {
Expand Down
57 changes: 43 additions & 14 deletions src/modules/settings/api/settings.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import instance from '../../../app/api/instance';
import applyTransform, {
camelToSnake,
notify,
snakeToCamel,
} from '@webitel/ui-sdk/src/api/transformers';
import instance from '../../../app/api/instance';

const baseUrl = 'users';

Expand All @@ -12,47 +12,76 @@ export const getWebPhone = async () => {

try {
const response = await instance.get(url);
return applyTransform(response.data, [snakeToCamel()]);
return applyTransform(response.data, [
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

я так зрозуміла, що це біом сплюскує отак applyTransform, а я його, виходить, заново "росправила"
мені, насправді, так не подобається як воно в одну строчку виглядає...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

мені теж
але тоді треба шукати як пофіксити біом)

snakeToCamel(),
]);
} catch (err) {
if (err.response.status === 404) return;
// phone settings doesn't exist on backend if user is new, and we have to hide notification about this error
// https://webitel.atlassian.net/browse/WTEL-4346
throw applyTransform(err, [notify]);
throw applyTransform(err, [
notify,
]);
}
};

export const changeWebPhone = async (changes) => {
const item = applyTransform(changes, [camelToSnake()]);

const item = applyTransform(changes, [
camelToSnake(),
]);

const url = 'user/settings/phone';

try {
const response = await instance.put(url, item);
return applyTransform(response.data, [snakeToCamel()]);
return applyTransform(response.data, [
snakeToCamel(),
]);
} catch (err) {
throw applyTransform(err, [
notify,
]);
}
};

export const getRingtonesList = async () => {
try {
const ringtones = await fetch(`${import.meta.env.VITE_RINGTONES_URL}/index.json`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я не впевнена що треба саме виносити у env, бо він більше включає загальні змінні для перевикористання

Copy link
Contributor Author

@liza-pohranichna liza-pohranichna Jul 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Даня в описі до задачі просто писав, шо тре

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

треба, бо це за межами апплікейшена

.then((res) => res.json());
return ringtones.ringtones;
} catch (err) {
throw applyTransform(err, [notify]);
throw applyTransform(err, [
notify,
]);
}
};

const patchItem = async ({ changes, id }) => {
const body = applyTransform(changes, [camelToSnake()]);
const body = applyTransform(changes, [
camelToSnake(),
]);
const url = `${baseUrl}/${id}`;
try {
const response = await instance.patch(url, body);
return applyTransform(response.data, [snakeToCamel()]);
return applyTransform(response.data, [
snakeToCamel(),
]);
} catch (err) {
throw applyTransform(err, [notify]);
throw applyTransform(err, [
notify,
]);
}
};

export const changePassword = ({ id, changes }) =>
patchItem({
id,
changes,
});
export const changePassword = ({ id, changes }) => patchItem({
id,
changes,
});

export default {
changePassword,
changeWebPhone,
getWebPhone,
getRingtonesList,
};
113 changes: 113 additions & 0 deletions src/modules/settings/components/the-ringtone.vue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а чого the-ringtone, а не, скажімо, custom-ringtone?

Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<template>
<section class="settings-section__setting">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Клас цей тут не потрібен, а як потрібен - називаємо як компонент)

<header class="content-header">
<h3 class="content-title">
{{ $t('settings.ringtones.title') }}
</h3>
</header>
<form>
<div class="settings-section__wrapper">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а дів тут точно потрібен?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

так

<wt-checkbox
v-model="isCustomRingtone"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

з велью не працює, працює з :selected. змінила

:label="$tc('settings.ringtones.customRingtone')"
@change="selectRingtoneType"
/>
<wt-select
v-model="currentRingtone"
:options="options"
:disabled="!isCustomRingtone"
:clearable="false"
:label="$tc('settings.ringtones.ringtone')"
option-label="label"
track-by="label"
/>
<wt-player
v-show="audioLink"
:src="audioLink"
:closable="false"
:autoplay="false"
/>
<wt-button
@click.prevent="saveRingtone"
>
{{ $t('objects.save') }}
</wt-button>
</div>
</form>
</section>
</template>

<script>
import { useVuelidate } from '@vuelidate/core';
import { getRingtonesList } from '../api/settings';

export default {
name: 'TheRingtone',
setup: () => ({
v$: useVuelidate(),
}),
data: () => ({
isCustomRingtone: false,
currentRingtone: {},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

може просто ringtone?

options: [],
}),
computed: {
currentRingtone: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а чому саме get/set потрібен?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

я досить довго проколупалась з тим, що "звичними способами" не працює. Схоже, через те, що ми в данному випадку оперуємо об'єктами, а не простими типами данних.
Тому знайшла в коді приклад з get/set, який запрацював.
Тобто, схоже, особливість того, як працює наш мультиселект, якщо мова про оперування об'єктами.

get() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

все таки не розумію навіщо гетер/сетер(

return this.currentRingtone;
},
set(value) {
this.currentRingtone = value;
},
},
audioLink() {
return this.currentRingtone.name && this.isCustomRingtone ?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Умова повторюється, давай її у компьютед)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

зробила

`${import.meta.env.VITE_RINGTONES_URL}${this.currentRingtone.name}`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

може /?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

точно, дякую!

: '';
},
},
async mounted() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mounted нижче методів)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

та наче ні... методи внизу, маунтед зверху
чи може я не вірно тебе зрозуміла?

Copy link
Contributor Author

@liza-pohranichna liza-pohranichna Jul 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

поміняла) мені чогось всю дорогу здавалось, що навпаки

try {
await this.loadRingtonesOptions();
this.restoreRingtone();
} catch (error) {
throw error;
}
},
methods: {
selectRingtoneType() {
if (this.isCustomRingtone && this.currentRingtone.name) this.currentRingtone = {};
},
saveRingtone() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saveRingtoneInLocalStorage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а нашо? якщо ми просто зберігаємо рінгтон, у нас немає інших типів збереження тут наразі, щоб ми могли з чимось сплутати
Мені здається, saveRingtone досить зрозуміло і локанічно. Стандартна дія, яка відбувається при кліку на кнопку save

this.currentRingtone.name
? localStorage.setItem('ringtone', this.currentRingtone.name)
: localStorage.removeItem('ringtone');
},
async loadRingtonesOptions() {
this.options = await getRingtonesList();
},
restoreRingtone() {
const ringtoneName = localStorage.getItem('ringtone');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я думаю якщо в локалСторадж ти зберігаєш тільки імя - то може і ключ назвати ringtone-name
А якщо не тільки імя - то тоді ця змінна має бути ringtone)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Чесно кажучи, не бачу сенсу називати в локал стореджі ringtoneName
Бо и локалстореджі зберігається багато різних сутностей і, як на мене, сутність "рінгтон" виглядає досить зрозуміло, просто і однозначно

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

треба settings/ringtone, або settings/custom-ringtone (я думаю, 1ше краще)

if (ringtoneName) {
this.currentRingtone = this.options.find(item => item.name === ringtoneName);
this.isCustomRingtone = true;
}
},
},

};
</script>

<style lang="scss" scoped>
.settings-section__wrapper {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Давай адаптуємо назви классів до назви компонента)

display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}

.wt-button {
display: block;
margin: 3px 0 0 auto;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а шо це за 3 пікселі затіхарілісь?))

}
</style>

7 changes: 5 additions & 2 deletions src/modules/settings/components/the-settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
</div>
</form>
</section>
<the-ringtone class="settings-section__setting" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Розберись будь ласочка з цим классом)
1 - settings-section__setting нема такого классу, є тільки settings-section. Да і чи потрібен він тобі
2 - цей же клас є в середині твого нового компонента, думаю він там не потрібен)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Насправді, в сеттінгах є цей класс
Тому я його і використовую. Тут зараз приберу.
Але, гадаю, цей момент, скоріше, ще вилізе в тасці call-end-notification, бо там робила візуальні зміни в сеттінгах, опираючись на ті класи, які зараз є.

</section>
</template>
</wt-page-wrapper>
Expand All @@ -93,10 +94,12 @@ import { useVuelidate } from '@vuelidate/core';
import { required, sameAs } from '@vuelidate/validators';
import getNamespacedState from '@webitel/ui-sdk/src/store/helpers/getNamespacedState';
import { mapState } from 'vuex';
import { changePassword, changeWebPhone, getWebPhone } from '../api/settings';
import { changePassword, changeWebPhone, getWebPhone, getRingtonesList } from '../api/settings';
import TheRingtone from './the-ringtone.vue';

export default {
name: 'TheSettings',
components: { TheRingtone },
inject: ['$eventBus'],

setup: () => ({
Expand Down Expand Up @@ -251,7 +254,7 @@ export default {
}

&__switcher {
margin-bottom: var(--spacing-xs);
margin-bottom: var(--spacing-sm);
}
}
</style>
Loading