Skip to content

Commit

Permalink
[frontend] Added auto collapse and submenu icon switches to settings (O…
Browse files Browse the repository at this point in the history
  • Loading branch information
Bonsai8863 committed Mar 26, 2024
1 parent ce1dbf9 commit b2123cd
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 23 deletions.
2 changes: 2 additions & 0 deletions opencti-platform/opencti-front/lang/front/de.json
Expand Up @@ -2673,5 +2673,7 @@
"Strategic": "Strategisch",
"Link created": "Link erstellt",
"Public dashboard": "Öffentliches Dashboard",
"Show left navigation submenu icons": "Symbole des linken Navigations-Untermenüs anzeigen",
"Auto collapse submenus in left navigation": "Untermenüs in der linken Navigation automatisch einklappen",
"Unless specific groups are selected, user will be created with default groups only.": "Wenn keine spezifischen Gruppen ausgewählt werden, wird der Benutzer nur mit den Standardgruppen erstellt."
}
2 changes: 2 additions & 0 deletions opencti-platform/opencti-front/lang/front/en.json
Expand Up @@ -2673,5 +2673,7 @@
"Operational": "Operational",
"Strategic": "Strategic",
"Link created": "Link created",
"Show left navigation submenu icons": "Show left navigation submenu icons",
"Auto collapse submenus in left navigation": "Auto collapse submenus in left navigation",
"Public dashboard": "Public dashboard"
}
2 changes: 2 additions & 0 deletions opencti-platform/opencti-front/lang/front/es.json
Expand Up @@ -2673,5 +2673,7 @@
"Strategic": "Estratégico",
"Link created": "Enlace creado",
"Public dashboard": "Cuadro de mandos público",
"Show left navigation submenu icons": "Mostrar iconos del submenú de navegación izquierdo",
"Auto collapse submenus in left navigation": "Submenús contraídos automáticamente en la navegación izquierda",
"Unless specific groups are selected, user will be created with default groups only.": "A menos que se seleccionen grupos específicos, el usuario se creará sólo con los grupos por defecto."
}
2 changes: 2 additions & 0 deletions opencti-platform/opencti-front/lang/front/fr.json
Expand Up @@ -2673,5 +2673,7 @@
"Strategic": "Stratégique",
"Link created": "Lien créé",
"Public dashboard": "Tableau de bord public",
"Show left navigation submenu icons": "Afficher les icônes du sous-menu de navigation de gauche",
"Auto collapse submenus in left navigation": "Sous-menus à réduction automatique dans la navigation de gauche",
"Unless specific groups are selected, user will be created with default groups only.": "À moins que des groupes spécifiques ne soient sélectionnés, l'utilisateur sera créé avec les groupes par défaut uniquement."
}
2 changes: 2 additions & 0 deletions opencti-platform/opencti-front/lang/front/ja.json
Expand Up @@ -2673,5 +2673,7 @@
"Strategic": "戦略的",
"Link created": "リンク作成",
"Public dashboard": "公開ダッシュボード",
"Show left navigation submenu icons": "左側のナビゲーション サブメニュー アイコンを表示する",
"Auto collapse submenus in left navigation": "左側のナビゲーションのサブメニューを自動的に折りたたむ",
"Unless specific groups are selected, user will be created with default groups only.": "特定のグループを選択しない限り、ユーザーはデフォルトのグループのみで作成されます。"
}
2 changes: 2 additions & 0 deletions opencti-platform/opencti-front/lang/front/zh.json
Expand Up @@ -2673,5 +2673,7 @@
"Strategic": "战略",
"Link created": "创建的链接",
"Public dashboard": "公共仪表板",
"Show left navigation submenu icons": "显示左侧导航子菜单图标",
"Auto collapse submenus in left navigation": "自动折叠左侧导航中的子菜单",
"Unless specific groups are selected, user will be created with default groups only.": "除非选择了特定组,否则创建的用户将只包含默认组。"
}
2 changes: 2 additions & 0 deletions opencti-platform/opencti-front/src/private/Root.tsx
Expand Up @@ -85,6 +85,8 @@ const rootPrivateQuery = graphql`
name
}
unit_system
submenu_show_icons
submenu_auto_collapse
default_dashboards {
id
name
Expand Down
Expand Up @@ -175,6 +175,9 @@ const useStyles = makeStyles((theme) => createStyles({
menuItemSmallText: {
padding: '1px 0 0 20px',
},
menuToggleSubmenuIcons: {
marginRight: 15,
},
}));

const StyledTooltip = styled(({ className, ...props }) => (
Expand All @@ -193,7 +196,10 @@ const LeftBar = () => {
const location = useLocation();
const ref = useRef();
const { t_i18n } = useFormatter();
const { settings: { platform_whitemark } } = useAuth();
const {
me: { submenu_auto_collapse, submenu_show_icons },
settings: { platform_whitemark },
} = useAuth();
const history = useHistory();
const isEnterpriseEdition = useEnterpriseEdition();
const isGrantedToKnowledge = useGranted([KNOWLEDGE]);
Expand All @@ -220,25 +226,47 @@ const LeftBar = () => {
data: useRef(null),
settings: useRef(null),
};
const [selectedMenu, setSelectedMenu] = useState(null);
// console.log(localStorage.getItem('selectedMenu'));
const [selectedMenu, setSelectedMenu] = useState(
JSON.parse(localStorage.getItem('selectedMenu') ?? '[]'),
);
const [navOpen, setNavOpen] = useState(
localStorage.getItem('navOpen') === 'true',
);
const classes = useStyles({ navOpen });
const addMenuUnique = (menu) => {
const joined = selectedMenu.concat(menu);
return joined.filter((value, index, array) => array.indexOf(value) === index);
};
const removeMenuUnique = (menu) => {
return selectedMenu.filter((value) => value !== menu);
};
const handleToggle = () => {
setSelectedMenu(null);
setSelectedMenu([]);
localStorage.setItem('navOpen', String(!navOpen));
localStorage.setItem('selectedMenu', JSON.stringify([]));
setNavOpen(!navOpen);
MESSAGING$.toggleNav.next('toggle');
};
const handleSelectedMenuOpen = (menu) => {
setSelectedMenu(menu);
const updatedMenu = submenu_auto_collapse ? addMenuUnique(menu) : [menu];
setSelectedMenu(updatedMenu);
};
const handleSelectedMenuClose = () => {
setSelectedMenu(null);
setSelectedMenu([]);
};
const handleSelectedMenuToggle = (menu) => {
setSelectedMenu(selectedMenu === menu ? null : menu);
let updatedMenu;
if (submenu_auto_collapse) {
updatedMenu = selectedMenu.includes(menu) ? [] : [menu];
setSelectedMenu(updatedMenu);
} else {
updatedMenu = selectedMenu.includes(menu)
? removeMenuUnique(menu)
: addMenuUnique(menu);
setSelectedMenu(updatedMenu);
}
localStorage.setItem('selectedMenu', JSON.stringify(updatedMenu));
};
const handleGoToPage = (link) => {
history.push(link);
Expand Down Expand Up @@ -308,7 +336,7 @@ const LeftBar = () => {
const isMobile = dimension.width < 768;
const generateSubMenu = (menu, entries) => {
return navOpen ? (
<Collapse in={selectedMenu === menu} timeout="auto" unmountOnExit={true}>
<Collapse in={selectedMenu.includes(menu)} timeout="auto" unmountOnExit={true}>
<MenuList component="nav" disablePadding={true}>
{entries.filter((entry) => entry.granted !== false && !hiddenEntities.includes(entry.type)).map((entry) => {
return (
Expand All @@ -320,12 +348,19 @@ const LeftBar = () => {
dense={true}
classes={{ root: classes.menuSubItem }}
>
{entry.icon && <ListItemIcon classes={{ root: classes.menuItemIcon }} style={{ minWidth: 20 }}>
{submenu_show_icons && entry.icon && <ListItemIcon classes={{ root: classes.menuItemIcon }} style={{ minWidth: 20 }}>
{entry.icon}
</ListItemIcon>}
<ListItemText
classes={{ primary: classes.menuSubItemText }}
primary={t_i18n(entry.label)}
primaryTypographyProps={{
style: {
whiteSpace: 'wrap',
lineHeight: 1.2,
padding: '4px 0 4px 10px',
},
}}
/>
</MenuItem>
</StyledTooltip>
Expand All @@ -336,7 +371,7 @@ const LeftBar = () => {
) : (
<Popover
sx={{ pointerEvents: 'none' }}
open={selectedMenu === menu}
open={selectedMenu.includes(menu)}
anchorEl={anchors[menu]?.current}
anchorOrigin={{
vertical: 'top',
Expand Down Expand Up @@ -446,7 +481,7 @@ const LeftBar = () => {
primary={t_i18n('Analyses')}
/>
)}
{navOpen && (selectedMenu === 'analyses' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('analyses') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideAnalyses && generateSubMenu(
Expand Down Expand Up @@ -478,7 +513,7 @@ const LeftBar = () => {
primary={t_i18n('Cases')}
/>
)}
{navOpen && (selectedMenu === 'cases' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('cases') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideCases && generateSubMenu(
Expand Down Expand Up @@ -510,7 +545,7 @@ const LeftBar = () => {
primary={t_i18n('Events')}
/>
)}
{navOpen && (selectedMenu === 'events' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('events') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideEvents && generateSubMenu(
Expand Down Expand Up @@ -540,7 +575,7 @@ const LeftBar = () => {
primary={t_i18n('Observations')}
/>
)}
{navOpen && (selectedMenu === 'observations' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('observations') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideObservations && generateSubMenu(
Expand Down Expand Up @@ -574,7 +609,7 @@ const LeftBar = () => {
primary={t_i18n('Threats')}
/>
)}
{navOpen && (selectedMenu === 'threats' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('threats') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideThreats && generateSubMenu(
Expand Down Expand Up @@ -605,7 +640,7 @@ const LeftBar = () => {
primary={t_i18n('Arsenal')}
/>
)}
{navOpen && (selectedMenu === 'arsenal' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('arsenal') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideArsenal && generateSubMenu(
Expand Down Expand Up @@ -636,7 +671,7 @@ const LeftBar = () => {
primary={t_i18n('Techniques')}
/>
)}
{navOpen && (selectedMenu === 'techniques' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('techniques') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideTechniques && generateSubMenu(
Expand Down Expand Up @@ -668,7 +703,7 @@ const LeftBar = () => {
primary={t_i18n('Entities')}
/>
)}
{navOpen && (selectedMenu === 'entities' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('entities') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideEntities && generateSubMenu(
Expand Down Expand Up @@ -700,7 +735,7 @@ const LeftBar = () => {
primary={t_i18n('Locations')}
/>
)}
{navOpen && (selectedMenu === 'locations' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('locations') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{!hideLocations && generateSubMenu(
Expand Down Expand Up @@ -777,7 +812,7 @@ const LeftBar = () => {
primary={t_i18n('Data')}
/>
)}
{navOpen && (selectedMenu === 'data' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('data') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
{generateSubMenu(
'data',
Expand Down Expand Up @@ -839,7 +874,7 @@ const LeftBar = () => {
primary={t_i18n('Settings')}
/>
)}
{navOpen && (selectedMenu === 'settings' ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
{navOpen && (selectedMenu.includes('settings') ? <ExpandLessOutlined /> : <ExpandMoreOutlined />)}
</MenuItem>
)}
{isGrantedToSettings && generateSubMenu(
Expand Down Expand Up @@ -889,7 +924,7 @@ const LeftBar = () => {
)}
<MenuItem
dense={true}
style={{ marginBottom: bannerHeightNumber ? 6 : undefined }}
style={{ marginBottom: bannerHeightNumber }}
classes={{
root: navOpen ? classes.menuCollapseOpen : classes.menuCollapse,
}}
Expand Down
Expand Up @@ -17,6 +17,7 @@ import DialogContent from '@mui/material/DialogContent';
import Dialog from '@mui/material/Dialog';
import DialogTitle from '@mui/material/DialogTitle';
import { useTheme } from '@mui/styles';
import { ListItem, ListItemText, Switch } from '@mui/material';
import inject18n, { useFormatter } from '../../../components/i18n';
import TextField from '../../../components/TextField';
import SelectField from '../../../components/SelectField';
Expand Down Expand Up @@ -45,6 +46,9 @@ const styles = () => ({
borderRadius: 4,
position: 'relative',
},
switchField: {
padding: '20px 0 0',
},
});

const profileOverviewFieldPatch = graphql`
Expand Down Expand Up @@ -103,6 +107,8 @@ const userValidation = (t) => Yup.object().shape({
description: Yup.string().nullable(),
otp_activated: Yup.boolean(),
unit_system: Yup.string().nullable(),
submenu_show_icons: Yup.boolean(),
submenu_auto_collapse: Yup.boolean(),
});

const passwordValidation = (t) => Yup.object().shape({
Expand Down Expand Up @@ -217,6 +223,8 @@ const ProfileOverviewComponent = (props) => {
'language',
'otp_activated',
'unit_system',
'submenu_show_icons',
'submenu_auto_collapse',
];
const initialValues = { ...pick(fieldNames, me), objectOrganization };

Expand Down Expand Up @@ -379,6 +387,30 @@ const ProfileOverviewComponent = (props) => {
<MenuItem value={'Imperial'}>{t('Imperial')}</MenuItem>
<MenuItem value={'Metric'}>{t('Metric')}</MenuItem>
</Field>
<ListItem classes={{ root: classes.switchField }}>
<ListItemText
primary={t('Show left navigation submenu icons')}
/>
<Field
component={Switch}
variant="standard"
name="submenu_show_icons"
checked={initialValues.submenu_show_icons}
onChange={(_, value) => handleSubmitField('submenu_show_icons', value)}
/>
</ListItem>
<ListItem classes={{ root: classes.switchField }}>
<ListItemText
primary={t('Auto collapse submenus in left navigation')}
/>
<Field
component={Switch}
variant="standard"
name="submenu_auto_collapse"
checked={initialValues.submenu_auto_collapse}
onChange={(_, value) => handleSubmitField('submenu_auto_collapse', value)}
/>
</ListItem>
<Field
component={TextField}
variant="standard"
Expand Down Expand Up @@ -556,6 +588,8 @@ const ProfileOverview = createFragmentContainer(ProfileOverviewComponent, {
otp_qr
description
unit_system
submenu_show_icons
submenu_auto_collapse
objectOrganization {
edges {
node {
Expand Down
Expand Up @@ -1466,6 +1466,8 @@ type User implements BasicObject & InternalObject {
account_lock_after_date: DateTime
administrated_organizations: [Organization!]!
unit_system: UnitSystem
submenu_show_icons: Boolean
submenu_auto_collapse: Boolean
editContext: [EditUserContext!]
}

Expand Down Expand Up @@ -1502,6 +1504,8 @@ type MeUser implements BasicObject & InternalObject {
account_lock_after_date: DateTime
administrated_organizations: [Organization!]!
unit_system: UnitSystem
submenu_show_icons: Boolean
submenu_auto_collapse: Boolean
}

type SessionDetail {
Expand Down Expand Up @@ -1529,6 +1533,8 @@ input UserAddInput {
account_status: String
account_lock_after_date: DateTime
unit_system: String
submenu_show_icons: Boolean
submenu_auto_collapse: Boolean
groups: [ID!]
user_confidence_level: ConfidenceLevelInput
}
Expand Down
Expand Up @@ -5,14 +5,14 @@ export default class LeftBarPage {
constructor(private page:Page) {}

async clickOnMenu(menuName: string, subMenuItem?: string) {
await this.page.getByRole('menuitem', { name: menuName }).click();
await this.page.getByRole('menuitem', { name: menuName, exact: true }).click();
if (subMenuItem) {
await this.page.getByRole('menuitem', { name: subMenuItem }).click();
}
}

async expectPage(menuName: string, pageName: string) {
await this.page.getByRole('menuitem', { name: pageName }).click();
await this.page.getByRole('menuitem', { name: pageName, exact: true }).click();
await expect(this.page.getByText(`${menuName}/${pageName}`)).toBeVisible();
}
}

0 comments on commit b2123cd

Please sign in to comment.