Skip to content

Commit

Permalink
IIIF #3 - Refactoring layout, list pages, and edit pages
Browse files Browse the repository at this point in the history
  • Loading branch information
dleadbetter committed Jun 29, 2022
1 parent ff487a0 commit 95b3ba3
Show file tree
Hide file tree
Showing 29 changed files with 615 additions and 236 deletions.
24 changes: 24 additions & 0 deletions app/controllers/api/organizations_controller.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
class Api::OrganizationsController < Api::BaseController
search_attributes :name, :location

protected

def apply_filters(query)
query = super

query = filter_user(query)

query
end

private

def filter_user(query)
return query unless params[:user_id].present?

query.where(
UserOrganization
.where(UserOrganization.arel_table[:organization_id].eq(Organization.arel_table[:id]))
.where(user_id: params[:user_id])
.arel
.exists
)
end
end
24 changes: 24 additions & 0 deletions app/controllers/api/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
class Api::UsersController < Api::BaseController
search_attributes :name, :email

protected

def apply_filters(query)
query = super

query = filter_organization(query)

query
end

private

def filter_organization(query)
return query unless params[:organization_id].present?

query.where(
UserOrganization
.where(UserOrganization.arel_table[:user_id].eq(User.arel_table[:id]))
.where(organization_id: params[:organization_id])
.arel
.exists
)
end
end
5 changes: 4 additions & 1 deletion client/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@
"no-underscore-dangle": "off",
"no-use-before-define": "off",
"react/destructuring-assignment": "off",
"react/function-component-definition": [2, { "namedComponents": "arrow-function" }],
"react/function-component-definition": [2, {
"namedComponents": "arrow-function",
"unnamedComponents": "arrow-function"
}],
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"react/jsx-no-bind": "off",
"react/no-did-update-set-state": "off",
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/AuthenticatedRoute.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// @flow

import React, { type ComponentType, type Node } from 'react';
import React, { type Node } from 'react';
import { Navigate } from 'react-router-dom';
import AuthenticationService from '../services/Authentication';

type Props = {
children: Array<Node>
};

const AuthenticatedRoute: ComponentType<any> = ({ children }: Props) => {
const AuthenticatedRoute = ({ children }: Props): Node => {
if (!AuthenticationService.isAuthenticated()) {
return <Navigate to='/login' />;
}
Expand Down
42 changes: 42 additions & 0 deletions client/src/components/Breadcrumb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// @flow

import { BaseService } from '@performant-software/shared-components';
import React, {
useEffect,
useState,
type Element,
type Node
} from 'react';
import { useParams } from 'react-router-dom';

type Props = {
idParam: string,
parameterName: string,
renderItem: (item: any) => Element<any>,
serviceClass: typeof BaseService,
};

const Breadcrumb = (props: Props): Node => {
const params = useParams();
const [item, setItem] = useState();

const id = params[props.idParam];

useEffect(() => {
if (id) {
props.serviceClass
.fetchOne(id)
.then(({ data }) => setItem(data[props.parameterName]));
}
}, [id]);

if (!item) {
return null;
}

return (
<span>{ props.renderItem(item) }</span>
);
};

export default Breadcrumb;
4 changes: 2 additions & 2 deletions client/src/components/Breadcrumbs.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// @flow

import cx from 'classnames';
import React, { useCallback, useContext, type ComponentType } from 'react';
import React, { useCallback, useContext, type Node } from 'react';
import { Link } from 'react-router-dom';
import _ from 'underscore';
import { Breadcrumb } from 'semantic-ui-react';
import styles from './Breadcrumbs.module.css';
import UserContext from '../context/UserContext';

const Breadcrumbs: ComponentType<any> = () => {
const Breadcrumbs = (): Node => {
const { breadcrumbs } = useContext(UserContext);

/**
Expand Down
14 changes: 14 additions & 0 deletions client/src/components/DetailLayout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @flow

import React, { type Node } from 'react';
import { Outlet } from 'react-router-dom';
import Breadcrumbs from './Breadcrumbs';

const DetailLayout = (): Node => (
<div>
<Breadcrumbs />
<Outlet />
</div>
);

export default DetailLayout;
43 changes: 43 additions & 0 deletions client/src/components/ItemList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// @flow

import { ListTable } from '@performant-software/semantic-components';
import React, { type Node } from 'react';
import { Link } from 'react-router-dom';
import { Button } from 'semantic-ui-react';
import _ from 'underscore';

type Props = {
actions?: Array<any>,
buttons?: Array<any>
};

const ItemList = (props: Props): Node => (
<ListTable
actions={[{
name: 'edit',
render: (item) => (
<Button
as={Link}
basic
compact
icon='edit'
to={item.id.toString()}
/>
)
}, {
name: 'delete'
}, ...(props.actions || [])]}
addButton={{}}
buttons={[{
as: Link,
basic: true,
content: 'Add',
icon: 'plus',
to: 'new'
}, ...(props.buttons || [])]}
perPageOptions={[10, 25, 50, 100]}
{..._.omit(props, 'actions', 'buttons')}
/>
);

export default ItemList;
11 changes: 6 additions & 5 deletions client/src/components/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import React, {
useEffect,
useRef,
useState,
type ComponentType
type Node
} from 'react';
import { Outlet } from 'react-router-dom';
import { Container } from 'semantic-ui-react';
import Sidebar from './Sidebar';
import styles from './Layout.module.css';
import Breadcrumbs from './Breadcrumbs';

const Layout: ComponentType<any> = () => {
const Layout = (): Node => {
const [menuWidth, setMenuWidth] = useState();

const sidebarRef = useRef();
Expand All @@ -38,8 +38,9 @@ const Layout: ComponentType<any> = () => {
marginLeft: menuWidth
}}
>
<Breadcrumbs />
<Outlet />
<Container>
<Outlet />
</Container>
</div>
</div>
);
Expand Down
34 changes: 24 additions & 10 deletions client/src/components/MenuLink.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// @flow

import React, { type ComponentType, type Node } from 'react';
import React, { useMemo, type Node } from 'react';
import {
Link,
useLocation,
useMatch,
useParams,
useResolvedPath
} from 'react-router-dom';
Expand All @@ -12,27 +13,36 @@ import _ from 'underscore';
import RouterUtils from '../utils/Router';

type Props = {
children: Node<any>,
index?: boolean,
children?: Node | (active: boolean) => Node,
pattern?: 'start' | 'end',
to: string
};

const INDEX_PATH = '/';

const MenuLink: ComponentType<any> = (props: Props) => {
const MenuLink = (props: Props): Node => {
const location = useLocation();
const params = useParams();

const { pathname } = useResolvedPath(props.to);
const currentPath = RouterUtils.getCurrentPath(location, params);
const match = useMatch({ path: pathname, end: true });

let active;
const active = useMemo(() => {
let value;

if (pathname === INDEX_PATH) {
active = currentPath === pathname;
} else {
active = currentPath.startsWith(pathname);
}
if (props.pattern === 'start') {
if (pathname === INDEX_PATH) {
value = currentPath === pathname;
} else {
value = currentPath.startsWith(pathname);
}
} else {
value = match;
}

return value;
}, [currentPath, match, pathname, props.pattern]);

return (
<Menu.Item
Expand All @@ -45,4 +55,8 @@ const MenuLink: ComponentType<any> = (props: Props) => {
);
};

MenuLink.defaultProps = {
pattern: 'start'
};

export default MenuLink;
38 changes: 0 additions & 38 deletions client/src/components/OrganizationModal.js

This file was deleted.

Loading

0 comments on commit 95b3ba3

Please sign in to comment.