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

feat: save last connected organization #1472

Merged
merged 14 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions front-end/src/main/shared/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export const DISPLAY_FILE_SIZE_LIMIT = 512 * 1024;
/* Claim */
export const DEFAULT_MAX_TRANSACTION_FEE_CLAIM_KEY = 'default_max_transaction_fee';
export const SELECTED_NETWORK = 'selected_network';
export const LAST_SELECTED_ORGANIZATION = 'last_selected_organization';
export const DEFAULT_ORGANIZATION_OPTION = 'default_organization_option';
export const USE_KEYCHAIN = 'use_keychain';
export const UPDATE_LOCATION = 'update_location';
export const MIGRATION_STARTED = 'migration_started';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useAutoLogin from '@renderer/composables/useAutoLogin';
import useLoader from '@renderer/composables/useLoader';
import useSetupStores from '@renderer/composables/user/useSetupStores';
import useRecoveryPhraseHashMigrate from '@renderer/composables/useRecoveryPhraseHashMigrate';
import useDefaultOrganization from '@renderer/composables/user/useDefaultOrganization';

import { getUseKeychain } from '@renderer/services/safeStorageService';
import { getUsersCount, resetDataLocal } from '@renderer/services/userService';
Expand All @@ -26,6 +27,7 @@ const user = useUserStore();
const withLoader = useLoader();
const tryAutoLogin = useAutoLogin();
const setupStores = useSetupStores();
const { select: selectDefaultOrganization } = useDefaultOrganization();
const { redirectIfRequiredKeysToMigrate } = useRecoveryPhraseHashMigrate();

/* State */
Expand All @@ -44,10 +46,14 @@ const handleImportantModalReady = async () => {

const handleBeginMigrationReadyState = async () => {
await withLoader(tryAutoLogin);

const redirect = await redirectIfRequiredKeysToMigrate();
if (!redirect) {
await withLoader(selectDefaultOrganization);
}

await user.refetchOrganizations();
await setupStores();

await redirectIfRequiredKeysToMigrate();
};

/* Hooks */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,6 @@ async function sendSignedTransactionsToOrganization() {
transactionGroup.description,
false,
transactionGroup.sequential,
transactionGroup.groupValidStart,
apiGroupItems,
);

Expand Down
4 changes: 4 additions & 0 deletions front-end/src/renderer/components/UserModeSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useNotificationsStore from '@renderer/stores/storeNotifications';
import useLoader from '@renderer/composables/useLoader';
import useCreateTooltips from '@renderer/composables/useCreateTooltips';
import useRecoveryPhraseHashMigrate from '@renderer/composables/useRecoveryPhraseHashMigrate';
import useDefaultOrganization from '@renderer/composables/user/useDefaultOrganization';

import { isOrganizationActive } from '@renderer/utils';

Expand All @@ -26,6 +27,7 @@ const notifications = useNotificationsStore();
const withLoader = useLoader();
const createTooltips = useCreateTooltips();
const { redirectIfRequiredKeysToMigrate } = useRecoveryPhraseHashMigrate();
const { setLast } = useDefaultOrganization();

/* State */
const selectedMode = ref<string>('personal');
Expand Down Expand Up @@ -54,6 +56,7 @@ const handleUserModeChange = async (e: Event) => {
dropDownValue.value = personalModeText;
await user.selectOrganization(null);
await redirectIfRequiredKeysToMigrate();
await setLast(null);
} else {
selectedMode.value = org ? org.id : 'personal';
const organizationNickname =
Expand All @@ -72,6 +75,7 @@ const handleUserModeChange = async (e: Event) => {

if (isOrganizationActive(user.selectedOrganization)) {
dropDownValue.value = organizationNickname;
await setLast(user.selectedOrganization?.id || null);
}

await redirectIfRequiredKeysToMigrate();
Expand Down
2 changes: 2 additions & 0 deletions front-end/src/renderer/composables/user/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './useAfterOrganizationSelection';
export * from './useSetupStores';
export * from './useDefaultOrganization';
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import useUserStore from '@renderer/stores/storeUser';

import { useRouter } from 'vue-router';

import useSetupStores from '@renderer/composables/user/useSetupStores';

import { get as getStoredMnemonics } from '@renderer/services/mnemonicService';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import useUserStore from '@renderer/stores/storeUser';

import { DEFAULT_ORGANIZATION_OPTION, LAST_SELECTED_ORGANIZATION } from '@main/shared/constants';

import { getOrganizations } from '@renderer/services/organizationsService';
import { getStoredClaim, add, update, remove } from '@renderer/services/claimService';

import { isUserLoggedIn, safeAwait } from '@renderer/utils';

export default function useDefaultOrganization() {
/* Stores */
const user = useUserStore();

/* Functions */
const get = async (key: string) => {
if (isUserLoggedIn(user.personal)) {
const { data } = await safeAwait(getStoredClaim(user.personal.id, key));
return data;
}
};

const getSelected = async () => {
const defaultOption = await get(DEFAULT_ORGANIZATION_OPTION);

if (defaultOption) {
return defaultOption;
}

return await get(LAST_SELECTED_ORGANIZATION);
};

const getDefault = async () => {
return await get(DEFAULT_ORGANIZATION_OPTION);
};

const set = async (organizationId: string | null, key: string) => {
if (isUserLoggedIn(user.personal)) {
if (organizationId === null) {
await remove(user.personal.id, [key]);
return;
}

const storedId = await get(key);
const addOrUpdate = storedId !== undefined ? update : add;
await addOrUpdate(user.personal.id, key, organizationId);
}
};

const setLast = async (organizationId: string | null) => {
await set(organizationId, LAST_SELECTED_ORGANIZATION);
};

const setDefault = async (organizationId: string | null) => {
await set(organizationId, DEFAULT_ORGANIZATION_OPTION);
};

const select = async () => {
if (isUserLoggedIn(user.personal)) {
const organizationId = await getSelected();

if (organizationId) {
const organizations = await getOrganizations();
const organization = organizations.find(org => org.id === organizationId);

if (organization) {
await user.selectOrganization(organization);
}
}
}
};

return { getDefault, setLast, setDefault, select };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script setup lang="ts">
import { computed, onBeforeMount, ref } from 'vue';

import useUserStore from '@renderer/stores/storeUser';

import useDefaultOrganization from '@renderer/composables/user/useDefaultOrganization';

import { isUserLoggedIn } from '@renderer/utils';

import AppSelect from '@renderer/components/ui/AppSelect.vue';

/* Stores */
const user = useUserStore();

/* Composables */
const { getDefault, setDefault, setLast } = useDefaultOrganization();

/* State */
const defaultOrganizationId = ref<string>('');

/* Computed */
const listedItems = computed(() => {
const organizations = user.organizations.map(org => ({ value: org.id, label: org.nickname }));
return [{ value: '', label: 'None' }, ...organizations];
});

const handleUpdateDefaultOrganization = async (id: string) => {
if (!isUserLoggedIn(user.personal)) return;

await setDefault(id || null);

if(!id) {
await setLast(user.selectedOrganization?.id || null);
}


defaultOrganizationId.value = id;
};

/* Hooks */
onBeforeMount(async () => {
if (isUserLoggedIn(user.personal)) {
defaultOrganizationId.value = (await getDefault()) || '';
}
});
</script>
<template>
<div class="mt-4">
<div class="col-sm-5 col-lg-4">
<label class="form-label me-3">Default Organization</label>
<AppSelect
:value="defaultOrganizationId"
@update:value="handleUpdateDefaultOrganization"
:items="listedItems"
toggle-text="Select Organization"
toggler-icon
:color="'secondary'"
button-class="w-100"
/>
</div>
</div>
</template>
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<script setup lang="ts">
import DefaultOrganization from './DefaultOrganization.vue';
import MaxTransactionFeeSetting from './MaxTransactionFeeSetting.vue';
import UpdateLocation from './UpdateLocation.vue';
</script>
<template>
<div class="p-4 border border-2 rounded-3 mt-5">
<p>Default Settings</p>
<MaxTransactionFeeSetting />
<DefaultOrganization />
<UpdateLocation />
</div>
</template>
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ onBeforeMount(async () => {
<template>
<div class="mt-4">
<div>
<label class="form-label me-3">Update Location</label>
<div class="d-flex align-items-center gap-3 mt-4">
<label class="form-label">Update Location</label>
<div class="d-flex align-items-center gap-3">
<div>
<AppButton type="button" color="primary" @click="handleSelectLocation">Select</AppButton>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ const handleChangeNickname = async (e: Event) => {
} else {
await updateOrganization(user.organizations[index].id, { nickname });
user.organizations[index].nickname = nickname;
await user.refetchOrganizations();
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,9 @@ const stepperItems = computed(() => {
];

if (
[
TransactionStatus.EXPIRED,
TransactionStatus.CANCELED,
TransactionStatus.ARCHIVED,
TransactionStatus.SIGN_ONLY,
].includes(props.transaction.status)
[TransactionStatus.EXPIRED, TransactionStatus.CANCELED, TransactionStatus.ARCHIVED].includes(
props.transaction.status,
)
) {
items.splice(2, 2);
}
Expand All @@ -45,9 +42,7 @@ const stepperItems = computed(() => {
bubbleClass: 'bg-danger text-white',
bubbleIcon: 'x-lg',
};
} else if (
[TransactionStatus.ARCHIVED, TransactionStatus.SIGN_ONLY].includes(props.transaction.status)
) {
} else if ([TransactionStatus.ARCHIVED].includes(props.transaction.status)) {
items.push({ title: 'Archived', name: 'Archived' });
}

Expand All @@ -59,7 +54,6 @@ const stepperActiveIndex = computed(() => {
case TransactionStatus.NEW:
return 0;
case TransactionStatus.WAITING_FOR_SIGNATURES:
case TransactionStatus.SIGN_ONLY:
return 1;
case TransactionStatus.WAITING_FOR_EXECUTION:
return 2;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ async function fetchTransactions() {
try {
const { totalItems: totalItemsCount, items: rawTransactions } = await getTransactionsForUser(
user.selectedOrganization.serverUrl,
[TransactionStatus.WAITING_FOR_SIGNATURES, TransactionStatus.SIGN_ONLY],
[TransactionStatus.WAITING_FOR_SIGNATURES],
network.network,
currentPage.value,
pageSize.value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useRouter } from 'vue-router';
import useCreateTooltips from '@renderer/composables/useCreateTooltips';
import useRecoveryPhraseHashMigrate from '@renderer/composables/useRecoveryPhraseHashMigrate';
import useSetupStores from '@renderer/composables/user/useSetupStores';
import useDefaultOrganization from '@renderer/composables/user/useDefaultOrganization';

import { loginLocal, registerLocal } from '@renderer/services/userService';
import { initializeUseKeychain } from '@renderer/services/safeStorageService';
Expand Down Expand Up @@ -49,6 +50,7 @@ const router = useRouter();
const createTooltips = useCreateTooltips();
const setupStores = useSetupStores();
const { redirectIfRequiredKeysToMigrate } = useRecoveryPhraseHashMigrate();
const { select: selectDefaultOrganization } = useDefaultOrganization();

/* Injected */
const globalModalLoaderRef = inject<GLOBAL_MODAL_LOADER_TYPE>(GLOBAL_MODAL_LOADER_KEY);
Expand Down Expand Up @@ -147,13 +149,15 @@ const handleOnFormSubmit = async () => {

if (user.secretHashes.length === 0) {
await router.push({ name: 'accountSetup' });
} else {
if (await redirectIfRequiredKeysToMigrate()) {
return;
}
return;
}

await redirectToPrevious(router, { name: 'transactions' });
if (await redirectIfRequiredKeysToMigrate()) {
return;
}

await redirectToPrevious(router, { name: 'transactions' });
await selectDefaultOrganization();
} finally {
buttonLoading.value = false;
globalModalLoaderRef?.value?.close();
Expand Down
2 changes: 1 addition & 1 deletion front-end/src/renderer/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as constants from '@renderer/router/constants';

import Transactions from '@renderer/pages/Transactions';
import UserLogin from '@renderer/pages/UserLogin';
import KeysTab from '@renderer/pages/Settings/components/KeysTab';
import CreateTransactionGroup from '@renderer/pages/CreateTransactionGroup/CreateTransactionGroup.vue';
import TransactionGroupDetails from '@renderer/pages/TransactionGroupDetails/TransactionGroupDetails.vue';

Expand All @@ -20,7 +21,6 @@ const SignUpUser = () => import('@renderer/pages/ContactList/SignUpUser');
const AccountSetup = () => import('@renderer/pages/AccountSetup');
const GeneralTab = () => import('@renderer/pages/Settings/components/GeneralTab');
const WorkGroupsTab = () => import('@renderer/pages/Settings/components/WorkGroupsTab.vue');
const KeysTab = () => import('@renderer/pages/Settings/components/KeysTab');
const NotificationsTab = () => import('@renderer/pages/Settings/components/NotificationsTab.vue');
const RestoreKey = () => import('@renderer/pages/RestoreKey');
const CreateTransaction = () => import('@renderer/pages/CreateTransaction');
Expand Down
3 changes: 1 addition & 2 deletions front-end/src/renderer/services/organization/health.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ export const healthCheck = async (serverUrl: string): Promise<boolean> => {
try {
const { data } = await axios.get(`${serverUrl}${healtController}`);
return data || false;
} catch (error) {
console.log(error);
} catch {
return false;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export const getAllInAppNotifications = async (
final = notifications.length >= totalItems;
page++;
}
} catch (error) {
console.log(error);
} catch {
return notifications;
}

return notifications;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export const submitTransactionGroup = async (
description: string,
atomic: boolean,
sequential: boolean,
groupValidStart: Date,
groupItems: ApiGroupItem[],
): Promise<{ id: number; transactionBytes: string }> => {
return commonRequestHandler(async () => {
Expand All @@ -37,7 +36,6 @@ export const submitTransactionGroup = async (
description,
atomic,
sequential,
groupValidStart,
groupItems,
},
{
Expand Down
Loading
Loading