Skip to content

Commit

Permalink
Merge pull request #147 from IMS-IIITH/add_download_button
Browse files Browse the repository at this point in the history
Add download button
  • Loading branch information
someyuck committed Sep 5, 2024
2 parents e641c18 + 44ecbaa commit 27eea73
Show file tree
Hide file tree
Showing 31 changed files with 170 additions and 49 deletions.
34 changes: 21 additions & 13 deletions src/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,38 @@ import { createNativeStackNavigator } from "@react-navigation/native-stack";

// Common
import Welcome from "./screens/Welcome/Welcome";
import Login from "./screens/Login/Login";
import LogOut from "./screens/LogOut/LogOut";
import Login from "./screens/AppAuth/Login";
import LogOut from "./screens/AppAuth/LogOut";
import BottomTab from "./components/BottomTab";
import Dashboard from "./screens/Dashboard/Dashboard";
import SidebarDisplay from "./components/SideBarDisplay";
import About from "./screens/About/About";
import Notification from "./screens/Notifications/Notifications";
import ReportBug from "./screens/ReportBug/ReportBug";
import NoNetwork from "./screens/NoNetwork";
import About from "./screens/GenericPages/About";
import Notification from "./screens/GenericPages/Notifications";
import ReportBug from "./screens/GenericPages/ReportBug";
import NoNetwork from "./screens/GenericPages/NoNetwork";
import EIdCard from "./screens/IDCard/IdCard";
import ProfileDetails from "./screens/MyProfile/ProfilePage";
import * as types from "./custom-types";
import { otherIcons, IconSet } from "./constants/Icons";

// Student
import BankDetails from "./screens/MyBank/BankDetails";
import BankPDF, { bankPDFTitle } from "./screens/MyBank/BankPDF";
import LeaveApplication from "./screens/ApplyLeave/LeaveApplication";
import LeavesBottomTab from "./screens/PastLeaves/LeavesBottomTab";
import BankPDF, { BankChequeDownloadButton } from "./screens/MyBank/BankPDF";
import LeaveApplication from "./screens/Leaves/LeaveApplication";
import LeavesBottomTab from "./screens/Leaves/LeavesBottomTab";
import Transcript from "./screens/Transcript/Transcript";
import ViewAttendance from "./screens/Attendance/Attendance";
import CourseAttendanceView from "./screens/Attendance/CourseAttendanceView";
import LeaveRules from "./screens/LeaveRules";
import AttendanceRules from "./screens/AttendanceRules";
import LeaveRules, {
LeaveRulesDownloadButton,
} from "./screens/Documents/LeaveRules";
import AttendanceRules, {
AttendanceDownloadButton,
} from "./screens/Documents/AttendanceRules";

// Faculty
import Contacts from "./screens/Contacts/Contacts";
import DetailContact from "./screens/DetailedContact/DetailedContact";
import DetailContact from "./screens/Contacts/DetailedContact";

const Stack = createNativeStackNavigator<types.RootStackParamList>();

Expand Down Expand Up @@ -177,7 +181,9 @@ function Navigation(): React.JSX.Element {
<Stack.Screen
name="BankPDF"
component={BankPDF}
options={{ title: bankPDFTitle }}
options={{
title: "Passbook / Cancelled Cheque",
}}
/>
<Stack.Screen
name="DashboardScreen"
Expand All @@ -189,13 +195,15 @@ function Navigation(): React.JSX.Element {
component={LeaveRules}
options={{
title: "Leave Rules",
headerRight: () => <LeaveRulesDownloadButton />,
}}
/>
<Stack.Screen
name="AttendanceRules"
component={AttendanceRules}
options={{
title: "Attendance Policy",
headerRight: () => <AttendanceDownloadButton />,
}}
/>
<Stack.Screen
Expand Down
2 changes: 1 addition & 1 deletion src/components/BottomTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import { SafeAreaView } from "react-native";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import Dashboard from "../screens/Dashboard/Dashboard";
import About from "../screens/About/About";
import About from "../screens/GenericPages/About";
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
import {
faHome as homeIcon,
Expand Down
56 changes: 56 additions & 0 deletions src/components/PdfDownload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import RNFetchBlob from "react-native-blob-util";
import RNFS from "react-native-fs";
import { Alert } from "react-native";
import { getAccessToken } from "../backend_requests/AccessToken";

export default async function downloadPdf(
fileName: string,
fileURL: string,
require_cookie: boolean = false,
) {
try {
const { config, android } = RNFetchBlob;

let filePath: string = `${RNFS.DownloadDirectoryPath}/${fileName}.pdf`;
let index: number = 1;
while (await RNFS.exists(filePath)) {
filePath = `${RNFS.DownloadDirectoryPath}/${fileName}${index}.pdf`;
index += 1;
}

const options = {
fileCache: true,
addAndroidDownloads: {
useDownloadManager: true,
notification: true,
path: filePath,
description: "Downloading PDF document",
mediaScannable: true,
},
};

const headers: { Accept: string; "Content-Type": string; cookie?: string } =
{
Accept: "application/pdf",
"Content-Type": "application/pdf",
};

if (require_cookie) {
const accessToken = await getAccessToken();
if (!accessToken) {
Alert.alert("Couldn't get unique access token.");
return;
}
headers.cookie = `access_token_ims_app=${accessToken}`;
}

config(options)
.fetch("GET", fileURL, headers)
.then((response) => {
const path = response.path();
android.actionViewIntent(path, "application/pdf");
});
} catch (err) {
Alert.alert("Couldn't download file.", (err as Error).toString());
}
}
4 changes: 2 additions & 2 deletions src/constants/APIHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const contact_details = domain + "/faculty/contacts";

// Policies
const leave_rules = domain + "/static/policies/Leave_Rules.pdf";
const attendance_rules = domain + "/static/policies/Attendance_Policy.pdf";
const attendance_policy = domain + "/static/policies/Attendance_Policy.pdf";

export {
domain,
Expand All @@ -54,5 +54,5 @@ export {
apply_leave,
contact_details,
leave_rules,
attendance_rules,
attendance_policy,
};
41 changes: 29 additions & 12 deletions src/device_permissions/FilePermission.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
import { PermissionsAndroid } from "react-native";
import { PermissionsAndroid, Platform } from "react-native";

export const askFILEACCESSPERMISSION = async () => {
try {
await PermissionsAndroid.request(
export const askFileAccessPermissions = async () => {
if (Platform.OS !== 'android') return;

const permissions = [];

// for higher we require no permission
if (Platform.Version < 29) {
permissions.push(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
{
title: "READ FILE PERMISSIONS",
message: "Please ALLOW IMS TO READ FILES ",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK",
},
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
);
}

try {
const results = await PermissionsAndroid.requestMultiple(permissions);

let allGranted = true;
Object.keys(results).forEach(key => {
if (results[key] !== PermissionsAndroid.RESULTS.GRANTED) {
allGranted = false;
}
});

if (allGranted) {
console.log('All permissions granted');
} else {
console.log('Some permissions denied');
}

} catch (err) {
console.warn(err);
console.warn('Error requesting permissions:', err);
}
};
File renamed without changes.
4 changes: 2 additions & 2 deletions src/screens/Login/Login.tsx → src/screens/AppAuth/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import UpdatePassword from "./components/UpdatePassword";
import styles from "./Styles/LoginStyles";
import { authenticate_user } from "../../backend_requests/AuthUser";
import { get_user_details } from "../../backend_requests/UserDetails";
import { askFILEACCESSPERMISSION } from "../../device_permissions/FilePermission";
import { askFileAccessPermissions } from "../../device_permissions/FilePermission";

function Login({ navigation }: types.LoginScreenProps): React.JSX.Element {
const [Email, onChangeEmail] = useState<string>("");
Expand Down Expand Up @@ -47,7 +47,7 @@ function Login({ navigation }: types.LoginScreenProps): React.JSX.Element {
};

useEffect(() => {
askFILEACCESSPERMISSION();
askFileAccessPermissions();
}, []);

return (
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import {
StyleSheet,
ActivityIndicator,
Text,
TouchableOpacity,
} from "react-native";
import * as types from "../custom-types";
import * as types from "../../custom-types";
import Pdf from "react-native-pdf";
import { attendance_rules } from "../constants/APIHandler";
import downloadPdf from "../../components/PdfDownload";
import { attendance_policy } from "../../constants/APIHandler";
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
import { faDownload } from "@fortawesome/free-solid-svg-icons";

const styles = StyleSheet.create({
container: {
Expand Down Expand Up @@ -39,7 +43,7 @@ const styles = StyleSheet.create({
},
});

function AttendanceRules({}: types.AttendanceRulesProps): React.JSX.Element {
export function AttendanceRules({}: types.AttendanceRulesProps): React.JSX.Element {
const [pdfLocation, setPdfLocation] = useState<{ uri: string }>({ uri: "" });
const [loading, setLoading] = useState(true);
const [errorText, setErrorText] = useState<string | null>(null);
Expand All @@ -48,7 +52,7 @@ function AttendanceRules({}: types.AttendanceRulesProps): React.JSX.Element {
setLoading(true);
setErrorText(null);
try {
const response = await fetch(attendance_rules, {
const response = await fetch(attendance_policy, {
method: "GET",
});
if (response.status === 200) {
Expand Down Expand Up @@ -100,4 +104,14 @@ function AttendanceRules({}: types.AttendanceRulesProps): React.JSX.Element {
);
}

export const AttendanceDownloadButton = (): React.JSX.Element => {
return (
<TouchableOpacity
onPress={() => downloadPdf("Attendance Policy", attendance_policy)}
>
<FontAwesomeIcon icon={faDownload} size={28} />
</TouchableOpacity>
);
};

export default AttendanceRules;
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import {
StyleSheet,
Text,
ActivityIndicator,
TouchableOpacity,
} from "react-native";
import Pdf from "react-native-pdf";
import { leave_rules } from "../constants/APIHandler";
import downloadPdf from "../../components/PdfDownload";
import { leave_rules } from "../../constants/APIHandler";
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
import { faDownload } from "@fortawesome/free-solid-svg-icons";

const styles = StyleSheet.create({
container: {
Expand Down Expand Up @@ -38,7 +42,7 @@ const styles = StyleSheet.create({
},
});

function LeaveRules() {
export function LeaveRules() {
const [pdfLocation, setPdfLocation] = useState<{ uri: string }>({ uri: "" });
const [loading, setLoading] = useState<boolean>(true);
const [errorText, setErrorText] = useState<string | null>(null);
Expand Down Expand Up @@ -99,4 +103,12 @@ function LeaveRules() {
);
}

export const LeaveRulesDownloadButton = (): React.JSX.Element => {
return (
<TouchableOpacity onPress={() => downloadPdf("Leave Rules", leave_rules)}>
<FontAwesomeIcon icon={faDownload} size={28} />
</TouchableOpacity>
);
};

export default LeaveRules;
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
} from "react-native";
import { useFocusEffect } from "@react-navigation/native";

import { Connectionstatus } from "../components/Connectionstatus";
import * as types from "../custom-types";
import { Connectionstatus } from "../../components/Connectionstatus";
import * as types from "../../custom-types";

const styles = StyleSheet.create({
safeArea: {
Expand Down Expand Up @@ -80,7 +80,7 @@ function NoNetwork({ navigation }: types.NoNetworkProps): React.JSX.Element {
return (
<SafeAreaView style={styles.safeArea}>
<View style={styles.errorContainer}>
<Image source={require("../assets/error.png")} style={styles.img} />
<Image source={require("../../assets/error.png")} style={styles.img} />
<View style={styles.textContainer}>
<Text style={styles.errorHead}>Connection Error</Text>
<Text style={styles.subText}>
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/screens/IDCard/IdCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Avatar } from "@rneui/themed";

import bank from "../../styles/bank";
import global from "../../styles/global";
import styles from "./id-styles";
import styles from "../../styles/eid";
import { otherIcons, IconSet } from "../../constants/Icons";
import { profile_details, profile_picture } from "../../constants/APIHandler";
import { userRole, rollno, userName } from "../../backend_requests/UserDetails";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ function LeaveApplication(): React.JSX.Element {
filename2: file2,
filedata2: file2_base64,
};
const request_status = await postLeaveToServer(json_to_send);
const request_status = await postLeaveToServer(
JSON.parse(JSON.stringify(json_to_send)),
);
if (request_status === "success") navigation.navigate("MyLeaves");
},
},
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
faCircleInfo,
} from "@fortawesome/free-solid-svg-icons";
import { faCircleXmark } from "@fortawesome/free-regular-svg-icons";
import LeaveApplicationCss from "../styles/LeaveScreenStyles";
import LeaveApplicationCss from "../../../styles/applyleave";
import { otherIcons, IconSet } from "../../../constants/Icons";

const lightIcons: IconSet = otherIcons.light;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { View, Text, TouchableOpacity, Alert } from "react-native";
import DateTimePicker from "@react-native-community/datetimepicker";
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
import { faCalendarDays } from "@fortawesome/free-solid-svg-icons";
import LeaveApplicationCss from "../styles/LeaveScreenStyles";
import LeaveApplicationCss from "../../../styles/applyleave";

function EventSchedule(props: {
fromDateText: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { View, Text, Image, TouchableOpacity, Alert } from "react-native";
import LeaveApplicationCss from "../styles/LeaveScreenStyles";
import LeaveApplicationCss from "../../../styles/applyleave";
import DateTimePicker, {
DateTimePickerEvent,
} from "@react-native-community/datetimepicker";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {

import { allCourses } from "../../Dashboard/components/CourseTable"; // Assuming this is where your course data is stored
import { otherIcons } from "../../../constants/Icons";
import LeaveApplicationCss from "../styles/LeaveScreenStyles";
import LeaveApplicationCss from "../../../styles/applyleave";

export interface CourseRow {
key: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState } from "react";
import { View, Text, Image, SafeAreaView, TextInput } from "react-native";
import { SelectList } from "react-native-dropdown-select-list";

import LeaveApplicationCss from "../styles/LeaveScreenStyles";
import LeaveApplicationCss from "../../../styles/applyleave";
import EventSchedule from "./EventSchedule";
import { otherIcons, IconSet } from "../../../constants/Icons";

Expand Down
Loading

0 comments on commit 27eea73

Please sign in to comment.