Skip to content

Commit

Permalink
Updates
Browse files Browse the repository at this point in the history
a) Move notification from str to array;
b) Streamline the whole process;
c) Increase loader animation timeframes.
  • Loading branch information
ccxzhang committed Aug 13, 2024
1 parent b3bfb5c commit c4962fc
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 65 deletions.
9 changes: 5 additions & 4 deletions src/renderer/src/input.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
}

@keyframes spin {
to {
100% {
transform: rotate(360deg);
}
}
Expand All @@ -30,7 +30,8 @@
border: 4px solid rgba(0, 0, 0, 0.1);
border-left-color: #4f46e5; /* Tailwind's indigo-600 */
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
width: 32px;
height: 32px;
animation: spin 1.2s linear infinite;
will-change: transform; /* Hint to the browser to optimize this element */
}
68 changes: 56 additions & 12 deletions src/renderer/src/output.css
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,10 @@ html {
height: 1.5rem;
}

.max-h-48 {
max-height: 12rem;
}

.max-h-60 {
max-height: 15rem;
}
Expand All @@ -765,6 +769,10 @@ html {
width: 50%;
}

.w-12 {
width: 3rem;
}

.w-4 {
width: 1rem;
}
Expand Down Expand Up @@ -809,6 +817,16 @@ html {
flex-grow: 1;
}

@keyframes spin {
to {
transform: rotate(360deg);
}
}

.animate-spin {
animation: spin 1s linear infinite;
}

.cursor-not-allowed {
cursor: not-allowed;
}
Expand All @@ -829,10 +847,6 @@ html {
flex-wrap: nowrap;
}

.items-start {
align-items: flex-start;
}

.items-center {
align-items: center;
}
Expand Down Expand Up @@ -889,6 +903,10 @@ html {
overflow-y: auto;
}

.overflow-x-hidden {
overflow-x: hidden;
}

.whitespace-normal {
white-space: normal;
}
Expand Down Expand Up @@ -942,6 +960,15 @@ html {
border-right-width: 1px;
}

.border-t-4 {
border-top-width: 4px;
}

.border-blue-500 {
--tw-border-opacity: 1;
border-color: rgb(59 130 246 / var(--tw-border-opacity));
}

.border-gray-200 {
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity));
Expand Down Expand Up @@ -1002,6 +1029,11 @@ html {
background-color: rgb(31 41 55 / var(--tw-bg-opacity));
}

.bg-gray-900 {
--tw-bg-opacity: 1;
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
}

.bg-red-500 {
--tw-bg-opacity: 1;
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
Expand All @@ -1016,6 +1048,10 @@ html {
--tw-bg-opacity: 0.5;
}

.bg-opacity-60 {
--tw-bg-opacity: 0.6;
}

.bg-opacity-75 {
--tw-bg-opacity: 0.75;
}
Expand Down Expand Up @@ -1091,10 +1127,6 @@ html {
padding-bottom: 2rem;
}

.pt-20 {
padding-top: 5rem;
}

.text-left {
text-align: left;
}
Expand Down Expand Up @@ -1248,6 +1280,12 @@ html {
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.shadow-xl {
--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
Expand All @@ -1270,6 +1308,10 @@ html {
transition-duration: 150ms;
}

.duration-200 {
transition-duration: 200ms;
}

.ease-in-out {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
Expand All @@ -1281,7 +1323,7 @@ html {
}

@keyframes spin {
to {
100% {
transform: rotate(360deg);
}
}
Expand All @@ -1291,9 +1333,11 @@ html {
border-left-color: #4f46e5;
/* Tailwind's indigo-600 */
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
width: 32px;
height: 32px;
animation: spin 1.2s linear infinite;
will-change: transform;
/* Hint to the browser to optimize this element */
}

.hover\:bg-blue-100:hover {
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/src/pages/DownloadHistory/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useDispatch, useSelector } from 'react-redux'
import JSZip from 'jszip'
import { useLiveQuery } from 'dexie-react-hooks'
import { objectToCsv } from '../../utils/downloadUtils'
import { setNotification, setLoading, triggerNotification } from '../../reducers/statusReducer'
import { setLoading, triggerNotification } from '../../reducers/statusReducer'
import { queryHeaders } from '../../service/db'
import {
selectAllRows,
Expand Down Expand Up @@ -98,11 +98,11 @@ const HistoryPage = ({ dictionaryDb, queryDb }) => {
const csvBlob = new Blob([e.data.data], { type: 'text/csv;charset=utf-8' })
zip.file(`history_${index}.csv`, csvBlob)
dispatch(
setNotification({ message: `Finished downloading from ${url}`, type: 'info' })
triggerNotification({ message: `Finished downloading from ${url}`, type: 'info' })
)
resolve()
} else if (e.data.type === 'error') {
dispatch(setNotification({ message: e.data.message, type: 'error' }))
dispatch(triggerNotification({ message: e.data.message, type: 'error' }))
reject(new Error(e.data.message))
}
}
Expand Down
15 changes: 9 additions & 6 deletions src/renderer/src/pages/MainPage/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import { generatePeriods } from '../../utils/dateUtils'
import { generateDownloadingUrl, createDataChunks } from '../../utils/downloadUtils'
import DownloadButton from './DownloadButton'
import { useSelector, useDispatch } from 'react-redux'
import { triggerLoading, triggerNotification } from '../../reducers/statusReducer'
import {
clearNotification,
triggerLoading,
triggerNotification
} from '../../reducers/statusReducer'
import Tooltip from '../../components/Tooltip'

// eslint-disable-next-line react/prop-types
Expand Down Expand Up @@ -38,7 +42,6 @@ const MainPage = ({ queryDb }) => {
console.log(downloadingUrl)
const chunks = createDataChunks(elementIds, periods, ou)

let notificationMessages = ''
let header = null

const fetchChunk = async (chunk, index) => {
Expand All @@ -56,12 +59,12 @@ const MainPage = ({ queryDb }) => {
if (!header) {
header = headerText.slice(0, indexOfFirstNewline)
}
notificationMessages += `Chunk ${index + 1}: \n${dx}(${firstPe}-${lastPe}) finished\n`
dispatch(triggerNotification({ message: notificationMessages, type: 'info' }))
const successMessage = `Chunk ${index + 1}: ${dx} (${firstPe}-${lastPe}) finished successfully.`
dispatch(triggerNotification({ message: successMessage, type: 'info' }))
return blob
} catch (error) {
notificationMessages += `Chunk ${index + 1}: \n${dx}(${firstPe}-${lastPe}) failed: ${error.message}\n`
dispatch(triggerNotification({ message: notificationMessages, type: 'error' }))
const errorMessage = `Chunk ${index + 1}: ${dx} (${firstPe}-${lastPe}) failed: ${error?.message}`
dispatch(triggerNotification({ message: errorMessage, type: 'error' }))
return null
}
}
Expand Down
11 changes: 1 addition & 10 deletions src/renderer/src/pages/Modals/ModalManager.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import SignoutModal from './SignoutModal'

const ModalManager = () => {
const modals = useSelector((state) => state.modal.modals)
const { isLoading, notification } = useSelector((state) => state.status)
const dispatch = useDispatch()

if (modals.length === 0) return null

Expand All @@ -15,14 +13,7 @@ const ModalManager = () => {
{modals.map((modal, index) => {
switch (modal.type) {
case 'NOTIFICATION':
return (
<NotificationModal
key={index}
isLoading={isLoading}
message={notification.message}
type={notification.type}
/>
)
return <NotificationModal />
case 'SIGN_OUT':
return <SignoutModal key={index} />
default:
Expand Down
59 changes: 41 additions & 18 deletions src/renderer/src/pages/Modals/NotificationModal.jsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,59 @@
import React from 'react'
import { useMemo } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { handleExit } from '../../reducers/statusReducer'
import { clearNotification, handleExit } from '../../reducers/statusReducer'

// eslint-disable-next-line react/display-name
const Notification = React.memo(() => {
const { isLoading, notification } = useSelector((state) => state.status)

const renderedMessages = useMemo(() => {
return notification.map((msg, index) => (
<p
key={index}
className={`${msg?.type === 'error' ? 'text-red-600' : 'text-blue-600'} mb-2 whitespace-pre-wrap`}
>
{msg?.message}
</p>
))
}, [notification])

if (notification.length === 0) return null

return <div>{renderedMessages}</div>
})

const NotificationModal = () => {
const dispatch = useDispatch()
const { isLoading, notification } = useSelector((state) => state.status)

const handleClose = () => dispatch(handleExit())
const handleClose = () => {
dispatch(handleExit())
dispatch(clearNotification())
}

if (!isLoading && !notification.message) return null
if (!isLoading && notification.length == 0) return null

return (
<div className="fixed inset-0 bg-gray-200 bg-opacity-75 flex items-start justify-center pt-20 z-50">
<div className="bg-white p-4 rounded shadow-lg flex flex-col items-center max-w-sm w-full max-h-96 overflow-y-auto">
<div className="fixed inset-0 bg-gray-900 bg-opacity-60 flex items-center justify-center z-50">
<div className="bg-white p-6 rounded-lg shadow-xl max-w-sm w-full max-h-96 overflow-y-auto overflow-x-hidden flex flex-col items-center">
{isLoading && (
<>
<div className="loader mb-4"></div>
<p className="text-gray-700 mb-2">Loading...</p>
</>
)}
{notification.message && (
<p
className={`${notification.type === 'error' ? 'text-red-600' : 'text-blue-600'} mb-2 whitespace-pre-wrap`}
>
{notification.message}
</p>
<div className="flex flex-col items-center mb-4">
<div className="loader mb-3 border-t-4 border-blue-500 rounded-full w-12 h-12 animate-spin"></div>
<p className="text-gray-600">Loading...</p>
</div>
)}

{/* Notification Content */}
<div className="flex-grow overflow-y-auto max-h-48 w-full p-4 bg-gray-100 rounded-lg border border-gray-300">
<Notification />
</div>

<button
onClick={handleClose}
className="px-3 py-2 bg-blue-500 text-white rounded hover:bg-blue-700 focus:outline-none"
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition ease-in-out duration-200 focus:outline-none w-full text-center"
>
{'Close'}
Close
</button>
</div>
</div>
Expand Down
19 changes: 7 additions & 12 deletions src/renderer/src/reducers/statusReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import { openModal } from './modalReducer'

const initialState = {
isLoading: false,
notification: {
message: '',
type: ''
}
notification: []
}

const statusSlice = createSlice({
Expand All @@ -16,13 +13,11 @@ const statusSlice = createSlice({
setLoading: (state, action) => {
state.isLoading = action.payload
},
setNotification: (state, action) => {
state.notification = { ...state.notification, ...action.payload }
addNotification: (state, action) => {
state.notification.push(action.payload)
},
abortDownload: (state) => {
state.isLoading = false
state.notification.message = 'Download aborted'
state.notification.type = 'info'
clearNotification: (state) => {
state.notification = []
},
handleExit: (state) => {
return initialState
Expand All @@ -34,7 +29,7 @@ export const triggerNotification = (payload) => (dispatch) => {
dispatch(openModal({ type: 'NOTIFICATION' }))

dispatch(
setNotification({
addNotification({
message: payload.message,
type: payload.type
})
Expand All @@ -48,5 +43,5 @@ export const triggerLoading = (isLoading) => (dispatch) => {
}
}

export const { setLoading, setNotification, abortDownload, handleExit } = statusSlice.actions
export const { setLoading, addNotification, clearNotification, handleExit } = statusSlice.actions
export default statusSlice.reducer

0 comments on commit c4962fc

Please sign in to comment.