diff --git a/fittrackee_client/src/components/Common/Pagination.vue b/fittrackee_client/src/components/Common/Pagination.vue index f93584e9..47d113dc 100644 --- a/fittrackee_client/src/components/Common/Pagination.vue +++ b/fittrackee_client/src/components/Common/Pagination.vue @@ -50,13 +50,14 @@ import { toRefs } from 'vue' import { IPagination, TPaginationPayload } from '@/types/api' + import { IOauth2ClientsPayload } from '@/types/oauth' import { TWorkoutsPayload } from '@/types/workouts' import { rangePagination } from '@/utils/api' interface Props { pagination: IPagination path: string - query: TWorkoutsPayload | TPaginationPayload + query: TWorkoutsPayload | TPaginationPayload | IOauth2ClientsPayload } const props = defineProps() diff --git a/fittrackee_client/src/components/User/ProfileDisplay/index.vue b/fittrackee_client/src/components/User/ProfileDisplay/index.vue index 63da634d..e29f38ae 100644 --- a/fittrackee_client/src/components/User/ProfileDisplay/index.vue +++ b/fittrackee_client/src/components/User/ProfileDisplay/index.vue @@ -22,7 +22,7 @@ const props = defineProps() const { user, tab } = toRefs(props) - const tabs = ['PROFILE', 'PREFERENCES', 'SPORTS'] + const tabs = ['PROFILE', 'PREFERENCES', 'SPORTS', 'APPS'] diff --git a/fittrackee_client/src/components/User/UserApps/index.vue b/fittrackee_client/src/components/User/UserApps/index.vue new file mode 100644 index 00000000..62aa00bd --- /dev/null +++ b/fittrackee_client/src/components/User/UserApps/index.vue @@ -0,0 +1,18 @@ + + + diff --git a/fittrackee_client/src/components/User/UserProfileTabs.vue b/fittrackee_client/src/components/User/UserProfileTabs.vue index 794c3e03..ea963045 100644 --- a/fittrackee_client/src/components/User/UserProfileTabs.vue +++ b/fittrackee_client/src/components/User/UserProfileTabs.vue @@ -38,6 +38,7 @@ case 'ACCOUNT': case 'PICTURE': return `/profile/edit/${tab.toLocaleLowerCase()}` + case 'APPS': case 'PREFERENCES': case 'SPORTS': return `/profile${ diff --git a/fittrackee_client/src/locales/en/en.ts b/fittrackee_client/src/locales/en/en.ts index 26b7052d..3b66703f 100644 --- a/fittrackee_client/src/locales/en/en.ts +++ b/fittrackee_client/src/locales/en/en.ts @@ -5,6 +5,7 @@ import ButtonsTranslations from './buttons.json' import CommonTranslations from './common.json' import DashboardTranslations from './dashboard.json' import ErrorTranslations from './error.json' +import OAuth2Translations from './oauth2.json' import SportsTranslations from './sports.json' import StatisticsTranslations from './statistics.json' import UserTranslations from './user.json' @@ -18,6 +19,7 @@ export default { common: CommonTranslations, dashboard: DashboardTranslations, error: ErrorTranslations, + oauth2: OAuth2Translations, sports: SportsTranslations, statistics: StatisticsTranslations, user: UserTranslations, diff --git a/fittrackee_client/src/locales/en/oauth2.json b/fittrackee_client/src/locales/en/oauth2.json new file mode 100644 index 00000000..b50c72e0 --- /dev/null +++ b/fittrackee_client/src/locales/en/oauth2.json @@ -0,0 +1,7 @@ +{ + "APP":{ + "ISSUE_AT": "issued at" + }, + "APPS_LIST": "OAuth2 applications", + "NO_APPS": "No applications" +} \ No newline at end of file diff --git a/fittrackee_client/src/locales/en/user.json b/fittrackee_client/src/locales/en/user.json index 23f9fb55..411cdfa3 100644 --- a/fittrackee_client/src/locales/en/user.json +++ b/fittrackee_client/src/locales/en/user.json @@ -72,6 +72,7 @@ "SUNDAY": "Sunday", "TABS": { "ACCOUNT": "account", + "APPS": "apps", "PICTURE": "picture", "PREFERENCES": "preferences", "PROFILE": "profile", diff --git a/fittrackee_client/src/locales/fr/fr.ts b/fittrackee_client/src/locales/fr/fr.ts index 26b7052d..3b66703f 100644 --- a/fittrackee_client/src/locales/fr/fr.ts +++ b/fittrackee_client/src/locales/fr/fr.ts @@ -5,6 +5,7 @@ import ButtonsTranslations from './buttons.json' import CommonTranslations from './common.json' import DashboardTranslations from './dashboard.json' import ErrorTranslations from './error.json' +import OAuth2Translations from './oauth2.json' import SportsTranslations from './sports.json' import StatisticsTranslations from './statistics.json' import UserTranslations from './user.json' @@ -18,6 +19,7 @@ export default { common: CommonTranslations, dashboard: DashboardTranslations, error: ErrorTranslations, + oauth2: OAuth2Translations, sports: SportsTranslations, statistics: StatisticsTranslations, user: UserTranslations, diff --git a/fittrackee_client/src/locales/fr/oauth2.json b/fittrackee_client/src/locales/fr/oauth2.json new file mode 100644 index 00000000..e23a545c --- /dev/null +++ b/fittrackee_client/src/locales/fr/oauth2.json @@ -0,0 +1,7 @@ +{ + "APP":{ + "ISSUE_AT": "créée le" + }, + "APPS_LIST": "Applications OAuth2", + "NO_APPS": "pas de applications" +} \ No newline at end of file diff --git a/fittrackee_client/src/locales/fr/user.json b/fittrackee_client/src/locales/fr/user.json index 091cb4d0..cb070072 100644 --- a/fittrackee_client/src/locales/fr/user.json +++ b/fittrackee_client/src/locales/fr/user.json @@ -72,6 +72,7 @@ "SUNDAY": "Dimanche", "TABS": { "ACCOUNT": "compte", + "APPS": "apps", "PICTURE": "image", "PREFERENCES": "préférences", "PROFILE": "profil", diff --git a/fittrackee_client/src/router/index.ts b/fittrackee_client/src/router/index.ts index 1ab827fe..358b591e 100644 --- a/fittrackee_client/src/router/index.ts +++ b/fittrackee_client/src/router/index.ts @@ -12,6 +12,8 @@ import UserAccountEdition from '@/components/User/ProfileEdition/UserAccountEdit import UserInfosEdition from '@/components/User/ProfileEdition/UserInfosEdition.vue' import UserPictureEdition from '@/components/User/ProfileEdition/UserPictureEdition.vue' import UserPreferencesEdition from '@/components/User/ProfileEdition/UserPreferencesEdition.vue' +import UserApps from '@/components/User/UserApps/index.vue' +import UserAppsList from '@/components/User/UserApps/UserAppsList.vue' import UserSportPreferences from '@/components/User/UserSportPreferences.vue' import store from '@/store' import { AUTH_USER_STORE } from '@/store/constants' @@ -144,6 +146,18 @@ const routes: Array = [ component: UserSportPreferences, props: { isEdition: false }, }, + { + path: 'apps', + name: 'UserApps', + component: UserApps, + children: [ + { + path: '', + name: 'UserAppsList', + component: UserAppsList, + }, + ], + }, ], }, { diff --git a/fittrackee_client/src/scss/base.scss b/fittrackee_client/src/scss/base.scss index 99618d45..0d5e497c 100644 --- a/fittrackee_client/src/scss/base.scss +++ b/fittrackee_client/src/scss/base.scss @@ -67,7 +67,7 @@ button { transform: translateY(2px); } - &:disabled { + &:disabled, &.confirm:disabled { background: var(--disabled-background-color); border-color: var(--disabled-color); color: var(--disabled-color); diff --git a/fittrackee_client/src/store/constants.ts b/fittrackee_client/src/store/constants.ts index c84856ef..2f2535b9 100644 --- a/fittrackee_client/src/store/constants.ts +++ b/fittrackee_client/src/store/constants.ts @@ -3,6 +3,11 @@ import { AuthUserGetters, AuthUserMutations, } from '@/store/modules/authUser/enums' +import { + OAuth2Actions, + OAuth2Getters, + OAuth2Mutations, +} from '@/store/modules/oauth2/enums' import { RootActions, RootGetters, @@ -52,6 +57,11 @@ export const AUTH_USER_STORE = { GETTERS: AuthUserGetters, MUTATIONS: AuthUserMutations, } +export const OAUTH2_STORE = { + ACTIONS: OAuth2Actions, + GETTERS: OAuth2Getters, + MUTATIONS: OAuth2Mutations, +} export const USERS_STORE = { ACTIONS: UsersActions, diff --git a/fittrackee_client/src/store/modules/oauth2/actions.ts b/fittrackee_client/src/store/modules/oauth2/actions.ts new file mode 100644 index 00000000..dd20c78c --- /dev/null +++ b/fittrackee_client/src/store/modules/oauth2/actions.ts @@ -0,0 +1,36 @@ +import { ActionContext, ActionTree } from 'vuex' + +import authApi from '@/api/authApi' +import { OAUTH2_STORE, ROOT_STORE } from '@/store/constants' +import { IOAuth2Actions, IOAuth2State } from '@/store/modules/oauth2/types' +import { IRootState } from '@/store/modules/root/types' +import { IOauth2ClientsPayload } from '@/types/oauth' +import { handleError } from '@/utils' + +export const actions: ActionTree & IOAuth2Actions = { + [OAUTH2_STORE.ACTIONS.GET_CLIENTS]( + context: ActionContext, + payload: IOauth2ClientsPayload + ): void { + context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES) + authApi + .get('oauth/apps', { + params: payload, + }) + .then((res) => { + if (res.data.status === 'success') { + context.commit( + OAUTH2_STORE.MUTATIONS.SET_CLIENTS, + res.data.data.clients + ) + context.commit( + OAUTH2_STORE.MUTATIONS.SET_CLIENTS_PAGINATION, + res.data.pagination + ) + } else { + handleError(context, null) + } + }) + .catch((error) => handleError(context, error)) + }, +} diff --git a/fittrackee_client/src/store/modules/oauth2/enums.ts b/fittrackee_client/src/store/modules/oauth2/enums.ts new file mode 100644 index 00000000..a03f50ba --- /dev/null +++ b/fittrackee_client/src/store/modules/oauth2/enums.ts @@ -0,0 +1,13 @@ +export enum OAuth2Actions { + GET_CLIENTS = 'GET_CLIENTS', +} + +export enum OAuth2Getters { + CLIENTS = 'CLIENTS', + CLIENTS_PAGINATION = 'CLIENTS_PAGINATION', +} + +export enum OAuth2Mutations { + SET_CLIENTS = 'SET_CLIENTS', + SET_CLIENTS_PAGINATION = 'SET_CLIENTS_PAGINATION', +} diff --git a/fittrackee_client/src/store/modules/oauth2/getters.ts b/fittrackee_client/src/store/modules/oauth2/getters.ts new file mode 100644 index 00000000..c88f72b5 --- /dev/null +++ b/fittrackee_client/src/store/modules/oauth2/getters.ts @@ -0,0 +1,11 @@ +import { GetterTree } from 'vuex' + +import { OAUTH2_STORE } from '@/store/constants' +import { IOAuth2Getters, IOAuth2State } from '@/store/modules/oauth2/types' +import { IRootState } from '@/store/modules/root/types' + +export const getters: GetterTree & IOAuth2Getters = { + [OAUTH2_STORE.GETTERS.CLIENTS]: (state: IOAuth2State) => state.clients, + [OAUTH2_STORE.GETTERS.CLIENTS_PAGINATION]: (state: IOAuth2State) => + state.pagination, +} diff --git a/fittrackee_client/src/store/modules/oauth2/index.ts b/fittrackee_client/src/store/modules/oauth2/index.ts new file mode 100644 index 00000000..90563ec2 --- /dev/null +++ b/fittrackee_client/src/store/modules/oauth2/index.ts @@ -0,0 +1,17 @@ +import { Module } from 'vuex' + +import { actions } from '@/store/modules/oauth2/actions' +import { getters } from '@/store/modules/oauth2/getters' +import { mutations } from '@/store/modules/oauth2/mutations' +import { oAuth2State } from '@/store/modules/oauth2/state' +import { IOAuth2State } from '@/store/modules/oauth2/types' +import { IRootState } from '@/store/modules/root/types' + +const oauth2: Module = { + state: oAuth2State, + actions, + getters, + mutations, +} + +export default oauth2 diff --git a/fittrackee_client/src/store/modules/oauth2/mutations.ts b/fittrackee_client/src/store/modules/oauth2/mutations.ts new file mode 100644 index 00000000..0480e0a2 --- /dev/null +++ b/fittrackee_client/src/store/modules/oauth2/mutations.ts @@ -0,0 +1,21 @@ +import { MutationTree } from 'vuex' + +import { OAUTH2_STORE } from '@/store/constants' +import { IOAuth2State, TOAuth2Mutations } from '@/store/modules/oauth2/types' +import { IPagination } from '@/types/api' +import { IOAuth2Client } from '@/types/oauth' + +export const mutations: MutationTree & TOAuth2Mutations = { + [OAUTH2_STORE.MUTATIONS.SET_CLIENTS]( + state: IOAuth2State, + clients: IOAuth2Client[] + ) { + state.clients = clients + }, + [OAUTH2_STORE.MUTATIONS.SET_CLIENTS_PAGINATION]( + state: IOAuth2State, + pagination: IPagination + ) { + state.pagination = pagination + }, +} diff --git a/fittrackee_client/src/store/modules/oauth2/state.ts b/fittrackee_client/src/store/modules/oauth2/state.ts new file mode 100644 index 00000000..47c19e21 --- /dev/null +++ b/fittrackee_client/src/store/modules/oauth2/state.ts @@ -0,0 +1,7 @@ +import { IOAuth2State } from '@/store/modules/oauth2/types' +import { IPagination } from '@/types/api' + +export const oAuth2State: IOAuth2State = { + clients: [], + pagination: {}, +} diff --git a/fittrackee_client/src/store/modules/oauth2/types.ts b/fittrackee_client/src/store/modules/oauth2/types.ts new file mode 100644 index 00000000..2c00c780 --- /dev/null +++ b/fittrackee_client/src/store/modules/oauth2/types.ts @@ -0,0 +1,60 @@ +import { + ActionContext, + CommitOptions, + DispatchOptions, + Store as VuexStore, +} from 'vuex' + +import { OAUTH2_STORE } from '@/store/constants' +import { IRootState } from '@/store/modules/root/types' +import { IPagination } from '@/types/api' +import { IOAuth2Client, IOauth2ClientsPayload } from '@/types/oauth' + +export interface IOAuth2State { + clients: IOAuth2Client[] + pagination: IPagination +} + +export interface IOAuth2Actions { + [OAUTH2_STORE.ACTIONS.GET_CLIENTS]( + context: ActionContext, + payload: IOauth2ClientsPayload + ): void +} + +export interface IOAuth2Getters { + [OAUTH2_STORE.GETTERS.CLIENTS](state: IOAuth2State): IOAuth2Client[] + [OAUTH2_STORE.GETTERS.CLIENTS_PAGINATION](state: IOAuth2State): IPagination +} + +export type TOAuth2Mutations = { + [OAUTH2_STORE.MUTATIONS.SET_CLIENTS](state: S, clients: IOAuth2Client[]): void + [OAUTH2_STORE.MUTATIONS.SET_CLIENTS_PAGINATION]( + state: S, + pagination: IPagination + ): void +} + +export type TOAuth2StoreModule = Omit< + VuexStore, + 'commit' | 'getters' | 'dispatch' +> & { + dispatch( + key: K, + payload?: Parameters[1], + options?: DispatchOptions + ): ReturnType +} & { + getters: { + [K in keyof IOAuth2Getters]: ReturnType + } +} & { + commit< + K extends keyof TOAuth2Mutations, + P extends Parameters[1] + >( + key: K, + payload?: P, + options?: CommitOptions + ): ReturnType +} diff --git a/fittrackee_client/src/store/modules/root/index.ts b/fittrackee_client/src/store/modules/root/index.ts index a2176d85..bdf048c4 100644 --- a/fittrackee_client/src/store/modules/root/index.ts +++ b/fittrackee_client/src/store/modules/root/index.ts @@ -1,6 +1,7 @@ import { Module, ModuleTree } from 'vuex' import authUserModule from '@/store/modules/authUser' +import oAuthModule from '@/store/modules/oauth2' import { actions } from '@/store/modules/root/actions' import { getters } from '@/store/modules/root/getters' import { mutations } from '@/store/modules/root/mutations' @@ -13,6 +14,7 @@ import workoutsModule from '@/store/modules/workouts' const modules: ModuleTree = { authUserModule, + oAuthModule, sportsModule, statsModule, usersModule, diff --git a/fittrackee_client/src/store/types.ts b/fittrackee_client/src/store/types.ts index 34d8833a..599f78c4 100644 --- a/fittrackee_client/src/store/types.ts +++ b/fittrackee_client/src/store/types.ts @@ -1,4 +1,5 @@ import { TAuthUserStoreModule } from '@/store/modules/authUser/types' +import { TOAuth2StoreModule } from '@/store/modules/oauth2/types' import { TRootStoreModule } from '@/store/modules/root/types' import { TSportsStoreModule } from '@/store/modules/sports/types' import { TStatisticsStoreModule } from '@/store/modules/statistics/types' @@ -7,6 +8,7 @@ import { TWorkoutsStoreModule } from '@/store/modules/workouts/types' type StoreModules = { authUserModule: TAuthUserStoreModule + oauth2Module: TOAuth2StoreModule rootModule: TRootStoreModule sportsModule: TSportsStoreModule statsModule: TStatisticsStoreModule @@ -15,6 +17,7 @@ type StoreModules = { } export type Store = TAuthUserStoreModule> & + TOAuth2StoreModule> & TSportsStoreModule> & TStatisticsStoreModule> & TWorkoutsStoreModule> & diff --git a/fittrackee_client/src/types/oauth.ts b/fittrackee_client/src/types/oauth.ts new file mode 100644 index 00000000..4d1e070c --- /dev/null +++ b/fittrackee_client/src/types/oauth.ts @@ -0,0 +1,15 @@ +export interface IOAuth2Client { + client_id: string + client_description: string | null + client_secret?: string + id: number + issued_at: string + name: string + redirect_uris: string[] + scope: string + website: string +} + +export interface IOauth2ClientsPayload { + page?: number +} diff --git a/fittrackee_client/src/utils/index.ts b/fittrackee_client/src/utils/index.ts index af2930c5..bbdd3f6f 100644 --- a/fittrackee_client/src/utils/index.ts +++ b/fittrackee_client/src/utils/index.ts @@ -3,6 +3,7 @@ import { ActionContext } from 'vuex' import { ROOT_STORE } from '@/store/constants' import { IAuthUserState } from '@/store/modules/authUser/types' +import { IOAuth2State } from '@/store/modules/oauth2/types' import { IRootState } from '@/store/modules/root/types' import { ISportsState } from '@/store/modules/sports/types' import { IStatisticsState } from '@/store/modules/statistics/types' @@ -19,6 +20,7 @@ export const handleError = ( context: | ActionContext | ActionContext + | ActionContext | ActionContext | ActionContext | ActionContext