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

Add as user toggle #445

Merged
merged 3 commits into from
Feb 17, 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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"express": "4.21.1",
"express-ws": "5.0.2",
"i18next": "^24.0.2",
"jwt-decode": "^4.0.0",
"loglevel": "1.9.2",
"monaco-editor": "^0.52.0",
"react": "17.0.2",
Expand Down
15 changes: 14 additions & 1 deletion src/Jobs/JobsAll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,28 @@ const JobsAll: React.FC = () => {
const [orderDirection, setOrderDirection] = useState<'asc' | 'desc'>('desc'); // Sorting order (ascending/descending)
const [selectedInstrument, setSelectedInstrument] = useState(instrumentName || 'ALL'); // Selected instrument filter
const [orderBy, setOrderBy] = useState<string>('run_start'); // Column to sort by
const [asUser, setAsUser] = useState<boolean>(() => {
// Whether to display jobs as a user or not
const storedValue = localStorage.getItem('asUser');
return storedValue ? JSON.parse(storedValue) : false; // Default to false
});

// Calculate the offset for API query based on current page
const offset = currentPage * rowsPerPage;

// Construct API query string with pagination and sorting parameters
const query = `limit=${rowsPerPage}&offset=${offset}&order_by=${orderBy}&order_direction=${orderDirection}&include_run=true`;
const query = `limit=${rowsPerPage}&offset=${offset}&order_by=${orderBy}&order_direction=${orderDirection}&include_run=true&as_user=${asUser}`;

// Fetch job data and total count using custom hooks
const fetchJobs = useFetchJobs(`/jobs`, query, setJobs);
const fetchTotalCount = useFetchTotalCount(`/jobs/count`, setTotalRows);

const handleToggleAsUser = (event: React.ChangeEvent<HTMLInputElement>): void => {
const newValue = event.target.checked;
setAsUser(newValue);
localStorage.setItem('asUser', JSON.stringify(newValue)); // Save to localStorage
};

return (
<JobsBase
selectedInstrument={selectedInstrument}
Expand Down Expand Up @@ -89,6 +100,8 @@ const JobsAll: React.FC = () => {
</TableCell>
)}
maxHeight={650} // Limit table height
asUser={asUser}
handleToggleAsUser={handleToggleAsUser}
/>
);
};
Expand Down
34 changes: 34 additions & 0 deletions src/Jobs/JobsBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import {
Collapse,
Drawer,
FormControl,
FormControlLabel,
IconButton,
InputLabel,
MenuItem,
Paper,
Select,
SelectChangeEvent,
Snackbar,
Switch,
Table,
TableBody,
TableCell,
Expand Down Expand Up @@ -55,6 +57,9 @@ import ConfigSettingsGeneral from '../ConfigSettings/ConfigSettingsGeneral';
import ConfigSettingsLOQ from '../ConfigSettings/ConfigSettingsLOQ';
import { fiaApi } from '../api';

// JWT decoder
import { jwtDecode } from 'jwt-decode';

export const headerStyles = (theme: Theme): CSSObject => ({
color: theme.palette.primary.contrastText,
backgroundColor: theme.palette.primary.main,
Expand Down Expand Up @@ -139,6 +144,8 @@ interface JobsBaseProps {
fetchTotalCount: () => Promise<void>;
maxHeight?: number;
showConfigButton?: boolean;
asUser: boolean;
handleToggleAsUser: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

const JobsBase: React.FC<JobsBaseProps> = ({
Expand All @@ -160,6 +167,8 @@ const JobsBase: React.FC<JobsBaseProps> = ({
fetchTotalCount,
maxHeight = 624,
showConfigButton = false,
asUser,
handleToggleAsUser,
}) => {
const theme = useTheme();
const allInstruments = [{ name: 'ALL' }, ...instruments]; // Add 'ALL' option to the instruments list
Expand All @@ -168,16 +177,31 @@ const JobsBase: React.FC<JobsBaseProps> = ({
const totalColumnCount = baseColumnCount + customColumnCount;
const [drawerOpen, setDrawerOpen] = useState(false);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [userRole, setUserRole] = useState<'staff' | 'user' | null>(null);
const rerunSuccessful = useRef<boolean | null>(null);
const rerunJobId = useRef<number | null>(null);

useEffect(() => {
fetchTotalCount();
fetchJobs();
setUserRole(getUserRole());
}, [fetchTotalCount, fetchJobs]);

const DATA_VIEWER_URL = process.env.REACT_APP_FIA_DATA_VIEWER_URL;

const getUserRole = (): 'staff' | 'user' | null => {
const token = localStorage.getItem('scigateway:token');
if (!token) return null;

try {
const decoded = jwtDecode<{ role?: 'staff' | 'user' }>(token);
return decoded.role || 'user';
} catch (error) {
console.error('Error decoding token:', error);
return null;
}
};

const openValueEditor = (jobId: number): void => {
const url = `/fia/value-editor/${jobId}`;
const windowName = 'ValueEditorWindow';
Expand Down Expand Up @@ -702,6 +726,16 @@ const JobsBase: React.FC<JobsBaseProps> = ({
Config
</Button>
)}
{userRole === 'staff' && (
<FormControlLabel
control={<Switch checked={asUser} onChange={handleToggleAsUser} color="warning" />}
label={
<Typography variant="body1" color={theme.palette.text.primary}>
View as user
</Typography>
}
/>
)}
{handleInstrumentChange && (
<FormControl style={{ width: '200px', marginLeft: '20px' }}>
<InputLabel id="instrument-select-label">Instrument</InputLabel>
Expand Down
15 changes: 14 additions & 1 deletion src/Jobs/JobsGeneral.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,28 @@ const JobsGeneral: React.FC = () => {
const [rowsPerPage, setRowsPerPage] = useState(25); // Number of rows displayed per page
const [orderDirection, setOrderDirection] = useState<'asc' | 'desc'>('desc'); // Sorting order (ascending/descending)
const [orderBy, setOrderBy] = useState<string>('run_start'); // Column to sort by
const [asUser, setAsUser] = useState<boolean>(() => {
// Whether to display jobs as a user or not
const storedValue = localStorage.getItem('asUser');
return storedValue ? JSON.parse(storedValue) : false; // Default to false
});

// Calculate the offset for API query based on current page
const offset = currentPage * rowsPerPage;

// Construct API query string with pagination and sorting parameters
const query = `limit=${rowsPerPage}&offset=${offset}&order_by=${orderBy}&order_direction=${orderDirection}&include_run=true`;
const query = `limit=${rowsPerPage}&offset=${offset}&order_by=${orderBy}&order_direction=${orderDirection}&include_run=true&as_user=${asUser}`;

// Fetch job data and total count using custom hooks
const fetchJobs = useFetchJobs(`/instrument/${selectedInstrument}/jobs`, query, setJobs);
const fetchTotalCount = useFetchTotalCount(`/instrument/${selectedInstrument}/jobs/count`, setTotalRows);

const handleToggleAsUser = (event: React.ChangeEvent<HTMLInputElement>): void => {
const newValue = event.target.checked;
setAsUser(newValue);
localStorage.setItem('asUser', JSON.stringify(newValue)); // Save to localStorage
};

return (
<JobsBase
selectedInstrument={selectedInstrument}
Expand Down Expand Up @@ -68,6 +79,8 @@ const JobsGeneral: React.FC = () => {
fetchJobs={fetchJobs}
fetchTotalCount={fetchTotalCount}
showConfigButton={selectedInstrument === 'LOQ' || selectedInstrument === 'MARI'} // Show config button only for specific instruments
asUser={asUser}
handleToggleAsUser={handleToggleAsUser}
>
{/* Link to view reductions for all instruments */}
<Typography
Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7836,6 +7836,7 @@ __metadata:
html-webpack-plugin: ^5.6.3
husky: 9.1.7
i18next: ^24.0.2
jwt-decode: ^4.0.0
lint-staged: 15.2.10
loglevel: 1.9.2
monaco-editor: ^0.52.0
Expand Down Expand Up @@ -10571,6 +10572,13 @@ __metadata:
languageName: node
linkType: hard

"jwt-decode@npm:^4.0.0":
version: 4.0.0
resolution: "jwt-decode@npm:4.0.0"
checksum: 390e2edcb31a92e86c8cbdd1edeea4c0d62acd371f8a8f0a8878e499390c0ecf4c658b365c4e941e4ef37d0170e4ca650aaa49f99a45c0b9695a235b210154b0
languageName: node
linkType: hard

"keyv@npm:^4.5.3":
version: 4.5.4
resolution: "keyv@npm:4.5.4"
Expand Down
Loading