Skip to content

Commit

Permalink
Merge pull request #226 from bcgov/ticdi-104
Browse files Browse the repository at this point in the history
Ticdi 104
  • Loading branch information
mgtennant authored Aug 29, 2024
2 parents 7df8238 + 2d5abde commit 39532e0
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 189 deletions.
282 changes: 110 additions & 172 deletions frontend/src/app/common/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import axios, { AxiosResponse, AxiosError, AxiosRequestConfig } from 'axios';
import axios, { AxiosResponse, AxiosRequestConfig } from 'axios';
import config from '../../config';
import { AUTH_TOKEN } from '../service/user-service';
import UserService from '../service/user-service';
import fileDownload from 'js-file-download';

const STATUS_CODES = {
Expand All @@ -23,100 +23,100 @@ interface ApiRequestParameters<T = {}> {
params?: T;
}

export const get = <T, M = {}>(parameters: ApiRequestParameters<M>, headers?: {}): Promise<T> => {
let config: AxiosRequestConfig = { headers: headers };
return new Promise<T>((resolve, reject) => {
const { url, requiresAuthentication, params } = parameters;

if (requiresAuthentication) {
axios.defaults.headers.common['Authorization'] = `Bearer ${localStorage.getItem(AUTH_TOKEN)}`;
const axiosInstance = axios.create();

// check the token status on every request, refresh it if it is 3 minutes old (5min expiry time)
axiosInstance.interceptors.request.use(
async (config) => {
if (config.headers.Authorization) {
const tokenAge = UserService.getTokenAge();
if (tokenAge > 180) {
// If token is older than 3 minutes
try {
const token = await UserService.updateToken();
config.headers.Authorization = `Bearer ${token}`;
} catch (error) {
console.error('Token refresh failed:', error);
return Promise.reject(error);
}
}
}

if (params) {
config.params = params;
return config;
},
(error) => Promise.reject(error)
);

// if we get a 401, it's because the token has expired, try to refresh it
axiosInstance.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config;
if (error.response.status === STATUS_CODES.Unauthorized && !originalRequest._retry) {
originalRequest._retry = true;
try {
const token = await UserService.updateToken();
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
return axiosInstance(originalRequest);
} catch (refreshError) {
// If refresh fails, redirect to login
console.error('Token refresh failed:', refreshError);
window.location.href = KEYCLOAK_URL;
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);

axios
.get(url, config)
.then((response: AxiosResponse) => {
const { data, status } = response;
export const get = <T, M = {}>(parameters: ApiRequestParameters<M>, headers?: {}): Promise<T> => {
const { url, requiresAuthentication, params } = parameters;
let config: AxiosRequestConfig = { headers: headers };

if (status === STATUS_CODES.Unauthorized) {
window.location = KEYCLOAK_URL;
}
if (requiresAuthentication) {
config.headers = {
...config.headers,
Authorization: `Bearer ${UserService.getToken()}`,
};
}

if (params) {
config.params = params;
}

resolve(data as T);
})
.catch((error: AxiosError) => {
console.log(error.message);
reject(error);
});
});
return axiosInstance.get(url, config).then((response: AxiosResponse) => response.data as T);
};

export const post = <T, M = {}>(parameters: ApiRequestParameters<M>): Promise<T> => {
let config: AxiosRequestConfig = {
headers: {},
};
return new Promise<T>((resolve, reject) => {
const { url, requiresAuthentication, params } = parameters;

if (requiresAuthentication) {
axios.defaults.headers.common['Authorization'] = `Bearer ${localStorage.getItem(AUTH_TOKEN)}`;
}
const { url, requiresAuthentication, params } = parameters;
let config: AxiosRequestConfig = { headers: {} };

if (requiresAuthentication && config && config.headers) {
config.headers['Authorization'] = `Bearer ${UserService.getToken()}`;
}

axios
.post(url, params, config)
.then((response: AxiosResponse) => {
resolve(response.data as T);
})
.catch((error: AxiosError) => {
console.log(error.message);
reject(error);
});
});
return axiosInstance.post(url, params, config).then((response: AxiosResponse) => response.data as T);
};

const fileDownloadGet = <T, M = {}>(parameters: ApiRequestParameters<M>): Promise<T> => {
const { url, requiresAuthentication } = parameters;
let config: AxiosRequestConfig = { headers: {}, responseType: 'blob' };
return new Promise<T>((resolve, reject) => {
const { url, requiresAuthentication } = parameters;

if (requiresAuthentication) {
axios.defaults.headers.common['Authorization'] = `Bearer ${localStorage.getItem(AUTH_TOKEN)}`;
}
if (requiresAuthentication && config && config.headers) {
config.headers['Authorization'] = `Bearer ${UserService.getToken()}`;
}

axios
.get(url, config)
.then((response: AxiosResponse) => {
resolve(response.data as T);
})
.catch((error: AxiosError) => {
console.log(error.message);
reject(error);
});
});
return axiosInstance.get(url, config).then((response: AxiosResponse) => response.data as T);
};

const fileDownloadPost = <T, M = {}>(parameters: ApiRequestParameters<M>): Promise<T> => {
const { url, requiresAuthentication, params } = parameters;
let config: AxiosRequestConfig = { headers: {}, responseType: 'blob' };
return new Promise<T>((resolve, reject) => {
const { url, requiresAuthentication, params } = parameters;

if (requiresAuthentication) {
axios.defaults.headers.common['Authorization'] = `Bearer ${localStorage.getItem(AUTH_TOKEN)}`;
}
if (requiresAuthentication && config && config.headers) {
config.headers['Authorization'] = `Bearer ${UserService.getToken()}`;
}

axios
.post(url, params, config)
.then((response: AxiosResponse) => {
resolve(response.data as T);
})
.catch((error: AxiosError) => {
console.log(error.message);
reject(error);
});
});
return axiosInstance.post(url, params, config).then((response: AxiosResponse) => response.data as T);
};

/**
Expand All @@ -128,16 +128,7 @@ const fileDownloadPost = <T, M = {}>(parameters: ApiRequestParameters<M>): Promi
export const handleFilePreviewGet = async (url: string): Promise<Blob | null> => {
try {
const getParameters = generateApiParameters(url);
return new Promise<Blob>((resolve, reject) => {
fileDownloadGet<Blob>(getParameters)
.then((blob) => {
resolve(blob);
})
.catch((error) => {
console.error('Preview error:', error);
reject(error);
});
});
return fileDownloadGet<Blob>(getParameters);
} catch (error) {
console.error('Preview error:', error);
return null;
Expand All @@ -152,13 +143,12 @@ export const handleFilePreviewGet = async (url: string): Promise<Blob | null> =>
*/
export const handleFileDownloadGet = async (url: string, filename: string) => {
const getParameters = generateApiParameters(url);
await fileDownloadGet<Blob>(getParameters)
.then(async (blob) => {
fileDownload(blob, filename);
})
.catch((error) => {
console.error('Download error:', error);
});
try {
const blob = await fileDownloadGet<Blob>(getParameters);
fileDownload(blob, filename);
} catch (error) {
console.error('Download error:', error);
}
};

/**
Expand All @@ -170,100 +160,37 @@ export const handleFileDownloadGet = async (url: string, filename: string) => {
*/
export const handleFileDownloadPost = async (url: string, data: any, filename: string) => {
const postParameters = generateApiParameters(url, data);

await fileDownloadPost<Blob>(postParameters)
.then(async (blob) => {
fileDownload(blob, filename);
})
.catch((error) => {
console.error('Download error:', error);
});
};

export const patch = <T, M = {}>(parameters: ApiRequestParameters<M>): Promise<T> => {
let config: AxiosRequestConfig = { headers: {} };
return new Promise<T>((resolve, reject) => {
const { url, requiresAuthentication, params: data } = parameters;

if (requiresAuthentication) {
axios.defaults.headers.common['Authorization'] = `Bearer ${localStorage.getItem(AUTH_TOKEN)}`;
}

axios
.patch(url, data, config)
.then((response: AxiosResponse) => {
const { status } = response;

if (status === STATUS_CODES.Unauthorized) {
window.location = KEYCLOAK_URL;
}

resolve(response.data as T);
})
.catch((error: AxiosError) => {
console.log(error.message);
reject(error);
});
});
try {
const blob = await fileDownloadPost<Blob>(postParameters);
fileDownload(blob, filename);
} catch (error) {
console.error('Download error:', error);
}
};

export const put = <T, M = {}>(parameters: ApiRequestParameters<M>): Promise<T> => {
const { url, requiresAuthentication, params: data } = parameters;
let config: AxiosRequestConfig = { headers: {} };
return new Promise<T>((resolve, reject) => {
const { url, requiresAuthentication, params: data } = parameters;

if (requiresAuthentication) {
axios.defaults.headers.common['Authorization'] = `Bearer ${localStorage.getItem(AUTH_TOKEN)}`;
}

axios
.put(url, data, config)
.then((response: AxiosResponse) => {
const { status } = response;

if (status === STATUS_CODES.Unauthorized) {
window.location = KEYCLOAK_URL;
}
if (requiresAuthentication && config && config.headers) {
config.headers['Authorization'] = `Bearer ${UserService.getToken()}`;
}

resolve(response.data as T);
})
.catch((error: AxiosError) => {
console.log(error.message);
reject(error);
});
});
return axiosInstance.put(url, data, config).then((response: AxiosResponse) => response.data as T);
};

// adjust for uploading templates
export const putFile = <T, M = {}>(parameters: ApiRequestParameters<M>, headers: {}, file: File): Promise<T> => {
const { url, requiresAuthentication } = parameters;
let config: AxiosRequestConfig = { headers: headers };

if (requiresAuthentication && config && config.headers) {
config.headers['Authorization'] = `Bearer ${UserService.getToken()}`;
}

const formData = new FormData();
if (file) formData.append('file', file);

return new Promise<T>((resolve, reject) => {
const { url, requiresAuthentication } = parameters;

if (requiresAuthentication) {
axios.defaults.headers.common['Authorization'] = `Bearer ${localStorage.getItem(AUTH_TOKEN)}`;
}

axios
.put(url, file, config)
.then((response: AxiosResponse) => {
const { status } = response;

if (status === STATUS_CODES.Unauthorized) {
window.location = KEYCLOAK_URL;
}

resolve(response.data as T);
})
.catch((error: AxiosError) => {
console.log(error.message);
reject(error);
});
});
return axiosInstance.put(url, formData, config).then((response: AxiosResponse) => response.data as T);
};

export const generateApiParameters = <T = {}>(
Expand All @@ -282,3 +209,14 @@ export const generateApiParameters = <T = {}>(

return result;
};

export default {
get,
post,
put,
putFile,
handleFilePreviewGet,
handleFileDownloadGet,
handleFileDownloadPost,
generateApiParameters,
};
5 changes: 0 additions & 5 deletions frontend/src/app/content/pages/LandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
generateReport,
getDisplayData,
saveDocument,
getMandatoryProvisionsByDocTypeId,
getGroupMaxByDocTypeId,
getDocumentData,
} from '../../common/report';
Expand Down Expand Up @@ -46,7 +45,6 @@ const LandingPage: FC = () => {
const [showGenerateError, setShowGenerateError] = useState<boolean>(false);

const [data, setData] = useState<DTRDisplayObject | null>(null);
const [mandatoryProvisionIds, setMandatoryProvisionIds] = useState<number[]>([]);
const [provisionGroups, setProvisionGroups] = useState<ProvisionGroup[]>([]);
const [dtidInput, setDtidInput] = useState<number | null>();
const [dtid, setDtid] = useState<number | null>(null);
Expand Down Expand Up @@ -170,9 +168,6 @@ const LandingPage: FC = () => {
.filter((provision) => provision.active_flag && !provision.is_deleted && provision.provision_group)
.map((provision) => provision.provision_group.id)
);
// mandatory provisions, will be validated against
const mpIds: number[] = await getMandatoryProvisionsByDocTypeId(documentType.id);
setMandatoryProvisionIds(mpIds);
// get provision groups and filter out the empty ones
const provisionGroupsObject: ProvisionGroup[] = await getGroupMaxByDocTypeId(documentType.id);
const activeProvisionGroups = provisionGroupsObject.filter((group) => activeProvisionIDs.has(group.id));
Expand Down
Loading

0 comments on commit 39532e0

Please sign in to comment.